Skip to content

Commit d0249d3

Browse files
xiaoxiaohehe001AnnaTrainingG
authored andcommitted
[Paddle Inference]Add split op TRT converter unittest. (PaddlePaddle#35127)
* add_split_op * add_split_teller * add_split_teller * add_split_teller * add_split_teller * add_split_teller * add_split_teller * add_split_teller * add_split_teller * add_split_teller * add_split_teller * add_split_teller * add_split_teller * add_split_teller * add_split_teller * add_split_teller
1 parent ba28504 commit d0249d3

File tree

3 files changed

+303
-28
lines changed

3 files changed

+303
-28
lines changed

paddle/fluid/inference/tensorrt/convert/split_op.cc

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -49,43 +49,21 @@ class SplitOpConverter : public OpConverter {
4949
} else {
5050
axis += (axis < 0) ? input_dims.nbDims : -1;
5151
}
52-
53-
PADDLE_ENFORCE_NE(input_dims.d[axis], -1,
54-
platform::errors::InvalidArgument(
55-
"The (%d) dim of input should not be -1", axis));
5652
if (num > 0) {
5753
int64_t in_axis_dim = input_dims.d[axis];
58-
PADDLE_ENFORCE_EQ(
59-
in_axis_dim % num, 0,
60-
platform::errors::InvalidArgument(
61-
"Invalid number to split. Tensor split does not result"
62-
" in an equal division of dimensions. Axis dim = %d %% num = %d "
63-
"!= 0",
64-
in_axis_dim, num));
6554
size_t out_axis_dim = in_axis_dim / num;
6655
for (int i = 0; i < num; ++i) {
6756
output_lengths.push_back(out_axis_dim);
6857
}
6958
}
7059

71-
PADDLE_ENFORCE_EQ(
72-
output_lengths.size(), output_num,
73-
platform::errors::InvalidArgument(
74-
"The output_length should be equal to the output size."));
75-
7660
nvinfer1::ILayer* layer = nullptr;
7761
if (engine_->with_dynamic_shape()) {
78-
#if IS_TRT_VERSION_GE(6000)
7962
bool with_fp16 =
8063
engine_->WithFp16() && !engine_->disable_trt_plugin_fp16();
8164
plugin::SplitPluginDynamic* plugin =
8265
new plugin::SplitPluginDynamic(axis, output_lengths, with_fp16);
8366
layer = engine_->AddDynamicPlugin(&input, input_num, plugin);
84-
#else
85-
PADDLE_THROW(platform::errors::Fatal(
86-
"You are running the TRT Dynamic Shape mode, need to confirm that "
87-
"your TRT version is no less than 6.0"));
88-
#endif
8967
} else {
9068
bool with_fp16 =
9169
engine_->WithFp16() && !engine_->disable_trt_plugin_fp16();

paddle/fluid/inference/tensorrt/op_teller.cc

Lines changed: 68 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -577,16 +577,78 @@ bool OpTeller::Tell(const framework::ir::Node* node, bool use_no_calib_int8,
577577
<< desc.Input("X").size() << ".";
578578
return false;
579579
}
580+
auto split_inputs = desc.Inputs();
581+
if (split_inputs.find("AxisTensor") != split_inputs.end()) {
582+
if (desc.Input("AxisTensor").size() >= 1) {
583+
return false;
584+
}
585+
}
586+
if (split_inputs.find("SectionsTensorList") != split_inputs.end()) {
587+
if (desc.Input("SectionsTensorList").size() >= 1) {
588+
return false;
589+
}
590+
}
580591
if (!desc.HasAttr("axis")) {
581592
return false;
582-
} else {
583-
int axis = BOOST_GET_CONST(int, desc.GetAttr("axis"));
584-
if (axis == 0) {
585-
VLOG(3) << "Invalid split axis. Split on batch is not supported in "
586-
"TensorRT";
587-
return false;
593+
}
594+
int axis = BOOST_GET_CONST(int, desc.GetAttr("axis"));
595+
596+
if (axis == 0) {
597+
VLOG(3) << "Invalid split axis. Split on batch is not supported in "
598+
"TensorRT";
599+
return false;
600+
}
601+
auto* block = desc.Block();
602+
auto x_var_name = desc.Input("X")[0];
603+
auto* x_var_desc = block->FindVar(x_var_name);
604+
const auto x_shape = x_var_desc->GetShape();
605+
size_t output_num = desc.Output("Out").size();
606+
std::vector<int> output_lengths;
607+
int num = 0;
608+
if (desc.HasAttr("num")) {
609+
num = BOOST_GET_CONST(int, desc.GetAttr("num"));
610+
}
611+
if (desc.HasAttr("sections")) {
612+
output_lengths =
613+
BOOST_GET_CONST(std::vector<int>, desc.GetAttr("sections"));
614+
}
615+
if (output_lengths.size() == 0 && num == 0) {
616+
VLOG(3) << "sections and num cannot be equal to 0 at the same time";
617+
return false;
618+
}
619+
if (with_dynamic_shape) {
620+
#if IS_TRT_VERSION_GE(6000)
621+
#else
622+
VLOG(3) << "You are running the TRT Dynamic Shape mode, need to "
623+
"confirm that "
624+
"your TRT version is no less than 6.0";
625+
return false;
626+
#endif
627+
}
628+
axis += (axis < 0) ? x_shape.size() : 0;
629+
if (x_shape[axis] == -1) {
630+
VLOG(3) << "The (" << axis << ") dim of input should not be -1";
631+
return false;
632+
}
633+
if (output_lengths.size() == 0) {
634+
if (num > 0) {
635+
int64_t in_axis_dim = x_shape[axis];
636+
if (in_axis_dim % num != 0) {
637+
VLOG(3) << "Invalid number to split. Tensor split does not result"
638+
" in an equal division of dimensions. Axis dim = "
639+
<< in_axis_dim << " num = " << num << "!= 0";
640+
return false;
641+
}
642+
size_t out_axis_dim = in_axis_dim / num;
643+
for (int i = 0; i < num; ++i) {
644+
output_lengths.push_back(out_axis_dim);
645+
}
588646
}
589647
}
648+
if (output_lengths.size() != output_num) {
649+
VLOG(3) << "The output_length should be equal to the output size.";
650+
return false;
651+
}
590652
}
591653
if (op_type == "scale") {
592654
auto scale_inputs = desc.Inputs();
Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from trt_layer_auto_scan_test import TrtLayerAutoScanTest, SkipReasons
16+
from program_config import TensorConfig, ProgramConfig
17+
import numpy as np
18+
import paddle.inference as paddle_infer
19+
from functools import partial
20+
from typing import Optional, List, Callable, Dict, Any, Set
21+
22+
23+
class TrtConvertSplitTest(TrtLayerAutoScanTest):
24+
def is_program_valid(self, program_config: ProgramConfig) -> bool:
25+
inputs = program_config.inputs
26+
weights = program_config.weights
27+
outputs = program_config.outputs
28+
29+
attrs = [
30+
program_config.ops[i].attrs
31+
for i in range(len(program_config.ops))
32+
]
33+
# the dimensions of input and axis match
34+
if len(inputs['split_input'].shape) <= attrs[0]['axis']:
35+
return False
36+
37+
#Sections and num cannot both be equal to 0.
38+
if len(attrs[0]['sections']) == 0:
39+
if attrs[0]['num'] == 0:
40+
return False
41+
42+
#When sections and num are not both equal to 0, sections has higher priority.
43+
#The sum of sections should be equal to the input size.
44+
if len(attrs[0]['sections']) != 0:
45+
if attrs[0]['num'] != 0:
46+
return False
47+
if len(outputs) != len(attrs[0]['sections']):
48+
return False
49+
sum = 0
50+
for num in attrs[0]['sections']:
51+
sum += num
52+
if sum != inputs['split_input'].shape[attrs[0]['axis']]:
53+
return False
54+
55+
#The size of num should be equal to the input dimension.
56+
if attrs[0]['num'] != 0:
57+
if len(outputs) != attrs[0]['num']:
58+
return False
59+
60+
#Test AxisTensor and SectionsTensorList
61+
if self.num_input == 0:
62+
if self.dims == 2 and attrs[0]['sections'] == [10, 14] and len(
63+
outputs) == 2:
64+
return True
65+
else:
66+
return False
67+
68+
return True
69+
70+
def sample_program_configs(self):
71+
def generate_input1(attrs: List[Dict[str, Any]], batch):
72+
if self.dims == 4:
73+
return np.ones([batch, 3, 3, 24]).astype(np.float32)
74+
elif self.dims == 3:
75+
return np.ones([batch, 3, 24]).astype(np.float32)
76+
elif self.dims == 2:
77+
return np.ones([batch, 24]).astype(np.float32)
78+
elif self.dims == 1:
79+
return np.ones([24]).astype(np.float32)
80+
81+
def generate_AxisTensor(attrs: List[Dict[str, Any]]):
82+
return np.ones([1]).astype(np.int32)
83+
84+
def generate_SectionsTensorList1(attrs: List[Dict[str, Any]]):
85+
return np.array([10]).astype(np.int32)
86+
87+
def generate_SectionsTensorList2(attrs: List[Dict[str, Any]]):
88+
return np.array([14]).astype(np.int32)
89+
90+
for num_input in [0, 1]:
91+
for dims in [1, 2, 3, 4]:
92+
for batch in [3, 6, 9]:
93+
for Out in [["output_var0", "output_var1"],
94+
["output_var0", "output_var1", "output_var2"]]:
95+
for sections in [[], [1, 2], [2, 1], [10, 14],
96+
[1, 1, 1], [2, 2, 2], [3, 3, 3],
97+
[3, 7, 14]]:
98+
for num in [0, 3]:
99+
for axis in [0, 1, 2, 3]:
100+
self.batch = batch
101+
self.num_input = num_input
102+
self.dims = dims
103+
dics = [{
104+
"sections": sections,
105+
"num": num,
106+
"axis": axis
107+
}, {}]
108+
109+
dics_intput = [{
110+
"X": ["split_input"],
111+
"AxisTensor": ["AxisTensor"],
112+
"SectionsTensorList": [
113+
"SectionsTensorList1",
114+
"SectionsTensorList2"
115+
]
116+
}, {
117+
"X": ["split_input"]
118+
}]
119+
dics_intputs = [{
120+
"AxisTensor":
121+
TensorConfig(data_gen=partial(
122+
generate_AxisTensor, dics)),
123+
"SectionsTensorList1": TensorConfig(
124+
data_gen=partial(
125+
generate_SectionsTensorList1,
126+
dics)),
127+
"SectionsTensorList2":
128+
TensorConfig(data_gen=partial(
129+
generate_SectionsTensorList2, dics))
130+
}, {}]
131+
132+
ops_config = [{
133+
"op_type": "split",
134+
"op_inputs": dics_intput[num_input],
135+
"op_outputs": {
136+
"Out": Out
137+
},
138+
"op_attrs": dics[0]
139+
}]
140+
ops = self.generate_op_config(ops_config)
141+
program_config = ProgramConfig(
142+
ops=ops,
143+
weights=dics_intputs[num_input],
144+
inputs={
145+
"split_input":
146+
TensorConfig(data_gen=partial(
147+
generate_input1, dics, batch))
148+
},
149+
outputs=Out)
150+
151+
yield program_config
152+
153+
def sample_predictor_configs(
154+
self, program_config) -> (paddle_infer.Config, List[int], float):
155+
def generate_dynamic_shape(attrs):
156+
if self.dims == 4:
157+
self.dynamic_shape.min_input_shape = {
158+
"split_input": [1, 3, 3, 24]
159+
}
160+
self.dynamic_shape.max_input_shape = {
161+
"split_input": [9, 3, 3, 24]
162+
}
163+
self.dynamic_shape.opt_input_shape = {
164+
"split_input": [1, 3, 3, 24]
165+
}
166+
elif self.dims == 3:
167+
self.dynamic_shape.min_input_shape = {"split_input": [1, 3, 24]}
168+
self.dynamic_shape.max_input_shape = {"split_input": [9, 3, 24]}
169+
self.dynamic_shape.opt_input_shape = {"split_input": [1, 3, 24]}
170+
elif self.dims == 2:
171+
self.dynamic_shape.min_input_shape = {"split_input": [1, 24]}
172+
self.dynamic_shape.max_input_shape = {"split_input": [9, 24]}
173+
self.dynamic_shape.opt_input_shape = {"split_input": [1, 24]}
174+
elif self.dims == 1:
175+
self.dynamic_shape.min_input_shape = {"split_input": [24]}
176+
self.dynamic_shape.max_input_shape = {"split_input": [24]}
177+
self.dynamic_shape.opt_input_shape = {"split_input": [24]}
178+
179+
def clear_dynamic_shape():
180+
self.dynamic_shape.min_input_shape = {}
181+
self.dynamic_shape.max_input_shape = {}
182+
self.dynamic_shape.opt_input_shape = {}
183+
184+
def generate_trt_nodes_num(attrs, dynamic_shape):
185+
if len(program_config.outputs) == 2:
186+
if attrs[0]['axis'] != 0:
187+
return 1, 3
188+
else:
189+
return 0, 4
190+
else:
191+
if attrs[0]['axis'] != 0:
192+
return 1, 4
193+
else:
194+
return 0, 5
195+
196+
attrs = [
197+
program_config.ops[i].attrs
198+
for i in range(len(program_config.ops))
199+
]
200+
self.trt_param.max_batch_size = 9
201+
# for static_shape
202+
clear_dynamic_shape()
203+
self.trt_param.precision = paddle_infer.PrecisionType.Float32
204+
yield self.create_inference_config(), generate_trt_nodes_num(
205+
attrs, False), 1e-5
206+
self.trt_param.precision = paddle_infer.PrecisionType.Half
207+
yield self.create_inference_config(), generate_trt_nodes_num(
208+
attrs, False), 1e-5
209+
210+
# for dynamic_shape
211+
generate_dynamic_shape(attrs)
212+
self.trt_param.precision = paddle_infer.PrecisionType.Float32
213+
yield self.create_inference_config(), generate_trt_nodes_num(attrs,
214+
True), 1e-5
215+
self.trt_param.precision = paddle_infer.PrecisionType.Half
216+
yield self.create_inference_config(), generate_trt_nodes_num(attrs,
217+
True), 1e-5
218+
219+
def add_skip_trt_case(self):
220+
def teller1(program_config, predictor_config):
221+
if len(program_config.weights) == 3:
222+
return True
223+
return False
224+
225+
self.add_skip_case(
226+
teller1, SkipReasons.TRT_NOT_SUPPORT,
227+
"INPUT AxisTensor AND SectionsTensorList NOT SUPPORT.")
228+
229+
def test(self):
230+
self.add_skip_trt_case()
231+
self.run_test()
232+
233+
234+
if __name__ == "__main__":
235+
unittest.main()

0 commit comments

Comments
 (0)