286 lines
8.8 KiB
Python
286 lines
8.8 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 tensorrt as trt
|
|
|
|
from paddle.tensorrt.converter_utils import (
|
|
generic_plugin_converter,
|
|
get_input_constant_value,
|
|
get_shape_tensor_element,
|
|
set_layer_name,
|
|
squeeze_trt,
|
|
trt_cast,
|
|
trt_gather,
|
|
trt_reshape,
|
|
trt_shape,
|
|
trt_unsqueeze,
|
|
)
|
|
from paddle.tensorrt.register import converter_registry
|
|
|
|
|
|
@converter_registry.register("pd_op.nonzero")
|
|
def non_zero_converter(network, paddle_op, inputs):
|
|
input_tensor = inputs[0]
|
|
cast_layer = network.add_cast(input_tensor, trt.float32)
|
|
set_layer_name(cast_layer, paddle_op)
|
|
|
|
non_zero_layer = network.add_non_zero(cast_layer.get_output(0))
|
|
nonzero_output = non_zero_layer.get_output(0)
|
|
set_layer_name(non_zero_layer, paddle_op)
|
|
|
|
shuffle_layer = network.add_shuffle(input=nonzero_output)
|
|
shuffle_layer.first_transpose = (1, 0)
|
|
transposed_output = shuffle_layer.get_output(0)
|
|
set_layer_name(shuffle_layer, paddle_op)
|
|
return transposed_output
|
|
|
|
|
|
@converter_registry.register("pd_op.argmax")
|
|
def argmax_converter(network, paddle_op, inputs):
|
|
x = inputs[0]
|
|
input_dims = x.shape
|
|
rank = len(input_dims)
|
|
axis = int(get_input_constant_value(paddle_op, inputs, 1)[0])
|
|
keepdims = paddle_op.attrs()["keepdims"]
|
|
|
|
if axis < 0:
|
|
axis += rank
|
|
|
|
topk_layer = network.add_topk(
|
|
input=x, op=trt.TopKOperation.MAX, k=1, axes=(1 << axis)
|
|
)
|
|
set_layer_name(topk_layer, paddle_op)
|
|
|
|
if keepdims:
|
|
return topk_layer.get_output(1)
|
|
else:
|
|
topk_out = topk_layer.get_output(1)
|
|
topk_out_shape_size = len(topk_out.shape)
|
|
# Mark which dimensions to squeeze
|
|
should_squeeze = [False] * topk_out_shape_size
|
|
should_squeeze[axis] = True
|
|
|
|
# Get dimensions to keep
|
|
gather_indices = [
|
|
i for i, squeeze in enumerate(should_squeeze) if not squeeze
|
|
]
|
|
|
|
# Add Shuffle layer
|
|
layer = network.add_shuffle(topk_out)
|
|
shape_tensor = trt_shape(
|
|
network, topk_out, name=[paddle_op.name(), 'shape_tensor']
|
|
)
|
|
real_shape_tensor = trt_gather(
|
|
network,
|
|
shape_tensor,
|
|
gather_indices,
|
|
name=[paddle_op.name(), 'real_shape_tensor'],
|
|
)
|
|
layer.set_input(1, real_shape_tensor)
|
|
set_layer_name(layer, paddle_op)
|
|
return layer.get_output(0)
|
|
|
|
|
|
@converter_registry.register("pd_op.argmin")
|
|
def argmin_converter(network, paddle_op, inputs):
|
|
x = inputs[0]
|
|
input_dims = x.shape
|
|
rank = len(input_dims)
|
|
axis = int(get_input_constant_value(paddle_op, inputs, 1)[0])
|
|
keepdims = paddle_op.attrs()["keepdims"]
|
|
|
|
if axis < 0:
|
|
axis += rank
|
|
|
|
topk_layer = network.add_topk(
|
|
input=x, op=trt.TopKOperation.MIN, k=1, axes=(1 << axis)
|
|
)
|
|
set_layer_name(topk_layer, paddle_op)
|
|
|
|
if keepdims:
|
|
return topk_layer.get_output(1)
|
|
else:
|
|
squeeze_layer = network.add_shuffle(topk_layer.get_output(1))
|
|
set_layer_name(squeeze_layer, paddle_op)
|
|
output_dims = []
|
|
for i in range(len(input_dims)):
|
|
if i == axis:
|
|
continue
|
|
output_dims.append(input_dims[i])
|
|
squeeze_layer.reshape_dims = tuple(output_dims)
|
|
return squeeze_layer.get_output(0)
|
|
|
|
|
|
@converter_registry.register("pd_op.argsort")
|
|
def argsort_converter(network, paddle_op, inputs):
|
|
input_tensor = inputs[0]
|
|
input_shape = input_tensor.shape
|
|
in_type = input_tensor.dtype
|
|
in_rank = len(input_shape)
|
|
axis = paddle_op.attrs()["axis"]
|
|
descending = paddle_op.attrs()["descending"]
|
|
if input_shape[axis] > 3840:
|
|
layer = generic_plugin_converter(network, paddle_op, inputs)
|
|
out0 = layer.get_output(0)
|
|
out1 = layer.get_output(1)
|
|
return out0, out1
|
|
else:
|
|
if axis < 0:
|
|
axis += len(input_shape)
|
|
topk_op = trt.TopKOperation.MAX if descending else trt.TopKOperation.MIN
|
|
need_cast = True if in_type != trt.DataType.FLOAT else False
|
|
if in_rank == 1:
|
|
unsqueeze_shape = trt.Dims([1, -1])
|
|
input_tensor = trt_reshape(
|
|
network,
|
|
input_tensor,
|
|
unsqueeze_shape,
|
|
is_shape_tensor=False,
|
|
name=[paddle_op.name(), 'input_tensor'],
|
|
)
|
|
axis = 1
|
|
if need_cast:
|
|
input_tensor = trt_cast(
|
|
network,
|
|
input_tensor,
|
|
trt.DataType.FLOAT,
|
|
name=[paddle_op.name(), 'input_tensor'],
|
|
)
|
|
topk_layer = network.add_topk(input_tensor, topk_op, 1, 1 << axis)
|
|
shape = trt_shape(
|
|
network, input_tensor, name=[paddle_op.name(), 'shape']
|
|
)
|
|
k_tensor = get_shape_tensor_element(
|
|
network, shape, axis, True, name=[paddle_op.name(), 'k_tensor']
|
|
)
|
|
topk_layer.set_input(1, k_tensor)
|
|
set_layer_name(topk_layer, paddle_op)
|
|
out = topk_layer.get_output(0)
|
|
indices = topk_layer.get_output(1)
|
|
if in_rank == 1:
|
|
squeeze_shape = trt.Dims([-1])
|
|
out = trt_reshape(
|
|
network,
|
|
out,
|
|
squeeze_shape,
|
|
is_shape_tensor=False,
|
|
name=[paddle_op.name(), 'out'],
|
|
)
|
|
indices = trt_reshape(
|
|
network,
|
|
indices,
|
|
squeeze_shape,
|
|
is_shape_tensor=False,
|
|
name=[paddle_op.name(), 'indices'],
|
|
)
|
|
out_tensor = trt_cast(
|
|
network, out, in_type, name=[paddle_op.name(), 'out_tensor']
|
|
)
|
|
indices_tensor = trt_cast(
|
|
network,
|
|
indices,
|
|
indices.dtype,
|
|
name=[paddle_op.name(), 'indices_tensor'],
|
|
)
|
|
return out_tensor, indices_tensor
|
|
|
|
|
|
@converter_registry.register("pd_op.where")
|
|
def where_converter(network, paddle_op, inputs):
|
|
condition = inputs[0]
|
|
x = inputs[1]
|
|
y = inputs[2]
|
|
|
|
select_layer = network.add_select(condition, x, y)
|
|
set_layer_name(select_layer, paddle_op)
|
|
|
|
return select_layer.get_output(0)
|
|
|
|
|
|
@converter_registry.register("pd_op.topk")
|
|
def topk_converter(network, paddle_op, inputs):
|
|
input_tensor = inputs[0]
|
|
|
|
input_shape = input_tensor.shape
|
|
|
|
axis = paddle_op.attrs().get("axis", -1)
|
|
largest = paddle_op.attrs().get("largest", True)
|
|
flag = trt.TopKOperation.MAX if largest else trt.TopKOperation.MIN
|
|
|
|
k_list = get_input_constant_value(paddle_op, inputs, 1)
|
|
if k_list is None:
|
|
raise NotImplementedError("Dynamic k is not supported in TensorRT.")
|
|
k = k_list[0]
|
|
input_rank = len(input_shape)
|
|
|
|
expand_to_2d = input_rank == 1
|
|
if expand_to_2d:
|
|
input_tensor = trt_unsqueeze(
|
|
network, input_tensor, [1], name=[paddle_op.name(), 'input_tensor']
|
|
)
|
|
|
|
input_type = input_tensor.dtype
|
|
if input_type == trt.DataType.INT32:
|
|
input_tensor = trt_cast(
|
|
network,
|
|
input_tensor,
|
|
trt.DataType.FLOAT,
|
|
name=[paddle_op.name(), 'input_tensor'],
|
|
)
|
|
|
|
if axis < 0:
|
|
axis += input_rank
|
|
|
|
layer = network.add_topk(input_tensor, flag, int(k), 1 << axis)
|
|
set_layer_name(layer, paddle_op)
|
|
values = layer.get_output(0)
|
|
indices = layer.get_output(1)
|
|
|
|
if expand_to_2d:
|
|
values = squeeze_trt(
|
|
network, values, [1], name=[paddle_op.name(), 'values']
|
|
)
|
|
indices = squeeze_trt(
|
|
network, indices, [1], name=[paddle_op.name(), 'indices']
|
|
)
|
|
|
|
if input_type == trt.DataType.INT32:
|
|
values = trt_cast(
|
|
network,
|
|
values,
|
|
trt.DataType.INT32,
|
|
name=[paddle_op.name(), 'values'],
|
|
)
|
|
|
|
return values, indices
|
|
|
|
|
|
@converter_registry.register("pd_op.index_select")
|
|
def index_select_converter(network, paddle_op, inputs):
|
|
input_tensor = inputs[0]
|
|
index_tensor = inputs[1]
|
|
axis = paddle_op.attrs().get("axis", 0)
|
|
|
|
reshape_layer = network.add_shuffle(index_tensor)
|
|
reshape_layer.reshape_dims = (-1,)
|
|
set_layer_name(reshape_layer, paddle_op)
|
|
|
|
gather_layer = network.add_gather(
|
|
input_tensor, reshape_layer.get_output(0), axis
|
|
)
|
|
set_layer_name(gather_layer, paddle_op)
|
|
|
|
return gather_layer.get_output(0)
|