Files
nvidia--tensorrt/plugin/scatterPlugin/scatterPlugin.cpp
T
wehub-resource-sync c8a779b1bb
Docker Image CI / build-ubuntu2004 (push) Waiting to run
chore: import upstream snapshot with attribution
2026-07-13 13:36:55 +08:00

302 lines
8.3 KiB
C++

/*
* 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 "scatterPlugin.h"
#include "common/half.h"
#include <cstring>
#include <iostream>
#include <memory>
#include <sstream>
namespace nvinfer1::plugin
{
namespace
{
char const* const kSCATTERND_PLUGIN_VERSION{"1"};
char const* const kSCATTERND_PLUGIN_NAME{"ScatterND"};
} // namespace
ScatterND::ScatterND() {}
int32_t ScatterND::getNbOutputs() const noexcept
{
// Plugin layer has 1 output
return 1;
}
DimsExprs ScatterND::getOutputDimensions(
int32_t outputIndex, DimsExprs const* inputs, int32_t nbInputs, IExprBuilder& exprBuilder) noexcept
{
// output should have same dimensions as data tensor
DimsExprs ret = inputs[dataTensorIdx];
return ret;
}
int32_t ScatterND::initialize() noexcept
{
return 0;
}
void ScatterND::terminate() noexcept {}
bool ScatterND::supportsFormatCombination(
int32_t pos, PluginTensorDesc const* inOut, int32_t nbInputs, int32_t nbOutputs) noexcept
{
PLUGIN_ASSERT(pos < 4);
PLUGIN_ASSERT(nbInputs == 3);
PLUGIN_ASSERT(nbOutputs == 1);
PluginTensorDesc const& desc = inOut[pos];
bool ret = false;
switch (pos)
{
case dataTensorIdx:
case updateTensorIdx:
ret = ((desc.type == DataType::kFLOAT || desc.type == DataType::kINT32)
&& desc.format == TensorFormat::kLINEAR);
break;
case indexTensorIdx: ret = (desc.type == DataType::kINT32 && desc.format == TensorFormat::kLINEAR); break;
case 3:
ret = ((desc.type == DataType::kFLOAT || desc.type == DataType::kINT32)
&& desc.format == TensorFormat::kLINEAR);
break;
}
return ret;
}
void ScatterND::configurePlugin(
DynamicPluginTensorDesc const* in, int32_t nbInputs, DynamicPluginTensorDesc const* out, int32_t nbOutputs) noexcept
{
}
int32_t ScatterND::calculateNumSlices(Dims indexTensorDims) const noexcept
{
int32_t nSlices = 1;
for (int32_t i = 0; i < indexTensorDims.nbDims - 1; i++)
{
nSlices *= indexTensorDims.d[i];
}
return nSlices;
}
size_t ScatterND::getWorkspaceSize(
PluginTensorDesc const* inputs, int32_t nbInputs, PluginTensorDesc const* outputs, int32_t nbOutputs) const noexcept
{
int32_t nSlices = calculateNumSlices(inputs[indexTensorIdx].dims);
// transformCoeffs + transformed indices
return outputs[0].dims.MAX_DIMS * sizeof(int32_t) + nSlices * sizeof(int32_t);
}
void ScatterND::calculateTransformCoeff(
Dims const& dataTensorDims, int32_t indexRank, int32_t* transformCoeff) const noexcept
{
std::vector<int32_t> pitches;
for (int32_t i = indexRank - 1, nIndx = 1; i >= 0; i--)
{
pitches.push_back(nIndx);
nIndx *= dataTensorDims.d[i];
}
std::reverse(pitches.begin(), pitches.end()); // last dimension pitch is always one (assuming linear mem)
std::copy(pitches.begin(), pitches.end(), transformCoeff);
}
int32_t ScatterND::calculateCopySize(Dims const& dataDims) const noexcept
{
int32_t copySize = 1;
for (int32_t i = 0; i < dataDims.nbDims; i++)
{
copySize *= dataDims.d[i];
}
copySize *= sizeof(float);
return copySize;
}
int32_t ScatterND::enqueue(PluginTensorDesc const* inputDesc, PluginTensorDesc const* outputDesc,
void const* const* inputs, void* const* outputs, void* workspace, cudaStream_t stream) noexcept
{
PLUGIN_VALIDATE(inputDesc != nullptr && outputDesc != nullptr && inputs != nullptr && outputs != nullptr
&& workspace != nullptr);
int32_t transformCoeff[nvinfer1::Dims::MAX_DIMS];
std::memset(transformCoeff, 0, sizeof(int32_t) * outputDesc[0].dims.MAX_DIMS);
Dims IndexDims = inputDesc[indexTensorIdx].dims;
Dims dataDims = inputDesc[dataTensorIdx].dims;
int32_t indexRank = IndexDims.d[IndexDims.nbDims - 1];
PLUGIN_ASSERT(indexRank <= dataDims.nbDims);
int32_t nSlices = calculateNumSlices(IndexDims);
int32_t rowSize = 1;
int32_t copySize = calculateCopySize(dataDims);
int32_t elementSizeInBytes = 1;
switch (inputDesc->type)
{
case DataType::kFLOAT:
case DataType::kINT32: elementSizeInBytes = 4; break;
case DataType::kHALF: elementSizeInBytes = 2; break;
case DataType::kINT8:
case DataType::kUINT8:
case DataType::kBOOL: elementSizeInBytes = 1; break;
case DataType::kFP8:
case DataType::kBF16:
case DataType::kINT64:
case DataType::kINT4:
case DataType::kFP4:
case DataType::kE8M0: PLUGIN_FAIL("Unsupported data type");
}
for (int32_t i = indexRank; i < dataDims.nbDims; i++)
{
rowSize *= dataDims.d[i];
}
calculateTransformCoeff(dataDims, indexRank, transformCoeff);
scatterNDInference(stream, transformCoeff, dataDims.nbDims, indexRank, nSlices, rowSize, copySize,
elementSizeInBytes, inputs[indexTensorIdx], inputs[updateTensorIdx], inputs[dataTensorIdx], outputs[0],
workspace);
return 0;
}
size_t ScatterND::getSerializationSize() const noexcept
{
return 0;
}
void ScatterND::serialize(void* buffer) const noexcept
{
return;
}
// Set plugin namespace
void ScatterND::setPluginNamespace(char const* pluginNamespace) noexcept
{
mPluginNamespace = pluginNamespace;
}
char const* ScatterND::getPluginNamespace() const noexcept
{
return mPluginNamespace.c_str();
}
// Return the DataType of the plugin output at the requested index
DataType ScatterND::getOutputDataType(
int32_t index, nvinfer1::DataType const* inputTypes, int32_t nbInputs) const noexcept
{
PLUGIN_ASSERT(index == 0);
return inputTypes[dataTensorIdx];
}
// Attach the plugin object to an execution context and grant the plugin the access to some context resource.
void ScatterND::attachToContext(cudnnContext* cudnn, cublasContext* cublas, IGpuAllocator* gpuAllocator) noexcept
{
return;
}
// Detach the plugin object from its execution context.
void ScatterND::detachFromContext() noexcept {}
char const* ScatterND::getPluginType() const noexcept
{
return kSCATTERND_PLUGIN_NAME;
}
char const* ScatterND::getPluginVersion() const noexcept
{
return kSCATTERND_PLUGIN_VERSION;
}
void ScatterND::destroy() noexcept
{
delete this;
}
// Clone the plugin
IPluginV2DynamicExt* ScatterND::clone() const noexcept
{
try
{
// Create a new instance
auto plugin = std::make_unique<ScatterND>();
plugin->setPluginNamespace(mPluginNamespace.c_str());
return plugin.release();
}
catch (std::exception const& e)
{
caughtError(e);
}
return nullptr;
}
ScatterNDPluginCreator::ScatterNDPluginCreator()
{
mFC.nbFields = 0;
}
char const* ScatterNDPluginCreator::getPluginName() const noexcept
{
return kSCATTERND_PLUGIN_NAME;
}
char const* ScatterNDPluginCreator::getPluginVersion() const noexcept
{
return kSCATTERND_PLUGIN_VERSION;
}
PluginFieldCollection const* ScatterNDPluginCreator::getFieldNames() noexcept
{
return &mFC;
}
IPluginV2Ext* ScatterNDPluginCreator::createPlugin(char const* name, PluginFieldCollection const* fc) noexcept
{
try
{
auto obj = std::make_unique<ScatterND>();
obj->setPluginNamespace(mNamespace.c_str());
return obj.release();
}
catch (std::exception const& e)
{
caughtError(e);
}
return nullptr;
}
IPluginV2Ext* ScatterNDPluginCreator::deserializePlugin(
char const* name, void const* serialData, size_t serialLength) noexcept
{
try
{
// This object will be deleted when the network is destroyed, which will
// call Normalize::destroy()
auto obj = std::make_unique<ScatterND>();
obj->setPluginNamespace(mNamespace.c_str());
return obj.release();
}
catch (std::exception const& e)
{
caughtError(e);
}
return nullptr;
}
} // namespace nvinfer1::plugin