onnxruntime/winml/test/scenario/cppwinrt/NoisyReluCpu.h
Paul McDaniel e8e285dd97
Layer dev paulm (#2506)
* commetns for dml graph transformer
fixed ort value passing using the allocatir info

* fixed and coded maps and sequences across the abi

* cleaned up w4's
cleaned up the model info ABI
delayload directml.dll from winml
2019-11-27 15:04:47 -08:00

295 lines
12 KiB
C++

#pragma once
#include "core/providers/dml/DmlExecutionProvider/inc/MLOperatorAuthor.h"
#include "core/common//common.h"
struct NoisyReluShapeInferrer : winrt::implements<NoisyReluShapeInferrer, IMLOperatorShapeInferrer>
{
STDMETHOD(InferOutputShapes)(IMLOperatorShapeInferenceContext* context) noexcept
{
try
{
uint32_t inputDimsSize;
context->GetInputTensorDimensionCount(0, &inputDimsSize);
uint32_t *inputDims = new uint32_t[inputDimsSize];
context->GetInputTensorShape(0, inputDimsSize, inputDims);
context->SetOutputTensorShape(0, inputDimsSize, inputDims);
return S_OK;
}
catch (...)
{
return winrt::to_hresult();
}
}
};
struct NoisyReluOperator: winrt::implements<NoisyReluOperator, IMLOperatorKernel>
{
float m_mean;
float m_variance;
NoisyReluOperator(float mean, float variance) :
m_mean(mean),
m_variance(variance)
{}
// Computes the outputs of the kernel. This may be called multiple times
// simultaneously within the same instance of the class. Implementations
// of this method must be thread-safe.
STDMETHOD(Compute)(IMLOperatorKernelContext* context)
{
try
{
// Get the input tensor
winrt::com_ptr<IMLOperatorTensor> inputTensor;
context->GetInputTensor(0, inputTensor.put());
// Get the output tensor
winrt::com_ptr<IMLOperatorTensor> outputTensor;
context->GetOutputTensor(0, outputTensor.put());
// Get the input and output shape sizes
uint32_t inputDimsSize = inputTensor->GetDimensionCount();
uint32_t outputDimsSize = outputTensor->GetDimensionCount();
if (inputDimsSize != outputDimsSize)
{
return E_UNEXPECTED;
}
// Get the input shape
std::vector<uint32_t> inputDims(inputDimsSize);
outputTensor->GetShape(inputDimsSize, inputDims.data());
// Get the output shape
std::vector<uint32_t> outputDims(outputDimsSize);
outputTensor->GetShape(outputDimsSize, outputDims.data());
// For the number of total elements in the input and output shapes
auto outputDataSize = std::accumulate(outputDims.begin(), outputDims.end(), 1, std::multiplies<uint32_t>());
auto inputDataSize = std::accumulate(inputDims.begin(), inputDims.end(), 1, std::multiplies<uint32_t>());
if (outputDataSize != inputDataSize)
{
return E_UNEXPECTED;
}
// If the tensor types are both float type
if (outputTensor->GetTensorDataType() == MLOperatorTensorDataType::Float &&
inputTensor->GetTensorDataType() == MLOperatorTensorDataType::Float)
{
// For cpu data
if (outputTensor->IsCpuData() && inputTensor->IsCpuData())
{
ComputeInternal<float>(inputTensor.get(), outputTensor.get(), inputDataSize);
}
}
else if (outputTensor->GetTensorDataType() == MLOperatorTensorDataType::Double &&
inputTensor->GetTensorDataType() == MLOperatorTensorDataType::Double)
{
// For cpu data
if (outputTensor->IsCpuData() && inputTensor->IsCpuData())
{
ComputeInternal<double>(inputTensor.get(), outputTensor.get(), inputDataSize);
}
}
return S_OK;
}
catch (...)
{
return winrt::to_hresult();
}
}
template <typename T, typename U = T>
void ComputeInternal(IMLOperatorTensor* pInputTensor, IMLOperatorTensor* pOutputTensor, uint32_t size)
{
// Create a normal distribution
std::normal_distribution<> dist{ m_mean, m_variance };
std::random_device rd{};
std::mt19937 gen{ rd() };
auto inputData = static_cast<T*>(pInputTensor->GetData());
auto outputData = static_cast<U*>(pOutputTensor->GetData());
for (uint32_t i = 0; i < size; i++)
{
outputData[i] = static_cast<U>(std::max<T>(0, static_cast<T>(inputData[i] + dist(gen))));
}
}
};
struct NoisyReluOperatorFactory : winrt::implements<NoisyReluOperatorFactory, IMLOperatorKernelFactory>
{
STDMETHOD(CreateKernel)(
IMLOperatorKernelCreationContext* context,
IMLOperatorKernel** kernel)
{
try
{
float mean;
context->GetAttribute("mean", MLOperatorAttributeType::Float, 1, sizeof(float), reinterpret_cast<void*>(&mean));
float variance;
context->GetAttribute("variance", MLOperatorAttributeType::Float, 1, sizeof(float), reinterpret_cast<void*>(&variance));
auto noisyReluOperator = winrt::make<NoisyReluOperator>(mean, variance);
noisyReluOperator.copy_to(kernel);
return S_OK;
}
catch (...)
{
return winrt::to_hresult();
}
}
static MLOperatorEdgeDescription CreateEdgeDescriptor(MLOperatorEdgeType type, MLOperatorTensorDataType dataType)
{
ORT_UNUSED_PARAMETER(type);
MLOperatorEdgeDescription desc;
desc.edgeType = MLOperatorEdgeType::Tensor;
desc.tensorDataType = dataType;
return desc;
}
static void RegisterNoisyReluSchema(winrt::com_ptr<IMLOperatorRegistry> registry)
{
MLOperatorSetId operatorSetId;
operatorSetId.domain = "";
operatorSetId.version = 7;
MLOperatorSchemaDescription noisyReluSchema;
noisyReluSchema.name = "NoisyRelu";
noisyReluSchema.operatorSetVersionAtLastChange = 1;
MLOperatorSchemaEdgeDescription noisyReluXInput;
noisyReluXInput.options = MLOperatorParameterOptions::Single;
noisyReluXInput.typeFormat = MLOperatorSchemaEdgeTypeFormat::Label;
noisyReluXInput.typeLabel = "T";
std::vector<MLOperatorSchemaEdgeDescription> inputs { noisyReluXInput };
noisyReluSchema.inputs = inputs.data();
noisyReluSchema.inputCount = static_cast<uint32_t>(inputs.size());
MLOperatorSchemaEdgeDescription noisyReluXOutput;
noisyReluXOutput.options = MLOperatorParameterOptions::Single;
noisyReluXOutput.typeFormat = MLOperatorSchemaEdgeTypeFormat::Label;
noisyReluXOutput.typeLabel = "T";
std::vector<MLOperatorSchemaEdgeDescription> outputs{ noisyReluXOutput };
noisyReluSchema.outputs = outputs.data();
noisyReluSchema.outputCount = static_cast<uint32_t>(outputs.size());
MLOperatorEdgeTypeConstrant typeConstraint;
typeConstraint.typeLabel = "T";
std::vector<MLOperatorEdgeDescription> allowedEdges
{
CreateEdgeDescriptor(MLOperatorEdgeType::Tensor, MLOperatorTensorDataType::Double),
CreateEdgeDescriptor(MLOperatorEdgeType::Tensor, MLOperatorTensorDataType::Float),
CreateEdgeDescriptor(MLOperatorEdgeType::Tensor, MLOperatorTensorDataType::Float16)
};
typeConstraint.allowedTypes = allowedEdges.data();
typeConstraint.allowedTypeCount = static_cast<uint32_t>(allowedEdges.size());
std::vector<MLOperatorEdgeTypeConstrant> typeConstraints { typeConstraint };
noisyReluSchema.typeConstraints = typeConstraints.data();
noisyReluSchema.typeConstraintCount = static_cast<uint32_t>(typeConstraints.size());
MLOperatorAttribute noisyReluMeanAttribute;
noisyReluMeanAttribute.name = "mean";
noisyReluMeanAttribute.required = false;
noisyReluMeanAttribute.type = MLOperatorAttributeType::Float;
MLOperatorAttribute noisyReluVarianceAttribute;
noisyReluVarianceAttribute.name = "variance";
noisyReluVarianceAttribute.required = false;
noisyReluVarianceAttribute.type = MLOperatorAttributeType::Float;
std::vector<MLOperatorAttribute> attributes { noisyReluMeanAttribute, noisyReluVarianceAttribute };
noisyReluSchema.attributes = attributes.data();
noisyReluSchema.attributeCount = static_cast<uint32_t>(attributes.size());
MLOperatorAttributeNameValue noisyReluMeanAttributeValue;
noisyReluMeanAttributeValue.name = "mean";
noisyReluMeanAttributeValue.type = MLOperatorAttributeType::Float;
noisyReluMeanAttributeValue.valueCount = 1;
static float defaultMeans[] = { 0.f };
noisyReluMeanAttributeValue.floats = defaultMeans;
MLOperatorAttributeNameValue noisyReluVarianceAttributeValue;
noisyReluVarianceAttributeValue.name = "variance";
noisyReluVarianceAttributeValue.type = MLOperatorAttributeType::Float;
noisyReluVarianceAttributeValue.valueCount = 1;
static float defaultVariance[] = { 1.f };
noisyReluVarianceAttributeValue.floats = defaultVariance;
std::vector<MLOperatorAttributeNameValue> attributeDefaultValues { noisyReluMeanAttributeValue, noisyReluVarianceAttributeValue };
noisyReluSchema.defaultAttributes = attributeDefaultValues.data();
noisyReluSchema.defaultAttributeCount = static_cast<uint32_t>(attributeDefaultValues.size());
std::vector<const MLOperatorSchemaDescription*> schemas { &noisyReluSchema };
registry->RegisterOperatorSetSchema(
&operatorSetId,
6 /* baseline version */,
schemas.data(),
static_cast<uint32_t>(schemas.size()),
nullptr,
nullptr
);
}
static void RegisterNoisyReluKernel(winrt::com_ptr<IMLOperatorRegistry> registry)
{
MLOperatorKernelDescription kernelDescription;
kernelDescription.domain = "";
kernelDescription.name = "NoisyRelu";
kernelDescription.minimumOperatorSetVersion = 1;
kernelDescription.executionType = MLOperatorExecutionType::Cpu;
MLOperatorEdgeTypeConstrant typeConstraint;
typeConstraint.typeLabel = "T";
std::vector<MLOperatorEdgeDescription> allowedEdges
{
CreateEdgeDescriptor(MLOperatorEdgeType::Tensor, MLOperatorTensorDataType::Double),
CreateEdgeDescriptor(MLOperatorEdgeType::Tensor, MLOperatorTensorDataType::Float),
CreateEdgeDescriptor(MLOperatorEdgeType::Tensor, MLOperatorTensorDataType::Float16)
};
typeConstraint.allowedTypes = allowedEdges.data();
typeConstraint.allowedTypeCount = static_cast<uint32_t>(allowedEdges.size());
std::vector<MLOperatorEdgeTypeConstrant> typeConstraints{ typeConstraint };
kernelDescription.typeConstraints = typeConstraints.data();
kernelDescription.typeConstraintCount = static_cast<uint32_t>(typeConstraints.size());
MLOperatorAttributeNameValue noisyReluMeanAttributeValue;
noisyReluMeanAttributeValue.name = "mean";
noisyReluMeanAttributeValue.type = MLOperatorAttributeType::Float;
noisyReluMeanAttributeValue.valueCount = 1;
static float defaultMeans[] = { 0.f };
noisyReluMeanAttributeValue.floats = defaultMeans;
MLOperatorAttributeNameValue noisyReluVarianceAttributeValue;
noisyReluVarianceAttributeValue.name = "variance";
noisyReluVarianceAttributeValue.type = MLOperatorAttributeType::Float;
noisyReluVarianceAttributeValue.valueCount = 1;
static float defaultVariance[] = { 1.f };
noisyReluVarianceAttributeValue.floats = defaultVariance;
std::vector<MLOperatorAttributeNameValue> attributeDefaultValues{ noisyReluMeanAttributeValue, noisyReluVarianceAttributeValue };
kernelDescription.defaultAttributes = attributeDefaultValues.data();
kernelDescription.defaultAttributeCount = static_cast<uint32_t>(attributeDefaultValues.size());
kernelDescription.options = MLOperatorKernelOptions::None;
kernelDescription.executionOptions = 0;
auto factory = winrt::make<NoisyReluOperatorFactory>();
auto shareInferrer = winrt::make<NoisyReluShapeInferrer>();
registry->RegisterOperatorKernel(
&kernelDescription,
factory.get(),
shareInferrer.get()
);
}
};