[DML EP] Add BiasAdd (#15211)

This commit is contained in:
Patrice Vignola 2023-04-10 14:46:33 -07:00 committed by GitHub
parent ce9ad8c8bc
commit 4a676b011a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 124 additions and 2 deletions

View file

@ -1173,6 +1173,7 @@ Do not modify directly.*
| |
|**Operator Domain:** *com.microsoft*||||
|Attention|*in* input:**T**<br> *in* weights:**T**<br> *in* bias:**T**<br> *in* mask_index:**M**<br> *in* past:**T**<br> *in* relative_position_bias:**T**<br> *in* past_sequence_length:**M**<br> *out* output:**T**<br> *out* present:**T**|1+|**M** = tensor(int32)<br/> **T** = tensor(float), tensor(float16)|
|BiasAdd|*in* X:**T**<br> *in* bias:**T**<br> *in* skip:**T**<br> *out* Y:**T**|1+|**T** = tensor(float), tensor(float16)|
|BiasGelu|*in* A:**T**<br> *in* B:**T**<br> *out* C:**T**|1+|**T** = tensor(float), tensor(float16)|
|ConvTransposeWithDynamicPads|*in* X:**T**<br> *in* W:**T**<br> *in* Pads:**tensor(int64)**<br> *in* B:**T**<br> *out* Y:**T**|1+|**T** = tensor(float), tensor(float16)|
|DequantizeLinear|*in* x:**T1**<br> *in* x_scale:**T2**<br> *in* x_zero_point:**T1**<br> *out* y:**T2**|1+|**T1** = tensor(float)<br/> **T2** = tensor(uint8)|

View file

@ -0,0 +1,113 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#include "precomp.h"
namespace Dml
{
class DmlOperatorBiasAdd : public DmlOperator
{
public:
DmlOperatorBiasAdd(const MLOperatorKernelCreationContext& kernelCreationContext)
: DmlOperator(kernelCreationContext)
{
ML_CHECK_VALID_ARGUMENT(kernelCreationContext.GetInputCount() == 3);
ML_CHECK_VALID_ARGUMENT(kernelCreationContext.GetOutputCount() == 1);
// Broadcast bias to have the same dimensions as the input
std::vector<uint32_t> inputTensorShape = kernelCreationContext.GetTensorShapeDescription().GetInputTensorShape(0);
DmlOperator::Initialize(kernelCreationContext, std::nullopt, std::nullopt, inputTensorShape);
ML_CHECK_VALID_ARGUMENT(m_inputTensorDescs.size() == 3);
ML_CHECK_VALID_ARGUMENT(m_outputTensorDescs.size() == 1);
ML_CHECK_VALID_ARGUMENT(m_inputTensorDescs[0].GetDimensionCount() == 4);
ML_CHECK_VALID_ARGUMENT(m_inputTensorDescs[1].GetDimensionCount() == 4);
ML_CHECK_VALID_ARGUMENT(m_inputTensorDescs[2].GetDimensionCount() == 4);
ML_CHECK_VALID_ARGUMENT(m_inputTensorDescs[0].GetSizes() == m_inputTensorDescs[2].GetSizes());
std::vector<DML_TENSOR_DESC> inputDescs = GetDmlInputDescs();
std::vector<DML_TENSOR_DESC> outputDescs = GetDmlOutputDescs();
// 1. Add the bias
DML_ELEMENT_WISE_ADD_OPERATOR_DESC addBiasDesc{};
addBiasDesc.ATensor = &inputDescs[0];
addBiasDesc.BTensor = &inputDescs[1];
addBiasDesc.OutputTensor = &inputDescs[0];
DML_OPERATOR_DESC dmlAddBiasDesc = { DML_OPERATOR_ELEMENT_WISE_ADD, &addBiasDesc };
// 2. Add the residual inputs
DML_ELEMENT_WISE_ADD_OPERATOR_DESC addSkipDesc{};
addSkipDesc.ATensor = &inputDescs[0];
addSkipDesc.BTensor = &inputDescs[2];
addSkipDesc.OutputTensor = &inputDescs[0];
DML_OPERATOR_DESC dmlAddSkipDesc = { DML_OPERATOR_ELEMENT_WISE_ADD, &addSkipDesc };
enum NodeIndex
{
addBiasNodeIndex,
addSkipNodeIndex,
nodeCount,
};
// Construct the graph
std::vector<const DML_OPERATOR_DESC*> opDescs(nodeCount);
opDescs[addBiasNodeIndex] = &dmlAddBiasDesc;
opDescs[addSkipNodeIndex] = &dmlAddSkipDesc;
std::vector<DML_INPUT_GRAPH_EDGE_DESC> inputEdges;
inputEdges.reserve(3);
std::vector<DML_INTERMEDIATE_GRAPH_EDGE_DESC> intermediateEdges;
intermediateEdges.reserve(1);
std::vector<DML_OUTPUT_GRAPH_EDGE_DESC> outputEdges;
outputEdges.reserve(1);
DML_INPUT_GRAPH_EDGE_DESC inputToAddBiasEdge{};
inputToAddBiasEdge.GraphInputIndex = 0;
inputToAddBiasEdge.ToNodeIndex = addBiasNodeIndex;
inputToAddBiasEdge.ToNodeInputIndex = 0;
inputEdges.push_back(inputToAddBiasEdge);
DML_INPUT_GRAPH_EDGE_DESC biasToAddBiasEdge{};
biasToAddBiasEdge.GraphInputIndex = 1;
biasToAddBiasEdge.ToNodeIndex = addBiasNodeIndex;
biasToAddBiasEdge.ToNodeInputIndex = 1;
inputEdges.push_back(biasToAddBiasEdge);
DML_INTERMEDIATE_GRAPH_EDGE_DESC addBiasToAddSkipEdge{};
addBiasToAddSkipEdge.FromNodeIndex = addBiasNodeIndex;
addBiasToAddSkipEdge.FromNodeOutputIndex = 0;
addBiasToAddSkipEdge.ToNodeIndex = addSkipNodeIndex;
addBiasToAddSkipEdge.ToNodeInputIndex = 0;
intermediateEdges.push_back(addBiasToAddSkipEdge);
DML_INPUT_GRAPH_EDGE_DESC skipToAddSkipEdge{};
skipToAddSkipEdge.GraphInputIndex = 2;
skipToAddSkipEdge.ToNodeIndex = addSkipNodeIndex;
skipToAddSkipEdge.ToNodeInputIndex = 1;
inputEdges.push_back(skipToAddSkipEdge);
DML_OUTPUT_GRAPH_EDGE_DESC addSkipToOutputEdge{};
addSkipToOutputEdge.FromNodeIndex = addSkipNodeIndex;
addSkipToOutputEdge.FromNodeOutputIndex = 0;
addSkipToOutputEdge.GraphOutputIndex = 0;
outputEdges.push_back(addSkipToOutputEdge);
MLOperatorGraphDesc operatorGraphDesc = {};
operatorGraphDesc.inputEdgeCount = gsl::narrow_cast<uint32_t>(inputEdges.size());
operatorGraphDesc.inputEdges = inputEdges.data();
operatorGraphDesc.intermediateEdgeCount = gsl::narrow_cast<uint32_t>(intermediateEdges.size());
operatorGraphDesc.intermediateEdges = intermediateEdges.data();
operatorGraphDesc.outputEdgeCount = gsl::narrow_cast<uint32_t>(outputEdges.size());
operatorGraphDesc.outputEdges = outputEdges.data();
operatorGraphDesc.nodeCount = gsl::narrow_cast<uint32_t>(opDescs.size());
operatorGraphDesc.nodesAsOpDesc = opDescs.data();
SetDmlOperatorGraphDesc(std::move(operatorGraphDesc), kernelCreationContext);
}
};
DML_OP_DEFINE_CREATION_FUNCTION(BiasAdd, DmlOperatorBiasAdd);
} // namespace Dml

View file

@ -211,6 +211,7 @@ DML_OP_EXTERN_CREATION_FUNCTION(LayerNormalization);
DML_OP_EXTERN_CREATION_FUNCTION(LayerNormalization17);
DML_OP_EXTERN_CREATION_FUNCTION(SkipLayerNormalization);
DML_OP_EXTERN_CREATION_FUNCTION(EmbedLayerNormalization);
DML_OP_EXTERN_CREATION_FUNCTION(BiasAdd);
DML_OP_EXTERN_CREATION_FUNCTION(LRN);
DML_OP_EXTERN_CREATION_FUNCTION(MeanVarianceNormalization);
DML_OP_EXTERN_CREATION_FUNCTION(GroupNorm);
@ -879,6 +880,7 @@ constexpr static OperatorRegistrationInformation operatorRegistrationInformation
{REG_INFO( 7, LayerNormalization, typeNameListLayerNormContrib, supportedTypeListLayerNormalizationContrib, DmlGraphSupport::Supported, requiredConstantCpuInputs(), std::nullopt, QueryLayerNormalization)},
{REG_INFO_MS( 1, SkipLayerNormalization, typeNameListDefault, supportedTypeListFloat16to32, DmlGraphSupport::Supported, requiredConstantCpuInputs(), std::nullopt, QuerySkipLayerNormalization)},
{REG_INFO_MS( 1, EmbedLayerNormalization, typeNameListDefault, supportedTypeListFloat16to32, DmlGraphSupport::Supported)},
{REG_INFO_MS( 1, BiasAdd, typeNameListDefault, supportedTypeListFloat16to32, DmlGraphSupport::Supported)},
{REG_INFO_MS( 1, QuickGelu, typeNameListDefault, supportedTypeListFloat16to32, DmlGraphSupport::Supported)},
{REG_INFO_MS( 1, GroupNorm, typeNameListGroupNorm, supportedTypeListGroupNorm, DmlGraphSupport::Supported)},
};

View file

@ -1444,6 +1444,7 @@ using ShapeInferenceHelper_LpNormalization = GetOutputShapeAsInputShapeHelper;
using ShapeInferenceHelper_RNN = RecurrentHelper;
using ShapeInferenceHelper_GRU = RecurrentHelper;
using ShapeInferenceHelper_LSTM = RecurrentHelper;
using ShapeInferenceHelper_BiasAdd = GetOutputShapeAsInputShapeHelper;
using ShapeInferenceHelper_Gather = GatherHelper;
using ShapeInferenceHelper_GatherElements = GetOutputShapeAsSpecificInputShapeHelper<1>;

View file

@ -410,6 +410,7 @@ namespace OperatorHelper
static const int sc_sinceVer_Attention = 1;
static const int sc_sinceVer_SkipLayerNormalization = 1;
static const int sc_sinceVer_EmbedLayerNormalization = 1;
static const int sc_sinceVer_BiasAdd = 1;
static const int sc_sinceVer_QuickGelu = 1;
static const int sc_sinceVer_GroupNorm = 1;
} // namespace MsftOperatorSet1

View file

@ -13,7 +13,7 @@ using namespace onnxruntime::test;
namespace onnxruntime {
namespace test {
#if defined(USE_CUDA) || defined(USE_ROCM)
#if defined(USE_CUDA) || defined(USE_ROCM) || defined(USE_DML)
static std::vector<float> GetExpectedResult(const std::vector<float>& input_data,
const std::vector<float>& bias_data,
const std::vector<float>& skip_data) {
@ -39,8 +39,9 @@ static void RunSkipBiasGpuTest(const std::vector<float>& input_data,
int min_cuda_architecture = use_float16 ? 530 : 0;
bool enable_cuda = HasCudaEnvironment(min_cuda_architecture);
bool enable_rocm = (nullptr != DefaultRocmExecutionProvider().get());
bool enable_dml = (nullptr != DefaultDmlExecutionProvider().get());
if (!enable_cuda && !enable_rocm) {
if (!enable_cuda && !enable_rocm && !enable_dml) {
return;
}
@ -65,6 +66,9 @@ static void RunSkipBiasGpuTest(const std::vector<float>& input_data,
if (enable_rocm) {
execution_providers.push_back(DefaultRocmExecutionProvider());
}
if (enable_dml) {
execution_providers.push_back(DefaultDmlExecutionProvider());
}
tester.Run(OpTester::ExpectResult::kExpectSuccess, "", {}, nullptr, &execution_providers);
}