Files
2026-07-13 12:40:42 +08:00

669 lines
27 KiB
Plaintext

// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.
//
// 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 "paddle/fluid/inference/tensorrt/plugin/custom_generic_plugin.h"
#include "paddle/common/enforce.h"
#include "paddle/fluid/framework/op_kernel_type.h"
#include "paddle/fluid/framework/phi_utils.h"
#include "paddle/fluid/inference/tensorrt/op_teller.h"
#include "paddle/phi/api/include/tensor.h"
#include "paddle/phi/backends/gpu/gpu_context.h"
#include "paddle/phi/common/data_type.h"
#include "paddle/phi/core/compat/op_utils.h"
#include "paddle/phi/core/framework/framework.pb.h"
#include "paddle/phi/core/kernel_context.h"
#include "paddle/phi/core/kernel_factory.h"
namespace paddle {
namespace inference {
namespace tensorrt {
namespace plugin {
void validate(const std::string& op_type,
const std::string& datatype,
const std::string& tensor_format) {
std::unordered_set<std::string> supports_dtypes = {
"float32", "float16", "int8", "int32"};
std::unordered_set<std::string> supports_tensor_formats = {
"LINEAR", "CHW32", "CHW2", "HWC8", "CHW4"};
supports_tensor_formats.insert("DHWC8");
supports_tensor_formats.insert("HWC16");
// refer to
// https://docs.nvidia.com/deeplearning/tensorrt/developer-guide/index.html#ipluginv2
PADDLE_ENFORCE_GE(supports_dtypes.count(datatype),
0,
common::errors::InvalidArgument(
"custom op [%s] has unsupported datatype: [%s], "
"now only support: [float32, float16, int8, int32].",
op_type,
datatype));
PADDLE_ENFORCE_GE(
supports_tensor_formats.count(tensor_format),
0,
common::errors::InvalidArgument(
"custom op [%s] has unsupported tensor format: [%s], "
"now only support: [LINEAR, CHW32, CHW2, HWC8, CHW4, DHWC8(TensorRT "
"7.2 and after), HWC16(TensorRT 8.0 and after)].",
op_type,
tensor_format));
if (datatype == "float32") {
std::unordered_set<std::string> supports_formats_tmp = {"LINEAR", "CHW32"};
PADDLE_ENFORCE_GE(
supports_formats_tmp.count(tensor_format),
0,
common::errors::InvalidArgument(
"custom op [%s]: float32 only supports [LINEAR, CHW32], "
"but got tensor format: [%s], ",
op_type,
tensor_format));
}
if (datatype == "float16") {
std::unordered_set<std::string> supports_formats_tmp = {
"LINEAR", "CHW2", "HWC8", "CHW4"};
supports_formats_tmp.insert("DHWC8");
supports_formats_tmp.insert("HWC16");
PADDLE_ENFORCE_GE(supports_formats_tmp.count(tensor_format),
0,
common::errors::InvalidArgument(
"custom op [%s]: float16 only supports [LINEAR, "
"CHW2, HWC8, CHW4, DHWC8(TensorRT 7.2 and after), "
"HWC16(TensorRT 8.0 and after)], "
"but got tensor format: [%s], ",
op_type,
tensor_format));
}
if (datatype == "int8") {
std::unordered_set<std::string> supports_formats_tmp = {
"LINEAR", "CHW32", "CHW4"};
PADDLE_ENFORCE_GE(
supports_formats_tmp.count(tensor_format),
0,
common::errors::InvalidArgument(
"custom op [%s]: int8 only supports [LINEAR, CHW32, CHW4], "
"but got tensor format: [%s], ",
op_type,
tensor_format));
}
if (datatype == "int32") {
std::unordered_set<std::string> supports_formats_tmp = {"LINEAR"};
PADDLE_ENFORCE_GE(supports_formats_tmp.count(tensor_format),
0,
common::errors::InvalidArgument(
"custom op [%s]: int32 only supports [LINEAR], "
"but got tensor format: [%s], ",
op_type,
tensor_format));
}
}
std::vector<std::pair<std::string, std::string>> parseConfig(
const std::string& op_type, const std::string& config) {
std::vector<std::pair<std::string, std::string>> res;
size_t start = 0;
size_t seg = config.find("+", start);
while (seg != std::string::npos) {
std::string dtype_format = config.substr(start, seg - start);
size_t split_pos = dtype_format.find(":");
std::string dtype = dtype_format.substr(0, split_pos);
std::string format;
if (split_pos == std::string::npos) {
format = "LINEAR";
} else {
format = dtype_format.substr(split_pos + 1);
}
transform(dtype.begin(), dtype.end(), dtype.begin(), ::tolower);
transform(format.begin(), format.end(), format.begin(), ::toupper);
validate(op_type, dtype, format);
res.emplace_back(dtype, format);
start = seg + 1;
seg = config.find("+", start);
}
std::string dtype_format = config.substr(start);
size_t split_pos = dtype_format.find(":");
std::string dtype = dtype_format.substr(0, split_pos);
std::string format;
if (split_pos == std::string::npos) {
format = "LINEAR";
} else {
format = dtype_format.substr(split_pos + 1);
}
transform(dtype.begin(), dtype.end(), dtype.begin(), ::tolower);
transform(format.begin(), format.end(), format.begin(), ::toupper);
validate(op_type, dtype, format);
res.emplace_back(dtype, format);
return res;
}
nvinfer1::DataType getTrtDtype(std::string dtype) {
if (dtype == "float32") {
return nvinfer1::DataType::kFLOAT;
} else if (dtype == "float16") {
return nvinfer1::DataType::kHALF;
} else if (dtype == "int8") {
return nvinfer1::DataType::kINT8;
} else if (dtype == "int32") {
return nvinfer1::DataType::kINT32;
} else {
PADDLE_THROW(
common::errors::Unimplemented("Unsupported data type [%s]", dtype));
}
}
nvinfer1::TensorFormat getTrtTensorFormat(std::string tensor_format) {
if (tensor_format == "LINEAR") {
return nvinfer1::TensorFormat::kLINEAR;
} else if (tensor_format == "CHW32") {
return nvinfer1::TensorFormat::kCHW32;
} else if (tensor_format == "CHW2") {
return nvinfer1::TensorFormat::kCHW2;
} else if (tensor_format == "HWC8") {
return nvinfer1::TensorFormat::kHWC8;
} else if (tensor_format == "CHW4") {
return nvinfer1::TensorFormat::kCHW4;
} else if (tensor_format == "DHWC8") {
return nvinfer1::TensorFormat::kDHWC8;
} else if (tensor_format == "HWC16") {
return nvinfer1::TensorFormat::kHWC16;
} else {
PADDLE_THROW(common::errors::Unimplemented("Unsupported tensor format [%s]",
tensor_format));
}
}
GenerateCustomGenericPluginDataType
ProtoTypeToGenerateCustomGenericPluginDataType(
framework::proto::VarType_Type proto_type) {
using framework::proto::VarType_Type;
switch (proto_type) {
case VarType_Type::VarType_Type_BOOL:
return GenerateCustomGenericPluginDataType::PLUGIN_BOOL;
case VarType_Type::VarType_Type_UINT8:
return GenerateCustomGenericPluginDataType::PLUGIN_UINT8;
case VarType_Type::VarType_Type_INT8:
return GenerateCustomGenericPluginDataType::PLUGIN_INT8;
case VarType_Type::VarType_Type_INT16:
return GenerateCustomGenericPluginDataType::PLUGIN_INT16;
case VarType_Type::VarType_Type_INT32:
return GenerateCustomGenericPluginDataType::PLUGIN_INT32;
case VarType_Type::VarType_Type_INT64:
return GenerateCustomGenericPluginDataType::PLUGIN_INT64;
case VarType_Type::VarType_Type_FP16:
return GenerateCustomGenericPluginDataType::PLUGIN_FP16;
case VarType_Type::VarType_Type_FP32:
return GenerateCustomGenericPluginDataType::PLUGIN_FP32;
case VarType_Type::VarType_Type_FP64:
return GenerateCustomGenericPluginDataType::PLUGIN_FP64;
case VarType_Type::VarType_Type_SIZE_T:
return GenerateCustomGenericPluginDataType::PLUGIN_SIZE_T;
case VarType_Type::VarType_Type_BF16:
return GenerateCustomGenericPluginDataType::PLUGIN_BF16;
case VarType_Type::VarType_Type_COMPLEX64:
return GenerateCustomGenericPluginDataType::PLUGIN_COMPLEX64;
case VarType_Type::VarType_Type_COMPLEX128:
return GenerateCustomGenericPluginDataType::PLUGIN_COMPLEX128;
default:
PADDLE_THROW(common::errors::Unimplemented(
"This data type is currently not supported"));
}
}
CustomGenericPlugin::CustomGenericPlugin(
const paddle::framework::proto::OpDesc& proto_op_desc,
const InputOutPutVarInfo& in_out_info,
bool with_fp16) {
proto_op_desc_ = proto_op_desc;
op_desc_ = framework::OpDesc(proto_op_desc_, nullptr);
proto_op_desc_.SerializeToString(&op_meta_data_);
inputs_data_type_ = in_out_info.inputs_data_type;
outputs_data_type_ = in_out_info.outputs_data_type;
with_fp16_ = with_fp16;
}
CustomGenericPlugin::CustomGenericPlugin(
const paddle::framework::proto::OpDesc& proto_op_desc,
const std::vector<GenerateCustomGenericPluginDataType>& inputs_data_type,
const std::vector<GenerateCustomGenericPluginDataType>& outputs_data_type,
bool with_fp16) {
proto_op_desc_ = proto_op_desc;
op_desc_ = framework::OpDesc(proto_op_desc_, nullptr);
proto_op_desc_.SerializeToString(&op_meta_data_);
inputs_data_type_ = inputs_data_type;
outputs_data_type_ = outputs_data_type;
with_fp16_ = with_fp16;
}
CustomGenericPlugin::CustomGenericPlugin(void const* serial_data,
size_t serial_length) {
DeserializeValue(&serial_data, &serial_length, &inputs_data_type_);
DeserializeValue(&serial_data, &serial_length, &outputs_data_type_);
DeserializeValue(&serial_data, &serial_length, &with_fp16_);
std::string op_meta_data((char*)(serial_data), serial_length); // NOLINT
op_meta_data_ = std::move(op_meta_data);
proto_op_desc_.ParseFromString(op_meta_data_);
op_desc_ = framework::OpDesc(proto_op_desc_, nullptr);
}
int CustomGenericPlugin::getNbOutputs() const TRT_NOEXCEPT {
int res = 0;
for (auto& i : op_desc_.Outputs()) {
if (!i.second.empty()) res += i.second.size();
}
return res;
}
int CustomGenericPlugin::getNbInputs() const TRT_NOEXCEPT {
int res = 0;
for (auto& i : op_desc_.Inputs()) {
if (!i.second.empty()) res += i.second.size();
}
return res;
}
nvinfer1::IPluginV2DynamicExt* CustomGenericPlugin::clone() const TRT_NOEXCEPT {
nvinfer1::IPluginV2DynamicExt* plugin = new CustomGenericPlugin(
proto_op_desc_, inputs_data_type_, outputs_data_type_, with_fp16_);
plugin->initialize();
return plugin;
}
void CustomGenericPlugin::serialize(void* buffer) const TRT_NOEXCEPT {
// inputs_data_type_
SerializeValue(&buffer, inputs_data_type_);
// outputs_data_type_
SerializeValue(&buffer, outputs_data_type_);
// use fp16
SerializeValue(&buffer, with_fp16_);
// serialize op_meta_data_
std::memcpy(buffer, op_meta_data_.c_str(), op_meta_data_.size());
reinterpret_cast<char*&>(buffer) += op_meta_data_.size();
}
bool CustomGenericPlugin::supportsFormatCombination(
int pos,
const nvinfer1::PluginTensorDesc* in_out,
int nb_inputs,
int nb_outputs) TRT_NOEXCEPT {
auto& op_meta_info_map = OpMetaInfoMap::Instance();
const auto& meta_info_map = op_meta_info_map.GetMap();
auto& op_info = meta_info_map.at(op_desc_.Type()).front();
auto& supports_format_config =
OpMetaInfoHelper::GetTrtSupportsFormatConfig(op_info);
PADDLE_ENFORCE_NE(supports_format_config.empty(),
true,
common::errors::InvalidArgument(
"The %s op has no tensorrt plugin "
"supportsFormatCombination config!"
"Please use SetTrtSupportsFormatConfig to set.",
op_desc_.Type().c_str()));
// generate support format combination function by config
size_t input_num = OpMetaInfoHelper::GetInputs(op_info).size();
size_t output_num = OpMetaInfoHelper::GetOutputs(op_info).size();
std::vector<std::vector<std::pair<std::string, std::string>>>
format_combinations;
for (auto& config : supports_format_config) {
auto format_combination = parseConfig(op_desc_.Type(), config);
PADDLE_ENFORCE_EQ(input_num + output_num,
format_combination.size(),
common::errors::InvalidArgument(
"Expected %d format_combination, but got %d.",
input_num + output_num,
format_combination.size()));
format_combinations.emplace_back(format_combination);
}
bool is_supported = false;
for (size_t i = 0; i < input_num + output_num; ++i) {
if (i < input_num) {
if (pos == i) {
for (auto& format_combination : format_combinations) {
is_supported |=
(in_out[pos].type == getTrtDtype(format_combination[i].first) &&
in_out[pos].format ==
getTrtTensorFormat(format_combination[i].second));
}
}
} else {
if (pos == i) {
for (auto& format_combination : format_combinations) {
bool is_supported_tmp = true;
for (size_t j = 0; j < input_num; ++j) {
is_supported_tmp &=
(in_out[j].type == getTrtDtype(format_combination[j].first) &&
in_out[j].format ==
getTrtTensorFormat(format_combination[j].second));
}
is_supported_tmp &=
(in_out[pos].type == getTrtDtype(format_combination[i].first) &&
in_out[pos].format ==
getTrtTensorFormat(format_combination[i].second));
is_supported |= is_supported_tmp;
}
}
}
}
return is_supported;
}
nvinfer1::DataType CustomGenericPlugin::getOutputDataType(
int index,
const nvinfer1::DataType* input_types,
int nb_inputs) const TRT_NOEXCEPT {
PADDLE_ENFORCE_NE(
input_types,
nullptr,
common::errors::Unavailable("Input type should not be nullptr."));
return input_types[0];
}
int CustomGenericPlugin::initialize() TRT_NOEXCEPT {
if (!tensor_inputs_)
tensor_inputs_ = new std::vector<paddle::Tensor>(getNbInputs());
if (!tensor_outputs_)
tensor_outputs_ = new std::vector<paddle::Tensor>(getNbOutputs());
return 0;
}
nvinfer1::DimsExprs CustomGenericPlugin::getOutputDimensions(
int output_index,
const nvinfer1::DimsExprs* inputs,
int nb_inputs,
nvinfer1::IExprBuilder& expr_builder) TRT_NOEXCEPT {
PADDLE_ENFORCE_LT(
output_index,
getNbOutputs(),
common::errors::InvalidArgument(
"Output index (%d) must be less than the number of outputs (%d).",
output_index,
getNbOutputs()));
auto& op_meta_info_map = OpMetaInfoMap::Instance();
const auto& meta_info_map = op_meta_info_map.GetMap();
auto& op_info = meta_info_map.at(op_desc_.Type()).front();
auto& infer_shape_fn = OpMetaInfoHelper::GetTrtInferShapeFn(op_info);
PADDLE_ENFORCE_NE(infer_shape_fn,
nullptr,
common::errors::InvalidArgument(
"The %s op has no getOutputDimensions function!"
"Please use SetTrtInferShapeFn to set.",
op_desc_.Type().c_str()));
std::vector<paddle::any> custom_attrs;
auto& attrs = op_desc_.GetAttrMap();
auto& op_attrs_names = OpMetaInfoHelper::GetAttrs(op_info);
for (auto& op_attrs_name : op_attrs_names) {
auto attr_name_and_type = paddle::ParseAttrStr(op_attrs_name);
auto attr_name = attr_name_and_type[0];
auto attr_type_str = attr_name_and_type[1];
if (attr_type_str == "bool") {
custom_attrs.emplace_back(PADDLE_GET_CONST(bool, attrs.at(attr_name)));
} else if (attr_type_str == "int") {
custom_attrs.emplace_back(PADDLE_GET_CONST(int, attrs.at(attr_name)));
} else if (attr_type_str == "float") {
custom_attrs.emplace_back(PADDLE_GET_CONST(float, attrs.at(attr_name)));
} else if (attr_type_str == "int64_t") {
custom_attrs.emplace_back(PADDLE_GET_CONST(int64_t, attrs.at(attr_name)));
} else if (attr_type_str == "std::string") {
custom_attrs.emplace_back(
PADDLE_GET_CONST(std::string, attrs.at(attr_name)));
} else if (attr_type_str == "std::vector<int>") {
custom_attrs.emplace_back(
PADDLE_GET_CONST(std::vector<int>, attrs.at(attr_name)));
} else if (attr_type_str == "std::vector<float>") {
custom_attrs.emplace_back(
PADDLE_GET_CONST(std::vector<float>, attrs.at(attr_name)));
} else if (attr_type_str == "std::vector<int64_t>") {
custom_attrs.emplace_back(
PADDLE_GET_CONST(std::vector<int64_t>, attrs.at(attr_name)));
} else if (attr_type_str == "std::vector<std::string>") {
custom_attrs.emplace_back(
PADDLE_GET_CONST(std::vector<std::string>, attrs.at(attr_name)));
} else {
PADDLE_THROW(common::errors::Unimplemented(
"Unsupported `%s` type value as custom attribute now. "
"Supported data types include `bool`, `int`, `float`, "
"`int64_t`, `std::string`, `std::vector<int>`, "
"`std::vector<float>`, `std::vector<int64_t>`, "
"`std::vector<std::string>`, Please check whether "
"the attribute data type and data type string are matched.",
attr_type_str));
}
}
return infer_shape_fn(
{output_index, nb_inputs}, inputs, expr_builder, custom_attrs);
}
void CustomGenericPlugin::configurePlugin(
const nvinfer1::DynamicPluginTensorDesc* in,
int nb_inputs,
const nvinfer1::DynamicPluginTensorDesc* out,
int nb_outputs) TRT_NOEXCEPT {
PADDLE_ENFORCE_EQ(nb_inputs,
getNbInputs(),
common::errors::InvalidArgument(
"Number of inputs (%d) does not match the "
"expected number of inputs (%d).",
nb_inputs,
getNbInputs()));
PADDLE_ENFORCE_EQ(nb_outputs,
getNbOutputs(),
common::errors::InvalidArgument(
"Number of outputs (%d) does not match the "
"expected number of outputs (%d).",
nb_outputs,
getNbOutputs()));
}
// Shutdown the layer. This is called when the engine is destroyed
void CustomGenericPlugin::terminate() TRT_NOEXCEPT {
delete tensor_inputs_;
delete tensor_outputs_;
}
int CustomGenericPlugin::enqueue(const nvinfer1::PluginTensorDesc* input_desc,
const nvinfer1::PluginTensorDesc* output_desc,
const void* const* inputs,
void* const* outputs,
void* workspace,
cudaStream_t stream) TRT_NOEXCEPT {
GPUPlace place(platform::GetCurrentDeviceId());
// TODO(inference): custom generic plugin do not support INT8 precision now.
auto protoType2PhiType =
[&](GenerateCustomGenericPluginDataType proto_type,
nvinfer1::DataType nv_dtype) -> std::pair<phi::DataType, int> {
if (proto_type == GenerateCustomGenericPluginDataType::PLUGIN_FP16) {
return {phi::DataType::FLOAT16, sizeof(half)};
} else if (proto_type == GenerateCustomGenericPluginDataType::PLUGIN_FP32) {
if (isFp16Supported() && nv_dtype == nvinfer1::DataType::kHALF) {
return {phi::DataType::FLOAT16, sizeof(half)};
} else {
return {phi::DataType::FLOAT32, sizeof(float)};
}
} else if (proto_type ==
GenerateCustomGenericPluginDataType::PLUGIN_INT64) {
return {phi::DataType::INT64, sizeof(int64_t)};
} else if (proto_type ==
GenerateCustomGenericPluginDataType::PLUGIN_INT32) {
return {phi::DataType::INT32, sizeof(int32_t)};
} else if (proto_type == GenerateCustomGenericPluginDataType::PLUGIN_BOOL) {
return {phi::DataType::BOOL, sizeof(bool)};
} else {
PADDLE_ENFORCE_EQ(
false,
true,
common::errors::InvalidArgument("Precision is not supported."));
}
};
nvinfer1::DataType data_type = input_desc[0].type;
PADDLE_ENFORCE_EQ(
(data_type == nvinfer1::DataType::kFLOAT) ||
(data_type == nvinfer1::DataType::kHALF),
true,
common::errors::InvalidArgument("The data type must be either kFLOAT or "
"kHALF, but received data type %d.",
static_cast<int>(data_type)));
paddle::CustomOpKernelContext kernel_ctx;
// input
for (int i = 0; i < getNbInputs(); i++) {
if (inputs_data_type_[i] ==
GenerateCustomGenericPluginDataType::PLUGIN_OPTIONAL) {
(*tensor_inputs_)[i] = paddle::Tensor();
continue;
}
auto const& input_dims = input_desc[i].dims;
std::vector<int> input_shape;
for (int j = 0; j < input_dims.nbDims; j++)
input_shape.push_back(input_dims.d[j]);
int input_numel = 1;
for (int k : input_shape) input_numel *= k;
auto data_type_and_size =
protoType2PhiType(inputs_data_type_[i], data_type);
phi::DenseTensorMeta input_meta(data_type_and_size.first,
phi::make_ddim(input_shape));
std::shared_ptr<phi::Allocation> input_alloc(
new phi::Allocation((void*)(inputs[i]), // NOLINT
input_numel * data_type_and_size.second,
place));
(*tensor_inputs_)[i] = paddle::Tensor(
std::make_shared<phi::DenseTensor>(input_alloc, input_meta));
kernel_ctx.EmplaceBackInput(std::move((*tensor_inputs_)[i]));
}
// output
for (int i = 0; i < getNbOutputs(); i++) {
auto const& output_dims = output_desc[i].dims;
std::vector<int> output_shape;
for (int j = 0; j < output_dims.nbDims; j++)
output_shape.push_back(output_dims.d[j]);
int output_numel = 1;
for (int k : output_shape) output_numel *= k;
auto data_type_and_size =
protoType2PhiType(outputs_data_type_[i], data_type);
phi::DenseTensorMeta output_meta(data_type_and_size.first,
phi::make_ddim(output_shape));
std::shared_ptr<phi::Allocation> output_alloc(
new phi::Allocation(reinterpret_cast<void*>(outputs[i]),
output_numel * data_type_and_size.second,
place));
(*tensor_outputs_)[i] = paddle::Tensor(
std::make_shared<phi::DenseTensor>(output_alloc, output_meta));
kernel_ctx.EmplaceBackOutput(std::move((*tensor_outputs_)[i]));
}
auto& op_meta_info_map = OpMetaInfoMap::Instance();
const auto& meta_info_map = op_meta_info_map.GetMap();
auto& op_info = meta_info_map.at(op_desc_.Type()).front();
auto& op_attrs_names = OpMetaInfoHelper::GetAttrs(op_info);
auto& attrs = op_desc_.GetAttrMap();
for (auto& op_attrs_name : op_attrs_names) {
auto attr_name_and_type = paddle::ParseAttrStr(op_attrs_name);
auto attr_name = attr_name_and_type[0];
auto attr_type_str = attr_name_and_type[1];
if (attr_type_str == "bool") {
kernel_ctx.EmplaceBackAttr(PADDLE_GET_CONST(bool, attrs.at(attr_name)));
} else if (attr_type_str == "int") {
kernel_ctx.EmplaceBackAttr(PADDLE_GET_CONST(int, attrs.at(attr_name)));
} else if (attr_type_str == "float") {
kernel_ctx.EmplaceBackAttr(PADDLE_GET_CONST(float, attrs.at(attr_name)));
} else if (attr_type_str == "int64_t") {
kernel_ctx.EmplaceBackAttr(
PADDLE_GET_CONST(int64_t, attrs.at(attr_name)));
} else if (attr_type_str == "std::string") {
kernel_ctx.EmplaceBackAttr(
PADDLE_GET_CONST(std::string, attrs.at(attr_name)));
} else if (attr_type_str == "std::vector<int>") {
kernel_ctx.EmplaceBackAttr(
PADDLE_GET_CONST(std::vector<int>, attrs.at(attr_name)));
} else if (attr_type_str == "std::vector<float>") {
kernel_ctx.EmplaceBackAttr(
PADDLE_GET_CONST(std::vector<float>, attrs.at(attr_name)));
} else if (attr_type_str == "std::vector<int64_t>") {
kernel_ctx.EmplaceBackAttr(
PADDLE_GET_CONST(std::vector<int64_t>, attrs.at(attr_name)));
} else if (attr_type_str == "std::vector<std::string>") {
kernel_ctx.EmplaceBackAttr(
PADDLE_GET_CONST(std::vector<std::string>, attrs.at(attr_name)));
} else {
PADDLE_THROW(common::errors::Unimplemented(
"Unsupported `%s` type value as custom attribute now. "
"Supported data types include `bool`, `int`, `float`, "
"`int64_t`, `std::string`, `std::vector<int>`, "
"`std::vector<float>`, `std::vector<int64_t>`, "
"`std::vector<std::string>`, Please check whether "
"the attribute data type and data type string are matched.",
attr_type_str));
}
}
auto kernel_fn = OpMetaInfoHelper::GetKernelFn(op_info);
kernel_ctx.UpdatePlainOutputs(OpMetaInfoHelper::GetInputs(op_info),
OpMetaInfoHelper::GetOutputs(op_info),
OpMetaInfoHelper::GetInplaceMap(op_info));
kernel_fn(&kernel_ctx);
kernel_ctx.AssignInplaceOutputs();
// sync output tensor data into TensorRT output
auto* calc_outs = kernel_ctx.AllMutableOutput();
for (int i = 0; i < getNbOutputs(); i++) {
auto calc_out =
std::dynamic_pointer_cast<phi::DenseTensor>(calc_outs->at(i).impl());
if (reinterpret_cast<void*>(calc_out->data()) !=
reinterpret_cast<void*>(outputs[i])) {
LOG_FIRST_N(WARNING, 1)
<< "You created new Tensor(s) in custom operator(s) used as "
"output(s), "
"we will do cudaMemcpy to synchronize the output(s) "
"address needed by TensorRT plugin. "
"Inplace operation is highly recommended for better performance.";
auto const& output_dims = output_desc[i].dims;
std::vector<int> output_shape;
for (int j = 0; j < output_dims.nbDims; j++)
output_shape.push_back(output_dims.d[j]);
int output_numel = 1;
for (int k : output_shape) output_numel *= k;
auto data_type_and_size =
protoType2PhiType(outputs_data_type_[i], data_type);
phi::DenseTensorMeta output_meta(data_type_and_size.first,
phi::make_ddim(output_shape));
std::shared_ptr<phi::Allocation> output_alloc(
new phi::Allocation(reinterpret_cast<void*>(outputs[i]),
output_numel * data_type_and_size.second,
place));
phi::DenseTensor dense_output =
std::move(phi::DenseTensor(output_alloc, output_meta));
cudaMemcpy(static_cast<void*>(dense_output.data()),
static_cast<void*>(calc_out->data()),
output_numel * data_type_and_size.second,
cudaMemcpyDeviceToDevice);
}
}
return cudaGetLastError() != cudaSuccess;
}
} // namespace plugin
} // namespace tensorrt
} // namespace inference
} // namespace paddle