chore: import upstream snapshot with attribution
Docker Image CI / build-ubuntu2004 (push) Has been cancelled
Docker Image CI / build-ubuntu2004 (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
#
|
||||
# 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(
|
||||
atomics.cuh
|
||||
reducer.cuh
|
||||
scatterElementsCommon.h
|
||||
scatterElementsPlugin.cpp
|
||||
scatterElementsPlugin.h
|
||||
scatterElementsPluginKernel.cu
|
||||
scatterElementsPluginKernel.h
|
||||
scatterElementsPluginLegacy.cpp
|
||||
scatterElementsPluginLegacy.h
|
||||
TensorInfo.cuh
|
||||
)
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
# scatterElements
|
||||
|
||||
**Table Of Contents**
|
||||
- [Description](#description)
|
||||
* [Structure](#structure)
|
||||
- [Parameters](#parameters)
|
||||
- [Additional resources](#additional-resources)
|
||||
- [License](#license)
|
||||
- [Changelog](#changelog)
|
||||
- [Known issues](#known-issues)
|
||||
|
||||
## Description
|
||||
|
||||
The scatterElements plugin implements the scatter operation described in (https://github.com/rusty1s/pytorch_scatter), in compliance with the [ONNX specification for ScatterElements](https://github.com/onnx/onnx/blob/main/docs/Operators.md#ScatterElements)
|
||||
|
||||
Note: ScatterElements with reduce="none" is implemented in TRT core, not this plugin.
|
||||
|
||||
### Structure
|
||||
|
||||
This plugin has the 2 versions. The latest is plugin creator class `ScatterElementsPluginV3Creator` and the plugin class `ScatterElementsPluginV3` which extends `IPluginV3`. (name: `ScatterElements`, version: 2)
|
||||
The legacy plugin that will be deprecated, is plugin creator class `ScatterElementsPluginV2Creator` and the plugin class `ScatterElementsPluginV2`, which extends `IPluginV2DynamicExt` (name: `ScatterElements`, version: 1).
|
||||
|
||||
The `ScatterElements` plugin consumes the following inputs:
|
||||
|
||||
1. `data` - T: Tensor of rank r >= 1.
|
||||
2. `indices` - Tind: Tensor of int64 indices, of r >= 1 (same rank as input). All index values are expected to be within bounds [-s, s-1] along axis of size s. It is an error if any of the index values are out of bounds.
|
||||
3. `updates` - T: Tensor of rank r >=1 (same rank and shape as indices)
|
||||
|
||||
The `ScatterElements` plugin produces the following output:
|
||||
|
||||
1. `output` - T: Tensor, same shape as `data`.
|
||||
|
||||
## Parameters
|
||||
|
||||
The `ScatterElements` plugin has the following parameters:
|
||||
|
||||
| Type | Parameter | Description
|
||||
|------------------|---------------------------------|--------------------------------------------------------
|
||||
|`int` |`axis` | Which axis to scatter on. Default is 0. Negative value means counting dimensions from the back. Accepted range is [-r, r-1] where r = rank(data).
|
||||
|`char` |`reduction` | Type of reduction to apply: add, mul, max, min. ‘add’: reduction using the addition operation. ‘mul’: reduction using the multiplication operation.‘max’: reduction using the maximum operation.‘min’: reduction using the minimum operation.
|
||||
|
||||
|
||||
The following resources provide a deeper understanding of the `scatterElements` plugin:
|
||||
|
||||
- [pytorch_scatter: original implementation and docs](https://github.com/rusty1s/pytorch_scatter)
|
||||
- [ONNX specification for ScatterElements](https://github.com/onnx/onnx/blob/main/docs/Operators.md#ScatterElements)
|
||||
|
||||
## 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)
|
||||
documentation.
|
||||
|
||||
## Changelog
|
||||
|
||||
- July 2024: Version 2 of the plugin migrated to `IPluginV3` interface design. The legacy plugin (version 1) using `IPluginV2DynamicExt` interface is deprecated.
|
||||
- Oct 2023: This is the first release of this `README.md` file.
|
||||
|
||||
## Known issues
|
||||
|
||||
- Types T=BFLOAT16 and T=INT8 are currently not supported.
|
||||
- ONNX spec allows Tind=int32 : only INT64 is supported by this plugin
|
||||
@@ -0,0 +1,153 @@
|
||||
#
|
||||
# SPDX-FileCopyrightText: Copyright (c) 2024-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.
|
||||
#
|
||||
|
||||
---
|
||||
name: ScatterElements
|
||||
interface: "IPluginV3"
|
||||
versions:
|
||||
"2":
|
||||
inputs:
|
||||
- data
|
||||
- indices
|
||||
- updates
|
||||
supported_input_types:
|
||||
- combination1:
|
||||
data: float32
|
||||
indices: int64
|
||||
updates: float32
|
||||
- combination2:
|
||||
data: int32
|
||||
indices: int64
|
||||
updates: int32
|
||||
- combination3:
|
||||
data: int64
|
||||
indices: int64
|
||||
updates: int64
|
||||
- combination4:
|
||||
data: float16
|
||||
indices: int64
|
||||
updates: float16
|
||||
- combination5:
|
||||
data: bfloat16
|
||||
indices: int64
|
||||
updates: bfloat16
|
||||
configs:
|
||||
config1:
|
||||
input_types:
|
||||
data: float32
|
||||
indices: int64
|
||||
updates: float32
|
||||
attribute_options:
|
||||
axis:
|
||||
- -1
|
||||
- 0
|
||||
- 1
|
||||
reduction:
|
||||
- "add"
|
||||
- "mul"
|
||||
- "min"
|
||||
- "max"
|
||||
config2:
|
||||
input_types:
|
||||
data: float16
|
||||
indices: int64
|
||||
updates: float16
|
||||
attribute_options:
|
||||
axis:
|
||||
- -1
|
||||
- 0
|
||||
- 1
|
||||
reduction:
|
||||
- "add"
|
||||
- "mul"
|
||||
- "min"
|
||||
- "max"
|
||||
config3:
|
||||
input_types:
|
||||
data: int32
|
||||
indices: int64
|
||||
updates: int32
|
||||
attribute_options:
|
||||
axis:
|
||||
- -1
|
||||
- 0
|
||||
- 1
|
||||
reduction:
|
||||
- "add"
|
||||
- "mul"
|
||||
- "min"
|
||||
- "max"
|
||||
config4:
|
||||
input_types:
|
||||
data: int64
|
||||
indices: int64
|
||||
updates: int64
|
||||
attribute_options:
|
||||
axis:
|
||||
- -1
|
||||
- 0
|
||||
- 1
|
||||
reduction:
|
||||
- "add"
|
||||
- "mul"
|
||||
- "min"
|
||||
- "max"
|
||||
config5:
|
||||
input_types:
|
||||
data: bfloat16
|
||||
indices: int64
|
||||
updates: bfloat16
|
||||
attribute_options:
|
||||
axis:
|
||||
- -1
|
||||
- 0
|
||||
- 1
|
||||
reduction:
|
||||
- "add"
|
||||
- "mul"
|
||||
- "min"
|
||||
- "max"
|
||||
outputs:
|
||||
- output
|
||||
attributes:
|
||||
- axis
|
||||
- reduction
|
||||
attribute_types:
|
||||
axis: int32
|
||||
reduction: char
|
||||
attribute_length:
|
||||
axis: 1
|
||||
reduction: -1
|
||||
attribute_options:
|
||||
axis:
|
||||
min: "=ninf"
|
||||
max: "=pinf"
|
||||
reduction:
|
||||
- "add"
|
||||
- "mul"
|
||||
- "min"
|
||||
- "max"
|
||||
attributes_required:
|
||||
- reduction
|
||||
golden_io_path: "plugin/ScatterElementsPlugin_PluginGoldenIO.json"
|
||||
abs_tol: 1e-2
|
||||
rel_tol: 1e-2
|
||||
bf16_rtol: 5e-2
|
||||
bf16_atol: 5e-2
|
||||
fp16_rtol: 5e-2
|
||||
fp16_atol: 5e-2
|
||||
...
|
||||
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* ************************************************************************
|
||||
* Modified from pytorch_scatter
|
||||
* Copyright (c) 2020 Matthias Fey <matthias.fey@tu-dortmund.de>
|
||||
* See https://github.com/rusty1s/pytorch_scatter/blob/master/LICENSE for details
|
||||
* ************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef TRT_SCATTER_ELEMENTS_TENSOR_INFO_H
|
||||
#define TRT_SCATTER_ELEMENTS_TENSOR_INFO_H
|
||||
|
||||
#include "common/plugin.h"
|
||||
|
||||
namespace nvinfer1
|
||||
{
|
||||
namespace plugin
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
static constexpr int32_t kMAX_TENSORINFO_DIMS = 25;
|
||||
|
||||
// CUDA kernel argument that defines tensor layout
|
||||
template <typename TScalar, typename TIndex>
|
||||
struct TensorInfo
|
||||
{
|
||||
TensorInfo();
|
||||
TensorInfo(const TScalar* p, int32_t dim, TIndex sz[kMAX_TENSORINFO_DIMS], TIndex st[kMAX_TENSORINFO_DIMS]);
|
||||
|
||||
// Contiguous tensors of more than one dimension are collapsed down
|
||||
// to one tensor
|
||||
__host__ __device__ inline bool isContiguous() const
|
||||
{
|
||||
return (dims == 1 && strides[0] == 1);
|
||||
}
|
||||
|
||||
const TScalar* data;
|
||||
TIndex sizes[kMAX_TENSORINFO_DIMS];
|
||||
TIndex strides[kMAX_TENSORINFO_DIMS];
|
||||
int32_t dims;
|
||||
};
|
||||
|
||||
// Creates TensorInfo object from PluginTensorDesc and data address
|
||||
template <typename TScalar, typename TIndex>
|
||||
TensorInfo<TScalar, TIndex> getTensorInfo(const void* d, PluginTensorDesc const& t)
|
||||
{
|
||||
TIndex sz[kMAX_TENSORINFO_DIMS];
|
||||
TIndex st[kMAX_TENSORINFO_DIMS];
|
||||
|
||||
int32_t dims = t.dims.nbDims;
|
||||
for (int32_t i = 0; i < dims; ++i)
|
||||
{
|
||||
sz[i] = t.dims.d[i];
|
||||
}
|
||||
for (int32_t i = dims; i < kMAX_TENSORINFO_DIMS; ++i)
|
||||
{
|
||||
sz[i] = static_cast<TIndex>(0);
|
||||
}
|
||||
// calculate strides
|
||||
st[dims - 1] = 1;
|
||||
for (int32_t i = dims - 2; i >= 0; --i)
|
||||
{
|
||||
st[i] = st[i + 1] * sz[i + 1];
|
||||
}
|
||||
return TensorInfo<TScalar, TIndex>(reinterpret_cast<const TScalar*>(d), dims, sz, st);
|
||||
}
|
||||
|
||||
template <typename TScalar, typename TIndex>
|
||||
TensorInfo<TScalar, TIndex>::TensorInfo()
|
||||
{
|
||||
data = nullptr;
|
||||
dims = 0;
|
||||
}
|
||||
|
||||
template <typename TScalar, typename TIndex>
|
||||
TensorInfo<TScalar, TIndex>::TensorInfo(
|
||||
const TScalar* p, int32_t dim, TIndex sz[kMAX_TENSORINFO_DIMS], TIndex st[kMAX_TENSORINFO_DIMS])
|
||||
{
|
||||
data = p;
|
||||
dims = dim;
|
||||
for (int32_t i = 0; i < dim; ++i)
|
||||
{
|
||||
sizes[i] = sz[i];
|
||||
strides[i] = st[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Translate a linear index for the apply to a T* offset;
|
||||
// specialized on `Dims` to reduce nvcc compilation time
|
||||
template <typename TScalar, typename TIndex, int tDims>
|
||||
struct IndexToOffset
|
||||
{
|
||||
static __host__ __device__ TIndex get(TIndex linearId, const TensorInfo<TScalar, TIndex>& info)
|
||||
{
|
||||
|
||||
TIndex offset = 0;
|
||||
|
||||
// Uses static dims
|
||||
for (int32_t i = tDims - 1; i > 0; --i)
|
||||
{
|
||||
TIndex curDimIndex = linearId % info.sizes[i];
|
||||
TIndex curDimOffset = curDimIndex * info.strides[i];
|
||||
offset += curDimOffset;
|
||||
linearId /= info.sizes[i];
|
||||
}
|
||||
|
||||
return offset + linearId * info.strides[0];
|
||||
}
|
||||
};
|
||||
|
||||
// Uses dynamic (runtime) instead of static (compiletime) dims
|
||||
template <typename TScalar, typename TIndex>
|
||||
struct IndexToOffset<TScalar, TIndex, -1>
|
||||
{
|
||||
static inline __host__ __device__ TIndex get(TIndex linearId, const TensorInfo<TScalar, TIndex>& info)
|
||||
{
|
||||
|
||||
TIndex offset = 0;
|
||||
|
||||
for (int32_t i = info.dims - 1; i > 0; --i)
|
||||
{
|
||||
TIndex curDimIndex = linearId % info.sizes[i];
|
||||
TIndex curDimOffset = curDimIndex * info.strides[i];
|
||||
offset += curDimOffset;
|
||||
linearId /= info.sizes[i];
|
||||
}
|
||||
|
||||
return offset + linearId * info.strides[0];
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace plugin
|
||||
} // namespace nvinfer1
|
||||
|
||||
#endif // TRT_SCATTER_ELEMENTS_TENSOR_INFO_H
|
||||
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* ************************************************************************
|
||||
* Modified from pytorch_scatter
|
||||
* Copyright (c) 2020 Matthias Fey <matthias.fey@tu-dortmund.de>
|
||||
* See https://github.com/rusty1s/pytorch_scatter/blob/master/LICENSE for details
|
||||
* ************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef TRT_SCATTER_ELEMENTS_ATOMICS_H
|
||||
#define TRT_SCATTER_ELEMENTS_ATOMICS_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <cuda_fp16.h>
|
||||
#include <cuda_bf16.h>
|
||||
#include <utility>
|
||||
|
||||
#define ATOMIC(NAME) \
|
||||
template <typename TScalar, size_t tSize> \
|
||||
struct Atomic##NAME##IntegerImpl; \
|
||||
\
|
||||
template <typename TScalar> \
|
||||
struct Atomic##NAME##IntegerImpl<TScalar, 4> \
|
||||
{ \
|
||||
inline __device__ void operator()(TScalar* address, TScalar val) \
|
||||
{ \
|
||||
std::uint32_t* addressAsUI = reinterpret_cast<std::uint32_t*>(address); \
|
||||
std::uint32_t old = *addressAsUI; \
|
||||
std::uint32_t assumed; \
|
||||
\
|
||||
do \
|
||||
{ \
|
||||
assumed = old; \
|
||||
old = atomicCAS(addressAsUI, assumed, OP(val, static_cast<TScalar>(old))); \
|
||||
} while (assumed != old); \
|
||||
} \
|
||||
}; \
|
||||
\
|
||||
template <typename TScalar> \
|
||||
struct Atomic##NAME##IntegerImpl<TScalar, 8> \
|
||||
{ \
|
||||
inline __device__ void operator()(TScalar* address, TScalar val) \
|
||||
{ \
|
||||
unsigned long long* addressAsULL = reinterpret_cast<unsigned long long*>(address); \
|
||||
unsigned long long old = *addressAsULL; \
|
||||
unsigned long long assumed; \
|
||||
\
|
||||
do \
|
||||
{ \
|
||||
assumed = old; \
|
||||
old = atomicCAS(addressAsULL, assumed, OP(val, static_cast<TScalar>(old))); \
|
||||
} while (assumed != old); \
|
||||
} \
|
||||
}; \
|
||||
\
|
||||
template <typename TScalar, size_t tSize> \
|
||||
struct Atomic##NAME##DecimalImpl; \
|
||||
\
|
||||
template <typename TScalar> \
|
||||
struct Atomic##NAME##DecimalImpl<TScalar, 4> \
|
||||
{ \
|
||||
inline __device__ void operator()(TScalar* address, TScalar val) \
|
||||
{ \
|
||||
std::int32_t* addressAsI = reinterpret_cast<std::int32_t*>(address); \
|
||||
std::int32_t old = *addressAsI; \
|
||||
std::int32_t assumed; \
|
||||
\
|
||||
do \
|
||||
{ \
|
||||
assumed = old; \
|
||||
old = atomicCAS(addressAsI, assumed, __float_as_int(OP(val, __int_as_float(assumed)))); \
|
||||
} while (assumed != old); \
|
||||
} \
|
||||
}; \
|
||||
template <typename TScalar> \
|
||||
struct Atomic##NAME##DecimalImpl<TScalar, 2> \
|
||||
{ \
|
||||
inline __device__ void operator()(TScalar* address, TScalar val) \
|
||||
{ \
|
||||
uint32_t* addressAsUI = reinterpret_cast<std::uint32_t*>((char*) address - ((std::size_t) address & 2)); \
|
||||
std::uint32_t old = *addressAsUI; \
|
||||
std::uint32_t assumed; \
|
||||
\
|
||||
do \
|
||||
{ \
|
||||
assumed = old; \
|
||||
std::uint16_t hsum_old; \
|
||||
hsum_old = reinterpret_cast<size_t>(address) & 2 ? (old >> 16) : (old & 0xffff); \
|
||||
auto hsum = OP(*reinterpret_cast<TScalar*>(&hsum_old), val); \
|
||||
old = (size_t) address & 2 ? (old & 0xffff) | ((*reinterpret_cast<std::uint16_t*>(&hsum)) << 16) \
|
||||
: (old & 0xffff0000) | *reinterpret_cast<std::uint16_t*>(&hsum); \
|
||||
old = atomicCAS(addressAsUI, assumed, old); \
|
||||
} while (assumed != old); \
|
||||
} \
|
||||
};
|
||||
|
||||
#define OP(X, Y) ((Y) + (X))
|
||||
ATOMIC(Add)
|
||||
#undef OP
|
||||
|
||||
static inline __device__ void atomAdd(float* address, float val)
|
||||
{
|
||||
atomicAdd(address, val);
|
||||
}
|
||||
static inline __device__ void atomAdd(__half* address, __half val)
|
||||
{
|
||||
#if defined(USE_ROCM) || (defined(__CUDA_ARCH__) && (__CUDA_ARCH__ < 700 || CUDA_VERSION < 10000))
|
||||
AtomicAddDecimalImpl<__half, sizeof(__half)>()(address, val);
|
||||
#else
|
||||
atomicAdd(address, val);
|
||||
#endif
|
||||
}
|
||||
static inline __device__ void atomAdd(__nv_bfloat16* address, __nv_bfloat16 val)
|
||||
{
|
||||
#if (defined(__CUDACC__) && (!defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 800))) || defined(_NVHPC_CUDA)
|
||||
atomicAdd(address, val);
|
||||
#else
|
||||
AtomicAddDecimalImpl<__nv_bfloat16, sizeof(__nv_bfloat16)>()(address, val);
|
||||
#endif
|
||||
}
|
||||
static inline __device__ void atomAdd(std::int32_t* address, std::int32_t val)
|
||||
{
|
||||
atomicAdd(address, val);
|
||||
}
|
||||
static inline __device__ void atomAdd(std::int64_t* address, std::int64_t val)
|
||||
{
|
||||
AtomicAddIntegerImpl<std::int64_t, sizeof(std::int64_t)>()(address, val);
|
||||
}
|
||||
|
||||
#define OP(X, Y) ((Y) * (X))
|
||||
ATOMIC(Mul)
|
||||
#undef OP
|
||||
static inline __device__ void atomMul(std::int32_t* address, std::int32_t val)
|
||||
{
|
||||
AtomicMulIntegerImpl<std::int32_t, sizeof(std::int32_t)>()(address, val);
|
||||
}
|
||||
static inline __device__ void atomMul(std::int64_t* address, std::int64_t val)
|
||||
{
|
||||
AtomicMulIntegerImpl<std::int64_t, sizeof(std::int64_t)>()(address, val);
|
||||
}
|
||||
static inline __device__ void atomMul(float* address, float val)
|
||||
{
|
||||
AtomicMulDecimalImpl<float, sizeof(float)>()(address, val);
|
||||
}
|
||||
static inline __device__ void atomMul(__half* address, __half val)
|
||||
{
|
||||
AtomicMulDecimalImpl<__half, sizeof(__half)>()(address, val);
|
||||
}
|
||||
static inline __device__ void atomMul(__nv_bfloat16* address, __nv_bfloat16 val)
|
||||
{
|
||||
AtomicMulDecimalImpl<__nv_bfloat16, sizeof(__nv_bfloat16)>()(address, val);
|
||||
}
|
||||
|
||||
|
||||
#define OP(X, Y) ((X) < (Y)) ? (Y) : (X)
|
||||
ATOMIC(Max)
|
||||
#undef OP
|
||||
static inline __device__ void atomMax(std::int32_t* address, std::int32_t val)
|
||||
{
|
||||
atomicMax(address, val);
|
||||
}
|
||||
static inline __device__ void atomMax(float* address, float val)
|
||||
{
|
||||
AtomicMaxDecimalImpl<float, sizeof(float)>()(address, val);
|
||||
}
|
||||
static inline __device__ void atomMax(std::int64_t* address, std::int64_t val)
|
||||
{
|
||||
AtomicMaxIntegerImpl<std::int64_t, sizeof(std::int64_t)>()(address, val);
|
||||
}
|
||||
static inline __device__ void atomMax(__half* address, __half val)
|
||||
{
|
||||
AtomicMaxDecimalImpl<__half, sizeof(__half)>()(address, val);
|
||||
}
|
||||
static inline __device__ void atomMax(__nv_bfloat16* address, __nv_bfloat16 val)
|
||||
{
|
||||
AtomicMaxDecimalImpl<__nv_bfloat16, sizeof(__nv_bfloat16)>()(address, val);
|
||||
}
|
||||
|
||||
#define OP(X, Y) ((X) > (Y)) ? (Y) : (X)
|
||||
ATOMIC(Min)
|
||||
#undef OP
|
||||
static inline __device__ void atomMin(std::int32_t* address, std::int32_t val)
|
||||
{
|
||||
atomicMin(address, val);
|
||||
}
|
||||
static inline __device__ void atomMin(std::int64_t* address, std::int64_t val)
|
||||
{
|
||||
AtomicMinIntegerImpl<std::int64_t, sizeof(std::int64_t)>()(address, val);
|
||||
}
|
||||
static inline __device__ void atomMin(float* address, float val)
|
||||
{
|
||||
AtomicMinDecimalImpl<float, sizeof(float)>()(address, val);
|
||||
}
|
||||
static inline __device__ void atomMin(__half* address, __half val)
|
||||
{
|
||||
AtomicMinDecimalImpl<__half, sizeof(__half)>()(address, val);
|
||||
}
|
||||
static inline __device__ void atomMin(__nv_bfloat16* address, __nv_bfloat16 val)
|
||||
{
|
||||
AtomicMinDecimalImpl<__nv_bfloat16, sizeof(__nv_bfloat16)>()(address, val);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* ************************************************************************
|
||||
* Modified from pytorch_scatter
|
||||
* Copyright (c) 2020 Matthias Fey <matthias.fey@tu-dortmund.de>
|
||||
* See https://github.com/rusty1s/pytorch_scatter/blob/master/LICENSE for details
|
||||
* ************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef TRT_SCATTER_ELEMENTS_REDUCER_H
|
||||
#define TRT_SCATTER_ELEMENTS_REDUCER_H
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include "atomics.cuh"
|
||||
#include "scatterElementsPluginKernel.h"
|
||||
|
||||
namespace nvinfer1
|
||||
{
|
||||
namespace plugin
|
||||
{
|
||||
|
||||
#define AT_DISPATCH_REDUCTION_TYPES(reduce, ...) \
|
||||
[&] { \
|
||||
switch (reduce) \
|
||||
{ \
|
||||
case ReductionType::kSUM: \
|
||||
{ \
|
||||
static constexpr ReductionType REDUCE = ReductionType::kSUM; \
|
||||
return __VA_ARGS__(); \
|
||||
} \
|
||||
case ReductionType::kMEAN: \
|
||||
{ \
|
||||
static constexpr ReductionType REDUCE = ReductionType::kMEAN; \
|
||||
return __VA_ARGS__(); \
|
||||
} \
|
||||
case ReductionType::kMUL: \
|
||||
{ \
|
||||
static constexpr ReductionType REDUCE = ReductionType::kMUL; \
|
||||
return __VA_ARGS__(); \
|
||||
} \
|
||||
case ReductionType::kMIN: \
|
||||
{ \
|
||||
static constexpr ReductionType REDUCE = ReductionType::kMIN; \
|
||||
return __VA_ARGS__(); \
|
||||
} \
|
||||
case ReductionType::kMAX: \
|
||||
{ \
|
||||
static constexpr ReductionType REDUCE = ReductionType::kMAX; \
|
||||
return __VA_ARGS__(); \
|
||||
} \
|
||||
} \
|
||||
}()
|
||||
|
||||
template <typename TScalar, ReductionType tReduce>
|
||||
struct Reducer
|
||||
{
|
||||
static inline __host__ __device__ TScalar init()
|
||||
{
|
||||
if (tReduce == ReductionType::kMUL)
|
||||
{
|
||||
return TScalar(1);
|
||||
}
|
||||
else if (tReduce == ReductionType::kMIN)
|
||||
{
|
||||
return std::numeric_limits<TScalar>::max();
|
||||
}
|
||||
else if (tReduce == ReductionType::kMAX)
|
||||
{
|
||||
return std::numeric_limits<TScalar>::lowest();
|
||||
}
|
||||
else
|
||||
{
|
||||
return TScalar(0);
|
||||
}
|
||||
}
|
||||
|
||||
static inline __host__ __device__ void update(TScalar* val, TScalar newVal)
|
||||
{
|
||||
if (tReduce == ReductionType::kSUM || tReduce == ReductionType::kMEAN)
|
||||
{
|
||||
*val = *val + newVal;
|
||||
}
|
||||
else if (tReduce == ReductionType::kMUL)
|
||||
{
|
||||
*val = *val * newVal;
|
||||
}
|
||||
else if ((tReduce == ReductionType::kMIN && newVal < *val) || (tReduce == ReductionType::kMAX && newVal > *val))
|
||||
{
|
||||
*val = newVal;
|
||||
}
|
||||
}
|
||||
|
||||
static inline __host__ __device__ void update(TScalar* val, TScalar newVal, int64_t* arg, int64_t newArg)
|
||||
{
|
||||
if (tReduce == ReductionType::kSUM || tReduce == ReductionType::kMEAN)
|
||||
{
|
||||
*val = *val + newVal;
|
||||
}
|
||||
else if (tReduce == ReductionType::kMUL)
|
||||
{
|
||||
*val = *val * newVal;
|
||||
}
|
||||
else if ((tReduce == ReductionType::kMIN && newVal < *val) || (tReduce == ReductionType::kMAX && newVal > *val))
|
||||
{
|
||||
*val = newVal;
|
||||
*arg = newArg;
|
||||
}
|
||||
}
|
||||
|
||||
static inline __host__ __device__ void write(
|
||||
TScalar* address, TScalar val, int64_t* argAddress, int64_t arg, int count)
|
||||
{
|
||||
if (tReduce == ReductionType::kSUM || tReduce == ReductionType::kMUL)
|
||||
{
|
||||
*address = val;
|
||||
}
|
||||
else if (tReduce == ReductionType::kMEAN)
|
||||
{
|
||||
*address = val / (TScalar) (count > 0 ? count : 1);
|
||||
}
|
||||
else if (tReduce == ReductionType::kMIN || tReduce == ReductionType::kMAX)
|
||||
{
|
||||
if (count > 0)
|
||||
{
|
||||
*address = val;
|
||||
*argAddress = arg;
|
||||
}
|
||||
else
|
||||
{
|
||||
*address = (TScalar) 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline __device__ void atomic_write(TScalar* address, TScalar val)
|
||||
{
|
||||
if (tReduce == ReductionType::kSUM || tReduce == ReductionType::kMEAN)
|
||||
{
|
||||
atomAdd(address, val);
|
||||
}
|
||||
else if (tReduce == ReductionType::kMUL)
|
||||
{
|
||||
atomMul(address, val);
|
||||
}
|
||||
else if (tReduce == ReductionType::kMIN)
|
||||
{
|
||||
atomMin(address, val);
|
||||
}
|
||||
else if (tReduce == ReductionType::kMAX)
|
||||
{
|
||||
atomMax(address, val);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace plugin
|
||||
} // namespace nvinfer1
|
||||
|
||||
#endif // TRT_SCATTER_ELEMENTS_REDUCER_H
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 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.
|
||||
*/
|
||||
|
||||
#ifndef SCATTER_ELEMENTS_COMMON_H
|
||||
#define SCATTER_ELEMENTS_COMMON_H
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "common/plugin.h"
|
||||
|
||||
enum class ReductionType : int32_t
|
||||
{
|
||||
kSUM,
|
||||
kMUL,
|
||||
kMEAN,
|
||||
kMIN,
|
||||
kMAX
|
||||
};
|
||||
|
||||
extern std::unordered_map<std::string, ReductionType> const kREDUCE_STR_TO_ENUM;
|
||||
extern std::unordered_map<ReductionType, std::string> const kREDUCE_ENUM_TO_STR;
|
||||
|
||||
#endif // SCATTER_ELEMENTS_COMMON_H
|
||||
@@ -0,0 +1,364 @@
|
||||
/*
|
||||
* 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 <algorithm>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string_view>
|
||||
|
||||
#include "common/serialize.hpp"
|
||||
#include "scatterElementsPlugin.h"
|
||||
#include "scatterElementsPluginKernel.h"
|
||||
|
||||
namespace nvinfer1::plugin
|
||||
{
|
||||
|
||||
std::unordered_map<std::string, ReductionType> const kREDUCE_STR_TO_ENUM{
|
||||
{"add", ReductionType::kSUM},
|
||||
{"mean", ReductionType::kMEAN},
|
||||
{"mul", ReductionType::kMUL},
|
||||
{"min", ReductionType::kMIN},
|
||||
{"max", ReductionType::kMAX},
|
||||
};
|
||||
std::unordered_map<ReductionType, std::string> const kREDUCE_ENUM_TO_STR{
|
||||
{ReductionType::kSUM, "add"},
|
||||
{ReductionType::kMEAN, "mean"},
|
||||
{ReductionType::kMUL, "mul"},
|
||||
{ReductionType::kMIN, "min"},
|
||||
{ReductionType::kMAX, "max"},
|
||||
};
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr char const* kSCATTER_PLUGIN_VERSION{"2"};
|
||||
constexpr char const* kSCATTER_PLUGIN_NAME{"ScatterElements"};
|
||||
} // namespace
|
||||
|
||||
ScatterElementsPluginV3::ScatterElementsPluginV3(ReductionType reduction, int32_t dim)
|
||||
: mReduction(reduction)
|
||||
, mAxis(dim)
|
||||
{
|
||||
}
|
||||
|
||||
ScatterElementsPluginV3::ScatterElementsPluginV3(std::string const& reduction, int32_t dim)
|
||||
: mReduction(kREDUCE_STR_TO_ENUM.at(reduction))
|
||||
, mAxis(dim)
|
||||
{
|
||||
}
|
||||
|
||||
int32_t ScatterElementsPluginV3::getNbOutputs() const noexcept
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
IPluginCapability* ScatterElementsPluginV3::getCapabilityInterface(PluginCapabilityType type) noexcept
|
||||
{
|
||||
try
|
||||
{
|
||||
if (type == PluginCapabilityType::kBUILD)
|
||||
{
|
||||
return static_cast<IPluginV3OneBuild*>(this);
|
||||
}
|
||||
if (type == PluginCapabilityType::kRUNTIME)
|
||||
{
|
||||
return static_cast<IPluginV3OneRuntime*>(this);
|
||||
}
|
||||
PLUGIN_ASSERT(type == PluginCapabilityType::kCORE);
|
||||
return static_cast<IPluginV3OneCore*>(this);
|
||||
}
|
||||
catch (std::exception const& e)
|
||||
{
|
||||
caughtError(e);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
char const* ScatterElementsPluginV3::getPluginVersion() const noexcept
|
||||
{
|
||||
return kSCATTER_PLUGIN_VERSION;
|
||||
}
|
||||
|
||||
int32_t ScatterElementsPluginV3::getOutputShapes(DimsExprs const* inputs, int32_t nbInputs,
|
||||
DimsExprs const* shapeInputs, int32_t nbShapeInputs, DimsExprs* outputs, int32_t nbOutputs,
|
||||
IExprBuilder& exprBuilder) noexcept
|
||||
{
|
||||
try
|
||||
{
|
||||
PLUGIN_ASSERT(nbInputs == 3);
|
||||
PLUGIN_ASSERT(inputs != nullptr);
|
||||
PLUGIN_ASSERT(nbOutputs == 1);
|
||||
outputs[kOUTPUT_TENSOR_IDX] = inputs[kDATA_TENSOR_IDX];
|
||||
return pluginStatus_t::STATUS_SUCCESS;
|
||||
}
|
||||
catch (std::exception const& e)
|
||||
{
|
||||
caughtError(e);
|
||||
}
|
||||
return pluginStatus_t::STATUS_FAILURE;
|
||||
}
|
||||
|
||||
int32_t ScatterElementsPluginV3::enqueue(PluginTensorDesc const* inputDesc, PluginTensorDesc const* outputDesc,
|
||||
void const* const* inputs, void* const* outputs, void* workspace, cudaStream_t stream) noexcept
|
||||
{
|
||||
try
|
||||
{
|
||||
PLUGIN_VALIDATE(inputDesc[kINDICES_TENSOR_IDX].type == DataType::kINT64);
|
||||
|
||||
runScatterElementsKernel(outputs[kOUTPUT_TENSOR_IDX], inputs[kDATA_TENSOR_IDX], inputs[kUPDATES_TENSOR_IDX],
|
||||
inputs[kINDICES_TENSOR_IDX], outputDesc[kOUTPUT_TENSOR_IDX], inputDesc[kDATA_TENSOR_IDX],
|
||||
inputDesc[kUPDATES_TENSOR_IDX], inputDesc[kINDICES_TENSOR_IDX], mAxis, mReduction, stream);
|
||||
return pluginStatus_t::STATUS_SUCCESS;
|
||||
}
|
||||
catch (std::exception const& e)
|
||||
{
|
||||
caughtError(e);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t ScatterElementsPluginV3::onShapeChange(
|
||||
PluginTensorDesc const* in, int32_t nbInputs, PluginTensorDesc const* out, int32_t nbOutputs) noexcept
|
||||
{
|
||||
PLUGIN_ASSERT(in != nullptr);
|
||||
PLUGIN_ASSERT(out != nullptr);
|
||||
PLUGIN_ASSERT(nbOutputs == 1);
|
||||
PLUGIN_ASSERT(nbInputs == 3);
|
||||
auto rank = in[0].dims.nbDims;
|
||||
// rank of input should be >=1
|
||||
PLUGIN_ASSERT(rank >= 1);
|
||||
// rank of indices should be same as rank of data
|
||||
PLUGIN_ASSERT(in[1].dims.nbDims == rank);
|
||||
// rank and shape of updates should be same as indices
|
||||
PLUGIN_ASSERT(in[2].dims.nbDims == rank);
|
||||
PLUGIN_VALIDATE(std::equal(in[2].dims.d, in[2].dims.d + rank, in[1].dims.d));
|
||||
return pluginStatus_t::STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
PluginFieldCollection const* ScatterElementsPluginV3::getFieldsToSerialize() noexcept
|
||||
{
|
||||
mDataToSerialize.clear();
|
||||
// "reduction" field is serialized as string
|
||||
mDataToSerialize.emplace_back("reduction", kREDUCE_ENUM_TO_STR.at(mReduction).c_str(), PluginFieldType::kCHAR,
|
||||
kREDUCE_ENUM_TO_STR.at(mReduction).size());
|
||||
mDataToSerialize.emplace_back("axis", &mAxis, PluginFieldType::kINT32, 1);
|
||||
|
||||
mFCToSerialize.nbFields = mDataToSerialize.size();
|
||||
mFCToSerialize.fields = mDataToSerialize.data();
|
||||
return &mFCToSerialize;
|
||||
}
|
||||
|
||||
bool ScatterElementsPluginV3::supportsFormatCombination(
|
||||
int32_t pos, DynamicPluginTensorDesc const* inOut, int32_t nbInputs, int32_t nbOutputs) noexcept
|
||||
{
|
||||
try
|
||||
{
|
||||
PLUGIN_VALIDATE(inOut && pos < (nbInputs + nbOutputs));
|
||||
|
||||
if (inOut[pos].desc.format != PluginFormat::kLINEAR)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto currentType = inOut[pos].desc.type;
|
||||
auto firstType = inOut[kDATA_TENSOR_IDX].desc.type;
|
||||
|
||||
// Only INT64 is supported for indices
|
||||
return pos == kINDICES_TENSOR_IDX ? (currentType == DataType::kINT64)
|
||||
: (currentType == firstType)
|
||||
&& (currentType == DataType::kFLOAT || currentType == DataType::kHALF
|
||||
|| (hasBfloat16AtomicAdd() && currentType == DataType::kBF16) || currentType == DataType::kINT32
|
||||
|| currentType == DataType::kINT64);
|
||||
}
|
||||
catch (std::exception const& e)
|
||||
{
|
||||
caughtError(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ScatterElementsPluginV3* ScatterElementsPluginV3::clone() noexcept
|
||||
{
|
||||
try
|
||||
{
|
||||
auto plugin = std::make_unique<ScatterElementsPluginV3>(mReduction, mAxis);
|
||||
plugin->setPluginNamespace(mNamespace.c_str());
|
||||
return plugin.release();
|
||||
}
|
||||
catch (std::exception const& e)
|
||||
{
|
||||
caughtError(e);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
IPluginV3* ScatterElementsPluginV3::attachToContext(IPluginResourceContext* context) noexcept
|
||||
{
|
||||
ScatterElementsPluginV3* obj = clone();
|
||||
return obj;
|
||||
}
|
||||
|
||||
int32_t ScatterElementsPluginV3::configurePlugin(
|
||||
DynamicPluginTensorDesc const* in, int32_t nbInputs, DynamicPluginTensorDesc const* out, int32_t nbOutputs) noexcept
|
||||
{
|
||||
try
|
||||
{
|
||||
PLUGIN_VALIDATE(nbInputs == 3);
|
||||
return pluginStatus_t::STATUS_SUCCESS;
|
||||
}
|
||||
catch (std::exception const& e)
|
||||
{
|
||||
caughtError(e);
|
||||
}
|
||||
return pluginStatus_t::STATUS_FAILURE;
|
||||
}
|
||||
|
||||
int32_t ScatterElementsPluginV3::getOutputDataTypes(
|
||||
DataType* outputTypes, int32_t nbOutputs, DataType const* inputTypes, int32_t nbInputs) const noexcept
|
||||
{
|
||||
try
|
||||
{
|
||||
PLUGIN_ASSERT(inputTypes != nullptr);
|
||||
PLUGIN_ASSERT(nbInputs == 3);
|
||||
PLUGIN_ASSERT(nbOutputs == 1);
|
||||
outputTypes[kOUTPUT_TENSOR_IDX] = inputTypes[kDATA_TENSOR_IDX];
|
||||
return pluginStatus_t::STATUS_SUCCESS;
|
||||
}
|
||||
catch (std::exception const& e)
|
||||
{
|
||||
caughtError(e);
|
||||
}
|
||||
return pluginStatus_t::STATUS_FAILURE;
|
||||
}
|
||||
|
||||
size_t ScatterElementsPluginV3::getWorkspaceSize(DynamicPluginTensorDesc const* inputs, int32_t nbInputs,
|
||||
DynamicPluginTensorDesc const* outputs, int32_t nbOutputs) const noexcept
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ScatterElementsPluginV3::setPluginNamespace(char const* libNamespace) noexcept
|
||||
{
|
||||
try
|
||||
{
|
||||
PLUGIN_ASSERT(libNamespace != nullptr);
|
||||
mNamespace = libNamespace;
|
||||
}
|
||||
catch (std::exception const& e)
|
||||
{
|
||||
caughtError(e);
|
||||
}
|
||||
}
|
||||
|
||||
char const* ScatterElementsPluginV3::getPluginName() const noexcept
|
||||
{
|
||||
return kSCATTER_PLUGIN_NAME;
|
||||
}
|
||||
|
||||
char const* ScatterElementsPluginV3::getPluginNamespace() const noexcept
|
||||
{
|
||||
return mNamespace.c_str();
|
||||
}
|
||||
|
||||
//
|
||||
// ScatterElementsPluginV3Creator
|
||||
//
|
||||
|
||||
ScatterElementsPluginV3Creator::ScatterElementsPluginV3Creator()
|
||||
{
|
||||
static std::mutex sMutex;
|
||||
std::lock_guard<std::mutex> guard(sMutex);
|
||||
gPluginAttributes.clear();
|
||||
gPluginAttributes.emplace_back(PluginField("reduction"));
|
||||
gPluginAttributes.emplace_back(PluginField("axis"));
|
||||
gFC.nbFields = gPluginAttributes.size();
|
||||
gFC.fields = gPluginAttributes.data();
|
||||
}
|
||||
|
||||
char const* ScatterElementsPluginV3Creator::getPluginName() const noexcept
|
||||
{
|
||||
return kSCATTER_PLUGIN_NAME;
|
||||
}
|
||||
|
||||
char const* ScatterElementsPluginV3Creator::getPluginVersion() const noexcept
|
||||
{
|
||||
return kSCATTER_PLUGIN_VERSION;
|
||||
}
|
||||
|
||||
PluginFieldCollection const* ScatterElementsPluginV3Creator::getFieldNames() noexcept
|
||||
{
|
||||
return &gFC;
|
||||
}
|
||||
|
||||
char const* ScatterElementsPluginV3Creator::getPluginNamespace() const noexcept
|
||||
{
|
||||
return mNamespace.c_str();
|
||||
}
|
||||
|
||||
void ScatterElementsPluginV3Creator::setPluginNamespace(char const* libNamespace) noexcept
|
||||
{
|
||||
PLUGIN_VALIDATE(libNamespace != nullptr);
|
||||
mNamespace = libNamespace;
|
||||
}
|
||||
|
||||
IPluginV3* ScatterElementsPluginV3Creator::createPlugin(
|
||||
char const* name, PluginFieldCollection const* fc, TensorRTPhase phase) noexcept
|
||||
{
|
||||
std::string reductionArg;
|
||||
int32_t axisArg = 0;
|
||||
|
||||
try
|
||||
{
|
||||
PLUGIN_VALIDATE(fc != nullptr);
|
||||
auto fields = fc->fields;
|
||||
|
||||
std::set<std::string> requiredFields{"reduction"};
|
||||
plugin::validateRequiredAttributesExist(requiredFields, fc);
|
||||
|
||||
using namespace std::string_view_literals;
|
||||
for (int32_t i = 0; i < fc->nbFields; ++i)
|
||||
{
|
||||
PLUGIN_VALIDATE(fields[i].name != nullptr);
|
||||
PLUGIN_VALIDATE(fields[i].data != nullptr);
|
||||
if (fields[i].name == "axis"sv)
|
||||
{
|
||||
auto data = static_cast<int32_t const*>(fields[i].data);
|
||||
axisArg = *data;
|
||||
}
|
||||
else if (fields[i].name == "reduction"sv)
|
||||
{
|
||||
auto data = static_cast<char const*>(fields[i].data);
|
||||
reductionArg = fields[i].length != -1 ? std::string(data, fields[i].length) : std::string(data);
|
||||
}
|
||||
}
|
||||
|
||||
PLUGIN_VALIDATE(kREDUCE_STR_TO_ENUM.find(reductionArg) != kREDUCE_STR_TO_ENUM.end(),
|
||||
(reductionArg + ": invalid value for 'reduction' plugin argument").c_str());
|
||||
|
||||
auto plugin = std::make_unique<ScatterElementsPluginV3>(reductionArg, axisArg);
|
||||
plugin->setPluginNamespace(mNamespace.c_str());
|
||||
return plugin.release();
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
caughtError(e);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace nvinfer1::plugin
|
||||
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* 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_SCATTER_ELEMENTS_PLUGIN_H
|
||||
#define TRT_SCATTER_ELEMENTS_PLUGIN_H
|
||||
#include "NvInfer.h"
|
||||
#include "NvInferPlugin.h"
|
||||
#include "common/plugin.h"
|
||||
#include "scatterElementsCommon.h"
|
||||
|
||||
namespace nvinfer1
|
||||
{
|
||||
namespace plugin
|
||||
{
|
||||
|
||||
class ScatterElementsPluginV3 : public IPluginV3,
|
||||
public IPluginV3OneCore,
|
||||
public IPluginV3OneBuild,
|
||||
public IPluginV3OneRuntime
|
||||
{
|
||||
public:
|
||||
// ctor and dtor
|
||||
ScatterElementsPluginV3() = delete;
|
||||
|
||||
ScatterElementsPluginV3(ScatterElementsPluginV3 const&) = delete;
|
||||
|
||||
ScatterElementsPluginV3(std::string const&, int32_t);
|
||||
|
||||
ScatterElementsPluginV3(ReductionType, int32_t);
|
||||
|
||||
~ScatterElementsPluginV3() override = default;
|
||||
|
||||
// IPluginV3 Methods
|
||||
IPluginCapability* getCapabilityInterface(PluginCapabilityType type) noexcept override;
|
||||
|
||||
ScatterElementsPluginV3* clone() noexcept override;
|
||||
// end IPluginV3 Methods
|
||||
|
||||
// IPluginV3Core Methods
|
||||
char const* getPluginVersion() const noexcept override;
|
||||
|
||||
char const* getPluginName() const noexcept override;
|
||||
|
||||
char const* getPluginNamespace() const noexcept override;
|
||||
|
||||
void setPluginNamespace(char const* pluginNamespace) noexcept;
|
||||
|
||||
// end IPluginV3Core Methods
|
||||
|
||||
// IPluginV3Build Methods
|
||||
int32_t getNbOutputs() const noexcept override;
|
||||
|
||||
bool supportsFormatCombination(
|
||||
int32_t pos, DynamicPluginTensorDesc const* inOut, int32_t nbInputs, int32_t nbOutputs) noexcept override;
|
||||
|
||||
int32_t getOutputShapes(DimsExprs const* inputs, int32_t nbInputs, DimsExprs const* shapeInputs,
|
||||
int32_t nbShapeInputs, DimsExprs* outputs, int32_t nbOutputs, IExprBuilder& exprBuilder) noexcept override;
|
||||
|
||||
int32_t configurePlugin(DynamicPluginTensorDesc const* in, int32_t nbInputs, DynamicPluginTensorDesc const* out,
|
||||
int32_t nbOutputs) noexcept override;
|
||||
|
||||
size_t getWorkspaceSize(DynamicPluginTensorDesc const* inputs, int32_t nbInputs,
|
||||
DynamicPluginTensorDesc const* outputs, int32_t nbOutputs) const noexcept override;
|
||||
|
||||
int32_t getOutputDataTypes(
|
||||
DataType* outputTypes, int32_t nbOutputs, DataType const* inputTypes, int32_t nbInputs) const noexcept override;
|
||||
// end IPluginV3Build Methods
|
||||
|
||||
// IPluginV3Runtime Methods
|
||||
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;
|
||||
|
||||
int32_t onShapeChange(
|
||||
PluginTensorDesc const* in, int32_t nbInputs, PluginTensorDesc const* out, int32_t nbOutputs) noexcept override;
|
||||
|
||||
IPluginV3* attachToContext(IPluginResourceContext* context) noexcept override;
|
||||
|
||||
PluginFieldCollection const* getFieldsToSerialize() noexcept override;
|
||||
// end IPluginV3Runtime Methods
|
||||
|
||||
private:
|
||||
ReductionType mReduction;
|
||||
int32_t mAxis;
|
||||
std::vector<nvinfer1::PluginField> mDataToSerialize;
|
||||
nvinfer1::PluginFieldCollection mFCToSerialize;
|
||||
std::string mNamespace;
|
||||
// input metadata
|
||||
static constexpr int32_t kINDICES_TENSOR_IDX = 1;
|
||||
static constexpr int32_t kUPDATES_TENSOR_IDX = 2;
|
||||
static constexpr int32_t kDATA_TENSOR_IDX = 0;
|
||||
// output metadata
|
||||
static constexpr int32_t kOUTPUT_TENSOR_IDX = 0;
|
||||
};
|
||||
|
||||
class ScatterElementsPluginV3Creator : public nvinfer1::IPluginCreatorV3One
|
||||
{
|
||||
public:
|
||||
// ctor and dtor
|
||||
ScatterElementsPluginV3Creator();
|
||||
|
||||
~ScatterElementsPluginV3Creator() override = default;
|
||||
|
||||
// get plugin metadata
|
||||
char const* getPluginName() const noexcept override;
|
||||
|
||||
char const* getPluginVersion() const noexcept override;
|
||||
|
||||
nvinfer1::PluginFieldCollection const* getFieldNames() noexcept override;
|
||||
|
||||
char const* getPluginNamespace() const noexcept override;
|
||||
|
||||
// setter
|
||||
void setPluginNamespace(char const* libNamespace) noexcept;
|
||||
|
||||
// create plugin
|
||||
IPluginV3* createPlugin(
|
||||
char const* name, nvinfer1::PluginFieldCollection const* fc, TensorRTPhase phase) noexcept override;
|
||||
|
||||
private:
|
||||
nvinfer1::PluginFieldCollection gFC;
|
||||
std::vector<PluginField> gPluginAttributes;
|
||||
std::string mNamespace;
|
||||
};
|
||||
|
||||
} // namespace plugin
|
||||
} // namespace nvinfer1
|
||||
|
||||
#endif // TRT_SCATTER_ELEMENTS_PLUGIN_H
|
||||
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* ************************************************************************
|
||||
* Modified from pytorch_scatter
|
||||
* Copyright (c) 2020 Matthias Fey <matthias.fey@tu-dortmund.de>
|
||||
* See https://github.com/rusty1s/pytorch_scatter/blob/master/LICENSE for details
|
||||
* ************************************************************************
|
||||
*/
|
||||
|
||||
#include "TensorInfo.cuh"
|
||||
#include "common/dimsHelpers.h"
|
||||
#include "reducer.cuh"
|
||||
#include "scatterElementsPluginKernel.h"
|
||||
#include <thrust/device_vector.h>
|
||||
|
||||
namespace nvinfer1
|
||||
{
|
||||
namespace plugin
|
||||
{
|
||||
|
||||
#define THREADS 256
|
||||
#define BLOCKS(N) (N + THREADS - 1) / THREADS
|
||||
|
||||
using detail::TensorInfo;
|
||||
using detail::getTensorInfo;
|
||||
using nvinfer1::pluginInternal::volume;
|
||||
|
||||
template <typename TScalar, ReductionType tReduce>
|
||||
__global__ void scatterElements_kernel(const TScalar* updatesData, const TensorInfo<int64_t, int32_t> indexInfo,
|
||||
TScalar* outData, int32_t nE, int32_t nK, int32_t nN, int32_t nbElements)
|
||||
{
|
||||
|
||||
int32_t thread_idx = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
|
||||
int32_t b = thread_idx / (nE * nK);
|
||||
int32_t k = thread_idx % nK;
|
||||
|
||||
if (thread_idx < nbElements)
|
||||
{
|
||||
int32_t offset = detail::IndexToOffset<int64_t, int32_t, -1>::get(thread_idx, indexInfo);
|
||||
int64_t idx = indexInfo.data[offset];
|
||||
|
||||
Reducer<TScalar, tReduce>::atomic_write(outData + b * nN * nK + idx * nK + k, updatesData[thread_idx]);
|
||||
}
|
||||
}
|
||||
|
||||
bool hasBfloat16AtomicAdd()
|
||||
{
|
||||
int deviceId;
|
||||
cudaGetDevice(&deviceId);
|
||||
cudaDeviceProp deviceProp;
|
||||
cudaGetDeviceProperties(&deviceProp, deviceId);
|
||||
return deviceProp.major >= 8;
|
||||
}
|
||||
|
||||
inline uint32_t getElementSize(nvinfer1::DataType t)
|
||||
{
|
||||
switch (t)
|
||||
{
|
||||
case nvinfer1::DataType::kINT64: return 8;
|
||||
case nvinfer1::DataType::kINT32:
|
||||
case nvinfer1::DataType::kFLOAT: return 4;
|
||||
case nvinfer1::DataType::kBF16:
|
||||
case nvinfer1::DataType::kHALF: return 2;
|
||||
case nvinfer1::DataType::kBOOL:
|
||||
case nvinfer1::DataType::kUINT8:
|
||||
case nvinfer1::DataType::kINT8:
|
||||
case nvinfer1::DataType::kFP8: return 1;
|
||||
case nvinfer1::DataType::kINT4:
|
||||
case nvinfer1::DataType::kFP4:
|
||||
case nvinfer1::DataType::kE8M0:
|
||||
PLUGIN_FAIL("Unsupported data type");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename TScalar>
|
||||
void dispatchScatterElementsKernel(void* outDataPtr, void const* dataDataPtr, void const* updatesDataPtr,
|
||||
void const* indicesDataPtr, PluginTensorDesc const& outDesc, PluginTensorDesc const& dataDesc,
|
||||
PluginTensorDesc const& updatesDesc, PluginTensorDesc const& indicesDesc, int64_t axis, ReductionType reduction,
|
||||
cudaStream_t stream)
|
||||
{
|
||||
auto updatesNumEl = volume(updatesDesc.dims);
|
||||
auto nB = 1;
|
||||
for (auto i = 0; i < axis; i++)
|
||||
{
|
||||
nB *= updatesDesc.dims.d[i];
|
||||
}
|
||||
auto nE = updatesDesc.dims.d[axis];
|
||||
auto nK = updatesNumEl / (nB * nE);
|
||||
auto nN = outDesc.dims.d[axis];
|
||||
|
||||
auto indexInfo = getTensorInfo<int64_t, int32_t>(indicesDataPtr, indicesDesc);
|
||||
|
||||
auto updatesData = (TScalar*) updatesDataPtr;
|
||||
auto outData = (TScalar*) outDataPtr;
|
||||
|
||||
AT_DISPATCH_REDUCTION_TYPES(reduction, [&] {
|
||||
scatterElements_kernel<TScalar, REDUCE>
|
||||
<<<BLOCKS(updatesNumEl), THREADS, 0, stream>>>(updatesData, indexInfo, outData, nE, nK, nN, updatesNumEl);
|
||||
});
|
||||
}
|
||||
|
||||
#define DISPATCH_RUN_KERNEL(TYPE) \
|
||||
dispatchScatterElementsKernel<TYPE>(outDataPtr, dataDataPtr, updatesDataPtr, indicesDataPtr, outDesc, dataDesc, \
|
||||
updatesDesc, indicesDesc, axis, reduction, stream)
|
||||
|
||||
void runScatterElementsKernel(void* outDataPtr, void const* dataDataPtr, void const* updatesDataPtr,
|
||||
void const* indicesDataPtr, PluginTensorDesc const& outDesc, PluginTensorDesc const& dataDesc,
|
||||
PluginTensorDesc const& updatesDesc, PluginTensorDesc const& indicesDesc, int64_t axis, ReductionType reduction,
|
||||
cudaStream_t stream)
|
||||
|
||||
{
|
||||
auto updatesNumEl = volume(updatesDesc.dims);
|
||||
auto outNumEl = volume(outDesc.dims);
|
||||
|
||||
// copy dataDataPtr data to outDataPtr area first
|
||||
cudaMemcpyAsync(outDataPtr, dataDataPtr, getElementSize(outDesc.type) * outNumEl, cudaMemcpyDeviceToDevice, stream);
|
||||
|
||||
if (updatesNumEl == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (outDesc.type)
|
||||
{
|
||||
case nvinfer1::DataType::kFLOAT: DISPATCH_RUN_KERNEL(float); break;
|
||||
case nvinfer1::DataType::kHALF: DISPATCH_RUN_KERNEL(__half); break;
|
||||
case nvinfer1::DataType::kINT32: DISPATCH_RUN_KERNEL(int32_t); break;
|
||||
case nvinfer1::DataType::kINT64: DISPATCH_RUN_KERNEL(int64_t); break;
|
||||
case nvinfer1::DataType::kBF16: DISPATCH_RUN_KERNEL(__nv_bfloat16); break;
|
||||
case nvinfer1::DataType::kBOOL:
|
||||
case nvinfer1::DataType::kUINT8:
|
||||
case nvinfer1::DataType::kINT8:
|
||||
case nvinfer1::DataType::kINT4:
|
||||
case nvinfer1::DataType::kFP8:
|
||||
case nvinfer1::DataType::kFP4:
|
||||
case nvinfer1::DataType::kE8M0:
|
||||
std::ostringstream stream;
|
||||
stream << "Unsupported data type:" << (int)outDesc.type << std::endl;
|
||||
PLUGIN_FAIL(stream.str().c_str());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace plugin
|
||||
} // namespace nvinfer1
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* ************************************************************************
|
||||
* Modified from pytorch_scatter
|
||||
* Copyright (c) 2020 Matthias Fey <matthias.fey@tu-dortmund.de>
|
||||
* See https://github.com/rusty1s/pytorch_scatter/blob/master/LICENSE for details
|
||||
* ************************************************************************
|
||||
*/
|
||||
#ifndef TRT_SCATTER_ELEMENTS_KERNEL_PLUGIN_H
|
||||
#define TRT_SCATTER_ELEMENTS_KERNEL_PLUGIN_H
|
||||
|
||||
#include "common/plugin.h"
|
||||
#include "scatterElementsCommon.h"
|
||||
|
||||
namespace nvinfer1
|
||||
{
|
||||
namespace plugin
|
||||
{
|
||||
|
||||
bool hasBfloat16AtomicAdd();
|
||||
|
||||
void runScatterElementsKernel(void* outDataPtr, void const* dataDataPtr, void const* updatesDataPtr,
|
||||
void const* indicesDataPtr, PluginTensorDesc const& outDesc, PluginTensorDesc const& dataDesc,
|
||||
PluginTensorDesc const& updatesDesc, PluginTensorDesc const& indicesDesc, int64_t axis, ReductionType reduction,
|
||||
cudaStream_t stream);
|
||||
|
||||
} // namespace plugin
|
||||
} // namespace nvinfer1
|
||||
#endif // TRT_SCATTER_ELEMENTS_KERNEL_PLUGIN_H
|
||||
@@ -0,0 +1,312 @@
|
||||
/*
|
||||
* 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 <algorithm>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string_view>
|
||||
|
||||
#include "common/serialize.hpp"
|
||||
#include "scatterElementsPluginKernel.h"
|
||||
#include "scatterElementsPluginLegacy.h"
|
||||
|
||||
namespace nvinfer1::plugin
|
||||
{
|
||||
|
||||
std::unordered_map<std::string, ReductionType> const kREDUCE_STR_TO_ENUM{
|
||||
{"add", ReductionType::kSUM},
|
||||
{"mean", ReductionType::kMEAN},
|
||||
{"mul", ReductionType::kMUL},
|
||||
{"min", ReductionType::kMIN},
|
||||
{"max", ReductionType::kMAX},
|
||||
};
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr char const* kSCATTER_ELEMENTS_NAME{"ScatterElements"};
|
||||
constexpr char const* kSCATTER_ELEMENTS_VERSION{"1"};
|
||||
} // namespace
|
||||
|
||||
ScatterElementsPluginV2::ScatterElementsPluginV2(ReductionType reduction, int32_t dim)
|
||||
: mReduction(reduction)
|
||||
, mAxis(dim)
|
||||
{
|
||||
}
|
||||
|
||||
ScatterElementsPluginV2::ScatterElementsPluginV2(std::string const& reduction, int32_t dim)
|
||||
: mReduction(kREDUCE_STR_TO_ENUM.at(reduction))
|
||||
, mAxis(dim)
|
||||
{
|
||||
}
|
||||
|
||||
ScatterElementsPluginV2::ScatterElementsPluginV2(void const* serialData, size_t serialLength)
|
||||
{
|
||||
deserialize_value(&serialData, &serialLength, &mReduction);
|
||||
deserialize_value(&serialData, &serialLength, &mAxis);
|
||||
}
|
||||
|
||||
int32_t ScatterElementsPluginV2::getNbOutputs() const noexcept
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int32_t ScatterElementsPluginV2::initialize() noexcept
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
char const* ScatterElementsPluginV2::getPluginType() const noexcept
|
||||
{
|
||||
return kSCATTER_ELEMENTS_NAME;
|
||||
}
|
||||
|
||||
char const* ScatterElementsPluginV2::getPluginVersion() const noexcept
|
||||
{
|
||||
return kSCATTER_ELEMENTS_VERSION;
|
||||
}
|
||||
|
||||
DimsExprs ScatterElementsPluginV2::getOutputDimensions(
|
||||
int32_t index, DimsExprs const* inputs, int32_t nbInputs, IExprBuilder& exprBuilder) noexcept
|
||||
{
|
||||
try
|
||||
{
|
||||
PLUGIN_VALIDATE(nbInputs == 3);
|
||||
PLUGIN_VALIDATE(inputs);
|
||||
PLUGIN_VALIDATE(index <= kOUTPUT_TENSOR_IDX);
|
||||
// both outputs are of the same size
|
||||
DimsExprs out(inputs[kDATA_TENSOR_IDX]);
|
||||
return out;
|
||||
}
|
||||
catch (std::exception const& e)
|
||||
{
|
||||
caughtError(e);
|
||||
}
|
||||
return DimsExprs();
|
||||
}
|
||||
|
||||
int32_t ScatterElementsPluginV2::enqueue(PluginTensorDesc const* inputDesc, PluginTensorDesc const* outputDesc,
|
||||
void const* const* inputs, void* const* outputs, void* workspace, cudaStream_t stream) noexcept
|
||||
{
|
||||
try
|
||||
{
|
||||
PLUGIN_VALIDATE(inputDesc[kINDICES_TENSOR_IDX].type == DataType::kINT64);
|
||||
|
||||
runScatterElementsKernel(outputs[kOUTPUT_TENSOR_IDX], inputs[kDATA_TENSOR_IDX], inputs[kUPDATES_TENSOR_IDX],
|
||||
inputs[kINDICES_TENSOR_IDX], outputDesc[kOUTPUT_TENSOR_IDX], inputDesc[kDATA_TENSOR_IDX],
|
||||
inputDesc[kUPDATES_TENSOR_IDX], inputDesc[kINDICES_TENSOR_IDX], mAxis, mReduction, stream);
|
||||
return 0;
|
||||
}
|
||||
catch (std::exception const& e)
|
||||
{
|
||||
caughtError(e);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
size_t ScatterElementsPluginV2::getSerializationSize() const noexcept
|
||||
{
|
||||
auto ret = serialized_size(mReduction) + serialized_size(mAxis);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ScatterElementsPluginV2::serialize(void* buffer) const noexcept
|
||||
{
|
||||
serialize_value(&buffer, mReduction);
|
||||
serialize_value(&buffer, mAxis);
|
||||
}
|
||||
|
||||
bool ScatterElementsPluginV2::supportsFormatCombination(
|
||||
int32_t pos, PluginTensorDesc const* inOut, int32_t nbInputs, int32_t nbOutputs) noexcept
|
||||
{
|
||||
try
|
||||
{
|
||||
PLUGIN_VALIDATE(inOut && pos < (nbInputs + nbOutputs));
|
||||
|
||||
if (inOut[pos].format != PluginFormat::kLINEAR)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto mytype = inOut[pos].type;
|
||||
auto firsttype = inOut[kDATA_TENSOR_IDX].type;
|
||||
|
||||
// Only INT64 is supported for indices
|
||||
return pos == kINDICES_TENSOR_IDX ? (mytype == DataType::kINT64)
|
||||
: (mytype == firsttype)
|
||||
&& (mytype == DataType::kFLOAT || mytype == DataType::kHALF
|
||||
|| (hasBfloat16AtomicAdd() && mytype == DataType::kBF16) || mytype == DataType::kINT32
|
||||
|| mytype == DataType::kINT64);
|
||||
}
|
||||
catch (std::exception const& e)
|
||||
{
|
||||
caughtError(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void ScatterElementsPluginV2::terminate() noexcept {}
|
||||
|
||||
void ScatterElementsPluginV2::destroy() noexcept
|
||||
{
|
||||
// This gets called when the network containing plugin is destroyed
|
||||
delete this;
|
||||
}
|
||||
|
||||
IPluginV2DynamicExt* ScatterElementsPluginV2::clone() const noexcept
|
||||
{
|
||||
auto plugin = std::make_unique<ScatterElementsPluginV2>(mReduction, mAxis);
|
||||
plugin->setPluginNamespace(mNamespace.c_str());
|
||||
return plugin.release();
|
||||
}
|
||||
|
||||
void ScatterElementsPluginV2::configurePlugin(
|
||||
DynamicPluginTensorDesc const* in, int32_t nbInputs, DynamicPluginTensorDesc const* out, int32_t nbOutputs) noexcept
|
||||
{
|
||||
try
|
||||
{
|
||||
PLUGIN_VALIDATE(nbInputs == 3);
|
||||
}
|
||||
catch (std::exception const& e)
|
||||
{
|
||||
caughtError(e);
|
||||
}
|
||||
}
|
||||
|
||||
DataType ScatterElementsPluginV2::getOutputDataType(
|
||||
int32_t index, DataType const* inputTypes, int32_t nbInputs) const noexcept
|
||||
{
|
||||
try
|
||||
{
|
||||
PLUGIN_VALIDATE(inputTypes && nbInputs == 3 && index == kOUTPUT_TENSOR_IDX);
|
||||
}
|
||||
catch (std::exception const& e)
|
||||
{
|
||||
caughtError(e);
|
||||
}
|
||||
return inputTypes[kDATA_TENSOR_IDX];
|
||||
}
|
||||
|
||||
size_t ScatterElementsPluginV2::getWorkspaceSize(
|
||||
PluginTensorDesc const* inputs, int32_t nbInputs, PluginTensorDesc const* outputs, int32_t nbOutputs) const noexcept
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ScatterElementsPluginV2::setPluginNamespace(char const* libNamespace) noexcept
|
||||
{
|
||||
mNamespace = libNamespace;
|
||||
}
|
||||
|
||||
char const* ScatterElementsPluginV2::getPluginNamespace() const noexcept
|
||||
{
|
||||
return mNamespace.c_str();
|
||||
}
|
||||
|
||||
//
|
||||
// ScatterElementsPluginV2Creator
|
||||
//
|
||||
|
||||
ScatterElementsPluginV2Creator::ScatterElementsPluginV2Creator()
|
||||
{
|
||||
gPluginAttributes.clear();
|
||||
gPluginAttributes.emplace_back(PluginField("reduction"));
|
||||
gPluginAttributes.emplace_back(PluginField("axis"));
|
||||
gFC.nbFields = gPluginAttributes.size();
|
||||
gFC.fields = gPluginAttributes.data();
|
||||
}
|
||||
|
||||
char const* ScatterElementsPluginV2Creator::getPluginName() const noexcept
|
||||
{
|
||||
return kSCATTER_ELEMENTS_NAME;
|
||||
}
|
||||
|
||||
char const* ScatterElementsPluginV2Creator::getPluginVersion() const noexcept
|
||||
{
|
||||
return kSCATTER_ELEMENTS_VERSION;
|
||||
}
|
||||
|
||||
PluginFieldCollection const* ScatterElementsPluginV2Creator::getFieldNames() noexcept
|
||||
{
|
||||
return &gFC;
|
||||
}
|
||||
|
||||
char const* ScatterElementsPluginV2Creator::getPluginNamespace() const noexcept
|
||||
{
|
||||
return mNamespace.c_str();
|
||||
}
|
||||
|
||||
void ScatterElementsPluginV2Creator::setPluginNamespace(char const* libNamespace) noexcept
|
||||
{
|
||||
mNamespace = libNamespace;
|
||||
}
|
||||
|
||||
IPluginV2DynamicExt* ScatterElementsPluginV2Creator::createPlugin(
|
||||
char const* name, PluginFieldCollection const* fc) noexcept
|
||||
{
|
||||
std::string reductionArg;
|
||||
int32_t axisArg = 0;
|
||||
|
||||
try
|
||||
{
|
||||
PLUGIN_VALIDATE(fc != nullptr);
|
||||
auto fields = fc->fields;
|
||||
|
||||
std::set<std::string> requiredFields{"reduction"};
|
||||
plugin::validateRequiredAttributesExist(requiredFields, fc);
|
||||
|
||||
using namespace std::string_view_literals;
|
||||
for (int32_t i = 0; i < fc->nbFields; ++i)
|
||||
{
|
||||
PLUGIN_VALIDATE(fields[i].name != nullptr);
|
||||
PLUGIN_VALIDATE(fields[i].data != nullptr);
|
||||
if (fields[i].name == "axis"sv)
|
||||
{
|
||||
auto data = static_cast<int32_t const*>(fields[i].data);
|
||||
axisArg = *data;
|
||||
}
|
||||
else if (fields[i].name == "reduction"sv)
|
||||
{
|
||||
auto data = static_cast<char const*>(fields[i].data);
|
||||
reductionArg = std::string(data);
|
||||
}
|
||||
}
|
||||
|
||||
PLUGIN_VALIDATE(kREDUCE_STR_TO_ENUM.find(reductionArg) != kREDUCE_STR_TO_ENUM.end(),
|
||||
(reductionArg + ": invalid value for 'reduction' plugin argument").c_str());
|
||||
|
||||
auto plugin = std::make_unique<ScatterElementsPluginV2>(reductionArg, axisArg);
|
||||
plugin->setPluginNamespace(mNamespace.c_str());
|
||||
return plugin.release();
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
caughtError(e);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
IPluginV2DynamicExt* ScatterElementsPluginV2Creator::deserializePlugin(
|
||||
char const* name, void const* serialData, size_t serialLength) noexcept
|
||||
{
|
||||
auto plugin = std::make_unique<ScatterElementsPluginV2>(serialData, serialLength);
|
||||
plugin->setPluginNamespace(mNamespace.c_str());
|
||||
return plugin.release();
|
||||
}
|
||||
|
||||
} // namespace nvinfer1::plugin
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* 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_SCATTER_ELEMENTS_PLUGIN_LEGACY_H
|
||||
#define TRT_SCATTER_ELEMENTS_PLUGIN_LEGACY_H
|
||||
|
||||
#include "common/plugin.h"
|
||||
#include "scatterElementsCommon.h"
|
||||
|
||||
namespace nvinfer1
|
||||
{
|
||||
namespace plugin
|
||||
{
|
||||
|
||||
class ScatterElementsPluginV2 final : public nvinfer1::IPluginV2DynamicExt
|
||||
{
|
||||
public:
|
||||
ScatterElementsPluginV2() = delete;
|
||||
ScatterElementsPluginV2(ScatterElementsPluginV2 const&) = delete;
|
||||
ScatterElementsPluginV2(std::string const&, int32_t);
|
||||
ScatterElementsPluginV2(ReductionType, int32_t);
|
||||
ScatterElementsPluginV2(void const* serialData, size_t serialLength);
|
||||
~ScatterElementsPluginV2() override = default;
|
||||
|
||||
// IPluginV2 methods
|
||||
char const* getPluginType() const noexcept override;
|
||||
char const* getPluginVersion() const noexcept override;
|
||||
int32_t getNbOutputs() const noexcept override;
|
||||
int32_t initialize() noexcept override;
|
||||
void terminate() noexcept override;
|
||||
size_t getSerializationSize() const noexcept override;
|
||||
void serialize(void* buffer) const noexcept override;
|
||||
void destroy() noexcept override;
|
||||
void setPluginNamespace(char const* libNamespace) noexcept override;
|
||||
char const* getPluginNamespace() const noexcept override;
|
||||
void setClipParam(bool clip) noexcept;
|
||||
void setScoreBits(int32_t scoreBits) noexcept;
|
||||
void setCaffeSemantics(bool caffeSemantics) noexcept;
|
||||
|
||||
// IPluginV2Ext methods
|
||||
nvinfer1::DataType getOutputDataType(
|
||||
int32_t index, nvinfer1::DataType const* inputTypes, int32_t nbInputs) const noexcept override;
|
||||
|
||||
// IPluginV2DynamicExt methods
|
||||
IPluginV2DynamicExt* clone() const noexcept override;
|
||||
DimsExprs getOutputDimensions(
|
||||
int32_t outputIndex, DimsExprs const* inputs, int32_t nbInputs, IExprBuilder& exprBuilder) noexcept override;
|
||||
bool supportsFormatCombination(
|
||||
int32_t pos, PluginTensorDesc const* inOut, int32_t nbInputs, int32_t nbOutputs) noexcept override;
|
||||
void configurePlugin(DynamicPluginTensorDesc const* in, int32_t nbInputs, DynamicPluginTensorDesc const* out,
|
||||
int32_t nbOutputs) noexcept override;
|
||||
size_t getWorkspaceSize(PluginTensorDesc const* inputs, int32_t nbInputs, PluginTensorDesc const* outputs,
|
||||
int32_t nbOutputs) const noexcept override;
|
||||
int32_t enqueue(PluginTensorDesc const* inputDesc, PluginTensorDesc const* outputDesc, void const* const* inputs,
|
||||
void* const* outputs, void* workspace, cudaStream_t stream) noexcept override;
|
||||
|
||||
private:
|
||||
ReductionType mReduction;
|
||||
int32_t mAxis;
|
||||
std::string mNamespace;
|
||||
|
||||
static constexpr int32_t kINDICES_TENSOR_IDX = 1;
|
||||
static constexpr int32_t kUPDATES_TENSOR_IDX = 2;
|
||||
static constexpr int32_t kDATA_TENSOR_IDX = 0;
|
||||
// outputs
|
||||
static constexpr int32_t kOUTPUT_TENSOR_IDX = 0;
|
||||
};
|
||||
|
||||
class ScatterElementsPluginV2Creator : public nvinfer1::IPluginCreator
|
||||
{
|
||||
public:
|
||||
ScatterElementsPluginV2Creator();
|
||||
|
||||
~ScatterElementsPluginV2Creator() override = default;
|
||||
|
||||
char const* getPluginName() const noexcept override;
|
||||
|
||||
char const* getPluginVersion() const noexcept override;
|
||||
|
||||
nvinfer1::PluginFieldCollection const* getFieldNames() noexcept override;
|
||||
|
||||
nvinfer1::IPluginV2DynamicExt* createPlugin(
|
||||
char const* name, nvinfer1::PluginFieldCollection const* fc) noexcept override;
|
||||
|
||||
nvinfer1::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:
|
||||
nvinfer1::PluginFieldCollection gFC;
|
||||
std::vector<nvinfer1::PluginField> gPluginAttributes;
|
||||
std::string mNamespace;
|
||||
};
|
||||
|
||||
} // namespace plugin
|
||||
} // namespace nvinfer1
|
||||
|
||||
#endif // TRT_SCATTER_ELEMENTS_PLUGIN_LEGACY_H
|
||||
Reference in New Issue
Block a user