442 lines
14 KiB
Python
442 lines
14 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
|
|
|
|
import paddle
|
|
from paddle.pir.core import datatype_to_str
|
|
from paddle.tensorrt.converter_utils import (
|
|
add_1D_constant_layer,
|
|
get_input_constant_value,
|
|
resize_to_1d,
|
|
set_layer_name,
|
|
trt_cast,
|
|
trt_floor_div,
|
|
trt_max,
|
|
trt_min,
|
|
trt_reduce_to_scalar,
|
|
trt_reshape,
|
|
trt_shape,
|
|
trt_sub,
|
|
)
|
|
from paddle.tensorrt.register import converter_registry
|
|
|
|
|
|
@converter_registry.register("pd_op.full_int_array")
|
|
def full_int_array_converter(network, paddle_op, inputs):
|
|
value = paddle_op.attrs()["value"]
|
|
if len(value) == 0:
|
|
return ()
|
|
value_weight = trt.Weights(np.array(value, dtype=np.int32))
|
|
full_int_array_layer = network.add_constant([len(value)], value_weight)
|
|
set_layer_name(full_int_array_layer, paddle_op)
|
|
return full_int_array_layer.get_output(0)
|
|
|
|
|
|
@converter_registry.register("pd_op.full")
|
|
def full_converter(network, paddle_op, inputs):
|
|
shape = paddle_op.attrs()["shape"]
|
|
value = paddle_op.attrs().get("value", 1.0)
|
|
dtype = paddle_op.attrs().get("dtype")
|
|
out_dtype = np.dtype(datatype_to_str[dtype])
|
|
if out_dtype == np.dtype("float64"):
|
|
out_dtype = np.dtype("float32")
|
|
if out_dtype == np.dtype("int64"):
|
|
out_dtype = np.dtype("int32")
|
|
full_layer = network.add_constant(
|
|
shape, np.full(shape, value, dtype=out_dtype)
|
|
)
|
|
set_layer_name(full_layer, paddle_op)
|
|
return full_layer.get_output(0)
|
|
|
|
|
|
@converter_registry.register("pd_op.assign")
|
|
@converter_registry.register("pd_op.assign_out_")
|
|
def assign_converter(network, paddle_op, inputs):
|
|
input_tensor = inputs[0]
|
|
identity_layer = network.add_identity(input_tensor)
|
|
set_layer_name(identity_layer, paddle_op)
|
|
return identity_layer.get_output(0)
|
|
|
|
|
|
@converter_registry.register("pd_op.assign_value")
|
|
@converter_registry.register("pd_op.assign_value_")
|
|
def assign_value_converter(network, paddle_op, inputs):
|
|
attrs = paddle_op.attrs()
|
|
shape = attrs['shape']
|
|
dtype = attrs['dtype']
|
|
values = attrs['values']
|
|
|
|
paddle_to_np_dtype_map = {
|
|
paddle.float16: np.float16,
|
|
paddle.float32: np.float32,
|
|
paddle.float64: np.float64,
|
|
paddle.int32: np.int32,
|
|
paddle.int64: np.int64,
|
|
}
|
|
|
|
if dtype not in paddle_to_np_dtype_map:
|
|
raise ValueError(
|
|
f"Unsupported dtype {dtype} for assign_value op in TRT converter."
|
|
)
|
|
|
|
np_dtype = paddle_to_np_dtype_map[dtype]
|
|
|
|
arr = np.array(values, dtype=np_dtype).reshape(shape)
|
|
if np_dtype == np.int64:
|
|
arr = arr.astype(np.int32)
|
|
const_layer = network.add_constant(tuple(shape), arr)
|
|
set_layer_name(const_layer, paddle_op)
|
|
if const_layer is None:
|
|
raise RuntimeError("Failed to create constant layer for assign_value.")
|
|
|
|
return const_layer.get_output(0)
|
|
|
|
|
|
@converter_registry.register("pd_op.arange")
|
|
def arange_converter(network, paddle_op, inputs):
|
|
start, end, step = inputs
|
|
zero_tensor = add_1D_constant_layer(
|
|
network, 0, name=[paddle_op.name(), 'zero_tensor']
|
|
)
|
|
|
|
delta = trt_sub(network, start, end, name=[paddle_op.name(), 'delta'])
|
|
|
|
f_quotient_tensor = trt_floor_div(
|
|
network, delta, step, name=[paddle_op.name(), 'f_quotient_tensor']
|
|
)
|
|
|
|
dtype = paddle_op.attrs().get("dtype")
|
|
|
|
if start.dtype == trt.DataType.FLOAT:
|
|
quotient_tensor = trt_cast(
|
|
network,
|
|
f_quotient_tensor,
|
|
trt.int32,
|
|
name=[paddle_op.name(), 'quotient_tensor'],
|
|
)
|
|
else:
|
|
quotient_tensor = f_quotient_tensor
|
|
|
|
delta_1 = trt_sub(
|
|
network,
|
|
zero_tensor,
|
|
quotient_tensor,
|
|
name=[paddle_op.name(), 'delta_1'],
|
|
)
|
|
number_tensor = trt_max(
|
|
network, delta_1, zero_tensor, name=[paddle_op.name(), 'number_tensor']
|
|
)
|
|
start1 = inputs[0]
|
|
start1 = trt_reshape(network, start1, (), name=[paddle_op.name(), 'start1'])
|
|
|
|
fill_layer = network.add_fill(shape=(), op=trt.FillOperation.LINSPACE)
|
|
fill_layer.set_input(0, number_tensor)
|
|
fill_layer.set_input(1, start1)
|
|
fill_layer.set_input(2, step)
|
|
set_layer_name(fill_layer, paddle_op)
|
|
|
|
output_tensor = fill_layer.get_output(0)
|
|
|
|
if dtype == paddle.int64 or dtype == paddle.int32:
|
|
output_tensor = trt_cast(
|
|
network,
|
|
output_tensor,
|
|
trt.int32,
|
|
name=[paddle_op.name(), 'output_tensor'],
|
|
)
|
|
return output_tensor
|
|
|
|
|
|
@converter_registry.register("pd_op.full_like")
|
|
def full_like_converter(network, paddle_op, inputs):
|
|
input_tensor = inputs[0]
|
|
shape = input_tensor.shape
|
|
ndims = len(shape)
|
|
|
|
dtype = int(paddle_op.attrs().get("dtype", -1))
|
|
|
|
dtype_map = {
|
|
0: None, # Undefined
|
|
1: trt.bool, # bool
|
|
2: trt.int32, # int32
|
|
3: trt.int32, # int64 -> int32
|
|
4: trt.int32, # int16 -> int32
|
|
5: trt.float32, # float16 -> float32
|
|
6: trt.float32, # float64 -> float32
|
|
7: trt.float32, # float32
|
|
8: trt.int32, # uint8 -> int32
|
|
11: trt.float32, # float32
|
|
}
|
|
|
|
target_dtype = dtype_map.get(dtype, None)
|
|
if target_dtype is None:
|
|
target_dtype = input_tensor.dtype
|
|
|
|
value = get_input_constant_value(paddle_op, inputs, 1)
|
|
if value is not None:
|
|
if isinstance(value, (list, tuple)):
|
|
value = value[0] if value else 0
|
|
|
|
if target_dtype == trt.int32:
|
|
value_tensor = add_1D_constant_layer(
|
|
network,
|
|
int(value),
|
|
np.int32,
|
|
name=[paddle_op.name(), 'value_tensor'],
|
|
)
|
|
else:
|
|
value_tensor = add_1D_constant_layer(
|
|
network,
|
|
float(value),
|
|
np.float32,
|
|
name=[paddle_op.name(), 'value_tensor'],
|
|
)
|
|
else:
|
|
value_tensor = inputs[1]
|
|
if value_tensor.dtype != target_dtype:
|
|
value_tensor = trt_cast(
|
|
network,
|
|
value_tensor,
|
|
target_dtype,
|
|
name=[paddle_op.name(), 'value_tensor'],
|
|
)
|
|
|
|
shape_tensor = trt_shape(
|
|
network, input_tensor, name=[paddle_op.name(), 'shape_tensor']
|
|
)
|
|
one_rank_tensor = add_1D_constant_layer(
|
|
network, [1] * ndims, name=[paddle_op.name(), 'one_rank_tensor']
|
|
)
|
|
input_shape_tensor = one_rank_tensor
|
|
|
|
shuffle_layer = network.add_shuffle(value_tensor)
|
|
shuffle_layer.set_input(1, input_shape_tensor)
|
|
set_layer_name(shuffle_layer, paddle_op)
|
|
start = trt.Dims([0] * ndims)
|
|
size = trt.Dims([1] * ndims)
|
|
stride = trt.Dims([1] * ndims)
|
|
|
|
starts_tensor = add_1D_constant_layer(
|
|
network, [0] * ndims, name=[paddle_op.name(), 'starts_tensor']
|
|
)
|
|
one_tensor = add_1D_constant_layer(
|
|
network, 1, name=[paddle_op.name(), 'one_tensor']
|
|
)
|
|
sizes_tensor = trt_max(
|
|
network,
|
|
input_shape_tensor,
|
|
shape_tensor,
|
|
name=[paddle_op.name(), 'sizes_tensor'],
|
|
)
|
|
input_sub_tensor = trt_sub(
|
|
network,
|
|
input_shape_tensor,
|
|
one_tensor,
|
|
name=[paddle_op.name(), 'input_sub_tensor'],
|
|
)
|
|
strides_tensor = trt_min(
|
|
network,
|
|
one_tensor,
|
|
input_sub_tensor,
|
|
name=[paddle_op.name(), 'strides_tensor'],
|
|
)
|
|
|
|
layer = network.add_slice(shuffle_layer.get_output(0), start, size, stride)
|
|
layer.set_input(1, starts_tensor)
|
|
layer.set_input(2, sizes_tensor)
|
|
layer.set_input(3, strides_tensor)
|
|
set_layer_name(layer, paddle_op)
|
|
|
|
output = layer.get_output(0)
|
|
|
|
if output.dtype != target_dtype:
|
|
output = trt_cast(
|
|
network, output, target_dtype, name=[paddle_op.name(), 'output']
|
|
)
|
|
|
|
return output
|
|
|
|
|
|
@converter_registry.register("pd_op.full_with_tensor")
|
|
def full_with_tensor_converter(network, paddle_op, inputs):
|
|
value_input = inputs[0]
|
|
|
|
shape_tensor = None
|
|
dtype = paddle_op.attrs()["dtype"]
|
|
|
|
operands = paddle_op.operands()
|
|
num_operands = len(operands)
|
|
|
|
if num_operands >= 2:
|
|
shape_tensor = inputs[1]
|
|
if isinstance(shape_tensor, list):
|
|
shape_tensor_list = shape_tensor
|
|
else:
|
|
shape_tensor_list = [shape_tensor]
|
|
|
|
shape_val = get_input_constant_value(paddle_op, inputs, 1)
|
|
if shape_val is not None:
|
|
shape_tensor = shape_val
|
|
else:
|
|
shape_tensor = inputs[1]
|
|
|
|
tensor_rank = 0
|
|
if isinstance(shape_tensor, trt.ITensor):
|
|
shapes_tensor = shape_tensor
|
|
elif isinstance(shape_tensor, (list, tuple)):
|
|
shapes_tensor = shape_tensor
|
|
else:
|
|
raise TypeError(f"Unsupported shape_tensor type: {type(shape_tensor)}")
|
|
|
|
if shape_tensor is not None and len(shape_tensor_list) == 1:
|
|
is_dynamic_shape = True
|
|
elif len(shape_tensor_list) >= 1:
|
|
is_dynamic_shape = True
|
|
else:
|
|
is_dynamic_shape = False
|
|
|
|
if is_dynamic_shape:
|
|
if len(shape_tensor_list) == 1:
|
|
shape_tensor = shape_tensor_list[0]
|
|
if not isinstance(shape_tensor, trt.ITensor):
|
|
raise TypeError("shape_tensor must be an ITensor")
|
|
tensor_rank = shape_tensor.shape[0]
|
|
shapes_tensor = shape_tensor
|
|
else:
|
|
shape_tensors = []
|
|
for tensor in shape_tensor_list:
|
|
if len(tensor.shape) == 0:
|
|
tensor = trt_reshape(
|
|
network, tensor, (1,), name=[paddle_op.name(), "tensor"]
|
|
)
|
|
shape_tensors.append(tensor)
|
|
|
|
concat_layer = network.add_concatenation(shape_tensors)
|
|
set_layer_name(concat_layer, paddle_op)
|
|
shapes_tensor = concat_layer.get_output(0)
|
|
tensor_rank = len(shape_tensors)
|
|
|
|
shapes_tensor = resize_to_1d(
|
|
network, shapes_tensor, name=[paddle_op.name(), "shapes_tensor"]
|
|
)
|
|
fill_layer = network.add_fill(shape=(), op=trt.FillOperation.LINSPACE)
|
|
fill_layer.set_input(0, shapes_tensor)
|
|
|
|
if dtype == paddle.int32 or dtype == paddle.int64:
|
|
beta_vec = [0] * tensor_rank
|
|
value_input = trt_reduce_to_scalar(
|
|
network, value_input, name=[paddle_op.name(), 'value_input']
|
|
)
|
|
fill_layer.set_input(1, value_input)
|
|
fill_layer.set_input(
|
|
2, add_1D_constant_layer(network, beta_vec, np.int32)
|
|
)
|
|
elif dtype == paddle.float32:
|
|
beta_vec = [0.0] * tensor_rank
|
|
value_input = trt_reduce_to_scalar(
|
|
network,
|
|
value_input,
|
|
trt.float32,
|
|
name=[paddle_op.name(), 'value_input'],
|
|
)
|
|
fill_layer.set_input(1, value_input)
|
|
fill_layer.set_input(
|
|
2, add_1D_constant_layer(network, beta_vec, np.float32)
|
|
)
|
|
else:
|
|
raise ValueError(f"Unsupported dtype for full_with_tensor: {dtype}")
|
|
|
|
set_layer_name(fill_layer, paddle_op)
|
|
output_tensor = fill_layer.get_output(0)
|
|
return output_tensor
|
|
|
|
|
|
@converter_registry.register("pd_op.meshgrid")
|
|
def meshgrid_converter(network, paddle_op, vec_inputs):
|
|
inputs = vec_inputs[0]
|
|
n = len(inputs)
|
|
outputs = []
|
|
|
|
# get all input dims (all input is 1-dim)
|
|
input_dims = [network.add_shape(inp).get_output(0) for inp in inputs]
|
|
|
|
for k in range(n):
|
|
# --------------------------------
|
|
# step1:reshape k input as [1,..,Dk,..,1]
|
|
# --------------------------------
|
|
x = inputs[k]
|
|
reshape_dims = [] # init dims as 1
|
|
for i in range(n):
|
|
one = add_1D_constant_layer(
|
|
network,
|
|
1,
|
|
dtype=np.int32,
|
|
is_scalar=False,
|
|
name=[paddle_op.name(), f'one_{k}'],
|
|
)
|
|
reshape_dims.append(one)
|
|
# replace k-th input dim as Dk
|
|
reshape_dims[k] = input_dims[k]
|
|
|
|
dim_concat = network.add_concatenation(reshape_dims)
|
|
set_layer_name(dim_concat, paddle_op)
|
|
x_reshaped = network.add_shuffle(x)
|
|
x_reshaped.set_input(1, dim_concat.get_output(0))
|
|
|
|
# --------------------------------
|
|
# step2: create tensor([D1, D2, ..., 1, ..., Dn]) that filled with 1
|
|
# --------------------------------
|
|
ones_shape = []
|
|
for i in range(n):
|
|
ones_shape.append(input_dims[i])
|
|
ones_shape[k] = add_1D_constant_layer(
|
|
network,
|
|
1,
|
|
dtype=np.int32,
|
|
is_scalar=False,
|
|
name=[paddle_op.name(), f'ones_shape_{k}'],
|
|
)
|
|
dim_concat = network.add_concatenation(ones_shape)
|
|
set_layer_name(dim_concat, paddle_op)
|
|
|
|
# Fill constant 1
|
|
fill_layer = network.add_fill(shape=(), op=trt.FillOperation.LINSPACE)
|
|
fill_layer.set_input(0, dim_concat.get_output(0))
|
|
value_input = add_1D_constant_layer(
|
|
network,
|
|
1,
|
|
dtype=np.float32,
|
|
is_scalar=True,
|
|
name=[paddle_op.name(), 'one_for_fill'],
|
|
)
|
|
fill_layer.set_input(1, value_input)
|
|
beta_vec = [0] * n
|
|
fill_layer.set_input(
|
|
2, add_1D_constant_layer(network, beta_vec, np.float32)
|
|
)
|
|
|
|
# --------------------------------
|
|
# step3: element wise multiplication
|
|
# --------------------------------
|
|
grid = network.add_elementwise(
|
|
x_reshaped.get_output(0),
|
|
fill_layer.get_output(0),
|
|
trt.ElementWiseOperation.PROD,
|
|
).get_output(0)
|
|
outputs.append(grid)
|
|
return outputs
|