549 lines
17 KiB
Python
549 lines
17 KiB
Python
# 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.
|
|
|
|
import numpy as np
|
|
import tensorrt as trt
|
|
|
|
from paddle.tensorrt.converter_utils import (
|
|
add_1D_constant_layer,
|
|
add_constant_layer,
|
|
set_layer_name,
|
|
trt_concat,
|
|
trt_div,
|
|
trt_min,
|
|
trt_pow,
|
|
trt_prod,
|
|
trt_sub,
|
|
trt_sum,
|
|
)
|
|
from paddle.tensorrt.register import converter_registry
|
|
|
|
activation_type_map = {
|
|
"pd_op.tanh": trt.ActivationType.TANH,
|
|
"pd_op.relu": trt.ActivationType.RELU,
|
|
"pd_op.sigmoid": trt.ActivationType.SIGMOID,
|
|
"pd_op.silu": trt.ActivationType.SIGMOID,
|
|
"pd_op.swish": trt.ActivationType.SIGMOID,
|
|
}
|
|
|
|
|
|
@converter_registry.register("pd_op.relu")
|
|
@converter_registry.register("pd_op.tanh")
|
|
@converter_registry.register("pd_op.sigmoid")
|
|
def activation_converter(network, paddle_op, inputs):
|
|
layer = network.add_activation(
|
|
inputs[0], activation_type_map[paddle_op.name()]
|
|
)
|
|
set_layer_name(layer, paddle_op)
|
|
return layer.get_output(0)
|
|
|
|
|
|
@converter_registry.register("pd_op.logsigmoid")
|
|
def logsigmoid_converter(network, paddle_op, inputs):
|
|
sigmoid_layer = network.add_activation(
|
|
inputs[0], trt.ActivationType.SIGMOID
|
|
)
|
|
set_layer_name(sigmoid_layer, paddle_op)
|
|
layer = network.add_unary(
|
|
sigmoid_layer.get_output(0), trt.UnaryOperation.LOG
|
|
)
|
|
set_layer_name(layer, paddle_op)
|
|
return layer.get_output(0)
|
|
|
|
|
|
@converter_registry.register("pd_op.relu6")
|
|
def relu6_converter(network, paddle_op, inputs):
|
|
layer = network.add_activation(inputs[0], trt.ActivationType.CLIP)
|
|
layer.alpha = 0.0
|
|
layer.beta = 6.0
|
|
set_layer_name(layer, paddle_op)
|
|
return layer.get_output(0)
|
|
|
|
|
|
@converter_registry.register("pd_op.softmax")
|
|
def softmax_converter(network, paddle_op, inputs):
|
|
from paddle.tensorrt.util import support_fp32_mix_precision
|
|
|
|
input1 = inputs[0]
|
|
input_shape = input1.shape
|
|
input_dims = len(input_shape)
|
|
axis = paddle_op.attrs().get("axis", -1)
|
|
|
|
# support 0 or 1 dims input
|
|
is_0_dims = input_dims == 0
|
|
is_1_dims = input_dims == 1
|
|
if is_0_dims or is_1_dims:
|
|
reshaped_layer = network.add_shuffle(input1)
|
|
reshaped_dims = (1, 1 if is_0_dims else input_shape[0])
|
|
reshaped_layer.reshape_dims = reshaped_dims
|
|
set_layer_name(reshaped_layer, paddle_op)
|
|
input1 = reshaped_layer.get_output(0)
|
|
input_shape = input1.shape
|
|
input_dims = len(input_shape)
|
|
axis = -1
|
|
|
|
layer = network.add_softmax(input1)
|
|
set_layer_name(layer, paddle_op)
|
|
support_fp32_mix_precision(paddle_op.name(), layer)
|
|
axes = max(0, input_dims - 3)
|
|
|
|
# Handle padded dimensions
|
|
padded_dims = 0
|
|
explicit_batch = 1
|
|
for i in range(input_dims - 1, explicit_batch, -1):
|
|
if input_shape[i] == 1:
|
|
padded_dims += 1
|
|
else:
|
|
break
|
|
|
|
if axis < 0:
|
|
axes = input_dims + axis
|
|
else:
|
|
axes = axis
|
|
|
|
layer.axes = 1 << axes
|
|
|
|
# Support 0 or 1 dims input
|
|
if is_0_dims or is_1_dims:
|
|
reshaped_layer = network.add_shuffle(layer.get_output(0))
|
|
reshaped_layer.reshape_dims = inputs[0].shape
|
|
layer = reshaped_layer
|
|
set_layer_name(layer, paddle_op)
|
|
|
|
return layer.get_output(0)
|
|
|
|
|
|
@converter_registry.register("pd_op.gelu")
|
|
def gelu_converter(network, paddle_op, inputs):
|
|
input_val = inputs[0]
|
|
approximate = paddle_op.attrs()["approximate"]
|
|
|
|
const_shape = [1] * len(input_val.shape)
|
|
|
|
if approximate:
|
|
constant_layer_pow = add_constant_layer(
|
|
network,
|
|
[3.0],
|
|
const_shape,
|
|
np.float32,
|
|
name=[paddle_op.name(), "constant_layer_pow"],
|
|
)
|
|
constant_layer_multiply = add_constant_layer(
|
|
network,
|
|
[0.044715],
|
|
const_shape,
|
|
np.float32,
|
|
name=[paddle_op.name(), "constant_layer_multiply"],
|
|
)
|
|
constant_layer_sqrt = add_constant_layer(
|
|
network,
|
|
[0.79788456080286535587989211986876],
|
|
const_shape,
|
|
np.float32,
|
|
name=[paddle_op.name(), "constant_layer_sqrt"],
|
|
)
|
|
constant_layer_one = add_constant_layer(
|
|
network,
|
|
[1.0],
|
|
const_shape,
|
|
np.float32,
|
|
name=[paddle_op.name(), "constant_layer_one"],
|
|
)
|
|
constant_layer_half = add_constant_layer(
|
|
network,
|
|
[0.5],
|
|
const_shape,
|
|
np.float32,
|
|
name=[paddle_op.name(), "constant_layer_half"],
|
|
)
|
|
|
|
layer_pow = trt_pow(
|
|
network,
|
|
input_val,
|
|
constant_layer_pow,
|
|
name=[paddle_op.name(), "layer_pow"],
|
|
)
|
|
layer_mul = trt_prod(
|
|
network,
|
|
layer_pow,
|
|
constant_layer_multiply,
|
|
name=[paddle_op.name(), "layer_mul"],
|
|
)
|
|
layer_add = trt_sum(
|
|
network, layer_mul, input_val, name=[paddle_op.name(), "layer_add"]
|
|
)
|
|
layer_sqrt = trt_prod(
|
|
network,
|
|
layer_add,
|
|
constant_layer_sqrt,
|
|
name=[paddle_op.name(), "layer_sqrt"],
|
|
)
|
|
|
|
layer_tanh = network.add_activation(layer_sqrt, trt.ActivationType.TANH)
|
|
set_layer_name(layer_tanh, paddle_op)
|
|
layer_one = trt_sum(
|
|
network,
|
|
layer_tanh.get_output(0),
|
|
constant_layer_one,
|
|
name=[paddle_op.name(), "layer_one"],
|
|
)
|
|
layer_cdf = trt_prod(
|
|
network,
|
|
layer_one,
|
|
constant_layer_half,
|
|
name=[paddle_op.name(), "layer_cdf"],
|
|
)
|
|
y = trt_prod(
|
|
network, layer_cdf, input_val, name=[paddle_op.name(), "y"]
|
|
)
|
|
|
|
return y
|
|
else:
|
|
constant_layer_one = add_constant_layer(
|
|
network,
|
|
[1.0],
|
|
const_shape,
|
|
np.float32,
|
|
name=[paddle_op.name(), "constant_layer_one"],
|
|
)
|
|
constant_layer_half = add_constant_layer(
|
|
network,
|
|
[0.5],
|
|
const_shape,
|
|
np.float32,
|
|
name=[paddle_op.name(), "constant_layer_half"],
|
|
)
|
|
constant_layer_rsqrt2 = add_constant_layer(
|
|
network,
|
|
[0.70710678118],
|
|
const_shape,
|
|
np.float32,
|
|
name=[paddle_op.name(), "constant_layer_rsqrt2"],
|
|
)
|
|
|
|
layer_mul = trt_prod(
|
|
network,
|
|
input_val,
|
|
constant_layer_rsqrt2,
|
|
name=[paddle_op.name(), "layer_mul"],
|
|
)
|
|
layer_erf = network.add_unary(layer_mul, trt.UnaryOperation.ERF)
|
|
set_layer_name(layer_erf, paddle_op)
|
|
layer_add = trt_sum(
|
|
network,
|
|
layer_erf.get_output(0),
|
|
constant_layer_one,
|
|
name=[paddle_op.name(), "layer_add"],
|
|
)
|
|
layer_cdf = trt_prod(
|
|
network,
|
|
layer_add,
|
|
constant_layer_half,
|
|
name=[paddle_op.name(), "layer_cdf"],
|
|
)
|
|
y = trt_prod(
|
|
network, layer_cdf, input_val, name=[paddle_op.name(), "y"]
|
|
)
|
|
|
|
return y
|
|
|
|
|
|
@converter_registry.register("pd_op.hardsigmoid")
|
|
def hardsigmoid_converter(network, paddle_op, inputs):
|
|
x = inputs[0]
|
|
slope = paddle_op.attrs()["slope"]
|
|
offset = paddle_op.attrs()["offset"]
|
|
hardsigmoid_layer = network.add_activation(
|
|
x, trt.ActivationType.HARD_SIGMOID
|
|
)
|
|
hardsigmoid_layer.alpha = slope
|
|
hardsigmoid_layer.beta = offset
|
|
set_layer_name(hardsigmoid_layer, paddle_op)
|
|
return hardsigmoid_layer.get_output(0)
|
|
|
|
|
|
@converter_registry.register("pd_op.hardswish")
|
|
def hardswish_converter(network, paddle_op, inputs):
|
|
x = inputs[0]
|
|
scale = 6.0
|
|
offset = 3.0
|
|
hardsigmoid_layer = network.add_activation(
|
|
x, trt.ActivationType.HARD_SIGMOID
|
|
)
|
|
hardsigmoid_layer.alpha = 1.0 / scale
|
|
hardsigmoid_layer.beta = offset / scale
|
|
set_layer_name(hardsigmoid_layer, paddle_op)
|
|
hardswish_layer = network.add_elementwise(
|
|
x, hardsigmoid_layer.get_output(0), trt.ElementWiseOperation.PROD
|
|
)
|
|
set_layer_name(hardswish_layer, paddle_op)
|
|
return hardswish_layer.get_output(0)
|
|
|
|
|
|
@converter_registry.register("pd_op.elu")
|
|
@converter_registry.register("pd_op.elu_")
|
|
def elu_converter(network, paddle_op, inputs):
|
|
x = inputs[0]
|
|
alpha = paddle_op.attrs()["alpha"]
|
|
elu_layer = network.add_activation(x, trt.ActivationType.ELU)
|
|
elu_layer.alpha = alpha
|
|
set_layer_name(elu_layer, paddle_op)
|
|
return elu_layer.get_output(0)
|
|
|
|
|
|
@converter_registry.register("pd_op.softplus")
|
|
def softplus_converter(network, paddle_op, inputs):
|
|
x = inputs[0]
|
|
beta = paddle_op.attrs()["beta"]
|
|
threshold = paddle_op.attrs()["threshold"]
|
|
layer_clip = network.add_activation(x, trt.ActivationType.CLIP)
|
|
layer_clip.alpha = -3.40282e038
|
|
layer_clip.beta = threshold / beta
|
|
set_layer_name(layer_clip, paddle_op)
|
|
|
|
softplus_layer = network.add_activation(
|
|
layer_clip.get_output(0), trt.ActivationType.SOFTPLUS
|
|
)
|
|
softplus_layer.alpha = 1.0 / beta
|
|
softplus_layer.beta = beta
|
|
set_layer_name(softplus_layer, paddle_op)
|
|
return softplus_layer.get_output(0)
|
|
|
|
|
|
@converter_registry.register("pd_op.swish")
|
|
@converter_registry.register("pd_op.silu")
|
|
def swish_silu_converter(network, paddle_op, inputs):
|
|
layer_output = network.add_activation(
|
|
inputs[0], activation_type_map[paddle_op.name()]
|
|
)
|
|
set_layer_name(layer_output, paddle_op)
|
|
return trt_prod(
|
|
network,
|
|
inputs[0],
|
|
layer_output.get_output(0),
|
|
name=[paddle_op.name(), "trt_prod"],
|
|
)
|
|
|
|
|
|
@converter_registry.register("pd_op.tanh_shrink")
|
|
def tanh_shrink_converter(network, paddle_op, inputs):
|
|
x = inputs[0]
|
|
tanh_layer = network.add_activation(x, trt.ActivationType.TANH)
|
|
set_layer_name(tanh_layer, paddle_op)
|
|
subtract_layer = network.add_elementwise(
|
|
x, tanh_layer.get_output(0), trt.ElementWiseOperation.SUB
|
|
)
|
|
set_layer_name(subtract_layer, paddle_op)
|
|
return subtract_layer.get_output(0)
|
|
|
|
|
|
@converter_registry.register("pd_op.stanh")
|
|
def stanh_converter(network, paddle_op, inputs):
|
|
x = inputs[0]
|
|
scale_a = paddle_op.attrs()["scale_a"]
|
|
scale_b = paddle_op.attrs()["scale_b"]
|
|
stanh_layer = network.add_activation(x, trt.ActivationType.SCALED_TANH)
|
|
stanh_layer.alpha = scale_b
|
|
stanh_layer.beta = scale_a
|
|
set_layer_name(stanh_layer, paddle_op)
|
|
return stanh_layer.get_output(0)
|
|
|
|
|
|
@converter_registry.register("pd_op.mish")
|
|
def mish_converter(network, paddle_op, inputs):
|
|
x = inputs[0]
|
|
softplus_layer = network.add_activation(x, trt.ActivationType.SOFTPLUS)
|
|
set_layer_name(softplus_layer, paddle_op)
|
|
softplus_output = softplus_layer.get_output(0)
|
|
|
|
tanh_layer = network.add_activation(
|
|
softplus_output, trt.ActivationType.TANH
|
|
)
|
|
set_layer_name(tanh_layer, paddle_op)
|
|
tanh_output = tanh_layer.get_output(0)
|
|
|
|
return trt_prod(
|
|
network, x, tanh_output, name=[paddle_op.name(), "trt_prod"]
|
|
)
|
|
|
|
|
|
@converter_registry.register("pd_op.celu")
|
|
def celu_converter(network, paddle_op, inputs):
|
|
input_tensor = inputs[0]
|
|
alpha = paddle_op.attrs()["alpha"]
|
|
input_rank = len(input_tensor.shape)
|
|
constant_shape = trt.Dims([1] * input_rank)
|
|
alpha_data = add_constant_layer(
|
|
network,
|
|
[alpha],
|
|
constant_shape,
|
|
dtype="float32",
|
|
name=[paddle_op.name(), "alpha_data"],
|
|
)
|
|
constant_zero_data = add_constant_layer(
|
|
network,
|
|
[0.0],
|
|
constant_shape,
|
|
dtype="float32",
|
|
name=[paddle_op.name(), "constant_zero_data"],
|
|
)
|
|
constant_one_data = add_constant_layer(
|
|
network,
|
|
[1.0],
|
|
constant_shape,
|
|
dtype="float32",
|
|
name=[paddle_op.name(), "constant_one_data"],
|
|
)
|
|
input_div_with_alpha = trt_div(
|
|
network,
|
|
input_tensor,
|
|
alpha_data,
|
|
name=[paddle_op.name(), "input_div_with_alpha"],
|
|
)
|
|
input_exp_layer = network.add_unary(
|
|
input_div_with_alpha, trt.UnaryOperation.EXP
|
|
)
|
|
set_layer_name(input_exp_layer, paddle_op)
|
|
input_sub_with_one = trt_sub(
|
|
network,
|
|
input_exp_layer.get_output(0),
|
|
constant_one_data,
|
|
name=[paddle_op.name(), "input_sub_with_one"],
|
|
)
|
|
input_prod_with_alpha = trt_prod(
|
|
network,
|
|
input_sub_with_one,
|
|
alpha_data,
|
|
name=[paddle_op.name(), "input_prod_with_alpha"],
|
|
)
|
|
min_input = trt_min(
|
|
network,
|
|
input_prod_with_alpha,
|
|
constant_zero_data,
|
|
name=[paddle_op.name(), "min_input"],
|
|
)
|
|
relu_layer = network.add_activation(input_tensor, trt.ActivationType.RELU)
|
|
set_layer_name(relu_layer, paddle_op)
|
|
output_tensor = trt_sum(
|
|
network,
|
|
relu_layer.get_output(0),
|
|
min_input,
|
|
name=[paddle_op.name(), "output_tensor"],
|
|
)
|
|
return output_tensor
|
|
|
|
|
|
@converter_registry.register("pd_op.thresholded_relu")
|
|
def thresholded_relu_converter(network, paddle_op, inputs):
|
|
x = inputs[0]
|
|
threshold = paddle_op.attrs()["threshold"]
|
|
thresholded_relu_layer = network.add_activation(
|
|
x, trt.ActivationType.THRESHOLDED_RELU
|
|
)
|
|
thresholded_relu_layer.alpha = threshold
|
|
set_layer_name(thresholded_relu_layer, paddle_op)
|
|
return thresholded_relu_layer.get_output(0)
|
|
|
|
|
|
@converter_registry.register("pd_op.leaky_relu")
|
|
@converter_registry.register("pd_op.leaky_relu_")
|
|
def leaky_relu_converter(network, paddle_op, inputs):
|
|
x = inputs[0]
|
|
negative_slope = paddle_op.attrs()["negative_slope"]
|
|
leaky_relu_layer = network.add_activation(x, trt.ActivationType.LEAKY_RELU)
|
|
leaky_relu_layer.alpha = negative_slope
|
|
set_layer_name(leaky_relu_layer, paddle_op)
|
|
return leaky_relu_layer.get_output(0)
|
|
|
|
|
|
@converter_registry.register("pd_op.selu")
|
|
def selu_converter(network, paddle_op, inputs):
|
|
x = inputs[0]
|
|
alpha = paddle_op.attrs()["alpha"]
|
|
scale = paddle_op.attrs()["scale"]
|
|
selu_layer = network.add_activation(x, trt.ActivationType.SELU)
|
|
selu_layer.alpha = alpha
|
|
selu_layer.beta = scale
|
|
set_layer_name(selu_layer, paddle_op)
|
|
return selu_layer.get_output(0)
|
|
|
|
|
|
@converter_registry.register("pd_op.prelu")
|
|
def prelu_converter(network, paddle_op, inputs):
|
|
input, alpha_data = inputs
|
|
input_dims = input.shape
|
|
data_format = paddle_op.attrs().get("data_format", "NCHW")
|
|
w_dims = trt.Dims(paddle_op.operands()[1].source().shape)
|
|
trt_w_dims = w_dims
|
|
|
|
alpha_tensor = network.add_constant(trt_w_dims, alpha_data)
|
|
set_layer_name(alpha_tensor, paddle_op)
|
|
alpha_tensor = alpha_tensor.get_output(0)
|
|
|
|
alpha_dims = alpha_tensor.shape
|
|
real_alpha_tensor = alpha_tensor
|
|
|
|
if len(alpha_dims) != len(input_dims):
|
|
reshape_layer = network.add_shuffle(alpha_tensor)
|
|
set_layer_name(reshape_layer, paddle_op)
|
|
c = alpha_dims[0]
|
|
|
|
n_tensor = add_1D_constant_layer(
|
|
network, [1], name=[paddle_op.name(), "n_tensor"]
|
|
)
|
|
c_tensor = add_1D_constant_layer(
|
|
network, [c], name=[paddle_op.name(), "c_tensor"]
|
|
)
|
|
hw_tensor = None
|
|
if len(input_dims) - 2 > 0:
|
|
hw_tensor = add_1D_constant_layer(
|
|
network,
|
|
[1] * (len(input_dims) - 2),
|
|
name=[paddle_op.name(), "hw_tensor"],
|
|
)
|
|
|
|
if data_format == "NCHW":
|
|
if hw_tensor:
|
|
shape_tensor = trt_concat(
|
|
network,
|
|
[n_tensor, c_tensor, hw_tensor],
|
|
name=[paddle_op.name(), "shape_tensor"],
|
|
)
|
|
else:
|
|
shape_tensor = trt_concat(
|
|
network,
|
|
[n_tensor, c_tensor],
|
|
name=[paddle_op.name(), "shape_tensor"],
|
|
)
|
|
else:
|
|
if hw_tensor:
|
|
shape_tensor = trt_concat(
|
|
network,
|
|
[n_tensor, hw_tensor, c_tensor],
|
|
name=[paddle_op.name(), "shape_tensor"],
|
|
)
|
|
else:
|
|
shape_tensor = trt_concat(
|
|
network,
|
|
[n_tensor, c_tensor],
|
|
name=[paddle_op.name(), "shape_tensor"],
|
|
)
|
|
|
|
reshape_layer.set_input(1, shape_tensor)
|
|
real_alpha_tensor = reshape_layer.get_output(0)
|
|
|
|
layer = network.add_parametric_relu(input, real_alpha_tensor)
|
|
set_layer_name(layer, paddle_op)
|
|
return layer.get_output(0)
|