Merged PR 4471419: DML EP kernels in ORT

- Add updated registrations for v11 of existing kernels (ScatterElements, Clip...).
- Add new kernels for GatherElements, GatherND, ScatterND, IsInf, Round, BitShift, CumSum, ReverseSequence, Mod.

Related work items: #23106898, #24655666
This commit is contained in:
Dwayne Robinson 2020-03-28 03:00:19 +00:00
commit 324166b9cd
26 changed files with 1237 additions and 218 deletions

View file

@ -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,

View file

@ -181,7 +181,7 @@ namespace Dml
// CPU Allocator used to create buffers for the MemcpyFromHost operator.
m_cpuInputAllocator = std::make_shared<CPUAllocator>(OrtMemType::OrtMemTypeCPUInput);
m_cpuOutputAllocator = std::make_shared<CPUAllocator>(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
);
}

View file

@ -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.
//

View file

@ -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"

View file

@ -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);
}
}

View file

@ -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<std::string, GraphPartition*>* nodeNameToPartitionMap
)

View file

@ -1508,7 +1508,7 @@ onnxruntime::Status AbiOpKernel::Compute(onnxruntime::OpKernelContext* context)
{
tensorWrapper = wil::MakeOrThrow<TensorWrapper>(
const_cast<onnxruntime::Tensor*>(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<onnxruntime::Tensor>(static_cast<int>(index));
if (index >= static_cast<uint32_t>(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<uint32_t>(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<const std::byte*>(tensor.GetByteData()),
reinterpret_cast<const std::byte*>(tensor.GetByteData()) + tensor.GetUnalignedTensorByteSize());
}
m_constantInputTensorContentsOfKernel[index].data.assign(
reinterpret_cast<const std::byte*>(tensor.GetByteData()),
reinterpret_cast<const std::byte*>(tensor.GetByteData()) + tensor.GetUnalignedTensorByteSize());
}
m_kernel = inferShapesAndCreateKernel(m_inputShapesOfKernelInference, m_inferredOutputShapes);

View file

@ -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<DML_TENSOR_DESC> inputDescs = GetDmlInputDescs();
std::vector<DML_TENSOR_DESC> 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

View file

@ -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<std::optional<uint32_t>> inputIndices = { 0 }; // The second tensor ('axis') is not bound, just 'input'.
std::vector<std::optional<uint32_t>> 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<int32_t>(AttrName::Exclusive, 0);
int32_t isReversed = kernelCreationContext.GetOptionalAttribute<int32_t>(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<int32_t>(CastToInt64(axisTensor.GetTensorDataType(), /*out*/ tensorBytes));
}
uint32_t dmlAxis = GetDmlAdjustedAxis(onnxAxis, kernelCreationContext, m_inputTensorDescs.front().GetDimensionCount());
std::vector<DML_TENSOR_DESC> inputDescs = GetDmlInputDescs();
std::vector<DML_TENSOR_DESC> 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

View file

@ -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<DML_TENSOR_DESC> inputDescs = GetDmlInputDescs();
std::vector<DML_TENSOR_DESC> 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

View file

@ -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<ComPtr<IDMLCompiledOperator>> 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<std::optional<uint32_t>> inputIndices = {0}; // min and max (1 and 2) are CPU-bound.
std::vector<std::optional<uint32_t>> outputIndices = {0};
DmlOperator::Initialize(kernelInfo, inputIndices, outputIndices, kernelInfo.GetTensorShapeDescription().GetOutputTensorShape(0));
std::vector<DML_TENSOR_DESC> inputDescs = GetDmlInputDescs();
std::vector<DML_TENSOR_DESC> 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<DML_TENSOR_DESC> inputDescs = GetDmlInputDescs();
std::vector<DML_TENSOR_DESC> outputDescs = GetDmlOutputDescs();
auto fmod = kernelInfo.GetOptionalAttribute<int>(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<DML_TENSOR_DESC> inputDescs = GetDmlInputDescs();
std::vector<DML_TENSOR_DESC> 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<std::string>(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<DML_TENSOR_DESC> inputDescs = GetDmlInputDescs();
std::vector<DML_TENSOR_DESC> outputDescs = GetDmlOutputDescs();
auto detectPositive = kernelInfo.GetOptionalAttribute<int>(AttrName::DetectPositive, 1);
auto detectNegative = kernelInfo.GetOptionalAttribute<int>(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<DML_TENSOR_DESC> inputDescs = GetDmlInputDescs();
std::vector<DML_TENSOR_DESC> 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_ELEMENT_WISE_SQRT_OPERATOR_DESC>);
DML_OP_DEFINE_CREATION_FUNCTION(Reciprocal, DmlOperatorElementwiseUnary<DML_ELEMENT_WISE_RECIP_OPERATOR_DESC>);
@ -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_ELEMENT_WISE_QUANTIZE_LINEAR_OPERATOR_DESC>);
DML_OP_DEFINE_CREATION_FUNCTION(DequantizeLinear, DmlOperatorElementwiseQLinear<DML_ELEMENT_WISE_DEQUANTIZE_LINEAR_OPERATOR_DESC>);
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<DML_ELEMENT_WISE_ADD1_OPERATOR_DESC>);

View file

@ -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<DML_TENSOR_DESC> inputDescs = GetDmlInputDescs();
std::vector<DML_TENSOR_DESC> outputDescs = GetDmlOutputDescs();
assert(inputDescs.size() == 2);
assert(outputDescs.size() == 1);
m_inputTensorDescs[1].ForceUnsignedDataType();
int32_t signedOnnxAxis = kernelCreationContext.GetOptionalAttribute<int>(AttrName::Axis, 0);
auto outputTensorShapeDescription = kernelCreationContext.GetTensorShapeDescription();
std::vector<DimensionType> dataDimensions = outputTensorShapeDescription.GetInputTensorShape(0);
std::vector<DimensionType> 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<DML_TENSOR_DESC> inputDescs = GetDmlInputDescs();
std::vector<DML_TENSOR_DESC> outputDescs = GetDmlOutputDescs();
assert(inputDescs.size() == 2);
assert(outputDescs.size() == 1);
m_inputTensorDescs[1].ForceUnsignedDataType();
auto outputTensorShapeDescription = kernelCreationContext.GetTensorShapeDescription();
std::vector<DimensionType> dataDimensions = outputTensorShapeDescription.GetInputTensorShape(0);
std::vector<DimensionType> 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<uint32_t>(dataDimensions.size());
operatorDesc.IndicesDimensionCount = static_cast<uint32_t>(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

View file

@ -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<DML_TENSOR_DESC> inputDescs = GetDmlInputDescs();
std::vector<DML_TENSOR_DESC> 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);

View file

@ -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<DML_TENSOR_DESC> inputDescs = GetDmlInputDescs();
std::vector<DML_TENSOR_DESC> 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

View file

@ -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.");

View file

@ -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<DML_TENSOR_DESC> inputDescs = GetDmlInputDescs();
std::vector<DML_TENSOR_DESC> 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

View file

@ -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<DML_TENSOR_DESC> inputDescs = GetDmlInputDescs();
std::vector<DML_TENSOR_DESC> 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

View file

@ -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<std::optional<uint32_t>> inputIndices = {}; // All tensors are CPU bound.
std::vector<std::optional<uint32_t>> outputIndices = { 0 };
DmlOperator::Initialize(kernelCreationContext, inputIndices, outputIndices);
std::vector<DML_TENSOR_DESC> inputDescs = GetDmlInputDescs();
std::vector<DML_TENSOR_DESC> 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

View file

@ -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<uint32_t> inputDimensions = kernelCreationContext.GetTensorShapeDescription().GetInputTensorShape(0);
std::vector<uint32_t> sequenceLengthDimensions = kernelCreationContext.GetTensorShapeDescription().GetInputTensorShape(1);
const uint32_t inputRank = static_cast<uint32_t>(inputDimensions.size());
// Read axis.
const int32_t batchAxis = HandleNegativeAxis(kernelCreationContext.GetOptionalAttribute<int32_t>(AttrName::BatchAxis, 0), inputRank);
const int32_t timeAxis = HandleNegativeAxis(kernelCreationContext.GetOptionalAttribute<int32_t>(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<uint32_t> 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<DML_TENSOR_DESC> inputDescs = GetDmlInputDescs();
std::vector<DML_TENSOR_DESC> 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

View file

@ -19,7 +19,7 @@ public:
std::vector<DimensionType> dataDimensions = tensorShapeDescription.GetInputTensorShape(0);
std::vector<DimensionType> indicesDimensions = tensorShapeDescription.GetInputTensorShape(1);
std::vector<DimensionType> updatesDimensions = tensorShapeDescription.GetInputTensorShape(2);
std::vector<DimensionType> outputDimensions = tensorShapeDescription.GetInputTensorShape(0);
std::vector<DimensionType> 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<DimensionType> dataDimensions = tensorShapeDescription.GetInputTensorShape(0);
std::vector<DimensionType> indicesDimensions = tensorShapeDescription.GetInputTensorShape(1);
std::vector<DimensionType> updatesDimensions = tensorShapeDescription.GetInputTensorShape(2);
std::vector<DimensionType> 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<DML_TENSOR_DESC> inputDescs = GetDmlInputDescs();
std::vector<DML_TENSOR_DESC> 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<uint32_t>(dataDimensions.size());
operatorDesc.IndicesDimensionCount = static_cast<uint32_t>(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

View file

@ -58,7 +58,7 @@ public:
}
};
void CALLBACK QuerySlice(IMLOperatorSupportQueryContextPrivate* context, bool *isSupported)
void CALLBACK QuerySlice(IMLOperatorSupportQueryContextPrivate* context, bool* isSupported)
{
*isSupported = (context->GetInputCount() <= 5);
}

View file

@ -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
};

View file

@ -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";

View file

@ -6,84 +6,84 @@
namespace OperatorHelper
{
bool ContainsEmptyDimensions(gsl::span<const DimensionType> 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<const DimensionType> dimensions)
{
signedOnnxAxis += dimCount;
return std::find(dimensions.begin(), dimensions.end(), 0) != dimensions.end();
}
uint32_t absoluteAxis = gsl::narrow_cast<uint32_t>(signedOnnxAxis);
ML_CHECK_VALID_ARGUMENT(absoluteAxis < dimCount);
return absoluteAxis;
}
void HandleNegativeAxes(gsl::span<int32_t> 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<int32_t>& result
)
{
result.clear();
ML_CHECK_VALID_ARGUMENT(tensor.IsCpuData(), "Tensor must be CPU Tensor.");
const std::vector<uint32_t>& tensorDimensions = tensor.GetShape();
const uint32_t elementCount = ComputeElementCountFromDimensions(tensorDimensions);
switch (tensor.GetTensorDataType())
{
case MLOperatorTensorDataType::Int32:
if (signedOnnxAxis < 0)
{
const int32_t* data = tensor.GetData<int32_t>();
result.assign(data, data + elementCount);
signedOnnxAxis += dimCount;
}
break;
uint32_t absoluteAxis = gsl::narrow_cast<uint32_t>(signedOnnxAxis);
ML_CHECK_VALID_ARGUMENT(absoluteAxis < dimCount);
return absoluteAxis;
}
case MLOperatorTensorDataType::Int64:
void HandleNegativeAxes(gsl::span<int32_t> onnxAxes, uint32_t dimCount)
{
for (int32_t& axis : onnxAxes)
{
const int64_t* data = tensor.GetData<int64_t>();
result.reserve(elementCount);
for (auto d : gsl::make_span(data, data + elementCount))
axis = HandleNegativeAxis(axis, dimCount);
}
}
void ReadCpuLocalTensorIntoInt32(
const MLOperatorTensor& tensor,
std::vector<int32_t>& result
)
{
result.clear();
ML_CHECK_VALID_ARGUMENT(tensor.IsCpuData(), "Tensor must be CPU Tensor.");
const std::vector<uint32_t>& tensorDimensions = tensor.GetShape();
const uint32_t elementCount = ComputeElementCountFromDimensions(tensorDimensions);
switch (tensor.GetTensorDataType())
{
case MLOperatorTensorDataType::Int32:
{
result.push_back(gsl::narrow_cast<int32_t>(d));
const int32_t* data = tensor.GetData<int32_t>();
result.assign(data, data + elementCount);
}
break;
case MLOperatorTensorDataType::Int64:
{
const int64_t* data = tensor.GetData<int64_t>();
result.reserve(elementCount);
for (auto d : gsl::make_span(data, data + elementCount))
{
result.push_back(gsl::narrow_cast<int32_t>(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<const int64_t> inputDimensions, std::vector<DimensionType>& outputDimensions)
{
outputDimensions.reserve(inputDimensions.size());
outputDimensions.clear();
for (int64_t dim : inputDimensions)
void DowncastDimensions(gsl::span<const int64_t> inputDimensions, std::vector<DimensionType>& outputDimensions)
{
outputDimensions.push_back(gsl::narrow_cast<uint32_t>(std::clamp<int64_t>(dim, INT32_MIN, INT32_MAX)));
outputDimensions.reserve(inputDimensions.size());
outputDimensions.clear();
for (int64_t dim : inputDimensions)
{
outputDimensions.push_back(gsl::narrow_cast<uint32_t>(std::clamp<int64_t>(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<int64_t>(*reinterpret_cast<const float*>(p));
case MLOperatorTensorDataType::UInt8: return static_cast<int64_t>(*reinterpret_cast<const uint8_t*>(p));
case MLOperatorTensorDataType::Int8: return static_cast<int64_t>(*reinterpret_cast<const int8_t*>(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<double>(*reinterpret_cast<const float*>(p));
case MLOperatorTensorDataType::UInt8: return static_cast<double>(*reinterpret_cast<const uint8_t*>(p));
case MLOperatorTensorDataType::Int8: return static_cast<double>(*reinterpret_cast<const int8_t*>(p));
case MLOperatorTensorDataType::UInt16: return static_cast<double>(*reinterpret_cast<const uint16_t*>(p));
case MLOperatorTensorDataType::Int16: return static_cast<double>(*reinterpret_cast<const int16_t*>(p));
case MLOperatorTensorDataType::Int32: return static_cast<double>(*reinterpret_cast<const int32_t*>(p));
case MLOperatorTensorDataType::Int64: return static_cast<double>(*reinterpret_cast<const int64_t*>(p));
case MLOperatorTensorDataType::String: ML_INVALID_ARGUMENT("MLOperatorTensorDataType::String type is unsupported for reading as an integer.");
case MLOperatorTensorDataType::Bool: return static_cast<double>(*reinterpret_cast<const uint8_t*>(p));
case MLOperatorTensorDataType::Float16: ML_INVALID_ARGUMENT("MLOperatorTensorDataType::Float16 type is unsupported for reading as an integer.");
case MLOperatorTensorDataType::Double: return static_cast<double>(*reinterpret_cast<const double*>(p));
case MLOperatorTensorDataType::UInt32: return static_cast<double>(*reinterpret_cast<const uint32_t*>(p));
case MLOperatorTensorDataType::UInt64: return static_cast<double>(*reinterpret_cast<const uint64_t*>(p));
case MLOperatorTensorDataType::Complex64: return static_cast<double>(*reinterpret_cast<const float*>(p)); // Read the real component.
case MLOperatorTensorDataType::Complex128: return static_cast<double>(*reinterpret_cast<const double*>(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<EdgeShapes> GetOutputShapeAsInputShapeHelper::GetOutputShapes(const MLShapeInferenceContext& shapeInfo) const
{
assert(shapeInfo.GetInputCount() >= 1);
std::vector<DimensionType> outputDimensions = shapeInfo.GetInputTensorShape(0);
assert(shapeInfo.GetInputCount() > m_inputTensorIndex);
std::vector<DimensionType> outputDimensions = shapeInfo.GetInputTensorShape(m_inputTensorIndex);
return { std::move(outputDimensions) };
}
@ -531,15 +596,9 @@ int64_t ReadAsInt64(MLOperatorTensorDataType tensorDataType, const void* p)
gsl::span<const DimensionType> inputDimensions
)
{
m_axis = operatorAttributes.GetOptionalAttribute<int>(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<int>(inputDimensions.size());
}
int32_t signedOnnxAxis = operatorAttributes.GetOptionalAttribute<int>(AttrName::Axis, 0);
uint32_t inputRank = gsl::narrow_cast<int>(inputDimensions.size());
m_axis = HandleNegativeAxis(signedOnnxAxis, inputRank);
}
std::vector<EdgeShapes> 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<EdgeShapes> GatherNdHelper::GetOutputShapes(const MLShapeInferenceContext& shapeInfo) const
{
std::vector<DimensionType> inputDimensions = shapeInfo.GetInputTensorShape(0);
std::vector<DimensionType> 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<uint32_t>(inputDimensions.size()) - numberOfCoordinatesPerIndex;
const uint32_t numberOfOutputDimensionsFromIndices = static_cast<uint32_t>(indicesDimensions.size()) - 1; // Strip off last dimension.
uint32_t outputDimensionCount = gsl::narrow_cast<uint32_t>(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<DimensionType> 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<const DimensionType> 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<EdgeShapes> UnpoolingHelper::GetOutputShapes(const MLShapeInferenceContext& shapeInfo) const
{
std::vector<DimensionType> 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<uint32_t> 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<int64_t>();
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<int64_t> outputDimensions64bit = shapeInfo.GetAttributeVector<int64_t>(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<const int32_t> axes,
gsl::span<const DimensionType> inputDimensions
)
{
m_axes.assign(axes.begin(), axes.end());
HandleNegativeAxes(/*inout*/ m_axes, gsl::narrow_cast<uint32_t>(inputDimensions.size()));
std::sort(m_axes.begin(), m_axes.end());
}
std::vector<EdgeShapes> 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<const int32_t> axes,
gsl::span<const DimensionType> inputDimensions
)
{
m_axes.assign(axes.begin(), axes.end());
const uint32_t outputDimensionCount = gsl::narrow_cast<uint32_t>(inputDimensions.size() + axes.size());
HandleNegativeAxes(/*inout*/ m_axes, outputDimensionCount);
std::sort(m_axes.begin(), m_axes.end());
}
std::vector<EdgeShapes> 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<uint32_t>(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<uint32_t>(std::max((range / delta) + (range % delta != 0), int64_t(0)));
}
m_outputDimensions.push_back(totalElementCount);
}
std::vector<EdgeShapes> RangeHelper::GetOutputShapes(const MLShapeInferenceContext& shapeInfo) const
{
return { m_outputDimensions };
}
std::vector<EdgeShapes> OneHotHelper::GetOutputShapes(const MLShapeInferenceContext& shapeInfo) const
{
return { std::move(EdgeShapes(m_outputDimensions)) };

View file

@ -93,7 +93,11 @@ void FillWithLeadingValues(/*inout*/ std::vector<T>& 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<int32_t>& 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 <typename Info_t, typename Shape_t>
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 <typename Info_t, typename Shape_t>
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<EdgeShapes> GetOutputShapes(const MLShapeInferenceContext& shapeInfo) const;
uint32_t m_inputTensorIndex = 0;
};
template <uint32_t InputTensorIndex>
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 <typename Info_t, typename Shape_t>
GetOutputShapeAsSpecificInputShapeHelper(const Info_t& info, const Shape_t& shape)
: GetOutputShapeAsInputShapeHelper(info, shape, InputTensorIndex)
{}
};
class GetBroadcastedOutputShapeHelper {
@ -349,10 +378,10 @@ public:
);
}
const std::vector<DimensionType> inputDimensions = shapeInfo.GetInputTensorShape(0);
const std::vector<DimensionType> filterDims = shapeInfo.GetInputTensorShape(1);
const std::vector<DimensionType> inputDimensions = shapeInfo.GetInputTensorShape(0);
const std::vector<DimensionType> 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<int>(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<int>(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<int>(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<int>(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<int>(inputDimensions.size() - m_kernel.spatialDimensionCount);
const int dimOffset = gsl::narrow_cast<int>(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<int>((inputDimensions[i + dimOffset] - 1) * stride + windowSize - m_outputShapes[0].GetShape()[i + dimOffset]);
paddings = std::max<int>(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<int>((inputDimensions[i + dimOffset] - 1) * stride + windowSize - m_outputShapes[0].GetShape()[i + dimOffset]);
paddings = std::max<int>(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 <typename Info_t, typename Shape_t>
GatherNdHelper(const Info_t& info, const Shape_t& shape) {
}
std::vector<EdgeShapes> 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<typename Info_t, typename Shape_t>
UnpoolingHelper(
const Info_t& info,
const Shape_t& shape
)
: m_inputShape(shape.GetInputTensorShape(0)),
m_kernel(InitializeKernel(info, static_cast<uint32_t>(m_inputShape.size()), gsl::span<uint32_t>()))
{
Initialize();
}
void Initialize();
std::vector<EdgeShapes> GetOutputShapes(const MLShapeInferenceContext& shapeInfo) const;
protected:
std::vector<DimensionType> m_inputShape;
std::vector<DimensionType> m_inferredOutputDimensions;
KernelArgs m_kernel;
};
class GlobalPoolingHelper : public PoolingHelperBase {
public:
template <typename Info_t, typename Shape_t>
@ -953,12 +1019,17 @@ class RoiPoolingHelper {
class SqueezeHelper {
public:
void Initialize(
gsl::span<const int32_t> axes,
gsl::span<const DimensionType> 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 <typename Info_t, typename Shape_t>
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<EdgeShapes> GetOutputShapes(const MLShapeInferenceContext& shapeInfo) const;
@ -969,12 +1040,17 @@ class SqueezeHelper {
class UnsqueezeHelper {
public:
void Initialize(
gsl::span<const int32_t> axes,
gsl::span<const DimensionType> 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 <typename Info_t, typename Shape_t>
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<EdgeShapes> GetOutputShapes(const MLShapeInferenceContext& shapeInfo) const;
@ -1124,6 +1200,37 @@ class ResizeHelper {
std::vector<float> 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 <typename Info_t, typename Shape_t>
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<EdgeShapes> GetOutputShapes(const MLShapeInferenceContext& shapeInfo) const;
protected:
std::vector<DimensionType> m_outputDimensions;
MLOperatorTensorDataType m_tensorDataType = MLOperatorTensorDataType::Undefined;
using TensorScalarData = typename std::aligned_storage_t<sizeof(double), alignof(double)>;
TensorScalarData m_valueStart;
TensorScalarData m_valueLimit;
TensorScalarData m_valueDelta;
};
class OneHotHelper {
public:
template <typename Info_t, typename Shape_t>
@ -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<uint32_t>(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;

View file

@ -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;