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..04c6ef202c 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); } @@ -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/DmlExecutionProvider/src/External/DirectMLHelpers/ApiTraits.h b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/External/DirectMLHelpers/ApiTraits.h index 703d027412..9a9ce5d672 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/External/DirectMLHelpers/ApiTraits.h +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/External/DirectMLHelpers/ApiTraits.h @@ -1594,7 +1594,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. // 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 07592cc2ee..a80653a78b 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/External/DirectMLHelpers/DirectMLSchema.h +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/External/DirectMLHelpers/DirectMLSchema.h @@ -1871,4 +1871,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 2d0c35b3eb..6d33af8a9c 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/External/DirectMLHelpers/GeneratedSchemaHelpers.h +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/External/DirectMLHelpers/GeneratedSchemaHelpers.h @@ -1237,6 +1237,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); } } 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/MLOperatorAuthorImpl.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/MLOperatorAuthorImpl.cpp index 55e8e23870..47cbcae00f 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/DmlOperatorConvInteger.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorConvInteger.cpp new file mode 100644 index 0000000000..e8bd374d3b --- /dev/null +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorConvInteger.cpp @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "precomp.h" + +namespace Dml +{ + +class DmlOperatorConvInteger : public DmlOperator +{ +public: + using Self = DmlOperatorConvInteger; + + DmlOperatorConvInteger(const MLOperatorKernelCreationContext& kernelCreationContext) + : DmlOperator(kernelCreationContext) + { +#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); + DmlOperator::Initialize(kernelCreationContext, inputIndices, outputIndices); + + std::vector inputDescs = GetDmlInputDescs(); + std::vector outputDescs = GetDmlOutputDescs(); + + 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_PLACEHOLDER, &operatorDesc }; + SetDmlOperatorDesc(opDesc, kernelCreationContext); +#endif + } +}; + +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..2a80555583 --- /dev/null +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorCumSum.cpp @@ -0,0 +1,56 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "precomp.h" + +namespace Dml +{ + +class DmlOperatorCumSum : public DmlOperator +{ +public: + using Self = DmlOperatorCumSum; + + DmlOperatorCumSum(const MLOperatorKernelCreationContext& kernelCreationContext) + : DmlOperator(kernelCreationContext) + { + ML_CHECK_VALID_ARGUMENT(kernelCreationContext.GetInputCount() >= 1); // input, axis + ML_CHECK_VALID_ARGUMENT(kernelCreationContext.GetOutputCount() == 1); + + 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); + + // Axis defaults to 0 if tensor not present. + int32_t onnxAxis = 0; + if (kernelCreationContext.IsInputValid(1)) + { + std::byte tensorBytes[8]; + MLOperatorTensor axisTensor = kernelCreationContext.GetConstantInputTensor(1); + ReadScalarTensorData(axisTensor, /*out*/ tensorBytes, sizeof(tensorBytes)); + onnxAxis = gsl::narrow_cast(CastToInt64(axisTensor.GetTensorDataType(), /*out*/ tensorBytes)); + } + 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..b727817e98 --- /dev/null +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorDynamicQuantizeLinear.cpp @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "precomp.h" + +namespace Dml +{ + +class DmlOperatorDynamicQuantizeLinear : public DmlOperator +{ +public: + using Self = DmlOperatorDynamicQuantizeLinear; + + DmlOperatorDynamicQuantizeLinear(const MLOperatorKernelCreationContext& kernelCreationContext) + : DmlOperator(kernelCreationContext) + { +#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); + + std::vector inputDescs = GetDmlInputDescs(); + std::vector outputDescs = GetDmlOutputDescs(); + + 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_PLACEHOLDER, &operatorDesc }; + SetDmlOperatorDesc(opDesc, kernelCreationContext); +#endif + } +}; + +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..910860f592 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(); @@ -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 = ReadScalarTensorCastToFloat64(kernelInfo.GetConstantInputTensor(1)); + } + if (kernelInfo.IsInputValid(2)) + { + maxValue = ReadScalarTensorCastToFloat64(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: @@ -534,6 +570,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_IS_INFINITY, &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); @@ -577,11 +717,16 @@ 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); 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..54ef525b46 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorGather.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorGather.cpp @@ -43,6 +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); +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/DmlOperatorGemm.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorGemm.cpp index e5c1ff555f..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(); @@ -36,7 +41,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..dcb7586f09 --- /dev/null +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorMatMulInteger.cpp @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "precomp.h" + +namespace Dml +{ + +class DmlOperatorMatMulInteger : public DmlOperator +{ +public: + using Self = DmlOperatorMatMulInteger; + + DmlOperatorMatMulInteger(const MLOperatorKernelCreationContext& kernelCreationContext) + : DmlOperator(kernelCreationContext) + { +#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); + DmlOperator::Initialize(kernelCreationContext, inputIndices, outputIndices); + + std::vector inputDescs = GetDmlInputDescs(); + std::vector outputDescs = GetDmlOutputDescs(); + + 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_PLACEHOLDER, &operatorDesc }; + SetDmlOperatorDesc(opDesc, kernelCreationContext); +#endif + } +}; + +DML_OP_DEFINE_CREATION_FUNCTION(MatMulInteger, DmlOperatorMatMulInteger); + +} // namespace Dml 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/DmlOperatorQLinearConv.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorQLinearConv.cpp new file mode 100644 index 0000000000..c2cd77d32d --- /dev/null +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorQLinearConv.cpp @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "precomp.h" + +namespace Dml +{ + +class DmlOperatorQLinearConv : public DmlOperator +{ +public: + using Self = DmlOperatorQLinearConv; + + DmlOperatorQLinearConv(const MLOperatorKernelCreationContext& kernelCreationContext) + : DmlOperator(kernelCreationContext) + { +#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); + DmlOperator::Initialize(kernelCreationContext, inputIndices, outputIndices); + + std::vector inputDescs = GetDmlInputDescs(); + std::vector outputDescs = GetDmlOutputDescs(); + + 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_PLACEHOLDER, &operatorDesc }; + SetDmlOperatorDesc(opDesc, kernelCreationContext); +#endif + } +}; + +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..aa0e34ec6d --- /dev/null +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorQLinearMatMul.cpp @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "precomp.h" + +namespace Dml +{ + +class DmlOperatorQLinearMatMul : public DmlOperator +{ +public: + using Self = DmlOperatorQLinearMatMul; + + DmlOperatorQLinearMatMul(const MLOperatorKernelCreationContext& kernelCreationContext) + : DmlOperator(kernelCreationContext) + { +#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); + DmlOperator::Initialize(kernelCreationContext, inputIndices, outputIndices); + + std::vector inputDescs = GetDmlInputDescs(); + std::vector outputDescs = GetDmlOutputDescs(); + + 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_PLACEHOLDER, &operatorDesc }; + SetDmlOperatorDesc(opDesc, kernelCreationContext); +#endif + } +}; + +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..ac7afca1dc --- /dev/null +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorRange.cpp @@ -0,0 +1,43 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + + +#include "precomp.h" + +namespace Dml +{ + +class DmlOperatorRange : public DmlOperator, RangeHelper +{ +public: + using Self = DmlOperatorRange; + + DmlOperatorRange(const MLOperatorKernelCreationContext& kernelCreationContext) + : DmlOperator(kernelCreationContext), + RangeHelper(kernelCreationContext, kernelCreationContext.GetTensorShapeDescription()) + { + ML_CHECK_VALID_ARGUMENT(kernelCreationContext.GetInputCount() == 3); + ML_CHECK_VALID_ARGUMENT(kernelCreationContext.GetOutputCount() == 1); + std::vector> inputIndices = {}; // All tensors are CPU bound. + std::vector> outputIndices = { 0 }; + DmlOperator::Initialize(kernelCreationContext, inputIndices, outputIndices); + + std::vector inputDescs = GetDmlInputDescs(); + std::vector outputDescs = GetDmlOutputDescs(); + + DML_FILL_VALUE_SEQUENCE_OPERATOR_DESC operatorDesc = {}; + operatorDesc.ValueDataType = m_outputTensorDescs[0].GetDmlDataType();; + 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 }; + 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..f13756043f --- /dev/null +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorReverseSequence.cpp @@ -0,0 +1,66 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + + +#include "precomp.h" + +namespace Dml +{ + +class DmlOperatorReverseSequence : public DmlOperator +{ +public: + using Self = DmlOperatorReverseSequence; + + DmlOperatorReverseSequence(const MLOperatorKernelCreationContext& kernelCreationContext) + : DmlOperator(kernelCreationContext) + { + 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); + const uint32_t inputRank = static_cast(inputDimensions.size()); + + // Read axis. + 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[timeAxis] = 1; + ML_CHECK_VALID_ARGUMENT(ComputeElementCountFromDimensions(adjustedSequenceLengthDimensions), ComputeElementCountFromDimensions(sequenceLengthDimensions)); + + m_inputTensorDescs[1] = + TensorDesc( + m_inputTensorDescs[1].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 = dmlTimeAxis; + + 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..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()); @@ -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); @@ -77,6 +74,51 @@ public: } }; -DML_OP_DEFINE_CREATION_FUNCTION(Scatter, DmlOperatorScatter); +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, DmlOperatorScatterNd); } // 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 5a2e9d888b..9837e79269 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorSlice.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/DmlOperatorSlice.cpp @@ -58,7 +58,7 @@ public: } }; -void CALLBACK QuerySlice(IMLOperatorSupportQueryContextPrivate* context, bool *isSupported) +void CALLBACK QuerySlice(IMLOperatorSupportQueryContextPrivate* context, bool* isSupported) { *isSupported = (context->GetInputCount() <= 5); } diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/OperatorRegistration.cpp index 8be3774de1..a7c145dadc 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); @@ -201,9 +202,26 @@ 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); +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); @@ -211,10 +229,10 @@ 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[1] = { "T" }; // Tind is curiously missing, only allowing 64-bit. const static char* const typeNameListSlice10[2] = { "T", "Tind" }; const static char* const typeNameListQuantize[2] = { "T1", "T2" }; const static char* const typeNameListWhere[2] = { "B", "T" }; @@ -222,6 +240,7 @@ 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 }; @@ -230,17 +249,20 @@ 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[1] = { SupportedTensorDataTypes::NumericDefault }; const static SupportedTensorDataTypes supportedTypeListSlice10[2] = { SupportedTensorDataTypes::NumericDefault, SupportedTensorDataTypes::Int32 | SupportedTensorDataTypes::Int64 }; 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 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, ...) \ @@ -275,11 +297,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)}, @@ -297,27 +328,45 @@ 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_VER( 7, Slice, typeNameListDefault, supportedTypeListNumericDefault, DmGraphSupport::Supported)}, - {REG_INFO_VER( 10, Slice, typeNameListSlice10, supportedTypeListSlice10, DmGraphSupport::Supported, {1, 2, 3, 4}, std::nullopt, QuerySlice)}, - {REG_INFO_VER( 11, Slice, typeNameListSlice10, supportedTypeListSlice10, DmGraphSupport::Supported, {1, 2, 3, 4}, std::nullopt, QuerySlice)}, + {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, 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)}, +#endif {REG_INFO( 7, SpaceToDepth, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, {REG_INFO( 7, DepthToSpace, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, - {REG_INFO( 7, Tile, typeNameListDefault, supportedTypeListNumericDefault, DmGraphSupport::Supported, {1})}, +#if 0 + // 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( 9, Scatter, 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. {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)}, + {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 @@ -329,7 +378,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)}, + {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)}, @@ -354,7 +404,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)}, @@ -363,18 +413,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)}, @@ -382,7 +445,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)}, @@ -409,8 +472,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)}, @@ -420,12 +486,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)}, @@ -438,50 +511,41 @@ const static OperatorRegistrationInformation operatorRegistrationInformationTabl {REG_INFO_MSDML(1, FusedAdd, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, {REG_INFO_MSDML(1, FusedSum, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported, {}, 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( 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, Scan, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, - {REG_INFO( 11, ScatterElements, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, - {REG_INFO( 11, ScatterND, 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( 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})}, + + {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 + +#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 }; diff --git a/onnxruntime/core/providers/dml/OperatorAuthorHelper/Attributes.h b/onnxruntime/core/providers/dml/OperatorAuthorHelper/Attributes.h index dc7def086d..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,14 +23,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_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"; 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 +55,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 +70,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.cpp b/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.cpp index f4123c97d0..0f905f6cd1 100644 --- a/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.cpp +++ b/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.cpp @@ -6,84 +6,84 @@ 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); - } -} - -void ReadCpuLocalTensorIntoInt32( - const MLOperatorTensor& tensor, - std::vector& result - ) -{ - result.clear(); - ML_CHECK_VALID_ARGUMENT(tensor.IsCpuData(), "Tensor must be CPU Tensor."); - - const std::vector& tensorDimensions = tensor.GetShape(); - const uint32_t elementCount = ComputeElementCountFromDimensions(tensorDimensions); - - switch (tensor.GetTensorDataType()) - { - case MLOperatorTensorDataType::Int32: + if (signedOnnxAxis < 0) { - const int32_t* data = tensor.GetData(); - result.assign(data, data + elementCount); + signedOnnxAxis += dimCount; } - break; + uint32_t absoluteAxis = gsl::narrow_cast(signedOnnxAxis); + ML_CHECK_VALID_ARGUMENT(absoluteAxis < dimCount); + return absoluteAxis; + } - case MLOperatorTensorDataType::Int64: + void HandleNegativeAxes(gsl::span onnxAxes, uint32_t dimCount) + { + for (int32_t& axis : onnxAxes) { - const int64_t* data = tensor.GetData(); - result.reserve(elementCount); - for (auto d : gsl::make_span(data, data + elementCount)) + axis = HandleNegativeAxis(axis, dimCount); + } + } + + void ReadCpuLocalTensorIntoInt32( + const MLOperatorTensor& tensor, + std::vector& result + ) + { + result.clear(); + ML_CHECK_VALID_ARGUMENT(tensor.IsCpuData(), "Tensor must be CPU Tensor."); + + const std::vector& tensorDimensions = tensor.GetShape(); + const uint32_t elementCount = ComputeElementCountFromDimensions(tensorDimensions); + + switch (tensor.GetTensorDataType()) + { + case MLOperatorTensorDataType::Int32: { - result.push_back(gsl::narrow_cast(d)); + const int32_t* data = tensor.GetData(); + result.assign(data, data + elementCount); } + break; + + case MLOperatorTensorDataType::Int64: + { + const int64_t* data = tensor.GetData(); + result.reserve(elementCount); + for (auto d : gsl::make_span(data, data + elementCount)) + { + result.push_back(gsl::narrow_cast(d)); + } + } + break; + + default: + ML_INVALID_ARGUMENT("Expecting CPU local tensor of type int32 or int64."); + break; } - break; - - default: - ML_INVALID_ARGUMENT("Expecting CPU local tensor of type int32 or int64."); - break; } -} -void DowncastDimensions(gsl::span inputDimensions, std::vector& outputDimensions) -{ - outputDimensions.reserve(inputDimensions.size()); - outputDimensions.clear(); - - for (int64_t dim : inputDimensions) + void DowncastDimensions(gsl::span inputDimensions, std::vector& outputDimensions) { - outputDimensions.push_back(gsl::narrow_cast(std::clamp(dim, INT32_MIN, INT32_MAX))); + outputDimensions.reserve(inputDimensions.size()); + outputDimensions.clear(); + + for (int64_t dim : inputDimensions) + { + outputDimensions.push_back(gsl::narrow_cast(std::clamp(dim, INT32_MIN, INT32_MAX))); + } } -} -int64_t ReadAsInt64(MLOperatorTensorDataType tensorDataType, const void* p) -{ - switch (tensorDataType) + int64_t CastToInt64(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)); @@ -104,6 +104,71 @@ int64_t ReadAsInt64(MLOperatorTensorDataType tensorDataType, const void* p) }; } + double CastToFloat64(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); + } + + int64_t ReadScalarTensorCastToInt64(const MLOperatorTensor& tensor) + { + std::byte tensorBytes[8]; + ReadScalarTensorData(tensor, /*out*/ &tensorBytes, sizeof(tensorBytes)); + return CastToInt64(tensor.GetTensorDataType(), &tensorBytes); + } + + double ReadScalarTensorCastToFloat64(const MLOperatorTensor& tensor) + { + std::byte tensorBytes[8]; + ReadScalarTensorData(tensor, /*out*/ &tensorBytes, sizeof(tensorBytes)); + return CastToFloat64(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). @@ -338,8 +403,8 @@ int64_t ReadAsInt64(MLOperatorTensorDataType tensorDataType, const void* p) 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) }; } @@ -531,15 +596,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 @@ -580,6 +639,30 @@ int64_t ReadAsInt64(MLOperatorTensorDataType tensorDataType, const void* p) return { EdgeShapes(std::move(outputDimensions)) }; } + 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() >= 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); + + // 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)) }; + } + void TransposeHelper::Initialize( const MLOperatorAttributes& operatorAttributes, gsl::span inputDimensions @@ -970,6 +1053,54 @@ int64_t ReadAsInt64(MLOperatorTensorDataType tensorDataType, const void* p) 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 + ) + { + 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); @@ -1003,6 +1134,17 @@ int64_t ReadAsInt64(MLOperatorTensorDataType tensorDataType, const void* p) 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); @@ -1187,6 +1329,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 = 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 = 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))); + } + 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 1f89948e34..76bfbf8721 100644 --- a/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.h +++ b/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorHelper.h @@ -93,7 +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); +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 ReadScalarTensorCastToInt64(const MLOperatorTensor& tensor); +double ReadScalarTensorCastToFloat64(const MLOperatorTensor& tensor); void ReadCpuLocalTensorIntoInt32(const MLOperatorTensor& tensor, std::vector& result); @@ -119,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]; @@ -194,13 +198,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 { @@ -349,10 +378,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) { @@ -387,39 +416,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: @@ -895,6 +924,17 @@ class GatherHelper { int m_axis = 0; }; +class GatherNdHelper { + 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 + GatherNdHelper(const Info_t& info, const Shape_t& shape) { + } + + std::vector GetOutputShapes(const MLShapeInferenceContext& shapeInfo) const; +}; + class PoolingHelperBase { public: // Info_t is used to obtain attributes which will be used for calculating the output shape later. @@ -917,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 @@ -953,12 +1019,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; @@ -969,12 +1040,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; @@ -1124,6 +1200,37 @@ 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) + { + auto startTensor = info.GetConstantInputTensor(0); + auto limitTensor = info.GetConstantInputTensor(1); + auto deltaTensor = info.GetConstantInputTensor(2); + Initialize(startTensor, limitTensor, deltaTensor); + } + + void Initialize( + 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_t; + TensorScalarData m_valueStart; + TensorScalarData m_valueLimit; + TensorScalarData m_valueDelta; +}; + class OneHotHelper { public: template @@ -1148,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()); @@ -1171,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; @@ -1183,7 +1291,14 @@ 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_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; @@ -1191,7 +1306,7 @@ using ShapeInferenceHelper_Transpose = TransposeHelper; using ShapeInferenceHelper_Concat = ConcatHelper; using ShapeInferenceHelper_Slice7 = SliceHelper; using ShapeInferenceHelper_Slice10 = Slice10Helper; -using ShapeInferenceHelper_Slice11 = Slice10Helper; // No functional change from 10. +using ShapeInferenceHelper_Slice11 = Slice10Helper; // 11 and 10 are identical - no functional change. using ShapeInferenceHelper_Pad = PaddingHelper; using ShapeInferenceHelper_SpaceToDepth = SpaceToDepthHelper; using ShapeInferenceHelper_DepthToSpace = DepthToSpaceHelper; @@ -1214,7 +1329,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; @@ -1239,7 +1355,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; @@ -1249,6 +1364,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; @@ -1301,6 +1420,10 @@ using ShapeInferenceHelper_RandomNormal = RandomNormalHelper; using ShapeInferenceHelper_RandomNormalLike = GetOutputShapeAsInputShapeHelper; using ShapeInferenceHelper_Multinomial = MultinomialHelper; +using ShapeInferenceHelper_ReverseSequence = GetOutputShapeAsInputShapeHelper; +using ShapeInferenceHelper_CumSum = GetOutputShapeAsInputShapeHelper; +using ShapeInferenceHelper_Range = RangeHelper; + 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..e64e0ce2d5 100644 --- a/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorRegistration.h +++ b/onnxruntime/core/providers/dml/OperatorAuthorHelper/OperatorRegistration.h @@ -185,12 +185,13 @@ 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 { - 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 +207,8 @@ 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_MaxUnpool = 11; static const int sc_sinceVer_OneHot = 11; static const int sc_sinceVer_Pad = 11; static const int sc_sinceVer_Range = 11; @@ -220,9 +223,9 @@ 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_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;