From 51c12a715b8b7ab91dc13752e257fd4ec4eba236 Mon Sep 17 00:00:00 2001 From: Bowen Bao Date: Mon, 21 Jun 2021 10:21:48 -0700 Subject: [PATCH] Add NGramRepeatBlock contrib op (#8078) **Description**: Enforce no repetition of n-grams. Scores are set to `-inf` for tokens that form a repeated n-gram if added to the back of the input_ids. **Motivation and Context** Needed by transformer models in sequence generation algorithms (greedy search and beam search). This module has heavy impact on performance, and can be highly parallelized. --- docs/ContribOperators.md | 42 +++++++++ docs/OperatorKernels.md | 2 + .../cpu/bert/ngram_repeat_block.cc | 20 +++++ .../contrib_ops/cpu/bert/ngram_repeat_block.h | 85 +++++++++++++++++++ .../contrib_ops/cpu/cpu_contrib_kernels.cc | 2 + .../cuda/bert/ngram_repeat_block.cc | 71 ++++++++++++++++ .../cuda/bert/ngram_repeat_block.h | 24 ++++++ .../cuda/bert/ngram_repeat_block_impl.cu | 84 ++++++++++++++++++ .../cuda/bert/ngram_repeat_block_impl.h | 26 ++++++ .../contrib_ops/cuda/cuda_contrib_kernels.cc | 3 + .../core/graph/contrib_ops/contrib_defs.cc | 23 +++++ .../contrib_ops/ngram_repeat_block_op_test.cc | 41 +++++++++ .../kernel_def_hashes/contrib.cpu.json | 4 + 13 files changed, 427 insertions(+) create mode 100644 onnxruntime/contrib_ops/cpu/bert/ngram_repeat_block.cc create mode 100644 onnxruntime/contrib_ops/cpu/bert/ngram_repeat_block.h create mode 100644 onnxruntime/contrib_ops/cuda/bert/ngram_repeat_block.cc create mode 100644 onnxruntime/contrib_ops/cuda/bert/ngram_repeat_block.h create mode 100644 onnxruntime/contrib_ops/cuda/bert/ngram_repeat_block_impl.cu create mode 100644 onnxruntime/contrib_ops/cuda/bert/ngram_repeat_block_impl.h create mode 100644 onnxruntime/test/contrib_ops/ngram_repeat_block_op_test.cc diff --git a/docs/ContribOperators.md b/docs/ContribOperators.md index ce59fa1337..adc13ee3ad 100644 --- a/docs/ContribOperators.md +++ b/docs/ContribOperators.md @@ -32,6 +32,7 @@ Do not modify directly.* * com.microsoft.MaxpoolWithMask * com.microsoft.MulInteger * com.microsoft.MurmurHash3 + * com.microsoft.NGramRepeatBlock * com.microsoft.NhwcMaxPool * com.microsoft.Pad * com.microsoft.QAttention @@ -1517,6 +1518,47 @@ This version of the operator has been available since version 1 of the 'com.micr +### **com.microsoft.NGramRepeatBlock** + + Enforce no repetition of n-grams. Scores are set to `-inf` for tokens that form a repeated n-gram if added to the back of the input_ids. + +#### Version + +This version of the operator has been available since version 1 of the 'com.microsoft' operator set. + +#### Attributes + +
+
ngram_size : int (required)
+
The NGram size.
+
+ +#### Inputs + +
+
input_ids : Tid
+
2D input tensor with shape (batch_size, sequence_length)
+
scores : T
+
2D input tensor with shape (batch_size, vocab_size)
+
+ +#### Outputs + +
+
scores_out : T
+
2D output tensor with shape (batch_size, vocab_size)
+
+ +#### Type Constraints + +
+
Tid : tensor(int64)
+
Constrain indices to integer types
+
T : tensor(float)
+
Constrain scores input and output types to float tensors.
+
+ + ### **com.microsoft.NhwcMaxPool** #### Version diff --git a/docs/OperatorKernels.md b/docs/OperatorKernels.md index 12ea0af6ef..97935346e0 100644 --- a/docs/OperatorKernels.md +++ b/docs/OperatorKernels.md @@ -388,6 +388,7 @@ Do not modify directly.* |MatMulIntegerToFloat|*in* A:**T1**
*in* B:**T2**
*in* a_scale:**T3**
*in* b_scale:**T3**
*in* a_zero_point:**T1**
*in* b_zero_point:**T2**
*in* bias:**T3**
*out* Y:**T3**|1+|**T1** = tensor(uint8)
**T2** = tensor(int8), tensor(uint8)
**T3** = tensor(float)| |MaxpoolWithMask|*in* X:**T**
*in* M:**tensor(int32)**
*out* Y:**T**|1+|**X** = tensor(float)| |MurmurHash3|*in* X:**T1**
*out* Y:**T2**|1+|**T1** = tensor(double), tensor(float), tensor(int32), tensor(int64), tensor(string), tensor(uint32), tensor(uint64)
**T2** = tensor(int32), tensor(uint32)| +|NGramRepeatBlock|*in* input_ids:**Tid**
*in* scores:**T**
*out* scores_out:**T**|1+|**T** = tensor(float)
**Tid** = tensor(int64)| |NhwcMaxPool|*in* x:**T**
*out* y:**T**|1+|**T** = tensor(uint8)| |Pad|*in* data:**T**
*in* pads:**tensor(int64)**
*in* value:**T**
*out* output:**T**|1+|**T** = tensor(float)| |QAttention|*in* input:**T1**
*in* weight:**T2**
*in* bias:**T3**
*in* input_scale:**T3**
*in* weight_scale:**T3**
*in* mask_index:**T4**
*in* input_zero_point:**T1**
*in* weight_zero_point:**T2**
*in* past:**T3**
*out* output:**T3**
*out* present:**T3**|1+|**T1** = tensor(uint8)
**T2** = tensor(int8), tensor(uint8)
**T3** = tensor(float)
**T4** = tensor(int32)| @@ -713,6 +714,7 @@ Do not modify directly.* |Inverse|*in* X:**T**
*out* Y:**T**|1+|**T** = tensor(double), tensor(float), tensor(float16)| |Irfft|*in* X:**T**
*out* Y:**T**|1+|**T** = tensor(double), tensor(float), tensor(float16)| |LongformerAttention|*in* input:**T**
*in* weight:**T**
*in* bias:**T**
*in* mask:**T**
*in* global_weight:**T**
*in* global_bias:**T**
*in* global:**G**
*out* output:**T**|1+|**T** = tensor(float), tensor(float16)| +|NGramRepeatBlock|*in* input_ids:**Tid**
*in* scores:**T**
*out* scores_out:**T**|1+|**T** = tensor(float)
**Tid** = tensor(int64)| |QAttention|*in* input:**T1**
*in* weight:**T2**
*in* bias:**T3**
*in* input_scale:**T3**
*in* weight_scale:**T3**
*in* mask_index:**T4**
*in* input_zero_point:**T1**
*in* weight_zero_point:**T2**
*in* past:**T3**
*out* output:**T3**
*out* present:**T3**|1+|**T1** = tensor(int8)
**T2** = tensor(int8)
**T3** = tensor(float), tensor(float16)
**T4** = tensor(int32)| |QuantizeLinear|*in* x:**T1**
*in* y_scale:**T1**
*in* y_zero_point:**T2**
*out* y:**T2**|1+|**T1** = tensor(float16)
**T2** = tensor(int8), tensor(uint8)| |Rfft|*in* X:**T**
*out* Y:**T**|1+|**T** = tensor(double), tensor(float), tensor(float16)| diff --git a/onnxruntime/contrib_ops/cpu/bert/ngram_repeat_block.cc b/onnxruntime/contrib_ops/cpu/bert/ngram_repeat_block.cc new file mode 100644 index 0000000000..1e651861fe --- /dev/null +++ b/onnxruntime/contrib_ops/cpu/bert/ngram_repeat_block.cc @@ -0,0 +1,20 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "ngram_repeat_block.h" + + +namespace onnxruntime { +namespace contrib { + +ONNX_OPERATOR_KERNEL_EX( + NGramRepeatBlock, + kMSDomain, + 1, + kCpuExecutionProvider, + KernelDefBuilder() + .TypeConstraint("Tid", DataTypeImpl::GetTensorType()) + .TypeConstraint("T", DataTypeImpl::GetTensorType()), + NGramRepeatBlock); +} // namespace contrib +} // namespace onnxruntime diff --git a/onnxruntime/contrib_ops/cpu/bert/ngram_repeat_block.h b/onnxruntime/contrib_ops/cpu/bert/ngram_repeat_block.h new file mode 100644 index 0000000000..509a35fc33 --- /dev/null +++ b/onnxruntime/contrib_ops/cpu/bert/ngram_repeat_block.h @@ -0,0 +1,85 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#include "core/common/common.h" +#include "core/framework/op_kernel.h" +#include "core/platform/threadpool.h" + +namespace onnxruntime { +namespace contrib { +class NGramRepeatBlock : public OpKernel { + public: + explicit NGramRepeatBlock(const OpKernelInfo& info) : OpKernel(info) { + ORT_ENFORCE(info.GetAttr("ngram_size", &ngram_size_).IsOK()); + ORT_ENFORCE(ngram_size_ > 0); + } + + Status Compute(OpKernelContext* context) const override { + const Tensor* input_ids = context->Input(0); + const Tensor* scores = context->Input(1); + Tensor* output = context->Output(0, scores->Shape()); + + const auto* scores_source = static_cast(scores->DataRaw()); + auto* scores_target = static_cast(output->MutableDataRaw()); + if (scores_source != scores_target) { + memcpy(scores_target, scores_source, scores->Shape().Size() * sizeof(float)); + } + + const auto& input_ids_dims = input_ids->Shape().GetDims(); + const auto& scores_dims = scores->Shape().GetDims(); + ORT_ENFORCE(input_ids_dims.size() == 2); + ORT_ENFORCE(scores_dims.size() == 2); + int64_t batch_size = input_ids_dims[0]; + int64_t cur_len = input_ids_dims[1]; + ORT_ENFORCE(scores_dims[0] == batch_size); + int64_t vocab_size = scores_dims[1]; + + if (cur_len + 1 < ngram_size_) { + return Status::OK(); + } + + const auto* input_ids_data = static_cast(input_ids->DataRaw(input_ids->DataType())); + + auto lambda = [&](int64_t b) { + for (int64_t i = 0; i < cur_len; ++i) { + if (i + ngram_size_ > cur_len) { + break; + } + + bool is_banned = true; + for (int64_t j = 0; j < ngram_size_ - 1; ++j) { + auto token_at_tail = input_ids_data[b * cur_len + i + j]; + auto token_to_cmp = input_ids_data[b * cur_len + cur_len + 1 - ngram_size_ + j]; + if (token_at_tail != token_to_cmp) { + is_banned = false; + break; + } + } + + if (is_banned) { + auto token_id = static_cast(input_ids_data[b * cur_len + i + ngram_size_ - 1]); + ORT_ENFORCE(token_id < vocab_size); + scores_target[b * vocab_size + token_id] = -std::numeric_limits::infinity(); + } + } + }; + + concurrency::ThreadPool* tp = context->GetOperatorThreadPool(); + concurrency::ThreadPool::TryParallelFor( + tp, batch_size, static_cast(cur_len * ngram_size_), + [&lambda](ptrdiff_t first, ptrdiff_t last) { + for (auto b = static_cast(first), end = static_cast(last); b < end; ++b) { + lambda(b); + } + } + ); + + return Status::OK(); + } + private: + int64_t ngram_size_; +}; +} // namespace contrib +} // namespace onnxruntime diff --git a/onnxruntime/contrib_ops/cpu/cpu_contrib_kernels.cc b/onnxruntime/contrib_ops/cpu/cpu_contrib_kernels.cc index 7933a06d26..0f9b2435a3 100644 --- a/onnxruntime/contrib_ops/cpu/cpu_contrib_kernels.cc +++ b/onnxruntime/contrib_ops/cpu/cpu_contrib_kernels.cc @@ -33,6 +33,7 @@ class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kMSDomain, 1, class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kMSDomain, 1, Gelu); class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kMSDomain, 1, BiasGelu); class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kMSDomain, 1, FastGelu); +class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kMSDomain, 1, NGramRepeatBlock); #ifdef BUILD_MS_EXPERIMENTAL_OPS class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kMSExperimentalDomain, 1, DFT); @@ -194,6 +195,7 @@ Status RegisterCpuContribKernels(KernelRegistry& kernel_registry) { BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, + BuildKernelCreateInfo, #ifdef BUILD_MS_EXPERIMENTAL_OPS BuildKernelCreateInfo, diff --git a/onnxruntime/contrib_ops/cuda/bert/ngram_repeat_block.cc b/onnxruntime/contrib_ops/cuda/bert/ngram_repeat_block.cc new file mode 100644 index 0000000000..53fb3ffa9d --- /dev/null +++ b/onnxruntime/contrib_ops/cuda/bert/ngram_repeat_block.cc @@ -0,0 +1,71 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "core/providers/cuda/cuda_common.h" +#include "ngram_repeat_block.h" +#include "ngram_repeat_block_impl.h" + +namespace onnxruntime { +namespace contrib { +namespace cuda { + +ONNX_OPERATOR_KERNEL_EX( + NGramRepeatBlock, + kMSDomain, + 1, + kCudaExecutionProvider, + (*KernelDefBuilder::Create()) + .TypeConstraint("Tid", DataTypeImpl::GetTensorType()) + .TypeConstraint("T", DataTypeImpl::GetTensorType()), + NGramRepeatBlock); + +using namespace ONNX_NAMESPACE; + +NGramRepeatBlock::NGramRepeatBlock(const OpKernelInfo& info) : CudaKernel(info) { + ORT_ENFORCE(info.GetAttr("ngram_size", &ngram_size_).IsOK()); + ORT_ENFORCE(ngram_size_ > 0); +} + +Status NGramRepeatBlock::ComputeInternal(OpKernelContext* context) const { + const Tensor* input_ids = context->Input(0); + const Tensor* scores = context->Input(1); + Tensor* output = context->Output(0, scores->Shape()); + + const auto* scores_source = static_cast(scores->DataRaw()); + auto* scores_target = static_cast(output->MutableDataRaw()); + if (scores_source != scores_target) { + CUDA_RETURN_IF_ERROR(cudaMemcpyAsync(scores_target, scores_source, scores->Shape().Size() * sizeof(float), cudaMemcpyDeviceToDevice, Stream())); + } + + const auto& input_ids_dims = input_ids->Shape().GetDims(); + const auto& scores_dims = scores->Shape().GetDims(); + ORT_ENFORCE(input_ids_dims.size() == 2); + ORT_ENFORCE(scores_dims.size() == 2); + int64_t batch_size = input_ids_dims[0]; + int64_t cur_len = input_ids_dims[1]; + ORT_ENFORCE(scores_dims[0] == batch_size); + int64_t vocab_size = scores_dims[1]; + + if (cur_len + 1 < ngram_size_) { + return Status::OK(); + } + + const auto* input_ids_data = static_cast(input_ids->DataRaw(input_ids->DataType())); + + NGramRepeatBlockImpl( + Stream(), + input_ids_data, + scores_target, + gsl::narrow_cast(batch_size), + gsl::narrow_cast(cur_len - 1), + gsl::narrow_cast(cur_len), + gsl::narrow_cast(vocab_size), + gsl::narrow_cast(1), + gsl::narrow_cast(ngram_size_)); + + return Status::OK(); +} + +} //namespace cuda +} // namespace contrib +} // namespace onnxruntime diff --git a/onnxruntime/contrib_ops/cuda/bert/ngram_repeat_block.h b/onnxruntime/contrib_ops/cuda/bert/ngram_repeat_block.h new file mode 100644 index 0000000000..eb219916ba --- /dev/null +++ b/onnxruntime/contrib_ops/cuda/bert/ngram_repeat_block.h @@ -0,0 +1,24 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once +#include "core/common/common.h" +#include "core/providers/cuda/cuda_kernel.h" + +namespace onnxruntime { +namespace contrib { +namespace cuda { + +using namespace onnxruntime::cuda; + +class NGramRepeatBlock final : public CudaKernel { + public: + NGramRepeatBlock(const OpKernelInfo& op_kernel_info); + Status ComputeInternal(OpKernelContext* ctx) const override; + private: + int64_t ngram_size_; +}; + +} // namespace cuda +} // namespace contrib +} // namespace onnxruntime diff --git a/onnxruntime/contrib_ops/cuda/bert/ngram_repeat_block_impl.cu b/onnxruntime/contrib_ops/cuda/bert/ngram_repeat_block_impl.cu new file mode 100644 index 0000000000..887f32721c --- /dev/null +++ b/onnxruntime/contrib_ops/cuda/bert/ngram_repeat_block_impl.cu @@ -0,0 +1,84 @@ +/* +Copyright (c) Microsoft Corporation. +Licensed under the MIT License. +*/ + +/* +Kernel implementation for blocking repeated n-grams. +*/ + +#include "core/providers/cuda/cu_inc/common.cuh" +#include "contrib_ops/cuda/bert/ngram_repeat_block_impl.h" + +namespace onnxruntime { +namespace contrib { +namespace cuda { + +using namespace onnxruntime::cuda; + +// Ban repeated ngrams of length = 'no_repeat_ngram_size' +__global__ void banRepeatedTokens(const int64_t* __restrict__ tokens, + float* __restrict__ lprobs, + int max_predict_len, int vocab_size, + int no_repeat_ngram_size) { + auto row = blockIdx.x; + auto col = threadIdx.x; + auto start = row * (max_predict_len) + col; + // Each thread compares ngram starting from + // thread index with final ngram starting from + // step - no_repeat_ngram_size +2 + auto check_start_pos = blockDim.x; + auto lprob_start = row * vocab_size; + bool is_banned = true; + extern __shared__ int64_t tokens_shm[]; + tokens_shm[col] = tokens[start]; + if (col == blockDim.x - 1) { + for (int i=1; i>>( + tokens_ptr, scores_ptr, max_predict_len, vocab_size, no_repeat_ngram_size); +} + +} // namespace cuda +} // namespace contrib +} // namespace onnxruntime diff --git a/onnxruntime/contrib_ops/cuda/bert/ngram_repeat_block_impl.h b/onnxruntime/contrib_ops/cuda/bert/ngram_repeat_block_impl.h new file mode 100644 index 0000000000..b96caf6a4d --- /dev/null +++ b/onnxruntime/contrib_ops/cuda/bert/ngram_repeat_block_impl.h @@ -0,0 +1,26 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once +#include "core/providers/cuda/shared_inc/cuda_utils.h" + +namespace onnxruntime { +namespace contrib { +namespace cuda { + +using namespace onnxruntime::cuda; + +void NGramRepeatBlockImpl( + cudaStream_t stream, + const int64_t* tokens_ptr, + float* scores_ptr, + int bsz, + int step, + int max_predict_len, + int vocab_size, + int beam_size, + int no_repeat_ngram_size); + +} // namespace cuda +} // namespace contrib +} // namespace onnxruntime diff --git a/onnxruntime/contrib_ops/cuda/cuda_contrib_kernels.cc b/onnxruntime/contrib_ops/cuda/cuda_contrib_kernels.cc index 64288cab64..86feca4f48 100644 --- a/onnxruntime/contrib_ops/cuda/cuda_contrib_kernels.cc +++ b/onnxruntime/contrib_ops/cuda/cuda_contrib_kernels.cc @@ -35,6 +35,8 @@ class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kMSDomain, 1 class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kMSDomain, 1, MLFloat16, ComplexMulConj); class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCudaExecutionProvider, kMSDomain, 1, BiasSoftmax); class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCudaExecutionProvider, kMSDomain, 1, BiasDropout); +class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCudaExecutionProvider, kMSDomain, 1, NGramRepeatBlock); + // These ops were experimental ops in onnx domain which have been removed now. We add them here as // contrib ops to maintain backward compatibility @@ -122,6 +124,7 @@ Status RegisterCudaContribKernels(KernelRegistry& kernel_registry) { BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, + BuildKernelCreateInfo, // These ops were experimental ops in onnx domain which have been removed now. We add them here as // contrib ops to maintain backward compatibility diff --git a/onnxruntime/core/graph/contrib_ops/contrib_defs.cc b/onnxruntime/core/graph/contrib_ops/contrib_defs.cc index d276cea322..ab51a82523 100644 --- a/onnxruntime/core/graph/contrib_ops/contrib_defs.cc +++ b/onnxruntime/core/graph/contrib_ops/contrib_defs.cc @@ -610,6 +610,29 @@ GELU (Gaussian Error Linear Unit) approximation: Y=0.5*X*(1+tanh(0.797885*X+0.03 .TypeConstraint("T", {"tensor(float)", "tensor(float16)"}, "Constrain input and output types to float or half tensors.") .TypeConstraint("U", {"tensor(float)"}, "Constrain mean and inv_std_var to float tensors.") .TypeAndShapeInferenceFunction(ONNX_NAMESPACE::propagateShapeAndTypeFromFirstInput); + + + static const char* NGramRepeatBlock_ver1_doc = R"DOC( +Enforce no repetition of n-grams. Scores are set to `-inf` for tokens that form a repeated n-gram if added to the back of the input_ids. +)DOC"; + + ONNX_CONTRIB_OPERATOR_SCHEMA(NGramRepeatBlock) + .SetDomain(kMSDomain) + .SinceVersion(1) + .SetDoc(NGramRepeatBlock_ver1_doc) + .Attr("ngram_size", "The NGram size.", AttributeProto::INT) + .Input(0, "input_ids", "2D input tensor with shape (batch_size, sequence_length)", "Tid") + .Input(1, "scores", "2D input tensor with shape (batch_size, vocab_size)", "T") + .Output(0, "scores_out", "2D output tensor with shape (batch_size, vocab_size)", "T") + .TypeConstraint("Tid", {"tensor(int64)"}, "Constrain indices to integer types") + .TypeConstraint("T", {"tensor(float)"}, "Constrain scores input and output types to float tensors.") + .TypeAndShapeInferenceFunction([](ONNX_NAMESPACE::InferenceContext& ctx) { + propagateElemTypeFromInputToOutput(ctx, 1, 0); + if (!hasInputShape(ctx, 1)) { + return; + } + propagateShapeFromInputToOutput(ctx, 1, 0); + }); } void RegisterContribSchemas() { diff --git a/onnxruntime/test/contrib_ops/ngram_repeat_block_op_test.cc b/onnxruntime/test/contrib_ops/ngram_repeat_block_op_test.cc new file mode 100644 index 0000000000..8b062a09f6 --- /dev/null +++ b/onnxruntime/test/contrib_ops/ngram_repeat_block_op_test.cc @@ -0,0 +1,41 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "gtest/gtest.h" +#include "test/common/tensor_op_test_utils.h" +#include "test/common/cuda_op_test_utils.h" +#include "test/providers/provider_test_utils.h" + +namespace onnxruntime { +namespace test { + +TEST(NGramRepeatBlockTest, NGramSize_3) { + OpTester tester("NGramRepeatBlock", 1, onnxruntime::kMSDomain); + + tester.AddInput("input_ids", {3, 6}, + {0, 1, 2, 3, 1, 2, + 0, 0, 0, 1, 0, 0, + 0, 1, 0, 1, 0, 1}); + tester.AddInput("scores", {3, 4}, + {1.0f, 2.0f, 3.0f, 4.0f, + 5.0f, 6.0f, 7.0f, 8.0f, + 9.0f, 10.0f, 11.0f, 12.0f}); + tester.AddAttribute("ngram_size", (int64_t)3); + tester.AddOutput("scores_out", {3, 4}, + {1.0f, 2.0f, 3.0f, -std::numeric_limits::infinity(), + -std::numeric_limits::infinity(), -std::numeric_limits::infinity(), 7.0f, 8.0f, + -std::numeric_limits::infinity(), 10.0f, 11.0f, 12.0f}); + + if (HasCudaEnvironment(0)) { + std::vector> execution_providers; + execution_providers.push_back(DefaultCudaExecutionProvider()); + tester.Run(OpTester::ExpectResult::kExpectSuccess, "", {}, nullptr, &execution_providers); + } + + std::vector> execution_providers; + execution_providers.push_back(DefaultCpuExecutionProvider()); + tester.Run(OpTester::ExpectResult::kExpectSuccess, "", {}, nullptr, &execution_providers); +} + +} // namespace test +} // namespace onnxruntime diff --git a/onnxruntime/test/testdata/kernel_def_hashes/contrib.cpu.json b/onnxruntime/test/testdata/kernel_def_hashes/contrib.cpu.json index 81706fb45f..6d79f1b5cc 100644 --- a/onnxruntime/test/testdata/kernel_def_hashes/contrib.cpu.json +++ b/onnxruntime/test/testdata/kernel_def_hashes/contrib.cpu.json @@ -151,6 +151,10 @@ "NhwcMaxPool com.microsoft CPUExecutionProvider", 8512357837341844248 ], + [ + "NGramRepeatBlock com.microsoft CPUExecutionProvider", + 17162613206685017176 + ], [ "Pad com.microsoft CPUExecutionProvider", 15076596470814458544