From d489288e3cc1b97cffb9451e644a8b51e23cc860 Mon Sep 17 00:00:00 2001 From: Dwayne Robinson Date: Fri, 13 Mar 2020 18:56:22 -0700 Subject: [PATCH 01/12] Add kernels, including stubs. --- .../src/External/DirectMLHelpers/ApiTraits.h | 173 ++++++++++++++++- .../External/DirectMLHelpers/DirectMLSchema.h | 153 +++++++++++++++ .../DirectMLHelpers/GeneratedSchemaHelpers.h | 135 +++++++++++++ .../DirectMLHelpers/GeneratedSchemaTypes.h | 26 ++- .../External/DirectMLHelpers/SchemaHelpers.h | 46 +++++ .../src/Operators/DmlOperatorConvInteger.cpp | 81 ++++++++ .../src/Operators/DmlOperatorCumSum.cpp | 45 +++++ .../DmlOperatorDynamicQuantizeLinear.cpp | 79 ++++++++ .../src/Operators/DmlOperatorElementWise.cpp | 110 ++++++++++- .../src/Operators/DmlOperatorGather.cpp | 3 + .../src/Operators/DmlOperatorGemm.cpp | 2 +- .../Operators/DmlOperatorMatMulInteger.cpp | 81 ++++++++ .../src/Operators/DmlOperatorQLinearConv.cpp | 81 ++++++++ .../Operators/DmlOperatorQLinearMatMul.cpp | 81 ++++++++ .../src/Operators/DmlOperatorRange.cpp | 82 ++++++++ .../Operators/DmlOperatorReverseSequence.cpp | 67 +++++++ .../src/Operators/DmlOperatorScatter.cpp | 8 +- .../src/Operators/DmlOperatorSlice.cpp | 3 +- .../src/Operators/OperatorRegistration.cpp | 177 +++++++++++++----- .../DmlExecutionProvider/src/TensorDesc.cpp | 6 +- .../dml/OperatorAuthorHelper/Attributes.h | 6 + .../dml/OperatorAuthorHelper/OperatorHelper.h | 10 + .../OperatorRegistration.h | 5 +- 23 files changed, 1393 insertions(+), 67 deletions(-) create mode 100644 onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorConvInteger.cpp create mode 100644 onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorCumSum.cpp create mode 100644 onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorDynamicQuantizeLinear.cpp create mode 100644 onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorMatMulInteger.cpp create mode 100644 onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorQLinearConv.cpp create mode 100644 onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorQLinearMatMul.cpp create mode 100644 onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorRange.cpp create mode 100644 onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorReverseSequence.cpp diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/External/DirectMLHelpers/ApiTraits.h b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/External/DirectMLHelpers/ApiTraits.h index 2870946480..666dc9c0f1 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/External/DirectMLHelpers/ApiTraits.h +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/External/DirectMLHelpers/ApiTraits.h @@ -13,7 +13,7 @@ struct EnumTraits template <> struct EnumTraits { - static constexpr auto ValueCount = 9; + static constexpr auto ValueCount = 12; }; template <> @@ -25,7 +25,7 @@ struct EnumTraits template <> struct EnumTraits { - static constexpr auto ValueCount = 97; + static constexpr auto ValueCount = 107; static constexpr size_t ActivationFunctionCount = 19; }; @@ -90,6 +90,24 @@ struct EnumTraits static constexpr auto ValueCount = 2; }; +template <> +struct EnumTraits +{ + static constexpr auto ValueCount = 3; +}; + +template <> +struct EnumTraits +{ + static constexpr auto ValueCount = 2; +}; + +template <> +struct EnumTraits +{ + static constexpr auto ValueCount = 3; +}; + template constexpr auto EnumValueCount = EnumTraits::ValueCount; @@ -610,6 +628,66 @@ struct OperatorDescTraits static constexpr DML_OPERATOR_TYPE Type = DML_OPERATOR_RESAMPLE; }; +template <> +struct OperatorDescTraits +{ + static constexpr DML_OPERATOR_TYPE Type = DML_OPERATOR_ELEMENT_WISE_BIT_SHIFT_LEFT; +}; + +template <> +struct OperatorDescTraits +{ + static constexpr DML_OPERATOR_TYPE Type = DML_OPERATOR_ELEMENT_WISE_BIT_SHIFT_RIGHT; +}; + +template <> +struct OperatorDescTraits +{ + static constexpr DML_OPERATOR_TYPE Type = DML_OPERATOR_ELEMENT_WISE_ROUND; +}; + +template <> +struct OperatorDescTraits +{ + static constexpr DML_OPERATOR_TYPE Type = DML_OPERATOR_ELEMENT_WISE_IS_INFINITY; +}; + +template <> +struct OperatorDescTraits +{ + static constexpr DML_OPERATOR_TYPE Type = DML_OPERATOR_ELEMENT_WISE_MODULUS_TRUNCATE; +}; + +template <> +struct OperatorDescTraits +{ + static constexpr DML_OPERATOR_TYPE Type = DML_OPERATOR_ELEMENT_WISE_MODULUS_FLOOR; +}; + +template <> +struct OperatorDescTraits +{ + static constexpr DML_OPERATOR_TYPE Type = DML_OPERATOR_FILL_VALUE_CONSTANT; +}; + +template <> +struct OperatorDescTraits +{ + static constexpr DML_OPERATOR_TYPE Type = DML_OPERATOR_FILL_VALUE_SEQUENCE; +}; + +template <> +struct OperatorDescTraits +{ + static constexpr DML_OPERATOR_TYPE Type = DML_OPERATOR_CUMULATIVE_SUMMATION; +}; + +template <> +struct OperatorDescTraits +{ + static constexpr DML_OPERATOR_TYPE Type = DML_OPERATOR_REVERSE_SUBSEQUENCES; +}; + template <> struct OperatorDescTraits { @@ -1192,6 +1270,66 @@ struct OperatorTypeTraits<(DML_OPERATOR_TYPE)DML_OPERATOR_RESAMPLE> using DescType = DML_RESAMPLE_OPERATOR_DESC; }; +template <> +struct OperatorTypeTraits<(DML_OPERATOR_TYPE)DML_OPERATOR_ELEMENT_WISE_BIT_SHIFT_LEFT> +{ + using DescType = DML_ELEMENT_WISE_BIT_SHIFT_LEFT_OPERATOR_DESC; +}; + +template <> +struct OperatorTypeTraits<(DML_OPERATOR_TYPE)DML_OPERATOR_ELEMENT_WISE_BIT_SHIFT_RIGHT> +{ + using DescType = DML_ELEMENT_WISE_BIT_SHIFT_RIGHT_OPERATOR_DESC; +}; + +template <> +struct OperatorTypeTraits<(DML_OPERATOR_TYPE)DML_OPERATOR_ELEMENT_WISE_ROUND> +{ + using DescType = DML_ELEMENT_WISE_ROUND_OPERATOR_DESC; +}; + +template <> +struct OperatorTypeTraits<(DML_OPERATOR_TYPE)DML_OPERATOR_ELEMENT_WISE_IS_INFINITY> +{ + using DescType = DML_ELEMENT_WISE_IS_INFINITY_OPERATOR_DESC; +}; + +template <> +struct OperatorTypeTraits<(DML_OPERATOR_TYPE)DML_OPERATOR_ELEMENT_WISE_MODULUS_TRUNCATE> +{ + using DescType = DML_ELEMENT_WISE_MODULUS_TRUNCATE_OPERATOR_DESC; +}; + +template <> +struct OperatorTypeTraits<(DML_OPERATOR_TYPE)DML_OPERATOR_ELEMENT_WISE_MODULUS_FLOOR> +{ + using DescType = DML_ELEMENT_WISE_MODULUS_FLOOR_OPERATOR_DESC; +}; + +template <> +struct OperatorTypeTraits<(DML_OPERATOR_TYPE)DML_OPERATOR_FILL_VALUE_CONSTANT> +{ + using DescType = DML_FILL_VALUE_CONSTANT_OPERATOR_DESC; +}; + +template <> +struct OperatorTypeTraits<(DML_OPERATOR_TYPE)DML_OPERATOR_FILL_VALUE_SEQUENCE> +{ + using DescType = DML_FILL_VALUE_SEQUENCE_OPERATOR_DESC; +}; + +template <> +struct OperatorTypeTraits<(DML_OPERATOR_TYPE)DML_OPERATOR_CUMULATIVE_SUMMATION> +{ + using DescType = DML_CUMULATIVE_SUMMATION_OPERATOR_DESC; +}; + +template <> +struct OperatorTypeTraits<(DML_OPERATOR_TYPE)DML_OPERATOR_REVERSE_SUBSEQUENCES> +{ + using DescType = DML_REVERSE_SUBSEQUENCES_OPERATOR_DESC; +}; + template <> struct OperatorTypeTraits<(DML_OPERATOR_TYPE)DML_OPERATOR_ACTIVATION_ELU> { @@ -1306,7 +1444,6 @@ struct OperatorTypeTraits<(DML_OPERATOR_TYPE)DML_OPERATOR_ACTIVATION_SHRINK> using DescType = DML_ACTIVATION_SHRINK_OPERATOR_DESC; }; - // Calls a visitor functor, supplying an empty operator desc corresponding to the given DML_OPERATOR_TYPE as // the first argument. // @@ -1474,6 +1611,26 @@ auto OperatorTypeVisitor(DML_OPERATOR_TYPE type, Visitor&& visitor, Ts&&... args return std::invoke(std::forward(visitor), DML_ONE_HOT_OPERATOR_DESC{}, std::forward(args)...); case DML_OPERATOR_RESAMPLE: return std::invoke(std::forward(visitor), DML_RESAMPLE_OPERATOR_DESC{}, std::forward(args)...); + case DML_OPERATOR_ELEMENT_WISE_BIT_SHIFT_LEFT: + return std::invoke(std::forward(visitor), DML_ELEMENT_WISE_BIT_SHIFT_LEFT_OPERATOR_DESC{}, std::forward(args)...); + case DML_OPERATOR_ELEMENT_WISE_BIT_SHIFT_RIGHT: + return std::invoke(std::forward(visitor), DML_ELEMENT_WISE_BIT_SHIFT_RIGHT_OPERATOR_DESC{}, std::forward(args)...); + case DML_OPERATOR_ELEMENT_WISE_ROUND: + return std::invoke(std::forward(visitor), DML_ELEMENT_WISE_ROUND_OPERATOR_DESC{}, std::forward(args)...); + case DML_OPERATOR_ELEMENT_WISE_IS_INFINITY: + return std::invoke(std::forward(visitor), DML_ELEMENT_WISE_IS_INFINITY_OPERATOR_DESC{}, std::forward(args)...); + case DML_OPERATOR_ELEMENT_WISE_MODULUS_TRUNCATE: + return std::invoke(std::forward(visitor), DML_ELEMENT_WISE_MODULUS_TRUNCATE_OPERATOR_DESC{}, std::forward(args)...); + case DML_OPERATOR_ELEMENT_WISE_MODULUS_FLOOR: + return std::invoke(std::forward(visitor), DML_ELEMENT_WISE_MODULUS_FLOOR_OPERATOR_DESC{}, std::forward(args)...); + case DML_OPERATOR_FILL_VALUE_CONSTANT: + return std::invoke(std::forward(visitor), DML_FILL_VALUE_CONSTANT_OPERATOR_DESC{}, std::forward(args)...); + case DML_OPERATOR_FILL_VALUE_SEQUENCE: + return std::invoke(std::forward(visitor), DML_FILL_VALUE_SEQUENCE_OPERATOR_DESC{}, std::forward(args)...); + case DML_OPERATOR_CUMULATIVE_SUMMATION: + return std::invoke(std::forward(visitor), DML_CUMULATIVE_SUMMATION_OPERATOR_DESC{}, std::forward(args)...); + case DML_OPERATOR_REVERSE_SUBSEQUENCES: + return std::invoke(std::forward(visitor), DML_REVERSE_SUBSEQUENCES_OPERATOR_DESC{}, std::forward(args)...); case DML_OPERATOR_ACTIVATION_ELU: return std::invoke(std::forward(visitor), DML_ACTIVATION_ELU_OPERATOR_DESC{}, std::forward(args)...); case DML_OPERATOR_ACTIVATION_HARDMAX: @@ -1601,6 +1758,16 @@ inline gsl::czstring ToString(DML_OPERATOR_TYPE value) case DML_OPERATOR_SCATTER: return "DML_OPERATOR_SCATTER"; case DML_OPERATOR_ONE_HOT: return "DML_OPERATOR_ONE_HOT"; case DML_OPERATOR_RESAMPLE: return "DML_OPERATOR_RESAMPLE"; + case DML_OPERATOR_ELEMENT_WISE_BIT_SHIFT_LEFT: return "DML_OPERATOR_ELEMENT_WISE_BIT_SHIFT_LEFT"; + case DML_OPERATOR_ELEMENT_WISE_BIT_SHIFT_RIGHT: return "DML_OPERATOR_ELEMENT_WISE_BIT_SHIFT_RIGHT"; + case DML_OPERATOR_ELEMENT_WISE_ROUND: return "DML_OPERATOR_ELEMENT_WISE_ROUND"; + case DML_OPERATOR_ELEMENT_WISE_IS_INFINITY: return "DML_OPERATOR_ELEMENT_WISE_IS_INFINITY"; + case DML_OPERATOR_ELEMENT_WISE_MODULUS_TRUNCATE: return "DML_OPERATOR_ELEMENT_WISE_MODULUS_TRUNCATE"; + case DML_OPERATOR_ELEMENT_WISE_MODULUS_FLOOR: return "DML_OPERATOR_ELEMENT_WISE_MODULUS_FLOOR"; + case DML_OPERATOR_FILL_VALUE_CONSTANT: return "DML_OPERATOR_FILL_VALUE_CONSTANT"; + case DML_OPERATOR_FILL_VALUE_SEQUENCE: return "DML_OPERATOR_FILL_VALUE_SEQUENCE"; + case DML_OPERATOR_CUMULATIVE_SUMMATION: return "DML_OPERATOR_CUMULATIVE_SUMMATION"; + case DML_OPERATOR_REVERSE_SUBSEQUENCES: return "DML_OPERATOR_REVERSE_SUBSEQUENCES"; default: assert(false); return ""; 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 7c46a8a6a2..b95fbfc95c 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/External/DirectMLHelpers/DirectMLSchema.h +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/External/DirectMLHelpers/DirectMLSchema.h @@ -19,12 +19,15 @@ enum DML_SCHEMA_FIELD_TYPE DML_SCHEMA_FIELD_TYPE_OPERATOR_DESC, DML_SCHEMA_FIELD_TYPE_OPERATOR_DESC_ARRAY, DML_SCHEMA_FIELD_TYPE_UINT, + DML_SCHEMA_FIELD_TYPE_UINT64, DML_SCHEMA_FIELD_TYPE_INT, DML_SCHEMA_FIELD_TYPE_FLOAT, DML_SCHEMA_FIELD_TYPE_UINT_ARRAY, + DML_SCHEMA_FIELD_TYPE_INT_ARRAY, DML_SCHEMA_FIELD_TYPE_FLOAT_ARRAY, DML_SCHEMA_FIELD_TYPE_SCALE_BIAS, DML_SCHEMA_FIELD_TYPE_SIZE_2D, + DML_SCHEMA_FIELD_TYPE_SCALAR_UNION, }; enum DML_SCHEMA_OPERATOR_SUPPORT_FLAGS @@ -1246,6 +1249,150 @@ constexpr DML_OPERATOR_SCHEMA DML_RESAMPLE_OPERATOR_SCHEMA { DML_RESAMPLE_OPERATOR_SCHEMA_FIELDS, }; +constexpr DML_SCHEMA_FIELD DML_ELEMENT_WISE_BIT_SHIFT_LEFT_OPERATOR_SCHEMA_FIELDS[3] { + DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_INPUT_TENSOR, DML_SCHEMA_FIELD_TYPE_TENSOR_DESC, "ATensor", false }, + DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_INPUT_TENSOR, DML_SCHEMA_FIELD_TYPE_TENSOR_DESC, "BTensor", false }, + DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_OUTPUT_TENSOR, DML_SCHEMA_FIELD_TYPE_TENSOR_DESC, "OutputTensor", false }, +}; + +constexpr DML_OPERATOR_SCHEMA DML_ELEMENT_WISE_BIT_SHIFT_LEFT_OPERATOR_SCHEMA { + "DML_OPERATOR_ELEMENT_WISE_BIT_SHIFT_LEFT", + DML_OPERATOR_ELEMENT_WISE_BIT_SHIFT_LEFT, + DML_SCHEMA_OPERATOR_SUPPORT_FLAG_IN_PLACE_EXECUTION, + 3, + DML_ELEMENT_WISE_BIT_SHIFT_LEFT_OPERATOR_SCHEMA_FIELDS, +}; + +constexpr DML_SCHEMA_FIELD DML_ELEMENT_WISE_BIT_SHIFT_RIGHT_OPERATOR_SCHEMA_FIELDS[3] { + DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_INPUT_TENSOR, DML_SCHEMA_FIELD_TYPE_TENSOR_DESC, "ATensor", false }, + DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_INPUT_TENSOR, DML_SCHEMA_FIELD_TYPE_TENSOR_DESC, "BTensor", false }, + DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_OUTPUT_TENSOR, DML_SCHEMA_FIELD_TYPE_TENSOR_DESC, "OutputTensor", false }, +}; + +constexpr DML_OPERATOR_SCHEMA DML_ELEMENT_WISE_BIT_SHIFT_RIGHT_OPERATOR_SCHEMA { + "DML_OPERATOR_ELEMENT_WISE_BIT_SHIFT_RIGHT", + DML_OPERATOR_ELEMENT_WISE_BIT_SHIFT_RIGHT, + DML_SCHEMA_OPERATOR_SUPPORT_FLAG_IN_PLACE_EXECUTION, + 3, + DML_ELEMENT_WISE_BIT_SHIFT_RIGHT_OPERATOR_SCHEMA_FIELDS, +}; + +constexpr DML_SCHEMA_FIELD DML_ELEMENT_WISE_ROUND_OPERATOR_SCHEMA_FIELDS[3] { + DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_INPUT_TENSOR, DML_SCHEMA_FIELD_TYPE_TENSOR_DESC, "InputTensor", false }, + DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_OUTPUT_TENSOR, DML_SCHEMA_FIELD_TYPE_TENSOR_DESC, "OutputTensor", false }, + DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_ATTRIBUTE, DML_SCHEMA_FIELD_TYPE_UINT, "RoundingMode", false }, +}; + +constexpr DML_OPERATOR_SCHEMA DML_ELEMENT_WISE_ROUND_OPERATOR_SCHEMA { + "DML_OPERATOR_ELEMENT_WISE_ROUND", + DML_OPERATOR_ELEMENT_WISE_ROUND, + DML_SCHEMA_OPERATOR_SUPPORT_FLAG_IN_PLACE_EXECUTION, + 3, + DML_ELEMENT_WISE_ROUND_OPERATOR_SCHEMA_FIELDS, +}; + +constexpr DML_SCHEMA_FIELD DML_ELEMENT_WISE_IS_INFINITY_OPERATOR_SCHEMA_FIELDS[3] { + DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_INPUT_TENSOR, DML_SCHEMA_FIELD_TYPE_TENSOR_DESC, "InputTensor", false }, + DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_OUTPUT_TENSOR, DML_SCHEMA_FIELD_TYPE_TENSOR_DESC, "OutputTensor", false }, + DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_ATTRIBUTE, DML_SCHEMA_FIELD_TYPE_UINT, "InfinityMode", false }, +}; + +constexpr DML_OPERATOR_SCHEMA DML_ELEMENT_WISE_IS_INFINITY_OPERATOR_SCHEMA { + "DML_OPERATOR_ELEMENT_WISE_IS_INFINITY", + DML_OPERATOR_ELEMENT_WISE_IS_INFINITY, + DML_SCHEMA_OPERATOR_SUPPORT_FLAG_IN_PLACE_EXECUTION, + 3, + DML_ELEMENT_WISE_IS_INFINITY_OPERATOR_SCHEMA_FIELDS, +}; + +constexpr DML_SCHEMA_FIELD DML_ELEMENT_WISE_MODULUS_TRUNCATE_OPERATOR_SCHEMA_FIELDS[3] { + DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_INPUT_TENSOR, DML_SCHEMA_FIELD_TYPE_TENSOR_DESC, "ATensor", false }, + DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_INPUT_TENSOR, DML_SCHEMA_FIELD_TYPE_TENSOR_DESC, "BTensor", false }, + DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_OUTPUT_TENSOR, DML_SCHEMA_FIELD_TYPE_TENSOR_DESC, "OutputTensor", false }, +}; + +constexpr DML_OPERATOR_SCHEMA DML_ELEMENT_WISE_MODULUS_TRUNCATE_OPERATOR_SCHEMA { + "DML_OPERATOR_ELEMENT_WISE_MODULUS_TRUNCATE", + DML_OPERATOR_ELEMENT_WISE_MODULUS_TRUNCATE, + DML_SCHEMA_OPERATOR_SUPPORT_FLAG_IN_PLACE_EXECUTION, + 3, + DML_ELEMENT_WISE_MODULUS_TRUNCATE_OPERATOR_SCHEMA_FIELDS, +}; + +constexpr DML_SCHEMA_FIELD DML_ELEMENT_WISE_MODULUS_FLOOR_OPERATOR_SCHEMA_FIELDS[3] { + DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_INPUT_TENSOR, DML_SCHEMA_FIELD_TYPE_TENSOR_DESC, "ATensor", false }, + DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_INPUT_TENSOR, DML_SCHEMA_FIELD_TYPE_TENSOR_DESC, "BTensor", false }, + DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_OUTPUT_TENSOR, DML_SCHEMA_FIELD_TYPE_TENSOR_DESC, "OutputTensor", false }, +}; + +constexpr DML_OPERATOR_SCHEMA DML_ELEMENT_WISE_MODULUS_FLOOR_OPERATOR_SCHEMA { + "DML_OPERATOR_ELEMENT_WISE_MODULUS_FLOOR", + DML_OPERATOR_ELEMENT_WISE_MODULUS_FLOOR, + DML_SCHEMA_OPERATOR_SUPPORT_FLAG_IN_PLACE_EXECUTION, + 3, + DML_ELEMENT_WISE_MODULUS_FLOOR_OPERATOR_SCHEMA_FIELDS, +}; + +constexpr DML_SCHEMA_FIELD DML_FILL_VALUE_CONSTANT_OPERATOR_SCHEMA_FIELDS[3] { + DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_OUTPUT_TENSOR, DML_SCHEMA_FIELD_TYPE_TENSOR_DESC, "OutputTensor", false }, + DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_ATTRIBUTE, DML_SCHEMA_FIELD_TYPE_UINT, "ValueDataType", false }, + DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_ATTRIBUTE, DML_SCHEMA_FIELD_TYPE_SCALAR_UNION, "Value", false }, +}; + +constexpr DML_OPERATOR_SCHEMA DML_FILL_VALUE_CONSTANT_OPERATOR_SCHEMA { + "DML_OPERATOR_FILL_VALUE_CONSTANT", + DML_OPERATOR_FILL_VALUE_CONSTANT, + DML_SCHEMA_OPERATOR_SUPPORT_FLAG_IN_PLACE_EXECUTION, + 3, + DML_FILL_VALUE_CONSTANT_OPERATOR_SCHEMA_FIELDS, +}; + +constexpr DML_SCHEMA_FIELD DML_FILL_VALUE_SEQUENCE_OPERATOR_SCHEMA_FIELDS[4] { + DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_OUTPUT_TENSOR, DML_SCHEMA_FIELD_TYPE_TENSOR_DESC, "OutputTensor", false }, + DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_ATTRIBUTE, DML_SCHEMA_FIELD_TYPE_UINT, "ValueDataType", false }, + DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_ATTRIBUTE, DML_SCHEMA_FIELD_TYPE_SCALAR_UNION, "ValueStart", false }, + DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_ATTRIBUTE, DML_SCHEMA_FIELD_TYPE_SCALAR_UNION, "ValueDelta", false }, +}; + +constexpr DML_OPERATOR_SCHEMA DML_FILL_VALUE_SEQUENCE_OPERATOR_SCHEMA { + "DML_OPERATOR_FILL_VALUE_SEQUENCE", + DML_OPERATOR_FILL_VALUE_SEQUENCE, + DML_SCHEMA_OPERATOR_SUPPORT_FLAG_IN_PLACE_EXECUTION, + 4, + DML_FILL_VALUE_SEQUENCE_OPERATOR_SCHEMA_FIELDS, +}; + +constexpr DML_SCHEMA_FIELD DML_CUMULATIVE_SUMMATION_OPERATOR_SCHEMA_FIELDS[5] { + DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_INPUT_TENSOR, DML_SCHEMA_FIELD_TYPE_TENSOR_DESC, "InputTensor", false }, + DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_OUTPUT_TENSOR, DML_SCHEMA_FIELD_TYPE_TENSOR_DESC, "OutputTensor", false }, + DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_ATTRIBUTE, DML_SCHEMA_FIELD_TYPE_UINT, "Axis", false }, + DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_ATTRIBUTE, DML_SCHEMA_FIELD_TYPE_UINT, "HasExclusiveSum", false }, + DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_ATTRIBUTE, DML_SCHEMA_FIELD_TYPE_UINT, "AxisDirection", false }, +}; + +constexpr DML_OPERATOR_SCHEMA DML_CUMULATIVE_SUMMATION_OPERATOR_SCHEMA { + "DML_OPERATOR_CUMULATIVE_SUMMATION", + DML_OPERATOR_CUMULATIVE_SUMMATION, + DML_SCHEMA_OPERATOR_SUPPORT_FLAG_IN_PLACE_EXECUTION, + 5, + DML_CUMULATIVE_SUMMATION_OPERATOR_SCHEMA_FIELDS, +}; + +constexpr DML_SCHEMA_FIELD DML_REVERSE_SUBSEQUENCES_OPERATOR_SCHEMA_FIELDS[4] { + DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_INPUT_TENSOR, DML_SCHEMA_FIELD_TYPE_TENSOR_DESC, "InputTensor", false }, + DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_INPUT_TENSOR, DML_SCHEMA_FIELD_TYPE_TENSOR_DESC, "SequenceLengthsTensor", false }, + DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_OUTPUT_TENSOR, DML_SCHEMA_FIELD_TYPE_TENSOR_DESC, "OutputTensor", false }, + DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_ATTRIBUTE, DML_SCHEMA_FIELD_TYPE_UINT, "Axis", false }, +}; + +constexpr DML_OPERATOR_SCHEMA DML_REVERSE_SUBSEQUENCES_OPERATOR_SCHEMA { + "DML_OPERATOR_REVERSE_SUBSEQUENCES", + DML_OPERATOR_REVERSE_SUBSEQUENCES, + DML_SCHEMA_OPERATOR_SUPPORT_FLAG_IN_PLACE_EXECUTION, + 4, + DML_REVERSE_SUBSEQUENCES_OPERATOR_SCHEMA_FIELDS, +}; + constexpr DML_SCHEMA_FIELD DML_ACTIVATION_ELU_OPERATOR_SCHEMA_FIELDS[3] { DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_INPUT_TENSOR, DML_SCHEMA_FIELD_TYPE_TENSOR_DESC, "InputTensor", false }, @@ -1511,4 +1658,10 @@ constexpr DML_OPERATOR_SCHEMA DML_ACTIVATION_SHRINK_OPERATOR_SCHEMA { DML_ACTIVATION_SHRINK_OPERATOR_SCHEMA_FIELDS, }; +constexpr DML_SCHEMA_FIELD DML_RNN_ZERO_OPERATOR_SCHEMA_FIELDS[3] { + DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_INPUT_TENSOR, DML_SCHEMA_FIELD_TYPE_TENSOR_DESC, "InputTensor", false }, + DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_INPUT_TENSOR, DML_SCHEMA_FIELD_TYPE_TENSOR_DESC, "SequenceLengthsTensor", false }, + DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_OUTPUT_TENSOR, DML_SCHEMA_FIELD_TYPE_TENSOR_DESC, "OutputTensor", false }, +}; + } // extern "C" diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/External/DirectMLHelpers/GeneratedSchemaHelpers.h b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/External/DirectMLHelpers/GeneratedSchemaHelpers.h index b8285c77a7..d565590ece 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/External/DirectMLHelpers/GeneratedSchemaHelpers.h +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/External/DirectMLHelpers/GeneratedSchemaHelpers.h @@ -738,6 +738,90 @@ inline std::vector GetFields(const DML_RESAMPLE_OPERATOR_DESC& de OperatorField(&DML_RESAMPLE_OPERATOR_SCHEMA.Fields[4], ToOperatorFieldType(static_cast(desc.Scales), desc.ScaleCount)), }; } +inline std::vector GetFields(const DML_ELEMENT_WISE_BIT_SHIFT_LEFT_OPERATOR_DESC& desc) +{ + return { + OperatorField(&DML_ELEMENT_WISE_BIT_SHIFT_LEFT_OPERATOR_SCHEMA.Fields[0], ToOperatorFieldType(static_cast(desc.ATensor))), + OperatorField(&DML_ELEMENT_WISE_BIT_SHIFT_LEFT_OPERATOR_SCHEMA.Fields[1], ToOperatorFieldType(static_cast(desc.BTensor))), + OperatorField(&DML_ELEMENT_WISE_BIT_SHIFT_LEFT_OPERATOR_SCHEMA.Fields[2], ToOperatorFieldType(static_cast(desc.OutputTensor))), + }; +} +inline std::vector GetFields(const DML_ELEMENT_WISE_BIT_SHIFT_RIGHT_OPERATOR_DESC& desc) +{ + return { + OperatorField(&DML_ELEMENT_WISE_BIT_SHIFT_RIGHT_OPERATOR_SCHEMA.Fields[0], ToOperatorFieldType(static_cast(desc.ATensor))), + OperatorField(&DML_ELEMENT_WISE_BIT_SHIFT_RIGHT_OPERATOR_SCHEMA.Fields[1], ToOperatorFieldType(static_cast(desc.BTensor))), + OperatorField(&DML_ELEMENT_WISE_BIT_SHIFT_RIGHT_OPERATOR_SCHEMA.Fields[2], ToOperatorFieldType(static_cast(desc.OutputTensor))), + }; +} +inline std::vector GetFields(const DML_ELEMENT_WISE_ROUND_OPERATOR_DESC& desc) +{ + return { + OperatorField(&DML_ELEMENT_WISE_ROUND_OPERATOR_SCHEMA.Fields[0], ToOperatorFieldType(static_cast(desc.InputTensor))), + OperatorField(&DML_ELEMENT_WISE_ROUND_OPERATOR_SCHEMA.Fields[1], ToOperatorFieldType(static_cast(desc.OutputTensor))), + OperatorField(&DML_ELEMENT_WISE_ROUND_OPERATOR_SCHEMA.Fields[2], ToOperatorFieldType(static_cast(desc.RoundingMode))), + }; +} +inline std::vector GetFields(const DML_ELEMENT_WISE_IS_INFINITY_OPERATOR_DESC& desc) +{ + return { + OperatorField(&DML_ELEMENT_WISE_IS_INFINITY_OPERATOR_SCHEMA.Fields[0], ToOperatorFieldType(static_cast(desc.InputTensor))), + OperatorField(&DML_ELEMENT_WISE_IS_INFINITY_OPERATOR_SCHEMA.Fields[1], ToOperatorFieldType(static_cast(desc.OutputTensor))), + OperatorField(&DML_ELEMENT_WISE_IS_INFINITY_OPERATOR_SCHEMA.Fields[2], ToOperatorFieldType(static_cast(desc.InfinityMode))), + }; +} +inline std::vector GetFields(const DML_ELEMENT_WISE_MODULUS_TRUNCATE_OPERATOR_DESC& desc) +{ + return { + OperatorField(&DML_ELEMENT_WISE_MODULUS_TRUNCATE_OPERATOR_SCHEMA.Fields[0], ToOperatorFieldType(static_cast(desc.ATensor))), + OperatorField(&DML_ELEMENT_WISE_MODULUS_TRUNCATE_OPERATOR_SCHEMA.Fields[1], ToOperatorFieldType(static_cast(desc.BTensor))), + OperatorField(&DML_ELEMENT_WISE_MODULUS_TRUNCATE_OPERATOR_SCHEMA.Fields[2], ToOperatorFieldType(static_cast(desc.OutputTensor))), + }; +} +inline std::vector GetFields(const DML_ELEMENT_WISE_MODULUS_FLOOR_OPERATOR_DESC& desc) +{ + return { + OperatorField(&DML_ELEMENT_WISE_MODULUS_FLOOR_OPERATOR_SCHEMA.Fields[0], ToOperatorFieldType(static_cast(desc.ATensor))), + OperatorField(&DML_ELEMENT_WISE_MODULUS_FLOOR_OPERATOR_SCHEMA.Fields[1], ToOperatorFieldType(static_cast(desc.BTensor))), + OperatorField(&DML_ELEMENT_WISE_MODULUS_FLOOR_OPERATOR_SCHEMA.Fields[2], ToOperatorFieldType(static_cast(desc.OutputTensor))), + }; +} +inline std::vector GetFields(const DML_FILL_VALUE_CONSTANT_OPERATOR_DESC& desc) +{ + return { + OperatorField(&DML_FILL_VALUE_CONSTANT_OPERATOR_SCHEMA.Fields[0], ToOperatorFieldType(static_cast(desc.OutputTensor))), + OperatorField(&DML_FILL_VALUE_CONSTANT_OPERATOR_SCHEMA.Fields[1], ToOperatorFieldType(static_cast(desc.ValueDataType))), + OperatorField(&DML_FILL_VALUE_CONSTANT_OPERATOR_SCHEMA.Fields[2], ToOperatorFieldType(static_cast(desc.Value))), + }; +} +inline std::vector GetFields(const DML_FILL_VALUE_SEQUENCE_OPERATOR_DESC& desc) +{ + return { + OperatorField(&DML_FILL_VALUE_SEQUENCE_OPERATOR_SCHEMA.Fields[0], ToOperatorFieldType(static_cast(desc.OutputTensor))), + OperatorField(&DML_FILL_VALUE_SEQUENCE_OPERATOR_SCHEMA.Fields[1], ToOperatorFieldType(static_cast(desc.ValueDataType))), + OperatorField(&DML_FILL_VALUE_SEQUENCE_OPERATOR_SCHEMA.Fields[2], ToOperatorFieldType(static_cast(desc.ValueStart))), + OperatorField(&DML_FILL_VALUE_SEQUENCE_OPERATOR_SCHEMA.Fields[3], ToOperatorFieldType(static_cast(desc.ValueDelta))), + }; +} +inline std::vector GetFields(const DML_CUMULATIVE_SUMMATION_OPERATOR_DESC& desc) +{ + return { + OperatorField(&DML_CUMULATIVE_SUMMATION_OPERATOR_SCHEMA.Fields[0], ToOperatorFieldType(static_cast(desc.InputTensor))), + OperatorField(&DML_CUMULATIVE_SUMMATION_OPERATOR_SCHEMA.Fields[1], ToOperatorFieldType(static_cast(desc.OutputTensor))), + OperatorField(&DML_CUMULATIVE_SUMMATION_OPERATOR_SCHEMA.Fields[2], ToOperatorFieldType(static_cast(desc.Axis))), + OperatorField(&DML_CUMULATIVE_SUMMATION_OPERATOR_SCHEMA.Fields[3], ToOperatorFieldType(static_cast(desc.HasExclusiveSum))), + OperatorField(&DML_CUMULATIVE_SUMMATION_OPERATOR_SCHEMA.Fields[4], ToOperatorFieldType(static_cast(desc.AxisDirection))), + }; +} +inline std::vector GetFields(const DML_REVERSE_SUBSEQUENCES_OPERATOR_DESC& desc) +{ + return { + OperatorField(&DML_REVERSE_SUBSEQUENCES_OPERATOR_SCHEMA.Fields[0], ToOperatorFieldType(static_cast(desc.InputTensor))), + OperatorField(&DML_REVERSE_SUBSEQUENCES_OPERATOR_SCHEMA.Fields[1], ToOperatorFieldType(static_cast(desc.SequenceLengthsTensor))), + OperatorField(&DML_REVERSE_SUBSEQUENCES_OPERATOR_SCHEMA.Fields[2], ToOperatorFieldType(static_cast(desc.OutputTensor))), + OperatorField(&DML_REVERSE_SUBSEQUENCES_OPERATOR_SCHEMA.Fields[3], ToOperatorFieldType(static_cast(desc.Axis))), + }; +} inline std::vector GetFields(const DML_ACTIVATION_ELU_OPERATOR_DESC& desc) { return { @@ -970,6 +1054,16 @@ inline const DML_OPERATOR_SCHEMA& GetSchema(DML_OPERATOR_TYPE operatorType) case DML_OPERATOR_SCATTER: return DML_SCATTER_OPERATOR_SCHEMA; case DML_OPERATOR_ONE_HOT: return DML_ONE_HOT_OPERATOR_SCHEMA; case DML_OPERATOR_RESAMPLE: return DML_RESAMPLE_OPERATOR_SCHEMA; + case DML_OPERATOR_ELEMENT_WISE_BIT_SHIFT_LEFT: return DML_ELEMENT_WISE_BIT_SHIFT_LEFT_OPERATOR_SCHEMA; + case DML_OPERATOR_ELEMENT_WISE_BIT_SHIFT_RIGHT: return DML_ELEMENT_WISE_BIT_SHIFT_RIGHT_OPERATOR_SCHEMA; + case DML_OPERATOR_ELEMENT_WISE_ROUND: return DML_ELEMENT_WISE_ROUND_OPERATOR_SCHEMA; + case DML_OPERATOR_ELEMENT_WISE_IS_INFINITY: return DML_ELEMENT_WISE_IS_INFINITY_OPERATOR_SCHEMA; + case DML_OPERATOR_ELEMENT_WISE_MODULUS_TRUNCATE: return DML_ELEMENT_WISE_MODULUS_TRUNCATE_OPERATOR_SCHEMA; + case DML_OPERATOR_ELEMENT_WISE_MODULUS_FLOOR: return DML_ELEMENT_WISE_MODULUS_FLOOR_OPERATOR_SCHEMA; + case DML_OPERATOR_FILL_VALUE_CONSTANT: return DML_FILL_VALUE_CONSTANT_OPERATOR_SCHEMA; + case DML_OPERATOR_FILL_VALUE_SEQUENCE: return DML_FILL_VALUE_SEQUENCE_OPERATOR_SCHEMA; + case DML_OPERATOR_CUMULATIVE_SUMMATION: return DML_CUMULATIVE_SUMMATION_OPERATOR_SCHEMA; + case DML_OPERATOR_REVERSE_SUBSEQUENCES: return DML_REVERSE_SUBSEQUENCES_OPERATOR_SCHEMA; case DML_OPERATOR_ACTIVATION_ELU: return DML_ACTIVATION_ELU_OPERATOR_SCHEMA; case DML_OPERATOR_ACTIVATION_HARDMAX: return DML_ACTIVATION_HARDMAX_OPERATOR_SCHEMA; case DML_OPERATOR_ACTIVATION_HARD_SIGMOID: return DML_ACTIVATION_HARD_SIGMOID_OPERATOR_SCHEMA; @@ -989,6 +1083,7 @@ inline const DML_OPERATOR_SCHEMA& GetSchema(DML_OPERATOR_TYPE operatorType) case DML_OPERATOR_ACTIVATION_TANH: return DML_ACTIVATION_TANH_OPERATOR_SCHEMA; case DML_OPERATOR_ACTIVATION_THRESHOLDED_RELU: return DML_ACTIVATION_THRESHOLDED_RELU_OPERATOR_SCHEMA; case DML_OPERATOR_ACTIVATION_SHRINK: return DML_ACTIVATION_SHRINK_OPERATOR_SCHEMA; + default: THROW_HR(E_INVALIDARG); } } @@ -1305,6 +1400,46 @@ inline AbstractOperatorDesc ConvertOperatorDesc(const DML_OPERATOR_DESC& opDesc) return AbstractOperatorDesc( &DML_RESAMPLE_OPERATOR_SCHEMA, GetFields(*static_cast(opDesc.Desc))); + case DML_OPERATOR_ELEMENT_WISE_BIT_SHIFT_LEFT: + return AbstractOperatorDesc( + &DML_ELEMENT_WISE_BIT_SHIFT_LEFT_OPERATOR_SCHEMA, + GetFields(*static_cast(opDesc.Desc))); + case DML_OPERATOR_ELEMENT_WISE_BIT_SHIFT_RIGHT: + return AbstractOperatorDesc( + &DML_ELEMENT_WISE_BIT_SHIFT_RIGHT_OPERATOR_SCHEMA, + GetFields(*static_cast(opDesc.Desc))); + case DML_OPERATOR_ELEMENT_WISE_ROUND: + return AbstractOperatorDesc( + &DML_ELEMENT_WISE_ROUND_OPERATOR_SCHEMA, + GetFields(*static_cast(opDesc.Desc))); + case DML_OPERATOR_ELEMENT_WISE_IS_INFINITY: + return AbstractOperatorDesc( + &DML_ELEMENT_WISE_IS_INFINITY_OPERATOR_SCHEMA, + GetFields(*static_cast(opDesc.Desc))); + case DML_OPERATOR_ELEMENT_WISE_MODULUS_TRUNCATE: + return AbstractOperatorDesc( + &DML_ELEMENT_WISE_MODULUS_TRUNCATE_OPERATOR_SCHEMA, + GetFields(*static_cast(opDesc.Desc))); + case DML_OPERATOR_ELEMENT_WISE_MODULUS_FLOOR: + return AbstractOperatorDesc( + &DML_ELEMENT_WISE_MODULUS_FLOOR_OPERATOR_SCHEMA, + GetFields(*static_cast(opDesc.Desc))); + case DML_OPERATOR_FILL_VALUE_CONSTANT: + return AbstractOperatorDesc( + &DML_FILL_VALUE_CONSTANT_OPERATOR_SCHEMA, + GetFields(*static_cast(opDesc.Desc))); + case DML_OPERATOR_FILL_VALUE_SEQUENCE: + return AbstractOperatorDesc( + &DML_FILL_VALUE_SEQUENCE_OPERATOR_SCHEMA, + GetFields(*static_cast(opDesc.Desc))); + case DML_OPERATOR_CUMULATIVE_SUMMATION: + return AbstractOperatorDesc( + &DML_CUMULATIVE_SUMMATION_OPERATOR_SCHEMA, + GetFields(*static_cast(opDesc.Desc))); + case DML_OPERATOR_REVERSE_SUBSEQUENCES: + return AbstractOperatorDesc( + &DML_REVERSE_SUBSEQUENCES_OPERATOR_SCHEMA, + GetFields(*static_cast(opDesc.Desc))); case DML_OPERATOR_ACTIVATION_ELU: return AbstractOperatorDesc( &DML_ACTIVATION_ELU_OPERATOR_SCHEMA, diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/External/DirectMLHelpers/GeneratedSchemaTypes.h b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/External/DirectMLHelpers/GeneratedSchemaTypes.h index 57c8ec8ce0..21c8c46af7 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/External/DirectMLHelpers/GeneratedSchemaTypes.h +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/External/DirectMLHelpers/GeneratedSchemaTypes.h @@ -7,13 +7,16 @@ using ApiAttributeVariant = std::variant< const DML_TENSOR_DESC*, const DML_OPERATOR_DESC*, UINT, + UINT64, INT, FLOAT, const UINT*, + const INT*, const FLOAT*, const DML_SCALE_BIAS*, - DML_SIZE_2D - >; + DML_SIZE_2D, + DML_SCALAR_UNION +>; namespace OperatorFieldTypes { @@ -22,12 +25,15 @@ namespace OperatorFieldTypes using OperatorDesc = std::optional; // DML_SCHEMA_FIELD_TYPE_OPERATOR_DESC using OperatorDescArray = std::optional>; // DML_SCHEMA_FIELD_TYPE_OPERATOR_DESC_ARRAY using UInt = uint32_t; // DML_SCHEMA_FIELD_TYPE_UINT + using UInt64 = uint64_t; // DML_SCHEMA_FIELD_TYPE_UINT64 using Int = int32_t; // DML_SCHEMA_FIELD_TYPE_INT using Float = float; // DML_SCHEMA_FIELD_TYPE_FLOAT using UIntArray = std::optional>; // DML_SCHEMA_FIELD_TYPE_UINT_ARRAY + using IntArray = std::optional>; // DML_SCHEMA_FIELD_TYPE_INT_ARRAY using FloatArray = std::optional>; // DML_SCHEMA_FIELD_TYPE_FLOAT_ARRAY using ScaleBias = std::optional; // DML_SCHEMA_FIELD_TYPE_SCALE_BIAS using Size2D = DML_SIZE_2D; // DML_SCHEMA_FIELD_TYPE_SIZE_2D + using ScalarUnion = DML_SCALAR_UNION; // DML_SCHEMA_FIELD_TYPE_SCALAR_UNION } using OperatorFieldVariant = std::variant< @@ -36,13 +42,16 @@ using OperatorFieldVariant = std::variant< OperatorFieldTypes::OperatorDesc, OperatorFieldTypes::OperatorDescArray, OperatorFieldTypes::UInt, + OperatorFieldTypes::UInt64, OperatorFieldTypes::Int, OperatorFieldTypes::Float, OperatorFieldTypes::UIntArray, + OperatorFieldTypes::IntArray, OperatorFieldTypes::FloatArray, OperatorFieldTypes::ScaleBias, - OperatorFieldTypes::Size2D - >; + OperatorFieldTypes::Size2D, + OperatorFieldTypes::ScalarUnion +>; class OperatorField { @@ -80,6 +89,9 @@ public: const OperatorFieldTypes::UInt& AsUInt() const { return std::get(m_data); } OperatorFieldTypes::UInt& AsUInt() { return std::get(m_data); } + const OperatorFieldTypes::UInt64& AsUInt64() const { return std::get(m_data); } + OperatorFieldTypes::UInt64& AsUInt64() { return std::get(m_data); } + const OperatorFieldTypes::Int& AsInt() const { return std::get(m_data); } OperatorFieldTypes::Int& AsInt() { return std::get(m_data); } @@ -89,6 +101,9 @@ public: const OperatorFieldTypes::UIntArray& AsUIntArray() const { return std::get(m_data); } OperatorFieldTypes::UIntArray& AsUIntArray() { return std::get(m_data); } + const OperatorFieldTypes::IntArray& AsIntArray() const { return std::get(m_data); } + OperatorFieldTypes::IntArray& AsIntArray() { return std::get(m_data); } + const OperatorFieldTypes::FloatArray& AsFloatArray() const { return std::get(m_data); } OperatorFieldTypes::FloatArray& AsFloatArray() { return std::get(m_data); } @@ -98,6 +113,9 @@ public: const OperatorFieldTypes::Size2D& AsSize2D() const { return std::get(m_data); } OperatorFieldTypes::Size2D& AsSize2D() { return std::get(m_data); } + const OperatorFieldTypes::ScalarUnion& AsScalarUnion() const { return std::get(m_data); } + OperatorFieldTypes::ScalarUnion& AsScalarUnion() { return std::get(m_data); } + private: const DML_SCHEMA_FIELD* m_schema; OperatorFieldVariant m_data; diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/External/DirectMLHelpers/SchemaHelpers.h b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/External/DirectMLHelpers/SchemaHelpers.h index fba6503dd6..09f1b1cdc4 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/External/DirectMLHelpers/SchemaHelpers.h +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/External/DirectMLHelpers/SchemaHelpers.h @@ -50,6 +50,11 @@ namespace SchemaHelpers return value; } + inline OperatorFieldTypes::UInt64 ToOperatorFieldType(uint64_t value) + { + return value; + } + inline OperatorFieldTypes::Int ToOperatorFieldType(int32_t value) { return value; @@ -71,6 +76,17 @@ namespace SchemaHelpers return field; } + inline OperatorFieldTypes::IntArray ToOperatorFieldType(const int32_t* values, uint32_t count) + { + OperatorFieldTypes::IntArray field; + if (values && count != 0) + { + field.emplace(count); + std::copy_n(values, count, field->begin()); + } + return field; + } + inline OperatorFieldTypes::FloatArray ToOperatorFieldType(const float* values, uint32_t count) { OperatorFieldTypes::FloatArray field; @@ -92,6 +108,10 @@ namespace SchemaHelpers return value; } + inline OperatorFieldTypes::ScalarUnion ToOperatorFieldType(DML_SCALAR_UNION value) + { + return value; + } class StructFieldWriter { @@ -250,6 +270,12 @@ namespace SchemaHelpers dst->Write(value); } break; + case DML_SCHEMA_FIELD_TYPE_UINT64: + { + uint64_t value = field.AsUInt64(); + dst->Write(value); + } break; + case DML_SCHEMA_FIELD_TYPE_INT: { int32_t value = field.AsInt(); @@ -276,6 +302,20 @@ namespace SchemaHelpers dst->Write(arrayPtr); } break; + case DML_SCHEMA_FIELD_TYPE_INT_ARRAY: + { + int32_t* arrayPtr = nullptr; + + const auto& values = field.AsIntArray(); + if (values) + { + arrayPtr = allocator->Allocate(values->size()); + std::copy(values->begin(), values->end(), arrayPtr); + } + + dst->Write(arrayPtr); + } break; + case DML_SCHEMA_FIELD_TYPE_FLOAT_ARRAY: { float* arrayPtr = nullptr; @@ -310,6 +350,12 @@ namespace SchemaHelpers dst->Write(value); } break; + case DML_SCHEMA_FIELD_TYPE_SCALAR_UNION: + { + uint64_t value = field.AsScalarUnion().UInt64; + dst->Write(value); + } break; + default: assert(false); THROW_HR(E_UNEXPECTED); diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorConvInteger.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorConvInteger.cpp new file mode 100644 index 0000000000..45f4204abd --- /dev/null +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorConvInteger.cpp @@ -0,0 +1,81 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +//TODO::: + +#include "precomp.h" + +namespace Dml +{ + +class DmlOperatorConvInteger : public DmlOperator, OneHotHelper// TODO::: +{ +public: + using Self = DmlOperatorConvInteger; + + DmlOperatorConvInteger(const MLOperatorKernelCreationContext& kernelCreationContext) + : DmlOperator(kernelCreationContext), + OneHotHelper(kernelCreationContext, kernelCreationContext.GetTensorShapeDescription()) + { + ML_CHECK_VALID_ARGUMENT(kernelCreationContext.GetInputCount() == 3); + ML_CHECK_VALID_ARGUMENT(kernelCreationContext.GetOutputCount() == 1); + std::vector> inputIndices = { 0, 2 }; // The second tensor ('depth') is not bound, just 'indices' and 'values'. + std::vector> outputIndices = { 0 }; + DmlOperator::Initialize(kernelCreationContext, inputIndices, outputIndices); + + // Unsqueeze the indices tensor by inserting a flat dimension of size 1, + // and compute the output tensor by expanding along the active axis. + // This way they are both size-compatible and directly consumable by DirectML. + std::vector indicesDimensions; + indicesDimensions = kernelCreationContext.GetTensorShapeDescription().GetInputTensorShape(0); + indicesDimensions.insert(indicesDimensions.begin() + m_absoluteAxis, 1u); + + // Update the tensor descriptions with new sizes. + m_inputTensorDescs[0] = + TensorDesc( + m_inputTensorDescs[0].GetMlOperatorDataType(), + gsl::make_span(indicesDimensions), + gsl::make_span(indicesDimensions), + TensorAxis::DoNotCoerce, + TensorAxis::W, + TensorAxis::RightAligned, + NchwDimensionCount, // minDimensionCount + 0 + ); + + m_outputTensorDescs[0] = + TensorDesc( + m_outputTensorDescs[0].GetMlOperatorDataType(), + gsl::make_span(m_outputDimensions), + gsl::make_span(m_outputDimensions), + TensorAxis::DoNotCoerce, + TensorAxis::W, + TensorAxis::RightAligned, + NchwDimensionCount, // minDimensionCount + 0 + ); + + // Adjust the axis so it's in DML's terms rather than the original ONNX indexing. + uint32_t dmlAxis = GetDmlAdjustedAxis( + m_absoluteAxis, + gsl::narrow_cast(indicesDimensions.size()), + m_inputTensorDescs.front().GetDimensionCount() + ); + + std::vector inputDescs = GetDmlInputDescs(); + std::vector outputDescs = GetDmlOutputDescs(); + + DML_ONE_HOT_OPERATOR_DESC operatorDesc = {}; + operatorDesc.IndicesTensor = &inputDescs[0]; + operatorDesc.ValuesTensor = &inputDescs[1]; + operatorDesc.OutputTensor = outputDescs.data(); + operatorDesc.Axis = dmlAxis; + + DML_OPERATOR_DESC opDesc = { DML_OPERATOR_ONE_HOT, &operatorDesc }; + SetDmlOperatorDesc(opDesc, kernelCreationContext); + } +}; + +DML_OP_DEFINE_CREATION_FUNCTION(ConvInteger, DmlOperatorConvInteger); + +} // namespace Dml diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorCumSum.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorCumSum.cpp new file mode 100644 index 0000000000..4a8e438eb1 --- /dev/null +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorCumSum.cpp @@ -0,0 +1,45 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "precomp.h" + +namespace Dml +{ + +class DmlOperatorCumSum : public DmlOperator, OneHotHelper +{ +public: + using Self = DmlOperatorCumSum; + + DmlOperatorCumSum(const MLOperatorKernelCreationContext& kernelCreationContext) + : DmlOperator(kernelCreationContext), + OneHotHelper(kernelCreationContext, kernelCreationContext.GetTensorShapeDescription()) + { + ML_CHECK_VALID_ARGUMENT(kernelCreationContext.GetInputCount() == 1); + ML_CHECK_VALID_ARGUMENT(kernelCreationContext.GetOutputCount() == 1); + DmlOperator::Initialize(kernelCreationContext); + + // Adjust the axis so it's in DML's terms rather than the original ONNX indexing. + int32_t hasExclusiveSum = kernelCreationContext.GetOptionalAttribute(AttrName::Exclusive, 0); + int32_t isReversed = kernelCreationContext.GetOptionalAttribute(AttrName::Reverse, 0); + int32_t onnxAxis = kernelCreationContext.GetOptionalAttribute(AttrName::Axis, -1); + uint32_t dmlAxis = GetDmlAdjustedAxis(onnxAxis, kernelCreationContext, m_inputTensorDescs.front().GetDimensionCount()); + + std::vector inputDescs = GetDmlInputDescs(); + std::vector outputDescs = GetDmlOutputDescs(); + + DML_CUMULATIVE_SUMMATION_OPERATOR_DESC operatorDesc = {}; + operatorDesc.InputTensor = inputDescs.data(); + operatorDesc.OutputTensor = outputDescs.data(); + operatorDesc.HasExclusiveSum = hasExclusiveSum; + operatorDesc.Axis = dmlAxis; + operatorDesc.AxisDirection = isReversed ? DML_AXIS_DIRECTION_DECREASING : DML_AXIS_DIRECTION_INCREASING; + + DML_OPERATOR_DESC opDesc = { DML_OPERATOR_CUMULATIVE_SUMMATION, &operatorDesc }; + SetDmlOperatorDesc(opDesc, kernelCreationContext); + } +}; + +DML_OP_DEFINE_CREATION_FUNCTION(CumSum, DmlOperatorCumSum); + +} // namespace Dml diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorDynamicQuantizeLinear.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorDynamicQuantizeLinear.cpp new file mode 100644 index 0000000000..0f4487de52 --- /dev/null +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorDynamicQuantizeLinear.cpp @@ -0,0 +1,79 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "precomp.h" +//TODO::: +namespace Dml +{ + +class DmlOperatorDynamicQuantizeLinear : public DmlOperator, OneHotHelper +{ +public: + using Self = DmlOperatorDynamicQuantizeLinear; + + DmlOperatorDynamicQuantizeLinear(const MLOperatorKernelCreationContext& kernelCreationContext) + : DmlOperator(kernelCreationContext), + OneHotHelper(kernelCreationContext, kernelCreationContext.GetTensorShapeDescription()) + { + ML_CHECK_VALID_ARGUMENT(kernelCreationContext.GetInputCount() == 3); + ML_CHECK_VALID_ARGUMENT(kernelCreationContext.GetOutputCount() == 1); + std::vector> inputIndices = { 0, 2 }; // The second tensor ('depth') is not bound, just 'indices' and 'values'. + std::vector> outputIndices = { 0 }; + DmlOperator::Initialize(kernelCreationContext, inputIndices, outputIndices); + + // Unsqueeze the indices tensor by inserting a flat dimension of size 1, + // and compute the output tensor by expanding along the active axis. + // This way they are both size-compatible and directly consumable by DirectML. + std::vector indicesDimensions; + indicesDimensions = kernelCreationContext.GetTensorShapeDescription().GetInputTensorShape(0); + indicesDimensions.insert(indicesDimensions.begin() + m_absoluteAxis, 1u); + + // Update the tensor descriptions with new sizes. + m_inputTensorDescs[0] = + TensorDesc( + m_inputTensorDescs[0].GetMlOperatorDataType(), + gsl::make_span(indicesDimensions), + gsl::make_span(indicesDimensions), + TensorAxis::DoNotCoerce, + TensorAxis::W, + TensorAxis::RightAligned, + NchwDimensionCount, // minDimensionCount + 0 + ); + + m_outputTensorDescs[0] = + TensorDesc( + m_outputTensorDescs[0].GetMlOperatorDataType(), + gsl::make_span(m_outputDimensions), + gsl::make_span(m_outputDimensions), + TensorAxis::DoNotCoerce, + TensorAxis::W, + TensorAxis::RightAligned, + NchwDimensionCount, // minDimensionCount + 0 + ); + + // Adjust the axis so it's in DML's terms rather than the original ONNX indexing. + uint32_t dmlAxis = GetDmlAdjustedAxis( + m_absoluteAxis, + gsl::narrow_cast(indicesDimensions.size()), + m_inputTensorDescs.front().GetDimensionCount() + ); + + std::vector inputDescs = GetDmlInputDescs(); + std::vector outputDescs = GetDmlOutputDescs(); + + DML_ONE_HOT_OPERATOR_DESC operatorDesc = {}; + operatorDesc.IndicesTensor = &inputDescs[0]; + operatorDesc.ValuesTensor = &inputDescs[1]; + operatorDesc.OutputTensor = outputDescs.data(); + operatorDesc.Axis = dmlAxis; + + DML_OPERATOR_DESC opDesc = { DML_OPERATOR_ONE_HOT, &operatorDesc }; + SetDmlOperatorDesc(opDesc, kernelCreationContext); + } +}; + +DML_OP_DEFINE_CREATION_FUNCTION(DynamicQuantizeLinear, DmlOperatorDynamicQuantizeLinear); + +} // namespace Dml diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorElementWise.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorElementWise.cpp index 3e7341c625..9226816503 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorElementWise.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorElementWise.cpp @@ -70,7 +70,7 @@ public: } else { - // Dml doesn't support UINT datatypes redirect to Identity because abs doesn't do anything to UINT + // DML doesn't support UINT datatypes. So redirect to Identity because Abs doesn't do anything to UINT. DML_ELEMENT_WISE_IDENTITY_OPERATOR_DESC opDesc = {}; opDesc.InputTensor = inputDescs.data(); opDesc.OutputTensor = outputDescs.data(); @@ -534,6 +534,110 @@ public: } }; +class DmlOperatorElementwiseMod : public DmlOperator +{ +public: + DmlOperatorElementwiseMod(const MLOperatorKernelCreationContext& kernelInfo) : DmlOperator(kernelInfo) + { + ML_CHECK_VALID_ARGUMENT(kernelInfo.GetInputCount() == 2); + ML_CHECK_VALID_ARGUMENT(kernelInfo.GetOutputCount() == 1); + + Initialize(kernelInfo, std::nullopt, std::nullopt, kernelInfo.GetTensorShapeDescription().GetOutputTensorShape(0)); + + std::vector inputDescs = GetDmlInputDescs(); + std::vector outputDescs = GetDmlOutputDescs(); + + auto fmod = kernelInfo.GetOptionalAttribute(AttrName::Fmod, 0); + + // Note TRUNCATE and FLOOR modulus operator descriptions are identical. + static_assert(sizeof(DML_ELEMENT_WISE_MODULUS_TRUNCATE_OPERATOR_DESC) == sizeof(DML_ELEMENT_WISE_MODULUS_FLOOR_OPERATOR_DESC)); + DML_ELEMENT_WISE_MODULUS_TRUNCATE_OPERATOR_DESC opDesc = {}; + opDesc.ATensor = &inputDescs[0]; + opDesc.BTensor = &inputDescs[1]; + opDesc.OutputTensor = &outputDescs[0]; + + DML_OPERATOR_TYPE type = fmod ? DML_OPERATOR_ELEMENT_WISE_MODULUS_TRUNCATE : DML_OPERATOR_ELEMENT_WISE_MODULUS_FLOOR; + SetDmlOperatorDesc({ type, &opDesc}, kernelInfo); + } +}; + +class DmlOperatorElementwiseBitShift : public DmlOperator +{ +public: + DmlOperatorElementwiseBitShift(const MLOperatorKernelCreationContext& kernelInfo) : DmlOperator(kernelInfo) + { + ML_CHECK_VALID_ARGUMENT(kernelInfo.GetInputCount() == 2); + ML_CHECK_VALID_ARGUMENT(kernelInfo.GetOutputCount() == 1); + + Initialize(kernelInfo, std::nullopt, std::nullopt, kernelInfo.GetTensorShapeDescription().GetOutputTensorShape(0)); + + std::vector inputDescs = GetDmlInputDescs(); + std::vector outputDescs = GetDmlOutputDescs(); + + // Note LEFT and RIGHT shift operator descriptions are identical. + static_assert(sizeof(DML_ELEMENT_WISE_BIT_SHIFT_LEFT_OPERATOR_DESC) == sizeof(DML_ELEMENT_WISE_BIT_SHIFT_RIGHT_OPERATOR_DESC)); + DML_ELEMENT_WISE_BIT_SHIFT_LEFT_OPERATOR_DESC opDesc = {}; + opDesc.ATensor = &inputDescs[0]; + opDesc.BTensor = &inputDescs[1]; + opDesc.OutputTensor = &outputDescs[0]; + + std::string mode = kernelInfo.GetOptionalAttribute(AttrName::Direction, ""); + ML_CHECK_VALID_ARGUMENT(mode == "LEFT" || mode == "RIGHT"); + + DML_OPERATOR_TYPE type = (mode == "LEFT") ? DML_OPERATOR_ELEMENT_WISE_BIT_SHIFT_LEFT : DML_OPERATOR_ELEMENT_WISE_BIT_SHIFT_RIGHT; + SetDmlOperatorDesc({ type, &opDesc}, kernelInfo); + } +}; + +class DmlOperatorElementwiseIsInf : public DmlOperator +{ +public: + DmlOperatorElementwiseIsInf(const MLOperatorKernelCreationContext& kernelInfo) : DmlOperator(kernelInfo) + { + ML_CHECK_VALID_ARGUMENT(kernelInfo.GetInputCount() == 1); + ML_CHECK_VALID_ARGUMENT(kernelInfo.GetOutputCount() == 1); + + Initialize(kernelInfo, std::nullopt, std::nullopt, kernelInfo.GetTensorShapeDescription().GetOutputTensorShape(0)); + + std::vector inputDescs = GetDmlInputDescs(); + std::vector outputDescs = GetDmlOutputDescs(); + + auto detectPositive = kernelInfo.GetOptionalAttribute(AttrName::DetectPositive, 1); + auto detectNegative = kernelInfo.GetOptionalAttribute(AttrName::DetectNegative, 1); + + DML_ELEMENT_WISE_IS_INFINITY_OPERATOR_DESC opDesc = {}; + opDesc.InputTensor = inputDescs.data(); + opDesc.OutputTensor = outputDescs.data(); + opDesc.InfinityMode = (detectPositive == detectNegative) ? DML_IS_INFINITY_MODE_EITHER + : detectPositive ? DML_IS_INFINITY_MODE_POSITIVE + : DML_IS_INFINITY_MODE_NEGATIVE; + + SetDmlOperatorDesc({ DML_OPERATOR_ELEMENT_WISE_CLIP, &opDesc}, kernelInfo); + } +}; + +class DmlOperatorElementwiseRound : public DmlOperator +{ +public: + DmlOperatorElementwiseRound(const MLOperatorKernelCreationContext& kernelInfo) : DmlOperator(kernelInfo) + { + ML_CHECK_VALID_ARGUMENT(kernelInfo.GetInputCount() == 1); + ML_CHECK_VALID_ARGUMENT(kernelInfo.GetOutputCount() == 1); + + Initialize(kernelInfo, std::nullopt, std::nullopt, kernelInfo.GetTensorShapeDescription().GetOutputTensorShape(0)); + + std::vector inputDescs = GetDmlInputDescs(); + std::vector outputDescs = GetDmlOutputDescs(); + + DML_ELEMENT_WISE_ROUND_OPERATOR_DESC opDesc = {}; + opDesc.InputTensor = inputDescs.data(); + opDesc.OutputTensor = outputDescs.data(); + opDesc.RoundingMode = DML_ROUNDING_MODE_HALVES_TO_NEAREST_EVEN; + + SetDmlOperatorDesc({ DML_OPERATOR_ELEMENT_WISE_ROUND, &opDesc}, kernelInfo); + } +}; + // Unary operators: DML_OP_DEFINE_CREATION_FUNCTION(Sqrt, DmlOperatorElementwiseUnary); DML_OP_DEFINE_CREATION_FUNCTION(Reciprocal, DmlOperatorElementwiseUnary); @@ -582,6 +686,10 @@ 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); // Fused operators: DML_OP_DEFINE_CREATION_FUNCTION(FusedAdd, DmlOperatorElementwiseBinary); diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorGather.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorGather.cpp index b06e1c3afd..01dd7379d3 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorGather.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorGather.cpp @@ -44,5 +44,8 @@ public: }; DML_OP_DEFINE_CREATION_FUNCTION(Gather, DmlOperatorGather); +// TODO::: +DML_OP_DEFINE_CREATION_FUNCTION(GatherElements, DmlOperatorGather); +DML_OP_DEFINE_CREATION_FUNCTION(GatherND, DmlOperatorGather); } // namespace Dml diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorGemm.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorGemm.cpp index e5c1ff555f..5fcc8a89fe 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorGemm.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorGemm.cpp @@ -36,7 +36,7 @@ public: DML_GEMM_OPERATOR_DESC gemmDesc = {}; gemmDesc.ATensor = &inputDescs[0]; gemmDesc.BTensor = &inputDescs[1]; - gemmDesc.CTensor = &inputDescs[2]; + gemmDesc.CTensor = kernelInfo.IsInputValid(2) ? &inputDescs[2] : nullptr; gemmDesc.OutputTensor = &outputDescs[0]; gemmDesc.TransA = (m_transA ? DML_MATRIX_TRANSFORM_TRANSPOSE : DML_MATRIX_TRANSFORM_NONE); gemmDesc.TransB = (m_transB ? DML_MATRIX_TRANSFORM_TRANSPOSE : DML_MATRIX_TRANSFORM_NONE); diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorMatMulInteger.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorMatMulInteger.cpp new file mode 100644 index 0000000000..bf9e62d3bb --- /dev/null +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorMatMulInteger.cpp @@ -0,0 +1,81 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + + +//TODO::: +#include "precomp.h" + +namespace Dml +{ + +class DmlOperatorMatMulInteger : public DmlOperator, OneHotHelper +{ +public: + using Self = DmlOperatorMatMulInteger; + + DmlOperatorMatMulInteger(const MLOperatorKernelCreationContext& kernelCreationContext) + : DmlOperator(kernelCreationContext), + OneHotHelper(kernelCreationContext, kernelCreationContext.GetTensorShapeDescription()) + { + ML_CHECK_VALID_ARGUMENT(kernelCreationContext.GetInputCount() == 3); + ML_CHECK_VALID_ARGUMENT(kernelCreationContext.GetOutputCount() == 1); + std::vector> inputIndices = { 0, 2 }; // The second tensor ('depth') is not bound, just 'indices' and 'values'. + std::vector> outputIndices = { 0 }; + DmlOperator::Initialize(kernelCreationContext, inputIndices, outputIndices); + + // Unsqueeze the indices tensor by inserting a flat dimension of size 1, + // and compute the output tensor by expanding along the active axis. + // This way they are both size-compatible and directly consumable by DirectML. + std::vector indicesDimensions; + indicesDimensions = kernelCreationContext.GetTensorShapeDescription().GetInputTensorShape(0); + indicesDimensions.insert(indicesDimensions.begin() + m_absoluteAxis, 1u); + + // Update the tensor descriptions with new sizes. + m_inputTensorDescs[0] = + TensorDesc( + m_inputTensorDescs[0].GetMlOperatorDataType(), + gsl::make_span(indicesDimensions), + gsl::make_span(indicesDimensions), + TensorAxis::DoNotCoerce, + TensorAxis::W, + TensorAxis::RightAligned, + NchwDimensionCount, // minDimensionCount + 0 + ); + + m_outputTensorDescs[0] = + TensorDesc( + m_outputTensorDescs[0].GetMlOperatorDataType(), + gsl::make_span(m_outputDimensions), + gsl::make_span(m_outputDimensions), + TensorAxis::DoNotCoerce, + TensorAxis::W, + TensorAxis::RightAligned, + NchwDimensionCount, // minDimensionCount + 0 + ); + + // Adjust the axis so it's in DML's terms rather than the original ONNX indexing. + uint32_t dmlAxis = GetDmlAdjustedAxis( + m_absoluteAxis, + gsl::narrow_cast(indicesDimensions.size()), + m_inputTensorDescs.front().GetDimensionCount() + ); + + std::vector inputDescs = GetDmlInputDescs(); + std::vector outputDescs = GetDmlOutputDescs(); + + DML_ONE_HOT_OPERATOR_DESC operatorDesc = {}; + operatorDesc.IndicesTensor = &inputDescs[0]; + operatorDesc.ValuesTensor = &inputDescs[1]; + operatorDesc.OutputTensor = outputDescs.data(); + operatorDesc.Axis = dmlAxis; + + DML_OPERATOR_DESC opDesc = { DML_OPERATOR_ONE_HOT, &operatorDesc }; + SetDmlOperatorDesc(opDesc, kernelCreationContext); + } +}; + +DML_OP_DEFINE_CREATION_FUNCTION(MatMulInteger, DmlOperatorMatMulInteger); + +} // namespace Dml diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorQLinearConv.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorQLinearConv.cpp new file mode 100644 index 0000000000..211d34f051 --- /dev/null +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorQLinearConv.cpp @@ -0,0 +1,81 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// TODO::: + +#include "precomp.h" + +namespace Dml +{ + +class DmlOperatorQLinearConv : public DmlOperator, OneHotHelper +{ +public: + using Self = DmlOperatorQLinearConv; + + DmlOperatorQLinearConv(const MLOperatorKernelCreationContext& kernelCreationContext) + : DmlOperator(kernelCreationContext), + OneHotHelper(kernelCreationContext, kernelCreationContext.GetTensorShapeDescription()) + { + ML_CHECK_VALID_ARGUMENT(kernelCreationContext.GetInputCount() == 3); + ML_CHECK_VALID_ARGUMENT(kernelCreationContext.GetOutputCount() == 1); + std::vector> inputIndices = { 0, 2 }; // The second tensor ('depth') is not bound, just 'indices' and 'values'. + std::vector> outputIndices = { 0 }; + DmlOperator::Initialize(kernelCreationContext, inputIndices, outputIndices); + + // Unsqueeze the indices tensor by inserting a flat dimension of size 1, + // and compute the output tensor by expanding along the active axis. + // This way they are both size-compatible and directly consumable by DirectML. + std::vector indicesDimensions; + indicesDimensions = kernelCreationContext.GetTensorShapeDescription().GetInputTensorShape(0); + indicesDimensions.insert(indicesDimensions.begin() + m_absoluteAxis, 1u); + + // Update the tensor descriptions with new sizes. + m_inputTensorDescs[0] = + TensorDesc( + m_inputTensorDescs[0].GetMlOperatorDataType(), + gsl::make_span(indicesDimensions), + gsl::make_span(indicesDimensions), + TensorAxis::DoNotCoerce, + TensorAxis::W, + TensorAxis::RightAligned, + NchwDimensionCount, // minDimensionCount + 0 + ); + + m_outputTensorDescs[0] = + TensorDesc( + m_outputTensorDescs[0].GetMlOperatorDataType(), + gsl::make_span(m_outputDimensions), + gsl::make_span(m_outputDimensions), + TensorAxis::DoNotCoerce, + TensorAxis::W, + TensorAxis::RightAligned, + NchwDimensionCount, // minDimensionCount + 0 + ); + + // Adjust the axis so it's in DML's terms rather than the original ONNX indexing. + uint32_t dmlAxis = GetDmlAdjustedAxis( + m_absoluteAxis, + gsl::narrow_cast(indicesDimensions.size()), + m_inputTensorDescs.front().GetDimensionCount() + ); + + std::vector inputDescs = GetDmlInputDescs(); + std::vector outputDescs = GetDmlOutputDescs(); + + DML_ONE_HOT_OPERATOR_DESC operatorDesc = {}; + operatorDesc.IndicesTensor = &inputDescs[0]; + operatorDesc.ValuesTensor = &inputDescs[1]; + operatorDesc.OutputTensor = outputDescs.data(); + operatorDesc.Axis = dmlAxis; + + DML_OPERATOR_DESC opDesc = { DML_OPERATOR_ONE_HOT, &operatorDesc }; + SetDmlOperatorDesc(opDesc, kernelCreationContext); + } +}; + +DML_OP_DEFINE_CREATION_FUNCTION(QLinearConv, DmlOperatorQLinearConv); + +} // namespace Dml diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorQLinearMatMul.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorQLinearMatMul.cpp new file mode 100644 index 0000000000..2d46a4cb92 --- /dev/null +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorQLinearMatMul.cpp @@ -0,0 +1,81 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +//TODO::: + +#include "precomp.h" + +namespace Dml +{ + +class DmlOperatorQLinearMatMul : public DmlOperator, OneHotHelper +{ +public: + using Self = DmlOperatorQLinearMatMul; + + DmlOperatorQLinearMatMul(const MLOperatorKernelCreationContext& kernelCreationContext) + : DmlOperator(kernelCreationContext), + OneHotHelper(kernelCreationContext, kernelCreationContext.GetTensorShapeDescription()) + { + ML_CHECK_VALID_ARGUMENT(kernelCreationContext.GetInputCount() == 3); + ML_CHECK_VALID_ARGUMENT(kernelCreationContext.GetOutputCount() == 1); + std::vector> inputIndices = { 0, 2 }; // The second tensor ('depth') is not bound, just 'indices' and 'values'. + std::vector> outputIndices = { 0 }; + DmlOperator::Initialize(kernelCreationContext, inputIndices, outputIndices); + + // Unsqueeze the indices tensor by inserting a flat dimension of size 1, + // and compute the output tensor by expanding along the active axis. + // This way they are both size-compatible and directly consumable by DirectML. + std::vector indicesDimensions; + indicesDimensions = kernelCreationContext.GetTensorShapeDescription().GetInputTensorShape(0); + indicesDimensions.insert(indicesDimensions.begin() + m_absoluteAxis, 1u); + + // Update the tensor descriptions with new sizes. + m_inputTensorDescs[0] = + TensorDesc( + m_inputTensorDescs[0].GetMlOperatorDataType(), + gsl::make_span(indicesDimensions), + gsl::make_span(indicesDimensions), + TensorAxis::DoNotCoerce, + TensorAxis::W, + TensorAxis::RightAligned, + NchwDimensionCount, // minDimensionCount + 0 + ); + + m_outputTensorDescs[0] = + TensorDesc( + m_outputTensorDescs[0].GetMlOperatorDataType(), + gsl::make_span(m_outputDimensions), + gsl::make_span(m_outputDimensions), + TensorAxis::DoNotCoerce, + TensorAxis::W, + TensorAxis::RightAligned, + NchwDimensionCount, // minDimensionCount + 0 + ); + + // Adjust the axis so it's in DML's terms rather than the original ONNX indexing. + uint32_t dmlAxis = GetDmlAdjustedAxis( + m_absoluteAxis, + gsl::narrow_cast(indicesDimensions.size()), + m_inputTensorDescs.front().GetDimensionCount() + ); + + std::vector inputDescs = GetDmlInputDescs(); + std::vector outputDescs = GetDmlOutputDescs(); + + DML_ONE_HOT_OPERATOR_DESC operatorDesc = {}; + operatorDesc.IndicesTensor = &inputDescs[0]; + operatorDesc.ValuesTensor = &inputDescs[1]; + operatorDesc.OutputTensor = outputDescs.data(); + operatorDesc.Axis = dmlAxis; + + DML_OPERATOR_DESC opDesc = { DML_OPERATOR_ONE_HOT, &operatorDesc }; + SetDmlOperatorDesc(opDesc, kernelCreationContext); + } +}; + +DML_OP_DEFINE_CREATION_FUNCTION(QLinearMatMul, DmlOperatorQLinearMatMul); + +} // namespace Dml diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorRange.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorRange.cpp new file mode 100644 index 0000000000..e9048056c3 --- /dev/null +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorRange.cpp @@ -0,0 +1,82 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + + +// TODO::: + +#include "precomp.h" + +namespace Dml +{ + +class DmlOperatorRange : public DmlOperator, OneHotHelper +{ +public: + using Self = DmlOperatorRange; + + DmlOperatorRange(const MLOperatorKernelCreationContext& kernelCreationContext) + : DmlOperator(kernelCreationContext), + OneHotHelper(kernelCreationContext, kernelCreationContext.GetTensorShapeDescription()) + { + ML_CHECK_VALID_ARGUMENT(kernelCreationContext.GetInputCount() == 3); + ML_CHECK_VALID_ARGUMENT(kernelCreationContext.GetOutputCount() == 1); + std::vector> inputIndices = { 0, 2 }; // The second tensor ('depth') is not bound, just 'indices' and 'values'. + std::vector> outputIndices = { 0 }; + DmlOperator::Initialize(kernelCreationContext, inputIndices, outputIndices); + + // Unsqueeze the indices tensor by inserting a flat dimension of size 1, + // and compute the output tensor by expanding along the active axis. + // This way they are both size-compatible and directly consumable by DirectML. + std::vector indicesDimensions; + indicesDimensions = kernelCreationContext.GetTensorShapeDescription().GetInputTensorShape(0); + indicesDimensions.insert(indicesDimensions.begin() + m_absoluteAxis, 1u); + + // Update the tensor descriptions with new sizes. + m_inputTensorDescs[0] = + TensorDesc( + m_inputTensorDescs[0].GetMlOperatorDataType(), + gsl::make_span(indicesDimensions), + gsl::make_span(indicesDimensions), + TensorAxis::DoNotCoerce, + TensorAxis::W, + TensorAxis::RightAligned, + NchwDimensionCount, // minDimensionCount + 0 + ); + + m_outputTensorDescs[0] = + TensorDesc( + m_outputTensorDescs[0].GetMlOperatorDataType(), + gsl::make_span(m_outputDimensions), + gsl::make_span(m_outputDimensions), + TensorAxis::DoNotCoerce, + TensorAxis::W, + TensorAxis::RightAligned, + NchwDimensionCount, // minDimensionCount + 0 + ); + + // Adjust the axis so it's in DML's terms rather than the original ONNX indexing. + uint32_t dmlAxis = GetDmlAdjustedAxis( + m_absoluteAxis, + gsl::narrow_cast(indicesDimensions.size()), + m_inputTensorDescs.front().GetDimensionCount() + ); + + std::vector inputDescs = GetDmlInputDescs(); + std::vector outputDescs = GetDmlOutputDescs(); + + DML_ONE_HOT_OPERATOR_DESC operatorDesc = {}; + operatorDesc.IndicesTensor = &inputDescs[0]; + operatorDesc.ValuesTensor = &inputDescs[1]; + operatorDesc.OutputTensor = outputDescs.data(); + operatorDesc.Axis = dmlAxis; + + DML_OPERATOR_DESC opDesc = { DML_OPERATOR_ONE_HOT, &operatorDesc }; + SetDmlOperatorDesc(opDesc, kernelCreationContext); + } +}; + +DML_OP_DEFINE_CREATION_FUNCTION(Range, DmlOperatorRange); + +} // namespace Dml diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorReverseSequence.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorReverseSequence.cpp new file mode 100644 index 0000000000..842ad8f4cc --- /dev/null +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorReverseSequence.cpp @@ -0,0 +1,67 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + + +// TODO::: + +#include "precomp.h" + +namespace Dml +{ + +class DmlOperatorReverseSequence : public DmlOperator, OneHotHelper +{ +public: + using Self = DmlOperatorReverseSequence; + + DmlOperatorReverseSequence(const MLOperatorKernelCreationContext& kernelCreationContext) + : DmlOperator(kernelCreationContext), + OneHotHelper(kernelCreationContext, kernelCreationContext.GetTensorShapeDescription()) + { + ML_CHECK_VALID_ARGUMENT(kernelCreationContext.GetInputCount() == 2); + ML_CHECK_VALID_ARGUMENT(kernelCreationContext.GetOutputCount() == 1); + DmlOperator::Initialize(kernelCreationContext); + + std::vector inputDimensions = kernelCreationContext.GetTensorShapeDescription().GetInputTensorShape(0); + std::vector sequenceLengthDimensions = kernelCreationContext.GetTensorShapeDescription().GetInputTensorShape(1); + + // Read axis. + int32_t onnxAxis = kernelCreationContext.GetOptionalAttribute(AttrName::TimeAxis, 0); + onnxAxis = HandleNegativeAxis(onnxAxis, static_cast(inputDimensions.size())); + const uint32_t dmlAxis = GetDmlAdjustedAxis(onnxAxis, onnxAxis, m_inputTensorDescs.front().GetDimensionCount()); + + // Fix up the sequence lengths tensor (originally 1D) to be rank compatible with input, + // with all dimensions being the same as input except the active reversal axis. + std::vector adjustedSequenceLengthDimensions = inputDimensions; + adjustedSequenceLengthDimensions[onnxAxis] = 1; + ML_CHECK_VALID_ARGUMENT(ComputeElementCountFromDimensions(adjustedSequenceLengthDimensions), ComputeElementCountFromDimensions(sequenceLengthDimensions)); + + m_inputTensorDescs[1] = + TensorDesc( + m_inputTensorDescs[0].GetMlOperatorDataType(), + gsl::make_span(adjustedSequenceLengthDimensions), + gsl::make_span(adjustedSequenceLengthDimensions), + TensorAxis::DoNotCoerce, + TensorAxis::W, + TensorAxis::RightAligned, + NchwDimensionCount, // minDimensionCount + 0 + ); + + std::vector inputDescs = GetDmlInputDescs(); + std::vector outputDescs = GetDmlOutputDescs(); + + DML_REVERSE_SUBSEQUENCES_OPERATOR_DESC operatorDesc = {}; + operatorDesc.InputTensor = &inputDescs[0]; + operatorDesc.SequenceLengthsTensor = &inputDescs[1]; + operatorDesc.OutputTensor = outputDescs.data(); + operatorDesc.Axis = dmlAxis; + + DML_OPERATOR_DESC opDesc = { DML_OPERATOR_REVERSE_SUBSEQUENCES, &operatorDesc }; + SetDmlOperatorDesc(opDesc, kernelCreationContext); + } +}; + +DML_OP_DEFINE_CREATION_FUNCTION(ReverseSequence, DmlOperatorReverseSequence); + +} // namespace Dml diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorScatter.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorScatter.cpp index ee742c4ccb..97b881d542 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorScatter.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorScatter.cpp @@ -38,13 +38,10 @@ public: assert(inputDescs.size() == 1); assert(outputDescs.size() == 1); - DML_SCALE_BIAS scaleBias = {}; - scaleBias.Scale = 1.0f; - DML_ELEMENT_WISE_IDENTITY_OPERATOR_DESC operatorDesc = {}; operatorDesc.InputTensor = &inputDescs[0]; operatorDesc.OutputTensor = outputDescs.data(); - operatorDesc.ScaleBias = &scaleBias; + operatorDesc.ScaleBias = nullptr; DML_OPERATOR_DESC opDesc = { DML_OPERATOR_ELEMENT_WISE_IDENTITY, &operatorDesc }; SetDmlOperatorDesc(opDesc, kernelCreationContext); @@ -78,5 +75,8 @@ public: }; DML_OP_DEFINE_CREATION_FUNCTION(Scatter, DmlOperatorScatter); +// TODO::: +DML_OP_DEFINE_CREATION_FUNCTION(ScatterElements, DmlOperatorScatter); +DML_OP_DEFINE_CREATION_FUNCTION(ScatterND, DmlOperatorScatter); } // namespace Dml diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorSlice.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorSlice.cpp index 0e9d0feb5a..bbeb9d9a87 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorSlice.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorSlice.cpp @@ -71,11 +71,12 @@ public: } }; -void CALLBACK QuerySlice(IMLOperatorSupportQueryContextPrivate* context, bool *isSupported) +void CALLBACK QuerySlice(IMLOperatorSupportQueryContextPrivate* context, bool* isSupported) { *isSupported = (context->GetInputCount() <= 4); } DML_OP_DEFINE_CREATION_FUNCTION(Slice7, DmlOperatorSliceTemplate<7>); DML_OP_DEFINE_CREATION_FUNCTION(Slice10, DmlOperatorSliceTemplate<10>); +DML_OP_DEFINE_CREATION_FUNCTION(Slice11, DmlOperatorSliceTemplate<11>); } // namespace Dml diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp index f19bf8d6a9..077cc38c3d 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp @@ -101,6 +101,7 @@ DML_OP_EXTERN_CREATION_FUNCTION(Tile); DML_OP_EXTERN_CREATION_FUNCTION(Concat); DML_OP_EXTERN_CREATION_FUNCTION(Slice7); DML_OP_EXTERN_CREATION_FUNCTION(Slice10); +DML_OP_EXTERN_CREATION_FUNCTION(Slice11); DML_OP_EXTERN_CREATION_FUNCTION(Pad); DML_OP_EXTERN_CREATION_FUNCTION(SpaceToDepth); DML_OP_EXTERN_CREATION_FUNCTION(DepthToSpace); @@ -203,6 +204,22 @@ DML_OP_EXTERN_CREATION_FUNCTION(MaxUnpool); DML_OP_EXTERN_CREATION_FUNCTION(Scatter); DML_OP_EXTERN_CREATION_FUNCTION(Resize); DML_OP_EXTERN_CREATION_FUNCTION(ConstantOfShape); +DML_OP_EXTERN_CREATION_FUNCTION(IsInf); +DML_OP_EXTERN_CREATION_FUNCTION(Mod); +DML_OP_EXTERN_CREATION_FUNCTION(BitShift); +DML_OP_EXTERN_CREATION_FUNCTION(CumSum); +DML_OP_EXTERN_CREATION_FUNCTION(GatherElements); +DML_OP_EXTERN_CREATION_FUNCTION(GatherND); +DML_OP_EXTERN_CREATION_FUNCTION(Range); +DML_OP_EXTERN_CREATION_FUNCTION(ReverseSequence); +DML_OP_EXTERN_CREATION_FUNCTION(Round); +DML_OP_EXTERN_CREATION_FUNCTION(ScatterElements); +DML_OP_EXTERN_CREATION_FUNCTION(ScatterND); +DML_OP_EXTERN_CREATION_FUNCTION(QLinearConv); +DML_OP_EXTERN_CREATION_FUNCTION(QLinearMatMul); +DML_OP_EXTERN_CREATION_FUNCTION(DynamicQuantizeLinear); +DML_OP_EXTERN_CREATION_FUNCTION(MatMulInteger); +DML_OP_EXTERN_CREATION_FUNCTION(ConvInteger); DML_OP_EXTERN_QUERY_FUNCTION(MaxPool); DML_OP_EXTERN_QUERY_FUNCTION(Slice); @@ -210,16 +227,17 @@ DML_OP_EXTERN_QUERY_FUNCTION(Slice); const static char* const typeNameListDefault[1] = {"T"}; const static char* const typeNameListTopK[2] = { "T", "I" }; const static char* const typeNameListLogicalComparison[2] = { "T", "T1" }; -const static char* const typeNameListCast[2] = { "T1", "T2" }; -const static char* const typeNameListIsNan[2] = { "T1", "T2" }; +const static char* const typeNameListT1T2[2] = { "T1", "T2" }; const static char* const typeNameListConstantOfShape[2] = { "T1", "T2" }; const static char* const typeNameListScatterGather[2] = { "T", "Tind" }; +const static char* const typeNameListScatterGatherND[2] = { "T" }; // Tind is curiously missing, only allowing 64-bit. const static char* const typeNameListQuantize[2] = { "T1", "T2" }; const static char* const typeNameListWhere[2] = { "B", "T" }; const static char* const typeNameListOneHot[3] = { "T1", "T2", "T3" }; const static char* const typeNameListEyeLike[1] = { "T2" }; const static SupportedTensorDataTypes supportedTypeListAll[1] = {SupportedTensorDataTypes::All}; const static SupportedTensorDataTypes supportedTypeListFloat16to32[1] = {SupportedTensorDataTypes::Float16to32}; +const static SupportedTensorDataTypes supportedTypeListInt8to32[1] = {SupportedTensorDataTypes::Int8to32}; const static SupportedTensorDataTypes supportedTypeListInt32to64AndFloat16to32[1] = {SupportedTensorDataTypes::Int32to64|SupportedTensorDataTypes::Float16to32}; const static SupportedTensorDataTypes supportedTypeListNumericDefault[1] = { SupportedTensorDataTypes::NumericDefault }; const static SupportedTensorDataTypes supportedTypeListAllScalars[1] = { SupportedTensorDataTypes::AllScalars }; @@ -228,10 +246,12 @@ const static SupportedTensorDataTypes supportedTypeListTopK[2] = {SupportedTenso const static SupportedTensorDataTypes supportedTypeListIndices[1] = { SupportedTensorDataTypes::Int32|SupportedTensorDataTypes::Int64 }; const static SupportedTensorDataTypes supportedTypeListCast[2] = { SupportedTensorDataTypes::AllScalars, SupportedTensorDataTypes::Scalars8to32 }; const static SupportedTensorDataTypes supportedTypeListScatterGather[2] = { SupportedTensorDataTypes::NumericDefault, SupportedTensorDataTypes::Int32 | SupportedTensorDataTypes::Int64 }; +const static SupportedTensorDataTypes supportedTypeListScatterGatherND[2] = { SupportedTensorDataTypes::NumericDefault }; const static SupportedTensorDataTypes supportedTypeListQuantizeLinear[2] = { SupportedTensorDataTypes::Float32 | SupportedTensorDataTypes::Int32, SupportedTensorDataTypes::UInt8 | SupportedTensorDataTypes::Int8 }; const static SupportedTensorDataTypes supportedTypeListDequantizeLinear[2] = { SupportedTensorDataTypes::Float32, SupportedTensorDataTypes::UInt8 | SupportedTensorDataTypes::Int8 | SupportedTensorDataTypes::Int32 }; const static SupportedTensorDataTypes supportedTypeListQuantize[2] = { SupportedTensorDataTypes::Float32, SupportedTensorDataTypes::UInt8 }; const static SupportedTensorDataTypes supportedTypeListIsNan[2] = { SupportedTensorDataTypes::Float16to32, SupportedTensorDataTypes::UInt8 }; +const static SupportedTensorDataTypes supportedTypeListIsInf[2] = { SupportedTensorDataTypes::Float16to32, SupportedTensorDataTypes::UInt8 }; const static SupportedTensorDataTypes supportedTypeListConstantOfShape[2] = { SupportedTensorDataTypes::Int32|SupportedTensorDataTypes::Int64, SupportedTensorDataTypes::Float16to32 }; const static SupportedTensorDataTypes supportedTypeListWhere[2] = { SupportedTensorDataTypes::UInt8, SupportedTensorDataTypes::Float16to32 }; const static SupportedTensorDataTypes supportedTypeListOneHot[3] = /* indices, depth, values */ { SupportedTensorDataTypes::Int32to64, SupportedTensorDataTypes::AllScalars, SupportedTensorDataTypes::Float16to32 }; @@ -272,11 +292,20 @@ const static OperatorRegistrationInformation operatorRegistrationInformationTabl {REG_INFO( 7, Conv, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, {REG_INFO( 7, ConvTranspose, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, {REG_INFO( 7, AveragePool, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, +#if 0 + // TODO:DwayneR add ceil mode https://microsoft.visualstudio.com/OS/_workitems/edit/24674310 + {REG_INFO( 10, AveragePool, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, + {REG_INFO( 11, AveragePool, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, +#endif {REG_INFO( 7, GlobalAveragePool, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, {REG_INFO( 7, MaxPool, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, {REG_INFO( 8, MaxPool, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported, {}, std::nullopt, QueryMaxPool)}, {REG_INFO( 10, MaxPool, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported, {}, std::nullopt, QueryMaxPool)}, - +#if 0 + // TODO:DwayneR add ceil mode https://microsoft.visualstudio.com/OS/_workitems/edit/24674310 + {REG_INFO( 11, MaxPool, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported, {}, std::nullopt, QueryMaxPool)}, +#endif + {REG_INFO( 7, GlobalMaxPool, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, {REG_INFO( 7, LpPool, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, {REG_INFO( 7, GlobalLpPool, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, @@ -294,13 +323,23 @@ const static OperatorRegistrationInformation operatorRegistrationInformationTabl // Data Reorganization Layers {REG_INFO( 7, Split, typeNameListDefault, supportedTypeListNumericDefault, DmGraphSupport::Supported)}, + {REG_INFO( 11, Split, typeNameListDefault, supportedTypeListNumericDefault, DmGraphSupport::Supported)}, // Adds negative axis. {REG_INFO( 7, Transpose, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, {REG_INFO( 7, Concat, typeNameListDefault, supportedTypeListNumericDefault, DmGraphSupport::Supported)}, + {REG_INFO( 11, Concat, typeNameListDefault, supportedTypeListNumericDefault, DmGraphSupport::Supported)}, // Adds negative axis. {REG_INFO_VER( 7, Slice, typeNameListDefault, supportedTypeListNumericDefault, DmGraphSupport::Supported)}, - {REG_INFO_VER( 10, Slice, typeNameListDefault, supportedTypeListNumericDefault, DmGraphSupport::Supported, {1, 2, 3}, std::nullopt, QuerySlice)}, + {REG_INFO_VER( 10, Slice, typeNameListDefault, supportedTypeListNumericDefault, DmGraphSupport::Supported, {1, 2, 3}, std::nullopt, QuerySlice)}, + {REG_INFO_VER( 11, Slice, typeNameListDefault, supportedTypeListNumericDefault, DmGraphSupport::Supported, {1, 2, 3}, std::nullopt, QuerySlice)}, // Adds negative axes. {REG_INFO( 7, Pad, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, +#if 0 // TODO:DwayneR Pads and Value are inputs. https://github.com/onnx/onnx/blob/master/docs/Changelog.md#Pad-11 + {REG_INFO( 11, Pad, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, +#endif {REG_INFO( 7, SpaceToDepth, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, {REG_INFO( 7, DepthToSpace, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, +#if 0 + // TODO:Dwayner https://microsoft.visualstudio.com/OS/_workitems/edit/24672169 + {REG_INFO( 11, DepthToSpace, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, +#endif {REG_INFO( 7, Tile, typeNameListDefault, supportedTypeListNumericDefault, DmGraphSupport::Supported, {1})}, {REG_INFO( 8, Expand, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported, {1})}, {REG_INFO( 9, ConstantOfShape, typeNameListConstantOfShape, supportedTypeListConstantOfShape, DmGraphSupport::NotSupported, {0})}, @@ -312,8 +351,13 @@ const static OperatorRegistrationInformation operatorRegistrationInformationTabl {REG_INFO_ID( 7, Identity, typeNameListDefault, supportedTypeListAllScalars, DmGraphSupport::Supported)}, {REG_INFO_ID( 7, Flatten, typeNameListDefault, supportedTypeListAllScalars, DmGraphSupport::Supported)}, {REG_INFO_ID( 9, Flatten, typeNameListDefault, supportedTypeListAllScalars, DmGraphSupport::Supported)}, + //!!!TODO:::DwayneR check remaining 11's for other work besides negative axes. + //Also verify that negative axes are handled. + {REG_INFO_ID( 11, Flatten, typeNameListDefault, supportedTypeListAllScalars, DmGraphSupport::Supported)}, {REG_INFO_ID( 7, Squeeze, typeNameListDefault, supportedTypeListAllScalars, DmGraphSupport::Supported)}, + {REG_INFO_ID( 11, Squeeze, typeNameListDefault, supportedTypeListAllScalars, DmGraphSupport::Supported)}, {REG_INFO_ID( 7, Unsqueeze, typeNameListDefault, supportedTypeListAllScalars, DmGraphSupport::Supported)}, + {REG_INFO_ID( 11, Unsqueeze, typeNameListDefault, supportedTypeListAllScalars, DmGraphSupport::Supported)}, {REG_INFO_ID( 7, Reshape, typeNameListDefault, supportedTypeListAllScalars, DmGraphSupport::Supported, {1})}, // Elementwise @@ -326,6 +370,9 @@ const static OperatorRegistrationInformation operatorRegistrationInformationTabl {REG_INFO( 7, Ceil, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, {REG_INFO( 7, Floor, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, {REG_INFO( 7, Clip, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, +#if 0 // TODO:DwayneR https://microsoft.visualstudio.com/OS/_workitems/edit/24674103 + {REG_INFO( 11, Clip, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, +#endif {REG_INFO( 7, Add, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, {REG_INFO( 7, Sub, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, {REG_INFO( 7, Mul, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, @@ -350,7 +397,7 @@ const static OperatorRegistrationInformation operatorRegistrationInformationTabl {REG_INFO_MS( 1, QuantizeLinear, typeNameListQuantize, supportedTypeListQuantize, DmGraphSupport::Supported)}, {REG_INFO_MS( 1, DequantizeLinear, typeNameListQuantize, supportedTypeListQuantize, DmGraphSupport::Supported)}, {REG_INFO( 9, Sign, typeNameListDefault, supportedTypeListNumericDefault, DmGraphSupport::Supported)}, - {REG_INFO( 9, IsNan, typeNameListIsNan, supportedTypeListIsNan, DmGraphSupport::Supported)}, + {REG_INFO( 9, IsNan, typeNameListT1T2, supportedTypeListIsNan, DmGraphSupport::Supported)}, {REG_INFO( 9, Sinh, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, {REG_INFO( 9, Cosh, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, {REG_INFO( 9, Asinh, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, @@ -359,18 +406,31 @@ const static OperatorRegistrationInformation operatorRegistrationInformationTabl {REG_INFO( 9, Erf, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, {REG_INFO( 9, Where, typeNameListWhere, supportedTypeListWhere, DmGraphSupport::Supported)}, {REG_INFO( 7, ReduceSum, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, + {REG_INFO( 11, ReduceSum, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, {REG_INFO( 7, ReduceMean, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, + {REG_INFO( 11, ReduceMean, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, {REG_INFO( 7, ReduceProd, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, + {REG_INFO( 11, ReduceProd, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, {REG_INFO( 7, ReduceLogSum, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, + {REG_INFO( 11, ReduceLogSum, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, {REG_INFO( 7, ReduceLogSumExp, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, + {REG_INFO( 11, ReduceLogSumExp, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, {REG_INFO( 7, ReduceSumSquare, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, + {REG_INFO( 11, ReduceSumSquare, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, {REG_INFO( 7, ReduceL1, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, + {REG_INFO( 11, ReduceL1, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, {REG_INFO( 7, ReduceL2, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, + {REG_INFO( 11, ReduceL2, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, {REG_INFO( 7, ReduceMax, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, + {REG_INFO( 11, ReduceMax, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, {REG_INFO( 7, ReduceMin, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, + {REG_INFO( 11, ReduceMin, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, {REG_INFO( 7, ArgMax, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, + {REG_INFO( 11, ArgMax, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, {REG_INFO( 7, ArgMin, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, + {REG_INFO( 11, ArgMin, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, {REG_INFO( 7, Gemm, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, + {REG_INFO( 11, Gemm, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, {REG_INFO( 9, Gemm, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, {REG_INFO( 7, Neg, typeNameListDefault, supportedTypeListSigned, DmGraphSupport::Supported)}, {REG_INFO( 7, Greater, typeNameListLogicalComparison, supportedTypeListLogicalComparison7,DmGraphSupport::Supported)}, @@ -405,8 +465,11 @@ const static OperatorRegistrationInformation operatorRegistrationInformationTabl {REG_INFO( 7, Elu, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, {REG_INFO( 7, Selu, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, {REG_INFO( 7, Softmax, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, + {REG_INFO( 11, Softmax, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, {REG_INFO( 7, LogSoftmax, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, + {REG_INFO( 11, LogSoftmax, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, {REG_INFO( 7, Hardmax, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, + {REG_INFO( 11, Hardmax, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, {REG_INFO( 7, Softsign, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, {REG_INFO( 7, Softplus, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, {REG_INFO( 7, ParametricSoftplus, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, @@ -416,12 +479,19 @@ const static OperatorRegistrationInformation operatorRegistrationInformationTabl // Uncategorized {REG_INFO( 7, MatMul, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, {REG_INFO( 9, MatMul, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, - {REG_INFO( 7, Cast, typeNameListCast, supportedTypeListCast, DmGraphSupport::Supported)}, - {REG_INFO( 9, Cast, typeNameListCast, supportedTypeListCast, DmGraphSupport::Supported)}, + {REG_INFO( 7, Cast, typeNameListT1T2, supportedTypeListCast, DmGraphSupport::Supported)}, + {REG_INFO( 9, Cast, typeNameListT1T2, supportedTypeListCast, DmGraphSupport::Supported)}, {REG_INFO( 7, MemcpyFromHost, typeNameListDefault, supportedTypeListAll)}, {REG_INFO( 7, MemcpyToHost, typeNameListDefault, supportedTypeListAll)}, {REG_INFO( 7, TopK, typeNameListTopK, supportedTypeListTopK, DmGraphSupport::Supported)}, +#if 0 + // TODO:Dwayner https://microsoft.visualstudio.com/OS/_workitems/edit/24674287 + {REG_INFO( 10, TopK, typeNameListTopK, supportedTypeListTopK, DmGraphSupport::Supported)}, + // TODO:Dwayner https://microsoft.visualstudio.com/OS/_workitems/edit/24671996 + {REG_INFO( 11, TopK, typeNameListTopK, supportedTypeListTopK, DmGraphSupport::Supported)}, +#endif {REG_INFO( 9, OneHot, typeNameListOneHot, supportedTypeListOneHot, DmGraphSupport::Supported, {1})}, + {REG_INFO( 11, OneHot, typeNameListOneHot, supportedTypeListOneHot, DmGraphSupport::Supported, {1})}, // Fused operators {REG_INFO_MSDML(1, FusedConv, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, @@ -434,51 +504,58 @@ const static OperatorRegistrationInformation operatorRegistrationInformationTabl {REG_INFO_MSDML(1, FusedAdd, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, {REG_INFO_MSDML(1, FusedSum, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported, {}, 2)}, + {REG_INFO( 10, IsInf, typeNameListT1T2, supportedTypeListIsInf, DmGraphSupport::Supported)}, + {REG_INFO( 10, Mod, typeNameListDefault, supportedTypeListNumericDefault, DmGraphSupport::Supported)}, + {REG_INFO( 11, BitShift, typeNameListDefault, supportedTypeListInt8to32, DmGraphSupport::Supported)}, + {REG_INFO( 11, Round, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, + {REG_INFO( 11, ReverseSequence, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, // TODO::: data types + {REG_INFO( 11, CumSum, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, +// {REG_INFO( 11, Range, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported), {0,1,2}}, #if 0 {REG_INFO( 9, MaxUnpool, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported, {2})}, - {REG_INFO( 10, IsInf, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, - {REG_INFO( 10, Mod, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, - {REG_INFO( 11, Argmax, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, - {REG_INFO( 11, Argmin, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, - {REG_INFO( 11, AveragePool, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, - {REG_INFO( 11, BitShift, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, - {REG_INFO( 11, Clip, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, - {REG_INFO( 11, Compress, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, - {REG_INFO( 11, Concat, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, - {REG_INFO( 11, CumSum, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, - {REG_INFO( 11, DepthToSpace, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, - {REG_INFO( 11, Flatten, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, - {REG_INFO( 11, Gather, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, - {REG_INFO( 11, GatherElements, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, - {REG_INFO( 11, GatherND, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, - {REG_INFO( 11, Gemm, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, - {REG_INFO( 11, Hardmax, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, - {REG_INFO( 11, LogSoftmax, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, - {REG_INFO( 11, OneHot, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, - {REG_INFO( 11, Pad, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, - {REG_INFO( 11, Range, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, - {REG_INFO( 11, ReduceL1, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, - {REG_INFO( 11, ReduceL2, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, - {REG_INFO( 11, ReduceLogSum, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, - {REG_INFO( 11, ReduceLogSumExp, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, - {REG_INFO( 11, ReduceMax, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, - {REG_INFO( 11, ReduceMean, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, - {REG_INFO( 11, ReduceMin, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, - {REG_INFO( 11, ReduceProd, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, - {REG_INFO( 11, ReduceSum, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, - {REG_INFO( 11, ReduceSumSquare, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, - {REG_INFO( 11, Resize, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, - {REG_INFO( 11, ReverseSequence, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, - {REG_INFO( 11, Round, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, - {REG_INFO( 11, Scan, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, - {REG_INFO( 11, ScatterElements, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, - {REG_INFO( 11, ScatterND, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, - {REG_INFO( 11, Slice, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, - {REG_INFO( 11, Softmax, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, - {REG_INFO( 11, Split, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, - {REG_INFO( 11, Squeeze, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, - {REG_INFO( 11, TopK, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, - {REG_INFO( 11, Unsqueeze, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, + {REG_INFO( 11, Gather, typeNameListScatterGather, supportedTypeListScatterGather, DmGraphSupport::Supported)}, + -{REG_INFO( 11, GatherElements, typeNameListScatterGather, supportedTypeListScatterGather, DmGraphSupport::Supported)}, + -{REG_INFO( 11, GatherND, typeNameListScatterGatherND, supportedTypeListScatterGatherND, DmGraphSupport::Supported)}, + {REG_INFO( 11, Resize, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported, {1})}, + -{REG_INFO( 11, ScatterElements, typeNameListScatterGather, supportedTypeListScatterGather, DmGraphSupport::Supported)}, + -{REG_INFO( 11, ScatterND, typeNameListScatterGatherND, supportedTypeListScatterGatherND, DmGraphSupport::Supported)}, + + {REG_INFO( 11, QLinearConv, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, + // T1 : tensor(int8), tensor(uint8) + // Constrain input type to 8-bit integer tensor. + // T2 : tensor(int8), tensor(uint8) + // Constrain filter type to 8-bit integer tensor. + // T3 : tensor(int8), tensor(uint8) + // Constrain output type to 8-bit integer tensor. + // T4 : tensor(int32) + // Constrain bias type to 32-bit integer tensor. + {REG_INFO( 11, QLinearMatMul, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, + // T1 : tensor(int8), tensor(uint8) + // Constrain input a and its zero point data type to 8-bit integer tensor. + // T2 : tensor(int8), tensor(uint8) + // Constrain input b and its zero point data type to 8-bit integer tensor. + // T3 : tensor(int8), tensor(uint8) + // Constrain output y and its zero point data type to 8-bit integer tensor. + {REG_INFO( 11, DynamicQuantizeLinear, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, + //T1 : tensor(float) + //Constrain 'x' to float tensor. + //T2 : tensor(uint8) + + {REG_INFO( 11, MatMulInteger, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, + MatMulInteger + //T1 : tensor(int8), tensor(uint8) + //Constrain input A data type to 8-bit integer tensor. + //T2 : tensor(int8), tensor(uint8) + //Constrain input B data type to 8-bit integer tensor. + //T3 : tensor(int32) + //Constrain output Y data type as 32-bit integer tensor. + {REG_INFO( 11, ConvInteger, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, + // T1 : tensor(int8), tensor(uint8) + // Constrain input x and its zero point data type to 8-bit integer tensor. + // T2 : tensor(int8), tensor(uint8) + // Constrain input w and its zero point data type to 8-bit integer tensor. + // T3 : tensor(int32) + // Constrain output y data type to 32-bit integer tensor. #endif }; diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/TensorDesc.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/TensorDesc.cpp index 1afb7d83e6..4bf97d889c 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/TensorDesc.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/TensorDesc.cpp @@ -277,10 +277,14 @@ DML_TENSOR_DESC TensorDesc::GetDmlDesc() // requires coercion by the caller. void TensorDesc::ForceUnsignedDataType() { - static_assert(ApiTraits::EnumValueCount == 9, "New tensor data type. Update cases."); + static_assert(ApiTraits::EnumValueCount == 12, "New tensor data type. Update cases."); switch (m_bufferTensorDesc.DataType) { + case DML_TENSOR_DATA_TYPE_INT64: + m_bufferTensorDesc.DataType = DML_TENSOR_DATA_TYPE_UINT64; + break; + case DML_TENSOR_DATA_TYPE_INT32: m_bufferTensorDesc.DataType = DML_TENSOR_DATA_TYPE_UINT32; break; diff --git a/onnxruntime/core/providers/dml/OperatorAuthorHelper/Attributes.h b/onnxruntime/core/providers/dml/OperatorAuthorHelper/Attributes.h index dc7def086d..02caf8f28b 100644 --- a/onnxruntime/core/providers/dml/OperatorAuthorHelper/Attributes.h +++ b/onnxruntime/core/providers/dml/OperatorAuthorHelper/Attributes.h @@ -22,14 +22,18 @@ namespace AttrName static constexpr const char* CeilMode = "ceil_mode"; static constexpr const char* Clip = "clip"; static constexpr const char* CountIncludePad = "count_include_pad"; + static constexpr const char* DetectPositive = "detect_negative"; + static constexpr const char* DetectNegative = "detect_negative "; static constexpr const char* Dilations = "dilations"; static constexpr const char* Direction = "direction"; static constexpr const char* Dtype = "dtype"; static constexpr const char* Ends = "ends"; static constexpr const char* Epsilon = "epsilon"; static constexpr const char* Exponent = "exponent"; + static constexpr const char* Fmod = "fmod"; static constexpr const char* Gamma = "gamma"; static constexpr const char* Group = "group"; + static constexpr const char* Exclusive = "exclusive"; static constexpr const char* HeightScale = "height_scale"; static constexpr const char* HiddenSize = "hidden_size"; static constexpr const char* High = "high"; @@ -50,6 +54,7 @@ namespace AttrName static constexpr const char* OutputPadding = "output_padding"; static constexpr const char* Pads = "pads"; static constexpr const char* PooledShape = "pooled_shape"; + static constexpr const char* Reverse = "reverse"; static constexpr const char* SampleSize = "sample_size"; static constexpr const char* Scale = "scale"; static constexpr const char* Scales = "scales"; @@ -64,6 +69,7 @@ namespace AttrName static constexpr const char* StorageOrder = "storage_order"; static constexpr const char* Strides = "strides"; static constexpr const char* Tiles = "tiles"; + static constexpr const char* TimeAxis = "time_axis"; static constexpr const char* To = "to"; static constexpr const char* TransA = "transA"; static constexpr const char* TransB = "transB"; diff --git a/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.h b/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.h index aa8486117f..f61f63b69a 100644 --- a/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.h +++ b/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.h @@ -528,6 +528,7 @@ public: { ends.push_back(gsl::narrow_cast(endsData[i])); } + uint32_t inputCount = operatorInfo.GetInputCount(); if (inputCount > 3) { @@ -1193,6 +1194,7 @@ using ShapeInferenceHelper_Transpose = TransposeHelper; using ShapeInferenceHelper_Concat = ConcatHelper; using ShapeInferenceHelper_Slice7 = SliceHelper; using ShapeInferenceHelper_Slice10 = Slice10Helper; +using ShapeInferenceHelper_Slice11 = Slice10Helper; // 11 and 10 are identical. using ShapeInferenceHelper_Pad = PaddingHelper; using ShapeInferenceHelper_SpaceToDepth = SpaceToDepthHelper; using ShapeInferenceHelper_DepthToSpace = DepthToSpaceHelper; @@ -1250,6 +1252,10 @@ using ShapeInferenceHelper_Asinh = GetBroadcastedOutputShapeHelper; using ShapeInferenceHelper_Acosh = GetBroadcastedOutputShapeHelper; using ShapeInferenceHelper_Atanh = GetBroadcastedOutputShapeHelper; using ShapeInferenceHelper_Where = GetBroadcastedOutputShapeHelper; +using ShapeInferenceHelper_IsInf = GetBroadcastedOutputShapeHelper; +using ShapeInferenceHelper_Mod = GetBroadcastedOutputShapeHelper; +using ShapeInferenceHelper_BitShift= GetBroadcastedOutputShapeHelper; +using ShapeInferenceHelper_Round = GetBroadcastedOutputShapeHelper; using ShapeInferenceHelper_ReduceSum = ReduceHelper; using ShapeInferenceHelper_ReduceMean = ReduceHelper; @@ -1302,6 +1308,10 @@ using ShapeInferenceHelper_RandomNormal = RandomNormalHelper; using ShapeInferenceHelper_RandomNormalLike = GetOutputShapeAsInputShapeHelper; using ShapeInferenceHelper_Multinomial = MultinomialHelper; +using ShapeInferenceHelper_ReverseSequence = GetOutputShapeAsInputShapeHelper; +using ShapeInferenceHelper_CumSum = GetOutputShapeAsInputShapeHelper; +// TODO::: using ShapeInferenceHelper_ShapeInferenceHelper_Range = ... + using ShapeInferenceHelper_FusedConv = ConvHelper; using ShapeInferenceHelper_FusedConvTranspose = ConvTransposeHelper; using ShapeInferenceHelper_FusedInstanceNormalization = GetOutputShapeAsInputShapeHelper; diff --git a/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorRegistration.h b/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorRegistration.h index 7fff38af20..8e55c78497 100644 --- a/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorRegistration.h +++ b/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorRegistration.h @@ -189,8 +189,8 @@ namespace OperatorHelper namespace OnnxOperatorSet11 { - static const int sc_sinceVer_Argmax = 11; - static const int sc_sinceVer_Argmin = 11; + static const int sc_sinceVer_ArgMax = 11; + static const int sc_sinceVer_ArgMin = 11; static const int sc_sinceVer_AveragePool = 11; static const int sc_sinceVer_BitShift = 11; static const int sc_sinceVer_Clip = 11; @@ -206,6 +206,7 @@ namespace OperatorHelper static const int sc_sinceVer_Gemm = 11; static const int sc_sinceVer_Hardmax = 11; static const int sc_sinceVer_LogSoftmax = 11; + static const int sc_sinceVer_MaxPool = 11; static const int sc_sinceVer_OneHot = 11; static const int sc_sinceVer_Pad = 11; static const int sc_sinceVer_Range = 11; From 551d28be9a162422f41487a76bc653b2e60b9b4a Mon Sep 17 00:00:00 2001 From: Dwayne Robinson Date: Fri, 13 Mar 2020 19:06:00 -0700 Subject: [PATCH 02/12] Update. --- .../DmlExecutionProvider/src/Operators/OperatorRegistration.cpp | 2 +- .../providers/dml/OperatorAuthorHelper/OperatorRegistration.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp index 077cc38c3d..ee096592ab 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp @@ -508,7 +508,7 @@ const static OperatorRegistrationInformation operatorRegistrationInformationTabl {REG_INFO( 10, Mod, typeNameListDefault, supportedTypeListNumericDefault, DmGraphSupport::Supported)}, {REG_INFO( 11, BitShift, typeNameListDefault, supportedTypeListInt8to32, DmGraphSupport::Supported)}, {REG_INFO( 11, Round, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, - {REG_INFO( 11, ReverseSequence, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, // TODO::: data types + {REG_INFO( 10, ReverseSequence, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, // TODO::: data types, why not registered?? {REG_INFO( 11, CumSum, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, // {REG_INFO( 11, Range, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported), {0,1,2}}, #if 0 diff --git a/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorRegistration.h b/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorRegistration.h index 8e55c78497..9d8cb743ea 100644 --- a/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorRegistration.h +++ b/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorRegistration.h @@ -185,6 +185,7 @@ namespace OperatorHelper static const int sc_sinceVer_DropOut = 10; static const int sc_sinceVer_RoiAlign = 10; static const int sc_sinceVer_TopK = 10; + static const int sc_sinceVer_ReverseSequence = 10; } // namespace OnnxOperatorSet10 namespace OnnxOperatorSet11 @@ -221,7 +222,6 @@ namespace OperatorHelper static const int sc_sinceVer_ReduceSum = 11; static const int sc_sinceVer_ReduceSumSquare = 11; static const int sc_sinceVer_Resize = 11; - static const int sc_sinceVer_ReverseSequence = 11; static const int sc_sinceVer_Round = 11; static const int sc_sinceVer_Scan = 11; static const int sc_sinceVer_ScatterElements = 11; From f6211217d8102998599a56847bac7ef30b101ecf Mon Sep 17 00:00:00 2001 From: Dwayne Robinson Date: Mon, 16 Mar 2020 21:26:36 -0700 Subject: [PATCH 03/12] Fixes --- .../src/GraphPartitioner.cpp | 1 - .../src/Operators/DmlOperatorConvInteger.cpp | 56 ++--------- .../src/Operators/DmlOperatorCumSum.cpp | 28 ++++-- .../DmlOperatorDynamicQuantizeLinear.cpp | 58 ++---------- .../src/Operators/DmlOperatorElementWise.cpp | 2 +- .../src/Operators/DmlOperatorGemm.cpp | 21 +++-- .../Operators/DmlOperatorMatMulInteger.cpp | 56 ++--------- .../src/Operators/DmlOperatorQLinearConv.cpp | 56 ++--------- .../Operators/DmlOperatorQLinearMatMul.cpp | 56 ++--------- .../src/Operators/DmlOperatorRange.cpp | 92 +++++++++---------- .../Operators/DmlOperatorReverseSequence.cpp | 19 ++-- .../src/Operators/OperatorRegistration.cpp | 11 ++- .../dml/OperatorAuthorHelper/Attributes.h | 5 +- .../OperatorAuthorHelper/OperatorHelper.cpp | 12 +-- .../dml/OperatorAuthorHelper/OperatorHelper.h | 36 +++++++- 15 files changed, 175 insertions(+), 334 deletions(-) diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/GraphPartitioner.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/GraphPartitioner.cpp index e6ffb31d00..90033bcd1b 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/GraphPartitioner.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/GraphPartitioner.cpp @@ -301,7 +301,6 @@ namespace Dml const onnxruntime::KernelRegistry& registry, uint32_t supportedDeviceDataTypeMask, // Each bit corresponds to each DML_TENSOR_DATA_TYPE. const InternalRegistrationInfoMap& internalRegInfoMap, - bool allow64BitInputThroughStrides, _In_opt_ const std::unordered_map* nodeNameToPartitionMap ) diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorConvInteger.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorConvInteger.cpp index 45f4204abd..e8bd374d3b 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorConvInteger.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorConvInteger.cpp @@ -1,78 +1,36 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -//TODO::: - #include "precomp.h" namespace Dml { -class DmlOperatorConvInteger : public DmlOperator, OneHotHelper// TODO::: +class DmlOperatorConvInteger : public DmlOperator { public: using Self = DmlOperatorConvInteger; DmlOperatorConvInteger(const MLOperatorKernelCreationContext& kernelCreationContext) - : DmlOperator(kernelCreationContext), - OneHotHelper(kernelCreationContext, kernelCreationContext.GetTensorShapeDescription()) + : DmlOperator(kernelCreationContext) { - ML_CHECK_VALID_ARGUMENT(kernelCreationContext.GetInputCount() == 3); +#if 0 // TODO:NickFe - https://github.com/onnx/onnx/blob/master/docs/Operators.md#convinteger + ML_CHECK_VALID_ARGUMENT(kernelCreationContext.GetInputCount() >= 2 && kernelCreationContext.GetInputCount() <= 4); ML_CHECK_VALID_ARGUMENT(kernelCreationContext.GetOutputCount() == 1); - std::vector> inputIndices = { 0, 2 }; // The second tensor ('depth') is not bound, just 'indices' and 'values'. - std::vector> outputIndices = { 0 }; DmlOperator::Initialize(kernelCreationContext, inputIndices, outputIndices); - - // Unsqueeze the indices tensor by inserting a flat dimension of size 1, - // and compute the output tensor by expanding along the active axis. - // This way they are both size-compatible and directly consumable by DirectML. - std::vector indicesDimensions; - indicesDimensions = kernelCreationContext.GetTensorShapeDescription().GetInputTensorShape(0); - indicesDimensions.insert(indicesDimensions.begin() + m_absoluteAxis, 1u); - // Update the tensor descriptions with new sizes. - m_inputTensorDescs[0] = - TensorDesc( - m_inputTensorDescs[0].GetMlOperatorDataType(), - gsl::make_span(indicesDimensions), - gsl::make_span(indicesDimensions), - TensorAxis::DoNotCoerce, - TensorAxis::W, - TensorAxis::RightAligned, - NchwDimensionCount, // minDimensionCount - 0 - ); - - m_outputTensorDescs[0] = - TensorDesc( - m_outputTensorDescs[0].GetMlOperatorDataType(), - gsl::make_span(m_outputDimensions), - gsl::make_span(m_outputDimensions), - TensorAxis::DoNotCoerce, - TensorAxis::W, - TensorAxis::RightAligned, - NchwDimensionCount, // minDimensionCount - 0 - ); - - // Adjust the axis so it's in DML's terms rather than the original ONNX indexing. - uint32_t dmlAxis = GetDmlAdjustedAxis( - m_absoluteAxis, - gsl::narrow_cast(indicesDimensions.size()), - m_inputTensorDescs.front().GetDimensionCount() - ); - std::vector inputDescs = GetDmlInputDescs(); std::vector outputDescs = GetDmlOutputDescs(); - DML_ONE_HOT_OPERATOR_DESC operatorDesc = {}; + DML_PLACEHOLDER_OPERATOR_DESC operatorDesc = {}; operatorDesc.IndicesTensor = &inputDescs[0]; operatorDesc.ValuesTensor = &inputDescs[1]; operatorDesc.OutputTensor = outputDescs.data(); operatorDesc.Axis = dmlAxis; - DML_OPERATOR_DESC opDesc = { DML_OPERATOR_ONE_HOT, &operatorDesc }; + DML_OPERATOR_DESC opDesc = { DML_OPERATOR_PLACEHOLDER, &operatorDesc }; SetDmlOperatorDesc(opDesc, kernelCreationContext); +#endif } }; diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorCumSum.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorCumSum.cpp index 4a8e438eb1..8eaa00f567 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorCumSum.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorCumSum.cpp @@ -6,25 +6,39 @@ namespace Dml { -class DmlOperatorCumSum : public DmlOperator, OneHotHelper +class DmlOperatorCumSum : public DmlOperator { public: using Self = DmlOperatorCumSum; DmlOperatorCumSum(const MLOperatorKernelCreationContext& kernelCreationContext) - : DmlOperator(kernelCreationContext), - OneHotHelper(kernelCreationContext, kernelCreationContext.GetTensorShapeDescription()) + : DmlOperator(kernelCreationContext) { - ML_CHECK_VALID_ARGUMENT(kernelCreationContext.GetInputCount() == 1); + ML_CHECK_VALID_ARGUMENT(kernelCreationContext.GetInputCount() >= 1); // input, axis ML_CHECK_VALID_ARGUMENT(kernelCreationContext.GetOutputCount() == 1); - DmlOperator::Initialize(kernelCreationContext); + + std::vector> inputIndices = { 0 }; // The second tensor ('axis') is not bound, just 'input'. + std::vector> outputIndices = { 0 }; + DmlOperator::Initialize(kernelCreationContext, inputIndices, outputIndices); // Adjust the axis so it's in DML's terms rather than the original ONNX indexing. int32_t hasExclusiveSum = kernelCreationContext.GetOptionalAttribute(AttrName::Exclusive, 0); int32_t isReversed = kernelCreationContext.GetOptionalAttribute(AttrName::Reverse, 0); - int32_t onnxAxis = kernelCreationContext.GetOptionalAttribute(AttrName::Axis, -1); + + // Axis defaults to 0 if tensor not present. + int32_t onnxAxis = 0; + if (kernelCreationContext.IsInputValid(1)) + { + MLOperatorTensor axisTensor = kernelCreationContext.GetConstantInputTensor(1); + const uint32_t axisElementCount = ComputeElementCountFromDimensions(axisTensor.GetShape()); + ML_CHECK_VALID_ARGUMENT(axisTensor.IsCpuData(), "CumSum's 'axis' tensor must be a CPU Tensor."); + ML_CHECK_VALID_ARGUMENT(axisElementCount == 1, "CumSum's 'axis' tensor must have one element."); + + const void* tensorData = axisTensor.GetByteData(); + onnxAxis = static_cast(ReadAsInt64(axisTensor.GetTensorDataType(), tensorData)); + } uint32_t dmlAxis = GetDmlAdjustedAxis(onnxAxis, kernelCreationContext, m_inputTensorDescs.front().GetDimensionCount()); - + std::vector inputDescs = GetDmlInputDescs(); std::vector outputDescs = GetDmlOutputDescs(); diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorDynamicQuantizeLinear.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorDynamicQuantizeLinear.cpp index 0f4487de52..b727817e98 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorDynamicQuantizeLinear.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorDynamicQuantizeLinear.cpp @@ -2,75 +2,35 @@ // Licensed under the MIT License. #include "precomp.h" -//TODO::: + namespace Dml { -class DmlOperatorDynamicQuantizeLinear : public DmlOperator, OneHotHelper +class DmlOperatorDynamicQuantizeLinear : public DmlOperator { public: using Self = DmlOperatorDynamicQuantizeLinear; DmlOperatorDynamicQuantizeLinear(const MLOperatorKernelCreationContext& kernelCreationContext) - : DmlOperator(kernelCreationContext), - OneHotHelper(kernelCreationContext, kernelCreationContext.GetTensorShapeDescription()) + : DmlOperator(kernelCreationContext) { - ML_CHECK_VALID_ARGUMENT(kernelCreationContext.GetInputCount() == 3); - ML_CHECK_VALID_ARGUMENT(kernelCreationContext.GetOutputCount() == 1); - std::vector> inputIndices = { 0, 2 }; // The second tensor ('depth') is not bound, just 'indices' and 'values'. - std::vector> outputIndices = { 0 }; +#if 0 // TODO:NickFe - https://github.com/onnx/onnx/blob/master/docs/Operators.md#dynamicquantizelinear + ML_CHECK_VALID_ARGUMENT(kernelCreationContext.GetInputCount() == 1); + ML_CHECK_VALID_ARGUMENT(kernelCreationContext.GetOutputCount() == 3); DmlOperator::Initialize(kernelCreationContext, inputIndices, outputIndices); - // Unsqueeze the indices tensor by inserting a flat dimension of size 1, - // and compute the output tensor by expanding along the active axis. - // This way they are both size-compatible and directly consumable by DirectML. - std::vector indicesDimensions; - indicesDimensions = kernelCreationContext.GetTensorShapeDescription().GetInputTensorShape(0); - indicesDimensions.insert(indicesDimensions.begin() + m_absoluteAxis, 1u); - - // Update the tensor descriptions with new sizes. - m_inputTensorDescs[0] = - TensorDesc( - m_inputTensorDescs[0].GetMlOperatorDataType(), - gsl::make_span(indicesDimensions), - gsl::make_span(indicesDimensions), - TensorAxis::DoNotCoerce, - TensorAxis::W, - TensorAxis::RightAligned, - NchwDimensionCount, // minDimensionCount - 0 - ); - - m_outputTensorDescs[0] = - TensorDesc( - m_outputTensorDescs[0].GetMlOperatorDataType(), - gsl::make_span(m_outputDimensions), - gsl::make_span(m_outputDimensions), - TensorAxis::DoNotCoerce, - TensorAxis::W, - TensorAxis::RightAligned, - NchwDimensionCount, // minDimensionCount - 0 - ); - - // Adjust the axis so it's in DML's terms rather than the original ONNX indexing. - uint32_t dmlAxis = GetDmlAdjustedAxis( - m_absoluteAxis, - gsl::narrow_cast(indicesDimensions.size()), - m_inputTensorDescs.front().GetDimensionCount() - ); - std::vector inputDescs = GetDmlInputDescs(); std::vector outputDescs = GetDmlOutputDescs(); - DML_ONE_HOT_OPERATOR_DESC operatorDesc = {}; + DML_PLACEHOLDER_OPERATOR_DESC operatorDesc = {}; operatorDesc.IndicesTensor = &inputDescs[0]; operatorDesc.ValuesTensor = &inputDescs[1]; operatorDesc.OutputTensor = outputDescs.data(); operatorDesc.Axis = dmlAxis; - DML_OPERATOR_DESC opDesc = { DML_OPERATOR_ONE_HOT, &operatorDesc }; + DML_OPERATOR_DESC opDesc = { DML_OPERATOR_PLACEHOLDER, &operatorDesc }; SetDmlOperatorDesc(opDesc, kernelCreationContext); +#endif } }; diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorElementWise.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorElementWise.cpp index 9226816503..d68c270ad3 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorElementWise.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorElementWise.cpp @@ -612,7 +612,7 @@ public: : detectPositive ? DML_IS_INFINITY_MODE_POSITIVE : DML_IS_INFINITY_MODE_NEGATIVE; - SetDmlOperatorDesc({ DML_OPERATOR_ELEMENT_WISE_CLIP, &opDesc}, kernelInfo); + SetDmlOperatorDesc({ DML_OPERATOR_ELEMENT_WISE_IS_INFINITY, &opDesc}, kernelInfo); } }; diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorGemm.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorGemm.cpp index 5fcc8a89fe..a559828d63 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorGemm.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorGemm.cpp @@ -13,19 +13,24 @@ public: : DmlOperator(kernelInfo), GemmHelper(kernelInfo, kernelInfo.GetTensorShapeDescription()) { - ML_CHECK_VALID_ARGUMENT(kernelInfo.GetInputCount() >= 3); + ML_CHECK_VALID_ARGUMENT(kernelInfo.GetInputCount() >= 2); ML_CHECK_VALID_ARGUMENT(kernelInfo.GetOutputCount() == 1); DmlOperator::Initialize(kernelInfo); + bool containsBiasTensor = kernelInfo.IsInputValid(2); + // Broadcast C tensor to the shape of the output tensor. - m_inputTensorDescs[2] = CreateTensorDescFromInput( - kernelInfo, - 2, - TensorAxis::DoNotCoerce, - TensorAxis::W, - TensorAxis::RightAligned, - kernelInfo.GetTensorShapeDescription().GetOutputTensorShape(0) + if (containsBiasTensor) + { + m_inputTensorDescs[2] = CreateTensorDescFromInput( + kernelInfo, + 2, + TensorAxis::DoNotCoerce, + TensorAxis::W, + TensorAxis::RightAligned, + kernelInfo.GetTensorShapeDescription().GetOutputTensorShape(0) ); + } std::vector inputDescs = GetDmlInputDescs(); std::vector outputDescs = GetDmlOutputDescs(); diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorMatMulInteger.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorMatMulInteger.cpp index bf9e62d3bb..dcb7586f09 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorMatMulInteger.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorMatMulInteger.cpp @@ -1,78 +1,36 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. - -//TODO::: #include "precomp.h" namespace Dml { -class DmlOperatorMatMulInteger : public DmlOperator, OneHotHelper +class DmlOperatorMatMulInteger : public DmlOperator { public: using Self = DmlOperatorMatMulInteger; DmlOperatorMatMulInteger(const MLOperatorKernelCreationContext& kernelCreationContext) - : DmlOperator(kernelCreationContext), - OneHotHelper(kernelCreationContext, kernelCreationContext.GetTensorShapeDescription()) + : DmlOperator(kernelCreationContext) { - ML_CHECK_VALID_ARGUMENT(kernelCreationContext.GetInputCount() == 3); +#if 0 // TODO:NickFe - https://github.com/onnx/onnx/blob/master/docs/Operators.md#MatMulInteger + ML_CHECK_VALID_ARGUMENT(kernelCreationContext.GetInputCount() >= 2 || kernelCreationContext.GetInputCount() <= 4); ML_CHECK_VALID_ARGUMENT(kernelCreationContext.GetOutputCount() == 1); - std::vector> inputIndices = { 0, 2 }; // The second tensor ('depth') is not bound, just 'indices' and 'values'. - std::vector> outputIndices = { 0 }; DmlOperator::Initialize(kernelCreationContext, inputIndices, outputIndices); - - // Unsqueeze the indices tensor by inserting a flat dimension of size 1, - // and compute the output tensor by expanding along the active axis. - // This way they are both size-compatible and directly consumable by DirectML. - std::vector indicesDimensions; - indicesDimensions = kernelCreationContext.GetTensorShapeDescription().GetInputTensorShape(0); - indicesDimensions.insert(indicesDimensions.begin() + m_absoluteAxis, 1u); - // Update the tensor descriptions with new sizes. - m_inputTensorDescs[0] = - TensorDesc( - m_inputTensorDescs[0].GetMlOperatorDataType(), - gsl::make_span(indicesDimensions), - gsl::make_span(indicesDimensions), - TensorAxis::DoNotCoerce, - TensorAxis::W, - TensorAxis::RightAligned, - NchwDimensionCount, // minDimensionCount - 0 - ); - - m_outputTensorDescs[0] = - TensorDesc( - m_outputTensorDescs[0].GetMlOperatorDataType(), - gsl::make_span(m_outputDimensions), - gsl::make_span(m_outputDimensions), - TensorAxis::DoNotCoerce, - TensorAxis::W, - TensorAxis::RightAligned, - NchwDimensionCount, // minDimensionCount - 0 - ); - - // Adjust the axis so it's in DML's terms rather than the original ONNX indexing. - uint32_t dmlAxis = GetDmlAdjustedAxis( - m_absoluteAxis, - gsl::narrow_cast(indicesDimensions.size()), - m_inputTensorDescs.front().GetDimensionCount() - ); - std::vector inputDescs = GetDmlInputDescs(); std::vector outputDescs = GetDmlOutputDescs(); - DML_ONE_HOT_OPERATOR_DESC operatorDesc = {}; + DML_PLACEHOLDER_OPERATOR_DESC operatorDesc = {}; operatorDesc.IndicesTensor = &inputDescs[0]; operatorDesc.ValuesTensor = &inputDescs[1]; operatorDesc.OutputTensor = outputDescs.data(); operatorDesc.Axis = dmlAxis; - DML_OPERATOR_DESC opDesc = { DML_OPERATOR_ONE_HOT, &operatorDesc }; + DML_OPERATOR_DESC opDesc = { DML_OPERATOR_PLACEHOLDER, &operatorDesc }; SetDmlOperatorDesc(opDesc, kernelCreationContext); +#endif } }; diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorQLinearConv.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorQLinearConv.cpp index 211d34f051..c2cd77d32d 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorQLinearConv.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorQLinearConv.cpp @@ -1,78 +1,36 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -// TODO::: - #include "precomp.h" namespace Dml { -class DmlOperatorQLinearConv : public DmlOperator, OneHotHelper +class DmlOperatorQLinearConv : public DmlOperator { public: using Self = DmlOperatorQLinearConv; DmlOperatorQLinearConv(const MLOperatorKernelCreationContext& kernelCreationContext) - : DmlOperator(kernelCreationContext), - OneHotHelper(kernelCreationContext, kernelCreationContext.GetTensorShapeDescription()) + : DmlOperator(kernelCreationContext) { - ML_CHECK_VALID_ARGUMENT(kernelCreationContext.GetInputCount() == 3); +#if 0 // TODO:NickFe - https://github.com/onnx/onnx/blob/master/docs/Operators.md#qlinearconv + ML_CHECK_VALID_ARGUMENT(kernelCreationContext.GetInputCount() >= 8 && kernelCreationContext.GetInputCount() <= 9); ML_CHECK_VALID_ARGUMENT(kernelCreationContext.GetOutputCount() == 1); - std::vector> inputIndices = { 0, 2 }; // The second tensor ('depth') is not bound, just 'indices' and 'values'. - std::vector> outputIndices = { 0 }; DmlOperator::Initialize(kernelCreationContext, inputIndices, outputIndices); - - // Unsqueeze the indices tensor by inserting a flat dimension of size 1, - // and compute the output tensor by expanding along the active axis. - // This way they are both size-compatible and directly consumable by DirectML. - std::vector indicesDimensions; - indicesDimensions = kernelCreationContext.GetTensorShapeDescription().GetInputTensorShape(0); - indicesDimensions.insert(indicesDimensions.begin() + m_absoluteAxis, 1u); - // Update the tensor descriptions with new sizes. - m_inputTensorDescs[0] = - TensorDesc( - m_inputTensorDescs[0].GetMlOperatorDataType(), - gsl::make_span(indicesDimensions), - gsl::make_span(indicesDimensions), - TensorAxis::DoNotCoerce, - TensorAxis::W, - TensorAxis::RightAligned, - NchwDimensionCount, // minDimensionCount - 0 - ); - - m_outputTensorDescs[0] = - TensorDesc( - m_outputTensorDescs[0].GetMlOperatorDataType(), - gsl::make_span(m_outputDimensions), - gsl::make_span(m_outputDimensions), - TensorAxis::DoNotCoerce, - TensorAxis::W, - TensorAxis::RightAligned, - NchwDimensionCount, // minDimensionCount - 0 - ); - - // Adjust the axis so it's in DML's terms rather than the original ONNX indexing. - uint32_t dmlAxis = GetDmlAdjustedAxis( - m_absoluteAxis, - gsl::narrow_cast(indicesDimensions.size()), - m_inputTensorDescs.front().GetDimensionCount() - ); - std::vector inputDescs = GetDmlInputDescs(); std::vector outputDescs = GetDmlOutputDescs(); - DML_ONE_HOT_OPERATOR_DESC operatorDesc = {}; + DML_PLACEHOLDER_OPERATOR_DESC operatorDesc = {}; operatorDesc.IndicesTensor = &inputDescs[0]; operatorDesc.ValuesTensor = &inputDescs[1]; operatorDesc.OutputTensor = outputDescs.data(); operatorDesc.Axis = dmlAxis; - DML_OPERATOR_DESC opDesc = { DML_OPERATOR_ONE_HOT, &operatorDesc }; + DML_OPERATOR_DESC opDesc = { DML_OPERATOR_PLACEHOLDER, &operatorDesc }; SetDmlOperatorDesc(opDesc, kernelCreationContext); +#endif } }; diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorQLinearMatMul.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorQLinearMatMul.cpp index 2d46a4cb92..aa0e34ec6d 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorQLinearMatMul.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorQLinearMatMul.cpp @@ -1,78 +1,36 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -//TODO::: - #include "precomp.h" namespace Dml { -class DmlOperatorQLinearMatMul : public DmlOperator, OneHotHelper +class DmlOperatorQLinearMatMul : public DmlOperator { public: using Self = DmlOperatorQLinearMatMul; DmlOperatorQLinearMatMul(const MLOperatorKernelCreationContext& kernelCreationContext) - : DmlOperator(kernelCreationContext), - OneHotHelper(kernelCreationContext, kernelCreationContext.GetTensorShapeDescription()) + : DmlOperator(kernelCreationContext) { - ML_CHECK_VALID_ARGUMENT(kernelCreationContext.GetInputCount() == 3); +#if 0 // TODO:NickFe - https://github.com/onnx/onnx/blob/master/docs/Operators.md#qlinearmatmul + ML_CHECK_VALID_ARGUMENT(kernelCreationContext.GetInputCount() == 8); ML_CHECK_VALID_ARGUMENT(kernelCreationContext.GetOutputCount() == 1); - std::vector> inputIndices = { 0, 2 }; // The second tensor ('depth') is not bound, just 'indices' and 'values'. - std::vector> outputIndices = { 0 }; DmlOperator::Initialize(kernelCreationContext, inputIndices, outputIndices); - - // Unsqueeze the indices tensor by inserting a flat dimension of size 1, - // and compute the output tensor by expanding along the active axis. - // This way they are both size-compatible and directly consumable by DirectML. - std::vector indicesDimensions; - indicesDimensions = kernelCreationContext.GetTensorShapeDescription().GetInputTensorShape(0); - indicesDimensions.insert(indicesDimensions.begin() + m_absoluteAxis, 1u); - // Update the tensor descriptions with new sizes. - m_inputTensorDescs[0] = - TensorDesc( - m_inputTensorDescs[0].GetMlOperatorDataType(), - gsl::make_span(indicesDimensions), - gsl::make_span(indicesDimensions), - TensorAxis::DoNotCoerce, - TensorAxis::W, - TensorAxis::RightAligned, - NchwDimensionCount, // minDimensionCount - 0 - ); - - m_outputTensorDescs[0] = - TensorDesc( - m_outputTensorDescs[0].GetMlOperatorDataType(), - gsl::make_span(m_outputDimensions), - gsl::make_span(m_outputDimensions), - TensorAxis::DoNotCoerce, - TensorAxis::W, - TensorAxis::RightAligned, - NchwDimensionCount, // minDimensionCount - 0 - ); - - // Adjust the axis so it's in DML's terms rather than the original ONNX indexing. - uint32_t dmlAxis = GetDmlAdjustedAxis( - m_absoluteAxis, - gsl::narrow_cast(indicesDimensions.size()), - m_inputTensorDescs.front().GetDimensionCount() - ); - std::vector inputDescs = GetDmlInputDescs(); std::vector outputDescs = GetDmlOutputDescs(); - DML_ONE_HOT_OPERATOR_DESC operatorDesc = {}; + DML_PLACEHOLDER_OPERATOR_DESC operatorDesc = {}; operatorDesc.IndicesTensor = &inputDescs[0]; operatorDesc.ValuesTensor = &inputDescs[1]; operatorDesc.OutputTensor = outputDescs.data(); operatorDesc.Axis = dmlAxis; - DML_OPERATOR_DESC opDesc = { DML_OPERATOR_ONE_HOT, &operatorDesc }; + DML_OPERATOR_DESC opDesc = { DML_OPERATOR_PLACEHOLDER, &operatorDesc }; SetDmlOperatorDesc(opDesc, kernelCreationContext); +#endif } }; diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorRange.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorRange.cpp index e9048056c3..bd0f3936e4 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorRange.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorRange.cpp @@ -9,70 +9,70 @@ namespace Dml { -class DmlOperatorRange : public DmlOperator, OneHotHelper +class DmlOperatorRange : public DmlOperator, RangeHelper { public: using Self = DmlOperatorRange; DmlOperatorRange(const MLOperatorKernelCreationContext& kernelCreationContext) : DmlOperator(kernelCreationContext), - OneHotHelper(kernelCreationContext, kernelCreationContext.GetTensorShapeDescription()) + RangeHelper(kernelCreationContext, kernelCreationContext.GetTensorShapeDescription()) { ML_CHECK_VALID_ARGUMENT(kernelCreationContext.GetInputCount() == 3); ML_CHECK_VALID_ARGUMENT(kernelCreationContext.GetOutputCount() == 1); - std::vector> inputIndices = { 0, 2 }; // The second tensor ('depth') is not bound, just 'indices' and 'values'. + std::vector> inputIndices = {}; // All tensors are CPU bound. std::vector> outputIndices = { 0 }; DmlOperator::Initialize(kernelCreationContext, inputIndices, outputIndices); - // Unsqueeze the indices tensor by inserting a flat dimension of size 1, - // and compute the output tensor by expanding along the active axis. - // This way they are both size-compatible and directly consumable by DirectML. - std::vector indicesDimensions; - indicesDimensions = kernelCreationContext.GetTensorShapeDescription().GetInputTensorShape(0); - indicesDimensions.insert(indicesDimensions.begin() + m_absoluteAxis, 1u); - - // Update the tensor descriptions with new sizes. - m_inputTensorDescs[0] = - TensorDesc( - m_inputTensorDescs[0].GetMlOperatorDataType(), - gsl::make_span(indicesDimensions), - gsl::make_span(indicesDimensions), - TensorAxis::DoNotCoerce, - TensorAxis::W, - TensorAxis::RightAligned, - NchwDimensionCount, // minDimensionCount - 0 - ); - - m_outputTensorDescs[0] = - TensorDesc( - m_outputTensorDescs[0].GetMlOperatorDataType(), - gsl::make_span(m_outputDimensions), - gsl::make_span(m_outputDimensions), - TensorAxis::DoNotCoerce, - TensorAxis::W, - TensorAxis::RightAligned, - NchwDimensionCount, // minDimensionCount - 0 - ); - - // Adjust the axis so it's in DML's terms rather than the original ONNX indexing. - uint32_t dmlAxis = GetDmlAdjustedAxis( - m_absoluteAxis, - gsl::narrow_cast(indicesDimensions.size()), - m_inputTensorDescs.front().GetDimensionCount() - ); +//-- // Unsqueeze the indices tensor by inserting a flat dimension of size 1, +//-- // and compute the output tensor by expanding along the active axis. +//-- // This way they are both size-compatible and directly consumable by DirectML. +//-- std::vector indicesDimensions; +//-- indicesDimensions = kernelCreationContext.GetTensorShapeDescription().GetInputTensorShape(0); +//-- indicesDimensions.insert(indicesDimensions.begin() + m_absoluteAxis, 1u); +//-- +//-- // Update the tensor descriptions with new sizes. +//-- m_inputTensorDescs[0] = +//-- TensorDesc( +//-- m_inputTensorDescs[0].GetMlOperatorDataType(), +//-- gsl::make_span(indicesDimensions), +//-- gsl::make_span(indicesDimensions), +//-- TensorAxis::DoNotCoerce, +//-- TensorAxis::W, +//-- TensorAxis::RightAligned, +//-- NchwDimensionCount, // minDimensionCount +//-- 0 +//-- ); +//-- +//-- m_outputTensorDescs[0] = +//-- TensorDesc( +//-- m_outputTensorDescs[0].GetMlOperatorDataType(), +//-- gsl::make_span(m_outputDimensions), +//-- gsl::make_span(m_outputDimensions), +//-- TensorAxis::DoNotCoerce, +//-- TensorAxis::W, +//-- TensorAxis::RightAligned, +//-- NchwDimensionCount, // minDimensionCount +//-- 0 +//-- ); +//-- +//-- // Adjust the axis so it's in DML's terms rather than the original ONNX indexing. +//-- uint32_t dmlAxis = GetDmlAdjustedAxis( +//-- m_absoluteAxis, +//-- gsl::narrow_cast(indicesDimensions.size()), +//-- m_inputTensorDescs.front().GetDimensionCount() +//-- ); std::vector inputDescs = GetDmlInputDescs(); std::vector outputDescs = GetDmlOutputDescs(); - DML_ONE_HOT_OPERATOR_DESC operatorDesc = {}; - operatorDesc.IndicesTensor = &inputDescs[0]; - operatorDesc.ValuesTensor = &inputDescs[1]; + DML_FILL_VALUE_SEQUENCE_OPERATOR_DESC operatorDesc = {}; + operatorDesc.ValueDataType = m_outputTensorDescs[0].GetDmlDataType();; + operatorDesc.ValueStart.Float32 = 1; // todo::: + operatorDesc.ValueDelta.Float32 = 1; operatorDesc.OutputTensor = outputDescs.data(); - operatorDesc.Axis = dmlAxis; - DML_OPERATOR_DESC opDesc = { DML_OPERATOR_ONE_HOT, &operatorDesc }; + DML_OPERATOR_DESC opDesc = { DML_OPERATOR_FILL_VALUE_SEQUENCE, &operatorDesc }; SetDmlOperatorDesc(opDesc, kernelCreationContext); } }; diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorReverseSequence.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorReverseSequence.cpp index 842ad8f4cc..2d8e849cab 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorReverseSequence.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorReverseSequence.cpp @@ -9,14 +9,13 @@ namespace Dml { -class DmlOperatorReverseSequence : public DmlOperator, OneHotHelper +class DmlOperatorReverseSequence : public DmlOperator { public: using Self = DmlOperatorReverseSequence; DmlOperatorReverseSequence(const MLOperatorKernelCreationContext& kernelCreationContext) - : DmlOperator(kernelCreationContext), - OneHotHelper(kernelCreationContext, kernelCreationContext.GetTensorShapeDescription()) + : DmlOperator(kernelCreationContext) { ML_CHECK_VALID_ARGUMENT(kernelCreationContext.GetInputCount() == 2); ML_CHECK_VALID_ARGUMENT(kernelCreationContext.GetOutputCount() == 1); @@ -24,21 +23,23 @@ public: std::vector inputDimensions = kernelCreationContext.GetTensorShapeDescription().GetInputTensorShape(0); std::vector sequenceLengthDimensions = kernelCreationContext.GetTensorShapeDescription().GetInputTensorShape(1); + const uint32_t inputRank = static_cast(inputDimensions.size()); // Read axis. - int32_t onnxAxis = kernelCreationContext.GetOptionalAttribute(AttrName::TimeAxis, 0); - onnxAxis = HandleNegativeAxis(onnxAxis, static_cast(inputDimensions.size())); - const uint32_t dmlAxis = GetDmlAdjustedAxis(onnxAxis, onnxAxis, m_inputTensorDescs.front().GetDimensionCount()); + const int32_t batchAxis = HandleNegativeAxis(kernelCreationContext.GetOptionalAttribute(AttrName::BatchAxis, 0), inputRank); + const int32_t timeAxis = HandleNegativeAxis(kernelCreationContext.GetOptionalAttribute(AttrName::TimeAxis, 0), inputRank); + const uint32_t dmlTimeAxis = GetDmlAdjustedAxis(timeAxis, inputRank, m_inputTensorDescs.front().GetDimensionCount()); + ML_CHECK_VALID_ARGUMENT(timeAxis != batchAxis); // Fix up the sequence lengths tensor (originally 1D) to be rank compatible with input, // with all dimensions being the same as input except the active reversal axis. std::vector adjustedSequenceLengthDimensions = inputDimensions; - adjustedSequenceLengthDimensions[onnxAxis] = 1; + adjustedSequenceLengthDimensions[timeAxis] = 1; ML_CHECK_VALID_ARGUMENT(ComputeElementCountFromDimensions(adjustedSequenceLengthDimensions), ComputeElementCountFromDimensions(sequenceLengthDimensions)); m_inputTensorDescs[1] = TensorDesc( - m_inputTensorDescs[0].GetMlOperatorDataType(), + m_inputTensorDescs[1].GetMlOperatorDataType(), gsl::make_span(adjustedSequenceLengthDimensions), gsl::make_span(adjustedSequenceLengthDimensions), TensorAxis::DoNotCoerce, @@ -55,7 +56,7 @@ public: operatorDesc.InputTensor = &inputDescs[0]; operatorDesc.SequenceLengthsTensor = &inputDescs[1]; operatorDesc.OutputTensor = outputDescs.data(); - operatorDesc.Axis = dmlAxis; + operatorDesc.Axis = dmlTimeAxis; DML_OPERATOR_DESC opDesc = { DML_OPERATOR_REVERSE_SUBSEQUENCES, &operatorDesc }; SetDmlOperatorDesc(opDesc, kernelCreationContext); diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp index ee096592ab..695484a833 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp @@ -250,14 +250,15 @@ const static SupportedTensorDataTypes supportedTypeListScatterGatherND[2] = { Su const static SupportedTensorDataTypes supportedTypeListQuantizeLinear[2] = { SupportedTensorDataTypes::Float32 | SupportedTensorDataTypes::Int32, SupportedTensorDataTypes::UInt8 | SupportedTensorDataTypes::Int8 }; const static SupportedTensorDataTypes supportedTypeListDequantizeLinear[2] = { SupportedTensorDataTypes::Float32, SupportedTensorDataTypes::UInt8 | SupportedTensorDataTypes::Int8 | SupportedTensorDataTypes::Int32 }; const static SupportedTensorDataTypes supportedTypeListQuantize[2] = { SupportedTensorDataTypes::Float32, SupportedTensorDataTypes::UInt8 }; -const static SupportedTensorDataTypes supportedTypeListIsNan[2] = { SupportedTensorDataTypes::Float16to32, SupportedTensorDataTypes::UInt8 }; -const static SupportedTensorDataTypes supportedTypeListIsInf[2] = { SupportedTensorDataTypes::Float16to32, SupportedTensorDataTypes::UInt8 }; +const static SupportedTensorDataTypes supportedTypeListIsNan[2] = { SupportedTensorDataTypes::Float16to32, SupportedTensorDataTypes::Bool }; +const static SupportedTensorDataTypes supportedTypeListIsInf[2] = { SupportedTensorDataTypes::Float32, SupportedTensorDataTypes::Bool }; const static SupportedTensorDataTypes supportedTypeListConstantOfShape[2] = { SupportedTensorDataTypes::Int32|SupportedTensorDataTypes::Int64, SupportedTensorDataTypes::Float16to32 }; -const static SupportedTensorDataTypes supportedTypeListWhere[2] = { SupportedTensorDataTypes::UInt8, SupportedTensorDataTypes::Float16to32 }; +const static SupportedTensorDataTypes supportedTypeListWhere[2] = { SupportedTensorDataTypes::Bool, SupportedTensorDataTypes::Float16to32 }; const static SupportedTensorDataTypes supportedTypeListOneHot[3] = /* indices, depth, values */ { SupportedTensorDataTypes::Int32to64, SupportedTensorDataTypes::AllScalars, SupportedTensorDataTypes::Float16to32 }; const static SupportedTensorDataTypes supportedTypeListLogicalComparison7[2] = /* A&B,C */ { SupportedTensorDataTypes::Float16to32, SupportedTensorDataTypes::Bool }; const static SupportedTensorDataTypes supportedTypeListLogicalComparison9[2] = /* A&B,C */ { SupportedTensorDataTypes::NumericDefault, SupportedTensorDataTypes::Bool }; const static SupportedTensorDataTypes supportedTypeListSigned[1] = { SupportedTensorDataTypes::Float16to32 | SupportedTensorDataTypes::Int32 | SupportedTensorDataTypes::Int16 | SupportedTensorDataTypes::Int8 }; +const static SupportedTensorDataTypes supportedTypeListRange[1] = {SupportedTensorDataTypes::Int16|SupportedTensorDataTypes::Int32|SupportedTensorDataTypes::Float32}; // Define a single row of registration information. #define REG_INFO(version, operatorName, ...) \ @@ -509,8 +510,8 @@ const static OperatorRegistrationInformation operatorRegistrationInformationTabl {REG_INFO( 11, BitShift, typeNameListDefault, supportedTypeListInt8to32, DmGraphSupport::Supported)}, {REG_INFO( 11, Round, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, {REG_INFO( 10, ReverseSequence, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, // TODO::: data types, why not registered?? - {REG_INFO( 11, CumSum, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, -// {REG_INFO( 11, Range, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported), {0,1,2}}, + {REG_INFO( 11, CumSum, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported, {1})}, + {REG_INFO( 11, Range, typeNameListDefault, supportedTypeListRange, DmGraphSupport::Supported), {0,1,2}}, #if 0 {REG_INFO( 9, MaxUnpool, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported, {2})}, {REG_INFO( 11, Gather, typeNameListScatterGather, supportedTypeListScatterGather, DmGraphSupport::Supported)}, diff --git a/onnxruntime/core/providers/dml/OperatorAuthorHelper/Attributes.h b/onnxruntime/core/providers/dml/OperatorAuthorHelper/Attributes.h index 02caf8f28b..38e744ed6e 100644 --- a/onnxruntime/core/providers/dml/OperatorAuthorHelper/Attributes.h +++ b/onnxruntime/core/providers/dml/OperatorAuthorHelper/Attributes.h @@ -14,6 +14,7 @@ namespace AttrName static constexpr const char* Axes = "axes"; static constexpr const char* Axis = "axis"; static constexpr const char* AxisW = "axis_w"; + static constexpr const char* BatchAxis = "batch_axis"; static constexpr const char* Beta = "beta"; static constexpr const char* Bias = "bias"; static constexpr const char* BlockSize = "blocksize"; @@ -22,8 +23,8 @@ namespace AttrName static constexpr const char* CeilMode = "ceil_mode"; static constexpr const char* Clip = "clip"; static constexpr const char* CountIncludePad = "count_include_pad"; - static constexpr const char* DetectPositive = "detect_negative"; - static constexpr const char* DetectNegative = "detect_negative "; + static constexpr const char* DetectPositive = "detect_positive"; + static constexpr const char* DetectNegative = "detect_negative"; static constexpr const char* Dilations = "dilations"; static constexpr const char* Direction = "direction"; static constexpr const char* Dtype = "dtype"; diff --git a/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.cpp b/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.cpp index 9f3a0ed7e6..89909b97ef 100644 --- a/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.cpp +++ b/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.cpp @@ -483,15 +483,9 @@ int64_t ReadAsInt64(MLOperatorTensorDataType tensorDataType, const void* p) gsl::span inputDimensions ) { - m_axis = operatorAttributes.GetOptionalAttribute(AttrName::Axis, 0); - ML_CHECK_VALID_ARGUMENT(m_axis >= -int(inputDimensions.size()) && m_axis <= int(inputDimensions.size()) - 1); - - // Adjust any negative axis, meaning it counts from the back, with -1 being the last dimension - // and -dimCount being the first dimension. - if (m_axis < 0) - { - m_axis += gsl::narrow_cast(inputDimensions.size()); - } + int32_t signedOnnxAxis = operatorAttributes.GetOptionalAttribute(AttrName::Axis, 0); + uint32_t inputRank = gsl::narrow_cast(inputDimensions.size()); + m_axis = HandleNegativeAxis(signedOnnxAxis, inputRank); } std::vector GatherHelper::GetOutputShapes(const MLShapeInferenceContext& shapeInfo) const diff --git a/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.h b/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.h index f61f63b69a..cb4292c72d 100644 --- a/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.h +++ b/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.h @@ -1127,6 +1127,40 @@ class ResizeHelper { std::vector m_scales; // Cached scales to check for updates/invalidate operator. }; +class RangeHelper { +public: + // Info_t is used to obtain attributes which will be used for calculating the output shape later. + // Shape_t is used to obtain input shape which will be used for adjusting attribute value. + template + RangeHelper(const Info_t& info, const Shape_t& shape) { + // Read the scales from the 2nd tensor. + if (info.GetInputCount() > 1) { + MLOperatorTensor scalesTensor = info.GetConstantInputTensor(1); + Initialize(scalesTensor, shape.GetInputTensorShape(0)); + } else // From attribute. + { + Initialize(info, shape.GetInputTensorShape(0)); + } + } + + void Initialize( + const MLOperatorAttributes& operatorAttributes, + gsl::span inputDimensions); + + void Initialize( + const MLOperatorTensor& scalesTensor, + gsl::span inputDimensions); + + void InitializeOutputDimensions( + gsl::span scales, + gsl::span inputDimensions); + + std::vector GetOutputShapes(const MLShapeInferenceContext& shapeInfo) const; + +protected: + std::vector m_outputDimensions; +}; + class OneHotHelper { public: template @@ -1310,7 +1344,7 @@ using ShapeInferenceHelper_Multinomial = MultinomialHelper; using ShapeInferenceHelper_ReverseSequence = GetOutputShapeAsInputShapeHelper; using ShapeInferenceHelper_CumSum = GetOutputShapeAsInputShapeHelper; -// TODO::: using ShapeInferenceHelper_ShapeInferenceHelper_Range = ... +using ShapeInferenceHelper_ShapeInferenceHelper_Range = RangeHelper; using ShapeInferenceHelper_FusedConv = ConvHelper; using ShapeInferenceHelper_FusedConvTranspose = ConvTransposeHelper; From 1df264f4b371bd990084871c8801a40c746ba012 Mon Sep 17 00:00:00 2001 From: Dwayne Robinson Date: Tue, 24 Mar 2020 00:03:08 -0700 Subject: [PATCH 04/12] Fix Range. --- .../inc/MLOperatorAuthor.h | 2 +- .../src/ExecutionProvider.cpp | 2 +- .../src/Operators/DmlOperatorCumSum.cpp | 9 +- .../src/Operators/DmlOperatorRange.cpp | 47 +--- .../src/Operators/OperatorRegistration.cpp | 19 +- .../OperatorAuthorHelper/OperatorHelper.cpp | 237 ++++++++++++++++-- .../dml/OperatorAuthorHelper/OperatorHelper.h | 172 +++++++++---- 7 files changed, 355 insertions(+), 133 deletions(-) diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/inc/MLOperatorAuthor.h b/onnxruntime/core/providers/dml/DmlExecutionProvider/inc/MLOperatorAuthor.h index 29c806acf0..a821755092 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/inc/MLOperatorAuthor.h +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/inc/MLOperatorAuthor.h @@ -49,7 +49,7 @@ enum class MLOperatorAttributeType : uint32_t //! \brief Specifies the data type of a tensor. //! Each data type numerically matches corresponding ONNX types. enum class MLOperatorTensorDataType : uint32_t -{ +{ //! Undefined (unused). Undefined = 0, diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/ExecutionProvider.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/ExecutionProvider.cpp index 84b298ca77..630e3bd3d8 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/ExecutionProvider.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/ExecutionProvider.cpp @@ -181,7 +181,7 @@ namespace Dml // CPU Allocator used to create buffers for the MemcpyFromHost operator. m_cpuInputAllocator = std::make_shared(OrtMemType::OrtMemTypeCPUInput); m_cpuOutputAllocator = std::make_shared(OrtMemType::OrtMemTypeCPUOutput); - + CreateDmlKernelRegistry(&m_kernelRegistry, &m_internalRegInfoMap); } diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorCumSum.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorCumSum.cpp index 8eaa00f567..1f8cf4aa31 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorCumSum.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorCumSum.cpp @@ -29,13 +29,10 @@ public: int32_t onnxAxis = 0; if (kernelCreationContext.IsInputValid(1)) { + uint64_t rawAxisBytes; MLOperatorTensor axisTensor = kernelCreationContext.GetConstantInputTensor(1); - const uint32_t axisElementCount = ComputeElementCountFromDimensions(axisTensor.GetShape()); - ML_CHECK_VALID_ARGUMENT(axisTensor.IsCpuData(), "CumSum's 'axis' tensor must be a CPU Tensor."); - ML_CHECK_VALID_ARGUMENT(axisElementCount == 1, "CumSum's 'axis' tensor must have one element."); - - const void* tensorData = axisTensor.GetByteData(); - onnxAxis = static_cast(ReadAsInt64(axisTensor.GetTensorDataType(), tensorData)); + ReadScalarTensorData(axisTensor, /*out*/ &rawAxisBytes, sizeof(rawAxisBytes)); + onnxAxis = gsl::narrow_cast(ReadAsInt64(axisTensor.GetTensorDataType(), /*out*/ &rawAxisBytes)); } uint32_t dmlAxis = GetDmlAdjustedAxis(onnxAxis, kernelCreationContext, m_inputTensorDescs.front().GetDimensionCount()); diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorRange.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorRange.cpp index bd0f3936e4..821ba6aaa6 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorRange.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorRange.cpp @@ -23,53 +23,16 @@ public: std::vector> inputIndices = {}; // All tensors are CPU bound. std::vector> outputIndices = { 0 }; DmlOperator::Initialize(kernelCreationContext, inputIndices, outputIndices); - -//-- // Unsqueeze the indices tensor by inserting a flat dimension of size 1, -//-- // and compute the output tensor by expanding along the active axis. -//-- // This way they are both size-compatible and directly consumable by DirectML. -//-- std::vector indicesDimensions; -//-- indicesDimensions = kernelCreationContext.GetTensorShapeDescription().GetInputTensorShape(0); -//-- indicesDimensions.insert(indicesDimensions.begin() + m_absoluteAxis, 1u); -//-- -//-- // Update the tensor descriptions with new sizes. -//-- m_inputTensorDescs[0] = -//-- TensorDesc( -//-- m_inputTensorDescs[0].GetMlOperatorDataType(), -//-- gsl::make_span(indicesDimensions), -//-- gsl::make_span(indicesDimensions), -//-- TensorAxis::DoNotCoerce, -//-- TensorAxis::W, -//-- TensorAxis::RightAligned, -//-- NchwDimensionCount, // minDimensionCount -//-- 0 -//-- ); -//-- -//-- m_outputTensorDescs[0] = -//-- TensorDesc( -//-- m_outputTensorDescs[0].GetMlOperatorDataType(), -//-- gsl::make_span(m_outputDimensions), -//-- gsl::make_span(m_outputDimensions), -//-- TensorAxis::DoNotCoerce, -//-- TensorAxis::W, -//-- TensorAxis::RightAligned, -//-- NchwDimensionCount, // minDimensionCount -//-- 0 -//-- ); -//-- -//-- // Adjust the axis so it's in DML's terms rather than the original ONNX indexing. -//-- uint32_t dmlAxis = GetDmlAdjustedAxis( -//-- m_absoluteAxis, -//-- gsl::narrow_cast(indicesDimensions.size()), -//-- m_inputTensorDescs.front().GetDimensionCount() -//-- ); - + std::vector inputDescs = GetDmlInputDescs(); std::vector outputDescs = GetDmlOutputDescs(); DML_FILL_VALUE_SEQUENCE_OPERATOR_DESC operatorDesc = {}; operatorDesc.ValueDataType = m_outputTensorDescs[0].GetDmlDataType();; - operatorDesc.ValueStart.Float32 = 1; // todo::: - operatorDesc.ValueDelta.Float32 = 1; + static_assert(sizeof(operatorDesc.ValueStart) == sizeof(m_valueStart)); + static_assert(sizeof(operatorDesc.ValueDelta) == sizeof(m_valueDelta)); + memcpy(&operatorDesc.ValueStart, &m_valueStart, sizeof(m_valueStart)); + memcpy(&operatorDesc.ValueDelta, &m_valueDelta, sizeof(m_valueDelta)); operatorDesc.OutputTensor = outputDescs.data(); DML_OPERATOR_DESC opDesc = { DML_OPERATOR_FILL_VALUE_SEQUENCE, &operatorDesc }; diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp index 695484a833..1dc7727749 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp @@ -230,7 +230,7 @@ const static char* const typeNameListLogicalComparison[2] = { "T", "T1" }; const static char* const typeNameListT1T2[2] = { "T1", "T2" }; const static char* const typeNameListConstantOfShape[2] = { "T1", "T2" }; const static char* const typeNameListScatterGather[2] = { "T", "Tind" }; -const static char* const typeNameListScatterGatherND[2] = { "T" }; // Tind is curiously missing, only allowing 64-bit. +const static char* const typeNameListScatterGatherND[1] = { "T" }; // Tind is curiously missing, only allowing 64-bit. const static char* const typeNameListQuantize[2] = { "T1", "T2" }; const static char* const typeNameListWhere[2] = { "B", "T" }; const static char* const typeNameListOneHot[3] = { "T1", "T2", "T3" }; @@ -246,7 +246,7 @@ const static SupportedTensorDataTypes supportedTypeListTopK[2] = {SupportedTenso const static SupportedTensorDataTypes supportedTypeListIndices[1] = { SupportedTensorDataTypes::Int32|SupportedTensorDataTypes::Int64 }; const static SupportedTensorDataTypes supportedTypeListCast[2] = { SupportedTensorDataTypes::AllScalars, SupportedTensorDataTypes::Scalars8to32 }; const static SupportedTensorDataTypes supportedTypeListScatterGather[2] = { SupportedTensorDataTypes::NumericDefault, SupportedTensorDataTypes::Int32 | SupportedTensorDataTypes::Int64 }; -const static SupportedTensorDataTypes supportedTypeListScatterGatherND[2] = { SupportedTensorDataTypes::NumericDefault }; +const static SupportedTensorDataTypes supportedTypeListScatterGatherND[1] = { SupportedTensorDataTypes::NumericDefault }; const static SupportedTensorDataTypes supportedTypeListQuantizeLinear[2] = { SupportedTensorDataTypes::Float32 | SupportedTensorDataTypes::Int32, SupportedTensorDataTypes::UInt8 | SupportedTensorDataTypes::Int8 }; const static SupportedTensorDataTypes supportedTypeListDequantizeLinear[2] = { SupportedTensorDataTypes::Float32, SupportedTensorDataTypes::UInt8 | SupportedTensorDataTypes::Int8 | SupportedTensorDataTypes::Int32 }; const static SupportedTensorDataTypes supportedTypeListQuantize[2] = { SupportedTensorDataTypes::Float32, SupportedTensorDataTypes::UInt8 }; @@ -511,15 +511,16 @@ const static OperatorRegistrationInformation operatorRegistrationInformationTabl {REG_INFO( 11, Round, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, {REG_INFO( 10, ReverseSequence, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, // TODO::: data types, why not registered?? {REG_INFO( 11, CumSum, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported, {1})}, - {REG_INFO( 11, Range, typeNameListDefault, supportedTypeListRange, DmGraphSupport::Supported), {0,1,2}}, + {REG_INFO( 11, Range, typeNameListDefault, supportedTypeListRange, DmGraphSupport::Supported, {0,1,2})}, + + {REG_INFO( 11, Gather, typeNameListScatterGather, supportedTypeListScatterGather, DmGraphSupport::Supported)}, + {REG_INFO( 11, GatherElements, typeNameListScatterGather, supportedTypeListScatterGather, DmGraphSupport::Supported)}, + {REG_INFO( 11, GatherND, typeNameListScatterGatherND, supportedTypeListScatterGatherND, DmGraphSupport::Supported)}, + {REG_INFO( 11, ScatterElements, typeNameListScatterGather, supportedTypeListScatterGather, DmGraphSupport::Supported)}, + {REG_INFO( 11, ScatterND, typeNameListScatterGatherND, supportedTypeListScatterGatherND, DmGraphSupport::Supported)}, #if 0 - {REG_INFO( 9, MaxUnpool, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported, {2})}, - {REG_INFO( 11, Gather, typeNameListScatterGather, supportedTypeListScatterGather, DmGraphSupport::Supported)}, - -{REG_INFO( 11, GatherElements, typeNameListScatterGather, supportedTypeListScatterGather, DmGraphSupport::Supported)}, - -{REG_INFO( 11, GatherND, typeNameListScatterGatherND, supportedTypeListScatterGatherND, DmGraphSupport::Supported)}, + {REG_INFO( 9, MaxUnpool, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported, {2})}, {REG_INFO( 11, Resize, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported, {1})}, - -{REG_INFO( 11, ScatterElements, typeNameListScatterGather, supportedTypeListScatterGather, DmGraphSupport::Supported)}, - -{REG_INFO( 11, ScatterND, typeNameListScatterGatherND, supportedTypeListScatterGatherND, DmGraphSupport::Supported)}, {REG_INFO( 11, QLinearConv, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, // T1 : tensor(int8), tensor(uint8) diff --git a/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.cpp b/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.cpp index 89909b97ef..24340b911e 100644 --- a/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.cpp +++ b/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.cpp @@ -6,36 +6,36 @@ namespace OperatorHelper { -bool ContainsEmptyDimensions(gsl::span dimensions) -{ - return std::find(dimensions.begin(), dimensions.end(), 0) != dimensions.end(); -} - -// Convert any negative axis into an absolute axis relative to the back end. -// So given 3 dimensions, a -1 refers to axis 2, and -3 to axis 0. -uint32_t HandleNegativeAxis(int32_t signedOnnxAxis, uint32_t dimCount) -{ - if (signedOnnxAxis < 0) + bool ContainsEmptyDimensions(gsl::span dimensions) { - signedOnnxAxis += dimCount; + return std::find(dimensions.begin(), dimensions.end(), 0) != dimensions.end(); } - uint32_t absoluteAxis = gsl::narrow_cast(signedOnnxAxis); - ML_CHECK_VALID_ARGUMENT(absoluteAxis < dimCount); - return absoluteAxis; -} -void HandleNegativeAxes(gsl::span onnxAxes, uint32_t dimCount) -{ - for (int32_t& axis : onnxAxes) + // Convert any negative axis into an absolute axis relative to the back end. + // So given 3 dimensions, a -1 refers to axis 2, and -3 to axis 0. + uint32_t HandleNegativeAxis(int32_t signedOnnxAxis, uint32_t dimCount) { - axis = HandleNegativeAxis(axis, dimCount); + if (signedOnnxAxis < 0) + { + signedOnnxAxis += dimCount; + } + uint32_t absoluteAxis = gsl::narrow_cast(signedOnnxAxis); + ML_CHECK_VALID_ARGUMENT(absoluteAxis < dimCount); + return absoluteAxis; } -} -int64_t ReadAsInt64(MLOperatorTensorDataType tensorDataType, const void* p) -{ - switch (tensorDataType) + void HandleNegativeAxes(gsl::span onnxAxes, uint32_t dimCount) { + for (int32_t& axis : onnxAxes) + { + axis = HandleNegativeAxis(axis, dimCount); + } + } + + int64_t ReadAsInt64(MLOperatorTensorDataType tensorDataType, const void* p) + { + switch (tensorDataType) + { case MLOperatorTensorDataType::Float: return static_cast(*reinterpret_cast(p)); case MLOperatorTensorDataType::UInt8: return static_cast(*reinterpret_cast(p)); case MLOperatorTensorDataType::Int8: return static_cast(*reinterpret_cast(p)); @@ -56,6 +56,57 @@ int64_t ReadAsInt64(MLOperatorTensorDataType tensorDataType, const void* p) }; } + double ReadAsFloat64(MLOperatorTensorDataType tensorDataType, const void* p) + { + switch (tensorDataType) + { + case MLOperatorTensorDataType::Float: return static_cast(*reinterpret_cast(p)); + case MLOperatorTensorDataType::UInt8: return static_cast(*reinterpret_cast(p)); + case MLOperatorTensorDataType::Int8: return static_cast(*reinterpret_cast(p)); + case MLOperatorTensorDataType::UInt16: return static_cast(*reinterpret_cast(p)); + case MLOperatorTensorDataType::Int16: return static_cast(*reinterpret_cast(p)); + case MLOperatorTensorDataType::Int32: return static_cast(*reinterpret_cast(p)); + case MLOperatorTensorDataType::Int64: return static_cast(*reinterpret_cast(p)); + case MLOperatorTensorDataType::String: ML_INVALID_ARGUMENT("MLOperatorTensorDataType::String type is unsupported for reading as an integer."); + case MLOperatorTensorDataType::Bool: return static_cast(*reinterpret_cast(p)); + case MLOperatorTensorDataType::Float16: ML_INVALID_ARGUMENT("MLOperatorTensorDataType::Float16 type is unsupported for reading as an integer."); + case MLOperatorTensorDataType::Double: return static_cast(*reinterpret_cast(p)); + case MLOperatorTensorDataType::UInt32: return static_cast(*reinterpret_cast(p)); + case MLOperatorTensorDataType::UInt64: return static_cast(*reinterpret_cast(p)); + case MLOperatorTensorDataType::Complex64: return static_cast(*reinterpret_cast(p)); // Read the real component. + case MLOperatorTensorDataType::Complex128: return static_cast(*reinterpret_cast(p)); // Read the real component. + case MLOperatorTensorDataType::Undefined: + default: ML_INVALID_ARGUMENT("Unknown MLOperatorTensorDataType."); + }; + } + + int64_t IsFloatDataType(MLOperatorTensorDataType tensorDataType) + { + switch (tensorDataType) + { + case MLOperatorTensorDataType::Float: + case MLOperatorTensorDataType::Float16: + case MLOperatorTensorDataType::Double: + case MLOperatorTensorDataType::Complex64: + case MLOperatorTensorDataType::Complex128: + return true; + }; + return false; + } + + void ReadScalarTensorData(const MLOperatorTensor& tensor, /*out*/ void* data, size_t dataByteSize) + { + // Read the tensor bytes of a scalar value into the output data, + // validating dimensions and byte size. + const uint32_t elementCount = ComputeElementCountFromDimensions(tensor.GetShape()); + const size_t elementByteSize = GetByteSizeFromMlDataType(tensor.GetTensorDataType()); + ML_CHECK_VALID_ARGUMENT(tensor.IsCpuData(), "Tensor must be a CPU Tensor."); + ML_CHECK_VALID_ARGUMENT(elementCount == 1, "Scalar tensors must have exactly 1 element."); + ML_CHECK_VALID_ARGUMENT(dataByteSize >= elementByteSize, "Scalar tensor element byte size is too large."); + + memcpy(data, tensor.GetByteData(), elementByteSize); + } + // Calculates the spatial dimensions from input dimensions and a kernel. The non-spatial (leading) // dimensions will be initialized to match the input dimensions. This assumes the spatial dimensions // are ordered such that they are at the end (e.g. NCHW or NCDHW). @@ -526,6 +577,106 @@ int64_t ReadAsInt64(MLOperatorTensorDataType tensorDataType, const void* p) return { EdgeShapes(std::move(outputDimensions)) }; } +// TODO::: + + void GatherNDHelper::Initialize( + const MLOperatorAttributes& operatorAttributes, + gsl::span inputDimensions + ) + { + int32_t signedOnnxAxis = operatorAttributes.GetOptionalAttribute(AttrName::Axis, 0); + uint32_t inputRank = gsl::narrow_cast(inputDimensions.size()); + m_axis = HandleNegativeAxis(signedOnnxAxis, inputRank); + } + + std::vector GatherNDHelper::GetOutputShapes(const MLShapeInferenceContext& shapeInfo) const + { + std::vector inputDimensions = shapeInfo.GetInputTensorShape(0); + std::vector indicesDimensions = shapeInfo.GetInputTensorShape(1); + + ML_CHECK_VALID_ARGUMENT(inputDimensions.size() >= 1); + ML_CHECK_VALID_ARGUMENT(indicesDimensions.size() >= 0); + int outDimCount = gsl::narrow_cast(inputDimensions.size() + indicesDimensions.size() - 1); + ML_CHECK_VALID_ARGUMENT(outDimCount > 0 && outDimCount <= NchwDimensionCount); + + std::vector outputDimensions(outDimCount, 1); + + // The input dimensions following the gather axis determine the final output dimensions. + int outputDim = outDimCount - 1; + int inputDim = gsl::narrow_cast(inputDimensions.size() - 1); + for (; inputDim > m_axis; --outputDim, --inputDim) + { + outputDimensions[outputDim] = inputDimensions[inputDim]; + } + + // The shape of the index tensor is reflected in the middle dimensions of the output tensor. + int indexDim = gsl::narrow_cast(indicesDimensions.size() - 1); + for (; indexDim >= 0; --outputDim, --indexDim) + { + outputDimensions[outputDim] = indicesDimensions[indexDim]; + } + + // The gather dimension is skipped for the purposes of sizing because the index values choose slices + // across it. Preceding input dimensions determine the shape of the output's leading dimensions. + inputDim = m_axis - 1; + for (; outputDim >= 0 && inputDim >= 0; --outputDim, --inputDim) + { + outputDimensions[outputDim] = inputDimensions[inputDim]; + } + + return { EdgeShapes(std::move(outputDimensions)) }; + } + +// TODO::: + + void ScatterNDHelper::Initialize( + const MLOperatorAttributes& operatorAttributes, + gsl::span inputDimensions + ) + { + int32_t signedOnnxAxis = operatorAttributes.GetOptionalAttribute(AttrName::Axis, 0); + uint32_t inputRank = gsl::narrow_cast(inputDimensions.size()); + m_axis = HandleNegativeAxis(signedOnnxAxis, inputRank); + } + + std::vector ScatterNDHelper::GetOutputShapes(const MLShapeInferenceContext& shapeInfo) const + { + std::vector inputDimensions = shapeInfo.GetInputTensorShape(0); + std::vector indicesDimensions = shapeInfo.GetInputTensorShape(1); + + ML_CHECK_VALID_ARGUMENT(inputDimensions.size() >= 1); + ML_CHECK_VALID_ARGUMENT(indicesDimensions.size() >= 0); + int outDimCount = gsl::narrow_cast(inputDimensions.size() + indicesDimensions.size() - 1); + ML_CHECK_VALID_ARGUMENT(outDimCount > 0 && outDimCount <= NchwDimensionCount); + + std::vector outputDimensions(outDimCount, 1); + + // The input dimensions following the gather axis determine the final output dimensions. + int outputDim = outDimCount - 1; + int inputDim = gsl::narrow_cast(inputDimensions.size() - 1); + for (; inputDim > m_axis; --outputDim, --inputDim) + { + outputDimensions[outputDim] = inputDimensions[inputDim]; + } + + // The shape of the index tensor is reflected in the middle dimensions of the output tensor. + int indexDim = gsl::narrow_cast(indicesDimensions.size() - 1); + for (; indexDim >= 0; --outputDim, --indexDim) + { + outputDimensions[outputDim] = indicesDimensions[indexDim]; + } + + // The gather dimension is skipped for the purposes of sizing because the index values choose slices + // across it. Preceding input dimensions determine the shape of the output's leading dimensions. + inputDim = m_axis - 1; + for (; outputDim >= 0 && inputDim >= 0; --outputDim, --inputDim) + { + outputDimensions[outputDim] = inputDimensions[inputDim]; + } + + return { EdgeShapes(std::move(outputDimensions)) }; + } + void TransposeHelper::Initialize( const MLOperatorAttributes& operatorAttributes, gsl::span inputDimensions @@ -1139,6 +1290,46 @@ int64_t ReadAsInt64(MLOperatorTensorDataType tensorDataType, const void* p) return { m_outputDimensions }; } + void RangeHelper::Initialize( + const MLOperatorTensor& startTensor, + const MLOperatorTensor& limitTensor, + const MLOperatorTensor& deltaTensor + ) + { + ReadScalarTensorData(startTensor, &m_valueStart, sizeof(m_valueStart)); + ReadScalarTensorData(limitTensor, &m_valueLimit, sizeof(m_valueLimit)); + ReadScalarTensorData(deltaTensor, &m_valueDelta, sizeof(m_valueDelta)); + m_tensorDataType = startTensor.GetTensorDataType(); + + // The output size is a 1D tensor ranging from start up to limit, + // where: + // + // number_of_elements = max(ceil((limit - start) / delta), 0) + // + uint32_t totalElementCount = 0; + if (IsFloatDataType(m_tensorDataType)) + { + double start = ReadAsFloat64(m_tensorDataType, &m_valueStart); + double limit = ReadAsFloat64(m_tensorDataType, &m_valueLimit); + double delta = ReadAsFloat64(m_tensorDataType, &m_valueDelta); + totalElementCount = gsl::narrow_cast(ceil((limit - start) / delta)); + } + else + { + int64_t start = ReadAsInt64(m_tensorDataType, &m_valueStart); + int64_t limit = ReadAsInt64(m_tensorDataType, &m_valueLimit); + int64_t delta = ReadAsInt64(m_tensorDataType, &m_valueDelta); + int64_t range = limit - start; + totalElementCount = gsl::narrow_cast((range / delta) + (range % delta != 0)); + } + m_outputDimensions.push_back(totalElementCount); + } + + std::vector RangeHelper::GetOutputShapes(const MLShapeInferenceContext& shapeInfo) const + { + return { m_outputDimensions }; + } + std::vector OneHotHelper::GetOutputShapes(const MLShapeInferenceContext& shapeInfo) const { return { std::move(EdgeShapes(m_outputDimensions)) }; diff --git a/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.h b/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.h index cb4292c72d..44a15abc79 100644 --- a/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.h +++ b/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.h @@ -76,6 +76,8 @@ void RemoveValuesByIndex(gsl::span indices, bool keepOneValue, / } int64_t ReadAsInt64(MLOperatorTensorDataType tensorDataType, const void* p); +double ReadAsFloat64(MLOperatorTensorDataType tensorDataType, const void* p); +void ReadScalarTensorData(const MLOperatorTensor& tensor, void* data, size_t dataByteSize); class EdgeShapes { public: @@ -174,13 +176,38 @@ class GetOutputShapeAsInputShapeHelper { public: // Info_t is used to obtain attributes which will be used for calculating the output shape later. // Shape_t is used to obtain input shape which will be used for adjusting attribute value. + // Default to first input tensor. template GetOutputShapeAsInputShapeHelper(const Info_t& info, const Shape_t& shape){ ORT_UNUSED_PARAMETER(info); ORT_UNUSED_PARAMETER(shape); }; + // Info_t is used to obtain attributes which will be used for calculating the output shape later. + // Shape_t is used to obtain input shape which will be used for adjusting attribute value. + // Pass specific tensor index. + template + GetOutputShapeAsInputShapeHelper(const Info_t& info, const Shape_t& shape, uint32_t inputTensorIndex) + : m_inputTensorIndex(inputTensorIndex) + { + ORT_UNUSED_PARAMETER(info); + ORT_UNUSED_PARAMETER(shape); + }; + std::vector GetOutputShapes(const MLShapeInferenceContext& shapeInfo) const; + + uint32_t m_inputTensorIndex = 0; +}; + +template +class GetOutputShapeAsSpecificInputShapeHelper : public GetOutputShapeAsInputShapeHelper { +public: + // Info_t is used to obtain attributes which will be used for calculating the output shape later. + // Shape_t is used to obtain input shape which will be used for adjusting attribute value. + template + GetOutputShapeAsSpecificInputShapeHelper(const Info_t& info, const Shape_t& shape) + : GetOutputShapeAsInputShapeHelper(info, shape, InputTensorIndex) + {} }; class GetBroadcastedOutputShapeHelper { @@ -329,10 +356,10 @@ public: ); } - const std::vector inputDimensions = shapeInfo.GetInputTensorShape(0); - const std::vector filterDims = shapeInfo.GetInputTensorShape(1); + const std::vector inputDimensions = shapeInfo.GetInputTensorShape(0); + const std::vector filterDims = shapeInfo.GetInputTensorShape(1); - ML_CHECK_VALID_ARGUMENT(inputDimensions.size() > NonspatialDimensionCount, "Input dimensions must be >= 3"); + ML_CHECK_VALID_ARGUMENT(inputDimensions.size() > NonspatialDimensionCount, "Input dimensions must be >= 3"); if (hasDynamicPads) { @@ -367,39 +394,39 @@ public: assert(m_outputShapes[0].GetShape().size() > C); m_outputShapes[0].GetShape()[C] = filterDims[C] * m_groupCount; - if (!outputShape.empty()) { - // Start padding, end padding, and output padding are all ignored if output shape is set. - std::fill(m_kernel.outputPadding, m_kernel.outputPadding + m_kernel.spatialDimensionCount, 0); + if (!outputShape.empty()) { + // Start padding, end padding, and output padding are all ignored if output shape is set. + std::fill(m_kernel.outputPadding, m_kernel.outputPadding + m_kernel.spatialDimensionCount, 0); - if (outputShape.size() > 2) { - ML_CHECK_VALID_ARGUMENT(outputShape[outputShape.size() - 3] == gsl::narrow_cast(m_outputShapes[0].GetShape()[C]), "Output channel must be equivalent to filter channel."); - } + if (outputShape.size() > 2) { + ML_CHECK_VALID_ARGUMENT(outputShape[outputShape.size() - 3] == gsl::narrow_cast(m_outputShapes[0].GetShape()[C]), "Output channel must be equivalent to filter channel."); + } - for (size_t i = 0; i < m_kernel.spatialDimensionCount; ++i) { - size_t outputIndex = outputShape.size() - m_kernel.spatialDimensionCount + i; - ML_CHECK_VALID_ARGUMENT(outputShape[outputIndex] >= gsl::narrow_cast(inputDimensions[H + i]), "Output dimension cannot be smaller than input dimension."); - m_outputShapes[0].GetShape()[H + i] = outputShape[outputIndex]; - } + for (size_t i = 0; i < m_kernel.spatialDimensionCount; ++i) { + size_t outputIndex = outputShape.size() - m_kernel.spatialDimensionCount + i; + ML_CHECK_VALID_ARGUMENT(outputShape[outputIndex] >= gsl::narrow_cast(inputDimensions[H + i]), "Output dimension cannot be smaller than input dimension."); + m_outputShapes[0].GetShape()[H + i] = outputShape[outputIndex]; + } - const int dimOffset = gsl::narrow_cast(inputDimensions.size() - m_kernel.spatialDimensionCount); + const int dimOffset = gsl::narrow_cast(inputDimensions.size() - m_kernel.spatialDimensionCount); - for (size_t i = 0; i < m_kernel.spatialDimensionCount; ++i) { - int stride = m_kernel.strides[i]; - int windowSize = m_kernel.windowSize[i]; + for (size_t i = 0; i < m_kernel.spatialDimensionCount; ++i) { + int stride = m_kernel.strides[i]; + int windowSize = m_kernel.windowSize[i]; - // Compute padding such that in reverse order, the logical input (m_outputShapes below) is fully defined - // for a convolution over the logical output region (inputDimensions below). - // - // The padding required is the first windowSize element (for the first logical output element), - // plus (logicalOutput - 1) steps of stride (the distance between each windowed set of logical - // input elements), minus the actual logical input size. - int paddings = gsl::narrow_cast((inputDimensions[i + dimOffset] - 1) * stride + windowSize - m_outputShapes[0].GetShape()[i + dimOffset]); - paddings = std::max(0, paddings); + // Compute padding such that in reverse order, the logical input (m_outputShapes below) is fully defined + // for a convolution over the logical output region (inputDimensions below). + // + // The padding required is the first windowSize element (for the first logical output element), + // plus (logicalOutput - 1) steps of stride (the distance between each windowed set of logical + // input elements), minus the actual logical input size. + int paddings = gsl::narrow_cast((inputDimensions[i + dimOffset] - 1) * stride + windowSize - m_outputShapes[0].GetShape()[i + dimOffset]); + paddings = std::max(0, paddings); - m_kernel.startPadding[i] = m_kernel.autoPadSameUpper ? (paddings + 1) / 2 : paddings / 2; - m_kernel.endPadding[i] = paddings - m_kernel.startPadding[i]; - } - } + m_kernel.startPadding[i] = m_kernel.autoPadSameUpper ? (paddings + 1) / 2 : paddings / 2; + m_kernel.endPadding[i] = paddings - m_kernel.startPadding[i]; + } + } } protected: @@ -898,6 +925,46 @@ class GatherHelper { int m_axis = 0; }; +class GatherNDHelper { + public: + void Initialize( + const MLOperatorAttributes& operatorAttributes, + gsl::span dataDimensions + ); + + // Info_t is used to obtain attributes which will be used for calculating the output shape later. + // Shape_t is used to obtain input shape which will be used for adjusting attribute value. + template + GatherNDHelper(const Info_t& info, const Shape_t& shape) { + Initialize(info, shape.GetInputTensorShape(0)); + } + + std::vector GetOutputShapes(const MLShapeInferenceContext& shapeInfo) const; + + protected: + int m_axis = 0; +}; + +class ScatterNDHelper { + public: + void Initialize( + const MLOperatorAttributes& operatorAttributes, + gsl::span dataDimensions + ); + + // Info_t is used to obtain attributes which will be used for calculating the output shape later. + // Shape_t is used to obtain input shape which will be used for adjusting attribute value. + template + ScatterNDHelper(const Info_t& info, const Shape_t& shape) { + Initialize(info, shape.GetInputTensorShape(0)); + } + + std::vector GetOutputShapes(const MLShapeInferenceContext& shapeInfo) const; + + protected: + int m_axis = 0; +}; + class PoolingHelperBase { public: // Info_t is used to obtain attributes which will be used for calculating the output shape later. @@ -1127,38 +1194,36 @@ class ResizeHelper { std::vector m_scales; // Cached scales to check for updates/invalidate operator. }; +//TODO::: class RangeHelper { public: // Info_t is used to obtain attributes which will be used for calculating the output shape later. // Shape_t is used to obtain input shape which will be used for adjusting attribute value. template - RangeHelper(const Info_t& info, const Shape_t& shape) { - // Read the scales from the 2nd tensor. - if (info.GetInputCount() > 1) { - MLOperatorTensor scalesTensor = info.GetConstantInputTensor(1); - Initialize(scalesTensor, shape.GetInputTensorShape(0)); - } else // From attribute. - { - Initialize(info, shape.GetInputTensorShape(0)); - } + RangeHelper(const Info_t& info, const Shape_t& shape) + { + auto startTensor = info.GetConstantInputTensor(0); + auto limitTensor = info.GetConstantInputTensor(1); + auto deltaTensor = info.GetConstantInputTensor(2); + Initialize(startTensor, limitTensor, deltaTensor); } void Initialize( - const MLOperatorAttributes& operatorAttributes, - gsl::span inputDimensions); - - void Initialize( - const MLOperatorTensor& scalesTensor, - gsl::span inputDimensions); - - void InitializeOutputDimensions( - gsl::span scales, - gsl::span inputDimensions); + const MLOperatorTensor& startTensor, + const MLOperatorTensor& limitTensor, + const MLOperatorTensor& deltaTensor + ); std::vector GetOutputShapes(const MLShapeInferenceContext& shapeInfo) const; protected: std::vector m_outputDimensions; + + MLOperatorTensorDataType m_tensorDataType = MLOperatorTensorDataType::Undefined; + using TensorScalarData = typename std::aligned_storage::type; + TensorScalarData m_valueStart; + TensorScalarData m_valueLimit; + TensorScalarData m_valueDelta; }; class OneHotHelper { @@ -1220,7 +1285,13 @@ using ShapeInferenceHelper_LpNormalization = GetOutputShapeAsInputShapeHelper; using ShapeInferenceHelper_RNN = RecurrentHelper; using ShapeInferenceHelper_GRU = RecurrentHelper; using ShapeInferenceHelper_LSTM = RecurrentHelper; + using ShapeInferenceHelper_Gather = GatherHelper; +using ShapeInferenceHelper_GatherElements = GetOutputShapeAsSpecificInputShapeHelper<1>; +using ShapeInferenceHelper_ScatterElements = GetOutputShapeAsInputShapeHelper; +using ShapeInferenceHelper_Scatter = ShapeInferenceHelper_ScatterElements; +using ShapeInferenceHelper_GatherND = GatherNDHelper; +using ShapeInferenceHelper_ScatterND = ScatterNDHelper; using ShapeInferenceHelper_Flatten = FlattenHelper; using ShapeInferenceHelper_Split = SplitHelper; @@ -1276,7 +1347,6 @@ using ShapeInferenceHelper_Atan = GetOutputShapeAsInputShapeHelper; using ShapeInferenceHelper_Affine = GetOutputShapeAsInputShapeHelper; using ShapeInferenceHelper_QuantizeLinear = GetOutputShapeAsInputShapeHelper; using ShapeInferenceHelper_DequantizeLinear = GetOutputShapeAsInputShapeHelper; -using ShapeInferenceHelper_Scatter = GetOutputShapeAsInputShapeHelper; using ShapeInferenceHelper_Sign = GetBroadcastedOutputShapeHelper; using ShapeInferenceHelper_IsNan = GetBroadcastedOutputShapeHelper; using ShapeInferenceHelper_Erf = GetBroadcastedOutputShapeHelper; @@ -1344,7 +1414,7 @@ using ShapeInferenceHelper_Multinomial = MultinomialHelper; using ShapeInferenceHelper_ReverseSequence = GetOutputShapeAsInputShapeHelper; using ShapeInferenceHelper_CumSum = GetOutputShapeAsInputShapeHelper; -using ShapeInferenceHelper_ShapeInferenceHelper_Range = RangeHelper; +using ShapeInferenceHelper_Range = RangeHelper; using ShapeInferenceHelper_FusedConv = ConvHelper; using ShapeInferenceHelper_FusedConvTranspose = ConvTransposeHelper; From 271126a86eaf2d5ed5b5d24f3ee4961838130171 Mon Sep 17 00:00:00 2001 From: Dwayne Robinson Date: Tue, 24 Mar 2020 01:04:08 -0700 Subject: [PATCH 05/12] Fix clip. --- .../src/Operators/DmlOperatorCumSum.cpp | 6 +-- .../src/Operators/DmlOperatorElementWise.cpp | 43 +++++++++++++++++-- .../src/Operators/OperatorRegistration.cpp | 15 +++---- .../OperatorAuthorHelper/OperatorHelper.cpp | 18 +++++++- .../dml/OperatorAuthorHelper/OperatorHelper.h | 9 ++-- 5 files changed, 72 insertions(+), 19 deletions(-) diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorCumSum.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorCumSum.cpp index 1f8cf4aa31..c323affc55 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorCumSum.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorCumSum.cpp @@ -29,10 +29,10 @@ public: int32_t onnxAxis = 0; if (kernelCreationContext.IsInputValid(1)) { - uint64_t rawAxisBytes; + std::byte tensorBytes[8]; MLOperatorTensor axisTensor = kernelCreationContext.GetConstantInputTensor(1); - ReadScalarTensorData(axisTensor, /*out*/ &rawAxisBytes, sizeof(rawAxisBytes)); - onnxAxis = gsl::narrow_cast(ReadAsInt64(axisTensor.GetTensorDataType(), /*out*/ &rawAxisBytes)); + ReadScalarTensorData(axisTensor, /*out*/ tensorBytes, sizeof(tensorBytes)); + onnxAxis = gsl::narrow_cast(ReadAsInt64(axisTensor.GetTensorDataType(), /*out*/ tensorBytes)); } uint32_t dmlAxis = GetDmlAdjustedAxis(onnxAxis, kernelCreationContext, m_inputTensorDescs.front().GetDimensionCount()); diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorElementWise.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorElementWise.cpp index d68c270ad3..bbbb8f2e59 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorElementWise.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorElementWise.cpp @@ -404,10 +404,10 @@ public: std::vector> m_compiledOperators; }; -class DmlOperatorElementwiseClip : public DmlOperator +class DmlOperatorElementwiseClip7 : public DmlOperator { public: - DmlOperatorElementwiseClip(const MLOperatorKernelCreationContext& kernelInfo) : DmlOperator(kernelInfo) + DmlOperatorElementwiseClip7(const MLOperatorKernelCreationContext& kernelInfo) : DmlOperator(kernelInfo) { ML_CHECK_VALID_ARGUMENT(kernelInfo.GetInputCount() == 1); ML_CHECK_VALID_ARGUMENT(kernelInfo.GetOutputCount() == 1); @@ -427,6 +427,42 @@ public: } }; +class DmlOperatorElementwiseClip11 : public DmlOperator +{ +public: + DmlOperatorElementwiseClip11(const MLOperatorKernelCreationContext& kernelInfo) : DmlOperator(kernelInfo) + { + ML_CHECK_VALID_ARGUMENT(kernelInfo.GetInputCount() >= 1 && kernelInfo.GetInputCount() <= 3); + ML_CHECK_VALID_ARGUMENT(kernelInfo.GetOutputCount() == 1); + + std::vector> inputIndices = {0}; // min and max (1 and 2) are CPU-bound. + std::vector> outputIndices = {0}; + DmlOperator::Initialize(kernelInfo, inputIndices, outputIndices, kernelInfo.GetTensorShapeDescription().GetOutputTensorShape(0)); + + std::vector inputDescs = GetDmlInputDescs(); + std::vector outputDescs = GetDmlOutputDescs(); + + float minValue = -FLT_MAX; + float maxValue = FLT_MAX; + if (kernelInfo.IsInputValid(1)) + { + minValue = ReadScalarTensorAsFloat64(kernelInfo.GetConstantInputTensor(1)); + } + if (kernelInfo.IsInputValid(2)) + { + maxValue = ReadScalarTensorAsFloat64(kernelInfo.GetConstantInputTensor(2)); + } + + DML_ELEMENT_WISE_CLIP_OPERATOR_DESC opDesc = {}; + opDesc.InputTensor = inputDescs.data(); + opDesc.OutputTensor = outputDescs.data(); + opDesc.Min = minValue; + opDesc.Max = maxValue; + + SetDmlOperatorDesc({ DML_OPERATOR_ELEMENT_WISE_CLIP, &opDesc}, kernelInfo); + } +}; + class DmlOperatorElementwisePow : public DmlOperator { public: @@ -681,7 +717,8 @@ DML_OP_DEFINE_CREATION_FUNCTION(Max, DmlOperatorElementwiseBinaryLo DML_OP_DEFINE_CREATION_FUNCTION(Mean, DmlOperatorElementwiseMean); // Operators with extra attributes: -DML_OP_DEFINE_CREATION_FUNCTION(Clip, DmlOperatorElementwiseClip); +DML_OP_DEFINE_CREATION_FUNCTION(Clip7, DmlOperatorElementwiseClip7); +DML_OP_DEFINE_CREATION_FUNCTION(Clip11, DmlOperatorElementwiseClip11); DML_OP_DEFINE_CREATION_FUNCTION(Pow, DmlOperatorElementwisePow); DML_OP_DEFINE_CREATION_FUNCTION(QuantizeLinear, DmlOperatorElementwiseQLinear); DML_OP_DEFINE_CREATION_FUNCTION(DequantizeLinear, DmlOperatorElementwiseQLinear); diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp index 1dc7727749..a3770ca2fa 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp @@ -113,7 +113,8 @@ DML_OP_EXTERN_CREATION_FUNCTION(Log); DML_OP_EXTERN_CREATION_FUNCTION(Abs); DML_OP_EXTERN_CREATION_FUNCTION(Ceil); DML_OP_EXTERN_CREATION_FUNCTION(Floor); -DML_OP_EXTERN_CREATION_FUNCTION(Clip); +DML_OP_EXTERN_CREATION_FUNCTION(Clip7); +DML_OP_EXTERN_CREATION_FUNCTION(Clip11); DML_OP_EXTERN_CREATION_FUNCTION(Greater); DML_OP_EXTERN_CREATION_FUNCTION(Less); DML_OP_EXTERN_CREATION_FUNCTION(Equal); @@ -329,8 +330,8 @@ const static OperatorRegistrationInformation operatorRegistrationInformationTabl {REG_INFO( 7, Concat, typeNameListDefault, supportedTypeListNumericDefault, DmGraphSupport::Supported)}, {REG_INFO( 11, Concat, typeNameListDefault, supportedTypeListNumericDefault, DmGraphSupport::Supported)}, // Adds negative axis. {REG_INFO_VER( 7, Slice, typeNameListDefault, supportedTypeListNumericDefault, DmGraphSupport::Supported)}, - {REG_INFO_VER( 10, Slice, typeNameListDefault, supportedTypeListNumericDefault, DmGraphSupport::Supported, {1, 2, 3}, std::nullopt, QuerySlice)}, - {REG_INFO_VER( 11, Slice, typeNameListDefault, supportedTypeListNumericDefault, DmGraphSupport::Supported, {1, 2, 3}, std::nullopt, QuerySlice)}, // Adds negative axes. + {REG_INFO_VER( 10, Slice, typeNameListDefault, supportedTypeListNumericDefault, DmGraphSupport::Supported, {1, 2, 3}, std::nullopt, QuerySlice)}, + {REG_INFO_VER( 11, Slice, typeNameListDefault, supportedTypeListNumericDefault, DmGraphSupport::Supported, {1, 2, 3}, std::nullopt, QuerySlice)}, // Adds negative axes. {REG_INFO( 7, Pad, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, #if 0 // TODO:DwayneR Pads and Value are inputs. https://github.com/onnx/onnx/blob/master/docs/Changelog.md#Pad-11 {REG_INFO( 11, Pad, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, @@ -341,7 +342,7 @@ const static OperatorRegistrationInformation operatorRegistrationInformationTabl // TODO:Dwayner https://microsoft.visualstudio.com/OS/_workitems/edit/24672169 {REG_INFO( 11, DepthToSpace, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, #endif - {REG_INFO( 7, Tile, typeNameListDefault, supportedTypeListNumericDefault, DmGraphSupport::Supported, {1})}, + {REG_INFO( 7, Tile, typeNameListDefault, supportedTypeListNumericDefault, DmGraphSupport::Supported, {1})}, {REG_INFO( 8, Expand, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported, {1})}, {REG_INFO( 9, ConstantOfShape, typeNameListConstantOfShape, supportedTypeListConstantOfShape, DmGraphSupport::NotSupported, {0})}, {REG_INFO( 7, Gather, typeNameListScatterGather, supportedTypeListScatterGather, DmGraphSupport::Supported)}, @@ -370,10 +371,8 @@ const static OperatorRegistrationInformation operatorRegistrationInformationTabl {REG_INFO( 7, Abs, typeNameListDefault, supportedTypeListNumericDefault, DmGraphSupport::Supported)}, {REG_INFO( 7, Ceil, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, {REG_INFO( 7, Floor, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, - {REG_INFO( 7, Clip, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, -#if 0 // TODO:DwayneR https://microsoft.visualstudio.com/OS/_workitems/edit/24674103 - {REG_INFO( 11, Clip, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, -#endif + {REG_INFO_VER( 7, Clip, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, + {REG_INFO_VER( 11, Clip, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported, {1,2})}, {REG_INFO( 7, Add, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, {REG_INFO( 7, Sub, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, {REG_INFO( 7, Mul, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, diff --git a/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.cpp b/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.cpp index 24340b911e..2a17a8e288 100644 --- a/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.cpp +++ b/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.cpp @@ -107,6 +107,20 @@ namespace OperatorHelper memcpy(data, tensor.GetByteData(), elementByteSize); } + int64_t ReadScalarTensorAsInt64(const MLOperatorTensor& tensor) + { + std::byte tensorBytes[8]; + ReadScalarTensorData(tensor, /*out*/ &tensorBytes, sizeof(tensorBytes)); + return ReadAsInt64(tensor.GetTensorDataType(), &tensorBytes); + } + + double ReadScalarTensorAsFloat64(const MLOperatorTensor& tensor) + { + std::byte tensorBytes[8]; + ReadScalarTensorData(tensor, /*out*/ &tensorBytes, sizeof(tensorBytes)); + return ReadAsFloat64(tensor.GetTensorDataType(), &tensorBytes); + } + // Calculates the spatial dimensions from input dimensions and a kernel. The non-spatial (leading) // dimensions will be initialized to match the input dimensions. This assumes the spatial dimensions // are ordered such that they are at the end (e.g. NCHW or NCDHW). @@ -1312,7 +1326,7 @@ namespace OperatorHelper double start = ReadAsFloat64(m_tensorDataType, &m_valueStart); double limit = ReadAsFloat64(m_tensorDataType, &m_valueLimit); double delta = ReadAsFloat64(m_tensorDataType, &m_valueDelta); - totalElementCount = gsl::narrow_cast(ceil((limit - start) / delta)); + totalElementCount = gsl::narrow_cast(std::max(ceil((limit - start) / delta), 0.0)); } else { @@ -1320,7 +1334,7 @@ namespace OperatorHelper int64_t limit = ReadAsInt64(m_tensorDataType, &m_valueLimit); int64_t delta = ReadAsInt64(m_tensorDataType, &m_valueDelta); int64_t range = limit - start; - totalElementCount = gsl::narrow_cast((range / delta) + (range % delta != 0)); + totalElementCount = gsl::narrow_cast(std::max((range / delta) + (range % delta != 0), int64_t(0))); } m_outputDimensions.push_back(totalElementCount); } diff --git a/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.h b/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.h index 44a15abc79..585011ff91 100644 --- a/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.h +++ b/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.h @@ -77,7 +77,9 @@ void RemoveValuesByIndex(gsl::span indices, bool keepOneValue, / int64_t ReadAsInt64(MLOperatorTensorDataType tensorDataType, const void* p); double ReadAsFloat64(MLOperatorTensorDataType tensorDataType, const void* p); -void ReadScalarTensorData(const MLOperatorTensor& tensor, void* data, size_t dataByteSize); +void ReadScalarTensorData(const MLOperatorTensor& tensor, /*out*/ void* data, size_t dataByteSize); +int64_t ReadScalarTensorAsInt64(const MLOperatorTensor& tensor); +double ReadScalarTensorAsFloat64(const MLOperatorTensor& tensor); class EdgeShapes { public: @@ -1220,7 +1222,7 @@ protected: std::vector m_outputDimensions; MLOperatorTensorDataType m_tensorDataType = MLOperatorTensorDataType::Undefined; - using TensorScalarData = typename std::aligned_storage::type; + using TensorScalarData = typename std::aligned_storage_t; TensorScalarData m_valueStart; TensorScalarData m_valueLimit; TensorScalarData m_valueDelta; @@ -1322,7 +1324,8 @@ using ShapeInferenceHelper_Log = GetOutputShapeAsInputShapeHelper; using ShapeInferenceHelper_Abs = GetOutputShapeAsInputShapeHelper; using ShapeInferenceHelper_Ceil = GetOutputShapeAsInputShapeHelper; using ShapeInferenceHelper_Floor = GetOutputShapeAsInputShapeHelper; -using ShapeInferenceHelper_Clip = GetOutputShapeAsInputShapeHelper; +using ShapeInferenceHelper_Clip7 = GetOutputShapeAsInputShapeHelper; +using ShapeInferenceHelper_Clip11 = GetOutputShapeAsInputShapeHelper; using ShapeInferenceHelper_Greater = GetBroadcastedOutputShapeHelper; using ShapeInferenceHelper_Less = GetBroadcastedOutputShapeHelper; using ShapeInferenceHelper_Equal = GetBroadcastedOutputShapeHelper; From 5366273110bc7219970ee856d965713cbab5c54f Mon Sep 17 00:00:00 2001 From: Dwayne Robinson Date: Tue, 24 Mar 2020 18:02:39 -0700 Subject: [PATCH 06/12] Fix GatherND and ScatterND. --- .../src/External/DirectMLHelpers/ApiTraits.h | 47 +++++++- .../External/DirectMLHelpers/DirectMLSchema.h | 47 ++++++++ .../DirectMLHelpers/GeneratedSchemaHelpers.h | 45 ++++++++ .../src/Operators/DmlOperatorGather.cpp | 78 ++++++++++++- .../src/Operators/DmlOperatorScatter.cpp | 50 +++++++- .../src/Operators/OperatorRegistration.cpp | 6 +- .../OperatorAuthorHelper/OperatorHelper.cpp | 108 +++--------------- .../dml/OperatorAuthorHelper/OperatorHelper.h | 40 +------ .../OperatorRegistration.h | 1 + 9 files changed, 286 insertions(+), 136 deletions(-) diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/External/DirectMLHelpers/ApiTraits.h b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/External/DirectMLHelpers/ApiTraits.h index 666dc9c0f1..4847bc4d8a 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/External/DirectMLHelpers/ApiTraits.h +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/External/DirectMLHelpers/ApiTraits.h @@ -25,7 +25,7 @@ struct EnumTraits template <> struct EnumTraits { - static constexpr auto ValueCount = 107; + static constexpr auto ValueCount = 110; static constexpr size_t ActivationFunctionCount = 19; }; @@ -688,6 +688,24 @@ struct OperatorDescTraits static constexpr DML_OPERATOR_TYPE Type = DML_OPERATOR_REVERSE_SUBSEQUENCES; }; +template <> +struct OperatorDescTraits +{ + static constexpr DML_OPERATOR_TYPE Type = DML_OPERATOR_GATHER_ELEMENTS; +}; + +template <> +struct OperatorDescTraits +{ + static constexpr DML_OPERATOR_TYPE Type = DML_OPERATOR_GATHER_ND; +}; + +template <> +struct OperatorDescTraits +{ + static constexpr DML_OPERATOR_TYPE Type = DML_OPERATOR_SCATTER_ND; +}; + template <> struct OperatorDescTraits { @@ -1330,6 +1348,24 @@ struct OperatorTypeTraits<(DML_OPERATOR_TYPE)DML_OPERATOR_REVERSE_SUBSEQUENCES> using DescType = DML_REVERSE_SUBSEQUENCES_OPERATOR_DESC; }; +template <> +struct OperatorTypeTraits<(DML_OPERATOR_TYPE)DML_OPERATOR_GATHER_ELEMENTS> +{ + using DescType = DML_GATHER_ELEMENTS_OPERATOR_DESC; +}; + +template <> +struct OperatorTypeTraits<(DML_OPERATOR_TYPE)DML_OPERATOR_GATHER_ND> +{ + using DescType = DML_GATHER_ND_OPERATOR_DESC; +}; + +template <> +struct OperatorTypeTraits<(DML_OPERATOR_TYPE)DML_OPERATOR_SCATTER_ND> +{ + using DescType = DML_SCATTER_ND_OPERATOR_DESC; +}; + template <> struct OperatorTypeTraits<(DML_OPERATOR_TYPE)DML_OPERATOR_ACTIVATION_ELU> { @@ -1631,6 +1667,12 @@ auto OperatorTypeVisitor(DML_OPERATOR_TYPE type, Visitor&& visitor, Ts&&... args return std::invoke(std::forward(visitor), DML_CUMULATIVE_SUMMATION_OPERATOR_DESC{}, std::forward(args)...); case DML_OPERATOR_REVERSE_SUBSEQUENCES: return std::invoke(std::forward(visitor), DML_REVERSE_SUBSEQUENCES_OPERATOR_DESC{}, std::forward(args)...); + case DML_OPERATOR_GATHER_ELEMENTS: + return std::invoke(std::forward(visitor), DML_GATHER_ELEMENTS_OPERATOR_DESC{}, std::forward(args)...); + case DML_OPERATOR_GATHER_ND: + return std::invoke(std::forward(visitor), DML_GATHER_ND_OPERATOR_DESC{}, std::forward(args)...); + case DML_OPERATOR_SCATTER_ND: + return std::invoke(std::forward(visitor), DML_SCATTER_ND_OPERATOR_DESC{}, std::forward(args)...); case DML_OPERATOR_ACTIVATION_ELU: return std::invoke(std::forward(visitor), DML_ACTIVATION_ELU_OPERATOR_DESC{}, std::forward(args)...); case DML_OPERATOR_ACTIVATION_HARDMAX: @@ -1768,6 +1810,9 @@ inline gsl::czstring ToString(DML_OPERATOR_TYPE value) case DML_OPERATOR_FILL_VALUE_SEQUENCE: return "DML_OPERATOR_FILL_VALUE_SEQUENCE"; case DML_OPERATOR_CUMULATIVE_SUMMATION: return "DML_OPERATOR_CUMULATIVE_SUMMATION"; case DML_OPERATOR_REVERSE_SUBSEQUENCES: return "DML_OPERATOR_REVERSE_SUBSEQUENCES"; + case DML_OPERATOR_GATHER_ELEMENTS: return "DML_OPERATOR_GATHER_ELEMENTS"; + case DML_OPERATOR_GATHER_ND: return "DML_OPERATOR_GATHER_ND"; + case DML_OPERATOR_SCATTER_ND: return "DML_OPERATOR_SCATTER_ND"; default: assert(false); return ""; 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 b95fbfc95c..ff2a5e0fbd 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/External/DirectMLHelpers/DirectMLSchema.h +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/External/DirectMLHelpers/DirectMLSchema.h @@ -1393,6 +1393,53 @@ constexpr DML_OPERATOR_SCHEMA DML_REVERSE_SUBSEQUENCES_OPERATOR_SCHEMA { DML_REVERSE_SUBSEQUENCES_OPERATOR_SCHEMA_FIELDS, }; +constexpr DML_SCHEMA_FIELD DML_GATHER_ELEMENTS_OPERATOR_SCHEMA_FIELDS[4] { + DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_INPUT_TENSOR, DML_SCHEMA_FIELD_TYPE_TENSOR_DESC, "InputTensor", false }, + DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_INPUT_TENSOR, DML_SCHEMA_FIELD_TYPE_TENSOR_DESC, "IndicesTensor", false }, + DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_OUTPUT_TENSOR, DML_SCHEMA_FIELD_TYPE_TENSOR_DESC, "OutputTensor", false }, + DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_ATTRIBUTE, DML_SCHEMA_FIELD_TYPE_UINT, "Axis", false }, +}; + +constexpr DML_OPERATOR_SCHEMA DML_GATHER_ELEMENTS_OPERATOR_SCHEMA { + "DML_OPERATOR_GATHER_ELEMENTS", + DML_OPERATOR_GATHER_ELEMENTS, + DML_SCHEMA_OPERATOR_SUPPORT_FLAG_NONE, + 4, + DML_GATHER_ELEMENTS_OPERATOR_SCHEMA_FIELDS, +}; + +constexpr DML_SCHEMA_FIELD DML_GATHER_ND_OPERATOR_SCHEMA_FIELDS[5] { + DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_INPUT_TENSOR, DML_SCHEMA_FIELD_TYPE_TENSOR_DESC, "InputTensor", false }, + DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_INPUT_TENSOR, DML_SCHEMA_FIELD_TYPE_TENSOR_DESC, "IndicesTensor", false }, + DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_OUTPUT_TENSOR, DML_SCHEMA_FIELD_TYPE_TENSOR_DESC, "OutputTensor", false }, + DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_ATTRIBUTE, DML_SCHEMA_FIELD_TYPE_UINT, "InputDimensionCount", false }, + DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_ATTRIBUTE, DML_SCHEMA_FIELD_TYPE_UINT, "IndicesDimensionCount", false }, +}; + +constexpr DML_OPERATOR_SCHEMA DML_GATHER_ND_OPERATOR_SCHEMA { + "DML_OPERATOR_GATHER_ND", + DML_OPERATOR_GATHER_ND, + DML_SCHEMA_OPERATOR_SUPPORT_FLAG_NONE, + 5, + DML_GATHER_ND_OPERATOR_SCHEMA_FIELDS, +}; + +constexpr DML_SCHEMA_FIELD DML_SCATTER_ND_OPERATOR_SCHEMA_FIELDS[6] { + DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_INPUT_TENSOR, DML_SCHEMA_FIELD_TYPE_TENSOR_DESC, "InputTensor", false }, + DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_INPUT_TENSOR, DML_SCHEMA_FIELD_TYPE_TENSOR_DESC, "IndicesTensor", false }, + DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_INPUT_TENSOR, DML_SCHEMA_FIELD_TYPE_TENSOR_DESC, "UpdatesTensor", false }, + DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_OUTPUT_TENSOR, DML_SCHEMA_FIELD_TYPE_TENSOR_DESC, "OutputTensor", false }, + DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_ATTRIBUTE, DML_SCHEMA_FIELD_TYPE_UINT, "InputDimensionCount", false }, + DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_ATTRIBUTE, DML_SCHEMA_FIELD_TYPE_UINT, "IndicesDimensionCount", false }, +}; + +constexpr DML_OPERATOR_SCHEMA DML_SCATTER_ND_OPERATOR_SCHEMA { + "DML_OPERATOR_SCATTER_ND", + DML_OPERATOR_SCATTER_ND, + DML_SCHEMA_OPERATOR_SUPPORT_FLAG_NONE, + 6, + DML_SCATTER_ND_OPERATOR_SCHEMA_FIELDS, +}; constexpr DML_SCHEMA_FIELD DML_ACTIVATION_ELU_OPERATOR_SCHEMA_FIELDS[3] { DML_SCHEMA_FIELD { DML_SCHEMA_FIELD_KIND_INPUT_TENSOR, DML_SCHEMA_FIELD_TYPE_TENSOR_DESC, "InputTensor", false }, diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/External/DirectMLHelpers/GeneratedSchemaHelpers.h b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/External/DirectMLHelpers/GeneratedSchemaHelpers.h index d565590ece..04411a94fe 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/External/DirectMLHelpers/GeneratedSchemaHelpers.h +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/External/DirectMLHelpers/GeneratedSchemaHelpers.h @@ -822,6 +822,36 @@ inline std::vector GetFields(const DML_REVERSE_SUBSEQUENCES_OPERA OperatorField(&DML_REVERSE_SUBSEQUENCES_OPERATOR_SCHEMA.Fields[3], ToOperatorFieldType(static_cast(desc.Axis))), }; } +inline std::vector GetFields(const DML_GATHER_ELEMENTS_OPERATOR_DESC& desc) +{ + return { + OperatorField(&DML_GATHER_ELEMENTS_OPERATOR_SCHEMA.Fields[0], ToOperatorFieldType(static_cast(desc.InputTensor))), + OperatorField(&DML_GATHER_ELEMENTS_OPERATOR_SCHEMA.Fields[1], ToOperatorFieldType(static_cast(desc.IndicesTensor))), + OperatorField(&DML_GATHER_ELEMENTS_OPERATOR_SCHEMA.Fields[2], ToOperatorFieldType(static_cast(desc.OutputTensor))), + OperatorField(&DML_GATHER_ELEMENTS_OPERATOR_SCHEMA.Fields[3], ToOperatorFieldType(static_cast(desc.Axis))), + }; +} +inline std::vector GetFields(const DML_GATHER_ND_OPERATOR_DESC& desc) +{ + return { + OperatorField(&DML_GATHER_ND_OPERATOR_SCHEMA.Fields[0], ToOperatorFieldType(static_cast(desc.InputTensor))), + OperatorField(&DML_GATHER_ND_OPERATOR_SCHEMA.Fields[1], ToOperatorFieldType(static_cast(desc.IndicesTensor))), + OperatorField(&DML_GATHER_ND_OPERATOR_SCHEMA.Fields[2], ToOperatorFieldType(static_cast(desc.OutputTensor))), + OperatorField(&DML_GATHER_ND_OPERATOR_SCHEMA.Fields[3], ToOperatorFieldType(static_cast(desc.InputDimensionCount))), + OperatorField(&DML_GATHER_ND_OPERATOR_SCHEMA.Fields[4], ToOperatorFieldType(static_cast(desc.IndicesDimensionCount))), + }; +} +inline std::vector GetFields(const DML_SCATTER_ND_OPERATOR_DESC& desc) +{ + return { + OperatorField(&DML_SCATTER_ND_OPERATOR_SCHEMA.Fields[0], ToOperatorFieldType(static_cast(desc.InputTensor))), + OperatorField(&DML_SCATTER_ND_OPERATOR_SCHEMA.Fields[1], ToOperatorFieldType(static_cast(desc.IndicesTensor))), + OperatorField(&DML_SCATTER_ND_OPERATOR_SCHEMA.Fields[2], ToOperatorFieldType(static_cast(desc.UpdatesTensor))), + OperatorField(&DML_SCATTER_ND_OPERATOR_SCHEMA.Fields[3], ToOperatorFieldType(static_cast(desc.OutputTensor))), + OperatorField(&DML_SCATTER_ND_OPERATOR_SCHEMA.Fields[4], ToOperatorFieldType(static_cast(desc.InputDimensionCount))), + OperatorField(&DML_SCATTER_ND_OPERATOR_SCHEMA.Fields[5], ToOperatorFieldType(static_cast(desc.IndicesDimensionCount))), + }; +} inline std::vector GetFields(const DML_ACTIVATION_ELU_OPERATOR_DESC& desc) { return { @@ -1064,6 +1094,9 @@ inline const DML_OPERATOR_SCHEMA& GetSchema(DML_OPERATOR_TYPE operatorType) case DML_OPERATOR_FILL_VALUE_SEQUENCE: return DML_FILL_VALUE_SEQUENCE_OPERATOR_SCHEMA; case DML_OPERATOR_CUMULATIVE_SUMMATION: return DML_CUMULATIVE_SUMMATION_OPERATOR_SCHEMA; case DML_OPERATOR_REVERSE_SUBSEQUENCES: return DML_REVERSE_SUBSEQUENCES_OPERATOR_SCHEMA; + case DML_OPERATOR_GATHER_ELEMENTS: return DML_GATHER_ELEMENTS_OPERATOR_SCHEMA; + case DML_OPERATOR_GATHER_ND: return DML_GATHER_ND_OPERATOR_SCHEMA; + case DML_OPERATOR_SCATTER_ND: return DML_SCATTER_ND_OPERATOR_SCHEMA; case DML_OPERATOR_ACTIVATION_ELU: return DML_ACTIVATION_ELU_OPERATOR_SCHEMA; case DML_OPERATOR_ACTIVATION_HARDMAX: return DML_ACTIVATION_HARDMAX_OPERATOR_SCHEMA; case DML_OPERATOR_ACTIVATION_HARD_SIGMOID: return DML_ACTIVATION_HARD_SIGMOID_OPERATOR_SCHEMA; @@ -1440,6 +1473,18 @@ inline AbstractOperatorDesc ConvertOperatorDesc(const DML_OPERATOR_DESC& opDesc) return AbstractOperatorDesc( &DML_REVERSE_SUBSEQUENCES_OPERATOR_SCHEMA, GetFields(*static_cast(opDesc.Desc))); + case DML_OPERATOR_GATHER_ELEMENTS: + return AbstractOperatorDesc( + &DML_GATHER_ELEMENTS_OPERATOR_SCHEMA, + GetFields(*static_cast(opDesc.Desc))); + case DML_OPERATOR_GATHER_ND: + return AbstractOperatorDesc( + &DML_GATHER_ND_OPERATOR_SCHEMA, + GetFields(*static_cast(opDesc.Desc))); + case DML_OPERATOR_SCATTER_ND: + return AbstractOperatorDesc( + &DML_SCATTER_ND_OPERATOR_SCHEMA, + GetFields(*static_cast(opDesc.Desc))); case DML_OPERATOR_ACTIVATION_ELU: return AbstractOperatorDesc( &DML_ACTIVATION_ELU_OPERATOR_SCHEMA, diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorGather.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorGather.cpp index 01dd7379d3..54ef525b46 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorGather.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorGather.cpp @@ -43,9 +43,81 @@ public: } }; +class DmlOperatorGatherElements : public DmlOperator +{ +public: + DmlOperatorGatherElements(const MLOperatorKernelCreationContext& kernelCreationContext) + : DmlOperator(kernelCreationContext) + { + ML_CHECK_VALID_ARGUMENT(kernelCreationContext.GetInputCount() == 2, "GatherElements expects 2 inputs."); + ML_CHECK_VALID_ARGUMENT(kernelCreationContext.GetOutputCount() == 1, "GatherElements expects 1 output."); + + DmlOperator::Initialize(kernelCreationContext); + + std::vector inputDescs = GetDmlInputDescs(); + std::vector outputDescs = GetDmlOutputDescs(); + assert(inputDescs.size() == 2); + assert(outputDescs.size() == 1); + + m_inputTensorDescs[1].ForceUnsignedDataType(); + + int32_t signedOnnxAxis = kernelCreationContext.GetOptionalAttribute(AttrName::Axis, 0); + auto outputTensorShapeDescription = kernelCreationContext.GetTensorShapeDescription(); + std::vector dataDimensions = outputTensorShapeDescription.GetInputTensorShape(0); + std::vector indicesDimensions = outputTensorShapeDescription.GetInputTensorShape(1); + ML_CHECK_VALID_ARGUMENT(dataDimensions.size() <= OperatorHelper::NchwDimensionCount); + uint32_t dmlAxis = GetDmlAdjustedAxis(signedOnnxAxis, kernelCreationContext, m_inputTensorDescs.front().GetDimensionCount()); + + DML_GATHER_ELEMENTS_OPERATOR_DESC operatorDesc = {}; + operatorDesc.InputTensor = &inputDescs[0]; + operatorDesc.IndicesTensor = &inputDescs[1]; + operatorDesc.OutputTensor = outputDescs.data(); + operatorDesc.Axis = dmlAxis; + + DML_OPERATOR_DESC opDesc = { DML_OPERATOR_GATHER_ELEMENTS, &operatorDesc }; + SetDmlOperatorDesc(opDesc, kernelCreationContext); + } +}; + +class DmlOperatorGatherNd : public DmlOperator, public GatherNdHelper +{ +public: + DmlOperatorGatherNd(const MLOperatorKernelCreationContext& kernelCreationContext) + : DmlOperator(kernelCreationContext), + GatherNdHelper(kernelCreationContext, kernelCreationContext.GetTensorShapeDescription()) + { + ML_CHECK_VALID_ARGUMENT(kernelCreationContext.GetInputCount() == 2, "GatherND expects 2 inputs."); + ML_CHECK_VALID_ARGUMENT(kernelCreationContext.GetOutputCount() == 1, "GatherND expects 1 output."); + + DmlOperator::Initialize(kernelCreationContext); + + std::vector inputDescs = GetDmlInputDescs(); + std::vector outputDescs = GetDmlOutputDescs(); + assert(inputDescs.size() == 2); + assert(outputDescs.size() == 1); + + m_inputTensorDescs[1].ForceUnsignedDataType(); + + auto outputTensorShapeDescription = kernelCreationContext.GetTensorShapeDescription(); + std::vector dataDimensions = outputTensorShapeDescription.GetInputTensorShape(0); + std::vector indicesDimensions = outputTensorShapeDescription.GetInputTensorShape(1); + ML_CHECK_VALID_ARGUMENT(dataDimensions.size() <= OperatorHelper::NchwDimensionCount); + ML_CHECK_VALID_ARGUMENT(indicesDimensions.size() <= OperatorHelper::NchwDimensionCount); + + DML_GATHER_ND_OPERATOR_DESC operatorDesc = {}; + operatorDesc.InputTensor = &inputDescs[0]; + operatorDesc.IndicesTensor = &inputDescs[1]; + operatorDesc.OutputTensor = outputDescs.data(); + operatorDesc.InputDimensionCount = static_cast(dataDimensions.size()); + operatorDesc.IndicesDimensionCount = static_cast(indicesDimensions.size()); + + DML_OPERATOR_DESC opDesc = { DML_OPERATOR_GATHER_ND, &operatorDesc }; + SetDmlOperatorDesc(opDesc, kernelCreationContext); + } +}; + DML_OP_DEFINE_CREATION_FUNCTION(Gather, DmlOperatorGather); -// TODO::: -DML_OP_DEFINE_CREATION_FUNCTION(GatherElements, DmlOperatorGather); -DML_OP_DEFINE_CREATION_FUNCTION(GatherND, DmlOperatorGather); +DML_OP_DEFINE_CREATION_FUNCTION(GatherElements, DmlOperatorGatherElements); +DML_OP_DEFINE_CREATION_FUNCTION(GatherND, DmlOperatorGatherNd); } // namespace Dml diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorScatter.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorScatter.cpp index 97b881d542..b9dfef8ba3 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorScatter.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorScatter.cpp @@ -19,7 +19,7 @@ public: std::vector dataDimensions = tensorShapeDescription.GetInputTensorShape(0); std::vector indicesDimensions = tensorShapeDescription.GetInputTensorShape(1); std::vector updatesDimensions = tensorShapeDescription.GetInputTensorShape(2); - std::vector outputDimensions = tensorShapeDescription.GetInputTensorShape(0); + std::vector outputDimensions = tensorShapeDescription.GetOutputTensorShape(0); ML_CHECK_VALID_ARGUMENT(dataDimensions == outputDimensions); ML_CHECK_VALID_ARGUMENT(indicesDimensions == updatesDimensions); ML_CHECK_VALID_ARGUMENT(dataDimensions.size() == indicesDimensions.size()); @@ -74,9 +74,51 @@ public: } }; -DML_OP_DEFINE_CREATION_FUNCTION(Scatter, DmlOperatorScatter); -// TODO::: +class DmlOperatorScatterNd : public DmlOperator +{ +public: + DmlOperatorScatterNd(const MLOperatorKernelCreationContext& kernelCreationContext) + : DmlOperator(kernelCreationContext) + { + ML_CHECK_VALID_ARGUMENT(kernelCreationContext.GetInputCount() == 3, "ScatterND expects 3 inputs."); + ML_CHECK_VALID_ARGUMENT(kernelCreationContext.GetOutputCount() == 1, "ScatterND expects 1 output."); + + auto tensorShapeDescription = kernelCreationContext.GetTensorShapeDescription(); + std::vector dataDimensions = tensorShapeDescription.GetInputTensorShape(0); + std::vector indicesDimensions = tensorShapeDescription.GetInputTensorShape(1); + std::vector updatesDimensions = tensorShapeDescription.GetInputTensorShape(2); + std::vector outputDimensions = tensorShapeDescription.GetOutputTensorShape(0); + ML_CHECK_VALID_ARGUMENT(dataDimensions == outputDimensions); + ML_CHECK_VALID_ARGUMENT(dataDimensions.size() <= OperatorHelper::NchwDimensionCount); + ML_CHECK_VALID_ARGUMENT(indicesDimensions.size() <= OperatorHelper::NchwDimensionCount); + ML_CHECK_VALID_ARGUMENT(updatesDimensions.size() <= OperatorHelper::NchwDimensionCount); + ML_CHECK_VALID_ARGUMENT(outputDimensions.size() <= OperatorHelper::NchwDimensionCount); + + DmlOperator::Initialize(kernelCreationContext); + + std::vector inputDescs = GetDmlInputDescs(); + std::vector outputDescs = GetDmlOutputDescs(); + assert(inputDescs.size() == 3); + assert(outputDescs.size() == 1); + + m_inputTensorDescs[1].ForceUnsignedDataType(); + + DML_SCATTER_ND_OPERATOR_DESC operatorDesc = {}; + operatorDesc.InputTensor = &inputDescs[0]; + operatorDesc.IndicesTensor = &inputDescs[1]; + operatorDesc.UpdatesTensor = &inputDescs[2]; + operatorDesc.OutputTensor = outputDescs.data(); + operatorDesc.InputDimensionCount = static_cast(dataDimensions.size()); + operatorDesc.IndicesDimensionCount = static_cast(indicesDimensions.size()); + + DML_OPERATOR_DESC opDesc = { DML_OPERATOR_SCATTER_ND, &operatorDesc }; + SetDmlOperatorDesc(opDesc, kernelCreationContext); + } +}; + +DML_OP_DEFINE_CREATION_FUNCTION(Scatter9, DmlOperatorScatter); +DML_OP_DEFINE_CREATION_FUNCTION(Scatter11, DmlOperatorScatter); DML_OP_DEFINE_CREATION_FUNCTION(ScatterElements, DmlOperatorScatter); -DML_OP_DEFINE_CREATION_FUNCTION(ScatterND, DmlOperatorScatter); +DML_OP_DEFINE_CREATION_FUNCTION(ScatterND, DmlOperatorScatterNd); } // namespace Dml diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp index a3770ca2fa..34066a6c88 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp @@ -202,7 +202,8 @@ DML_OP_EXTERN_CREATION_FUNCTION(Shrink); DML_OP_EXTERN_CREATION_FUNCTION(OneHot); DML_OP_EXTERN_CREATION_FUNCTION(EyeLike); DML_OP_EXTERN_CREATION_FUNCTION(MaxUnpool); -DML_OP_EXTERN_CREATION_FUNCTION(Scatter); +DML_OP_EXTERN_CREATION_FUNCTION(Scatter9); +DML_OP_EXTERN_CREATION_FUNCTION(Scatter11); DML_OP_EXTERN_CREATION_FUNCTION(Resize); DML_OP_EXTERN_CREATION_FUNCTION(ConstantOfShape); DML_OP_EXTERN_CREATION_FUNCTION(IsInf); @@ -346,7 +347,8 @@ const static OperatorRegistrationInformation operatorRegistrationInformationTabl {REG_INFO( 8, Expand, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported, {1})}, {REG_INFO( 9, ConstantOfShape, typeNameListConstantOfShape, supportedTypeListConstantOfShape, DmGraphSupport::NotSupported, {0})}, {REG_INFO( 7, Gather, typeNameListScatterGather, supportedTypeListScatterGather, DmGraphSupport::Supported)}, - {REG_INFO( 9, Scatter, typeNameListScatterGather, supportedTypeListScatterGather, DmGraphSupport::Supported)}, + {REG_INFO_VER( 9, Scatter, typeNameListScatterGather, supportedTypeListScatterGather, DmGraphSupport::Supported)}, + {REG_INFO_VER( 11, Scatter, typeNameListScatterGather, supportedTypeListScatterGather, DmGraphSupport::Supported)}, {REG_INFO( 9, EyeLike, typeNameListEyeLike, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, // Data reorganization that merely changes the dimensions while keeping the data identical. diff --git a/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.cpp b/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.cpp index 2a17a8e288..c18652f29f 100644 --- a/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.cpp +++ b/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.cpp @@ -355,8 +355,8 @@ namespace OperatorHelper std::vector GetOutputShapeAsInputShapeHelper::GetOutputShapes(const MLShapeInferenceContext& shapeInfo) const { - assert(shapeInfo.GetInputCount() >= 1); - std::vector outputDimensions = shapeInfo.GetInputTensorShape(0); + assert(shapeInfo.GetInputCount() > m_inputTensorIndex); + std::vector outputDimensions = shapeInfo.GetInputTensorShape(m_inputTensorIndex); return { std::move(outputDimensions) }; } @@ -591,102 +591,26 @@ namespace OperatorHelper return { EdgeShapes(std::move(outputDimensions)) }; } -// TODO::: - - void GatherNDHelper::Initialize( - const MLOperatorAttributes& operatorAttributes, - gsl::span inputDimensions - ) - { - int32_t signedOnnxAxis = operatorAttributes.GetOptionalAttribute(AttrName::Axis, 0); - uint32_t inputRank = gsl::narrow_cast(inputDimensions.size()); - m_axis = HandleNegativeAxis(signedOnnxAxis, inputRank); - } - - std::vector GatherNDHelper::GetOutputShapes(const MLShapeInferenceContext& shapeInfo) const + std::vector GatherNdHelper::GetOutputShapes(const MLShapeInferenceContext& shapeInfo) const { std::vector inputDimensions = shapeInfo.GetInputTensorShape(0); std::vector indicesDimensions = shapeInfo.GetInputTensorShape(1); + // Determine the number of output dimensions. ML_CHECK_VALID_ARGUMENT(inputDimensions.size() >= 1); - ML_CHECK_VALID_ARGUMENT(indicesDimensions.size() >= 0); - int outDimCount = gsl::narrow_cast(inputDimensions.size() + indicesDimensions.size() - 1); - ML_CHECK_VALID_ARGUMENT(outDimCount > 0 && outDimCount <= NchwDimensionCount); + ML_CHECK_VALID_ARGUMENT(indicesDimensions.size() >= 1); + const uint32_t numberOfCoordinatesPerIndex = indicesDimensions.back(); + ML_CHECK_VALID_ARGUMENT(inputDimensions.size() >= numberOfCoordinatesPerIndex); + const uint32_t numberOfOutputDimensionsFromInput = static_cast(inputDimensions.size()) - numberOfCoordinatesPerIndex; + const uint32_t numberOfOutputDimensionsFromIndices = static_cast(indicesDimensions.size()) - 1; // Strip off last dimension. + uint32_t outputDimensionCount = gsl::narrow_cast(numberOfOutputDimensionsFromIndices + numberOfOutputDimensionsFromInput); + ML_CHECK_VALID_ARGUMENT(outputDimensionCount > 0 && outputDimensionCount <= NchwDimensionCount); - std::vector outputDimensions(outDimCount, 1); - - // The input dimensions following the gather axis determine the final output dimensions. - int outputDim = outDimCount - 1; - int inputDim = gsl::narrow_cast(inputDimensions.size() - 1); - for (; inputDim > m_axis; --outputDim, --inputDim) - { - outputDimensions[outputDim] = inputDimensions[inputDim]; - } - - // The shape of the index tensor is reflected in the middle dimensions of the output tensor. - int indexDim = gsl::narrow_cast(indicesDimensions.size() - 1); - for (; indexDim >= 0; --outputDim, --indexDim) - { - outputDimensions[outputDim] = indicesDimensions[indexDim]; - } - - // The gather dimension is skipped for the purposes of sizing because the index values choose slices - // across it. Preceding input dimensions determine the shape of the output's leading dimensions. - inputDim = m_axis - 1; - for (; outputDim >= 0 && inputDim >= 0; --outputDim, --inputDim) - { - outputDimensions[outputDim] = inputDimensions[inputDim]; - } - - return { EdgeShapes(std::move(outputDimensions)) }; - } - -// TODO::: - - void ScatterNDHelper::Initialize( - const MLOperatorAttributes& operatorAttributes, - gsl::span inputDimensions - ) - { - int32_t signedOnnxAxis = operatorAttributes.GetOptionalAttribute(AttrName::Axis, 0); - uint32_t inputRank = gsl::narrow_cast(inputDimensions.size()); - m_axis = HandleNegativeAxis(signedOnnxAxis, inputRank); - } - - std::vector ScatterNDHelper::GetOutputShapes(const MLShapeInferenceContext& shapeInfo) const - { - std::vector inputDimensions = shapeInfo.GetInputTensorShape(0); - std::vector indicesDimensions = shapeInfo.GetInputTensorShape(1); - - ML_CHECK_VALID_ARGUMENT(inputDimensions.size() >= 1); - ML_CHECK_VALID_ARGUMENT(indicesDimensions.size() >= 0); - int outDimCount = gsl::narrow_cast(inputDimensions.size() + indicesDimensions.size() - 1); - ML_CHECK_VALID_ARGUMENT(outDimCount > 0 && outDimCount <= NchwDimensionCount); - - std::vector outputDimensions(outDimCount, 1); - - // The input dimensions following the gather axis determine the final output dimensions. - int outputDim = outDimCount - 1; - int inputDim = gsl::narrow_cast(inputDimensions.size() - 1); - for (; inputDim > m_axis; --outputDim, --inputDim) - { - outputDimensions[outputDim] = inputDimensions[inputDim]; - } - - // The shape of the index tensor is reflected in the middle dimensions of the output tensor. - int indexDim = gsl::narrow_cast(indicesDimensions.size() - 1); - for (; indexDim >= 0; --outputDim, --indexDim) - { - outputDimensions[outputDim] = indicesDimensions[indexDim]; - } - - // The gather dimension is skipped for the purposes of sizing because the index values choose slices - // across it. Preceding input dimensions determine the shape of the output's leading dimensions. - inputDim = m_axis - 1; - for (; outputDim >= 0 && inputDim >= 0; --outputDim, --inputDim) - { - outputDimensions[outputDim] = inputDimensions[inputDim]; - } + // Form the full expected size by concatenating the prefix part of the indices tensor shape + // with the suffix of the input tensor shape. + std::vector outputDimensions; + outputDimensions.assign(indicesDimensions.begin(), indicesDimensions.end() - 1); + outputDimensions.insert(outputDimensions.end(), inputDimensions.end() - numberOfOutputDimensionsFromInput, inputDimensions.end()); return { EdgeShapes(std::move(outputDimensions)) }; } diff --git a/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.h b/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.h index 585011ff91..5b8757199f 100644 --- a/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.h +++ b/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.h @@ -927,44 +927,15 @@ class GatherHelper { int m_axis = 0; }; -class GatherNDHelper { +class GatherNdHelper { public: - void Initialize( - const MLOperatorAttributes& operatorAttributes, - gsl::span dataDimensions - ); - // Info_t is used to obtain attributes which will be used for calculating the output shape later. // Shape_t is used to obtain input shape which will be used for adjusting attribute value. template - GatherNDHelper(const Info_t& info, const Shape_t& shape) { - Initialize(info, shape.GetInputTensorShape(0)); + GatherNdHelper(const Info_t& info, const Shape_t& shape) { } std::vector GetOutputShapes(const MLShapeInferenceContext& shapeInfo) const; - - protected: - int m_axis = 0; -}; - -class ScatterNDHelper { - public: - void Initialize( - const MLOperatorAttributes& operatorAttributes, - gsl::span dataDimensions - ); - - // Info_t is used to obtain attributes which will be used for calculating the output shape later. - // Shape_t is used to obtain input shape which will be used for adjusting attribute value. - template - ScatterNDHelper(const Info_t& info, const Shape_t& shape) { - Initialize(info, shape.GetInputTensorShape(0)); - } - - std::vector GetOutputShapes(const MLShapeInferenceContext& shapeInfo) const; - - protected: - int m_axis = 0; }; class PoolingHelperBase { @@ -1291,9 +1262,10 @@ using ShapeInferenceHelper_LSTM = RecurrentHelper; using ShapeInferenceHelper_Gather = GatherHelper; using ShapeInferenceHelper_GatherElements = GetOutputShapeAsSpecificInputShapeHelper<1>; using ShapeInferenceHelper_ScatterElements = GetOutputShapeAsInputShapeHelper; -using ShapeInferenceHelper_Scatter = ShapeInferenceHelper_ScatterElements; -using ShapeInferenceHelper_GatherND = GatherNDHelper; -using ShapeInferenceHelper_ScatterND = ScatterNDHelper; +using ShapeInferenceHelper_Scatter9 = ShapeInferenceHelper_ScatterElements; // Old deprecated alias for ScatterElements. +using ShapeInferenceHelper_Scatter11 = ShapeInferenceHelper_ScatterElements; // Old deprecated alias for ScatterElements. +using ShapeInferenceHelper_GatherND = GatherNdHelper; +using ShapeInferenceHelper_ScatterND = GetOutputShapeAsInputShapeHelper; using ShapeInferenceHelper_Flatten = FlattenHelper; using ShapeInferenceHelper_Split = SplitHelper; diff --git a/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorRegistration.h b/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorRegistration.h index 9d8cb743ea..5fda5b29fe 100644 --- a/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorRegistration.h +++ b/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorRegistration.h @@ -224,6 +224,7 @@ namespace OperatorHelper static const int sc_sinceVer_Resize = 11; static const int sc_sinceVer_Round = 11; static const int sc_sinceVer_Scan = 11; + static const int sc_sinceVer_Scatter = 11; // Deprecated alias static const int sc_sinceVer_ScatterElements = 11; static const int sc_sinceVer_ScatterND = 11; static const int sc_sinceVer_Slice = 11; From cc095fefbb884822cf809753548d358c7af348e4 Mon Sep 17 00:00:00 2001 From: Dwayne Robinson Date: Tue, 24 Mar 2020 23:24:58 -0700 Subject: [PATCH 07/12] Fix squeeze. --- .../src/MLOperatorAuthorImpl.cpp | 32 +++++++++++-------- .../src/Operators/OperatorRegistration.cpp | 10 +++--- .../OperatorAuthorHelper/OperatorHelper.cpp | 21 ++++++++++++ .../dml/OperatorAuthorHelper/OperatorHelper.h | 18 ++++++++--- 4 files changed, 59 insertions(+), 22 deletions(-) diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/MLOperatorAuthorImpl.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/MLOperatorAuthorImpl.cpp index 5df941e9ef..0c4e3fb9ea 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/MLOperatorAuthorImpl.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/MLOperatorAuthorImpl.cpp @@ -1508,7 +1508,7 @@ onnxruntime::Status AbiOpKernel::Compute(onnxruntime::OpKernelContext* context) { tensorWrapper = wil::MakeOrThrow( const_cast(tensor), - IsAllocationInterface(tensor->Location()), + tensor ? IsAllocationInterface(tensor->Location()) : false, winmlProviderCapture.Get(), internalOpCapture); } @@ -1552,21 +1552,27 @@ onnxruntime::Status AbiOpKernel::Compute(onnxruntime::OpKernelContext* context) m_constantInputTensorContentsOfKernel.resize(context->InputCount()); for (uint32_t index : m_requiredConstantCpuInputs) { - MLOperatorTensor tensor = MLOperatorTensor(constantInputGetter(index).Get()); + const onnxruntime::Tensor* weakTensor = context->Input(static_cast(index)); - if (index >= static_cast(context->InputCount())) { - continue; - } - m_constantInputTensorContentsOfKernel[index].isValid = (tensor.GetInterface() != nullptr); + // Skip optional constant tensors. + if (weakTensor != nullptr) + { + MLOperatorTensor tensor = MLOperatorTensor(constantInputGetter(index).Get()); - if (tensor.GetInterface() != nullptr) { - m_constantInputTensorContentsOfKernel[index].shape = tensor.GetShape(); - m_constantInputTensorContentsOfKernel[index].type = tensor.GetTensorDataType(); - m_constantInputTensorContentsOfKernel[index].data.resize(tensor.GetUnalignedTensorByteSize()); + if (index >= static_cast(context->InputCount())) { + continue; + } + m_constantInputTensorContentsOfKernel[index].isValid = (tensor.GetInterface() != nullptr); + + if (tensor.GetInterface() != nullptr) { + m_constantInputTensorContentsOfKernel[index].shape = tensor.GetShape(); + m_constantInputTensorContentsOfKernel[index].type = tensor.GetTensorDataType(); + m_constantInputTensorContentsOfKernel[index].data.resize(tensor.GetUnalignedTensorByteSize()); + } + m_constantInputTensorContentsOfKernel[index].data.assign( + reinterpret_cast(tensor.GetByteData()), + reinterpret_cast(tensor.GetByteData()) + tensor.GetUnalignedTensorByteSize()); } - m_constantInputTensorContentsOfKernel[index].data.assign( - reinterpret_cast(tensor.GetByteData()), - reinterpret_cast(tensor.GetByteData()) + tensor.GetUnalignedTensorByteSize()); } m_kernel = inferShapesAndCreateKernel(m_inputShapesOfKernelInference, m_inferredOutputShapes); diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp index 34066a6c88..cee4d219de 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp @@ -332,15 +332,17 @@ const static OperatorRegistrationInformation operatorRegistrationInformationTabl {REG_INFO( 11, Concat, typeNameListDefault, supportedTypeListNumericDefault, DmGraphSupport::Supported)}, // Adds negative axis. {REG_INFO_VER( 7, Slice, typeNameListDefault, supportedTypeListNumericDefault, DmGraphSupport::Supported)}, {REG_INFO_VER( 10, Slice, typeNameListDefault, supportedTypeListNumericDefault, DmGraphSupport::Supported, {1, 2, 3}, std::nullopt, QuerySlice)}, +#if 0 // TODO:DwayneR {REG_INFO_VER( 11, Slice, typeNameListDefault, supportedTypeListNumericDefault, DmGraphSupport::Supported, {1, 2, 3}, std::nullopt, QuerySlice)}, // Adds negative axes. +#endif {REG_INFO( 7, Pad, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, -#if 0 // TODO:DwayneR Pads and Value are inputs. https://github.com/onnx/onnx/blob/master/docs/Changelog.md#Pad-11 +#if 0 // TODO:NickFe Pads and Value are inputs. https://microsoft.visualstudio.com/OS/_workitems/edit/24674281, https://github.com/onnx/onnx/blob/master/docs/Changelog.md#Pad-11 {REG_INFO( 11, Pad, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, #endif {REG_INFO( 7, SpaceToDepth, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, {REG_INFO( 7, DepthToSpace, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, #if 0 - // TODO:Dwayner https://microsoft.visualstudio.com/OS/_workitems/edit/24672169 + // TODO:Dwayner Update operator DepthToSpace-11 - added column-row-depth shuffle order mode https://microsoft.visualstudio.com/OS/_workitems/edit/24672169 {REG_INFO( 11, DepthToSpace, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, #endif {REG_INFO( 7, Tile, typeNameListDefault, supportedTypeListNumericDefault, DmGraphSupport::Supported, {1})}, @@ -355,8 +357,6 @@ const static OperatorRegistrationInformation operatorRegistrationInformationTabl {REG_INFO_ID( 7, Identity, typeNameListDefault, supportedTypeListAllScalars, DmGraphSupport::Supported)}, {REG_INFO_ID( 7, Flatten, typeNameListDefault, supportedTypeListAllScalars, DmGraphSupport::Supported)}, {REG_INFO_ID( 9, Flatten, typeNameListDefault, supportedTypeListAllScalars, DmGraphSupport::Supported)}, - //!!!TODO:::DwayneR check remaining 11's for other work besides negative axes. - //Also verify that negative axes are handled. {REG_INFO_ID( 11, Flatten, typeNameListDefault, supportedTypeListAllScalars, DmGraphSupport::Supported)}, {REG_INFO_ID( 7, Squeeze, typeNameListDefault, supportedTypeListAllScalars, DmGraphSupport::Supported)}, {REG_INFO_ID( 11, Squeeze, typeNameListDefault, supportedTypeListAllScalars, DmGraphSupport::Supported)}, @@ -440,7 +440,7 @@ const static OperatorRegistrationInformation operatorRegistrationInformationTabl {REG_INFO( 7, Less, typeNameListLogicalComparison, supportedTypeListLogicalComparison7,DmGraphSupport::Supported)}, {REG_INFO( 9, Less, typeNameListLogicalComparison, supportedTypeListLogicalComparison9,DmGraphSupport::Supported)}, {REG_INFO( 7, Equal, typeNameListLogicalComparison, supportedTypeListLogicalComparison7,DmGraphSupport::Supported)}, - {REG_INFO( 11, Equal, typeNameListLogicalComparison, supportedTypeListLogicalComparison9,DmGraphSupport::Supported)}, + {REG_INFO( 11, Equal, typeNameListLogicalComparison, supportedTypeListLogicalComparison9,DmGraphSupport::Supported)}, {REG_INFO( 7, Not, typeNameListDefault, supportedTypeListBool, DmGraphSupport::Supported)}, {REG_INFO( 7, And, typeNameListDefault, supportedTypeListBool, DmGraphSupport::Supported)}, {REG_INFO( 7, Or, typeNameListDefault, supportedTypeListBool, DmGraphSupport::Supported)}, diff --git a/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.cpp b/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.cpp index c18652f29f..dbaf941203 100644 --- a/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.cpp +++ b/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.cpp @@ -1005,6 +1005,16 @@ namespace OperatorHelper return { std::move(EdgeShapes(outputDimensions)) }; } + void SqueezeHelper::Initialize( + gsl::span axes, + gsl::span inputDimensions + ) + { + m_axes.assign(axes.begin(), axes.end()); + HandleNegativeAxes(/*inout*/ m_axes, gsl::narrow_cast(inputDimensions.size())); + std::sort(m_axes.begin(), m_axes.end()); + } + std::vector SqueezeHelper::GetOutputShapes(const MLShapeInferenceContext& shapeInfo) const { auto outputDimensions = shapeInfo.GetInputTensorShape(0); @@ -1038,6 +1048,17 @@ namespace OperatorHelper return { std::move(outputDimensions) }; } + void UnsqueezeHelper::Initialize( + gsl::span axes, + gsl::span inputDimensions + ) + { + m_axes.assign(axes.begin(), axes.end()); + const uint32_t outputDimensionCount = gsl::narrow_cast(inputDimensions.size() + axes.size()); + HandleNegativeAxes(/*inout*/ m_axes, outputDimensionCount); + std::sort(m_axes.begin(), m_axes.end()); + } + std::vector UnsqueezeHelper::GetOutputShapes(const MLShapeInferenceContext& shapeInfo) const { auto inputDimensions = shapeInfo.GetInputTensorShape(0); diff --git a/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.h b/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.h index 5b8757199f..d63d3214cc 100644 --- a/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.h +++ b/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.h @@ -996,12 +996,17 @@ class RoiPoolingHelper { class SqueezeHelper { public: + void Initialize( + gsl::span axes, + gsl::span inputDimensions); + // Info_t is used to obtain attributes which will be used for calculating the output shape later. // Shape_t is used to obtain input shape which will be used for adjusting attribute value. template SqueezeHelper(const Info_t& info, const Shape_t& shape) { - m_axes = info.GetOptionalAttributeVectorInt32(AttrName::Axes); - std::sort(m_axes.begin(), m_axes.end()); + Initialize( + info.GetOptionalAttributeVectorInt32(AttrName::Axes), + shape.GetInputTensorShape(0)); } std::vector GetOutputShapes(const MLShapeInferenceContext& shapeInfo) const; @@ -1012,12 +1017,17 @@ class SqueezeHelper { class UnsqueezeHelper { public: + void Initialize( + gsl::span axes, + gsl::span inputDimensions); + // Info_t is used to obtain attributes which will be used for calculating the output shape later. // Shape_t is used to obtain input shape which will be used for adjusting attribute value. template UnsqueezeHelper(const Info_t& info, const Shape_t& shape) { - m_axes = info.GetOptionalAttributeVectorInt32(AttrName::Axes); - std::sort(m_axes.begin(), m_axes.end()); + Initialize( + info.GetOptionalAttributeVectorInt32(AttrName::Axes), + shape.GetInputTensorShape(0)); } std::vector GetOutputShapes(const MLShapeInferenceContext& shapeInfo) const; From 55d32085f615634f8e7230b076c0dd5fced9c553 Mon Sep 17 00:00:00 2001 From: Dwayne Robinson Date: Tue, 24 Mar 2020 23:37:37 -0700 Subject: [PATCH 08/12] Update comments. --- .../src/Operators/OperatorRegistration.cpp | 72 ++++++++----------- 1 file changed, 29 insertions(+), 43 deletions(-) diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp index cee4d219de..26ea3240a8 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp @@ -342,15 +342,20 @@ const static OperatorRegistrationInformation operatorRegistrationInformationTabl {REG_INFO( 7, SpaceToDepth, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, {REG_INFO( 7, DepthToSpace, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, #if 0 - // TODO:Dwayner Update operator DepthToSpace-11 - added column-row-depth shuffle order mode https://microsoft.visualstudio.com/OS/_workitems/edit/24672169 + // TODO:DwayneR Update operator DepthToSpace-11 - added column-row-depth shuffle order mode https://microsoft.visualstudio.com/OS/_workitems/edit/24672169 {REG_INFO( 11, DepthToSpace, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, #endif {REG_INFO( 7, Tile, typeNameListDefault, supportedTypeListNumericDefault, DmGraphSupport::Supported, {1})}, {REG_INFO( 8, Expand, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported, {1})}, {REG_INFO( 9, ConstantOfShape, typeNameListConstantOfShape, supportedTypeListConstantOfShape, DmGraphSupport::NotSupported, {0})}, {REG_INFO( 7, Gather, typeNameListScatterGather, supportedTypeListScatterGather, DmGraphSupport::Supported)}, + {REG_INFO( 11, Gather, typeNameListScatterGather, supportedTypeListScatterGather, DmGraphSupport::Supported)}, + {REG_INFO( 11, GatherElements, typeNameListScatterGather, supportedTypeListScatterGather, DmGraphSupport::Supported)}, + {REG_INFO( 11, GatherND, typeNameListScatterGatherND, supportedTypeListScatterGatherND, DmGraphSupport::Supported)}, {REG_INFO_VER( 9, Scatter, typeNameListScatterGather, supportedTypeListScatterGather, DmGraphSupport::Supported)}, {REG_INFO_VER( 11, Scatter, typeNameListScatterGather, supportedTypeListScatterGather, DmGraphSupport::Supported)}, + {REG_INFO( 11, ScatterElements, typeNameListScatterGather, supportedTypeListScatterGather, DmGraphSupport::Supported)}, + {REG_INFO( 11, ScatterND, typeNameListScatterGatherND, supportedTypeListScatterGatherND, DmGraphSupport::Supported)}, {REG_INFO( 9, EyeLike, typeNameListEyeLike, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, // Data reorganization that merely changes the dimensions while keeping the data identical. @@ -514,51 +519,32 @@ const static OperatorRegistrationInformation operatorRegistrationInformationTabl {REG_INFO( 11, CumSum, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported, {1})}, {REG_INFO( 11, Range, typeNameListDefault, supportedTypeListRange, DmGraphSupport::Supported, {0,1,2})}, - {REG_INFO( 11, Gather, typeNameListScatterGather, supportedTypeListScatterGather, DmGraphSupport::Supported)}, - {REG_INFO( 11, GatherElements, typeNameListScatterGather, supportedTypeListScatterGather, DmGraphSupport::Supported)}, - {REG_INFO( 11, GatherND, typeNameListScatterGatherND, supportedTypeListScatterGatherND, DmGraphSupport::Supported)}, - {REG_INFO( 11, ScatterElements, typeNameListScatterGather, supportedTypeListScatterGather, DmGraphSupport::Supported)}, - {REG_INFO( 11, ScatterND, typeNameListScatterGatherND, supportedTypeListScatterGatherND, DmGraphSupport::Supported)}, -#if 0 +#if 0 // TODO:DwayneR {REG_INFO( 9, MaxUnpool, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported, {2})}, {REG_INFO( 11, Resize, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported, {1})}, +#endif - {REG_INFO( 11, QLinearConv, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, - // T1 : tensor(int8), tensor(uint8) - // Constrain input type to 8-bit integer tensor. - // T2 : tensor(int8), tensor(uint8) - // Constrain filter type to 8-bit integer tensor. - // T3 : tensor(int8), tensor(uint8) - // Constrain output type to 8-bit integer tensor. - // T4 : tensor(int32) - // Constrain bias type to 32-bit integer tensor. - {REG_INFO( 11, QLinearMatMul, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, - // T1 : tensor(int8), tensor(uint8) - // Constrain input a and its zero point data type to 8-bit integer tensor. - // T2 : tensor(int8), tensor(uint8) - // Constrain input b and its zero point data type to 8-bit integer tensor. - // T3 : tensor(int8), tensor(uint8) - // Constrain output y and its zero point data type to 8-bit integer tensor. - {REG_INFO( 11, DynamicQuantizeLinear, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, - //T1 : tensor(float) - //Constrain 'x' to float tensor. - //T2 : tensor(uint8) - - {REG_INFO( 11, MatMulInteger, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, - MatMulInteger - //T1 : tensor(int8), tensor(uint8) - //Constrain input A data type to 8-bit integer tensor. - //T2 : tensor(int8), tensor(uint8) - //Constrain input B data type to 8-bit integer tensor. - //T3 : tensor(int32) - //Constrain output Y data type as 32-bit integer tensor. - {REG_INFO( 11, ConvInteger, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, - // T1 : tensor(int8), tensor(uint8) - // Constrain input x and its zero point data type to 8-bit integer tensor. - // T2 : tensor(int8), tensor(uint8) - // Constrain input w and its zero point data type to 8-bit integer tensor. - // T3 : tensor(int32) - // Constrain output y data type to 32-bit integer tensor. +#if 0 // TODO:NickFe + {REG_INFO( 11, QLinearConv, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, + // T1 : tensor(int8), tensor(uint8) - Constrain input type to 8-bit integer tensor. + // T2 : tensor(int8), tensor(uint8) - Constrain filter type to 8-bit integer tensor. + // T3 : tensor(int8), tensor(uint8) - Constrain output type to 8-bit integer tensor. + // T4 : tensor(int32) - Constrain bias type to 32-bit integer tensor. + {REG_INFO( 11, QLinearMatMul, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, + // T1 : tensor(int8), tensor(uint8) - Constrain input a and its zero point data type to 8-bit integer tensor. + // T2 : tensor(int8), tensor(uint8) - Constrain input b and its zero point data type to 8-bit integer tensor. + // T3 : tensor(int8), tensor(uint8) - Constrain output y and its zero point data type to 8-bit integer tensor. + {REG_INFO( 11, DynamicQuantizeLinear, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, + //T1 : tensor(float) - Constrain 'x' to float tensor. + //T2 : tensor(uint8) + {REG_INFO( 11, MatMulInteger, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, + //T1 : tensor(int8), tensor(uint8) - Constrain input A data type to 8-bit integer tensor. + //T2 : tensor(int8), tensor(uint8) - Constrain input B data type to 8-bit integer tensor. + //T3 : tensor(int32) - Constrain output Y data type as 32-bit integer tensor. + {REG_INFO( 11, ConvInteger, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, + // T1 : tensor(int8), tensor(uint8) - Constrain input x and its zero point data type to 8-bit integer tensor. + // T2 : tensor(int8), tensor(uint8) - Constrain input w and its zero point data type to 8-bit integer tensor. + // T3 : tensor(int32) - Constrain output y data type to 32-bit integer tensor. #endif }; From 0f6ace2c3649255beab55760bee7f95fddf384c3 Mon Sep 17 00:00:00 2001 From: Dwayne Robinson Date: Wed, 25 Mar 2020 00:16:08 -0700 Subject: [PATCH 09/12] Fix comments with stale todo's. --- .../dml/DmlExecutionProvider/src/Operators/DmlOperatorRange.cpp | 2 -- .../src/Operators/DmlOperatorReverseSequence.cpp | 2 -- .../DmlExecutionProvider/src/Operators/OperatorRegistration.cpp | 2 +- .../core/providers/dml/OperatorAuthorHelper/OperatorHelper.h | 1 - 4 files changed, 1 insertion(+), 6 deletions(-) diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorRange.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorRange.cpp index 821ba6aaa6..ac7afca1dc 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorRange.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorRange.cpp @@ -2,8 +2,6 @@ // Licensed under the MIT License. -// TODO::: - #include "precomp.h" namespace Dml diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorReverseSequence.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorReverseSequence.cpp index 2d8e849cab..f13756043f 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorReverseSequence.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorReverseSequence.cpp @@ -2,8 +2,6 @@ // Licensed under the MIT License. -// TODO::: - #include "precomp.h" namespace Dml diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp index 26ea3240a8..92f300969f 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp @@ -515,7 +515,7 @@ const static OperatorRegistrationInformation operatorRegistrationInformationTabl {REG_INFO( 10, Mod, typeNameListDefault, supportedTypeListNumericDefault, DmGraphSupport::Supported)}, {REG_INFO( 11, BitShift, typeNameListDefault, supportedTypeListInt8to32, DmGraphSupport::Supported)}, {REG_INFO( 11, Round, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, - {REG_INFO( 10, ReverseSequence, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, // TODO::: data types, why not registered?? + {REG_INFO( 10, ReverseSequence, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, {REG_INFO( 11, CumSum, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported, {1})}, {REG_INFO( 11, Range, typeNameListDefault, supportedTypeListRange, DmGraphSupport::Supported, {0,1,2})}, diff --git a/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.h b/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.h index d63d3214cc..d80b54731e 100644 --- a/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.h +++ b/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.h @@ -1177,7 +1177,6 @@ class ResizeHelper { std::vector m_scales; // Cached scales to check for updates/invalidate operator. }; -//TODO::: class RangeHelper { public: // Info_t is used to obtain attributes which will be used for calculating the output shape later. From f1a062c292955e200101fe7331076e959f85c0f6 Mon Sep 17 00:00:00 2001 From: Dwayne Robinson Date: Fri, 27 Mar 2020 19:22:25 -0700 Subject: [PATCH 10/12] PR feedback --- .../src/Operators/DmlOperatorCumSum.cpp | 2 +- .../src/Operators/DmlOperatorElementWise.cpp | 4 +- .../src/Operators/DmlOperatorMaxUnpool.cpp | 5 +- .../src/Operators/OperatorRegistration.cpp | 3 +- .../OperatorAuthorHelper/OperatorHelper.cpp | 58 +++++++++++++++---- .../dml/OperatorAuthorHelper/OperatorHelper.h | 39 +++++++++++-- .../OperatorRegistration.h | 1 + 7 files changed, 90 insertions(+), 22 deletions(-) diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorCumSum.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorCumSum.cpp index c323affc55..2a80555583 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorCumSum.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorCumSum.cpp @@ -32,7 +32,7 @@ public: std::byte tensorBytes[8]; MLOperatorTensor axisTensor = kernelCreationContext.GetConstantInputTensor(1); ReadScalarTensorData(axisTensor, /*out*/ tensorBytes, sizeof(tensorBytes)); - onnxAxis = gsl::narrow_cast(ReadAsInt64(axisTensor.GetTensorDataType(), /*out*/ tensorBytes)); + onnxAxis = gsl::narrow_cast(CastToInt64(axisTensor.GetTensorDataType(), /*out*/ tensorBytes)); } uint32_t dmlAxis = GetDmlAdjustedAxis(onnxAxis, kernelCreationContext, m_inputTensorDescs.front().GetDimensionCount()); diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorElementWise.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorElementWise.cpp index bbbb8f2e59..910860f592 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorElementWise.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorElementWise.cpp @@ -446,11 +446,11 @@ public: float maxValue = FLT_MAX; if (kernelInfo.IsInputValid(1)) { - minValue = ReadScalarTensorAsFloat64(kernelInfo.GetConstantInputTensor(1)); + minValue = ReadScalarTensorCastToFloat64(kernelInfo.GetConstantInputTensor(1)); } if (kernelInfo.IsInputValid(2)) { - maxValue = ReadScalarTensorAsFloat64(kernelInfo.GetConstantInputTensor(2)); + maxValue = ReadScalarTensorCastToFloat64(kernelInfo.GetConstantInputTensor(2)); } DML_ELEMENT_WISE_CLIP_OPERATOR_DESC opDesc = {}; diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorMaxUnpool.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorMaxUnpool.cpp index e42b8033d2..416fd3620c 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorMaxUnpool.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorMaxUnpool.cpp @@ -6,13 +6,14 @@ namespace Dml { -class DmlOperatorMaxUnpool : public DmlOperator +class DmlOperatorMaxUnpool : public DmlOperator, public UnpoolingHelper { public: using Self = DmlOperatorMaxUnpool; DmlOperatorMaxUnpool(const MLOperatorKernelCreationContext& kernelCreationContext) - : DmlOperator(kernelCreationContext) + : DmlOperator(kernelCreationContext), + UnpoolingHelper(kernelCreationContext, kernelCreationContext.GetTensorShapeDescription()) { uint32_t inputCount = kernelCreationContext.GetInputCount(); ML_CHECK_VALID_ARGUMENT(inputCount == 2 || inputCount == 3, "MaxUnpool expects 2 or 3 inputs."); diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp index 315f347960..423429e91c 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp @@ -520,8 +520,9 @@ const static OperatorRegistrationInformation operatorRegistrationInformationTabl {REG_INFO( 11, CumSum, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported, {1})}, {REG_INFO( 11, Range, typeNameListDefault, supportedTypeListRange, DmGraphSupport::Supported, {0,1,2})}, -#if 0 // TODO:DwayneR {REG_INFO( 9, MaxUnpool, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported, {2})}, + {REG_INFO( 11, MaxUnpool, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported, {2})}, // 11 is identical to 9. +#if 0 // TODO:DwayneR {REG_INFO( 11, Resize, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported, {1})}, #endif diff --git a/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.cpp b/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.cpp index d407a7c011..92404fce16 100644 --- a/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.cpp +++ b/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.cpp @@ -80,7 +80,7 @@ namespace OperatorHelper } } - int64_t ReadAsInt64(MLOperatorTensorDataType tensorDataType, const void* p) + int64_t CastToInt64(MLOperatorTensorDataType tensorDataType, const void* p) { switch (tensorDataType) { @@ -104,7 +104,7 @@ namespace OperatorHelper }; } - double ReadAsFloat64(MLOperatorTensorDataType tensorDataType, const void* p) + double CastToFloat64(MLOperatorTensorDataType tensorDataType, const void* p) { switch (tensorDataType) { @@ -159,14 +159,14 @@ namespace OperatorHelper { std::byte tensorBytes[8]; ReadScalarTensorData(tensor, /*out*/ &tensorBytes, sizeof(tensorBytes)); - return ReadAsInt64(tensor.GetTensorDataType(), &tensorBytes); + return CastToInt64(tensor.GetTensorDataType(), &tensorBytes); } double ReadScalarTensorAsFloat64(const MLOperatorTensor& tensor) { std::byte tensorBytes[8]; ReadScalarTensorData(tensor, /*out*/ &tensorBytes, sizeof(tensorBytes)); - return ReadAsFloat64(tensor.GetTensorDataType(), &tensorBytes); + return CastToFloat64(tensor.GetTensorDataType(), &tensorBytes); } // Calculates the spatial dimensions from input dimensions and a kernel. The non-spatial (leading) @@ -1053,6 +1053,44 @@ namespace OperatorHelper return { std::move(EdgeShapes(outputDimensions)) }; } + void UnpoolingHelper::Initialize() + { + ResolveAutoPadding(m_kernel, m_inputShape); + m_inferredOutputDimensions = InitializeKernelOutputDimsTranspose(m_inputShape, m_kernel); + } + + std::vector UnpoolingHelper::GetOutputShapes(const MLShapeInferenceContext& shapeInfo) const + { + std::vector outputDimensions; + + if (shapeInfo.IsInputValid(2)) + { + // Read the dimensions from the output_shape tensor. + MLOperatorTensor outputShapeTensor = shapeInfo.GetConstantInputTensor(2); + ML_CHECK_VALID_ARGUMENT(outputShapeTensor.IsCpuData(), "MaxUnpool's scales tensor must be CPU Tensor."); + + const std::vector outputShapeTensorDimensions = outputShapeTensor.GetShape(); + ML_CHECK_VALID_ARGUMENT(outputShapeTensorDimensions.size() == 1, "output_shape tensor must be 1D."); + const size_t dimCount = outputShapeTensorDimensions[0]; + const int64_t* data = outputShapeTensor.GetData(); + + ML_CHECK_VALID_ARGUMENT(dimCount == m_inputShape.size(), "Input dimensions and output_shape must have same rank."); + DowncastDimensions(gsl::make_span(data, dimCount), /*out*/ outputDimensions); + } + else if (shapeInfo.HasAttribute(AttrName::OutputShape, MLOperatorAttributeType::IntArray)) + { + std::vector outputDimensions64bit = shapeInfo.GetAttributeVector(AttrName::OutputShape); + ML_CHECK_VALID_ARGUMENT(outputDimensions64bit.size() == m_inputShape.size(), "Input dimensions and output_shape must have same rank."); + DowncastDimensions(outputDimensions64bit, /*out*/ outputDimensions); + } + else + { + outputDimensions = m_inferredOutputDimensions; + } + + return { std::move(outputDimensions) }; + } + void SqueezeHelper::Initialize( gsl::span axes, gsl::span inputDimensions @@ -1310,16 +1348,16 @@ namespace OperatorHelper uint32_t totalElementCount = 0; if (IsFloatDataType(m_tensorDataType)) { - double start = ReadAsFloat64(m_tensorDataType, &m_valueStart); - double limit = ReadAsFloat64(m_tensorDataType, &m_valueLimit); - double delta = ReadAsFloat64(m_tensorDataType, &m_valueDelta); + double start = CastToFloat64(m_tensorDataType, &m_valueStart); + double limit = CastToFloat64(m_tensorDataType, &m_valueLimit); + double delta = CastToFloat64(m_tensorDataType, &m_valueDelta); totalElementCount = gsl::narrow_cast(std::max(ceil((limit - start) / delta), 0.0)); } else { - int64_t start = ReadAsInt64(m_tensorDataType, &m_valueStart); - int64_t limit = ReadAsInt64(m_tensorDataType, &m_valueLimit); - int64_t delta = ReadAsInt64(m_tensorDataType, &m_valueDelta); + int64_t start = CastToInt64(m_tensorDataType, &m_valueStart); + int64_t limit = CastToInt64(m_tensorDataType, &m_valueLimit); + int64_t delta = CastToInt64(m_tensorDataType, &m_valueDelta); int64_t range = limit - start; totalElementCount = gsl::narrow_cast(std::max((range / delta) + (range % delta != 0), int64_t(0))); } diff --git a/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.h b/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.h index 3ab5879515..76bfbf8721 100644 --- a/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.h +++ b/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.h @@ -93,11 +93,11 @@ void FillWithLeadingValues(/*inout*/ std::vector& values, uint32_t minimumEle std::fill_n(values.data(), fillCount, fillValue); } -int64_t ReadAsInt64(MLOperatorTensorDataType tensorDataType, const void* p); -double ReadAsFloat64(MLOperatorTensorDataType tensorDataType, const void* p); +int64_t CastToInt64(MLOperatorTensorDataType tensorDataType, const void* p); +double CastToFloat64(MLOperatorTensorDataType tensorDataType, const void* p); void ReadScalarTensorData(const MLOperatorTensor& tensor, /*out*/ void* data, size_t dataByteSize); -int64_t ReadScalarTensorAsInt64(const MLOperatorTensor& tensor); -double ReadScalarTensorAsFloat64(const MLOperatorTensor& tensor); +int64_t ReadScalarTensorCastToInt64(const MLOperatorTensor& tensor); +double ReadScalarTensorCastToFloat64(const MLOperatorTensor& tensor); void ReadCpuLocalTensorIntoInt32(const MLOperatorTensor& tensor, std::vector& result); @@ -123,7 +123,7 @@ struct KernelArgs { // values beyond that may be bogus. uint32_t strides[NcdhwSpatialDimensionCount]; uint32_t dilations[NcdhwSpatialDimensionCount]; - uint32_t windowSize[NcdhwSpatialDimensionCount]; + uint32_t windowSize[NcdhwSpatialDimensionCount]; // The filter kernel dimensions. uint32_t startPadding[NcdhwSpatialDimensionCount]; uint32_t endPadding[NcdhwSpatialDimensionCount]; uint32_t outputPadding[NcdhwSpatialDimensionCount]; @@ -957,6 +957,32 @@ class PoolingHelperBase { KernelArgs m_kernel; }; +class UnpoolingHelper +{ +public: + // Info_t is used to obtain attributes which will be used for calculating the output shape later. + // Shape_t is used to obtain input shape which will be used for adjusting attribute value. + template + UnpoolingHelper( + const Info_t& info, + const Shape_t& shape + ) + : m_inputShape(shape.GetInputTensorShape(0)), + m_kernel(InitializeKernel(info, static_cast(m_inputShape.size()), gsl::span())) + { + Initialize(); + } + + void Initialize(); + + std::vector GetOutputShapes(const MLShapeInferenceContext& shapeInfo) const; + +protected: + std::vector m_inputShape; + std::vector m_inferredOutputDimensions; + KernelArgs m_kernel; +}; + class GlobalPoolingHelper : public PoolingHelperBase { public: template @@ -1229,7 +1255,7 @@ class OneHotHelper { ML_CHECK_VALID_ARGUMENT(shapeTensor.IsCpuData(), "OneHots's 'depth' tensor must be a CPU Tensor."); ML_CHECK_VALID_ARGUMENT(depthElementCount == 1, "OneHots's 'depth' tensor must have one element."); const void* tensorData = shapeTensor.GetByteData(); - const int64_t depth64 = ReadAsInt64(shapeTensor.GetTensorDataType(), tensorData); + const int64_t depth64 = CastToInt64(shapeTensor.GetTensorDataType(), tensorData); ML_CHECK_VALID_ARGUMENT(depth64 > 0, "Negative or zero 'depth' values for OneHot are illegal."); const uint32_t depth = gsl::narrow_cast(depth64); m_outputDimensions.assign(indicesShape.begin(), indicesShape.end()); @@ -1252,6 +1278,7 @@ using ShapeInferenceHelper_AveragePool = PoolingHelper; using ShapeInferenceHelper_GlobalAveragePool = GlobalPoolingHelper; using ShapeInferenceHelper_MaxPool = PoolingHelper; using ShapeInferenceHelper_GlobalMaxPool = GlobalPoolingHelper; +using ShapeInferenceHelper_MaxUnpool = UnpoolingHelper; using ShapeInferenceHelper_LpPool = PoolingHelper; using ShapeInferenceHelper_GlobalLpPool = GlobalPoolingHelper; using ShapeInferenceHelper_MaxRoiPool = RoiPoolingHelper; diff --git a/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorRegistration.h b/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorRegistration.h index 5fda5b29fe..e64e0ce2d5 100644 --- a/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorRegistration.h +++ b/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorRegistration.h @@ -208,6 +208,7 @@ namespace OperatorHelper static const int sc_sinceVer_Hardmax = 11; static const int sc_sinceVer_LogSoftmax = 11; static const int sc_sinceVer_MaxPool = 11; + static const int sc_sinceVer_MaxUnpool = 11; static const int sc_sinceVer_OneHot = 11; static const int sc_sinceVer_Pad = 11; static const int sc_sinceVer_Range = 11; From 5972ce5566fc270db590145ab5218a4b5c973053 Mon Sep 17 00:00:00 2001 From: Dwayne Robinson Date: Fri, 27 Mar 2020 19:32:47 -0700 Subject: [PATCH 11/12] PR feedback --- .../dml/DmlExecutionProvider/src/ExecutionProvider.cpp | 9 +++++---- .../dml/OperatorAuthorHelper/OperatorHelper.cpp | 4 ++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/ExecutionProvider.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/ExecutionProvider.cpp index 630e3bd3d8..04c6ef202c 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/ExecutionProvider.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/ExecutionProvider.cpp @@ -500,11 +500,12 @@ namespace Dml std::string partitionKernelPrefix = std::to_string(m_partitionKernelPrefixVal++) + "_"; uint32_t deviceDataTypeMask = GetSuppportedDeviceDataTypeMask(); - return PartitionGraph(graph, + return PartitionGraph( + graph, *m_internalRegInfoMap, - registries, - deviceDataTypeMask, - m_kernelRegistry.get(), + registries, + deviceDataTypeMask, + m_kernelRegistry.get(), partitionKernelPrefix ); } diff --git a/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.cpp b/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.cpp index 92404fce16..0f905f6cd1 100644 --- a/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.cpp +++ b/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.cpp @@ -155,14 +155,14 @@ namespace OperatorHelper memcpy(data, tensor.GetByteData(), elementByteSize); } - int64_t ReadScalarTensorAsInt64(const MLOperatorTensor& tensor) + int64_t ReadScalarTensorCastToInt64(const MLOperatorTensor& tensor) { std::byte tensorBytes[8]; ReadScalarTensorData(tensor, /*out*/ &tensorBytes, sizeof(tensorBytes)); return CastToInt64(tensor.GetTensorDataType(), &tensorBytes); } - double ReadScalarTensorAsFloat64(const MLOperatorTensor& tensor) + double ReadScalarTensorCastToFloat64(const MLOperatorTensor& tensor) { std::byte tensorBytes[8]; ReadScalarTensorData(tensor, /*out*/ &tensorBytes, sizeof(tensorBytes)); From 5bc81b7ae9a7de4b9caf2ea756a5b0e732701c55 Mon Sep 17 00:00:00 2001 From: Dwayne Robinson Date: Fri, 27 Mar 2020 19:58:41 -0700 Subject: [PATCH 12/12] Fix bad merge (caused Slice to fail). --- .../src/Operators/OperatorRegistration.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp index 423429e91c..a7c145dadc 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp @@ -332,10 +332,9 @@ const static OperatorRegistrationInformation operatorRegistrationInformationTabl {REG_INFO( 7, Transpose, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, {REG_INFO( 7, Concat, typeNameListDefault, supportedTypeListNumericDefault, DmGraphSupport::Supported)}, {REG_INFO( 11, Concat, typeNameListDefault, supportedTypeListNumericDefault, DmGraphSupport::Supported)}, // Adds negative axis. - {REG_INFO_VER( 7, Slice, typeNameListDefault, supportedTypeListNumericDefault, DmGraphSupport::Supported)}, - {REG_INFO_VER( 10, Slice, typeNameListDefault, supportedTypeListNumericDefault, DmGraphSupport::Supported, {1, 2, 3}, std::nullopt, QuerySlice)}, - {REG_INFO_VER( 10, Slice, typeNameListSlice10, supportedTypeListSlice10, DmGraphSupport::Supported, {1, 2, 3, 4}, std::nullopt, QuerySlice)}, // Adds negative axes. - {REG_INFO_VER( 11, Slice, typeNameListSlice10, supportedTypeListSlice10, DmGraphSupport::Supported, {1, 2, 3, 4}, std::nullopt, QuerySlice)}, + {REG_INFO_VER( 7, Slice, typeNameListDefault, supportedTypeListNumericDefault, DmGraphSupport::Supported)}, + {REG_INFO_VER( 10, Slice, typeNameListSlice10, supportedTypeListSlice10, DmGraphSupport::Supported, {1, 2, 3, 4}, std::nullopt, QuerySlice)}, // Adds negative axes. + {REG_INFO_VER( 11, Slice, typeNameListSlice10, supportedTypeListSlice10, DmGraphSupport::Supported, {1, 2, 3, 4}, std::nullopt, QuerySlice)}, {REG_INFO( 7, Pad, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, #if 0 // TODO:NickFe Pads and Value are inputs. https://microsoft.visualstudio.com/OS/_workitems/edit/24674281, https://github.com/onnx/onnx/blob/master/docs/Changelog.md#Pad-11 {REG_INFO( 11, Pad, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)},