mirror of
https://github.com/saymrwulf/onnxruntime.git
synced 2026-07-29 20:14:01 +00:00
Fix Range.
This commit is contained in:
parent
f6211217d8
commit
1df264f4b3
7 changed files with 355 additions and 133 deletions
|
|
@ -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,
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,13 +29,10 @@ public:
|
|||
int32_t onnxAxis = 0;
|
||||
if (kernelCreationContext.IsInputValid(1))
|
||||
{
|
||||
uint64_t rawAxisBytes;
|
||||
MLOperatorTensor axisTensor = kernelCreationContext.GetConstantInputTensor(1);
|
||||
const uint32_t axisElementCount = ComputeElementCountFromDimensions(axisTensor.GetShape());
|
||||
ML_CHECK_VALID_ARGUMENT(axisTensor.IsCpuData(), "CumSum's 'axis' tensor must be a CPU Tensor.");
|
||||
ML_CHECK_VALID_ARGUMENT(axisElementCount == 1, "CumSum's 'axis' tensor must have one element.");
|
||||
|
||||
const void* tensorData = axisTensor.GetByteData();
|
||||
onnxAxis = static_cast<int32_t>(ReadAsInt64(axisTensor.GetTensorDataType(), tensorData));
|
||||
ReadScalarTensorData(axisTensor, /*out*/ &rawAxisBytes, sizeof(rawAxisBytes));
|
||||
onnxAxis = gsl::narrow_cast<int32_t>(ReadAsInt64(axisTensor.GetTensorDataType(), /*out*/ &rawAxisBytes));
|
||||
}
|
||||
uint32_t dmlAxis = GetDmlAdjustedAxis(onnxAxis, kernelCreationContext, m_inputTensorDescs.front().GetDimensionCount());
|
||||
|
||||
|
|
|
|||
|
|
@ -23,53 +23,16 @@ public:
|
|||
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);
|
||||
|
||||
//-- // Unsqueeze the indices tensor by inserting a flat dimension of size 1,
|
||||
//-- // and compute the output tensor by expanding along the active axis.
|
||||
//-- // This way they are both size-compatible and directly consumable by DirectML.
|
||||
//-- std::vector<uint32_t> indicesDimensions;
|
||||
//-- indicesDimensions = kernelCreationContext.GetTensorShapeDescription().GetInputTensorShape(0);
|
||||
//-- indicesDimensions.insert(indicesDimensions.begin() + m_absoluteAxis, 1u);
|
||||
//--
|
||||
//-- // Update the tensor descriptions with new sizes.
|
||||
//-- m_inputTensorDescs[0] =
|
||||
//-- TensorDesc(
|
||||
//-- m_inputTensorDescs[0].GetMlOperatorDataType(),
|
||||
//-- gsl::make_span(indicesDimensions),
|
||||
//-- gsl::make_span(indicesDimensions),
|
||||
//-- TensorAxis::DoNotCoerce,
|
||||
//-- TensorAxis::W,
|
||||
//-- TensorAxis::RightAligned,
|
||||
//-- NchwDimensionCount, // minDimensionCount
|
||||
//-- 0
|
||||
//-- );
|
||||
//--
|
||||
//-- m_outputTensorDescs[0] =
|
||||
//-- TensorDesc(
|
||||
//-- m_outputTensorDescs[0].GetMlOperatorDataType(),
|
||||
//-- gsl::make_span(m_outputDimensions),
|
||||
//-- gsl::make_span(m_outputDimensions),
|
||||
//-- TensorAxis::DoNotCoerce,
|
||||
//-- TensorAxis::W,
|
||||
//-- TensorAxis::RightAligned,
|
||||
//-- NchwDimensionCount, // minDimensionCount
|
||||
//-- 0
|
||||
//-- );
|
||||
//--
|
||||
//-- // Adjust the axis so it's in DML's terms rather than the original ONNX indexing.
|
||||
//-- uint32_t dmlAxis = GetDmlAdjustedAxis(
|
||||
//-- m_absoluteAxis,
|
||||
//-- gsl::narrow_cast<uint32_t>(indicesDimensions.size()),
|
||||
//-- m_inputTensorDescs.front().GetDimensionCount()
|
||||
//-- );
|
||||
|
||||
|
||||
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();;
|
||||
operatorDesc.ValueStart.Float32 = 1; // todo:::
|
||||
operatorDesc.ValueDelta.Float32 = 1;
|
||||
static_assert(sizeof(operatorDesc.ValueStart) == sizeof(m_valueStart));
|
||||
static_assert(sizeof(operatorDesc.ValueDelta) == sizeof(m_valueDelta));
|
||||
memcpy(&operatorDesc.ValueStart, &m_valueStart, sizeof(m_valueStart));
|
||||
memcpy(&operatorDesc.ValueDelta, &m_valueDelta, sizeof(m_valueDelta));
|
||||
operatorDesc.OutputTensor = outputDescs.data();
|
||||
|
||||
DML_OPERATOR_DESC opDesc = { DML_OPERATOR_FILL_VALUE_SEQUENCE, &operatorDesc };
|
||||
|
|
|
|||
|
|
@ -230,7 +230,7 @@ const static char* const typeNameListLogicalComparison[2] = { "T", "T1" };
|
|||
const static char* const typeNameListT1T2[2] = { "T1", "T2" };
|
||||
const static char* const typeNameListConstantOfShape[2] = { "T1", "T2" };
|
||||
const static char* const typeNameListScatterGather[2] = { "T", "Tind" };
|
||||
const static char* const typeNameListScatterGatherND[2] = { "T" }; // Tind is curiously missing, only allowing 64-bit.
|
||||
const static char* const typeNameListScatterGatherND[1] = { "T" }; // Tind is curiously missing, only allowing 64-bit.
|
||||
const static char* const typeNameListQuantize[2] = { "T1", "T2" };
|
||||
const static char* const typeNameListWhere[2] = { "B", "T" };
|
||||
const static char* const typeNameListOneHot[3] = { "T1", "T2", "T3" };
|
||||
|
|
@ -246,7 +246,7 @@ const static SupportedTensorDataTypes supportedTypeListTopK[2] = {SupportedTenso
|
|||
const static SupportedTensorDataTypes supportedTypeListIndices[1] = { SupportedTensorDataTypes::Int32|SupportedTensorDataTypes::Int64 };
|
||||
const static SupportedTensorDataTypes supportedTypeListCast[2] = { SupportedTensorDataTypes::AllScalars, SupportedTensorDataTypes::Scalars8to32 };
|
||||
const static SupportedTensorDataTypes supportedTypeListScatterGather[2] = { SupportedTensorDataTypes::NumericDefault, SupportedTensorDataTypes::Int32 | SupportedTensorDataTypes::Int64 };
|
||||
const static SupportedTensorDataTypes supportedTypeListScatterGatherND[2] = { SupportedTensorDataTypes::NumericDefault };
|
||||
const static SupportedTensorDataTypes supportedTypeListScatterGatherND[1] = { SupportedTensorDataTypes::NumericDefault };
|
||||
const static SupportedTensorDataTypes supportedTypeListQuantizeLinear[2] = { SupportedTensorDataTypes::Float32 | SupportedTensorDataTypes::Int32, SupportedTensorDataTypes::UInt8 | SupportedTensorDataTypes::Int8 };
|
||||
const static SupportedTensorDataTypes supportedTypeListDequantizeLinear[2] = { SupportedTensorDataTypes::Float32, SupportedTensorDataTypes::UInt8 | SupportedTensorDataTypes::Int8 | SupportedTensorDataTypes::Int32 };
|
||||
const static SupportedTensorDataTypes supportedTypeListQuantize[2] = { SupportedTensorDataTypes::Float32, SupportedTensorDataTypes::UInt8 };
|
||||
|
|
@ -511,15 +511,16 @@ const static OperatorRegistrationInformation operatorRegistrationInformationTabl
|
|||
{REG_INFO( 11, Round, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)},
|
||||
{REG_INFO( 10, ReverseSequence, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)}, // TODO::: data types, why not registered??
|
||||
{REG_INFO( 11, CumSum, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported, {1})},
|
||||
{REG_INFO( 11, Range, typeNameListDefault, supportedTypeListRange, DmGraphSupport::Supported), {0,1,2}},
|
||||
{REG_INFO( 11, Range, typeNameListDefault, supportedTypeListRange, DmGraphSupport::Supported, {0,1,2})},
|
||||
|
||||
{REG_INFO( 11, Gather, typeNameListScatterGather, supportedTypeListScatterGather, DmGraphSupport::Supported)},
|
||||
{REG_INFO( 11, GatherElements, typeNameListScatterGather, supportedTypeListScatterGather, DmGraphSupport::Supported)},
|
||||
{REG_INFO( 11, GatherND, typeNameListScatterGatherND, supportedTypeListScatterGatherND, DmGraphSupport::Supported)},
|
||||
{REG_INFO( 11, ScatterElements, typeNameListScatterGather, supportedTypeListScatterGather, DmGraphSupport::Supported)},
|
||||
{REG_INFO( 11, ScatterND, typeNameListScatterGatherND, supportedTypeListScatterGatherND, DmGraphSupport::Supported)},
|
||||
#if 0
|
||||
{REG_INFO( 9, MaxUnpool, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported, {2})},
|
||||
{REG_INFO( 11, Gather, typeNameListScatterGather, supportedTypeListScatterGather, DmGraphSupport::Supported)},
|
||||
-{REG_INFO( 11, GatherElements, typeNameListScatterGather, supportedTypeListScatterGather, DmGraphSupport::Supported)},
|
||||
-{REG_INFO( 11, GatherND, typeNameListScatterGatherND, supportedTypeListScatterGatherND, DmGraphSupport::Supported)},
|
||||
{REG_INFO( 9, MaxUnpool, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported, {2})},
|
||||
{REG_INFO( 11, Resize, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported, {1})},
|
||||
-{REG_INFO( 11, ScatterElements, typeNameListScatterGather, supportedTypeListScatterGather, DmGraphSupport::Supported)},
|
||||
-{REG_INFO( 11, ScatterND, typeNameListScatterGatherND, supportedTypeListScatterGatherND, DmGraphSupport::Supported)},
|
||||
|
||||
{REG_INFO( 11, QLinearConv, typeNameListDefault, supportedTypeListFloat16to32, DmGraphSupport::Supported)},
|
||||
// T1 : tensor(int8), tensor(uint8)
|
||||
|
|
|
|||
|
|
@ -6,36 +6,36 @@
|
|||
|
||||
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);
|
||||
if (signedOnnxAxis < 0)
|
||||
{
|
||||
signedOnnxAxis += dimCount;
|
||||
}
|
||||
uint32_t absoluteAxis = gsl::narrow_cast<uint32_t>(signedOnnxAxis);
|
||||
ML_CHECK_VALID_ARGUMENT(absoluteAxis < dimCount);
|
||||
return absoluteAxis;
|
||||
}
|
||||
}
|
||||
|
||||
int64_t ReadAsInt64(MLOperatorTensorDataType tensorDataType, const void* p)
|
||||
{
|
||||
switch (tensorDataType)
|
||||
void HandleNegativeAxes(gsl::span<int32_t> onnxAxes, uint32_t dimCount)
|
||||
{
|
||||
for (int32_t& axis : onnxAxes)
|
||||
{
|
||||
axis = HandleNegativeAxis(axis, dimCount);
|
||||
}
|
||||
}
|
||||
|
||||
int64_t ReadAsInt64(MLOperatorTensorDataType tensorDataType, const void* p)
|
||||
{
|
||||
switch (tensorDataType)
|
||||
{
|
||||
case MLOperatorTensorDataType::Float: return static_cast<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));
|
||||
|
|
@ -56,6 +56,57 @@ int64_t ReadAsInt64(MLOperatorTensorDataType tensorDataType, const void* p)
|
|||
};
|
||||
}
|
||||
|
||||
double ReadAsFloat64(MLOperatorTensorDataType tensorDataType, const void* p)
|
||||
{
|
||||
switch (tensorDataType)
|
||||
{
|
||||
case MLOperatorTensorDataType::Float: return static_cast<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);
|
||||
}
|
||||
|
||||
// Calculates the spatial dimensions from input dimensions and a kernel. The non-spatial (leading)
|
||||
// dimensions will be initialized to match the input dimensions. This assumes the spatial dimensions
|
||||
// are ordered such that they are at the end (e.g. NCHW or NCDHW).
|
||||
|
|
@ -526,6 +577,106 @@ int64_t ReadAsInt64(MLOperatorTensorDataType tensorDataType, const void* p)
|
|||
return { EdgeShapes(std::move(outputDimensions)) };
|
||||
}
|
||||
|
||||
// TODO:::
|
||||
|
||||
void GatherNDHelper::Initialize(
|
||||
const MLOperatorAttributes& operatorAttributes,
|
||||
gsl::span<const DimensionType> inputDimensions
|
||||
)
|
||||
{
|
||||
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> GatherNDHelper::GetOutputShapes(const MLShapeInferenceContext& shapeInfo) const
|
||||
{
|
||||
std::vector<DimensionType> inputDimensions = shapeInfo.GetInputTensorShape(0);
|
||||
std::vector<DimensionType> indicesDimensions = shapeInfo.GetInputTensorShape(1);
|
||||
|
||||
ML_CHECK_VALID_ARGUMENT(inputDimensions.size() >= 1);
|
||||
ML_CHECK_VALID_ARGUMENT(indicesDimensions.size() >= 0);
|
||||
int outDimCount = gsl::narrow_cast<int>(inputDimensions.size() + indicesDimensions.size() - 1);
|
||||
ML_CHECK_VALID_ARGUMENT(outDimCount > 0 && outDimCount <= NchwDimensionCount);
|
||||
|
||||
std::vector<DimensionType> outputDimensions(outDimCount, 1);
|
||||
|
||||
// The input dimensions following the gather axis determine the final output dimensions.
|
||||
int outputDim = outDimCount - 1;
|
||||
int inputDim = gsl::narrow_cast<int>(inputDimensions.size() - 1);
|
||||
for (; inputDim > m_axis; --outputDim, --inputDim)
|
||||
{
|
||||
outputDimensions[outputDim] = inputDimensions[inputDim];
|
||||
}
|
||||
|
||||
// The shape of the index tensor is reflected in the middle dimensions of the output tensor.
|
||||
int indexDim = gsl::narrow_cast<int>(indicesDimensions.size() - 1);
|
||||
for (; indexDim >= 0; --outputDim, --indexDim)
|
||||
{
|
||||
outputDimensions[outputDim] = indicesDimensions[indexDim];
|
||||
}
|
||||
|
||||
// The gather dimension is skipped for the purposes of sizing because the index values choose slices
|
||||
// across it. Preceding input dimensions determine the shape of the output's leading dimensions.
|
||||
inputDim = m_axis - 1;
|
||||
for (; outputDim >= 0 && inputDim >= 0; --outputDim, --inputDim)
|
||||
{
|
||||
outputDimensions[outputDim] = inputDimensions[inputDim];
|
||||
}
|
||||
|
||||
return { EdgeShapes(std::move(outputDimensions)) };
|
||||
}
|
||||
|
||||
// TODO:::
|
||||
|
||||
void ScatterNDHelper::Initialize(
|
||||
const MLOperatorAttributes& operatorAttributes,
|
||||
gsl::span<const DimensionType> inputDimensions
|
||||
)
|
||||
{
|
||||
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> ScatterNDHelper::GetOutputShapes(const MLShapeInferenceContext& shapeInfo) const
|
||||
{
|
||||
std::vector<DimensionType> inputDimensions = shapeInfo.GetInputTensorShape(0);
|
||||
std::vector<DimensionType> indicesDimensions = shapeInfo.GetInputTensorShape(1);
|
||||
|
||||
ML_CHECK_VALID_ARGUMENT(inputDimensions.size() >= 1);
|
||||
ML_CHECK_VALID_ARGUMENT(indicesDimensions.size() >= 0);
|
||||
int outDimCount = gsl::narrow_cast<int>(inputDimensions.size() + indicesDimensions.size() - 1);
|
||||
ML_CHECK_VALID_ARGUMENT(outDimCount > 0 && outDimCount <= NchwDimensionCount);
|
||||
|
||||
std::vector<DimensionType> outputDimensions(outDimCount, 1);
|
||||
|
||||
// The input dimensions following the gather axis determine the final output dimensions.
|
||||
int outputDim = outDimCount - 1;
|
||||
int inputDim = gsl::narrow_cast<int>(inputDimensions.size() - 1);
|
||||
for (; inputDim > m_axis; --outputDim, --inputDim)
|
||||
{
|
||||
outputDimensions[outputDim] = inputDimensions[inputDim];
|
||||
}
|
||||
|
||||
// The shape of the index tensor is reflected in the middle dimensions of the output tensor.
|
||||
int indexDim = gsl::narrow_cast<int>(indicesDimensions.size() - 1);
|
||||
for (; indexDim >= 0; --outputDim, --indexDim)
|
||||
{
|
||||
outputDimensions[outputDim] = indicesDimensions[indexDim];
|
||||
}
|
||||
|
||||
// The gather dimension is skipped for the purposes of sizing because the index values choose slices
|
||||
// across it. Preceding input dimensions determine the shape of the output's leading dimensions.
|
||||
inputDim = m_axis - 1;
|
||||
for (; outputDim >= 0 && inputDim >= 0; --outputDim, --inputDim)
|
||||
{
|
||||
outputDimensions[outputDim] = inputDimensions[inputDim];
|
||||
}
|
||||
|
||||
return { EdgeShapes(std::move(outputDimensions)) };
|
||||
}
|
||||
|
||||
void TransposeHelper::Initialize(
|
||||
const MLOperatorAttributes& operatorAttributes,
|
||||
gsl::span<const DimensionType> inputDimensions
|
||||
|
|
@ -1139,6 +1290,46 @@ int64_t ReadAsInt64(MLOperatorTensorDataType tensorDataType, const void* p)
|
|||
return { m_outputDimensions };
|
||||
}
|
||||
|
||||
void RangeHelper::Initialize(
|
||||
const MLOperatorTensor& startTensor,
|
||||
const MLOperatorTensor& limitTensor,
|
||||
const MLOperatorTensor& deltaTensor
|
||||
)
|
||||
{
|
||||
ReadScalarTensorData(startTensor, &m_valueStart, sizeof(m_valueStart));
|
||||
ReadScalarTensorData(limitTensor, &m_valueLimit, sizeof(m_valueLimit));
|
||||
ReadScalarTensorData(deltaTensor, &m_valueDelta, sizeof(m_valueDelta));
|
||||
m_tensorDataType = startTensor.GetTensorDataType();
|
||||
|
||||
// The output size is a 1D tensor ranging from start up to limit,
|
||||
// where:
|
||||
//
|
||||
// number_of_elements = max(ceil((limit - start) / delta), 0)
|
||||
//
|
||||
uint32_t totalElementCount = 0;
|
||||
if (IsFloatDataType(m_tensorDataType))
|
||||
{
|
||||
double start = ReadAsFloat64(m_tensorDataType, &m_valueStart);
|
||||
double limit = ReadAsFloat64(m_tensorDataType, &m_valueLimit);
|
||||
double delta = ReadAsFloat64(m_tensorDataType, &m_valueDelta);
|
||||
totalElementCount = gsl::narrow_cast<uint32_t>(ceil((limit - start) / delta));
|
||||
}
|
||||
else
|
||||
{
|
||||
int64_t start = ReadAsInt64(m_tensorDataType, &m_valueStart);
|
||||
int64_t limit = ReadAsInt64(m_tensorDataType, &m_valueLimit);
|
||||
int64_t delta = ReadAsInt64(m_tensorDataType, &m_valueDelta);
|
||||
int64_t range = limit - start;
|
||||
totalElementCount = gsl::narrow_cast<uint32_t>((range / delta) + (range % delta != 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)) };
|
||||
|
|
|
|||
|
|
@ -76,6 +76,8 @@ void RemoveValuesByIndex(gsl::span<const uint32_t> indices, bool keepOneValue, /
|
|||
}
|
||||
|
||||
int64_t ReadAsInt64(MLOperatorTensorDataType tensorDataType, const void* p);
|
||||
double ReadAsFloat64(MLOperatorTensorDataType tensorDataType, const void* p);
|
||||
void ReadScalarTensorData(const MLOperatorTensor& tensor, void* data, size_t dataByteSize);
|
||||
|
||||
class EdgeShapes {
|
||||
public:
|
||||
|
|
@ -174,13 +176,38 @@ class GetOutputShapeAsInputShapeHelper {
|
|||
public:
|
||||
// Info_t is used to obtain attributes which will be used for calculating the output shape later.
|
||||
// Shape_t is used to obtain input shape which will be used for adjusting attribute value.
|
||||
// Default to first input tensor.
|
||||
template <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 {
|
||||
|
|
@ -329,10 +356,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)
|
||||
{
|
||||
|
|
@ -367,39 +394,39 @@ public:
|
|||
assert(m_outputShapes[0].GetShape().size() > C);
|
||||
m_outputShapes[0].GetShape()[C] = filterDims[C] * m_groupCount;
|
||||
|
||||
if (!outputShape.empty()) {
|
||||
// Start padding, end padding, and output padding are all ignored if output shape is set.
|
||||
std::fill(m_kernel.outputPadding, m_kernel.outputPadding + m_kernel.spatialDimensionCount, 0);
|
||||
if (!outputShape.empty()) {
|
||||
// Start padding, end padding, and output padding are all ignored if output shape is set.
|
||||
std::fill(m_kernel.outputPadding, m_kernel.outputPadding + m_kernel.spatialDimensionCount, 0);
|
||||
|
||||
if (outputShape.size() > 2) {
|
||||
ML_CHECK_VALID_ARGUMENT(outputShape[outputShape.size() - 3] == gsl::narrow_cast<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:
|
||||
|
|
@ -898,6 +925,46 @@ class GatherHelper {
|
|||
int m_axis = 0;
|
||||
};
|
||||
|
||||
class GatherNDHelper {
|
||||
public:
|
||||
void Initialize(
|
||||
const MLOperatorAttributes& operatorAttributes,
|
||||
gsl::span<const DimensionType> dataDimensions
|
||||
);
|
||||
|
||||
// Info_t is used to obtain attributes which will be used for calculating the output shape later.
|
||||
// Shape_t is used to obtain input shape which will be used for adjusting attribute value.
|
||||
template <typename Info_t, typename Shape_t>
|
||||
GatherNDHelper(const Info_t& info, const Shape_t& shape) {
|
||||
Initialize(info, shape.GetInputTensorShape(0));
|
||||
}
|
||||
|
||||
std::vector<EdgeShapes> GetOutputShapes(const MLShapeInferenceContext& shapeInfo) const;
|
||||
|
||||
protected:
|
||||
int m_axis = 0;
|
||||
};
|
||||
|
||||
class ScatterNDHelper {
|
||||
public:
|
||||
void Initialize(
|
||||
const MLOperatorAttributes& operatorAttributes,
|
||||
gsl::span<const DimensionType> dataDimensions
|
||||
);
|
||||
|
||||
// Info_t is used to obtain attributes which will be used for calculating the output shape later.
|
||||
// Shape_t is used to obtain input shape which will be used for adjusting attribute value.
|
||||
template <typename Info_t, typename Shape_t>
|
||||
ScatterNDHelper(const Info_t& info, const Shape_t& shape) {
|
||||
Initialize(info, shape.GetInputTensorShape(0));
|
||||
}
|
||||
|
||||
std::vector<EdgeShapes> GetOutputShapes(const MLShapeInferenceContext& shapeInfo) const;
|
||||
|
||||
protected:
|
||||
int m_axis = 0;
|
||||
};
|
||||
|
||||
class PoolingHelperBase {
|
||||
public:
|
||||
// Info_t is used to obtain attributes which will be used for calculating the output shape later.
|
||||
|
|
@ -1127,38 +1194,36 @@ class ResizeHelper {
|
|||
std::vector<float> m_scales; // Cached scales to check for updates/invalidate operator.
|
||||
};
|
||||
|
||||
//TODO:::
|
||||
class RangeHelper {
|
||||
public:
|
||||
// Info_t is used to obtain attributes which will be used for calculating the output shape later.
|
||||
// Shape_t is used to obtain input shape which will be used for adjusting attribute value.
|
||||
template <typename Info_t, typename Shape_t>
|
||||
RangeHelper(const Info_t& info, const Shape_t& shape) {
|
||||
// Read the scales from the 2nd tensor.
|
||||
if (info.GetInputCount() > 1) {
|
||||
MLOperatorTensor scalesTensor = info.GetConstantInputTensor(1);
|
||||
Initialize(scalesTensor, shape.GetInputTensorShape(0));
|
||||
} else // From attribute.
|
||||
{
|
||||
Initialize(info, shape.GetInputTensorShape(0));
|
||||
}
|
||||
RangeHelper(const Info_t& info, const Shape_t& shape)
|
||||
{
|
||||
auto startTensor = info.GetConstantInputTensor(0);
|
||||
auto limitTensor = info.GetConstantInputTensor(1);
|
||||
auto deltaTensor = info.GetConstantInputTensor(2);
|
||||
Initialize(startTensor, limitTensor, deltaTensor);
|
||||
}
|
||||
|
||||
void Initialize(
|
||||
const MLOperatorAttributes& operatorAttributes,
|
||||
gsl::span<const DimensionType> inputDimensions);
|
||||
|
||||
void Initialize(
|
||||
const MLOperatorTensor& scalesTensor,
|
||||
gsl::span<const DimensionType> inputDimensions);
|
||||
|
||||
void InitializeOutputDimensions(
|
||||
gsl::span<const float> scales,
|
||||
gsl::span<const DimensionType> inputDimensions);
|
||||
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<sizeof(double), alignof(double)>::type;
|
||||
TensorScalarData m_valueStart;
|
||||
TensorScalarData m_valueLimit;
|
||||
TensorScalarData m_valueDelta;
|
||||
};
|
||||
|
||||
class OneHotHelper {
|
||||
|
|
@ -1220,7 +1285,13 @@ using ShapeInferenceHelper_LpNormalization = GetOutputShapeAsInputShapeHelper;
|
|||
using ShapeInferenceHelper_RNN = RecurrentHelper;
|
||||
using ShapeInferenceHelper_GRU = RecurrentHelper;
|
||||
using ShapeInferenceHelper_LSTM = RecurrentHelper;
|
||||
|
||||
using ShapeInferenceHelper_Gather = GatherHelper;
|
||||
using ShapeInferenceHelper_GatherElements = GetOutputShapeAsSpecificInputShapeHelper<1>;
|
||||
using ShapeInferenceHelper_ScatterElements = GetOutputShapeAsInputShapeHelper;
|
||||
using ShapeInferenceHelper_Scatter = ShapeInferenceHelper_ScatterElements;
|
||||
using ShapeInferenceHelper_GatherND = GatherNDHelper;
|
||||
using ShapeInferenceHelper_ScatterND = ScatterNDHelper;
|
||||
|
||||
using ShapeInferenceHelper_Flatten = FlattenHelper;
|
||||
using ShapeInferenceHelper_Split = SplitHelper;
|
||||
|
|
@ -1276,7 +1347,6 @@ using ShapeInferenceHelper_Atan = GetOutputShapeAsInputShapeHelper;
|
|||
using ShapeInferenceHelper_Affine = GetOutputShapeAsInputShapeHelper;
|
||||
using ShapeInferenceHelper_QuantizeLinear = GetOutputShapeAsInputShapeHelper;
|
||||
using ShapeInferenceHelper_DequantizeLinear = GetOutputShapeAsInputShapeHelper;
|
||||
using ShapeInferenceHelper_Scatter = GetOutputShapeAsInputShapeHelper;
|
||||
using ShapeInferenceHelper_Sign = GetBroadcastedOutputShapeHelper;
|
||||
using ShapeInferenceHelper_IsNan = GetBroadcastedOutputShapeHelper;
|
||||
using ShapeInferenceHelper_Erf = GetBroadcastedOutputShapeHelper;
|
||||
|
|
@ -1344,7 +1414,7 @@ using ShapeInferenceHelper_Multinomial = MultinomialHelper;
|
|||
|
||||
using ShapeInferenceHelper_ReverseSequence = GetOutputShapeAsInputShapeHelper;
|
||||
using ShapeInferenceHelper_CumSum = GetOutputShapeAsInputShapeHelper;
|
||||
using ShapeInferenceHelper_ShapeInferenceHelper_Range = RangeHelper;
|
||||
using ShapeInferenceHelper_Range = RangeHelper;
|
||||
|
||||
using ShapeInferenceHelper_FusedConv = ConvHelper;
|
||||
using ShapeInferenceHelper_FusedConvTranspose = ConvTransposeHelper;
|
||||
|
|
|
|||
Loading…
Reference in a new issue