Files
paddlepaddle--paddle/python/paddle/tensorrt/impls/search.py
T
2026-07-13 12:40:42 +08:00

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)