chore: import upstream snapshot with attribution
Docker Image CI / build-ubuntu2004 (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 13:36:55 +08:00
commit c8a779b1bb
1887 changed files with 3245738 additions and 0 deletions
@@ -0,0 +1,23 @@
#
# SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
add_plugin_source(
groupNormalizationKernel.cu
groupNormalizationPlugin.cpp
groupNormalizationPlugin.h
)
@@ -0,0 +1,111 @@
#
# SPDX-FileCopyrightText: Copyright (c) 2022-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
---
name: GroupNormalizationPlugin
interface: "IPluginV2DynamicExt"
versions:
"1":
inputs:
- input
- scale
- bias
outputs:
- output
input_dims:
input: 4
scale: 1
bias: 1
input_dim_constraints:
- "input_1 MULTIPLE_OF num_groups_0"
- "scale_0 == input_1"
- "bias_0 == scale_0"
input_dim_range:
input:
min: "=1, =1, =1, =1"
max: "=pinf, =pinf, =pinf, =pinf"
scale:
min: "=1"
max: "=pinf"
bias:
min: "=1"
max: "=pinf"
supported_input_types:
- combination1:
input: float32
scale: float32
bias: float32
output_dims:
output: "input_0, input_1, input_2, input_3"
attributes:
- eps
- num_groups
attribute_types:
eps: float32
num_groups: int32
attribute_length:
eps: 1
num_groups: 1
attribute_dim_range:
eps:
min: "=1"
max: "=1"
num_groups:
min: "=1"
max: "=1"
attribute_options:
eps:
min: "0"
max: "=pinf"
num_groups:
min: "=1"
max: "=pinf"
attributes_required: []
abs_tol: 1e-2
rel_tol: 1e-2
golden_reference_script: "plugin/GroupNormalizationPlugin_PluginReference.py"
configs:
config1:
input_types:
input: float32
scale: float32
bias: float32
attribute_options:
eps:
value: 0.0001
num_groups:
value: 1
config2:
input_types:
input: float32
scale: float32
bias: float32
attribute_options:
eps:
value: 0.001
num_groups:
value: 2
config3:
input_types:
input: float32
scale: float32
bias: float32
attribute_options:
eps:
value: 0.01
num_groups:
value: 3
...
+71
View File
@@ -0,0 +1,71 @@
# GroupNormalizationPlugin [DEPRECATED]
**This plugin is deprecated since TensorRT 10.12 and will be removed in a future release. No alternatives are planned to be provided.**
**Table Of Contents**
- [Description](#description)
* [Non-support for Blackwell and later platforms](#non-support-for-blackwell-and-later-platforms)
* [Structure](#structure)
- [Parameters](#parameters)
- [Additional Resources](#additional-resources)
- [License](#license)
- [Changelog](#changelog)
- [Known Issues](#known-issues)
## Description
The `GroupNormalizationPlugin` implements Group Normalization, which divides channels into groups and computes normalization statistics within each group. This is particularly useful for vision models where batch sizes may be small.
### Non-support for Blackwell and later platforms
As of TensorRT 10.7, usage of this plugin is not supported on Blackwell or later platforms.
This plugin can be replaced by TensorRT's native `INormalizationLayer`([C++](https://docs.nvidia.com/deeplearning/tensorrt/api/c_api/classnvinfer1_1_1_i_normalization_layer.html), [Python](https://docs.nvidia.com/deeplearning/tensorrt/operators/docs/Normalization.html)).
**Note:** This plugin remains supported on pre-Blackwell platforms.
### Structure
The plugin takes three inputs:
1. Input tensor with shape `[N, C, H, W]` (batch, channels, height, width), where `C` must be divisible by `num_groups`. (See [Parameters](#parameters) for more details on `num_groups`)
2. Scale parameters (per-channel, shape `[C]`)
3. Bias parameters (per-channel, shape `[C]`)
It produces one output with the same dimensions as the input. The normalization is computed as:
```
group_mean = mean(input, group)
group_var = variance(input, group)
output = gamma (input - group_mean) / sqrt(group_var + epsilon) + beta
```
Key differences from Instance Normalization:
- Normalizes across channel groups rather than individual channels
- More stable for small batch sizes
- Groups channels to capture cross-channel dependencies
## Parameters
| Parameter | Type | Description |
|--------------|---------|-------------|
| `epsilon` | float | Small value added to variance for numerical stability (default: 1e-5) |
| `num_groups` | int32 | Number of groups to split channels into; must evenly divide C |
## Additional Resources
- **Original Paper**: [Group Normalization](https://arxiv.org/abs/1803.08494)
- **ONNX Operator**: [GroupNormalization](https://github.com/onnx/onnx/blob/main/docs/Operators.md#GroupNormalization)
- **TensorRT Documentation**: [INormalizationLayer](https://docs.nvidia.com/deeplearning/tensorrt/api/c_api/classnvinfer1_1_1_i_normalization_layer.html)
- [Master README](../README.md) - Back to main documentation
## License
For terms and conditions for use, reproduction, and distribution, see the [TensorRT Software License Agreement](https://docs.nvidia.com/deeplearning/sdk/tensorrt-sla/index.html).
## Changelog
- **May 2025**: Add deprecation note.
- **Feb 2025**: Initial release of this README, Deprecation and non-support notice added.
## Known Issues
- Limited to FP32 precision (native implementation supports mixed precision)
- No NHWC layout support (native implementation supports multiple layouts)
- Batch size must be known during network creation
@@ -0,0 +1,63 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 1993-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "groupNormalizationPlugin.h"
namespace nvinfer1
{
namespace plugin
{
template <typename T, unsigned TPB>
__global__ void scaleShiftChannelsInplaceKernel(T* inOut, const int ld, const float* beta, const float* gamma)
{
// grid is blocks x C x B
// ld should be H*W
// blockIdx.z = batch
// blockIdx.y = channel
// blockIdx.x = block per col
const T b = beta[blockIdx.y];
const T g = gamma[blockIdx.y];
const int offset = (blockIdx.z * gridDim.y + blockIdx.y) * ld;
const int tx = blockIdx.x * TPB + threadIdx.x;
if (tx < ld)
{
inOut[offset + tx] = g * inOut[offset + tx] + b;
}
}
template <typename T>
cudaError_t scaleShiftChannelsInplace(T* inOut, const int B, const int C, const int channelVolume, const float* beta,
const float* gamma, cudaStream_t stream)
{
constexpr int TPB = 256;
const int colBlocks = (channelVolume + TPB - 1) / TPB;
const dim3 grid(colBlocks, C, B);
scaleShiftChannelsInplaceKernel<T, TPB><<<grid, TPB, 0, stream>>>(inOut, channelVolume, beta, gamma);
return cudaPeekAtLastError();
}
template cudaError_t scaleShiftChannelsInplace<float>(float* inOut, const int B, const int C, const int channelVolume, const float* beta,
const float* gamma, cudaStream_t stream);
} /* plugin */
} /* nvinfer1 */
@@ -0,0 +1,445 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 1993-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "groupNormalizationPlugin.h"
#include "common/dimsHelpers.h"
#include "common/serialize.hpp"
#include <memory>
#include <numeric>
#include <stdexcept>
#include <string_view>
using namespace nvinfer1;
using namespace nvinfer1::pluginInternal;
using nvinfer1::plugin::GroupNormalizationPlugin;
using nvinfer1::plugin::GroupNormalizationPluginCreator;
namespace
{
using namespace std::string_view_literals;
constexpr char const* kGROUP_NORM_VERSION{"1"};
constexpr char const* kGROUP_NORM_NAME{"GroupNormalizationPlugin"};
} // namespace
// std::vector<nvinfer1::PluginField> GroupNormalizationPluginCreator::mPluginAttributes;
REGISTER_TENSORRT_PLUGIN(GroupNormalizationPluginCreator);
GroupNormalizationPlugin::GroupNormalizationPlugin(float epsilon, int32_t nbGroups)
: mEpsilon(epsilon)
, mNbGroups(nbGroups)
{
PLUGIN_VALIDATE(mEpsilon > 0.0F);
PLUGIN_VALIDATE(mNbGroups > 0);
}
int32_t GroupNormalizationPlugin::initialize() noexcept
{
return STATUS_SUCCESS;
}
GroupNormalizationPlugin::GroupNormalizationPlugin(void const* data, size_t length)
{
// Deserialize in the same order as serialization
deserialize_value(&data, &length, &mEpsilon);
deserialize_value(&data, &length, &mNbGroups);
}
char const* GroupNormalizationPlugin::getPluginType() const noexcept
{
return kGROUP_NORM_NAME;
}
char const* GroupNormalizationPlugin::getPluginVersion() const noexcept
{
return kGROUP_NORM_VERSION;
}
int32_t GroupNormalizationPlugin::getNbOutputs() const noexcept
{
return 1;
}
nvinfer1::DimsExprs GroupNormalizationPlugin::getOutputDimensions(
int32_t index, nvinfer1::DimsExprs const* inputs, int32_t nbInputs, nvinfer1::IExprBuilder& exprBuilder) noexcept
{
try
{
// Input (from previous layer), scale and bias are the three inputs to the plugin.
PLUGIN_VALIDATE(nbInputs == 3);
PLUGIN_VALIDATE(index == 0);
return inputs[0];
}
catch (std::exception const& e)
{
caughtError(e);
return DimsExprs{};
}
}
void GroupNormalizationPlugin::attachToContext(
cudnnContext* cudnnContext, cublasContext* cublasContext, IGpuAllocator* gpuAllocator) noexcept
{
try
{
std::string kFULL_NAME = std::string(kGROUP_NORM_NAME) + ", version: " + std::string(kGROUP_NORM_VERSION);
mCudnnWrapper = createPluginCudnnWrapper(gpuAllocator, kFULL_NAME.c_str());
mCudnnHandle = mCudnnWrapper->getCudnnHandle();
PLUGIN_VALIDATE(mCudnnHandle);
PLUGIN_CUDNNASSERT(mCudnnWrapper->cudnnCreateTensorDescriptor(&mTensorDesc));
PLUGIN_CUDNNASSERT(mCudnnWrapper->cudnnCreateTensorDescriptor(&mBNTensorDesc));
}
catch (std::exception const& e)
{
caughtError(e);
}
}
// Detach the plugin object from its execution context.
void GroupNormalizationPlugin::detachFromContext() noexcept
{
try
{
PLUGIN_CUDNNASSERT(mCudnnWrapper->cudnnDestroyTensorDescriptor(mTensorDesc));
PLUGIN_CUDNNASSERT(mCudnnWrapper->cudnnDestroyTensorDescriptor(mBNTensorDesc));
}
catch (std::exception const& e)
{
caughtError(e);
}
}
int32_t GroupNormalizationPlugin::enqueue(nvinfer1::PluginTensorDesc const* inputDesc,
nvinfer1::PluginTensorDesc const* /* outputDesc */, void const* const* inputs, void* const* outputs,
void* /* workspace */, cudaStream_t stream) noexcept
{
try
{
PLUGIN_VALIDATE(inputDesc != nullptr && inputs != nullptr && outputs != nullptr);
PLUGIN_VALIDATE(mBnScales != nullptr && mBnScales->mPtr != nullptr);
PLUGIN_VALIDATE(mBnBias != nullptr && mBnBias->mPtr != nullptr);
PLUGIN_VALIDATE(mCudnnHandle != nullptr);
PLUGIN_VALIDATE(mTensorDesc != nullptr);
PLUGIN_VALIDATE(mBNTensorDesc != nullptr);
}
catch (std::exception const& e)
{
caughtError(e);
return STATUS_FAILURE;
}
PLUGIN_CHECK_CUDNN(mCudnnWrapper->cudnnSetStream(mCudnnHandle, stream));
// The tensor descriptors were set up in configurePlugin() to make Batch Normalization actually
// perform Group Normalization. This was done by setting the tensor descriptor shape to
// (1, batch*num_groups, channels_per_group, volume_of_spatial_dims).
// cudnnBatchNorm will normalize over the last two dimensions.
float const one = 1.F;
float const zero = 0.F;
PLUGIN_CHECK_CUDNN(mCudnnWrapper->cudnnBatchNormalizationForwardTraining(mCudnnHandle, // handle
CUDNN_BATCHNORM_SPATIAL, // BatchNormMode_t, try also non persistent
&one, //
&zero, //
mTensorDesc, // in/out descriptor
inputs[0], // input
mTensorDesc, // in/out descriptor
outputs[0], // output
mBNTensorDesc, //
mBnScales->mPtr, // 1
mBnBias->mPtr, // 0
0.0, // exponential average factor
nullptr, // resultRunningMean
nullptr, // resultRunningVar
mEpsilon, // eps
nullptr, // resultSaveMean
nullptr // resultSaveInvVar
));
// Apply an additional scale and bias on each channel.
nvinfer1::Dims inputDims = inputDesc[0].dims;
int32_t batchSize = inputDims.d[0];
int32_t nbChannels = inputDims.d[1];
auto* output = static_cast<float*>(outputs[0]);
return scaleShiftChannelsInplace(output, batchSize, nbChannels, mChannelVolume,
static_cast<float const*>(inputs[2]), static_cast<float const*>(inputs[1]), stream); // mBetaDev, mGammaDev,
}
size_t GroupNormalizationPlugin::getSerializationSize() const noexcept
{
return sizeof(mNbGroups) + sizeof(mEpsilon);
}
void GroupNormalizationPlugin::serialize(void* buffer) const noexcept
{
PLUGIN_ASSERT(buffer != nullptr);
auto* const start = reinterpret_cast<uint8_t*>(buffer);
serialize_value(&buffer, mEpsilon);
serialize_value(&buffer, mNbGroups);
PLUGIN_ASSERT(start + getSerializationSize() == reinterpret_cast<uint8_t*>(buffer));
}
bool GroupNormalizationPlugin::supportsFormatCombination(
int32_t pos, nvinfer1::PluginTensorDesc const* inOut, int32_t nbInputs, int32_t nbOutputs) noexcept
{
try
{
PLUGIN_VALIDATE(inOut != nullptr);
PLUGIN_VALIDATE(pos < nbInputs + nbOutputs);
PLUGIN_VALIDATE(pos >= 0);
return ((inOut[pos].type == nvinfer1::DataType::kFLOAT) && inOut[pos].format == nvinfer1::PluginFormat::kLINEAR
&& inOut[pos].type == inOut[0].type);
}
catch (std::exception const& e)
{
caughtError(e);
return false;
}
}
void GroupNormalizationPlugin::terminate() noexcept
{
mBnScales.reset();
mBnBias.reset();
}
void GroupNormalizationPlugin::destroy() noexcept
{
// This gets called when the network containing plugin is destroyed
delete this;
}
IPluginV2DynamicExt* GroupNormalizationPlugin::clone() const noexcept
{
try
{
auto plugin = std::make_unique<GroupNormalizationPlugin>(mEpsilon, mNbGroups);
plugin->setPluginNamespace(mNamespace.c_str());
plugin->mNbScaleBias = mNbScaleBias;
plugin->mBnScales = mBnScales;
plugin->mBnBias = mBnBias;
plugin->mChannelVolume = mChannelVolume;
return plugin.release();
}
catch (std::exception const& e)
{
caughtError(e);
}
return nullptr;
}
void GroupNormalizationPlugin::configurePlugin(nvinfer1::DynamicPluginTensorDesc const* in, int32_t nbInputs,
nvinfer1::DynamicPluginTensorDesc const* out, int32_t nbOutputs) noexcept
{
try
{
PLUGIN_VALIDATE(in != nullptr);
PLUGIN_VALIDATE(out != nullptr);
PLUGIN_VALIDATE(nbInputs == 3);
PLUGIN_VALIDATE(nbOutputs == getNbOutputs());
nvinfer1::Dims inputDims = in[0].desc.dims;
int32_t const batchSize = inputDims.d[0];
int32_t const nbChannels = inputDims.d[1];
if (batchSize <= 0 || nbChannels <= 0)
{
// Input size not yet known, nothing to configure.
return;
}
if (mTensorDesc == nullptr)
{
// Not yet attached to context.
return;
}
// Allocate scale/bias tensors needed for cudnnBatchNorm.
mNbScaleBias = batchSize * mNbGroups;
auto allocScaleBias = [this](std::shared_ptr<CudaBind<float>>& buf, float value) {
PLUGIN_VALIDATE(mNbScaleBias > 0);
if (!buf || !buf->mPtr || buf->mSize != mNbScaleBias)
{
// Allocate device memory.
buf = std::make_shared<CudaBind<float>>(mNbScaleBias);
// Initialize values.
std::vector<float> const values(mNbScaleBias, value);
PLUGIN_CUASSERT(
cudaMemcpy(buf->mPtr, values.data(), sizeof(float) * mNbScaleBias, cudaMemcpyHostToDevice));
}
};
allocScaleBias(mBnScales, 1.F);
allocScaleBias(mBnBias, 0.F);
// Calculate size of each group
int32_t groupSize = nbChannels / mNbGroups;
mChannelVolume = pluginInternal::volume(inputDims, /*start*/ 2, /*stop*/ inputDims.nbDims);
// Set tensor descriptor in a way that cudnnBatchNorm will perform Group Normalization.
PLUGIN_CUDNNASSERT(mCudnnWrapper->cudnnSetTensor4dDescriptor(mTensorDesc, // descriptor
CUDNN_TENSOR_NCHW, // tensor format
CUDNN_DATA_FLOAT, // type
1, // Batchsize
batchSize * mNbGroups, // Channels
groupSize, // Height
mChannelVolume // Width
));
PLUGIN_CUDNNASSERT(
mCudnnWrapper->cudnnDeriveBNTensorDescriptor(mBNTensorDesc, mTensorDesc, CUDNN_BATCHNORM_SPATIAL));
}
catch (std::exception const& e)
{
caughtError(e);
}
}
nvinfer1::DataType GroupNormalizationPlugin::getOutputDataType(
int32_t index, nvinfer1::DataType const* inputTypes, int32_t nbInputs) const noexcept
{
try
{
PLUGIN_VALIDATE(inputTypes != nullptr);
PLUGIN_VALIDATE(index == 0);
return inputTypes[0];
}
catch (std::exception const& e)
{
caughtError(e);
return DataType{};
}
}
size_t GroupNormalizationPlugin::getWorkspaceSize(nvinfer1::PluginTensorDesc const* inputs, int32_t nbInputs,
nvinfer1::PluginTensorDesc const* outputs, int32_t nbOutputs) const noexcept
{
return 0;
}
void GroupNormalizationPlugin::setPluginNamespace(char const* libNamespace) noexcept
{
try
{
PLUGIN_VALIDATE(libNamespace != nullptr);
mNamespace = libNamespace;
}
catch (std::exception const& e)
{
caughtError(e);
}
}
char const* GroupNormalizationPlugin::getPluginNamespace() const noexcept
{
return mNamespace.c_str();
}
GroupNormalizationPluginCreator::GroupNormalizationPluginCreator()
{
mPluginAttributes.clear();
mPluginAttributes.emplace_back(PluginField("eps", nullptr, PluginFieldType::kFLOAT32, 1));
mPluginAttributes.emplace_back(PluginField("num_groups", nullptr, PluginFieldType::kINT32, 1));
mFC.nbFields = mPluginAttributes.size();
mFC.fields = mPluginAttributes.data();
}
char const* GroupNormalizationPluginCreator::getPluginName() const noexcept
{
return kGROUP_NORM_NAME;
}
char const* GroupNormalizationPluginCreator::getPluginVersion() const noexcept
{
return kGROUP_NORM_VERSION;
}
PluginFieldCollection const* GroupNormalizationPluginCreator::getFieldNames() noexcept
{
return &mFC;
}
char const* GroupNormalizationPluginCreator::getPluginNamespace() const noexcept
{
return mNamespace.c_str();
}
void GroupNormalizationPluginCreator::setPluginNamespace(char const* libNamespace) noexcept
{
try
{
PLUGIN_VALIDATE(libNamespace != nullptr);
mNamespace = libNamespace;
}
catch (std::exception const& e)
{
caughtError(e);
}
}
IPluginV2DynamicExt* GroupNormalizationPluginCreator::createPlugin(
char const* name, PluginFieldCollection const* fc) noexcept
{
try
{
PLUGIN_VALIDATE(fc != nullptr);
// Set default values
int32_t nbGroups{1};
float epsilon{0.00001F};
for (int32_t i = 0; i < fc->nbFields; i++)
{
PLUGIN_VALIDATE(fc->fields[i].name != nullptr);
std::string_view const fieldName = fc->fields[i].name;
if (fieldName == "eps"sv)
{
epsilon = *static_cast<float const*>(fc->fields[i].data);
}
if (fieldName == "num_groups"sv)
{
nbGroups = *static_cast<int32_t const*>(fc->fields[i].data);
}
}
auto plugin = std::make_unique<GroupNormalizationPlugin>(epsilon, nbGroups);
plugin->setPluginNamespace(mNamespace.c_str());
return plugin.release();
}
catch (std::exception const& e)
{
caughtError(e);
}
return nullptr;
}
IPluginV2DynamicExt* GroupNormalizationPluginCreator::deserializePlugin(
char const* name, void const* serialData, size_t serialLength) noexcept
{
try
{
auto plugin = std::make_unique<GroupNormalizationPlugin>(serialData, serialLength);
plugin->setPluginNamespace(mNamespace.c_str());
return plugin.release();
}
catch (std::exception const& e)
{
caughtError(e);
}
return nullptr;
}
@@ -0,0 +1,150 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef TRT_GROUP_NORM_PLUGIN_H
#define TRT_GROUP_NORM_PLUGIN_H
#include "common/plugin.h"
#include <string>
#include <vector>
// One of the preferred ways of making TensorRT to be able to see
// our custom layer requires extending IPluginV2 and IPluginCreator classes.
// For requirements for overriden functions, check TensorRT API docs.
namespace nvinfer1
{
namespace plugin
{
template <typename T>
cudaError_t scaleShiftChannelsInplace(T* inOut, int32_t const B, int32_t const C, int32_t const channelVolume,
float const* beta, float const* gamma, cudaStream_t stream);
class GroupNormalizationPlugin final : public nvinfer1::IPluginV2DynamicExt
{
public:
GroupNormalizationPlugin(float epsilon, int32_t const nbGroups);
GroupNormalizationPlugin(void const* data, size_t length);
// It doesn't make sense to make GroupNormalizationPlugin without arguments, so we
// delete default constructor.
GroupNormalizationPlugin() = delete;
int32_t getNbOutputs() const noexcept override;
// DynamicExt plugins returns DimsExprs class instead of Dims
DimsExprs getOutputDimensions(int32_t index, nvinfer1::DimsExprs const* inputs, int32_t nbInputDims,
nvinfer1::IExprBuilder& exprBuilder) noexcept override;
int32_t initialize() noexcept override;
void terminate() noexcept override;
size_t getWorkspaceSize(nvinfer1::PluginTensorDesc const* inputs, int32_t nbInputs,
nvinfer1::PluginTensorDesc const* outputs, int32_t nbOutputs) const noexcept override;
int32_t enqueue(nvinfer1::PluginTensorDesc const* inputDesc, nvinfer1::PluginTensorDesc const* outputDesc,
void const* const* inputs, void* const* outputs, void* workspace, cudaStream_t stream) noexcept override;
size_t getSerializationSize() const noexcept override;
void serialize(void* buffer) const noexcept override;
bool supportsFormatCombination(
int32_t pos, nvinfer1::PluginTensorDesc const* inOut, int32_t nbInputs, int32_t nbOutputs) noexcept override;
char const* getPluginType() const noexcept override;
char const* getPluginVersion() const noexcept override;
nvinfer1::IPluginV2DynamicExt* clone() const noexcept override;
void destroy() noexcept override;
DataType getOutputDataType(
int32_t index, nvinfer1::DataType const* inputTypes, int32_t nbInputs) const noexcept override;
void attachToContext(
cudnnContext* cudnn, cublasContext* cublas, nvinfer1::IGpuAllocator* allocator) noexcept override;
void detachFromContext() noexcept override;
void setPluginNamespace(char const* pluginNamespace) noexcept override;
char const* getPluginNamespace() const noexcept override;
void configurePlugin(nvinfer1::DynamicPluginTensorDesc const* in, int32_t nbInputs,
nvinfer1::DynamicPluginTensorDesc const* out, int32_t nbOutputs) noexcept override;
private:
std::string mNamespace;
float mEpsilon;
int32_t mNbGroups;
int32_t mChannelVolume;
nvinfer1::pluginInternal::cudnnHandle_t mCudnnHandle{};
// the wrapper pointer is shared among all plugins attached to the same context.
std::shared_ptr<nvinfer1::pluginInternal::CudnnWrapper> mCudnnWrapper;
// Describes input and output.
nvinfer1::pluginInternal::cudnnTensorDescriptor_t mTensorDesc{};
nvinfer1::pluginInternal::cudnnTensorDescriptor_t mBNTensorDesc{};
// These are buffers initialized to 1 and 0 respectively
std::shared_ptr<CudaBind<float>> mBnScales{};
std::shared_ptr<CudaBind<float>> mBnBias{};
size_t mNbScaleBias{};
using IPluginV2::getOutputDimensions;
using IPluginV2::getWorkspaceSize;
using IPluginV2::enqueue;
using IPluginV2Ext::configurePlugin;
};
class GroupNormalizationPluginCreator : public IPluginCreator
{
public:
GroupNormalizationPluginCreator();
~GroupNormalizationPluginCreator() override = default;
char const* getPluginName() const noexcept override;
char const* getPluginVersion() const noexcept override;
PluginFieldCollection const* getFieldNames() noexcept override;
IPluginV2DynamicExt* createPlugin(char const* name, PluginFieldCollection const* fc) noexcept override;
IPluginV2DynamicExt* deserializePlugin(
char const* name, void const* serialData, size_t serialLength) noexcept override;
void setPluginNamespace(char const* pluginNamespace) noexcept override;
char const* getPluginNamespace() const noexcept override;
private:
PluginFieldCollection mFC;
std::vector<PluginField> mPluginAttributes;
std::string mNamespace;
};
} // namespace plugin
} // namespace nvinfer1
#endif // TRT_GROUP_NORM_PLUGIN_H