mirror of
https://github.com/saymrwulf/onnxruntime.git
synced 2026-07-30 20:18:08 +00:00
Merge pull request #10619 from microsoft/user/dwayner/DmlDev20220221
Update DirectML EP for ORT 1.11
This commit is contained in:
commit
ea7f773a6e
16 changed files with 950 additions and 576 deletions
|
|
@ -124,8 +124,12 @@ namespace Dml::GraphDescBuilder
|
|||
// Check whether this specific node requested support for constant CPU inputs
|
||||
if (std::find(requiredConstantCpuInputs.begin(), requiredConstantCpuInputs.end(), inputIndex) != requiredConstantCpuInputs.end())
|
||||
{
|
||||
const onnxruntime::NodeArg* arg = node.InputDefs()[inputIndex];
|
||||
tensor = constantCpuGraphInputGetter(arg->Name());
|
||||
auto inputDefs = node.InputDefs();
|
||||
if (inputIndex < inputDefs.size())
|
||||
{
|
||||
const onnxruntime::NodeArg* arg = inputDefs[inputIndex];
|
||||
tensor = constantCpuGraphInputGetter(arg->Name());
|
||||
}
|
||||
}
|
||||
|
||||
return tensor;
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
#include "GraphPartitioner.h"
|
||||
#include "core/providers/dml/OperatorAuthorHelper/Attributes.h"
|
||||
#include "core/providers/dml/OperatorAuthorHelper/OperatorHelper.h"
|
||||
#include "core/providers/dml/OperatorAuthorHelper/OperatorRegistration.h"
|
||||
#include "core/providers/dml/OperatorAuthorHelper/OperatorVersions.h"
|
||||
#include "core/framework/kernel_registry.h"
|
||||
#include "core/graph/graph_utils.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -505,41 +505,53 @@ public:
|
|||
std::vector<uint32_t> outputShape = kernelInfo.GetTensorShapeDescription().GetOutputTensorShape(0);
|
||||
const uint32_t outputShapeDimCount = gsl::narrow_cast<uint32_t>(outputShape.size());
|
||||
|
||||
Initialize(kernelInfo, std::nullopt, std::nullopt, outputShape);
|
||||
Initialize(kernelInfo, std::nullopt, std::nullopt);
|
||||
|
||||
// If the axis attribute is explicitly provided, then broadcasting must be performed along that axis.
|
||||
// So massage the actual shapes of the scale and zero-point tensors (1D with length equal to the input
|
||||
// axis being broadcast to) into broadcastable shapes.
|
||||
uint32_t axis = 0;
|
||||
uint32_t broadcastAxisLength = 0;
|
||||
|
||||
// If an axis was given explicitly passed (or the default value 1 is set from the schema),
|
||||
// then other inputs are broadcasting to the shape of the input data tensor.
|
||||
if (kernelInfo.HasAttribute(AttrName::Axis, MLOperatorAttributeType::Int))
|
||||
{
|
||||
const int32_t signedAxis = gsl::narrow_cast<int32_t>(kernelInfo.GetAttribute<int64_t>(AttrName::Axis));
|
||||
const uint32_t axis = Dml::HandleNegativeAxis(signedAxis, outputShapeDimCount);
|
||||
const uint32_t broadcastAxisLength = outputShape[axis];
|
||||
axis = Dml::HandleNegativeAxis(signedAxis, outputShapeDimCount);
|
||||
broadcastAxisLength = outputShape[axis];
|
||||
}
|
||||
|
||||
// Explicitly reshape each of the inputs after the first input (scale and zero point tensors).
|
||||
for (uint32_t index = 1, inputCount = gsl::narrow_cast<uint32_t>(m_inputTensorDescs.size()); index < inputCount; ++index)
|
||||
|
||||
// Explicitly reshape each of the inputs after the first input (scale and zero point tensors).
|
||||
for (uint32_t index = 1, inputCount = gsl::narrow_cast<uint32_t>(m_inputTensorDescs.size()); index < inputCount; ++index)
|
||||
{
|
||||
auto edgeDesc = kernelInfo.GetInputEdgeDescription(index);
|
||||
assert(edgeDesc.edgeType == MLOperatorEdgeType::Tensor);
|
||||
|
||||
// Fix up the the tensor shape by filling with trailing ones. So input[2,3] with axis=0 and scale[2]
|
||||
// becomes scale[2,1], so that broadcasting works correctly.
|
||||
std::vector<uint32_t> inputTensorShape = kernelInfo.GetTensorShapeDescription().GetInputTensorShape(index);
|
||||
|
||||
// If the input tensor is a 1D vector, then extra massaging is needed to project their
|
||||
// 1D vectors back to the full shape for broadcasting along the given axis.
|
||||
// The 1D vector should have a length equal to the output tensor's dimension on that axis.
|
||||
if (inputTensorShape.size() == 1 && inputTensorShape != outputShape)
|
||||
{
|
||||
auto edgeDesc = kernelInfo.GetInputEdgeDescription(index);
|
||||
assert(edgeDesc.edgeType == MLOperatorEdgeType::Tensor);
|
||||
|
||||
// Fix up the the tensor shape by filling with trailing ones. So input[2,3] with axis=0 and scale[2]
|
||||
// becomes scale[2,1], so that broadcasting works correctly.
|
||||
std::vector<uint32_t> adjustedInputTensorShape = kernelInfo.GetTensorShapeDescription().GetInputTensorShape(index);
|
||||
ML_CHECK_VALID_ARGUMENT(adjustedInputTensorShape.size() == 1);
|
||||
ML_CHECK_VALID_ARGUMENT(adjustedInputTensorShape[0] == broadcastAxisLength);
|
||||
adjustedInputTensorShape.insert(adjustedInputTensorShape.end(), outputShapeDimCount - 1 - axis, 1);
|
||||
|
||||
m_inputTensorDescs[index] = TensorDesc(
|
||||
edgeDesc.tensorDataType,
|
||||
gsl::make_span(outputShape),
|
||||
gsl::make_span(adjustedInputTensorShape),
|
||||
TensorAxis::DoNotCoerce,
|
||||
TensorAxis::W,
|
||||
TensorAxis::RightAligned,
|
||||
NchwDimensionCount, // minDimensionCount
|
||||
0 // guaranteedBaseOffsetAlignment
|
||||
);
|
||||
ML_CHECK_VALID_ARGUMENT(inputTensorShape[0] == broadcastAxisLength);
|
||||
inputTensorShape.insert(inputTensorShape.begin(), axis, 1);
|
||||
inputTensorShape.insert(inputTensorShape.end(), outputShapeDimCount - 1 - axis, 1);
|
||||
}
|
||||
// For any other shape (scalar/ND), leave it alone, and the TensorDesc constructor
|
||||
// will apply broadcasting with standard elementwise alignment.
|
||||
|
||||
m_inputTensorDescs[index] = TensorDesc(
|
||||
edgeDesc.tensorDataType,
|
||||
gsl::make_span(outputShape),
|
||||
gsl::make_span(inputTensorShape),
|
||||
TensorAxis::DoNotCoerce,
|
||||
TensorAxis::W,
|
||||
TensorAxis::RightAligned,
|
||||
NchwDimensionCount, // minDimensionCount
|
||||
0 // guaranteedBaseOffsetAlignment
|
||||
);
|
||||
}
|
||||
|
||||
std::vector<DML_TENSOR_DESC> inputDescs = GetDmlInputDescs();
|
||||
|
|
|
|||
|
|
@ -14,44 +14,51 @@ public:
|
|||
DML_REDUCE_FUNCTION function
|
||||
)
|
||||
: DmlOperator(kernelInfo),
|
||||
ReduceHelperBase(kernelInfo,
|
||||
kernelInfo.GetTensorShapeDescription(),
|
||||
(function != DML_REDUCE_FUNCTION_ARGMAX && function != DML_REDUCE_FUNCTION_ARGMIN))
|
||||
ReduceHelperBase(
|
||||
kernelInfo,
|
||||
kernelInfo.GetTensorShapeDescription(),
|
||||
(function != DML_REDUCE_FUNCTION_ARGMAX && function != DML_REDUCE_FUNCTION_ARGMIN)
|
||||
)
|
||||
{
|
||||
ML_CHECK_VALID_ARGUMENT(kernelInfo.GetInputCount() == 1);
|
||||
ML_CHECK_VALID_ARGUMENT(kernelInfo.GetInputCount() >= 1);
|
||||
ML_CHECK_VALID_ARGUMENT(kernelInfo.GetOutputCount() == 1);
|
||||
DmlOperator::Initialize(kernelInfo);
|
||||
std::vector<std::optional<uint32_t>> inputIndices = { 0 };
|
||||
std::vector<std::optional<uint32_t>> outputIndices = { 0 };
|
||||
DmlOperator::Initialize(kernelInfo, inputIndices, outputIndices, std::nullopt, std::nullopt, 1u);
|
||||
|
||||
std::vector<uint32_t> dmlAxes;
|
||||
std::vector<DimensionType> reducedDims = kernelInfo.GetTensorShapeDescription().GetInputTensorShape(0);
|
||||
int dimOffset = gsl::narrow_cast<int>(m_inputTensorDescs[0].GetDimensionCount() - reducedDims.size());
|
||||
for (auto& dim : m_axes)
|
||||
{
|
||||
// Replace all reduced axes with 1 for their size.
|
||||
assert(dim < static_cast<int32_t>(reducedDims.size())); // ReduceHelperBase already validated this.
|
||||
reducedDims[dim] = 1;
|
||||
dmlAxes.push_back(static_cast<uint32_t>(dim + dimOffset));
|
||||
dmlAxes.push_back(static_cast<uint32_t>(dim)); // Signed to unsigned which DML expects.
|
||||
}
|
||||
|
||||
if (!m_keepDims)
|
||||
{
|
||||
// DML doesn't know about keepDim and always assume the dim is preserved after reduce.
|
||||
// DML expects the input and output tensors to have identical counts and doesn't know about
|
||||
// ONNX's 'keepdims' attribute, keeping all dimensions anyway rather removing those of size 1.
|
||||
// So if m_keepDims is false, the ONNX output dim is different than DML tensor desc dim.
|
||||
// ReduceSum example:
|
||||
// input dims: {3, 2, 2}
|
||||
// axes: 1
|
||||
// keepDims: 0
|
||||
//
|
||||
// the ONNX output expect to be of dim {3, 2}, while DML expect the output tensor desc
|
||||
// dim to be {3, 1, 2}.
|
||||
//
|
||||
// ReduceSum example:
|
||||
// input dims: {3, 2, 2}
|
||||
// axes: 1
|
||||
// keepDims: 0
|
||||
//
|
||||
// The ONNX output expects output dims of {3, 2},
|
||||
// while DML expect the output tensor desc of {3, 1, 2}.
|
||||
|
||||
m_outputTensorDescs[0] = CreateTensorDescFromOutput(
|
||||
kernelInfo,
|
||||
0,
|
||||
TensorAxis::DoNotCoerce,
|
||||
TensorAxis::W,
|
||||
kernelInfo,
|
||||
0,
|
||||
TensorAxis::DoNotCoerce,
|
||||
TensorAxis::W,
|
||||
TensorAxis::RightAligned,
|
||||
reducedDims);
|
||||
reducedDims,
|
||||
1 // minimumDimensionCount
|
||||
);
|
||||
}
|
||||
|
||||
std::vector<DML_TENSOR_DESC> inputDescs = GetDmlInputDescs();
|
||||
|
|
|
|||
|
|
@ -19,9 +19,10 @@ constexpr NameAndIndex coordinateTransformationModes[] =
|
|||
constexpr NameAndIndex nearestNeighborRoundingModes[] =
|
||||
{
|
||||
{"", 0},
|
||||
{"round_prefer_floor", 0},
|
||||
{"round_prefer_ceil", 1},
|
||||
{"floor", 2},
|
||||
{"round_prefer_floor", 0}, // round halves down
|
||||
{"round_prefer_ceil", 1}, // round halves up
|
||||
{"floor", 2}, // round always down
|
||||
// {"ceil", 3}, // round always up (requires a DirectML API addition)
|
||||
};
|
||||
|
||||
void ComputePixelOffsetsAndScales(
|
||||
|
|
@ -338,9 +339,9 @@ void CALLBACK QueryResize(IMLOperatorSupportQueryContextPrivate* context, bool*
|
|||
|
||||
DML_OP_DEFINE_CREATION_FUNCTION(Resize10, VersionedKernel<DmlOperatorResize, 10>);
|
||||
DML_OP_DEFINE_CREATION_FUNCTION(Resize11, VersionedKernel<DmlOperatorResize, 11>);
|
||||
DML_OP_DEFINE_CREATION_FUNCTION(Resize13, VersionedKernel<DmlOperatorResize, 13>);
|
||||
DML_OP_DEFINE_CREATION_FUNCTION(Upsample7, VersionedKernel<DmlOperatorResize, 7>);
|
||||
DML_OP_DEFINE_CREATION_FUNCTION(Upsample9, VersionedKernel<DmlOperatorResize, 9>);
|
||||
DML_OP_DEFINE_CREATION_FUNCTION(Upsample10, VersionedKernel<DmlOperatorResize, 10>);
|
||||
DML_OP_DEFINE_CREATION_FUNCTION(Upsample13, VersionedKernel<DmlOperatorResize, 13>);
|
||||
|
||||
} // namespace Dml
|
||||
|
|
|
|||
|
|
@ -11,13 +11,18 @@ class DmlOperatorSplit : public DmlOperator, public SplitHelper
|
|||
public:
|
||||
using Self = DmlOperatorSplit;
|
||||
|
||||
DmlOperatorSplit(const MLOperatorKernelCreationContext& kernelInfo)
|
||||
DmlOperatorSplit(const MLOperatorKernelCreationContext& kernelInfo, uint32_t opsetVersion)
|
||||
: DmlOperator(kernelInfo),
|
||||
SplitHelper(kernelInfo, kernelInfo.GetTensorShapeDescription())
|
||||
SplitHelper(kernelInfo, kernelInfo.GetTensorShapeDescription(), opsetVersion)
|
||||
{
|
||||
ML_CHECK_VALID_ARGUMENT(kernelInfo.GetInputCount() == 1, "DML only supports split on a single input tensor.");
|
||||
ML_CHECK_VALID_ARGUMENT(kernelInfo.GetOutputCount() > 0, "Runtime error no output stream specified.");
|
||||
DmlOperator::Initialize(kernelInfo);
|
||||
ML_CHECK_VALID_ARGUMENT(kernelInfo.GetInputCount() > 0, "Splits needs an input tensor.");
|
||||
ML_CHECK_VALID_ARGUMENT(kernelInfo.GetOutputCount() > 0, "Splits needs an output tensor.");
|
||||
|
||||
// Use only the first input tensor. Later opset versions may pass parameters
|
||||
// like splits as dynamic parameters via tensors rather than constants,
|
||||
// and that second parameter is CPU based.
|
||||
std::vector<std::optional<uint32_t>> inputIndices = {0};
|
||||
DmlOperator::Initialize(kernelInfo, inputIndices, std::nullopt);
|
||||
|
||||
uint32_t dmlAxis = GetDmlAdjustedAxis(m_axis, kernelInfo, m_inputTensorDescs.front().GetDimensionCount());
|
||||
|
||||
|
|
@ -36,6 +41,8 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
DML_OP_DEFINE_CREATION_FUNCTION(Split, DmlOperatorSplit);
|
||||
DML_OP_DEFINE_CREATION_FUNCTION(Split7, VersionedKernel<DmlOperatorSplit, 7>);
|
||||
DML_OP_DEFINE_CREATION_FUNCTION(Split11, VersionedKernel<DmlOperatorSplit, 11>);
|
||||
DML_OP_DEFINE_CREATION_FUNCTION(Split13, VersionedKernel<DmlOperatorSplit, 13>);
|
||||
|
||||
} // namespace Dml
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
#include "precomp.h"
|
||||
#include "OperatorRegistration.h"
|
||||
#include "core/providers/dml/OperatorAuthorHelper/MLOperatorAuthorHelper.h"
|
||||
#include "core/providers/dml/OperatorAuthorHelper/OperatorRegistration.h"
|
||||
#include "core/providers/dml/OperatorAuthorHelper/OperatorVersions.h"
|
||||
#include "core/providers/dml/DmlExecutionProvider/inc/IWinmlExecutionProvider.h"
|
||||
#include "core/framework/customregistry.h"
|
||||
#include "onnx/defs/operator_sets.h"
|
||||
|
|
@ -103,7 +103,9 @@ DML_OP_EXTERN_CREATION_FUNCTION(GRU);
|
|||
DML_OP_EXTERN_CREATION_FUNCTION(LSTM);
|
||||
DML_OP_EXTERN_CREATION_FUNCTION(Gather);
|
||||
DML_OP_EXTERN_CREATION_FUNCTION(Flatten);
|
||||
DML_OP_EXTERN_CREATION_FUNCTION(Split);
|
||||
DML_OP_EXTERN_CREATION_FUNCTION(Split7);
|
||||
DML_OP_EXTERN_CREATION_FUNCTION(Split11);
|
||||
DML_OP_EXTERN_CREATION_FUNCTION(Split13);
|
||||
DML_OP_EXTERN_CREATION_FUNCTION(Transpose);
|
||||
DML_OP_EXTERN_CREATION_FUNCTION(Tile);
|
||||
DML_OP_EXTERN_CREATION_FUNCTION(Concat);
|
||||
|
|
@ -165,7 +167,6 @@ DML_OP_EXTERN_CREATION_FUNCTION(ImageScaler);
|
|||
DML_OP_EXTERN_CREATION_FUNCTION(Upsample7);
|
||||
DML_OP_EXTERN_CREATION_FUNCTION(Upsample9);
|
||||
DML_OP_EXTERN_CREATION_FUNCTION(Upsample10);
|
||||
DML_OP_EXTERN_CREATION_FUNCTION(Upsample13);
|
||||
DML_OP_EXTERN_CREATION_FUNCTION(Sigmoid);
|
||||
DML_OP_EXTERN_CREATION_FUNCTION(HardSigmoid);
|
||||
DML_OP_EXTERN_CREATION_FUNCTION(Tanh);
|
||||
|
|
@ -229,6 +230,7 @@ DML_OP_EXTERN_CREATION_FUNCTION(Scatter11);
|
|||
DML_OP_EXTERN_CREATION_FUNCTION(Scatter13);
|
||||
DML_OP_EXTERN_CREATION_FUNCTION(Resize10);
|
||||
DML_OP_EXTERN_CREATION_FUNCTION(Resize11);
|
||||
DML_OP_EXTERN_CREATION_FUNCTION(Resize13);
|
||||
DML_OP_EXTERN_CREATION_FUNCTION(ConstantOfShape);
|
||||
DML_OP_EXTERN_CREATION_FUNCTION(IsInf);
|
||||
DML_OP_EXTERN_CREATION_FUNCTION(Mod);
|
||||
|
|
@ -303,6 +305,7 @@ constexpr static std::array<SupportedTensorDataTypes, 2> supportedTypeListLogica
|
|||
constexpr static std::array<SupportedTensorDataTypes, 1> supportedTypeListSigned = { SupportedTensorDataTypes::Float16to32 | SupportedTensorDataTypes::Int64 | SupportedTensorDataTypes::Int32 | SupportedTensorDataTypes::Int16 | SupportedTensorDataTypes::Int8 };
|
||||
constexpr static std::array<SupportedTensorDataTypes, 1> supportedTypeListRange = {SupportedTensorDataTypes::Int16|SupportedTensorDataTypes::Int32|SupportedTensorDataTypes::Int64|SupportedTensorDataTypes::Float32};
|
||||
constexpr static std::array<SupportedTensorDataTypes, 2> supportedTypeListResize11 = {SupportedTensorDataTypes::Float16to32, SupportedTensorDataTypes::Float16to32 /* ROI read by CPU */};
|
||||
constexpr static std::array<SupportedTensorDataTypes, 2> supportedTypeListResize13 = supportedTypeListResize11;
|
||||
constexpr static std::array<SupportedTensorDataTypes, 3> supportedTypeListInteger = {SupportedTensorDataTypes::Int8|SupportedTensorDataTypes::UInt8, SupportedTensorDataTypes::Int8|SupportedTensorDataTypes::UInt8, SupportedTensorDataTypes::Int32 };
|
||||
constexpr static std::array<SupportedTensorDataTypes, 1> supportedTypeListInteger8 = {SupportedTensorDataTypes::Int8|SupportedTensorDataTypes::UInt8 };
|
||||
constexpr static std::array<SupportedTensorDataTypes, 2> supportedTypeListRoiAlign = {SupportedTensorDataTypes::Float16to32, SupportedTensorDataTypes::Int32|SupportedTensorDataTypes::Int64 };
|
||||
|
|
@ -333,7 +336,7 @@ constexpr auto requiredConstantCpuInputs(Args... args)
|
|||
return std::make_pair(inputs, static_cast<int>(sizeof...(args)));
|
||||
}
|
||||
|
||||
// Define a single row of registration information.
|
||||
// Define a single row of OperatorRegistrationInformation.
|
||||
#define REG_INFO(version, operatorName, ...) \
|
||||
#operatorName, OnnxOperatorSet##version::sc_sinceVer_##operatorName, onnxruntime::kOnnxDomain, Create##operatorName, ShapeInferenceFunction<ShapeInferenceHelper_##operatorName>, false, ##__VA_ARGS__,
|
||||
|
||||
|
|
@ -341,12 +344,10 @@ constexpr auto requiredConstantCpuInputs(Args... args)
|
|||
#define REG_INFO_VER(version, operatorName, ...) \
|
||||
#operatorName, OnnxOperatorSet##version::sc_sinceVer_##operatorName, onnxruntime::kOnnxDomain, Create##operatorName##version, ShapeInferenceFunction<ShapeInferenceHelper_##operatorName##version>, false, ##__VA_ARGS__,
|
||||
|
||||
// Identity operators use Copy, alias their first input, and require floating point formats
|
||||
// for usage in the graph, besides constant inputs. This is because they currently use
|
||||
// element-wise identity operators in the graph for striding support, but issue actual copies
|
||||
// outside the graph. Element-wise identity currently only supports floating point types.
|
||||
// Identity operators use Copy, alias their first input, and use elementwise identity operators
|
||||
// when needed for striding support, but issue actual copies outside the graph.
|
||||
#define REG_INFO_ID(version, operatorName, ...) \
|
||||
#operatorName, OnnxOperatorSet##version::sc_sinceVer_##operatorName, onnxruntime::kOnnxDomain, CreateCopy, ShapeInferenceFunction<ShapeInferenceHelper_##operatorName>, true, ##__VA_ARGS__,
|
||||
#operatorName, OnnxOperatorSet##version::sc_sinceVer_##operatorName, onnxruntime::kOnnxDomain, CreateCopy, ShapeInferenceFunction<ShapeInferenceHelper_##operatorName##version>, true, ##__VA_ARGS__,
|
||||
|
||||
// MS-domain operators
|
||||
#define REG_INFO_MS(version, operatorName, ...) \
|
||||
|
|
@ -398,8 +399,9 @@ constexpr static OperatorRegistrationInformation operatorRegistrationInformation
|
|||
{REG_INFO_MS( 1, ConvTransposeWithDynamicPads, typeNameListDefault, supportedTypeListFloat16to32, DmlGraphSupport::Supported, requiredConstantCpuInputs(2))},
|
||||
|
||||
// Data Reorganization Layers
|
||||
{REG_INFO( 7, Split, typeNameListDefault, supportedTypeListAllScalars, DmlGraphSupport::Supported)},
|
||||
{REG_INFO( 11, Split, typeNameListDefault, supportedTypeListAllScalars, DmlGraphSupport::Supported)}, // Adds negative axis.
|
||||
{REG_INFO_VER( 7, Split, typeNameListDefault, supportedTypeListAllScalars, DmlGraphSupport::Supported)},
|
||||
{REG_INFO_VER( 11, Split, typeNameListDefault, supportedTypeListAllScalars, DmlGraphSupport::Supported)}, // Adds negative axis.
|
||||
{REG_INFO_VER( 13, Split, typeNameListDefault, supportedTypeListAllScalars, DmlGraphSupport::Supported, requiredConstantCpuInputs(1))}, // Moves splits from constant parameter to dynamic input.
|
||||
{REG_INFO( 7, Transpose, typeNameListDefault, supportedTypeListAllScalars, DmlGraphSupport::Supported)},
|
||||
{REG_INFO( 13, Transpose, typeNameListDefault, supportedTypeListAllScalars, DmlGraphSupport::Supported)},
|
||||
{REG_INFO( 7, Concat, typeNameListDefault, supportedTypeListAllScalars, DmlGraphSupport::Supported)},
|
||||
|
|
@ -448,10 +450,12 @@ constexpr static OperatorRegistrationInformation operatorRegistrationInformation
|
|||
{REG_INFO_ID( 13, Flatten, typeNameListDefault, supportedTypeListAllScalars, DmlGraphSupport::Supported)},
|
||||
{REG_INFO_ID( 7, Squeeze, typeNameListDefault, supportedTypeListAllScalars, DmlGraphSupport::Supported)},
|
||||
{REG_INFO_ID( 11, Squeeze, typeNameListDefault, supportedTypeListAllScalars, DmlGraphSupport::Supported)},
|
||||
{REG_INFO_ID( 13, Squeeze, typeNameListDefault, supportedTypeListAllScalars, DmlGraphSupport::Supported, requiredConstantCpuInputs(1))},
|
||||
{REG_INFO_ID( 7, Unsqueeze, typeNameListDefault, supportedTypeListAllScalars, DmlGraphSupport::Supported)},
|
||||
{REG_INFO_ID( 11, Unsqueeze, typeNameListDefault, supportedTypeListAllScalars, DmlGraphSupport::Supported)},
|
||||
{REG_INFO_ID( 7, Reshape, typeNameListDefault, supportedTypeListAllScalars, DmlGraphSupport::Supported, requiredConstantCpuInputs(1))},
|
||||
{REG_INFO_ID( 13, Reshape, typeNameListDefault, supportedTypeListAllScalars, DmlGraphSupport::Supported, requiredConstantCpuInputs(1))},
|
||||
{REG_INFO_ID( 13, Unsqueeze, typeNameListDefault, supportedTypeListAllScalars, DmlGraphSupport::Supported, requiredConstantCpuInputs(1))},
|
||||
{REG_INFO_ID( 7, Reshape, typeNameListDefault, supportedTypeListAllScalars, DmlGraphSupport::Supported, requiredConstantCpuInputs(1))},
|
||||
{REG_INFO_ID( 13, Reshape, typeNameListDefault, supportedTypeListAllScalars, DmlGraphSupport::Supported, requiredConstantCpuInputs(1))},
|
||||
|
||||
// Elementwise
|
||||
{REG_INFO( 7, Sqrt, typeNameListDefault, supportedTypeListFloat16to32, DmlGraphSupport::Supported)},
|
||||
|
|
@ -505,7 +509,9 @@ constexpr static OperatorRegistrationInformation operatorRegistrationInformation
|
|||
{REG_INFO( 7, Atan, typeNameListDefault, supportedTypeListFloat16to32, DmlGraphSupport::Supported)},
|
||||
{REG_INFO( 7, Affine, typeNameListDefault, supportedTypeListFloat16to32, DmlGraphSupport::Supported)},
|
||||
{REG_INFO( 10, QuantizeLinear, typeNameListTwo, supportedTypeListQuantizeLinear, DmlGraphSupport::Supported)},
|
||||
{REG_INFO( 13, QuantizeLinear, typeNameListTwo, supportedTypeListQuantizeLinear, DmlGraphSupport::Supported)},
|
||||
{REG_INFO( 10, DequantizeLinear, typeNameListTwo, supportedTypeListDequantizeLinear, DmlGraphSupport::Supported)},
|
||||
{REG_INFO( 13, DequantizeLinear, typeNameListTwo, supportedTypeListDequantizeLinear, DmlGraphSupport::Supported)},
|
||||
{REG_INFO_MS( 1, QuantizeLinear, typeNameListTwo, supportedTypeListQuantize, DmlGraphSupport::Supported)},
|
||||
{REG_INFO_MS( 1, DequantizeLinear, typeNameListTwo, supportedTypeListQuantize, DmlGraphSupport::Supported)},
|
||||
{REG_INFO( 9, Sign, typeNameListDefault, supportedTypeListNumericDefault, DmlGraphSupport::Supported)},
|
||||
|
|
@ -522,6 +528,7 @@ constexpr static OperatorRegistrationInformation operatorRegistrationInformation
|
|||
{REG_INFO( 9, Where, typeNameListWhere, supportedTypeListWhere, DmlGraphSupport::Supported)},
|
||||
{REG_INFO( 7, ReduceSum, typeNameListDefault, supportedTypeListFloat16to32Ints32to64, DmlGraphSupport::Supported)},
|
||||
{REG_INFO( 11, ReduceSum, typeNameListDefault, supportedTypeListFloat16to32Ints32to64, DmlGraphSupport::Supported)},
|
||||
{REG_INFO( 13, ReduceSum, typeNameListDefault, supportedTypeListFloat16to32Ints32to64, DmlGraphSupport::Supported, requiredConstantCpuInputs(1))},
|
||||
{REG_INFO_VER( 12, Einsum, typeNameListDefault, supportedTypeListFloat16to32, DmlGraphSupport::Supported, requiredConstantCpuInputs(), std::nullopt, QueryEinSum )},
|
||||
{REG_INFO( 7, ReduceMean, typeNameListDefault, supportedTypeListFloat16to32, DmlGraphSupport::Supported)},
|
||||
{REG_INFO( 11, ReduceMean, typeNameListDefault, supportedTypeListFloat16to32, DmlGraphSupport::Supported)},
|
||||
|
|
@ -588,9 +595,9 @@ constexpr static OperatorRegistrationInformation operatorRegistrationInformation
|
|||
{REG_INFO_VER( 7, Upsample, typeNameListDefault, supportedTypeListFloat16to32, DmlGraphSupport::Supported)},
|
||||
{REG_INFO_VER( 9, Upsample, typeNameListDefault, supportedTypeListFloat16to32, DmlGraphSupport::Supported, requiredConstantCpuInputs(1) /*scales*/)},
|
||||
{REG_INFO_VER( 10, Upsample, typeNameListDefault, supportedTypeListFloat16to32, DmlGraphSupport::Supported, requiredConstantCpuInputs(1) /*scales*/)},
|
||||
{REG_INFO_VER( 13, Upsample, typeNameListDefault, supportedTypeListFloat16to32, DmlGraphSupport::Supported, requiredConstantCpuInputs(1) /*scales*/)},
|
||||
{REG_INFO_VER( 10, Resize, typeNameListDefault, supportedTypeListFloat16to32, DmlGraphSupport::Supported, requiredConstantCpuInputs(1) /*scales*/)},
|
||||
{REG_INFO_VER( 11, Resize, typeNameListTwo, supportedTypeListResize11, DmlGraphSupport::Supported, requiredConstantCpuInputs(1, 2, 3) /*roi, scales, sizes*/, std::nullopt, QueryResize)},
|
||||
{REG_INFO_VER( 13, Resize, typeNameListTwo, supportedTypeListResize13, DmlGraphSupport::Supported, requiredConstantCpuInputs(1, 2, 3) /*roi, scales, sizes*/, std::nullopt, QueryResize)},
|
||||
|
||||
// Activation Functions
|
||||
{REG_INFO( 7, Sigmoid, typeNameListDefault, supportedTypeListFloat16to32, DmlGraphSupport::Supported)},
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include "precomp.h"
|
||||
#include "OperatorUtility.h"
|
||||
#include "core/providers/dml/OperatorAuthorHelper/OperatorRegistration.h"
|
||||
#include "core/providers/dml/OperatorAuthorHelper/OperatorVersions.h"
|
||||
|
||||
namespace Dml
|
||||
{
|
||||
|
|
|
|||
|
|
@ -7,4 +7,4 @@
|
|||
#include "core/providers/dml/OperatorAuthorHelper/Attributes.h"
|
||||
#include "core/providers/dml/OperatorAuthorHelper/OperatorHelper.h"
|
||||
#include "DmlOperator.h"
|
||||
#include "OperatorRegistration.h"
|
||||
#include "OperatorRegistration.h"
|
||||
|
|
|
|||
|
|
@ -47,7 +47,6 @@ namespace AttrName
|
|||
static constexpr const char* InputForget = "input_forget";
|
||||
static constexpr const char* K = "k";
|
||||
static constexpr const char* KeepDims = "keepdims";
|
||||
static constexpr const char* SelectLastIndex = "select_last_index";
|
||||
static constexpr const char* KernelShape = "kernel_shape";
|
||||
static constexpr const char* LinearBeforeReset = "linear_before_reset";
|
||||
static constexpr const char* Lambda = "lambd"; // Deliberate typo to match ONNX spec.
|
||||
|
|
@ -58,6 +57,7 @@ namespace AttrName
|
|||
static constexpr const char* Min = "min";
|
||||
static constexpr const char* Mode = "mode";
|
||||
static constexpr const char* NearestMode = "nearest_mode";
|
||||
static constexpr const char* NoopWithEmptyAxes = "noop_with_empty_axes";
|
||||
static constexpr const char* NormalizeVariance = "normalize_variance";
|
||||
static constexpr const char* P = "p";
|
||||
static constexpr const char* OutputHeight = "output_height";
|
||||
|
|
@ -72,6 +72,7 @@ namespace AttrName
|
|||
static constexpr const char* Scale = "scale";
|
||||
static constexpr const char* Scales = "scales";
|
||||
static constexpr const char* Seed = "seed";
|
||||
static constexpr const char* SelectLastIndex = "select_last_index";
|
||||
static constexpr const char* Shape = "shape";
|
||||
static constexpr const char* Size = "size";
|
||||
static constexpr const char* Sorted = "sorted";
|
||||
|
|
|
|||
|
|
@ -190,10 +190,10 @@ class MLOperatorTensorShapeDescription
|
|||
return ret;
|
||||
}
|
||||
|
||||
Microsoft::WRL::ComPtr<IMLOperatorTensorShapeDescription> GetInterface() const { return m_impl; }
|
||||
Microsoft::WRL::ComPtr<IMLOperatorTensorShapeDescription> GetInterface() const noexcept { return m_impl; }
|
||||
|
||||
protected:
|
||||
Microsoft::WRL::ComPtr<IMLOperatorTensorShapeDescription> m_impl ;
|
||||
Microsoft::WRL::ComPtr<IMLOperatorTensorShapeDescription> m_impl;
|
||||
};
|
||||
|
||||
class MLOperatorAttributes
|
||||
|
|
@ -203,6 +203,12 @@ class MLOperatorAttributes
|
|||
{
|
||||
}
|
||||
|
||||
// For cases of interop where the caller needs to pass the unwrapped class across a boundary.
|
||||
Microsoft::WRL::ComPtr<IMLOperatorAttributes> GetInterface() const noexcept
|
||||
{
|
||||
return m_impl;
|
||||
}
|
||||
|
||||
uint32_t GetAttributeElementCount(
|
||||
_In_z_ MLConstStringParam name,
|
||||
MLOperatorAttributeType type) const
|
||||
|
|
@ -638,7 +644,7 @@ public:
|
|||
MLOperatorTypeInferenceContext(IMLOperatorTypeInferenceContext* impl) : MLOperatorAttributes(impl), m_impl(impl) {}
|
||||
|
||||
// For cases of interop where the caller needs to pass the unwrapped class across a boundary.
|
||||
Microsoft::WRL::ComPtr<IMLOperatorTypeInferenceContext> GetInterface() const noexcept
|
||||
Microsoft::WRL::ComPtr<IMLOperatorTypeInferenceContext> GetInterface() const noexcept
|
||||
{
|
||||
return m_impl;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -617,6 +617,122 @@ namespace OperatorHelper
|
|||
return outputShape;
|
||||
}
|
||||
|
||||
void ConvolutionHelperBase::InitializeKernelAndShapes(const IShapeInformationAdapter& shapeInformation)
|
||||
{
|
||||
const std::vector<DimensionType> inputDimensions = shapeInformation.GetInputTensorShape(m_inputTensorIndex);
|
||||
const std::vector<DimensionType> filterDims = shapeInformation.GetInputTensorShape(m_filterTensorIndex);
|
||||
|
||||
ML_CHECK_VALID_ARGUMENT(
|
||||
inputDimensions.size() >= 3 && inputDimensions.size() <= 5,
|
||||
"Input dimensions must be: 3, 4, 5."
|
||||
);
|
||||
|
||||
ResolvingPadding(inputDimensions);
|
||||
|
||||
m_outputShapes.resize(1);
|
||||
m_outputShapes[0] = InitializeKernelOutputDimensions(inputDimensions, m_kernel);
|
||||
m_outputShapes[0].GetShape()[C] = filterDims[K];
|
||||
}
|
||||
|
||||
void ConvolutionHelperBase::InitializeKernelAndShapesTransposed(
|
||||
const IKernelInformationAdapter& kernelInformation,
|
||||
const IShapeInformationAdapter& shapeInformation,
|
||||
bool hasDynamicPads
|
||||
)
|
||||
{
|
||||
auto& attributes = kernelInformation.GetAttributes();
|
||||
std::vector<int> outputShape = attributes.GetOptionalAttributeVectorInt32(AttrName::OutputShape);
|
||||
if (!outputShape.empty())
|
||||
{
|
||||
ML_CHECK_VALID_ARGUMENT(
|
||||
outputShape.size() >= m_kernel.spatialDimensionCount,
|
||||
"The output shape must equal the number of spatial dimensions"
|
||||
);
|
||||
}
|
||||
|
||||
const std::vector<DimensionType> inputDimensions = shapeInformation.GetInputTensorShape(m_inputTensorIndex);
|
||||
const std::vector<DimensionType> filterDims = shapeInformation.GetInputTensorShape(m_filterTensorIndex);
|
||||
|
||||
ML_CHECK_VALID_ARGUMENT(inputDimensions.size() > NonspatialDimensionCount, "Input dimensions must be >= 3");
|
||||
|
||||
if (hasDynamicPads)
|
||||
{
|
||||
MLOperatorTensor padsTensor = kernelInformation.GetConstantInputTensor(2);
|
||||
const std::vector<uint32_t>& padsTensorDimensions = padsTensor.GetShape();
|
||||
ML_CHECK_VALID_ARGUMENT(padsTensorDimensions.size() == 1, "Pads dimensions must equal 1");
|
||||
const size_t dimCount = padsTensorDimensions[0];
|
||||
ML_CHECK_VALID_ARGUMENT(dimCount == 2 * NchwSpatialDimensionCount, "Pads count must equal 4");
|
||||
const int64_t* padsData = padsTensor.GetData<int64_t>();
|
||||
|
||||
for (size_t i = 0; i < dimCount; ++i)
|
||||
{
|
||||
ML_CHECK_VALID_ARGUMENT(padsData[i] >= 0, "Padding values must be greater than or equal to 0");
|
||||
if (i < dimCount / 2)
|
||||
{
|
||||
m_kernel.startPadding[i] = gsl::narrow_cast<uint32_t>(padsData[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_kernel.endPadding[i - dimCount/2] = gsl::narrow_cast<uint32_t>(padsData[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ResolvingPadding(inputDimensions);
|
||||
}
|
||||
|
||||
m_outputShapes.resize(1);
|
||||
m_outputShapes[0] = InitializeKernelOutputDimsTranspose(inputDimensions, m_kernel);
|
||||
static_assert(C < NonspatialDimensionCount);
|
||||
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.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];
|
||||
}
|
||||
|
||||
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];
|
||||
|
||||
// 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];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<EdgeShapes> ConvolutionHelperBase::GetOutputShapes(const MLShapeInferenceContext& shapeInformation) const
|
||||
{
|
||||
ORT_UNUSED_PARAMETER(shapeInformation);
|
||||
return m_outputShapes;
|
||||
}
|
||||
|
||||
void ConvolutionHelperBase::ResolvingPadding(gsl::span<const DimensionType> inputDimensions)
|
||||
{
|
||||
ResolveAutoPadding(m_kernel, inputDimensions);
|
||||
|
|
@ -638,13 +754,30 @@ namespace OperatorHelper
|
|||
}
|
||||
|
||||
void SplitHelper::Initialize(
|
||||
const MLOperatorAttributes& operatorAttributes,
|
||||
gsl::span<const DimensionType> inputDimensions
|
||||
IKernelInformationAdapter const& kernelInformation,
|
||||
IShapeInformationAdapter const& shapeInformation,
|
||||
uint32_t opsetVersion
|
||||
)
|
||||
{
|
||||
auto& operatorAttributes = kernelInformation.GetAttributes();
|
||||
if (opsetVersion >= 13) // Axes are a dynamic input parameter.
|
||||
{
|
||||
// The tensor is optional, which if empty, means to default to equal splits.
|
||||
if (kernelInformation.IsInputValid(1))
|
||||
{
|
||||
ReadCpuLocalTensorIntoInt32(kernelInformation.GetConstantInputTensor(1), /*out*/ m_split);
|
||||
}
|
||||
}
|
||||
else // Axes were a constant attribute parameter.
|
||||
{
|
||||
m_split = operatorAttributes.GetOptionalAttributeVectorInt32(AttrName::Split);
|
||||
}
|
||||
|
||||
const std::vector<DimensionType> inputDimensions = shapeInformation.GetInputTensorShape(0);
|
||||
|
||||
const uint32_t inputDimCount = gsl::narrow_cast<int32_t>(inputDimensions.size());
|
||||
m_axis = static_cast<int>(HandleNegativeAxis(operatorAttributes.GetOptionalAttribute<int32_t>(AttrName::Axis, 0), inputDimCount));
|
||||
m_split = operatorAttributes.GetOptionalAttributeVectorInt32(AttrName::Split);
|
||||
const uint32_t axis = operatorAttributes.GetOptionalAttribute<int32_t>(AttrName::Axis, 0);
|
||||
m_axis = static_cast<int>(HandleNegativeAxis(axis, inputDimCount));
|
||||
}
|
||||
|
||||
std::vector<EdgeShapes> SplitHelper::GetOutputShapes(const MLShapeInferenceContext& shapeInfo) const
|
||||
|
|
@ -699,13 +832,124 @@ namespace OperatorHelper
|
|||
return edgeShapes;
|
||||
}
|
||||
|
||||
void SliceHelper::Initialize(
|
||||
const IKernelInformationAdapter& kernelInformation,
|
||||
const IShapeInformationAdapter& shapeInformation,
|
||||
uint32_t opsetVersion
|
||||
)
|
||||
{
|
||||
auto& attributes = kernelInformation.GetAttributes();
|
||||
std::vector<DimensionType> inputDimensions = shapeInformation.GetInputTensorShape(0);
|
||||
|
||||
std::vector<int32_t> starts;
|
||||
std::vector<int32_t> ends;
|
||||
std::vector<int32_t> axes;
|
||||
std::vector<int32_t> steps;
|
||||
|
||||
if (opsetVersion >= 10)
|
||||
{
|
||||
// Get starts, ends, optional axes, and optional steps from constant tensor inputs.
|
||||
ReadCpuLocalTensorIntoInt32(kernelInformation.GetConstantInputTensor(1), /*out*/ starts);
|
||||
ReadCpuLocalTensorIntoInt32(kernelInformation.GetConstantInputTensor(2), /*out*/ ends);
|
||||
if (kernelInformation.IsInputValid(3))
|
||||
{
|
||||
ReadCpuLocalTensorIntoInt32(kernelInformation.GetConstantInputTensor(3), /*out*/ axes);
|
||||
}
|
||||
if (kernelInformation.IsInputValid(4))
|
||||
{
|
||||
ReadCpuLocalTensorIntoInt32(kernelInformation.GetConstantInputTensor(4), /*out*/ steps);
|
||||
}
|
||||
}
|
||||
else if (opsetVersion >= 7)
|
||||
{
|
||||
// Read starts, ends, and axes from attributes.
|
||||
starts = attributes.GetOptionalAttributeVectorInt32(AttrName::Starts);
|
||||
ends = attributes.GetOptionalAttributeVectorInt32(AttrName::Ends);
|
||||
axes = attributes.GetOptionalAttributeVectorInt32(AttrName::Axes);
|
||||
}
|
||||
|
||||
const uint32_t inputDimensionCount = gsl::narrow_cast<int32_t>(inputDimensions.size());
|
||||
HandleNegativeAxes(/*inout*/ axes, inputDimensionCount);
|
||||
|
||||
ML_CHECK_VALID_ARGUMENT(starts.size() == ends.size(), "'starts' must equal 'ends' in size.");
|
||||
ML_CHECK_VALID_ARGUMENT(steps.empty() || steps.size() == axes.size(), "'steps' must equal 'axes' in size, or 'steps' must be empty.");
|
||||
ML_CHECK_VALID_ARGUMENT(axes.empty() || starts.size() == axes.size(), "'axes' must equal 'starts' in size, or 'axes' must be empty.");
|
||||
|
||||
m_outputDimensions.assign(inputDimensions.begin(), inputDimensions.end());
|
||||
m_offsets.resize(m_outputDimensions.size());
|
||||
m_sizes.resize(m_outputDimensions.size());
|
||||
m_strides.resize(m_outputDimensions.size(), 1); // Default initialize to all steps to 1's.
|
||||
|
||||
// Set initial defaults lest 'starts' and 'ends' arrays are shorter than the dimension count.
|
||||
std::copy(inputDimensions.begin(), inputDimensions.begin() + m_outputDimensions.size(), m_sizes.begin());
|
||||
|
||||
// Clamp selected dimensions to given 'starts' and 'ends'.
|
||||
for (int i = 0, ci = gsl::narrow_cast<int>(starts.size()); i < ci; ++i)
|
||||
{
|
||||
int dimIndex = axes.empty() ? i : axes[i];
|
||||
int stride = steps.empty() ? 1 : steps[i];
|
||||
ML_CHECK_VALID_ARGUMENT(static_cast<size_t>(dimIndex) < static_cast<size_t>(inputDimensions.size()), "'axes' must be valid with within actual input dimensions.");
|
||||
ML_CHECK_VALID_ARGUMENT(stride != 0, "'steps' must not be 0.");
|
||||
|
||||
// Positive values are offsets from 0.
|
||||
// Negative values are offsets from back of the dimension's size.
|
||||
// INT_MIN is a special value in ONNX which means to treat it as the smallest
|
||||
// possible value, rather than the usual reversed from-the-back semantics.
|
||||
int dim = gsl::narrow_cast<int>(inputDimensions[dimIndex]);
|
||||
int start = (starts[i] < 0 && starts[i] > INT_MIN) ? (starts[i] + dim) : starts[i];
|
||||
int end = (ends[i] < 0 && starts[i] > INT_MIN) ? (ends[i] + dim) : ends[i];
|
||||
|
||||
// For negative strides, the ONNX start and end values are off-by-one.
|
||||
// So fix them such that the start value remains the minimum extent
|
||||
// of the slice window, and end remains the maximum exclusive extent.
|
||||
if (stride < 0)
|
||||
{
|
||||
std::swap(start, end);
|
||||
start += (start < INT_MAX) ? 1 : 0; // Avoid overflow wrap.
|
||||
end += (end < INT_MAX) ? 1 : 0;
|
||||
}
|
||||
|
||||
// Clamp the dimensions to the slice extents.
|
||||
// Clamp negative numbers to 0, per case test_slice_start_out_of_bounds.
|
||||
start = std::max(start, 0);
|
||||
end = std::min(end, dim);
|
||||
int size = std::max(end - start, 0);
|
||||
|
||||
// Set the input window offsets/sizes, and compute output size based on input
|
||||
// window size (rounding up).
|
||||
// e.g. a window size 13 and step 3 yields 5 output elements.
|
||||
int absoluteStride = abs(stride);
|
||||
m_outputDimensions[dimIndex] = (size / absoluteStride) + (size % absoluteStride != 0);
|
||||
m_offsets[dimIndex] = start;
|
||||
m_strides[dimIndex] = stride;
|
||||
m_sizes[dimIndex] = gsl::narrow_cast<uint32_t>(size);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<EdgeShapes> SliceHelper::GetOutputShapes(const MLShapeInferenceContext& shapeInfo) const
|
||||
{
|
||||
return { m_outputDimensions };
|
||||
}
|
||||
|
||||
void PaddingHelper::Initialize(const MLOperatorAttributes& operatorAttributes, gsl::span<int32_t> padding, uint32_t opsetVersion)
|
||||
void PaddingHelper::Initialize(
|
||||
const IKernelInformationAdapter& kernelInformation,
|
||||
const IShapeInformationAdapter& shapeInformation,
|
||||
uint32_t opsetVersion
|
||||
)
|
||||
{
|
||||
auto& attributes = kernelInformation.GetAttributes();
|
||||
|
||||
std::vector<int32_t> padding;
|
||||
if (opsetVersion >= 11)
|
||||
{
|
||||
MLOperatorTensor padsTensor = kernelInformation.GetConstantInputTensor(1);
|
||||
ReadCpuLocalTensorIntoInt32(padsTensor, /*out*/ padding);
|
||||
}
|
||||
else
|
||||
{
|
||||
padding = attributes.GetOptionalAttributeVectorInt32(AttrName::Pads);
|
||||
}
|
||||
|
||||
ML_CHECK_VALID_ARGUMENT(padding.size() % 2 == 0, "Padding must be even count, including begin/end pairs.");
|
||||
|
||||
uint32_t dimCount = gsl::narrow_cast<uint32_t>(padding.size() / 2);
|
||||
|
|
@ -746,10 +990,13 @@ namespace OperatorHelper
|
|||
}
|
||||
|
||||
void GatherHelper::Initialize(
|
||||
const MLOperatorAttributes& operatorAttributes,
|
||||
gsl::span<const DimensionType> inputDimensions
|
||||
const IKernelInformationAdapter& kernelInformation,
|
||||
const IShapeInformationAdapter& shapeInformation
|
||||
)
|
||||
{
|
||||
auto& operatorAttributes = kernelInformation.GetAttributes();
|
||||
std::vector<DimensionType> inputDimensions = shapeInformation.GetInputTensorShape(0);
|
||||
|
||||
int32_t signedOnnxAxis = operatorAttributes.GetOptionalAttribute<int>(AttrName::Axis, 0);
|
||||
uint32_t inputRank = gsl::narrow_cast<int>(inputDimensions.size());
|
||||
m_axis = HandleNegativeAxis(signedOnnxAxis, inputRank);
|
||||
|
|
@ -865,6 +1112,39 @@ namespace OperatorHelper
|
|||
return { EdgeShapes(std::move(outputDimensions)) };
|
||||
}
|
||||
|
||||
void ReduceHelperBase::Initialize(
|
||||
IKernelInformationAdapter const& kernelInformation,
|
||||
IShapeInformationAdapter const& shapeInformation,
|
||||
bool usingMultipleAxes
|
||||
)
|
||||
{
|
||||
auto& attributes = kernelInformation.GetAttributes();
|
||||
m_keepDims = attributes.GetOptionalAttribute<int32_t>(AttrName::KeepDims, 1);
|
||||
m_selectLastIndex = attributes.GetOptionalAttribute<int32_t>(AttrName::SelectLastIndex, 0);
|
||||
m_noopWithEmptyAxes = attributes.GetOptionalAttribute<int32_t>(AttrName::NoopWithEmptyAxes, 0);
|
||||
|
||||
if (usingMultipleAxes) // Read full axis list. e.g. ReduceSum.
|
||||
{
|
||||
if (kernelInformation.IsInputValid(1)) // Axes are from a dynamic input parameter.
|
||||
{
|
||||
ReadCpuLocalTensorIntoInt32(kernelInformation.GetConstantInputTensor(1), /*out*/ m_axes);
|
||||
}
|
||||
else // Axes were a constant attribute parameter.
|
||||
{
|
||||
m_axes = attributes.GetOptionalAttributeVectorInt32(AttrName::Axes);
|
||||
}
|
||||
}
|
||||
else // Only read a single axis. e.g. ArgMin/ArgMax.
|
||||
{
|
||||
int axis = attributes.GetOptionalAttribute<int32_t>(AttrName::Axis, 0);
|
||||
m_axes.push_back(axis);
|
||||
}
|
||||
|
||||
std::vector<uint32_t> inputShape = shapeInformation.GetInputTensorShape(0);
|
||||
HandleNegativeAxes(/*inout*/ m_axes, gsl::narrow_cast<uint32_t>(inputShape.size()));
|
||||
HandleEmptyAxes(/*inout*/ m_axes, inputShape, bool(m_noopWithEmptyAxes));
|
||||
}
|
||||
|
||||
std::vector<EdgeShapes> ReduceHelperBase::GetOutputShapes(const MLShapeInferenceContext& shapeInfo) const
|
||||
{
|
||||
// Example:
|
||||
|
|
@ -909,13 +1189,18 @@ namespace OperatorHelper
|
|||
}
|
||||
}
|
||||
|
||||
void ReduceHelperBase::AdjustAxesAndOutputShape(const std::vector<uint32_t>& inputShape)
|
||||
void ReduceHelperBase::HandleEmptyAxes(
|
||||
/*inout*/std::vector<int32_t>& axes,
|
||||
gsl::span<const uint32_t> inputShape,
|
||||
bool treatEmptyAsNop
|
||||
)
|
||||
{
|
||||
// If axes is not specified, reduce over all the dimensions
|
||||
if (m_axes.empty())
|
||||
// If axes is not specified, reduce over all the dimensions.
|
||||
// If empty axes should be treated as a nop, then just leave them as-is.
|
||||
if (axes.empty() && !treatEmptyAsNop)
|
||||
{
|
||||
m_axes.resize(inputShape.size());
|
||||
std::iota(m_axes.begin(), m_axes.end(), 0);
|
||||
axes.resize(inputShape.size());
|
||||
std::iota(axes.begin(), axes.end(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1236,7 +1521,32 @@ namespace OperatorHelper
|
|||
|
||||
return {std::move(outputDims)};
|
||||
}
|
||||
|
||||
|
||||
void TopKHelper::Initialize(
|
||||
const IKernelInformationAdapter& kernelInformation,
|
||||
const IShapeInformationAdapter& shapeInformation,
|
||||
uint32_t opsetVersion
|
||||
)
|
||||
{
|
||||
auto& attributes = kernelInformation.GetAttributes();
|
||||
int32_t k;
|
||||
if (opsetVersion >= 10)
|
||||
{
|
||||
MLOperatorTensor kTensor = kernelInformation.GetConstantInputTensor(1);
|
||||
k = gsl::narrow_cast<int32_t>(ReadScalarTensorCastToInt64(kTensor));
|
||||
}
|
||||
else
|
||||
{
|
||||
k = attributes.template GetOptionalAttribute<int32_t>(AttrName::K, -1);
|
||||
}
|
||||
ML_CHECK_VALID_ARGUMENT(k >= 0, "Attribute k is missing or negative.");
|
||||
m_k = k;
|
||||
|
||||
auto inputShape = shapeInformation.GetInputTensorShape(0);
|
||||
int32_t axis = attributes.template GetOptionalAttribute<int32_t>(AttrName::Axis, -1);
|
||||
m_axis = HandleNegativeAxis(axis, gsl::narrow_cast<uint32_t>(inputShape.size()));
|
||||
}
|
||||
|
||||
std::vector<EdgeShapes> TopKHelper::GetOutputShapes(const MLShapeInferenceContext& shapeInfo) const
|
||||
{
|
||||
assert(m_axis >= 0);
|
||||
|
|
@ -1528,11 +1838,20 @@ namespace OperatorHelper
|
|||
}
|
||||
|
||||
void SqueezeHelper::Initialize(
|
||||
gsl::span<const int32_t> axes,
|
||||
gsl::span<const DimensionType> inputDimensions
|
||||
IKernelInformationAdapter const& kernelInformation,
|
||||
IShapeInformationAdapter const& shapeInformation,
|
||||
uint32_t opsetVersion
|
||||
)
|
||||
{
|
||||
m_axes.assign(axes.begin(), axes.end());
|
||||
if (opsetVersion >= 13) // Axes are a dynamic input parameter.
|
||||
{
|
||||
ReadCpuLocalTensorIntoInt32(kernelInformation.GetConstantInputTensor(1), /*out*/ m_axes);
|
||||
}
|
||||
else // Axes were a constant attribute parameter.
|
||||
{
|
||||
m_axes = kernelInformation.GetAttributes().GetOptionalAttributeVectorInt32(AttrName::Axes);
|
||||
}
|
||||
std::vector<DimensionType> inputDimensions = shapeInformation.GetInputTensorShape(0);
|
||||
HandleNegativeAxes(/*inout*/ m_axes, gsl::narrow_cast<uint32_t>(inputDimensions.size()));
|
||||
std::sort(m_axes.begin(), m_axes.end());
|
||||
}
|
||||
|
|
@ -1571,12 +1890,22 @@ namespace OperatorHelper
|
|||
}
|
||||
|
||||
void UnsqueezeHelper::Initialize(
|
||||
gsl::span<const int32_t> axes,
|
||||
gsl::span<const DimensionType> inputDimensions
|
||||
IKernelInformationAdapter const& kernelInformation,
|
||||
IShapeInformationAdapter const& shapeInformation,
|
||||
uint32_t opsetVersion
|
||||
)
|
||||
{
|
||||
m_axes.assign(axes.begin(), axes.end());
|
||||
const uint32_t outputDimensionCount = gsl::narrow_cast<uint32_t>(inputDimensions.size() + axes.size());
|
||||
if (opsetVersion >= 13) // Axes are a dynamic input parameter.
|
||||
{
|
||||
ReadCpuLocalTensorIntoInt32(kernelInformation.GetConstantInputTensor(1), /*out*/ m_axes);
|
||||
}
|
||||
else // Axes were a constant attribute parameter.
|
||||
{
|
||||
m_axes = kernelInformation.GetAttributes().GetOptionalAttributeVectorInt32(AttrName::Axes);
|
||||
}
|
||||
std::vector<DimensionType> inputDimensions = shapeInformation.GetInputTensorShape(0);
|
||||
|
||||
const uint32_t outputDimensionCount = gsl::narrow_cast<uint32_t>(inputDimensions.size() + m_axes.size());
|
||||
HandleNegativeAxes(/*inout*/ m_axes, outputDimensionCount);
|
||||
std::sort(m_axes.begin(), m_axes.end());
|
||||
}
|
||||
|
|
@ -1615,7 +1944,19 @@ namespace OperatorHelper
|
|||
|
||||
return { EdgeShapes(outputDimensions) };
|
||||
}
|
||||
|
||||
|
||||
void ReshapeHelper::Initialize(IKernelInformationAdapter const& kernelInformation)
|
||||
{
|
||||
ML_CHECK_VALID_ARGUMENT(kernelInformation.GetInputCount() >= 2);
|
||||
ML_CHECK_VALID_ARGUMENT(kernelInformation.GetOutputCount() >= 1);
|
||||
|
||||
// The 'shape' tensor is a 1D tensor holding the new shape to reshape to,
|
||||
// and the first element of its own shape holds how many dimensions there
|
||||
// will be for the output.
|
||||
MLOperatorTensor shapeTensor = kernelInformation.GetConstantInputTensor(1);
|
||||
ReadCpuLocalTensorIntoInt32(shapeTensor, /*out*/ m_shapeDims);
|
||||
}
|
||||
|
||||
std::vector<EdgeShapes> ReshapeHelper::GetOutputShapes(const MLShapeInferenceContext& shapeInfo) const
|
||||
{
|
||||
// Fill in the output dimensions. The shape may have -1 in a single dimension,
|
||||
|
|
@ -1709,15 +2050,84 @@ namespace OperatorHelper
|
|||
return { EdgeShapes(desiredTensorShape) };
|
||||
}
|
||||
|
||||
void TileHelper::Initialize(
|
||||
const IKernelInformationAdapter& kernelInformation,
|
||||
const IShapeInformationAdapter& shapeInformation
|
||||
)
|
||||
{
|
||||
m_inputDimensions = shapeInformation.GetInputTensorShape(0);
|
||||
|
||||
// Read the repeats tensor.
|
||||
const std::vector<uint32_t> repeatsTensorDimensions = shapeInformation.GetInputTensorShape(1);
|
||||
ML_CHECK_VALID_ARGUMENT(repeatsTensorDimensions.size() == 1, "Tile's repeats tensor must be 1D.");
|
||||
const size_t dimCount = repeatsTensorDimensions[0];
|
||||
|
||||
MLOperatorTensor repeatsTensor = kernelInformation.GetConstantInputTensor(1);
|
||||
const int64_t* repeatsData = repeatsTensor.GetData<int64_t>();
|
||||
ML_CHECK_VALID_ARGUMENT(m_inputDimensions.size() == dimCount, "Tile's repeats tensor must be the same dimension count as the input tensor.");
|
||||
ML_CHECK_VALID_ARGUMENT(repeatsTensor.IsCpuData(), "Tile's repeats tensor must be CPU Tensor.");
|
||||
|
||||
for (size_t i = 0; i < dimCount; ++i)
|
||||
{
|
||||
ML_CHECK_VALID_ARGUMENT(repeatsData[i] >= 0, "Repeat values should be >= 0.");
|
||||
m_repeatsData.push_back(gsl::narrow_cast<uint32_t>(repeatsData[i]));
|
||||
}
|
||||
|
||||
// Update the computed output shape accordingly, repeat every axis's length by the repeat count.
|
||||
m_outputDimensions.assign(m_inputDimensions.begin(), m_inputDimensions.end());
|
||||
|
||||
for (size_t dimIndex = 0; dimIndex < dimCount; ++dimIndex)
|
||||
{
|
||||
m_outputDimensions[dimIndex] *= m_repeatsData[dimIndex];
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<EdgeShapes> TileHelper::GetOutputShapes(const MLShapeInferenceContext& shapeInfo) const
|
||||
{
|
||||
return { EdgeShapes(m_outputDimensions) };
|
||||
}
|
||||
|
||||
void ResizeHelper::Initialize(
|
||||
gsl::span<const int32_t> outputSizes
|
||||
IKernelInformationAdapter const& kernelInformation,
|
||||
IShapeInformationAdapter const& shapeInformation,
|
||||
uint32_t opsetVersion
|
||||
)
|
||||
{
|
||||
auto& attributes = kernelInformation.GetAttributes();
|
||||
m_inputDimensions = shapeInformation.GetInputTensorShape(0);
|
||||
std::vector<int32_t> outputSizes;
|
||||
|
||||
if (opsetVersion >= 11)
|
||||
{
|
||||
if (kernelInformation.IsInputValid(1))
|
||||
{
|
||||
MLOperatorTensor regionOfInterestTensor = kernelInformation.GetConstantInputTensor(1);
|
||||
ReadCpuLocalTensorIntoFloat32(regionOfInterestTensor, /*out*/ m_regionOfInterest);
|
||||
}
|
||||
if (kernelInformation.IsInputValid(2))
|
||||
{
|
||||
MLOperatorTensor scalesTensor = kernelInformation.GetConstantInputTensor(2);
|
||||
ReadCpuLocalTensorIntoFloat32(scalesTensor, /*out*/ m_scales);
|
||||
}
|
||||
if (kernelInformation.IsInputValid(3))
|
||||
{
|
||||
MLOperatorTensor outputSizesTensor = kernelInformation.GetConstantInputTensor(3);
|
||||
ReadCpuLocalTensorIntoInt32(outputSizesTensor, /*out*/ outputSizes);
|
||||
}
|
||||
}
|
||||
else if (opsetVersion >= 9)
|
||||
{
|
||||
// Read the scales from the 2nd tensor.
|
||||
// Compatible with Upsample-9/Upsample-10 and Resize-10.
|
||||
MLOperatorTensor scalesTensor = kernelInformation.GetConstantInputTensor(1);
|
||||
ReadCpuLocalTensorIntoFloat32(scalesTensor, /*out*/ m_scales);
|
||||
}
|
||||
else
|
||||
{
|
||||
// From attribute, compatible with Upsample-7.
|
||||
m_scales = attributes.template GetOptionalAttribute<std::vector<float>>(AttrName::Scales, std::vector<float>());
|
||||
}
|
||||
|
||||
assert(m_outputDimensions.empty());
|
||||
ML_CHECK_VALID_ARGUMENT(m_scales.empty() || outputSizes.empty(), "scales and roi cannot both be present.");
|
||||
|
||||
|
|
@ -1797,6 +2207,35 @@ namespace OperatorHelper
|
|||
return { m_outputDimensions };
|
||||
}
|
||||
|
||||
void OneHotHelper::Initialize(
|
||||
const IKernelInformationAdapter& kernelInformation,
|
||||
const IShapeInformationAdapter& shapeInformation
|
||||
)
|
||||
{
|
||||
ML_CHECK_VALID_ARGUMENT(kernelInformation.GetInputCount() == 3);
|
||||
ML_CHECK_VALID_ARGUMENT(kernelInformation.GetOutputCount() == 1);
|
||||
|
||||
auto& attributes = kernelInformation.GetAttributes();
|
||||
const std::vector<DimensionType> inputDimensions = shapeInformation.GetInputTensorShape(0);
|
||||
std::vector<uint32_t> outputDimensions;
|
||||
|
||||
m_onnxAxis = attributes.template GetOptionalAttribute<int32_t>(AttrName::Axis, -1);
|
||||
|
||||
// Get 'depth' tensor, which is really a scalar for the output size along the given axis.
|
||||
MLOperatorTensor shapeTensor = kernelInformation.GetConstantInputTensor(1);
|
||||
|
||||
auto indicesShape = shapeInformation.GetInputTensorShape(0);
|
||||
m_absoluteAxis = HandleNegativeAxis(m_onnxAxis, gsl::narrow_cast<uint32_t>(indicesShape.size() + 1));
|
||||
|
||||
// The shape tensor ('depth') is a 0D tensor holding the size for the output tensor along the specified axis.
|
||||
// It must be registered as OrtMemType::OrtMemTypeCPUInput for CPU read access.
|
||||
const int64_t depth64 = ReadScalarTensorCastToInt64(shapeTensor);
|
||||
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());
|
||||
m_outputDimensions.insert(m_outputDimensions.begin() + m_absoluteAxis, depth);
|
||||
}
|
||||
|
||||
std::vector<EdgeShapes> OneHotHelper::GetOutputShapes(const MLShapeInferenceContext& shapeInfo) const
|
||||
{
|
||||
return { EdgeShapes(m_outputDimensions) };
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -276,6 +276,7 @@ namespace OperatorHelper
|
|||
static const int sc_sinceVer_Concat = 13;
|
||||
static const int sc_sinceVer_Constant = 13;
|
||||
static const int sc_sinceVer_DepthToSpace = 13;
|
||||
static const int sc_sinceVer_DequantizeLinear = 13;
|
||||
static const int sc_sinceVer_Div = 13;
|
||||
static const int sc_sinceVer_Equal = 13;
|
||||
static const int sc_sinceVer_Erf = 13;
|
||||
|
|
@ -303,6 +304,7 @@ namespace OperatorHelper
|
|||
static const int sc_sinceVer_Neg = 13;
|
||||
static const int sc_sinceVer_Pad = 13;
|
||||
static const int sc_sinceVer_Pow = 13;
|
||||
static const int sc_sinceVer_QuantizeLinear = 13;
|
||||
static const int sc_sinceVer_Reciprocal = 13;
|
||||
static const int sc_sinceVer_ReduceL1 = 13;
|
||||
static const int sc_sinceVer_ReduceL2 = 13;
|
||||
|
|
@ -312,23 +314,28 @@ namespace OperatorHelper
|
|||
static const int sc_sinceVer_ReduceMean = 13;
|
||||
static const int sc_sinceVer_ReduceMin = 13;
|
||||
static const int sc_sinceVer_ReduceProd = 13;
|
||||
static const int sc_sinceVer_ReduceSum = 13;
|
||||
static const int sc_sinceVer_ReduceSumSquare = 13;
|
||||
static const int sc_sinceVer_Relu = 13;
|
||||
static const int sc_sinceVer_Reshape = 13;
|
||||
static const int sc_sinceVer_Resize = 13;
|
||||
static const int sc_sinceVer_Scatter = 13;
|
||||
static const int sc_sinceVer_ScatterElements = 13;
|
||||
static const int sc_sinceVer_ScatterND = 13;
|
||||
static const int sc_sinceVer_Sigmoid = 13;
|
||||
static const int sc_sinceVer_Sign = 13;
|
||||
static const int sc_sinceVer_Slice = 13;
|
||||
static const int sc_sinceVer_Split = 13;
|
||||
static const int sc_sinceVer_SpaceToDepth = 13;
|
||||
static const int sc_sinceVer_Sqrt = 13;
|
||||
static const int sc_sinceVer_Squeeze = 13;
|
||||
static const int sc_sinceVer_Sub = 13;
|
||||
static const int sc_sinceVer_Sum = 13;
|
||||
static const int sc_sinceVer_Tanh = 13;
|
||||
static const int sc_sinceVer_Tile = 13;
|
||||
static const int sc_sinceVer_Transpose = 13;
|
||||
static const int sc_sinceVer_Upsample = 13;
|
||||
static const int sc_sinceVer_Unsqueeze = 13;
|
||||
static const int sc_sinceVer_ReduseSum = 13;
|
||||
} // namespace OnnxOperatorSet13
|
||||
|
||||
namespace MsftOperatorSet1
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "OperatorHelper.h"
|
||||
#include "OperatorRegistration.h"
|
||||
#include "OperatorVersions.h"
|
||||
|
||||
namespace SchemaInferenceOverrider
|
||||
{
|
||||
|
|
@ -61,7 +61,7 @@ namespace SchemaInferenceOverrider
|
|||
}
|
||||
}
|
||||
|
||||
#pragma push_macro("REGISTER_FUSED_OP_SCHEMA")
|
||||
#pragma push_macro("OVERRIDE_SCHEMA")
|
||||
#define OVERRIDE_SCHEMA(version, isLatest, opName) \
|
||||
OverrideSchemaInferenceFunction<OperatorHelper::ShapeInferenceHelper_##opName>( \
|
||||
#opName, OperatorHelper::OnnxOperatorSet##version##::sc_sinceVer_##opName, isLatest, gsl::span<uint32_t>());
|
||||
|
|
@ -82,7 +82,7 @@ OverrideSchemaInferenceFunction<OperatorHelper::ShapeInferenceHelper_##shapeInfe
|
|||
OVERRIDE_SCHEMA_EX( 7, false, Upsample, Upsample7);
|
||||
OVERRIDE_SCHEMA_EX( 9, true, Upsample, Upsample9, 1);
|
||||
OVERRIDE_SCHEMA_EX( 7, true, Slice, Slice7);
|
||||
OVERRIDE_SCHEMA( 7, true, Split);
|
||||
OVERRIDE_SCHEMA_EX( 7, true, Split, Split7);
|
||||
OVERRIDE_SCHEMA_EX( 7, true, Tile, Tile, 1);
|
||||
OVERRIDE_SCHEMA_EX( 8, true, Expand, Expand, 1);
|
||||
OVERRIDE_SCHEMA( 8, true, MaxPool);
|
||||
|
|
@ -91,6 +91,6 @@ OverrideSchemaInferenceFunction<OperatorHelper::ShapeInferenceHelper_##shapeInfe
|
|||
|
||||
}
|
||||
#pragma pop_macro("OVERRIDE_SCHEMA_EX")
|
||||
#pragma pop_macro("REGISTER_FUSED_OP_SCHEMA")
|
||||
#pragma pop_macro("OVERRIDE_SCHEMA")
|
||||
|
||||
}
|
||||
|
|
@ -17,7 +17,7 @@
|
|||
#include "core/providers/dml/DmlExecutionProvider/src/ErrorHandling.h"
|
||||
#include "core/providers/dml/OperatorAuthorHelper/MLOperatorAuthorHelper.h"
|
||||
#include "core/providers/dml/OperatorAuthorHelper/OperatorHelper.h"
|
||||
#include "core/providers/dml/OperatorAuthorHelper/OperatorRegistration.h"
|
||||
#include "core/providers/dml/OperatorAuthorHelper/OperatorVersions.h"
|
||||
#include "core/graph/constants.h"
|
||||
#include "CustomNullOp.h"
|
||||
#include <wil/wrl.h>
|
||||
|
|
|
|||
Loading…
Reference in a new issue