|
| 1 | +/* Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved. |
| 2 | +Licensed under the Apache License, Version 2.0 (the "License"); |
| 3 | +you may not use this file except in compliance with the License. |
| 4 | +You may obtain a copy of the License at |
| 5 | +http://www.apache.org/licenses/LICENSE-2.0 |
| 6 | +Unless required by applicable law or agreed to in writing, software |
| 7 | +distributed under the License is distributed on an "AS IS" BASIS, |
| 8 | +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 9 | +See the License for the specific language governing permissions and |
| 10 | +limitations under the License. */ |
| 11 | + |
| 12 | +#include <vector> |
| 13 | +#include "paddle/fluid/inference/tensorrt/convert/op_converter.h" |
| 14 | + |
| 15 | +namespace paddle { |
| 16 | +namespace framework { |
| 17 | +class Scope; |
| 18 | +namespace proto { |
| 19 | +class OpDesc; |
| 20 | +} // namespace proto |
| 21 | +} // namespace framework |
| 22 | +} // namespace paddle |
| 23 | + |
| 24 | +namespace paddle { |
| 25 | +namespace inference { |
| 26 | +namespace tensorrt { |
| 27 | + |
| 28 | +class GroupNormOpConverter : public OpConverter { |
| 29 | + public: |
| 30 | + void operator()(const framework::proto::OpDesc& op, |
| 31 | + const framework::Scope& scope, bool test_mode) override { |
| 32 | + VLOG(3) << "convert a fluid group_norm op"; |
| 33 | + |
| 34 | + framework::OpDesc op_desc(op, nullptr); |
| 35 | + |
| 36 | + auto* input_itensor = engine_->GetITensor(op_desc.Input("X").front()); |
| 37 | + |
| 38 | + int groups = BOOST_GET_CONST(int, op_desc.GetAttr("groups")); |
| 39 | + float epsilon = BOOST_GET_CONST(float, op_desc.GetAttr("epsilon")); |
| 40 | + |
| 41 | + std::string scale_name = op_desc.Input("Scale").front(); |
| 42 | + std::string bias_name = op_desc.Input("Bias").front(); |
| 43 | + |
| 44 | + // get the presistable var's data |
| 45 | + auto get_persistable_data = [&](const std::string& var_name, |
| 46 | + framework::DDim* dims) -> float* { |
| 47 | + auto* temp_var = scope.FindVar(var_name); |
| 48 | + auto* temp_tensor = temp_var->GetMutable<framework::LoDTensor>(); |
| 49 | + (*dims) = temp_tensor->dims(); |
| 50 | + |
| 51 | + auto* temp_data = engine_->GetWeightCPUData(var_name, temp_tensor, false); |
| 52 | + return temp_data; |
| 53 | + }; |
| 54 | + |
| 55 | + framework::DDim scale_dims; |
| 56 | + framework::DDim bias_dims; |
| 57 | + float* scale_data = get_persistable_data(scale_name, &scale_dims); |
| 58 | + float* bias_data = get_persistable_data(bias_name, &bias_dims); |
| 59 | + |
| 60 | + int64_t scale_numel = framework::product(scale_dims); |
| 61 | + int64_t bias_numel = framework::product(bias_dims); |
| 62 | + |
| 63 | + TensorRTEngine::Weight scale_weights{nvinfer1::DataType::kFLOAT, |
| 64 | + static_cast<void*>(scale_data), |
| 65 | + static_cast<size_t>(scale_numel)}; |
| 66 | + TensorRTEngine::Weight bias_weights{nvinfer1::DataType::kFLOAT, |
| 67 | + static_cast<void*>(bias_data), |
| 68 | + static_cast<size_t>(bias_numel)}; |
| 69 | + |
| 70 | + nvinfer1::Dims scale_nv_dims; |
| 71 | + nvinfer1::Dims bias_nv_dims; |
| 72 | + scale_nv_dims.nbDims = scale_dims.size(); |
| 73 | + bias_nv_dims.nbDims = bias_dims.size(); |
| 74 | + for (int i = 0; i < scale_dims.size(); i++) { |
| 75 | + scale_nv_dims.d[i] = scale_dims.at(i); |
| 76 | + } |
| 77 | + for (int i = 0; i < bias_dims.size(); i++) { |
| 78 | + bias_nv_dims.d[i] = bias_dims.at(i); |
| 79 | + } |
| 80 | + |
| 81 | + auto* scale_layer = TRT_ENGINE_ADD_LAYER(engine_, Constant, scale_nv_dims, |
| 82 | + scale_weights.get()); |
| 83 | + auto* bias_layer = TRT_ENGINE_ADD_LAYER(engine_, Constant, bias_nv_dims, |
| 84 | + bias_weights.get()); |
| 85 | + |
| 86 | + std::vector<nvinfer1::ITensor*> plugin_inputs; |
| 87 | + plugin_inputs.emplace_back(input_itensor); |
| 88 | + plugin_inputs.emplace_back(scale_layer->getOutput(0)); |
| 89 | + plugin_inputs.emplace_back(bias_layer->getOutput(0)); |
| 90 | + |
| 91 | + const std::vector<nvinfer1::PluginField> fields{ |
| 92 | + {"eps", &epsilon, nvinfer1::PluginFieldType::kFLOAT32, 1}, |
| 93 | + {"num_groups", &groups, nvinfer1::PluginFieldType::kINT32, 1}, |
| 94 | + }; |
| 95 | + |
| 96 | + nvinfer1::PluginFieldCollection* plugin_collections = |
| 97 | + static_cast<nvinfer1::PluginFieldCollection*>( |
| 98 | + malloc(sizeof(*plugin_collections) + |
| 99 | + fields.size() * sizeof(nvinfer1::PluginField))); |
| 100 | + plugin_collections->nbFields = static_cast<int>(fields.size()); |
| 101 | + plugin_collections->fields = fields.data(); |
| 102 | + |
| 103 | + auto creator = |
| 104 | + GetPluginRegistry()->getPluginCreator("GroupNormalizationPlugin", "1"); |
| 105 | + auto group_norm_plugin = |
| 106 | + creator->createPlugin("GroupNormalizationPlugin", plugin_collections); |
| 107 | + free(plugin_collections); |
| 108 | + |
| 109 | + auto group_norm_plugin_layer = engine_->network()->addPluginV2( |
| 110 | + plugin_inputs.data(), plugin_inputs.size(), *group_norm_plugin); |
| 111 | + |
| 112 | + auto output_name = op_desc.Output("Y")[0]; |
| 113 | + RreplenishLayerAndOutput(group_norm_plugin_layer, "group_norm", |
| 114 | + {output_name}, test_mode); |
| 115 | + } |
| 116 | +}; |
| 117 | + |
| 118 | +} // namespace tensorrt |
| 119 | +} // namespace inference |
| 120 | +} // namespace paddle |
| 121 | + |
| 122 | +REGISTER_TRT_OP_CONVERTER(group_norm, GroupNormOpConverter); |
0 commit comments