Files
paddlepaddle--paddle/paddle/fluid/inference/tensorrt/pir/generic_plugin.cu
T
2026-07-13 12:40:42 +08:00

929 lines
38 KiB
Plaintext

// Copyright (c) 2024 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 <map>
#include "paddle/common/macros.h"
#include "paddle/fluid/inference/tensorrt/pir/dynamic_shape_infermeta_factory.h"
#include "paddle/fluid/inference/tensorrt/pir/dynamic_shape_infermeta_registry.h"
#include "paddle/fluid/inference/tensorrt/pir/generic_plugin.h"
#include "paddle/fluid/pir/dialect/kernel/ir/kernel_type.h"
#include "paddle/fluid/pir/dialect/operator/interface/op_yaml_info.h"
#include "paddle/fluid/pir/dialect/operator/ir/op_attribute.h"
#include "paddle/fluid/pir/dialect/operator/utils/utils.h"
#include "paddle/fluid/pir/serialize_deserialize/include/ir_deserialize.h"
#include "paddle/fluid/pir/serialize_deserialize/include/ir_serialize.h"
#include "paddle/phi/backends/context_pool.h"
#include "paddle/phi/backends/gpu/gpu_context.h"
#include "paddle/phi/backends/gpu/gpu_info.h"
#include "paddle/phi/common/place.h"
#include "paddle/phi/core/dense_tensor.h"
#include "paddle/phi/core/device_context.h"
#include "paddle/phi/core/kernel_context.h"
#include "paddle/phi/core/memory/memcpy.h"
#include "paddle/phi/kernels/funcs/data_type_transform.h"
#include "paddle/pir/include/core/op_info.h"
namespace paddle::inference::tensorrt::pir {
class GatherNdOpConfig : public SpecialOpConfig {
public:
GatherNdOpConfig() : SpecialOpConfig(true, false, false) {}
bool supportsFormatCombination(int pos,
const nvinfer1::PluginTensorDesc* in_out,
int nb_inputs,
int nb_outputs,
bool is_fp16_supported) override {
if (pos == 0)
return (in_out[pos].type == nvinfer1::DataType::kFLOAT ||
(is_fp16_supported &&
in_out[pos].type == nvinfer1::DataType::kHALF)) &&
(in_out[pos].format == nvinfer1::TensorFormat::kLINEAR);
if (pos == 1)
return (in_out[pos].type == nvinfer1::DataType::kINT32) &&
(in_out[pos].format == nvinfer1::TensorFormat::kLINEAR);
// output
if (pos == 2)
return in_out[0].type == in_out[pos].type &&
in_out[0].format == in_out[pos].format;
}
};
class YoloBoxOpConfig : public SpecialOpConfig {
public:
YoloBoxOpConfig() : SpecialOpConfig(true, false, false) {}
bool supportsFormatCombination(int pos,
const nvinfer1::PluginTensorDesc* in_out,
int nb_inputs,
int nb_outputs,
bool is_fp16_supported) override {
if (pos == 0)
return (in_out[pos].type == nvinfer1::DataType::kFLOAT ||
(is_fp16_supported &&
in_out[pos].type == nvinfer1::DataType::kHALF)) &&
(in_out[pos].format == nvinfer1::TensorFormat::kLINEAR);
if (pos == 1)
return (in_out[pos].type == nvinfer1::DataType::kINT32) &&
(in_out[pos].format == nvinfer1::TensorFormat::kLINEAR);
// output
if (pos == 2)
return in_out[0].type == in_out[pos].type &&
in_out[0].format == in_out[pos].format;
}
};
class ScatterNdAddOpConfig : public SpecialOpConfig {
public:
ScatterNdAddOpConfig() : SpecialOpConfig(true, false, false) {}
bool supportsFormatCombination(int pos,
const nvinfer1::PluginTensorDesc* in_out,
int nb_inputs,
int nb_outputs,
bool is_fp16_supported) override {
// input X
if (pos == 0)
return (in_out[pos].type == nvinfer1::DataType::kFLOAT ||
(is_fp16_supported &&
in_out[pos].type == nvinfer1::DataType::kHALF)) &&
(in_out[pos].format == nvinfer1::TensorFormat::kLINEAR);
// input Index
if (pos == 1)
return (in_out[pos].type == nvinfer1::DataType::kINT32) &&
(in_out[pos].format == nvinfer1::TensorFormat::kLINEAR);
// input Updates and output
if (pos == 2 || pos == 3)
return in_out[0].type == in_out[pos].type &&
in_out[0].format == in_out[pos].format;
}
};
class EmbeddingOpConfig : public SpecialOpConfig {
public:
EmbeddingOpConfig() : SpecialOpConfig(true, true, false) {}
bool supportsFormatCombination(int pos,
const nvinfer1::PluginTensorDesc* in_out,
int nb_inputs,
int nb_outputs,
bool is_fp16_supported) override {
if (pos == 0)
return (in_out[pos].type == nvinfer1::DataType::kINT32 &&
(in_out[pos].format == nvinfer1::TensorFormat::kLINEAR));
if (pos == 1)
return (in_out[pos].type == nvinfer1::DataType::kFLOAT) ||
((is_fp16_supported &&
in_out[pos].type == nvinfer1::DataType::kHALF)) &&
(in_out[pos].format == nvinfer1::TensorFormat::kLINEAR);
// output
if (pos == 2)
return in_out[1].type == in_out[pos].type &&
in_out[1].format == in_out[pos].format;
}
nvinfer1::DataType getOutputDataType(int index,
const nvinfer1::DataType* input_types,
int nb_inputs) override {
return input_types[1];
}
};
class ArgsortOpConfig : public SpecialOpConfig {
public:
ArgsortOpConfig() : SpecialOpConfig(true, true, true) {}
bool supportsFormatCombination(int pos,
const nvinfer1::PluginTensorDesc* in_out,
int nb_inputs,
int nb_outputs,
bool is_fp16_supported) override {
// input x
if (pos == 0) {
return ((in_out[pos].type == nvinfer1::DataType::kFLOAT ||
(is_fp16_supported &&
in_out[pos].type == nvinfer1::DataType::kHALF)) &&
in_out[pos].format == nvinfer1::TensorFormat::kLINEAR);
}
// output out
if (pos == 1) {
return (in_out[pos].type == in_out[0].type &&
in_out[pos].format == in_out[0].format);
}
// output indices
if (pos == 2) {
return (in_out[pos].type == nvinfer1::DataType::kINT32 &&
in_out[pos].format == in_out[0].format);
}
}
nvinfer1::DataType getOutputDataType(int index,
const nvinfer1::DataType* input_types,
int nb_inputs) override {
if (index == 1) {
return nvinfer1::DataType::kINT32;
} else {
return input_types[0];
}
}
void outputsPostProcess(phi::DeviceContextPool& pool, // NOLINT
std::vector<phi::DenseTensor>* dense_tensor_outputs,
void* const* outputs) override {
for (int i = 0; i < dense_tensor_outputs->size(); i++) {
phi::DenseTensor& output_tensor = (*dense_tensor_outputs)[i];
phi::DataType dtype = output_tensor.dtype();
if (dtype == phi::DataType::INT64) {
auto& int32_tensor = output_tensor;
auto ctx = pool.Get(output_tensor.place());
int32_tensor = phi::funcs::TransDataType(
reinterpret_cast<const phi::GPUContext&>(*ctx),
output_tensor,
phi::DataType::INT32);
paddle::memory::Copy(output_tensor.place(),
outputs[i],
output_tensor.place(),
int32_tensor.data<int32_t>(),
int32_tensor.numel() * sizeof(int),
nullptr);
}
}
}
};
class ScatterOpConfig : public SpecialOpConfig {
public:
ScatterOpConfig() : SpecialOpConfig(true, false, false) {}
bool supportsFormatCombination(int pos,
const nvinfer1::PluginTensorDesc* in_out,
int nb_inputs,
int nb_outputs,
bool is_fp16_supported) override {
// input X
if (pos == 0)
return (in_out[pos].type == nvinfer1::DataType::kFLOAT ||
(is_fp16_supported &&
in_out[pos].type == nvinfer1::DataType::kHALF)) &&
(in_out[pos].format == nvinfer1::TensorFormat::kLINEAR);
// Ids
if (pos == 1)
return (in_out[pos].type == nvinfer1::DataType::kINT32) &&
(in_out[pos].format == nvinfer1::TensorFormat::kLINEAR);
// 3:output 2:input Updates
if (pos == 3 || pos == 2)
return in_out[0].type == in_out[pos].type &&
in_out[0].format == in_out[pos].format;
}
};
class SolveOpConfig : public SpecialOpConfig {
public:
SolveOpConfig() : SpecialOpConfig(true, false, false) {}
bool supportsFormatCombination(int pos,
const nvinfer1::PluginTensorDesc* in_out,
int nb_inputs,
int nb_outputs,
bool is_fp16_supported) override {
// input X
if (pos == 0)
return in_out[pos].type == nvinfer1::DataType::kFLOAT &&
in_out[pos].format == nvinfer1::TensorFormat::kLINEAR;
// input Y
if (pos == 1)
return in_out[pos].type == nvinfer1::DataType::kFLOAT &&
in_out[pos].format == nvinfer1::TensorFormat::kLINEAR;
// output
if (pos == 2)
return in_out[0].type == in_out[pos].type &&
in_out[0].format == in_out[pos].format;
}
};
class Pad3dOpConfig : public SpecialOpConfig {
public:
Pad3dOpConfig() : SpecialOpConfig(true, false, false) {}
bool supportsFormatCombination(int pos,
const nvinfer1::PluginTensorDesc* in_out,
int nb_inputs,
int nb_outputs,
bool is_fp16_supported) override {
if (pos == 0) {
bool type_ok = (in_out[pos].type == nvinfer1::DataType::kFLOAT ||
(is_fp16_supported &&
in_out[pos].type == nvinfer1::DataType::kHALF));
return type_ok;
}
if (pos == 1) {
bool type_ok = (in_out[pos].type == nvinfer1::DataType::kINT32);
return type_ok;
}
if (pos == 2) {
bool type_match = (in_out[0].type == in_out[pos].type);
bool format_match = (in_out[0].format == in_out[pos].format);
return type_match && format_match;
}
}
};
GenericPlugin::GenericPlugin(const std::string& op_name,
const std::string& attrs_map_info,
const std::vector<std::string>& inputs_type_info,
const std::vector<std::string>& outputs_type_info,
bool with_fp16) {
op_name_ = op_name;
attrs_map_info_ = attrs_map_info;
inputs_type_info_ = inputs_type_info;
outputs_type_info_ = outputs_type_info;
::pir::OpInfo op_info =
::pir::IrContext::Instance()->GetRegisteredOpInfo(op_name);
auto op_info_interface =
op_info.GetInterfaceImpl<paddle::dialect::OpYamlInfoInterface>();
if (op_info_interface) {
op_yaml_info_ = std::make_unique<paddle::dialect::OpYamlInfoParser>(
op_info_interface->get_op_info_(op_name),
paddle::dialect::IsLegacyOp(op_name));
}
::pir::ProgramReader reader(1);
auto attrs_json_data = Json::parse(attrs_map_info);
attrs_map_ = reader.RecoverOpAttributesMap(&attrs_json_data);
for (auto input_type_info : inputs_type_info) {
auto type_json_data = Json::parse(input_type_info);
inputs_type_.push_back(reader.RecoverType(&type_json_data));
}
for (auto output_type_info : outputs_type_info) {
auto type_json_data = Json::parse(output_type_info);
outputs_type_.push_back(reader.RecoverType(&type_json_data));
}
with_fp16_ = with_fp16;
// Add special op config for deal with special situation
special_op_config_["pd_op.gather_nd"] = std::make_unique<GatherNdOpConfig>();
special_op_config_["pd_op.yolo_box"] = std::make_unique<YoloBoxOpConfig>();
special_op_config_["pd_op.scatter_nd_add"] =
std::make_unique<ScatterNdAddOpConfig>();
special_op_config_["pd_op.embedding"] = std::make_unique<EmbeddingOpConfig>();
special_op_config_["pd_op.argsort"] = std::make_unique<ArgsortOpConfig>();
special_op_config_["pd_op.scatter"] = std::make_unique<ScatterOpConfig>();
special_op_config_["pd_op.solve"] = std::make_unique<SolveOpConfig>();
special_op_config_["pd_op.pad3d"] = std::make_unique<Pad3dOpConfig>();
}
GenericPlugin::GenericPlugin(void const* serial_data, size_t serial_length) {
// deserialize with_fp16_
paddle::platform::DeserializeValue(&serial_data, &serial_length, &with_fp16_);
// deserialize op_name
int op_name_size = 0;
paddle::platform::DeserializeValue(
&serial_data, &serial_length, &op_name_size);
std::string op_name((char*)(serial_data), op_name_size); // NOLINT
op_name_ = std::move(op_name);
reinterpret_cast<char const*&>(serial_data) += op_name_size;
serial_length -= op_name_size;
// deserialize attrs_map
int attrs_map_info_size = 0;
paddle::platform::DeserializeValue(
&serial_data, &serial_length, &attrs_map_info_size);
std::string attrs_map_info(reinterpret_cast<char const*&>(serial_data),
attrs_map_info_size); // NOLINT
attrs_map_info_ = std::move(attrs_map_info);
reinterpret_cast<char const*&>(serial_data) += attrs_map_info_size;
serial_length -= attrs_map_info_size;
// deserialize inputs_type_info_
int inputs_type_info_size = 0;
paddle::platform::DeserializeValue(
&serial_data, &serial_length, &inputs_type_info_size);
for (int i = 0; i < inputs_type_info_size; i++) {
int input_type_info_size = 0;
paddle::platform::DeserializeValue(
&serial_data, &serial_length, &input_type_info_size);
std::string input_type_info(reinterpret_cast<char const*&>(serial_data),
input_type_info_size); // NOLINT
reinterpret_cast<char const*&>(serial_data) += input_type_info_size;
serial_length -= input_type_info_size;
inputs_type_info_.push_back(input_type_info);
}
// deserialize outputs_type_info_
int outputs_type_info_size = 0;
paddle::platform::DeserializeValue(
&serial_data, &serial_length, &outputs_type_info_size);
for (int i = 0; i < outputs_type_info_size; i++) {
int output_type_info_size = 0;
paddle::platform::DeserializeValue(
&serial_data, &serial_length, &output_type_info_size);
std::string output_type_info(reinterpret_cast<char const*&>(serial_data),
output_type_info_size); // NOLINT
reinterpret_cast<char const*&>(serial_data) += output_type_info_size;
serial_length -= output_type_info_size;
outputs_type_info_.push_back(output_type_info);
}
::pir::OpInfo op_info =
::pir::IrContext::Instance()->GetRegisteredOpInfo(op_name_);
auto op_info_interface =
op_info.GetInterfaceImpl<paddle::dialect::OpYamlInfoInterface>();
if (op_info_interface) {
op_yaml_info_ = std::make_unique<paddle::dialect::OpYamlInfoParser>(
op_info_interface->get_op_info_(op_name),
paddle::dialect::IsLegacyOp(op_name_));
}
::pir::ProgramReader reader(1);
auto attrs_json_data = Json::parse(attrs_map_info_);
attrs_map_ = reader.RecoverOpAttributesMap(&attrs_json_data);
for (auto input_type_info : inputs_type_info_) {
auto type_json_data = Json::parse(input_type_info);
inputs_type_.push_back(reader.RecoverType(&type_json_data));
}
for (auto output_type_info : outputs_type_info_) {
auto type_json_data = Json::parse(output_type_info);
outputs_type_.push_back(reader.RecoverType(&type_json_data));
}
}
int GenericPlugin::getNbOutputs() const TRT_NOEXCEPT {
int num = 0;
for (auto output_type : outputs_type_) {
if (output_type.isa<::pir::VectorType>()) {
num += output_type.dyn_cast<::pir::VectorType>().size();
} else {
num++;
}
}
return num;
}
int GenericPlugin::getNbInputs() const TRT_NOEXCEPT {
int num = 0;
for (auto input_type : inputs_type_) {
if (input_type.isa<::pir::VectorType>()) {
num += input_type.dyn_cast<::pir::VectorType>().size();
} else {
num++;
}
}
return num;
}
nvinfer1::IPluginV2DynamicExt* GenericPlugin::clone() const TRT_NOEXCEPT {
nvinfer1::IPluginV2DynamicExt* plugin = new GenericPlugin(op_name_,
attrs_map_info_,
inputs_type_info_,
outputs_type_info_,
with_fp16_);
plugin->initialize();
return plugin;
}
void GenericPlugin::serialize(void* buffer) const TRT_NOEXCEPT {
// use fp16
paddle::platform::SerializeValue(&buffer, with_fp16_);
// serialize op_name_
paddle::platform::SerializeValue(&buffer, static_cast<int>(op_name_.size()));
std::memcpy(buffer, op_name_.c_str(), op_name_.size());
reinterpret_cast<char*&>(buffer) += op_name_.size();
// serialize attrs_map_info_
paddle::platform::SerializeValue(&buffer,
static_cast<int>(attrs_map_info_.size()));
std::memcpy(buffer, attrs_map_info_.c_str(), attrs_map_info_.size());
reinterpret_cast<char*&>(buffer) += attrs_map_info_.size();
// serialize inputs_type_info_
paddle::platform::SerializeValue(&buffer,
static_cast<int>(inputs_type_info_.size()));
for (auto input_type_info : inputs_type_info_) {
paddle::platform::SerializeValue(&buffer,
static_cast<int>(input_type_info.size()));
std::memcpy(buffer, input_type_info.c_str(), input_type_info.size());
reinterpret_cast<char*&>(buffer) += input_type_info.size();
}
// serialize outputs_type_info_
paddle::platform::SerializeValue(&buffer,
static_cast<int>(outputs_type_info_.size()));
for (auto output_type_info : outputs_type_info_) {
paddle::platform::SerializeValue(&buffer,
static_cast<int>(output_type_info.size()));
std::memcpy(buffer, output_type_info.c_str(), output_type_info.size());
reinterpret_cast<char*&>(buffer) += output_type_info.size();
}
}
bool GenericPlugin::supportsFormatCombination(
int pos,
const nvinfer1::PluginTensorDesc* in_out,
int nb_inputs,
int nb_outputs) TRT_NOEXCEPT {
if (special_op_config_.find(op_name_) != special_op_config_.end() &&
special_op_config_[op_name_]->HasFormatCombinationFunc()) {
return special_op_config_[op_name_]->supportsFormatCombination(
pos, in_out, nb_inputs, nb_outputs, isFp16Supported());
} else {
return (in_out[pos].type == nvinfer1::DataType::kFLOAT ||
(isFp16Supported() &&
in_out[pos].type == nvinfer1::DataType::kHALF)) &&
(in_out[pos].format == nvinfer1::TensorFormat::kLINEAR) &&
(in_out[0].type == in_out[pos].type);
}
}
nvinfer1::DataType GenericPlugin::getOutputDataType(
int index,
const nvinfer1::DataType* input_types,
int nb_inputs) const TRT_NOEXCEPT {
if (special_op_config_.find(op_name_) != special_op_config_.end() &&
special_op_config_.at(op_name_)->HasGetOutputDataTypeFunc()) {
return special_op_config_.at(op_name_)->getOutputDataType(
index, input_types, nb_inputs);
}
return input_types[0];
}
int GenericPlugin::initialize() TRT_NOEXCEPT {
std::string kernel_func = op_yaml_info_->OpRuntimeInfo().kernel_func;
PADDLE_ENFORCE_EQ(
phi::KernelFactory::Instance().HasCompatiblePhiKernel(kernel_func),
true,
common::errors::Fatal("%s has no compatible phi kernel!",
op_name_.c_str()));
phi::DeviceContextPool& pool = phi::DeviceContextPool::Instance();
GPUPlace place(phi::backends::gpu::GetCurrentDeviceId());
auto* dev_ctx = static_cast<phi::GPUContext*>(pool.Get(place));
std::vector<phi::DataType> precision_types{phi::DataType::FLOAT32,
phi::DataType::FLOAT16};
for (auto& precision_type : precision_types) {
phi::KernelKey phi_kernel_key(
phi::Backend::GPU, phi::DataLayout::ANY, precision_type);
auto nv_dtype = paddle::platform::PhiType2NvType(precision_type);
phi_kernels_[nv_dtype] = std::make_unique<phi::Kernel>(
phi::KernelFactory::Instance().SelectKernel(kernel_func,
phi_kernel_key));
if (phi_kernel_contexts_.find(nv_dtype) == phi_kernel_contexts_.end() ||
!phi_kernel_contexts_[nv_dtype]) {
phi_kernel_contexts_[nv_dtype] =
std::make_unique<phi::KernelContext>(dev_ctx);
}
}
PADDLE_ENFORCE_EQ(
phi_kernels_[nvinfer1::DataType::kFLOAT]->IsValid() ||
phi_kernels_[nvinfer1::DataType::kHALF]->IsValid(),
true,
common::errors::Fatal("%s phi kernel is invalid!.", kernel_func));
if (!dense_tensor_inputs_)
dense_tensor_inputs_ = new std::vector<phi::DenseTensor>(getNbInputs());
if (!dense_tensor_outputs_)
dense_tensor_outputs_ = new std::vector<phi::DenseTensor>(getNbOutputs());
return 0;
}
nvinfer1::DimsExprs GenericPlugin::getOutputDimensions(
int output_index,
const nvinfer1::DimsExprs* inputs,
int nb_inputs,
nvinfer1::IExprBuilder& expr_builder) TRT_NOEXCEPT {
CHECK(output_index < getNbOutputs());
auto& dynamic_infermeta_factory = DynamicMetaFnFactory::Instance();
auto op_name_without_dialect = op_name_;
auto pos = op_name_.find_last_of(".");
if (pos != std::string::npos) {
op_name_without_dialect = op_name_.substr(pos + 1);
}
PADDLE_ENFORCE_EQ(
dynamic_infermeta_factory.Contains(op_name_without_dialect),
true,
common::errors::InvalidArgument(
"The %s op has no dynamic plugin infershape function!", op_name_));
auto* infershape_func =
dynamic_infermeta_factory.Get(op_name_without_dialect);
return infershape_func(
output_index, inputs, nb_inputs, expr_builder, attrs_map_);
}
void GenericPlugin::configurePlugin(
const nvinfer1::DynamicPluginTensorDesc* in,
int nb_inputs,
const nvinfer1::DynamicPluginTensorDesc* out,
int nb_outputs) TRT_NOEXCEPT {
CHECK(phi_kernels_[nvinfer1::DataType::kFLOAT]->IsValid() ||
phi_kernels_[nvinfer1::DataType::kHALF]->IsValid());
CHECK(nb_inputs == getNbInputs());
CHECK(nb_outputs == getNbOutputs());
}
// Shutdown the layer. This is called when the engine is destroyed
void GenericPlugin::terminate() TRT_NOEXCEPT {
delete dense_tensor_inputs_;
delete dense_tensor_outputs_;
}
int GenericPlugin::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(phi::backends::gpu::GetCurrentDeviceId());
phi::DeviceContextPool& pool = phi::DeviceContextPool::Instance();
// TODO(inference): generic plugin do not support INT8 precision now.
auto nvType2PhiType =
[&](nvinfer1::DataType nv_dtype) -> std::pair<phi::DataType, int> {
const std::map<nvinfer1::DataType, std::pair<phi::DataType, int>> _map{
{nvinfer1::DataType::kFLOAT, {phi::DataType::FLOAT32, sizeof(float)}},
{nvinfer1::DataType::kHALF, {phi::DataType::FLOAT16, sizeof(half)}},
{nvinfer1::DataType::kINT32, {phi::DataType::INT32, sizeof(int32_t)}},
{nvinfer1::DataType::kBOOL, {phi::DataType::BOOL, sizeof(bool)}},
};
CHECK(_map.count(nv_dtype))
<< "dtype [" << static_cast<int>(nv_dtype) << "] is not supported.";
return _map.at(nv_dtype);
};
nvinfer1::DataType data_type;
// input
if (op_name_ == "pd_op.embedding") {
data_type = input_desc[1].type;
} else {
data_type = input_desc[0].type;
}
CHECK((data_type == nvinfer1::DataType::kFLOAT) ||
(data_type == nvinfer1::DataType::kHALF));
phi_kernel_contexts_[data_type]->ClearInputOutput();
auto* dev_ctx = static_cast<phi::GPUContext*>(pool.Get(place));
phi_kernel_contexts_[data_type]->SetDeviceContext(dev_ctx);
auto& vec_kernel_fn_tensor_params = op_yaml_info_->TensorParams(true);
int kernel_input_count = vec_kernel_fn_tensor_params.size();
for (int i = 0; i < getNbInputs(); i++) {
// Tensor Input
if (!inputs_type_[i]) {
phi_kernel_contexts_[data_type]->EmplaceBackInput(nullptr);
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 = 0; k < input_shape.size(); k++) input_numel *= input_shape[k];
auto data_type_and_size = nvType2PhiType(input_desc[i].type);
phi::DenseTensorMeta input_meta(data_type_and_size.first,
common::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));
(*dense_tensor_inputs_)[i] =
std::move(phi::DenseTensor(input_alloc, input_meta));
if (i < kernel_input_count) {
phi_kernel_contexts_[data_type]->EmplaceBackInput(
&((*dense_tensor_inputs_)[i]));
}
}
VLOG(8) << "EmplaceBackBackInput done";
// attribute
auto& name2id = op_yaml_info_->InputName2Id();
auto& vec_kernel_fn_attr_params = op_yaml_info_->AttrParams(true);
int tensor_attr_count = 0;
for (auto& t : vec_kernel_fn_attr_params) {
if (name2id.count(t)) {
// tensor attribute, get information from input
tensor_attr_count++;
PADDLE_ENFORCE_LE(tensor_attr_count + kernel_input_count,
getNbInputs(),
common::errors::OutOfRange(
"The set input tensor number is %d, but got %d "
"that is greater than set input tensor num.",
getNbInputs(),
tensor_attr_count + kernel_input_count));
auto operand_type = inputs_type_[name2id.at(t)];
auto& tensor_attr_type = op_yaml_info_->TensorAttrTypeName(t);
VLOG(6) << "ctx->EmplaceBack mutable attr: " << t;
int tensor_index = kernel_input_count + tensor_attr_count - 1;
if (tensor_attr_type == "paddle::dialect::IntArrayAttribute") {
if (operand_type.isa<paddle::dialect::AllocatedDenseTensorType>()) {
phi::Attribute attr =
phi::TensorRef(&((*dense_tensor_inputs_)[tensor_index]));
phi_kernel_contexts_[data_type]->EmplaceBackAttr(attr);
} else if (operand_type.isa<paddle::dialect::DenseTensorType>()) {
phi::Attribute attr =
phi::TensorRef(&((*dense_tensor_inputs_)[tensor_index]));
phi_kernel_contexts_[data_type]->EmplaceBackAttr(attr);
} else {
PADDLE_THROW(common::errors::Unimplemented(
" [%s] only support dense tensor ", tensor_attr_type));
}
} else if (tensor_attr_type == "paddle::dialect::ScalarAttribute") {
phi::Attribute attr =
phi::TensorRef(&((*dense_tensor_inputs_)[tensor_index]));
phi_kernel_contexts_[data_type]->EmplaceBackAttr(attr);
} else {
PADDLE_THROW(common::errors::Unimplemented(
"attr type not support [%s] ", tensor_attr_type));
}
continue;
}
PADDLE_ENFORCE_NE(
attrs_map_.find(t),
attrs_map_.end(),
common::errors::NotFound("Not found %s in attrs_map_, please check "
"attrs_map_info when construct GenericPlugin.",
t));
auto& attr_type_name = op_yaml_info_->AttrTypeName(t);
if (attr_type_name == "paddle::dialect::IntArrayAttribute") {
phi_kernel_contexts_[data_type]->EmplaceBackAttr(
attrs_map_[t].dyn_cast<paddle::dialect::IntArrayAttribute>().data());
} else if (attr_type_name == "paddle::dialect::DataTypeAttribute") {
phi_kernel_contexts_[data_type]->EmplaceBackAttr(
attrs_map_[t].dyn_cast<paddle::dialect::DataTypeAttribute>().data());
} else if (attr_type_name == "pir::Int32Attribute") {
phi_kernel_contexts_[data_type]->EmplaceBackAttr(
attrs_map_[t].dyn_cast<::pir::Int32Attribute>().data());
} else if (attr_type_name == "pir::Int64Attribute") {
phi_kernel_contexts_[data_type]->EmplaceBackAttr(
attrs_map_[t].dyn_cast<::pir::Int64Attribute>().data());
} else if (attr_type_name == "pir::FloatAttribute") {
phi_kernel_contexts_[data_type]->EmplaceBackAttr(
attrs_map_[t].dyn_cast<::pir::FloatAttribute>().data());
} else if (attr_type_name == "pir::DoubleAttribute") {
if (attrs_map_[t].type_id() == ::pir::FloatAttribute::type_id()) {
const auto val = attrs_map_[t].dyn_cast<::pir::FloatAttribute>().data();
phi_kernel_contexts_[data_type]->EmplaceBackAttr(
static_cast<double>(val));
} else {
phi_kernel_contexts_[data_type]->EmplaceBackAttr(
attrs_map_[t].dyn_cast<::pir::DoubleAttribute>().data());
}
} else if (attr_type_name == "pir::BoolAttribute") {
phi_kernel_contexts_[data_type]->EmplaceBackAttr(
attrs_map_[t].dyn_cast<::pir::BoolAttribute>().data());
} else if (attr_type_name == "pir::StrAttribute") {
phi_kernel_contexts_[data_type]->EmplaceBackAttr(
attrs_map_[t].dyn_cast<::pir::StrAttribute>().AsString());
} else if (attr_type_name ==
"pir::ArrayAttribute<paddle::dialect::ScalarAttribute>") {
auto array_list =
attrs_map_[t].dyn_cast<::pir::ArrayAttribute>().AsVector();
std::vector<phi::Scalar> vec_res;
if (array_list.size() > 0) {
PADDLE_ENFORCE_EQ(
array_list[0].isa<paddle::dialect::ScalarAttribute>(),
true,
common::errors::Unimplemented(
"the 0th elementwise MUST be dialect::ScalarAttribute"));
for (size_t i = 0; i < array_list.size(); ++i) {
vec_res.push_back(array_list[i]
.dyn_cast<paddle::dialect::ScalarAttribute>()
.data());
}
}
phi_kernel_contexts_[data_type]->EmplaceBackAttr(vec_res);
} else if (attr_type_name == "pir::ArrayAttribute<::pir::Int32Attribute>") {
auto array_list =
attrs_map_[t].dyn_cast<::pir::ArrayAttribute>().AsVector();
std::vector<int32_t> vec_res;
if (array_list.size() > 0) {
PADDLE_ENFORCE_EQ(
array_list[0].isa<::pir::Int32Attribute>(),
true,
common::errors::Unimplemented(
"the 0th elementwise MUST be ::pir::Int32Attribute"));
for (size_t i = 0; i < array_list.size(); ++i) {
vec_res.push_back(
array_list[i].dyn_cast<::pir::Int32Attribute>().data());
}
}
phi_kernel_contexts_[data_type]->EmplaceBackAttr(vec_res);
} else if (attr_type_name == "pir::ArrayAttribute<::pir::FloatAttribute>") {
auto array_list =
attrs_map_[t].dyn_cast<::pir::ArrayAttribute>().AsVector();
std::vector<float> vec_res;
if (array_list.size() > 0) {
if (array_list[0].isa<::pir::FloatAttribute>()) {
for (size_t i = 0; i < array_list.size(); ++i) {
vec_res.push_back(
array_list[i].dyn_cast<::pir::FloatAttribute>().data());
}
} else {
PADDLE_THROW(common::errors::Unimplemented(
"attr type not support [%s] ", attr_type_name));
}
}
phi_kernel_contexts_[data_type]->EmplaceBackAttr(vec_res);
} else if (attr_type_name == "pir::ArrayAttribute<::pir::Int64Attribute>") {
auto array_list =
attrs_map_[t].dyn_cast<::pir::ArrayAttribute>().AsVector();
std::vector<int64_t> vec_res;
if (array_list.size() > 0) {
PADDLE_ENFORCE_EQ(
array_list[0].isa<::pir::Int64Attribute>(),
true,
common::errors::PreconditionNotMet(
"Element in array list MUST be ::pir::Int64Attribute "));
for (size_t i = 0; i < array_list.size(); ++i) {
vec_res.push_back(
array_list[i].dyn_cast<::pir::Int64Attribute>().data());
}
}
phi_kernel_contexts_[data_type]->EmplaceBackAttr(vec_res);
} else if (attr_type_name == "pir::ArrayAttribute<::pir::Int64Attribute>") {
auto array_list =
attrs_map_[t].dyn_cast<::pir::ArrayAttribute>().AsVector();
std::vector<int64_t> vec_res;
if (array_list.size() > 0) {
PADDLE_ENFORCE_EQ(
array_list[0].isa<::pir::Int64Attribute>(),
true,
common::errors::PreconditionNotMet(
"Element in array list MUST be ::pir::Int64Attribute "));
for (size_t i = 0; i < array_list.size(); ++i) {
vec_res.push_back(
array_list[i].dyn_cast<::pir::Int64Attribute>().data());
}
}
phi_kernel_contexts_[data_type]->EmplaceBackAttr(vec_res);
} else if (attr_type_name == "pir::ArrayAttribute<::pir::StrAttribute>") {
auto array_list =
attrs_map_[t].dyn_cast<::pir::ArrayAttribute>().AsVector();
std::vector<std::string> vec_res;
if (array_list.size() > 0) {
PADDLE_ENFORCE_EQ(
array_list[0].isa<::pir::StrAttribute>(),
true,
common::errors::PreconditionNotMet(
"Element in array list MUST be ::pir::StrAttribute "));
for (size_t i = 0; i < array_list.size(); ++i) {
vec_res.push_back(
array_list[i].dyn_cast<::pir::StrAttribute>().AsString());
}
}
phi_kernel_contexts_[data_type]->EmplaceBackAttr(vec_res);
} else if (attr_type_name == "paddle::dialect::PlaceAttribute") {
phi_kernel_contexts_[data_type]->EmplaceBackAttr(
attrs_map_[t].dyn_cast<paddle::dialect::PlaceAttribute>().data());
} else if (attr_type_name == "paddle::dialect::ScalarAttribute") {
phi_kernel_contexts_[data_type]->EmplaceBackAttr(
attrs_map_[t].dyn_cast<paddle::dialect::ScalarAttribute>().data());
} else {
PADDLE_THROW(common::errors::Unimplemented("attr type not support [%s] ",
attr_type_name));
}
VLOG(6) << "ctx->EmplaceBackAttr: " << t;
}
VLOG(8) << "EmplaceBackBackAttributes done";
// 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 = 0; k < output_shape.size(); k++)
output_numel *= output_shape[k];
auto data_type_and_size = nvType2PhiType(output_desc[i].type);
phi::DenseTensorMeta output_meta(data_type_and_size.first,
common::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));
(*dense_tensor_outputs_)[i] =
std::move(phi::DenseTensor(output_alloc, output_meta));
phi_kernel_contexts_[data_type]->EmplaceBackOutput(
&((*dense_tensor_outputs_)[i]));
}
VLOG(8) << "EmplaceBackBackOutput done";
CHECK_EQ(phi_kernel_contexts_[data_type]->InputsSize(),
getNbInputs() - tensor_attr_count);
CHECK_EQ(phi_kernel_contexts_[data_type]->OutputsSize(), getNbOutputs());
(*phi_kernels_[data_type])(phi_kernel_contexts_[data_type].get());
if (special_op_config_.find(op_name_) != special_op_config_.end() &&
special_op_config_[op_name_]->HasOutputsPostProcessFunc()) {
special_op_config_[op_name_]->outputsPostProcess(
pool, dense_tensor_outputs_, outputs);
}
return cudaGetLastError() != cudaSuccess;
}
nvinfer1::IPluginV2* PIRGenericPluginCreator::createPlugin(
const char* name, const nvinfer1::PluginFieldCollection* fc) TRT_NOEXCEPT {
std::string op_name;
std::string attrs_map_info;
std::vector<std::string> inputs_type_info;
std::vector<std::string> outputs_type_info;
bool with_fp16 = false;
for (int i = 0; i < fc->nbFields; ++i) {
const std::string field_name(fc->fields[i].name);
if (field_name.compare("op_name") == 0) {
op_name = std::string(static_cast<const char*>(fc->fields[i].data),
fc->fields[i].length);
} else if (field_name.compare("attrs_map_info") == 0) {
attrs_map_info = std::string(static_cast<const char*>(fc->fields[i].data),
fc->fields[i].length);
} else if (field_name.compare("inputs_type_info") == 0) {
std::string all_inputs_type_info(
static_cast<const char*>(fc->fields[i].data), fc->fields[i].length);
std::stringstream recovered_info(all_inputs_type_info);
std::string item;
while (std::getline(recovered_info, item, '\n')) {
inputs_type_info.push_back(item);
}
} else if (field_name.compare("outputs_type_info") == 0) {
std::string all_outputs_type_info(
static_cast<const char*>(fc->fields[i].data), fc->fields[i].length);
std::stringstream recovered_info(all_outputs_type_info);
std::string item;
while (std::getline(recovered_info, item, '\n')) {
outputs_type_info.push_back(item);
}
} else if (field_name.compare("with_fp16") == 0) {
with_fp16 = *static_cast<const bool*>(fc->fields[i].data);
} else {
assert(false && "unknown plugin field name.");
}
}
return new GenericPlugin(
op_name, attrs_map_info, inputs_type_info, outputs_type_info, with_fp16);
}
REGISTER_TRT_PLUGIN_V2(PIRGenericPluginCreator);
} // namespace paddle::inference::tensorrt::pir
REGISTER_FILE_SYMBOLS(generic_plugin);