From 22a20be3c373d578a39e50e7d4f77ac8c258b0bc Mon Sep 17 00:00:00 2001 From: root Date: Tue, 3 Aug 2021 13:49:34 +0000 Subject: [PATCH 001/127] fix some problems for matmul --- python/tvm/relay/frontend/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/python/tvm/relay/frontend/__init__.py b/python/tvm/relay/frontend/__init__.py index aa8ac4fc7434..aa49b63203f2 100644 --- a/python/tvm/relay/frontend/__init__.py +++ b/python/tvm/relay/frontend/__init__.py @@ -31,4 +31,5 @@ from .darknet import from_darknet from .pytorch import from_pytorch from .caffe import from_caffe +from .paddlepaddle import from_paddle from .change_datatype import ChangeDatatype From 1a7f180944949db25ac28eff3f48f2fe4738637b Mon Sep 17 00:00:00 2001 From: root Date: Tue, 3 Aug 2021 13:49:50 +0000 Subject: [PATCH 002/127] fix some problems for matmul --- python/tvm/relay/frontend/paddlepaddle.py | 768 ++++++++++++++++++++++ 1 file changed, 768 insertions(+) create mode 100644 python/tvm/relay/frontend/paddlepaddle.py diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py new file mode 100644 index 000000000000..9326ba8a184e --- /dev/null +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -0,0 +1,768 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. +# pylint: disable=invalid-name, import-self, len-as-condition, unused-argument, too-many-lines +# pylint: disable=import-outside-toplevel +"""Paddle: PArallel Distributed Deep LEarning.""" +import copy +import warnings +import six + +import numpy as np + +import tvm +from tvm.ir import IRModule + +from .. import analysis +from .. import expr as _expr +from .. import function as _function +from .. import ty as _ty +from .. import op as _op +from .common import ( + fold_constant, + infer_shape, + infer_type, + infer_value, + new_var, +) + +__all__ = ["from_paddle"] + + +def shape_of(x, dtype='int32'): + ttype = infer_type(x).checked_type + if not _ty.is_dynamic(ttype): + shape = list(ttype.shape) + return _expr.const(shape, dtype) + return _op.shape_of(x, dtype) + + +def convert_arg_max(g, op, block): + """Operator converter for arg_max.""" + + axis = op.attr('axis') + keepdims = op.attr('keepdims') + flatten = op.attr('flatten') + assert not flatten, "Only flatten==True is supported for PaddlePaddle's arg_max" + + x = g.get_node(x.input('X')[0]) + out = _op.argmax(x, axis=axis, keepdims=keepdims) + g.add_node(op.output('Out')[0], out) + + +def convert_assign(g, op, block): + """Operator converter for assign.""" + + out = _op.copy(g.get_node(op.input('X')[0])) + g.add_node(op.output('Out')[0], out) + + +def convert_batch_norm(g, op, block): + """Operator converter for batch_norm.""" + + ipt_name = op.input('X')[0] + scale_name = op.input('Scale')[0] + bias_name = op.input('Bias')[0] + mean_name = op.input('Mean')[0] + variance_name = op.input('Variance')[0] + epsilon = op.attr('epsilon') + momentum = op.attr('momentum') + out = _op.nn.batch_norm(g.get_node(ipt_name), + g.get_node(scale_name), + g.get_node(bias_name), + g.get_node(mean_name), + g.get_node(variance_name), + epsilon=epsilon) + g.add_node(op.output('Y')[0], out[0]) + + +def convert_cast(g, op, block): + """Operator converter for cast.""" + + dtype = block.var(op.output('Out')[0]).dtype + dtype = str(dtype).strip().split('.')[1] + x = g.get_node(op.input('X')[0]) + out = _op.cast(x, dtype=dtype) + g.add_node(op.output('Out')[0], out) + + +def convert_concat(g, op, block): + """Operator converter for concat.""" + + inputs = [g.get_node(op.input('X')[i]) for i in range(len(op.input('X')))] + axis = op.attr('axis') + out = _op.concatenate(inputs, axis=axis) + g.add_node(op.output('Out')[0], out) + + +def convert_conv2d(g, op, block): + """Operator converter for conv2d.""" + def get_pad_size(in_size, dilated_kernel_size, stride_size): + if stride_size == 1 or in_size & stride_size == 0: + pad = max(dilated_kernel_size - stride_size, 0) + else: + pad = max(dilated_kernel_size - (in_size % stride_size), 0) + return [pad // 2, pad - pad // 2] + + assert op.attr( + 'data_format' + ) == 'NCHW', "Only NCHW format is support for PaddlePaddle's conv2d" + dilations = op.attr('dilations') + groups = op.attr('groups') + paddings = op.attr('paddings') + padding_algorithm = op.attr('padding_algorithm') + strides = op.attr('strides') + + kernel = g.get_node(op.input('Filter')[0]) + input = g.get_node(op.input('Input')[0]) + out_channels, _, k_h, k_w = infer_shape(kernel) + in_h, in_w = infer_shape(input)[2:] + assert len( + paddings + ) == 2, "Only support len(paddings)==2 for PaddlePaddle's conv2d" + assert len( + dilations + ) == 2, "Only support len(dilations)==2 for PaddlePaddle's conv2d" + if padding_algorithm == "SAME": + pad_h = get_pad_size(in_h, (k_h - 1) * dilations[0] + 1, strides[0]) + pad_w = get_pad_size(in_w, (k_w - 1) * dilations[1] + 1, strides[1]) + paddings = [pad_h[0], pad_w[0], pad_h[1], pad_w[1]] + out = _op.nn.conv2d(input, + kernel, + strides=strides, + padding=paddings, + dilation=dilations, + groups=groups, + channels=out_channels, + kernel_size=[k_h, k_w]) + g.add_node(op.output('Output')[0], out) + + +def convert_cumsum(g, op, block): + """Operator converter for cumsum.""" + + axis = op.attr('axis') + exclusive = op.attr('exclusive') + flatten = op.attr('flatten') + reverse = op.attr('reverse') + + assert not flatten, "Only flatten==False is supported for PaddlePaddle's cumsum" + + x = g.get_node(op.input('X')[0]) + if reverse: + x = _op.reverse(x, axis=axis) + out = _op.cumsum(x, axis=axis, exclusive=exclusive) + out = _op.reverse(out, axis=axis) + else: + out = _op.cumsum(x, axis=axis, exclusive=exclusive) + g.add_node(op.output('Out')[0], out) + + +def convert_dropout(g, op, block): + """Operator converter for dropout.""" + + x = g.get_node(op.input('X')[0]) + out = _op.copy(x) + g.add_node(op.output('Out')[0], out) + + +def convert_elementwise_op(g, op, block): + """Operator converter for all the elementwise operators.""" + + op_map = { + 'elementwise_div': lambda x, y: x / y, + 'elementwise_add': lambda x, y: x + y, + 'elementwise_mul': lambda x, y: x * y, + 'elementwise_sub': lambda x, y: x - y, + 'elementwise_mod': lambda x, y: x % y, + } + op_func = op_map[op.type] + ipt0 = g.get_node(op.input('X')[0]) + ipt1 = g.get_node(op.input('Y')[0]) + ipt0_shape = block.var(op.input('X')[0]).shape + ipt1_shape = block.var(op.input('Y')[0]).shape + axis = op.attr('axis') + if len(ipt0_shape) != len(ipt1_shape): + if axis < 0: + axis = axis + len(ipt0_shape) + if axis != len(ipt0_shape) - 1: + ipt1 = _op.expand_dims(ipt1, + axis=axis, + num_newaxis=(len(ipt0_shape) - axis - 1)) + out = op_func(ipt0, ipt1) + g.add_node(op.output('Out')[0], out) + + +def convert_equal(g, op, block): + """Operator converter for equal.""" + + x = g.get_node(op.input('X')[0]) + y = g.get_node(op.input('Y')[0]) + out = _op.equal(x, y) + g.add_node(op.output('Out')[0], out) + + +def convert_activation(g, op, block): + """Operator converter for all the activation.""" + + op_map = { + 'exp': _op.exp, + 'relu': _op.nn.relu, + 'tanh': _op.tanh, + 'sqrt': _op.sqrt, + 'erf': _op.erf, + 'abs': _op.abs, + } + act_func = op_map[op.type] + out = act_func(g.get_node(op.input('X')[0])) + g.add_node(op.output('Out')[0], out) + + +def convert_feed(g, op, block): + """Converter for model input node.""" + + ipt_name = op.output('Out')[0] + ipt_shape = block.var(ipt_name).shape + ipt_dtype = block.var(ipt_name).dtype + ipt_dtype = str(ipt_dtype).strip().split('.')[1] + if g.shape_dict is not None: + ipt_shape = g.shape_dict[ipt_name] + out = new_var(ipt_name, shape=ipt_shape, dtype=ipt_dtype) + g.add_node(ipt_name, out) + + +def convert_fill_any_like(g, op, block): + """Operator converter for fill_any_like.""" + + out_name = op.output('Out')[0] + out_dtype = block.var(out_name).dtype + out_dtype = str(out_dtype).strip().split('.')[1] + x = g.get_node(op.input('X')[0]) + ipt_shape = infer_shape(x) + if not is_fixed_shape(ipt_shape): + msg = "Only support fixed input shape of PaddlePaddle's fill_any_like" + raise tvm.error.OpNotImplemented(msg) + value = op.attr('value') + const = np.ones(ipt_shape) * value + out = _expr.const(const.astype(out_dtype)) + g.add_node(op.output('Out')[0], out) + + +def convert_fill_constant(g, op, block): + """Operator converter for fill_constant.""" + + value = op.attr('value') + shape = block.var(op.output('Out')[0]).shape + dtype = block.var(op.output('Out')[0]).dtype + dtype = str(dtype).strip().split('.')[1] + value = np.full(shape, value, dtype) + out = _expr.const(value.astype(dtype)).astype(dtype) + g.add_node(op.output('Out')[0], out) + + +def convert_gelu(g, op, block): + """Operator converter for gelu.""" + + x = g.get_node(op.input('X')[0]) + out = x * (_expr.const(0.5, dtype='float32') + + _op.erf(x * _expr.const(0.5**0.5, dtype='float32')) * + _expr.const(0.5, dtype='float32')) + g.add_node(op.output('Out')[0], out) + + +def convert_hard_sigmoid(g, op, block): + """Operator converter for hard_sigmoid.""" + + slope = op.attr('slope') + offset = op.attr('offset') + x = g.get_node(op.input('X')[0]) + out = x * _expr.const(slope) + _expr.const(0.5) + out = _op.clip(out, 0, 1) + g.add_node(op.output('Out')[0], out) + + +def convert_hard_swish(g, op, block): + """Operator converter for hard_swish.""" + + offset = op.attr('offset') + scale = op.attr('scale') + threshold = op.attr('threshold') + assert np.isclose( + offset, 3.0), "Only support offset==3.0 for PaddlePaddle's hard_swish" + assert np.isclose( + scale, 6.0), "Only support scale==6.0 for PaddlePaddle's hard_swish" + assert np.isclose( + threshold, + 6.0), "Only support threshold==6.0 for PaddlePaddle's hard_swish" + x = g.get_node(op.input('X')[0]) + out = _op.clip(x, -1 * offset, offset) + out = out / _expr.const(threshold) + _expr.const(0.5) + out = x * out + g.add_node(op.output('Out')[0], out) + + +def convert_layer_norm(g, op, block): + """Operator converter for layer_norm.""" + + begin_norm_axis = op.attr('begin_norm_axis') + epsilon = op.attr('epsilon') + x = g.get_node(op.input('X')[0]) + bias = g.get_node(op.input('Bias')[0]) + scale = g.get_node(op.input('Scale')[0]) + out = _op.nn.layer_norm(x, + gamma=scale, + beta=bias, + axis=begin_norm_axis, + epsilon=epsilon, + center=True, + scale=True) + g.add_node(op.output('Y')[0], out) + + +def convert_leaky_relu(g, op, block): + """Operator converter for leaky_relu.""" + + alpha = op.attr('alpha') + x = g.get_node(op.input('X')[0]) + out = _op.nn.leaky_relu(x, alpha=alpha) + g.add_node(op.output('Out')[0]) + + +def convert_lookup_table(g, op, block): + """Operator converter for lookup_table_v2.""" + + indices = g.get_node(op.input('Ids')[0]) + padding_idx = op.attr('padding_idx') + is_sparse = op.attr('is_sparse') + height_sections = op.attr('height_sections') + if padding_idx != -1: + g.get_params[op.input('W')[0]][padding_idx] = 0.0 + g.add_node(op.input('W')[0], _expr.const(g.params[op.input('W')[0]])) + weights = g.get_node(op.input('W')[0]) + out = _op.take(weights, indices.astype('int32'), axis=0) + g.add_node(op.output('Out')[0], out) + + +def convert_matmul(g, op, block): + """Operator converter for matmul.""" + + inputs = [g.get_node(op.input('X')[0]), g.get_node(op.input('Y')[0])] + a_shape = infer_shape(inputs[0]) + b_shape = infer_shape(inputs[1]) + try: + # for matmul_v2 + trans_x = op.attr('trans_x') + trans_y = op.attr('trans_y') + except: + # for matmul + trans_x = op.attr('transpose_X') + trans_y = op.attr('transpose_Y') + if trans_x: + perm = list(range(len(a_shape))) + perm[-2] = len(a_shape) - 1 + perm[-1] = len(a_shape) - 2 + inputs[0] = _op.transpose(inputs[0], axes=perm) + if trans_y: + perm = list(range(len(b_shape))) + perm[-2] = len(b_shape) - 1 + perm[-1] = len(b_shape) - 2 + inputs[1] = _op.transpose(inputs[1], axes=perm) + + # This implemention almost keeps same with ONNX + # Need to check input shape as batch matmul must be supported. + a_shape = shape_of(inputs[0]) + a_rank = infer_shape(a_shape)[0] + b_shape = shape_of(inputs[1]) + b_rank = infer_shape(b_shape)[0] + # When performing a batch matmul, we need to properly handle N-dim shapes. + if a_rank > 2 or b_rank > 2: + + def flatten_to_nd(x, x_shape, nd=3): + ndims = infer_shape(x_shape)[0] + if ndims == nd: + return x + newshape = _op.concatenate( + [ + _expr.const([-1], + dtype=infer_type(x_shape).checked_type.dtype), + _op.strided_slice(x_shape, [ndims - nd + 1], [ndims]), + ], + 0, + ) + out = _op.reshape(x, fold_constant(newshape)) + return out + + b_type = infer_type(inputs[1]) + # Convert to dense if the second matrix is 2d and non-dynamic + if b_rank == 2 and not _ty.is_dynamic(b_type.checked_type): + a = flatten_to_nd(inputs[0], a_shape, 2) + b = _op.transpose(inputs[1]) + output = _op.nn.dense(a, b) + else: + # Convert a and b into 3 dimensional tensors. + a = flatten_to_nd(inputs[0], a_shape, 3) + b = flatten_to_nd(inputs[1], b_shape, 3) + # Transpose matrix dimensions of b. + b = _op.transpose(b, [0, 2, 1]) + # Perform a batch matmul. + output = _op.nn.batch_matmul(a, b) + # Determine the output batch dimension. + if a_rank > b_rank: + out_batch = _op.strided_slice(a_shape, [0], [a_rank - 2]) + elif a_rank < b_rank: + out_batch = _op.strided_slice(b_shape, [0], [b_rank - 2]) + # If its unclear how broadcasting should be applied, the output + # shape is determined by choosing the maximum value from each input. + else: + out_batch = _op.concatenate( + [ + _op.maximum( + _op.strided_slice(a_shape, [i], [i + 1]), + _op.strided_slice(b_shape, [i], [i + 1]), + ) for i in range(a_rank - 2) + ], + 0, + ) + # Reshape output to original dimensions. + final_shape = _op.concatenate( + [ + out_batch, + _op.strided_slice(a_shape, [infer_shape(a_shape)[0] - 2], + [infer_shape(a_shape)[0] - 1]), + _op.strided_slice(b_shape, [infer_shape(b_shape)[0] - 1], + [infer_shape(b_shape)[0]]), + ], + 0, + ) + out = _op.reshape(output, fold_constant(final_shape)) + g.add_node(op.output('Out')[0], out) + return + # Otherwise a simple dense op will get the job done. + input_1_t = _op.transpose(inputs[1], axes=(1, 0)) + out = _op.nn.dense(inputs[0], input_1_t) + g.add_node(op.output('Out')[0], out) + + +def convert_pool2d(g, op, block): + """Operator converter for pool2d.""" + + layout = op.attr('data_format') + assert layout == 'NCHW', "Only support NCHW format for PaddlePaddle's pool2d." + adaptive = op.attr('adaptive') + ceil_mode = op.attr('ceil_mode') + exclusive = op.attr('exclusive') + global_pooling = op.attr('global_pooling') + ksize = op.attr('ksize') + paddings = op.attr('paddings') + padding_algorithm = op.attr('padding_algorithm') + pooling_type = op.attr('pooling_type') + + op_map = { + 'avg': 'avg_pool2d', + 'max': 'max_pool2d', + } + strides = op.attr('strides') + assert exclusive, "Only support exclusive==True for PaddlePaddle's pool2d" + assert padding_algorithm == "EXPLICIT", "Only support padding_algorithm==EXPLICIT for PaddlePaddle's pool2d" + if isinstance(strides, int): + strides = [strides, strides] + if isinstance(ksize, int): + ksize = [ksize, ksize] + if isinstance(paddings, six.string_types): + msg = "Setting paddings to `SAME` or `VALID` is not support for PaddlePaddle's pool2d" + raise tvm.error.OpNotImplemented(msg) + elif isinstance(paddings, int): + paddings = [paddings] * 2 + elif len(paddings) == 2: + pass + elif len(paddings) == 4: + msg = "Only support length of paddings equals to 2 for PaddlePaddle's pool2d" + raise tvm.error.OpNotImplemented(msg) + + x = g.get_node(op.input('X')[0]) + if not adaptive: + out = getattr(_op.nn, op_map[pooling_type])(x, + pool_size=ksize, + strides=strides, + padding=paddings, + ceil_mode=ceil_mode) + else: + out = getattr(_op.nn, + "adaptive_" + op_map[pooling_type])(x, output_size=ksize) + g.add_node(op.output('Out')[0], out) + + +def convert_reshape(g, op, block): + """Operator converter for reshape.""" + + shape = op.attr('shape') + out = _op.reshape(g.get_node(op.input('X')[0]), shape) + g.add_node(op.output('Out')[0], out) + + +def convert_scale(g, op, block): + """Operator converter for scale.""" + + scale = op.attr('scale') + bias = op.attr('bias') + bias_after_scale = op.attr('bias_after_scale') + x = g.get_node(op.input('X')[0]) + if np.isclose(scale, 1.0) and np.isclose(bias, 0.0): + out = _op.copy(x) + else: + if np.isclose(bias, 0.0): + out = x * _expr.const(np.array(scale).astype('float32')) + elif np.isclose(scale, 1.0): + out = x + _expr.const(np.array(bias).astype('float32')) + else: + if bias_after_scale: + out = x * _expr.const( + np.array(scale).astype('float32')) + _expr.const( + np.array(bias).astype('float32')) + else: + out = (x + _expr.const(np.array(bias).astype('float32')) + ) * _expr.const(np.array(scale).astype('float32')) + g.add_node(op.output('Out')[0], out) + + +def convert_shape(g, op, block): + """Operator converter for shape.""" + + x = g.get_node(op.input('Input')[0]) + out = shape_of(x) + g.add_node(op.output('Out')[0], out) + + +def convert_slice(g, op, block): + """Operator converter for slice.""" + def parameter_process(starts, ends, axes): + new_axes = [] + new_starts = [] + new_ends = [] + pop_index = 0 + for i in range(max(axes) + 1): + new_axes.append(i) + if i in axes: + new_starts.append(starts[pop_index]) + new_ends.append(ends[pop_index]) + pop_index += 1 + else: + new_starts.append(0) + new_ends.append(np.iinfo(np.int32).max) + return new_starts, new_ends, new_axes + + starts = op.attr('starts') + ends = op.attr('ends') + axes = op.attr('axes') + if isinstance(starts, int): + starts = [starts] + if isinstance(ends, int): + ends = [ends] + if isinstance(axes, int): + axes = [axes] + starts, ends, axes = parameter_process(starts, ends, axes) + out = _op.strided_slice(g.get_node(op.input('Input')[0]), + begin=starts, + end=ends) + g.add_node(op.output('Out')[0], out) + + +def convert_softmax(g, op, block): + """Operator converter for softmax.""" + + axis = op.attr('axis') + input_shape = block.var(op.input('X')[0]).shape + if axis < 0: + axis = len(input_shape) + axis + x = g.get_node(op.input('X')[0]) + m = _op.max(x, axis, keepdims=True) + e = _op.exp(x - m) + out = e / _op.sum(e, axis, keepdims=True) + g.add_node(op.output('Out')[0], out) + + +def convert_transpose(g, op, block): + """Operator converter for transpose.""" + + perm = op.attr('axis') + out = _op.transpose(g.get_node(op.input('X')[0]), axes=perm) + g.add_node(op.output('Out')[0], out) + + +def convert_unsqueeze(g, op, block): + """Operator converter for unsqueeze.""" + + x = g.get_node(op.input('X')[0]) + axes = sorted(op.attr('axes')) + for axis in axes: + x = _op.expand_dims(x, axis=axis, num_newaxis=1) + g.add_node(op.output('Out')[0], x) + + +_convert_map = { + 'arg_max': convert_arg_max, + 'assign': convert_assign, + 'batch_norm': convert_batch_norm, + 'cast': convert_cast, + 'concat': convert_concat, + 'conv2d': convert_conv2d, + 'cumsum': convert_cumsum, + 'depthwise_conv2d': convert_conv2d, + 'dropout': convert_dropout, + 'elementwise_add': convert_elementwise_op, + 'elementwise_div': convert_elementwise_op, + 'elementwise_mul': convert_elementwise_op, + 'elementwise_sub': convert_elementwise_op, + 'equal': convert_equal, + 'exp': convert_activation, + 'feed': convert_feed, + 'fill_any_like': convert_fill_any_like, + 'fill_constant': convert_fill_constant, + 'gelu': convert_gelu, + 'hard_sigmoid': convert_hard_sigmoid, + 'hard_swish': convert_hard_swish, + 'layer_norm': convert_layer_norm, + 'leaky_relu': convert_leaky_relu, + 'lookup_table_v2': convert_lookup_table, + 'matmul': convert_matmul, + 'matmul_v2': convert_matmul, + 'pool2d': convert_pool2d, + 'relu': convert_activation, + 'reshape2': convert_reshape, + 'scale': convert_scale, + 'shape': convert_shape, + 'slice': convert_slice, + 'softmax': convert_softmax, + 'tanh': convert_activation, + 'transpose2': convert_transpose, + 'unsqueeze2': convert_unsqueeze, +} + + +class GraphProto(object): + """ A helper class for handling relay functions from PaddlePaddle model.""" + def __init__(self): + self.nodes = {} + self.params = {} + self.shape_dict = None + + def get_node(self, name): + assert name in self.nodes + return self.nodes[name] + + def add_node(self, name, node): + self.nodes[name] = fold_constant(node) + + def get_params(self, name): + assert name in self.params + return self.params[name] + + def extract_parameters(self, program, scope): + """ Extract all the weights from PaddlePaddle program.""" + + self.params = {} + variables = program.global_block().vars + for name in variables: + var = program.global_block().var(name) + if name.endswith('feed') or name.endswith('fetch'): + continue + if not var.persistable: + continue + if isinstance(scope, dict): + self.params[name] = scope[name] + else: + self.params[name] = np.array(scope.var(name).get_tensor()) + self.nodes[name] = _expr.const(self.params[name]) + + def check_input_shape(self, op, block): + """ Check the shape information of model's inputs, fixed shape is recommended.""" + + ipt_name = op.input(op.input_names[0]) + ipt_shape = block.var(ipt_name).shape + for i in ipt_shape: + if i < 0: + warning_msg = ( + "Input {}(shape={}) has unkown dimension shapes. Specifying static values may improve performance" + .format(ipt_name, ipt_shape)) + warings.warn(warning_msg) + + def check_unsupported_ops(self, program): + """ Check whether all the operators are supported.""" + + unsupported_ops = set() + for block in program.blocks: + for i, op in enumerate(block.ops): + if op.type == 'fetch': + continue + if op.type not in _convert_map: + unsupported_ops.add(op.type) + if len(unsupported_ops) > 0: + msg = "The following operators are not supported for frontend Paddle: " + msg += ", ".join(unsupported_ops) + raise tvm.error.OpNotImplemented(msg) + + def ops_to_relay(self, program, scope): + """ Convert PaddlePaddle operators to TVM relay functions.""" + + for block in program.blocks: + for i, op in enumerate(block.ops): + if op.type == 'fetch': + continue + convert_func = _convert_map[op.type] + convert_func(self, op, block) + + def get_outputs(self, program): + """ Get outputs of PaddlePaddle model.""" + + outputs = list() + for block in program.blocks: + for i, op in enumerate(block.ops): + if op.type == "fetch": + outputs.append(op.input('X')[0]) + return outputs + + def from_paddle(self, program, shape_dict, scope): + """ Construct the TVM relay expression from PaddlePaddle program.""" + + self.shape_dict = shape_dict + if scope is None: + import paddle + scope = paddle.fluid.global_scope() + self.check_unsupported_ops(program) + self.extract_parameters(program, scope) + self.ops_to_relay(program, scope) + output_names = self.get_outputs(program) + + outputs = [self.nodes[name] for name in output_names] + outputs = outputs[0] if len(outputs) == 1 else _expr.Tuple(outputs) + + free_vars = analysis.free_vars(outputs) + func = _function.Function(free_vars, outputs) + mod = IRModule.from_expr(func) + return mod, self.params + + +def from_paddle(program, shape_dict=None, scope=None): + """ Convert a PaddlePaddle model into an equivalent Relay Function. + + PaddlePaddle Program represent the computation graph of PaddlePaddle model, + and PaddlePaddle scope stores all the weights of PaddlePaddle model. + """ + + import paddle + g = GraphProto() + mod, params = g.from_paddle(program, shape_dict, scope) + return mod, params From 3f604e925f04415ebc1bfae3e6a13b4014113bc2 Mon Sep 17 00:00:00 2001 From: root Date: Wed, 4 Aug 2021 03:01:45 +0000 Subject: [PATCH 003/127] add alpha parameter for matmul --- python/tvm/relay/frontend/paddlepaddle.py | 28 ++++++++++++++--------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 9326ba8a184e..87a8679adcc2 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -251,13 +251,14 @@ def convert_fill_any_like(g, op, block): out_dtype = block.var(out_name).dtype out_dtype = str(out_dtype).strip().split('.')[1] x = g.get_node(op.input('X')[0]) - ipt_shape = infer_shape(x) - if not is_fixed_shape(ipt_shape): - msg = "Only support fixed input shape of PaddlePaddle's fill_any_like" - raise tvm.error.OpNotImplemented(msg) + ipt_type = infer_type(x).checked_type value = op.attr('value') - const = np.ones(ipt_shape) * value - out = _expr.const(const.astype(out_dtype)) + if not _ty.is_dynamic(ipt_type): + shape = infer_shape(x) + const = np.ones(shape) * value + out = _expr.const(const.astype(out_dtype)) + else: + out = _op.transform.full_like(x, value).astype(out_dtype) g.add_node(op.output('Out')[0], out) @@ -448,11 +449,16 @@ def flatten_to_nd(x, x_shape, nd=3): 0, ) out = _op.reshape(output, fold_constant(final_shape)) - g.add_node(op.output('Out')[0], out) - return - # Otherwise a simple dense op will get the job done. - input_1_t = _op.transpose(inputs[1], axes=(1, 0)) - out = _op.nn.dense(inputs[0], input_1_t) + else: + # Otherwise a simple dense op will get the job done. + input_1_t = _op.transpose(inputs[1], axes=(1, 0)) + out = _op.nn.dense(inputs[0], input_1_t) + try: + alpha = op.attr('alpha') + if not np.isclose(alpha, 1.0): + out = out * _expr.const(alpha).astype('float32') + except: + pass g.add_node(op.output('Out')[0], out) From fe6de07603bebbb7adb05df1f8dc89b5453562f3 Mon Sep 17 00:00:00 2001 From: root Date: Wed, 4 Aug 2021 06:11:48 +0000 Subject: [PATCH 004/127] remove unnecessary condition --- python/tvm/relay/frontend/paddlepaddle.py | 28 +---------------------- 1 file changed, 1 insertion(+), 27 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 87a8679adcc2..e2beb3a15b0b 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -117,9 +117,6 @@ def get_pad_size(in_size, dilated_kernel_size, stride_size): pad = max(dilated_kernel_size - (in_size % stride_size), 0) return [pad // 2, pad - pad // 2] - assert op.attr( - 'data_format' - ) == 'NCHW', "Only NCHW format is support for PaddlePaddle's conv2d" dilations = op.attr('dilations') groups = op.attr('groups') paddings = op.attr('paddings') @@ -130,16 +127,6 @@ def get_pad_size(in_size, dilated_kernel_size, stride_size): input = g.get_node(op.input('Input')[0]) out_channels, _, k_h, k_w = infer_shape(kernel) in_h, in_w = infer_shape(input)[2:] - assert len( - paddings - ) == 2, "Only support len(paddings)==2 for PaddlePaddle's conv2d" - assert len( - dilations - ) == 2, "Only support len(dilations)==2 for PaddlePaddle's conv2d" - if padding_algorithm == "SAME": - pad_h = get_pad_size(in_h, (k_h - 1) * dilations[0] + 1, strides[0]) - pad_w = get_pad_size(in_w, (k_w - 1) * dilations[1] + 1, strides[1]) - paddings = [pad_h[0], pad_w[0], pad_h[1], pad_w[1]] out = _op.nn.conv2d(input, kernel, strides=strides, @@ -465,11 +452,8 @@ def flatten_to_nd(x, x_shape, nd=3): def convert_pool2d(g, op, block): """Operator converter for pool2d.""" - layout = op.attr('data_format') - assert layout == 'NCHW', "Only support NCHW format for PaddlePaddle's pool2d." adaptive = op.attr('adaptive') ceil_mode = op.attr('ceil_mode') - exclusive = op.attr('exclusive') global_pooling = op.attr('global_pooling') ksize = op.attr('ksize') paddings = op.attr('paddings') @@ -481,22 +465,12 @@ def convert_pool2d(g, op, block): 'max': 'max_pool2d', } strides = op.attr('strides') - assert exclusive, "Only support exclusive==True for PaddlePaddle's pool2d" - assert padding_algorithm == "EXPLICIT", "Only support padding_algorithm==EXPLICIT for PaddlePaddle's pool2d" if isinstance(strides, int): strides = [strides, strides] if isinstance(ksize, int): ksize = [ksize, ksize] - if isinstance(paddings, six.string_types): - msg = "Setting paddings to `SAME` or `VALID` is not support for PaddlePaddle's pool2d" - raise tvm.error.OpNotImplemented(msg) - elif isinstance(paddings, int): + if isinstance(paddings, int): paddings = [paddings] * 2 - elif len(paddings) == 2: - pass - elif len(paddings) == 4: - msg = "Only support length of paddings equals to 2 for PaddlePaddle's pool2d" - raise tvm.error.OpNotImplemented(msg) x = g.get_node(op.input('X')[0]) if not adaptive: From dfb9cb1e12f267fecea546002ef038bb84c3431d Mon Sep 17 00:00:00 2001 From: root Date: Wed, 4 Aug 2021 12:55:04 +0000 Subject: [PATCH 005/127] add TranslatedLayer which support model loaded by jit.load --- python/tvm/relay/frontend/paddlepaddle.py | 79 ++++++++++++++++------- 1 file changed, 57 insertions(+), 22 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index e2beb3a15b0b..b517ab1969a3 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -221,10 +221,15 @@ def convert_activation(g, op, block): def convert_feed(g, op, block): """Converter for model input node.""" - ipt_name = op.output('Out')[0] - ipt_shape = block.var(ipt_name).shape - ipt_dtype = block.var(ipt_name).dtype - ipt_dtype = str(ipt_dtype).strip().split('.')[1] + if block is not None: + ipt_shape = block.var(ipt_name).shape + ipt_dtype = block.var(ipt_name).dtype + ipt_dtype = str(ipt_dtype).strip().split('.')[1] + ipt_name = op.output('Out')[0] + else: + ipt_shape = op.shape + ipt_dtype = str(op.dtype).strip().split('.')[1] + ipt_name = op.name if g.shape_dict is not None: ipt_shape = g.shape_dict[ipt_name] out = new_var(ipt_name, shape=ipt_shape, dtype=ipt_dtype) @@ -650,7 +655,7 @@ def get_params(self, name): assert name in self.params return self.params[name] - def extract_parameters(self, program, scope): + def extract_parameters(self, program, scope=None): """ Extract all the weights from PaddlePaddle program.""" self.params = {} @@ -694,9 +699,12 @@ def check_unsupported_ops(self, program): msg += ", ".join(unsupported_ops) raise tvm.error.OpNotImplemented(msg) - def ops_to_relay(self, program, scope): + def ops_to_relay(self, program, input_specs=None): """ Convert PaddlePaddle operators to TVM relay functions.""" + if input_specs is not None: + for input_spec in input_specs: + convert_feed(self, input_spec, None) for block in program.blocks: for i, op in enumerate(block.ops): if op.type == 'fetch': @@ -704,17 +712,7 @@ def ops_to_relay(self, program, scope): convert_func = _convert_map[op.type] convert_func(self, op, block) - def get_outputs(self, program): - """ Get outputs of PaddlePaddle model.""" - - outputs = list() - for block in program.blocks: - for i, op in enumerate(block.ops): - if op.type == "fetch": - outputs.append(op.input('X')[0]) - return outputs - - def from_paddle(self, program, shape_dict, scope): + def from_program(self, program, shape_dict, scope): """ Construct the TVM relay expression from PaddlePaddle program.""" self.shape_dict = shape_dict @@ -723,8 +721,37 @@ def from_paddle(self, program, shape_dict, scope): scope = paddle.fluid.global_scope() self.check_unsupported_ops(program) self.extract_parameters(program, scope) - self.ops_to_relay(program, scope) - output_names = self.get_outputs(program) + self.ops_to_relay(program) + + output_names = list() + for block in program.blocks: + for i, op in enumerate(block.ops): + if op.type == "fetch": + output_names.append(op.input('X')[0]) + + outputs = [self.nodes[name] for name in output_names] + outputs = outputs[0] if len(outputs) == 1 else _expr.Tuple(outputs) + + free_vars = analysis.free_vars(outputs) + func = _function.Function(free_vars, outputs) + mod = IRModule.from_expr(func) + return mod, self.params + + def from_translated_layer(self, layer, shape_dict): + """ Construct the TVM relay expression from PaddlePaddle TranslatedLayer.""" + + self.shape_dict = shape_dict + program = layer.program() + parameters = dict() + for param in layer.parameters(): + parameters[param.name] = np.array(param.value().get_tensor()) + self.check_unsupported_ops(program) + self.extract_parameters(program, parameters) + + input_specs = layer._input_spec() + self.ops_to_relay(program, input_specs) + + output_names = [x.name for x in layer._output_spec()] outputs = [self.nodes[name] for name in output_names] outputs = outputs[0] if len(outputs) == 1 else _expr.Tuple(outputs) @@ -735,14 +762,22 @@ def from_paddle(self, program, shape_dict, scope): return mod, self.params -def from_paddle(program, shape_dict=None, scope=None): +def from_paddle(program_or_layer, shape_dict=None, scope=None): """ Convert a PaddlePaddle model into an equivalent Relay Function. - PaddlePaddle Program represent the computation graph of PaddlePaddle model, + PaddlePaddle Program/TranslatedLayer represent the computation graph of PaddlePaddle model, and PaddlePaddle scope stores all the weights of PaddlePaddle model. """ import paddle g = GraphProto() - mod, params = g.from_paddle(program, shape_dict, scope) + if isinstance(program_or_layer, paddle.fluid.dygraph.TranslatedLayer): + # model is loaded by `paddle.jit.load` + mod, params = g.from_translated_layer(program_or_layer, shape_dict) + elif isinstance(program_or_layer, paddle.fluid.framework.Program): + # model is loaded by `paddle.static.load_inference_model` + mod, params = g.from_program(program_or_layer, shape_dict, scope) + else: + raise Exception( + "Only PaddlePaddle's Program and TranslatedLayer are supported.") return mod, params From 36ab16e8a58ffabb918bbe5d0f7debd9eb5c9743 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 5 Aug 2021 02:56:19 +0000 Subject: [PATCH 006/127] add mul operator support --- python/tvm/relay/frontend/paddlepaddle.py | 55 ++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index b517ab1969a3..54c72ff9d628 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -222,10 +222,10 @@ def convert_feed(g, op, block): """Converter for model input node.""" if block is not None: + ipt_name = op.output('Out')[0] ipt_shape = block.var(ipt_name).shape ipt_dtype = block.var(ipt_name).dtype ipt_dtype = str(ipt_dtype).strip().split('.')[1] - ipt_name = op.output('Out')[0] else: ipt_shape = op.shape ipt_dtype = str(op.dtype).strip().split('.')[1] @@ -454,6 +454,55 @@ def flatten_to_nd(x, x_shape, nd=3): g.add_node(op.output('Out')[0], out) +def convert_mul(g, op, block): + """Operator converter for mul.""" + + x = g.get_node(op.input('X')[0]) + y = g.get_node(op.input('Y')[0]) + x_num_col_dims = op.attr('x_num_col_dims') + y_num_col_dims = op.attr('y_num_col_dims') + x_shape = shape_of(x) + y_shape = shape_of(y) + x_dim = infer_shape(x_shape)[0] + y_dim = infer_shape(y_shape)[0] + if x_num_col_dims < 0: + x_num_col_dims += x_dim + if y_num_col_dims < 0: + y_num_col_dims += y_dim + if x_num_col_dims == 1: + x = _op.nn.batch_flatten(x) + else: + pre_shape = _op.prod(_op.strided_slice(x_shape, [0], [x_num_col_dims], + [1]), + keepdims=True) + post_shape = _op.prod(_op.strided_slice(x_shape, [x_num_col_dims], + [x_dim], [1]), + keepdims=True) + new_shape = _op.concatenate([pre_shape, post_shape], axis=0) + new_shape = fold_constant(new_shape) + x = _op.reshape(x, new_shape) + if y_num_col_dims == 1: + y = _op.nn.batch_flatten(y) + else: + pre_shape = _op.prod(_op.strided_slice(y_shape, [0], [y_num_col_dims], + [1]), + keepdims=True) + post_shape = _op.prod(_op.strided_slice(y_shape, [y_num_col_dims], + [y_dim], [1]), + keepdims=True) + new_shape = _op.concatenate([pre_shape, post_shape], axis=0) + new_shape = fold_constant(new_shape) + y = _op.reshape(y, new_shape) + y = _op.transpose(y) + out = _op.nn.dense(x, y) + out_pre_shape = _op.strided_slice(x_shape, [0], [x_num_col_dims], [1]) + out_post_shape = _op.strided_slice(y_shape, [y_num_col_dims], [y_dim], [1]) + out_shape = _op.concatenate([out_pre_shape, out_post_shape], axis=0) + out_shape = fold_constant(out_shape) + out = _op.reshape(out, out_shape) + g.add_node(op.output('Out')[0], out) + + def convert_pool2d(g, op, block): """Operator converter for pool2d.""" @@ -464,6 +513,9 @@ def convert_pool2d(g, op, block): paddings = op.attr('paddings') padding_algorithm = op.attr('padding_algorithm') pooling_type = op.attr('pooling_type') + if global_pooling: + adaptive = True + ksize = [1, 1] op_map = { 'avg': 'avg_pool2d', @@ -624,6 +676,7 @@ def convert_unsqueeze(g, op, block): 'lookup_table_v2': convert_lookup_table, 'matmul': convert_matmul, 'matmul_v2': convert_matmul, + 'mul': convert_mul, 'pool2d': convert_pool2d, 'relu': convert_activation, 'reshape2': convert_reshape, From 63b0138e6f431fa6f5634594308b724e8f71d6cd Mon Sep 17 00:00:00 2001 From: wjj19950828 Date: Thu, 5 Aug 2021 11:37:52 +0800 Subject: [PATCH 007/127] Add padding mode support for conv/pool2d --- python/tvm/relay/frontend/paddlepaddle.py | 46 +++++++++++++++++++---- 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index e2beb3a15b0b..397b7dfb39f4 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -50,6 +50,18 @@ def shape_of(x, dtype='int32'): return _op.shape_of(x, dtype) +def _get_pad_size(in_size, dilated_kernel_size, stride_size): + if stride_size == 1 or in_size % stride_size == 0: + pad = max(dilated_kernel_size - stride_size, 0) + else: + pad = max(dilated_kernel_size - (in_size % stride_size), 0) + + pad_before = pad // 2 + pad_after = pad - pad_before + + return [pad_before, pad_after] + + def convert_arg_max(g, op, block): """Operator converter for arg_max.""" @@ -110,13 +122,6 @@ def convert_concat(g, op, block): def convert_conv2d(g, op, block): """Operator converter for conv2d.""" - def get_pad_size(in_size, dilated_kernel_size, stride_size): - if stride_size == 1 or in_size & stride_size == 0: - pad = max(dilated_kernel_size - stride_size, 0) - else: - pad = max(dilated_kernel_size - (in_size % stride_size), 0) - return [pad // 2, pad - pad // 2] - dilations = op.attr('dilations') groups = op.attr('groups') paddings = op.attr('paddings') @@ -127,6 +132,16 @@ def get_pad_size(in_size, dilated_kernel_size, stride_size): input = g.get_node(op.input('Input')[0]) out_channels, _, k_h, k_w = infer_shape(kernel) in_h, in_w = infer_shape(input)[2:] + if padding_algorithm == "VALID": + paddings = [0, 0] + elif padding_algorithm == "SAME": + pad_h = _get_pad_size(in_h, (k_h - 1) * dilations[0] + 1, strides[0]) + pad_w = _get_pad_size(in_w, (k_w - 1) * dilations[1] + 1, strides[1]) + paddings = [pad_h[0], pad_w[0], pad_h[1], pad_w[1]] + else: + msg = 'Value {} in attribute "padding" of operator Conv is not ' "valid." + raise tvm.error.OpAttributeInvalid(msg.format(padding_algorithm)) + out = _op.nn.conv2d(input, kernel, strides=strides, @@ -459,6 +474,12 @@ def convert_pool2d(g, op, block): paddings = op.attr('paddings') padding_algorithm = op.attr('padding_algorithm') pooling_type = op.attr('pooling_type') + if global_pooling: + adaptive = True + ksize = [1, 1] + + input = g.get_node(op.input('X')[0]) + in_h, in_w = infer_shape(input)[2:] op_map = { 'avg': 'avg_pool2d', @@ -472,6 +493,16 @@ def convert_pool2d(g, op, block): if isinstance(paddings, int): paddings = [paddings] * 2 + if padding_algorithm == "VALID": + paddings = [0, 0] + elif padding_algorithm == "SAME": + pad_h = _get_pad_size(in_h, ksize[0], strides[0]) + pad_w = _get_pad_size(in_w, ksize[1], strides[1]) + paddings = [pad_h[0], pad_w[0], pad_h[1], pad_w[1]] + else: + msg = 'Value {} in attribute "padding" of operator Pool2d is not ' "valid." + raise tvm.error.OpAttributeInvalid(msg.format(padding_algorithm)) + x = g.get_node(op.input('X')[0]) if not adaptive: out = getattr(_op.nn, op_map[pooling_type])(x, @@ -634,6 +665,7 @@ def convert_unsqueeze(g, op, block): class GraphProto(object): """ A helper class for handling relay functions from PaddlePaddle model.""" + def __init__(self): self.nodes = {} self.params = {} From 1967d461ddf82d7b12854cf33e3fb1d075ab532b Mon Sep 17 00:00:00 2001 From: wjj19950828 Date: Thu, 5 Aug 2021 15:22:34 +0800 Subject: [PATCH 008/127] support 4 two-tuples --- python/tvm/relay/frontend/paddlepaddle.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 397b7dfb39f4..2beca3a491db 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -138,6 +138,11 @@ def convert_conv2d(g, op, block): pad_h = _get_pad_size(in_h, (k_h - 1) * dilations[0] + 1, strides[0]) pad_w = _get_pad_size(in_w, (k_w - 1) * dilations[1] + 1, strides[1]) paddings = [pad_h[0], pad_w[0], pad_h[1], pad_w[1]] + elif padding_algorithm == "EXPLICIT": + if len(paddings) == 2: + paddings = [paddings[0],paddings[1],paddings[0],paddings[1]] + if len(paddings) == 4: + paddings = [paddings[0],paddings[2],paddings[1],paddings[3]] else: msg = 'Value {} in attribute "padding" of operator Conv is not ' "valid." raise tvm.error.OpAttributeInvalid(msg.format(padding_algorithm)) @@ -499,6 +504,11 @@ def convert_pool2d(g, op, block): pad_h = _get_pad_size(in_h, ksize[0], strides[0]) pad_w = _get_pad_size(in_w, ksize[1], strides[1]) paddings = [pad_h[0], pad_w[0], pad_h[1], pad_w[1]] + elif padding_algorithm == "EXPLICIT": + if len(paddings) == 2: + paddings = [paddings[0],paddings[1],paddings[0],paddings[1]] + if len(paddings) == 4: + paddings = [paddings[0],paddings[2],paddings[1],paddings[3]] else: msg = 'Value {} in attribute "padding" of operator Pool2d is not ' "valid." raise tvm.error.OpAttributeInvalid(msg.format(padding_algorithm)) From f4932bf5649e816650ef7381b9f75a85084fd1a9 Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Thu, 5 Aug 2021 20:00:48 +0800 Subject: [PATCH 009/127] add paddle test case --- .../frontend/paddlepaddle/test_forward.py | 124 ++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 tests/python/frontend/paddlepaddle/test_forward.py diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py new file mode 100644 index 000000000000..1b4c960824dd --- /dev/null +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -0,0 +1,124 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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 os +from pathlib import Path +import re + +import numpy as np +import tvm +import tvm.testing +import tvm.topi.testing +from tvm import relay +from tvm.contrib import graph_executor + +import paddle +import paddle.nn as nn + +PADDLE_TEST_DATA_ROOT_PATH = Path(Path("~").expanduser(), ".tvm_test_data", "paddle") +PADDLE_TEST_DATA_ROOT_PATH.mkdir(parents=True, exist_ok=True) + +def assert_shapes_match(tru, est): + if tru.shape != est.shape: + msg = "Output shapes {} and {} don't match" + raise AssertionError(msg.format(tru.shape, est.shape)) + +def get_paddle_model(func, input_spec): + global PADDLE_TEST_DATA_ROOT_PATH + model_path = Path(PADDLE_TEST_DATA_ROOT_PATH, "model") + + paddle.jit.save(func, str(model_path), input_spec=input_spec) + baseline_model = paddle.jit.load(str(model_path)) + + os.remove(str(model_path) + '.pdmodel') + return baseline_model + +def verify_model(func, input_data, rtol=1e-5, atol=1e-5): + if not (isinstance(input_data, list) or isinstance(input_data, tuple)): + input_data = [input_data] + + input_spec = [] + input_names = [] + input_shape_dict = {} + for idx, data in enumerate(input_data): + input_name = "input{}".format(idx) + input_spec.append(paddle.static.InputSpec(dtype=data.dtype, shape=data.shape, name=input_name)) + input_names.append(input_name) + input_shape_dict[input_name] = data.shape + + baseline_model = get_paddle_model(func, input_spec) + with paddle.no_grad(): + baseline_outputs = baseline_model(*[input.clone() for input in input_data]) + + # get paddle outputs + if isinstance(baseline_outputs, tuple): + baseline_outputs = tuple(out.numpy() for out in baseline_outputs) + else: + baseline_outputs = (baseline_outputs.numpy(),) + + mod, params = relay.frontend.from_paddle(baseline_model, input_shape_dict) + for arg in mod["main"].params[: len(input_names)]: + assert arg.name_hint in input_names + compiled_input = dict(zip(input_names, [inp.clone().numpy() for inp in input_data])) + + with tvm.transform.PassContext(opt_level=3): + for target, dev in tvm.testing.enabled_targets(): + lib = relay.build(mod, target=target, params=params) + gmod = graph_executor.GraphModule(lib["default"](dev)) + for name, inp in compiled_input.items(): + gmod.set_input(name, inp) + gmod.run() + + for i, baseline_output in enumerate(baseline_outputs): + compiled_output = gmod.get_output(i).numpy() + + assert_shapes_match(baseline_output, compiled_output) + tvm.testing.assert_allclose(baseline_output, compiled_output, rtol=rtol, atol=atol) + +@tvm.testing.uses_gpu +def test_forward_add(): + paddle.set_grad_enabled(False) + input_shape = [10] + + @paddle.jit.to_static + def add(inputs): + return paddle.add(inputs, inputs) + + @paddle.jit.to_static + def add2(inputs): + return inputs + 1 + + @paddle.jit.to_static + def add3(inputs): + ones = paddle.ones([10], dtype="float32") + return inputs + ones + + class add4(nn.Layer): + @paddle.jit.to_static + def forward(self, input1, input2): + return input1 + input2 + + input_data = paddle.rand(input_shape, dtype="float32") + verify_model(add, input_data) + verify_model(add2, input_data) + verify_model(add3, input_data) + input_data = paddle.rand([2, 3], dtype="float32") + input_data2 = paddle.rand([2, 3], dtype="float32") + model = add4() + verify_model(model, [input_data, input_data2]) + +if __name__ == "__main__": + test_forward_add() From 0c92955cb195376abe1781910601c1c6fba212b4 Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Thu, 5 Aug 2021 21:30:24 +0800 Subject: [PATCH 010/127] add paddle conv2d case --- .../frontend/paddlepaddle/test_forward.py | 69 +++++++++++++++---- 1 file changed, 56 insertions(+), 13 deletions(-) diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index 1b4c960824dd..786c0769c0d8 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -16,9 +16,10 @@ # under the License. import os from pathlib import Path -import re +import shutil import numpy as np +from paddle.fluid.layers.nn import pad import tvm import tvm.testing import tvm.topi.testing @@ -43,7 +44,7 @@ def get_paddle_model(func, input_spec): paddle.jit.save(func, str(model_path), input_spec=input_spec) baseline_model = paddle.jit.load(str(model_path)) - os.remove(str(model_path) + '.pdmodel') + shutil.rmtree(str(PADDLE_TEST_DATA_ROOT_PATH)) return baseline_model def verify_model(func, input_data, rtol=1e-5, atol=1e-5): @@ -60,8 +61,7 @@ def verify_model(func, input_data, rtol=1e-5, atol=1e-5): input_shape_dict[input_name] = data.shape baseline_model = get_paddle_model(func, input_spec) - with paddle.no_grad(): - baseline_outputs = baseline_model(*[input.clone() for input in input_data]) + baseline_outputs = baseline_model(*[input.clone() for input in input_data]) # get paddle outputs if isinstance(baseline_outputs, tuple): @@ -106,19 +106,62 @@ def add3(inputs): ones = paddle.ones([10], dtype="float32") return inputs + ones - class add4(nn.Layer): - @paddle.jit.to_static - def forward(self, input1, input2): - return input1 + input2 - input_data = paddle.rand(input_shape, dtype="float32") verify_model(add, input_data) verify_model(add2, input_data) verify_model(add3, input_data) - input_data = paddle.rand([2, 3], dtype="float32") - input_data2 = paddle.rand([2, 3], dtype="float32") - model = add4() - verify_model(model, [input_data, input_data2]) + +@tvm.testing.uses_gpu +def test_forward_conv(): + paddle.set_grad_enabled(False) + conv1d_input_shape = [1, 3, 10] + conv2d_input_shape = [1, 3, 10, 10] + + class Conv2D1(nn.Layer): + def __init__(self): + super(Conv2D1, self).__init__() + self.conv = nn.Conv2D(3, 6, 7, bias_attr=True) + self.softmax = nn.Softmax() + + @paddle.jit.to_static + def forward(self, inputs): + return self.softmax(self.conv(inputs)) + + class Conv2D2(nn.Layer): + def __init__(self): + super(Conv2D2, self).__init__() + self.conv = nn.Conv2D(3, 6, 7, groups=3, bias_attr=False) + self.softmax = nn.Softmax() + + @paddle.jit.to_static + def forward(self, inputs): + return self.softmax(self.conv(inputs)) + + class Conv1D1(nn.Layer): + def __init__(self): + super(Conv1D1, self).__init__() + self.conv = nn.Conv1D(3, 6, 7, bias_attr=True) + self.softmax = nn.Softmax() + + @paddle.jit.to_static + def forward(self, inputs): + return self.softmax(self.conv(inputs)) + + class Conv1D2(nn.Layer): + def __init__(self): + super(Conv1D2, self).__init__() + self.conv = nn.Conv1d(3, 6, 7, groups=3, bias_attr=False) + self.softmax = nn.Softmax() + + @paddle.jit.to_static + def forward(self, inputs): + return self.softmax(self.conv(inputs)) + + conv2d_input_data = paddle.rand(conv2d_input_shape, dtype="float32") + verify_model(Conv2D1(), input_data=conv2d_input_data) + verify_model(Conv2D2(), input_data=conv2d_input_data) + if __name__ == "__main__": test_forward_add() + test_forward_conv() From b0b80946ca1dda023c6c62e4dd1df092225a2a00 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 6 Aug 2021 03:28:53 +0000 Subject: [PATCH 011/127] update test_forward.py --- .../frontend/paddlepaddle/test_forward.py | 23 ------------------- 1 file changed, 23 deletions(-) diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index 786c0769c0d8..1006cd799a35 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -90,7 +90,6 @@ def verify_model(func, input_data, rtol=1e-5, atol=1e-5): @tvm.testing.uses_gpu def test_forward_add(): - paddle.set_grad_enabled(False) input_shape = [10] @paddle.jit.to_static @@ -113,8 +112,6 @@ def add3(inputs): @tvm.testing.uses_gpu def test_forward_conv(): - paddle.set_grad_enabled(False) - conv1d_input_shape = [1, 3, 10] conv2d_input_shape = [1, 3, 10, 10] class Conv2D1(nn.Layer): @@ -137,26 +134,6 @@ def __init__(self): def forward(self, inputs): return self.softmax(self.conv(inputs)) - class Conv1D1(nn.Layer): - def __init__(self): - super(Conv1D1, self).__init__() - self.conv = nn.Conv1D(3, 6, 7, bias_attr=True) - self.softmax = nn.Softmax() - - @paddle.jit.to_static - def forward(self, inputs): - return self.softmax(self.conv(inputs)) - - class Conv1D2(nn.Layer): - def __init__(self): - super(Conv1D2, self).__init__() - self.conv = nn.Conv1d(3, 6, 7, groups=3, bias_attr=False) - self.softmax = nn.Softmax() - - @paddle.jit.to_static - def forward(self, inputs): - return self.softmax(self.conv(inputs)) - conv2d_input_data = paddle.rand(conv2d_input_shape, dtype="float32") verify_model(Conv2D1(), input_data=conv2d_input_data) verify_model(Conv2D2(), input_data=conv2d_input_data) From 35fccb2b16d9f583553f6586ee950333b4c8c00a Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Fri, 6 Aug 2021 16:44:41 +0800 Subject: [PATCH 012/127] fix paddle convert_matmul --- python/tvm/relay/frontend/paddlepaddle.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 54c72ff9d628..ec2cd945e456 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -442,9 +442,13 @@ def flatten_to_nd(x, x_shape, nd=3): ) out = _op.reshape(output, fold_constant(final_shape)) else: + if b_rank == 1: + inputs[1] = _op.expand_dims(inputs[1], 1, 1) # Otherwise a simple dense op will get the job done. input_1_t = _op.transpose(inputs[1], axes=(1, 0)) out = _op.nn.dense(inputs[0], input_1_t) + if b_rank == 1: + out = _op.squeeze(out, axis=[-1]) try: alpha = op.attr('alpha') if not np.isclose(alpha, 1.0): From 094f44ed8121e8145405699bd5f952aa17e21561 Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Fri, 6 Aug 2021 16:47:31 +0800 Subject: [PATCH 013/127] add paddle multiply and matmul op test case --- .../frontend/paddlepaddle/test_forward.py | 74 ++++++++++++++++--- 1 file changed, 63 insertions(+), 11 deletions(-) diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index 1006cd799a35..94a2c468b21a 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -89,26 +89,76 @@ def verify_model(func, input_data, rtol=1e-5, atol=1e-5): tvm.testing.assert_allclose(baseline_output, compiled_output, rtol=rtol, atol=atol) @tvm.testing.uses_gpu -def test_forward_add(): +def test_forward_add_subtract(): input_shape = [10] @paddle.jit.to_static - def add(inputs): - return paddle.add(inputs, inputs) + def add_subtract(inputs): + return paddle.subtract(paddle.add(inputs, inputs), inputs) @paddle.jit.to_static - def add2(inputs): - return inputs + 1 + def add_subtract2(inputs): + return inputs + 1 - 2 @paddle.jit.to_static - def add3(inputs): + def add_subtract3(inputs1, inputs2): ones = paddle.ones([10], dtype="float32") - return inputs + ones + return inputs1 + ones - inputs2 input_data = paddle.rand(input_shape, dtype="float32") - verify_model(add, input_data) - verify_model(add2, input_data) - verify_model(add3, input_data) + verify_model(add_subtract, input_data) + verify_model(add_subtract2, input_data) + input_data2 = paddle.rand(input_shape, dtype="float32") + verify_model(add_subtract3, [input_data, input_data2]) + +@tvm.testing.uses_gpu +def test_forward_multiply(): + input_shape = [10] + + @paddle.jit.to_static + def multiply1(inputs): + return inputs * inputs + + @paddle.jit.to_static + def multiply2(inputs): + return inputs * 1.0 + + @paddle.jit.to_static + def multiply3(inputs): + ones = paddle.ones([10], dtype="float32") + return inputs * ones + + input_data = paddle.rand(input_shape, dtype="float32") + verify_model(multiply1, input_data=input_data) + verify_model(multiply2, input_data=input_data) + verify_model(multiply3, input_data=input_data) + +@tvm.testing.uses_gpu +def test_forward_matmul(): + + class MatMul1(nn.Layer): + def forward(self, input1, input2): + return paddle.matmul(input1, input2) + + # matrix x vector + input_data1 = paddle.randn((3, 4), dtype="float32") + input_data2 = paddle.randn((4,), dtype="float32") + verify_model(MatMul1(), input_data=[input_data1, input_data2]) + + # matrix x matrix + input_data1 = paddle.randn((5, 4), dtype="float32") + input_data2 = paddle.randn((4, 5), dtype="float32") + verify_model(MatMul1(), input_data=[input_data1, input_data2]) + + # batched matrix x batched matrix + input_data1 = paddle.randn((10, 3, 4), dtype="float32") + input_data2 = paddle.randn((10, 4, 5), dtype="float32") + verify_model(MatMul1(), input_data=[input_data1, input_data2]) + + # batched matrix x broadcasted matrix + input_data1 = paddle.randn((10, 3, 4), dtype="float32") + input_data2 = paddle.randn((4, 5), dtype="float32") + verify_model(MatMul1(), input_data=[input_data1, input_data2]) @tvm.testing.uses_gpu def test_forward_conv(): @@ -140,5 +190,7 @@ def forward(self, inputs): if __name__ == "__main__": - test_forward_add() + test_forward_add_subtract() + test_forward_multiply() + test_forward_matmul() test_forward_conv() From 4520515996dba25662644a3160ce6ca661d9e6d4 Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Wed, 11 Aug 2021 20:12:10 +0800 Subject: [PATCH 014/127] add test case and fix bug --- python/tvm/relay/frontend/paddlepaddle.py | 94 +++- .../frontend/paddlepaddle/test_forward.py | 466 ++++++++++++++++-- 2 files changed, 497 insertions(+), 63 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 3d63826b6ea2..02f256ab3435 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -19,6 +19,7 @@ """Paddle: PArallel Distributed Deep LEarning.""" import copy import warnings +from pandas.core.dtypes.inference import is_scalar import six import numpy as np @@ -68,10 +69,13 @@ def convert_arg_max(g, op, block): axis = op.attr('axis') keepdims = op.attr('keepdims') flatten = op.attr('flatten') - assert not flatten, "Only flatten==True is supported for PaddlePaddle's arg_max" - x = g.get_node(x.input('X')[0]) - out = _op.argmax(x, axis=axis, keepdims=keepdims) + x = g.get_node(op.input('X')[0]) + if axis is None or flatten: + x = _op.reshape(x, [-1]) + out = _op.argmax(x, axis=None, keepdims=True) + else: + out = _op.argmax(x, axis=axis, keepdims=keepdims) g.add_node(op.output('Out')[0], out) @@ -166,9 +170,9 @@ def convert_cumsum(g, op, block): flatten = op.attr('flatten') reverse = op.attr('reverse') - assert not flatten, "Only flatten==False is supported for PaddlePaddle's cumsum" - x = g.get_node(op.input('X')[0]) + if axis is None or flatten: + x = _op.reshape(x, [-1]) if reverse: x = _op.reverse(x, axis=axis) out = _op.cumsum(x, axis=axis, exclusive=exclusive) @@ -281,6 +285,12 @@ def convert_fill_constant(g, op, block): shape = block.var(op.output('Out')[0]).shape dtype = block.var(op.output('Out')[0]).dtype dtype = str(dtype).strip().split('.')[1] + if op.input('ValueTensor'): + shape = g.get_node(op.input('ValueTensor')[0]) + shape = infer_value(shape, g.get_params()).numpy() + if op.input('ShapeTensor'): + shape = g.get_node(op.input('ShapeTensor')[0]) + shape = infer_value(shape, g.get_params()).numpy() value = np.full(shape, value, dtype) out = _expr.const(value.astype(dtype)).astype(dtype) g.add_node(op.output('Out')[0], out) @@ -333,8 +343,22 @@ def convert_layer_norm(g, op, block): begin_norm_axis = op.attr('begin_norm_axis') epsilon = op.attr('epsilon') x = g.get_node(op.input('X')[0]) - bias = g.get_node(op.input('Bias')[0]) - scale = g.get_node(op.input('Scale')[0]) + bias_input = op.input('Bias') + scale_input = op.input('Scale') + + x_shape = infer_shape(x) + assert begin_norm_axis == -1 or begin_norm_axis == len(x_shape) - 1, "Support only normalization over last one dimension." + + if bias_input: + bias = g.get_node(bias_input[0]) + else: + bias = _expr.const(np.zeros(x_shape[begin_norm_axis])) + + if scale_input: + scale = g.get_node(scale_input[0]) + else: + scale = _expr.const(np.ones(x_shape[begin_norm_axis])) + out = _op.nn.layer_norm(x, gamma=scale, beta=bias, @@ -351,7 +375,7 @@ def convert_leaky_relu(g, op, block): alpha = op.attr('alpha') x = g.get_node(op.input('X')[0]) out = _op.nn.leaky_relu(x, alpha=alpha) - g.add_node(op.output('Out')[0]) + g.add_node(op.output('Out')[0], out) def convert_lookup_table(g, op, block): @@ -540,7 +564,7 @@ def convert_pool2d(g, op, block): if global_pooling: adaptive = True ksize = [1, 1] - + input = g.get_node(op.input('X')[0]) in_h, in_w = infer_shape(input)[2:] @@ -587,8 +611,27 @@ def convert_pool2d(g, op, block): def convert_reshape(g, op, block): """Operator converter for reshape.""" - shape = op.attr('shape') - out = _op.reshape(g.get_node(op.input('X')[0]), shape) + shape_attr = op.input('Shape') + tensor_attr = op.input('ShapeTensor') + data = g.get_node(op.input('X')[0]) + if shape_attr: + new_shape = g.get_node(shape_attr[0]) + elif tensor_attr: + tmp_shape = [] + for shape_name in tensor_attr: + shape = g.get_node(shape_name) + if len(infer_shape(shape)) == 0: + shape = _op.reshape(shape, [-1]) + if isinstance(shape, _expr.Constant): + tmp_shape.append(shape) + elif isinstance(shape, _expr.Expr): + tmp_shape.append(shape) + else: + tmp_shape.append(_expr.const(np.array(shape).astype('int64'))) + new_shape = _op.concatenate(tmp_shape, axis=0) + else: + new_shape = op.attr('shape') + out = _op.reshape(data, new_shape) g.add_node(op.output('Out')[0], out) @@ -627,7 +670,7 @@ def convert_shape(g, op, block): def convert_slice(g, op, block): """Operator converter for slice.""" - def parameter_process(starts, ends, axes): + def parameter_process(starts, ends, axes, dshape): new_axes = [] new_starts = [] new_ends = [] @@ -640,22 +683,29 @@ def parameter_process(starts, ends, axes): pop_index += 1 else: new_starts.append(0) - new_ends.append(np.iinfo(np.int32).max) + new_ends.append(dshape[i]) return new_starts, new_ends, new_axes + data = g.get_node(op.input('Input')[0]) + dshape = infer_shape(data) starts = op.attr('starts') ends = op.attr('ends') axes = op.attr('axes') + decrease_axis = op.attr('decrease_axis') if isinstance(starts, int): starts = [starts] if isinstance(ends, int): ends = [ends] if isinstance(axes, int): axes = [axes] - starts, ends, axes = parameter_process(starts, ends, axes) - out = _op.strided_slice(g.get_node(op.input('Input')[0]), + if isinstance(decrease_axis, int): + decrease_axis = [decrease_axis] + starts, ends, axes = parameter_process(starts, ends, axes, dshape) + out = _op.strided_slice(data, begin=starts, end=ends) + if decrease_axis: + out = _op.squeeze(out, axis=decrease_axis) g.add_node(op.output('Out')[0], out) @@ -672,15 +722,6 @@ def convert_softmax(g, op, block): out = e / _op.sum(e, axis, keepdims=True) g.add_node(op.output('Out')[0], out) - -def convert_transpose(g, op, block): - """Operator converter for transpose.""" - - perm = op.attr('axis') - out = _op.transpose(g.get_node(op.input('X')[0]), axes=perm) - g.add_node(op.output('Out')[0], out) - - def convert_unsqueeze(g, op, block): """Operator converter for unsqueeze.""" @@ -727,7 +768,6 @@ def convert_unsqueeze(g, op, block): 'slice': convert_slice, 'softmax': convert_softmax, 'tanh': convert_activation, - 'transpose2': convert_transpose, 'unsqueeze2': convert_unsqueeze, } @@ -747,7 +787,9 @@ def get_node(self, name): def add_node(self, name, node): self.nodes[name] = fold_constant(node) - def get_params(self, name): + def get_params(self, name=None): + if name is None: + return self.params assert name in self.params return self.params[name] diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index 94a2c468b21a..d4dea6cbe59a 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -19,7 +19,6 @@ import shutil import numpy as np -from paddle.fluid.layers.nn import pad import tvm import tvm.testing import tvm.topi.testing @@ -48,38 +47,45 @@ def get_paddle_model(func, input_spec): return baseline_model def verify_model(func, input_data, rtol=1e-5, atol=1e-5): - if not (isinstance(input_data, list) or isinstance(input_data, tuple)): + if not (isinstance(input_data, (tuple, list))): input_data = [input_data] input_spec = [] input_names = [] input_shape_dict = {} + compiled_input = {} for idx, data in enumerate(input_data): input_name = "input{}".format(idx) input_spec.append(paddle.static.InputSpec(dtype=data.dtype, shape=data.shape, name=input_name)) input_names.append(input_name) input_shape_dict[input_name] = data.shape + if isinstance(data, np.ndarray): + compiled_input[input_name] = data + else: + compiled_input[input_name] = data.numpy() baseline_model = get_paddle_model(func, input_spec) - baseline_outputs = baseline_model(*[input.clone() for input in input_data]) + baseline_outputs = baseline_model(*[input[:] for input in input_data]) # get paddle outputs - if isinstance(baseline_outputs, tuple): + if isinstance(baseline_outputs, (tuple, list)): baseline_outputs = tuple(out.numpy() for out in baseline_outputs) else: baseline_outputs = (baseline_outputs.numpy(),) mod, params = relay.frontend.from_paddle(baseline_model, input_shape_dict) - for arg in mod["main"].params[: len(input_names)]: + parms_num = min(len(input_names), len(mod["main"].params)) + compiled_names = [] + for arg in mod["main"].params[: parms_num]: assert arg.name_hint in input_names - compiled_input = dict(zip(input_names, [inp.clone().numpy() for inp in input_data])) + compiled_names.append(arg.name_hint) with tvm.transform.PassContext(opt_level=3): for target, dev in tvm.testing.enabled_targets(): lib = relay.build(mod, target=target, params=params) gmod = graph_executor.GraphModule(lib["default"](dev)) - for name, inp in compiled_input.items(): - gmod.set_input(name, inp) + for name in compiled_names: + gmod.set_input(name, compiled_input[name]) gmod.run() for i, baseline_output in enumerate(baseline_outputs): @@ -112,26 +118,310 @@ def add_subtract3(inputs1, inputs2): verify_model(add_subtract3, [input_data, input_data2]) @tvm.testing.uses_gpu -def test_forward_multiply(): - input_shape = [10] +def test_forward_argmax(): + input_shape = [1, 3, 10, 10] + + class ArgMax(nn.Layer): + @paddle.jit.to_static + def forward(self, inputs): + return paddle.argmax(inputs) + + class ArgMax1(nn.Layer): + @paddle.jit.to_static + def forward(self, inputs): + return inputs.argmax(axis=1) + + class ArgMax2(nn.Layer): + @paddle.jit.to_static + def forward(self, inputs): + return inputs.argmax(axis=1, keepdim=False) + + class ArgMax3(nn.Layer): + @paddle.jit.to_static + def forward(self, inputs): + return inputs.argmax(axis=2, keepdim=True) + + input_data = paddle.rand(input_shape, dtype="float32") + verify_model(ArgMax(), input_data=input_data) + verify_model(ArgMax1(), input_data=input_data) + verify_model(ArgMax2(), input_data=input_data) + verify_model(ArgMax3(), input_data=input_data) + +@tvm.testing.uses_gpu +def test_forward_assign(): + @paddle.jit.to_static + def assign(inputs): + return paddle.assign(inputs) + + input_shape = [2, 3] + input_data = paddle.rand(input_shape, dtype="float32") + verify_model(assign, [input_data,]) + input_data2 = np.random.randint(100, size=input_shape) + verify_model(assign, [input_data2,]) + +@tvm.testing.uses_gpu +def test_forward_batch_norm(): + class BatchNorm1D(nn.Layer): + def __init__(self): + super(BatchNorm1D, self).__init__() + self.batch_norm = nn.BatchNorm1D(2) + + @paddle.jit.to_static + def forward(self, input_data): + return self.batch_norm(input_data) + + class BatchNorm2D(nn.Layer): + def __init__(self): + super(BatchNorm2D, self).__init__() + self.batch_norm = nn.BatchNorm2D(2) + + @paddle.jit.to_static + def forward(self, input_data): + return self.batch_norm(input_data) + + class BatchNorm3D(nn.Layer): + def __init__(self): + super(BatchNorm3D, self).__init__() + self.batch_norm = nn.BatchNorm3D(2) + + @paddle.jit.to_static + def forward(self, input_data): + return self.batch_norm(input_data) + + input_data = paddle.rand((2, 2, 3), dtype="float32") + verify_model(BatchNorm1D(), input_data=input_data) + input_data = paddle.rand((2, 2, 2, 3), dtype="float32") + verify_model(BatchNorm2D(), input_data=input_data) + input_data = paddle.rand((2, 2, 2, 2, 3), dtype="float32") + verify_model(BatchNorm3D(), input_data=input_data) + +@tvm.testing.uses_gpu +def test_forward_cast(): + @paddle.jit.to_static + def cast1(inputs, dtype="uint8"): + return paddle.cast(inputs, dtype) + + @paddle.jit.to_static + def cast2(inputs, dtype="int64"): + return inputs.cast(dtype) + + input_shape = [2, 3] + input_data = paddle.rand(input_shape, dtype="float32") * 100 + verify_model(cast1, [input_data,]) + verify_model(cast2, [input_data,]) + +@tvm.testing.uses_gpu +def test_forward_concat_unsqueeze(): + @paddle.jit.to_static + def concat_unsqueeze1(inputs): + return paddle.concat([inputs[:, 0].unsqueeze(1), inputs[:, 1].unsqueeze(1)], axis=1) + + @paddle.jit.to_static + def concat_unsqueeze2(inputs): + a = (inputs[:, :, 0] + 2) * 7 + b = (inputs[:, :, 1] + 3) * 11 + c = (inputs[:, :, 2] + 5) * 13 + return paddle.concat([paddle.unsqueeze(t, axis=2) for t in [a, b, c]], axis=2) + + input_shape = [1, 3, 10, 10] + input_data = paddle.rand(input_shape, dtype="float32") + verify_model(concat_unsqueeze1, input_data=input_data) + verify_model(concat_unsqueeze2, input_data=input_data) + +@tvm.testing.uses_gpu +def test_forward_cumsum(): + @paddle.jit.to_static + def cusum1(inputs): + return paddle.cumsum(inputs) + + @paddle.jit.to_static + def cusum2(inputs): + return paddle.cumsum(inputs, axis=0) + + @paddle.jit.to_static + def cusum3(inputs): + return paddle.cumsum(inputs, axis=1) + + input_data = paddle.randint(0, 100, (10, 10), dtype=paddle.int32) + verify_model(cusum1, [input_data]) + verify_model(cusum1, [input_data.astype(paddle.int64)]) + verify_model(cusum2, [input_data, ]) + verify_model(cusum3, [input_data, ]) + +@tvm.testing.uses_gpu +def test_forward_conv(): + conv2d_input_shape = [1, 3, 10, 10] + + class Conv2D1(nn.Layer): + def __init__(self): + super(Conv2D1, self).__init__() + self.conv = nn.Conv2D(3, 6, 7, bias_attr=True) + self.softmax = nn.Softmax() + + @paddle.jit.to_static + def forward(self, inputs): + return self.softmax(self.conv(inputs)) + + class Conv2D2(nn.Layer): + def __init__(self): + super(Conv2D2, self).__init__() + self.conv = nn.Conv2D(3, 6, 7, groups=3, bias_attr=False) + self.softmax = nn.Softmax() + + @paddle.jit.to_static + def forward(self, inputs): + return self.softmax(self.conv(inputs)) + + conv2d_input_data = paddle.rand(conv2d_input_shape, dtype="float32") + verify_model(Conv2D1(), input_data=conv2d_input_data) + verify_model(Conv2D2(), input_data=conv2d_input_data) + +@tvm.testing.uses_gpu +def test_forward_dropout(): + @paddle.jit.to_static + def dropout(inputs): + return nn.functional.dropout(inputs) + + input_shape = [1, 3, 10, 10] + input_data = paddle.rand(input_shape, dtype="float32") + verify_model(dropout, input_data=input_data[0, 0]) + verify_model(dropout, input_data=input_data) + +@tvm.testing.uses_gpu +def test_forward_shape_full(): + @paddle.jit.to_static + def full1(inputs): + return paddle.full(paddle.shape(inputs), 3.14) + + @paddle.jit.to_static + def full2(inputs): + return paddle.full(paddle.shape(inputs), 1.0, dtype=inputs.dtype) + input_shape = [1, 3, 10, 10] + input_data = paddle.rand(input_shape, dtype="float32") + verify_model(full1, input_data=[input_data]) + verify_model(full2, input_data=[input_data]) + +@tvm.testing.uses_gpu +def test_forward_ones_like(): + @paddle.jit.to_static + def ones_like1(inputs): + return paddle.ones_like(inputs) + + @paddle.jit.to_static + def ones_like2(inputs): + return paddle.ones_like(inputs, dtype="int32") + + input_shape = [1, 3, 10, 10] + input_data = paddle.rand(input_shape, dtype="float32") + verify_model(ones_like1, input_data=input_data) + verify_model(ones_like2, input_data=input_data) + +@tvm.testing.uses_gpu +def test_forward_gelu(): + @paddle.jit.to_static + def gelu(inputs): + return nn.functional.gelu(inputs) + + input_shape = [1, 3, 10, 10] + input_data = paddle.rand(input_shape, dtype="float32") + verify_model(gelu, input_data=input_data) + +@tvm.testing.uses_gpu +def test_forward_hard_sigmoid(): + @paddle.jit.to_static + def hard_sigmoid(inputs): + return nn.functional.hardsigmoid(inputs) + + input_shape = [1, 3, 10, 10] + input_data = paddle.rand(input_shape, dtype="float32") + verify_model(hard_sigmoid, input_data=input_data) + +@tvm.testing.uses_gpu +def test_forward_hard_swish(): + @paddle.jit.to_static + def hard_swish(inputs): + return nn.functional.hardswish(inputs) + + input_shape = [1, 3, 10, 10] + input_data = paddle.rand(input_shape, dtype="float32") + verify_model(hard_swish, input_data=input_data) + +@tvm.testing.uses_gpu +def test_forward_layer_norm(): + @paddle.jit.to_static + def layer_norm(inputs, weight, bias): + return nn.functional.layer_norm(inputs, inputs.shape[-1], weight=weight, bias=bias) + + class LayerNorm(nn.Layer): + def __init__(self): + super(LayerNorm, self).__init__() + data_shape = [10] + self.layer_norm = nn.LayerNorm(data_shape) + + @paddle.jit.to_static + def forward(self, inputs): + return self.layer_norm(inputs) + + input_shape = [1, 3, 10, 10] + input_data = paddle.rand(input_shape, dtype="float32") + weight = paddle.rand([10], dtype="float32") + bias = paddle.rand([10], dtype="float32") + verify_model(layer_norm, input_data=[input_data, weight, bias]) + verify_model(LayerNorm(), input_data=input_data) + +@tvm.testing.uses_gpu +def test_forward_leaky_relu(): + @paddle.jit.to_static + def leaky_relu(inputs): + return nn.functional.leaky_relu(inputs) + + input_shape = [1, 3, 10, 10] + input_data = paddle.rand(input_shape, dtype="float32") + verify_model(leaky_relu, input_data=input_data) + +@tvm.testing.uses_gpu +def test_forward_look_up(): + @paddle.jit.to_static + def look_up(inputs, weight): + return nn.functional.embedding(inputs, weight) + + class LookUp(nn.Layer): + def __init__(self): + super(LookUp, self).__init__() + self.embedding = paddle.nn.Embedding(10, 4, sparse=True) + + @paddle.jit.to_static + def forward(self, inputs): + return self.embedding(inputs) + + input_shape = [1, 3, 10, 10] + input_data = paddle.randint(0, 10, input_shape, dtype="int32") + weight = paddle.rand([10, 4], dtype="float32") + verify_model(look_up, input_data=[input_data, weight]) + verify_model(LookUp(), input_data=input_data) + +@tvm.testing.uses_gpu +def test_forward_multiply(): @paddle.jit.to_static def multiply1(inputs): return inputs * inputs @paddle.jit.to_static def multiply2(inputs): - return inputs * 1.0 + return inputs * 1.0 / 2.0 @paddle.jit.to_static - def multiply3(inputs): + def multiply3(inputs, inputs2): ones = paddle.ones([10], dtype="float32") - return inputs * ones + return inputs * ones / inputs2 + input_shape = [10] input_data = paddle.rand(input_shape, dtype="float32") verify_model(multiply1, input_data=input_data) verify_model(multiply2, input_data=input_data) - verify_model(multiply3, input_data=input_data) + input_data2 = paddle.rand(input_shape, dtype="float32") + verify_model(multiply3, input_data=[input_data, input_data2]) @tvm.testing.uses_gpu def test_forward_matmul(): @@ -161,36 +451,138 @@ def forward(self, input1, input2): verify_model(MatMul1(), input_data=[input_data1, input_data2]) @tvm.testing.uses_gpu -def test_forward_conv(): - conv2d_input_shape = [1, 3, 10, 10] +def test_forward_pool2d(): + @paddle.jit.to_static + def pool2d1(inputs): + return nn.functional.avg_pool2d(inputs, kernel_size=2, stride=2, padding=0) - class Conv2D1(nn.Layer): - def __init__(self): - super(Conv2D1, self).__init__() - self.conv = nn.Conv2D(3, 6, 7, bias_attr=True) - self.softmax = nn.Softmax() - - @paddle.jit.to_static - def forward(self, inputs): - return self.softmax(self.conv(inputs)) + @paddle.jit.to_static + def pool2d2(inputs): + return nn.functional.adaptive_avg_pool2d(inputs, output_size=[3, 3]) - class Conv2D2(nn.Layer): - def __init__(self): - super(Conv2D2, self).__init__() - self.conv = nn.Conv2D(3, 6, 7, groups=3, bias_attr=False) - self.softmax = nn.Softmax() + @paddle.jit.to_static + def pool2d3(inputs): + return nn.functional.max_pool2d(inputs, kernel_size=2, stride=2, padding=0, return_mask=True) - @paddle.jit.to_static - def forward(self, inputs): - return self.softmax(self.conv(inputs)) + input_data = paddle.uniform(shape=[1, 2, 32, 32], dtype='float32', min=-1, max=1) + verify_model(pool2d1, input_data=input_data) + verify_model(pool2d2, input_data=input_data) + # verify_model(pool2d3, input_data=input_data) - conv2d_input_data = paddle.rand(conv2d_input_shape, dtype="float32") - verify_model(Conv2D1(), input_data=conv2d_input_data) - verify_model(Conv2D2(), input_data=conv2d_input_data) +@tvm.testing.uses_gpu +def test_forward_relu(): + @paddle.jit.to_static + def relu(inputs): + return nn.functional.relu(inputs) + input_shape = [10, 10] + input_data = paddle.rand(input_shape, dtype="float32") + verify_model(relu, input_data=input_data) + +@tvm.testing.uses_gpu +def test_forward_reshape(): + @paddle.jit.to_static + def reshape1(inputs, x): + new_shape = paddle.shape(x) + return paddle.reshape(inputs, new_shape) + + @paddle.jit.to_static + def reshape2(inputs): + return inputs.reshape([-1]) + + @paddle.jit.to_static + def reshape3(inputs): + data_shape = inputs.shape + return inputs.reshape([data_shape[0] * data_shape[1], data_shape[2]]) + + @paddle.jit.to_static + def reshape4(inputs, x): + new_shape = paddle.shape(x) + return paddle.reshape(inputs, [new_shape[2], 2, -1]) + + input_shape = [2, 1, 10, 1, 10] + input_data = paddle.rand(input_shape, dtype="float32") + input_data2 = paddle.randn([2, 1, 10, 10]) + verify_model(reshape1, input_data=[input_data, input_data2]) + verify_model(reshape2, input_data=input_data) + verify_model(reshape3, input_data=paddle.randn((2, 3, 4))) + verify_model(reshape4, input_data=[input_data, input_data2]) + +@tvm.testing.uses_gpu +def test_forward_scale(): + @paddle.jit.to_static + def scale1(inputs): + return paddle.scale(inputs, scale=2.0, bias=1.0) + + @paddle.jit.to_static + def scale2(inputs): + return paddle.scale(inputs, scale=3, bias=2.1, act="gelu") + + input_data = paddle.randn(shape=[2,3], dtype='float32') + verify_model(scale1, input_data=[input_data,]) + verify_model(scale2, input_data=input_data) + +@tvm.testing.uses_gpu +def test_forward_slice(): + @paddle.jit.to_static + def slice1(inputs): + return inputs[:, :, :, :3] + + @paddle.jit.to_static + def slice2(inputs): + return inputs[0, :, :-3, :] + + @paddle.jit.to_static + def slice3(inputs): + return inputs[0::2, 0::2] + inputs[1::2, 1::2] + + @paddle.jit.to_static + def slice4(inputs): + x0 = paddle.to_tensor([2]) - paddle.to_tensor([1]) + x1 = paddle.to_tensor([3]) + paddle.to_tensor([1]) + return inputs[:, x0:, 1:x1, :] + input_shape = [1, 3, 10, 10] + input_data = paddle.rand(input_shape, dtype="float32") + verify_model(slice1, input_data=[input_data,]) + verify_model(slice2, input_data=input_data) + # need op "strided_slice" + # verify_model(slice3, input_data=paddle.randn((4, 4))) + # need op "assign_value" + # verify_model(slice4, input_data=input_data) + +@tvm.testing.uses_gpu +def test_forward_tanh(): + @paddle.jit.to_static + def tanh(inputs): + return paddle.tanh(inputs) + + input_shape = [1, 3, 10, 10] + input_data = paddle.rand(input_shape, dtype="float32") + verify_model(tanh, input_data=input_data) if __name__ == "__main__": test_forward_add_subtract() + test_forward_argmax() + test_forward_assign() + test_forward_batch_norm() + test_forward_cast() + test_forward_concat_unsqueeze() + test_forward_cumsum() + test_forward_conv() + test_forward_dropout() + test_forward_shape_full() + test_forward_ones_like() + test_forward_gelu() + test_forward_hard_sigmoid() + test_forward_hard_swish() + test_forward_layer_norm() + test_forward_leaky_relu() + test_forward_look_up() test_forward_multiply() test_forward_matmul() - test_forward_conv() + test_forward_pool2d() + test_forward_relu() + test_forward_reshape() + test_forward_scale() + test_forward_slice() + test_forward_tanh() From 1d599c1d2faf6284da38fdbc38fb2b29c419cb2a Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Wed, 11 Aug 2021 20:18:04 +0800 Subject: [PATCH 015/127] delete import pandas --- python/tvm/relay/frontend/paddlepaddle.py | 1 - 1 file changed, 1 deletion(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 02f256ab3435..5308c960b838 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -19,7 +19,6 @@ """Paddle: PArallel Distributed Deep LEarning.""" import copy import warnings -from pandas.core.dtypes.inference import is_scalar import six import numpy as np From 75ef19b0f143e3986fcf13d7fae5286d94eec5da Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Fri, 13 Aug 2021 14:45:34 +0800 Subject: [PATCH 016/127] add paddlepaddle tests --- tests/scripts/task_python_frontend.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/scripts/task_python_frontend.sh b/tests/scripts/task_python_frontend.sh index fb388a6b7edd..d25d52438daa 100755 --- a/tests/scripts/task_python_frontend.sh +++ b/tests/scripts/task_python_frontend.sh @@ -54,3 +54,6 @@ run_pytest cython python-frontend-darknet tests/python/frontend/darknet echo "Running relay PyTorch frontend test..." run_pytest cython python-frontend-pytorch tests/python/frontend/pytorch + +echo "Running relay PaddlePaddle frontend test..." +run_pytest cython python-frontend-paddlepaddle tests/python/frontend/paddlepaddle From 67ca20da4b4c921f7a1986733107b429c2e869eb Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Fri, 13 Aug 2021 15:15:22 +0800 Subject: [PATCH 017/127] modify the variable name of convert_reshape --- python/tvm/relay/frontend/paddlepaddle.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 5308c960b838..dc2e94c896b8 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -610,14 +610,14 @@ def convert_pool2d(g, op, block): def convert_reshape(g, op, block): """Operator converter for reshape.""" - shape_attr = op.input('Shape') - tensor_attr = op.input('ShapeTensor') + input_shape = op.input('Shape') + input_shape_tensor = op.input('ShapeTensor') data = g.get_node(op.input('X')[0]) - if shape_attr: - new_shape = g.get_node(shape_attr[0]) - elif tensor_attr: + if input_shape: + new_shape = g.get_node(input_shape[0]) + elif input_shape_tensor: tmp_shape = [] - for shape_name in tensor_attr: + for shape_name in input_shape_tensor: shape = g.get_node(shape_name) if len(infer_shape(shape)) == 0: shape = _op.reshape(shape, [-1]) From 6f91fc5150b773c542f4dd1d9cd2fb12c280df4c Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Fri, 13 Aug 2021 15:29:04 +0800 Subject: [PATCH 018/127] formatting --- python/tvm/relay/frontend/paddlepaddle.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index dc2e94c896b8..c95ed0108b49 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -143,9 +143,9 @@ def convert_conv2d(g, op, block): paddings = [pad_h[0], pad_w[0], pad_h[1], pad_w[1]] elif padding_algorithm == "EXPLICIT": if len(paddings) == 2: - paddings = [paddings[0],paddings[1],paddings[0],paddings[1]] + paddings = [paddings[0], paddings[1], paddings[0], paddings[1]] if len(paddings) == 4: - paddings = [paddings[0],paddings[2],paddings[1],paddings[3]] + paddings = [paddings[0], paddings[2], paddings[1], paddings[3]] else: msg = 'Value {} in attribute "padding" of operator Conv is not ' "valid." raise tvm.error.OpAttributeInvalid(msg.format(padding_algorithm)) @@ -346,7 +346,8 @@ def convert_layer_norm(g, op, block): scale_input = op.input('Scale') x_shape = infer_shape(x) - assert begin_norm_axis == -1 or begin_norm_axis == len(x_shape) - 1, "Support only normalization over last one dimension." + assert begin_norm_axis == -1 or begin_norm_axis == len( + x_shape) - 1, "Support only normalization over last one dimension." if bias_input: bias = g.get_node(bias_input[0]) @@ -356,7 +357,7 @@ def convert_layer_norm(g, op, block): if scale_input: scale = g.get_node(scale_input[0]) else: - scale = _expr.const(np.ones(x_shape[begin_norm_axis])) + scale = _expr.const(np.ones(x_shape[begin_norm_axis])) out = _op.nn.layer_norm(x, gamma=scale, @@ -587,9 +588,9 @@ def convert_pool2d(g, op, block): paddings = [pad_h[0], pad_w[0], pad_h[1], pad_w[1]] elif padding_algorithm == "EXPLICIT": if len(paddings) == 2: - paddings = [paddings[0],paddings[1],paddings[0],paddings[1]] + paddings = [paddings[0], paddings[1], paddings[0], paddings[1]] if len(paddings) == 4: - paddings = [paddings[0],paddings[2],paddings[1],paddings[3]] + paddings = [paddings[0], paddings[2], paddings[1], paddings[3]] else: msg = 'Value {} in attribute "padding" of operator Pool2d is not ' "valid." raise tvm.error.OpAttributeInvalid(msg.format(padding_algorithm)) @@ -700,9 +701,7 @@ def parameter_process(starts, ends, axes, dshape): if isinstance(decrease_axis, int): decrease_axis = [decrease_axis] starts, ends, axes = parameter_process(starts, ends, axes, dshape) - out = _op.strided_slice(data, - begin=starts, - end=ends) + out = _op.strided_slice(data, begin=starts, end=ends) if decrease_axis: out = _op.squeeze(out, axis=decrease_axis) g.add_node(op.output('Out')[0], out) @@ -721,6 +720,7 @@ def convert_softmax(g, op, block): out = e / _op.sum(e, axis, keepdims=True) g.add_node(op.output('Out')[0], out) + def convert_unsqueeze(g, op, block): """Operator converter for unsqueeze.""" @@ -773,7 +773,6 @@ def convert_unsqueeze(g, op, block): class GraphProto(object): """ A helper class for handling relay functions from PaddlePaddle model.""" - def __init__(self): self.nodes = {} self.params = {} From a0aee15ccd26131d75ec45fd3f69a25c89816fc7 Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Fri, 13 Aug 2021 15:32:09 +0800 Subject: [PATCH 019/127] formatting --- .../frontend/paddlepaddle/test_forward.py | 117 ++++++++++++++---- 1 file changed, 92 insertions(+), 25 deletions(-) diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index d4dea6cbe59a..20a110f7d657 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -28,14 +28,17 @@ import paddle import paddle.nn as nn -PADDLE_TEST_DATA_ROOT_PATH = Path(Path("~").expanduser(), ".tvm_test_data", "paddle") +PADDLE_TEST_DATA_ROOT_PATH = Path( + Path("~").expanduser(), ".tvm_test_data", "paddle") PADDLE_TEST_DATA_ROOT_PATH.mkdir(parents=True, exist_ok=True) + def assert_shapes_match(tru, est): if tru.shape != est.shape: msg = "Output shapes {} and {} don't match" raise AssertionError(msg.format(tru.shape, est.shape)) + def get_paddle_model(func, input_spec): global PADDLE_TEST_DATA_ROOT_PATH model_path = Path(PADDLE_TEST_DATA_ROOT_PATH, "model") @@ -46,6 +49,7 @@ def get_paddle_model(func, input_spec): shutil.rmtree(str(PADDLE_TEST_DATA_ROOT_PATH)) return baseline_model + def verify_model(func, input_data, rtol=1e-5, atol=1e-5): if not (isinstance(input_data, (tuple, list))): input_data = [input_data] @@ -56,7 +60,10 @@ def verify_model(func, input_data, rtol=1e-5, atol=1e-5): compiled_input = {} for idx, data in enumerate(input_data): input_name = "input{}".format(idx) - input_spec.append(paddle.static.InputSpec(dtype=data.dtype, shape=data.shape, name=input_name)) + input_spec.append( + paddle.static.InputSpec(dtype=data.dtype, + shape=data.shape, + name=input_name)) input_names.append(input_name) input_shape_dict[input_name] = data.shape if isinstance(data, np.ndarray): @@ -71,15 +78,15 @@ def verify_model(func, input_data, rtol=1e-5, atol=1e-5): if isinstance(baseline_outputs, (tuple, list)): baseline_outputs = tuple(out.numpy() for out in baseline_outputs) else: - baseline_outputs = (baseline_outputs.numpy(),) + baseline_outputs = (baseline_outputs.numpy(), ) mod, params = relay.frontend.from_paddle(baseline_model, input_shape_dict) parms_num = min(len(input_names), len(mod["main"].params)) compiled_names = [] - for arg in mod["main"].params[: parms_num]: + for arg in mod["main"].params[:parms_num]: assert arg.name_hint in input_names compiled_names.append(arg.name_hint) - + with tvm.transform.PassContext(opt_level=3): for target, dev in tvm.testing.enabled_targets(): lib = relay.build(mod, target=target, params=params) @@ -92,7 +99,11 @@ def verify_model(func, input_data, rtol=1e-5, atol=1e-5): compiled_output = gmod.get_output(i).numpy() assert_shapes_match(baseline_output, compiled_output) - tvm.testing.assert_allclose(baseline_output, compiled_output, rtol=rtol, atol=atol) + tvm.testing.assert_allclose(baseline_output, + compiled_output, + rtol=rtol, + atol=atol) + @tvm.testing.uses_gpu def test_forward_add_subtract(): @@ -101,7 +112,7 @@ def test_forward_add_subtract(): @paddle.jit.to_static def add_subtract(inputs): return paddle.subtract(paddle.add(inputs, inputs), inputs) - + @paddle.jit.to_static def add_subtract2(inputs): return inputs + 1 - 2 @@ -117,6 +128,7 @@ def add_subtract3(inputs1, inputs2): input_data2 = paddle.rand(input_shape, dtype="float32") verify_model(add_subtract3, [input_data, input_data2]) + @tvm.testing.uses_gpu def test_forward_argmax(): input_shape = [1, 3, 10, 10] @@ -147,6 +159,7 @@ def forward(self, inputs): verify_model(ArgMax2(), input_data=input_data) verify_model(ArgMax3(), input_data=input_data) + @tvm.testing.uses_gpu def test_forward_assign(): @paddle.jit.to_static @@ -155,9 +168,14 @@ def assign(inputs): input_shape = [2, 3] input_data = paddle.rand(input_shape, dtype="float32") - verify_model(assign, [input_data,]) + verify_model(assign, [ + input_data, + ]) input_data2 = np.random.randint(100, size=input_shape) - verify_model(assign, [input_data2,]) + verify_model(assign, [ + input_data2, + ]) + @tvm.testing.uses_gpu def test_forward_batch_norm(): @@ -195,6 +213,7 @@ def forward(self, input_data): input_data = paddle.rand((2, 2, 2, 2, 3), dtype="float32") verify_model(BatchNorm3D(), input_data=input_data) + @tvm.testing.uses_gpu def test_forward_cast(): @paddle.jit.to_static @@ -207,27 +226,35 @@ def cast2(inputs, dtype="int64"): input_shape = [2, 3] input_data = paddle.rand(input_shape, dtype="float32") * 100 - verify_model(cast1, [input_data,]) - verify_model(cast2, [input_data,]) + verify_model(cast1, [ + input_data, + ]) + verify_model(cast2, [ + input_data, + ]) + @tvm.testing.uses_gpu def test_forward_concat_unsqueeze(): @paddle.jit.to_static def concat_unsqueeze1(inputs): - return paddle.concat([inputs[:, 0].unsqueeze(1), inputs[:, 1].unsqueeze(1)], axis=1) + return paddle.concat( + [inputs[:, 0].unsqueeze(1), inputs[:, 1].unsqueeze(1)], axis=1) @paddle.jit.to_static def concat_unsqueeze2(inputs): a = (inputs[:, :, 0] + 2) * 7 b = (inputs[:, :, 1] + 3) * 11 c = (inputs[:, :, 2] + 5) * 13 - return paddle.concat([paddle.unsqueeze(t, axis=2) for t in [a, b, c]], axis=2) + return paddle.concat([paddle.unsqueeze(t, axis=2) for t in [a, b, c]], + axis=2) input_shape = [1, 3, 10, 10] input_data = paddle.rand(input_shape, dtype="float32") verify_model(concat_unsqueeze1, input_data=input_data) verify_model(concat_unsqueeze2, input_data=input_data) + @tvm.testing.uses_gpu def test_forward_cumsum(): @paddle.jit.to_static @@ -245,8 +272,13 @@ def cusum3(inputs): input_data = paddle.randint(0, 100, (10, 10), dtype=paddle.int32) verify_model(cusum1, [input_data]) verify_model(cusum1, [input_data.astype(paddle.int64)]) - verify_model(cusum2, [input_data, ]) - verify_model(cusum3, [input_data, ]) + verify_model(cusum2, [ + input_data, + ]) + verify_model(cusum3, [ + input_data, + ]) + @tvm.testing.uses_gpu def test_forward_conv(): @@ -276,6 +308,7 @@ def forward(self, inputs): verify_model(Conv2D1(), input_data=conv2d_input_data) verify_model(Conv2D2(), input_data=conv2d_input_data) + @tvm.testing.uses_gpu def test_forward_dropout(): @paddle.jit.to_static @@ -287,6 +320,7 @@ def dropout(inputs): verify_model(dropout, input_data=input_data[0, 0]) verify_model(dropout, input_data=input_data) + @tvm.testing.uses_gpu def test_forward_shape_full(): @paddle.jit.to_static @@ -302,6 +336,7 @@ def full2(inputs): verify_model(full1, input_data=[input_data]) verify_model(full2, input_data=[input_data]) + @tvm.testing.uses_gpu def test_forward_ones_like(): @paddle.jit.to_static @@ -317,6 +352,7 @@ def ones_like2(inputs): verify_model(ones_like1, input_data=input_data) verify_model(ones_like2, input_data=input_data) + @tvm.testing.uses_gpu def test_forward_gelu(): @paddle.jit.to_static @@ -327,6 +363,7 @@ def gelu(inputs): input_data = paddle.rand(input_shape, dtype="float32") verify_model(gelu, input_data=input_data) + @tvm.testing.uses_gpu def test_forward_hard_sigmoid(): @paddle.jit.to_static @@ -337,6 +374,7 @@ def hard_sigmoid(inputs): input_data = paddle.rand(input_shape, dtype="float32") verify_model(hard_sigmoid, input_data=input_data) + @tvm.testing.uses_gpu def test_forward_hard_swish(): @paddle.jit.to_static @@ -347,11 +385,15 @@ def hard_swish(inputs): input_data = paddle.rand(input_shape, dtype="float32") verify_model(hard_swish, input_data=input_data) + @tvm.testing.uses_gpu def test_forward_layer_norm(): @paddle.jit.to_static def layer_norm(inputs, weight, bias): - return nn.functional.layer_norm(inputs, inputs.shape[-1], weight=weight, bias=bias) + return nn.functional.layer_norm(inputs, + inputs.shape[-1], + weight=weight, + bias=bias) class LayerNorm(nn.Layer): def __init__(self): @@ -370,6 +412,7 @@ def forward(self, inputs): verify_model(layer_norm, input_data=[input_data, weight, bias]) verify_model(LayerNorm(), input_data=input_data) + @tvm.testing.uses_gpu def test_forward_leaky_relu(): @paddle.jit.to_static @@ -380,6 +423,7 @@ def leaky_relu(inputs): input_data = paddle.rand(input_shape, dtype="float32") verify_model(leaky_relu, input_data=input_data) + @tvm.testing.uses_gpu def test_forward_look_up(): @paddle.jit.to_static @@ -401,6 +445,7 @@ def forward(self, inputs): verify_model(look_up, input_data=[input_data, weight]) verify_model(LookUp(), input_data=input_data) + @tvm.testing.uses_gpu def test_forward_multiply(): @paddle.jit.to_static @@ -423,16 +468,16 @@ def multiply3(inputs, inputs2): input_data2 = paddle.rand(input_shape, dtype="float32") verify_model(multiply3, input_data=[input_data, input_data2]) + @tvm.testing.uses_gpu def test_forward_matmul(): - class MatMul1(nn.Layer): def forward(self, input1, input2): return paddle.matmul(input1, input2) # matrix x vector input_data1 = paddle.randn((3, 4), dtype="float32") - input_data2 = paddle.randn((4,), dtype="float32") + input_data2 = paddle.randn((4, ), dtype="float32") verify_model(MatMul1(), input_data=[input_data1, input_data2]) # matrix x matrix @@ -450,11 +495,15 @@ def forward(self, input1, input2): input_data2 = paddle.randn((4, 5), dtype="float32") verify_model(MatMul1(), input_data=[input_data1, input_data2]) + @tvm.testing.uses_gpu def test_forward_pool2d(): @paddle.jit.to_static def pool2d1(inputs): - return nn.functional.avg_pool2d(inputs, kernel_size=2, stride=2, padding=0) + return nn.functional.avg_pool2d(inputs, + kernel_size=2, + stride=2, + padding=0) @paddle.jit.to_static def pool2d2(inputs): @@ -462,13 +511,21 @@ def pool2d2(inputs): @paddle.jit.to_static def pool2d3(inputs): - return nn.functional.max_pool2d(inputs, kernel_size=2, stride=2, padding=0, return_mask=True) - - input_data = paddle.uniform(shape=[1, 2, 32, 32], dtype='float32', min=-1, max=1) + return nn.functional.max_pool2d(inputs, + kernel_size=2, + stride=2, + padding=0, + return_mask=True) + + input_data = paddle.uniform(shape=[1, 2, 32, 32], + dtype='float32', + min=-1, + max=1) verify_model(pool2d1, input_data=input_data) verify_model(pool2d2, input_data=input_data) # verify_model(pool2d3, input_data=input_data) + @tvm.testing.uses_gpu def test_forward_relu(): @paddle.jit.to_static @@ -479,6 +536,7 @@ def relu(inputs): input_data = paddle.rand(input_shape, dtype="float32") verify_model(relu, input_data=input_data) + @tvm.testing.uses_gpu def test_forward_reshape(): @paddle.jit.to_static @@ -508,6 +566,7 @@ def reshape4(inputs, x): verify_model(reshape3, input_data=paddle.randn((2, 3, 4))) verify_model(reshape4, input_data=[input_data, input_data2]) + @tvm.testing.uses_gpu def test_forward_scale(): @paddle.jit.to_static @@ -518,10 +577,13 @@ def scale1(inputs): def scale2(inputs): return paddle.scale(inputs, scale=3, bias=2.1, act="gelu") - input_data = paddle.randn(shape=[2,3], dtype='float32') - verify_model(scale1, input_data=[input_data,]) + input_data = paddle.randn(shape=[2, 3], dtype='float32') + verify_model(scale1, input_data=[ + input_data, + ]) verify_model(scale2, input_data=input_data) + @tvm.testing.uses_gpu def test_forward_slice(): @paddle.jit.to_static @@ -541,15 +603,19 @@ def slice4(inputs): x0 = paddle.to_tensor([2]) - paddle.to_tensor([1]) x1 = paddle.to_tensor([3]) + paddle.to_tensor([1]) return inputs[:, x0:, 1:x1, :] + input_shape = [1, 3, 10, 10] input_data = paddle.rand(input_shape, dtype="float32") - verify_model(slice1, input_data=[input_data,]) + verify_model(slice1, input_data=[ + input_data, + ]) verify_model(slice2, input_data=input_data) # need op "strided_slice" # verify_model(slice3, input_data=paddle.randn((4, 4))) # need op "assign_value" # verify_model(slice4, input_data=input_data) + @tvm.testing.uses_gpu def test_forward_tanh(): @paddle.jit.to_static @@ -560,6 +626,7 @@ def tanh(inputs): input_data = paddle.rand(input_shape, dtype="float32") verify_model(tanh, input_data=input_data) + if __name__ == "__main__": test_forward_add_subtract() test_forward_argmax() From 80d308a8e096e0ac1cd4781c8e69aa5267c25e0d Mon Sep 17 00:00:00 2001 From: root Date: Fri, 13 Aug 2021 07:55:21 +0000 Subject: [PATCH 020/127] use black to format python code --- python/tvm/relay/frontend/paddlepaddle.py | 563 +++++++++--------- .../frontend/paddlepaddle/test_forward.py | 122 ++-- 2 files changed, 343 insertions(+), 342 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index c95ed0108b49..c67c8b9c39e0 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -42,7 +42,7 @@ __all__ = ["from_paddle"] -def shape_of(x, dtype='int32'): +def shape_of(x, dtype="int32"): ttype = infer_type(x).checked_type if not _ty.is_dynamic(ttype): shape = list(ttype.shape) @@ -65,74 +65,76 @@ def _get_pad_size(in_size, dilated_kernel_size, stride_size): def convert_arg_max(g, op, block): """Operator converter for arg_max.""" - axis = op.attr('axis') - keepdims = op.attr('keepdims') - flatten = op.attr('flatten') + axis = op.attr("axis") + keepdims = op.attr("keepdims") + flatten = op.attr("flatten") - x = g.get_node(op.input('X')[0]) + x = g.get_node(op.input("X")[0]) if axis is None or flatten: x = _op.reshape(x, [-1]) out = _op.argmax(x, axis=None, keepdims=True) else: out = _op.argmax(x, axis=axis, keepdims=keepdims) - g.add_node(op.output('Out')[0], out) + g.add_node(op.output("Out")[0], out) def convert_assign(g, op, block): """Operator converter for assign.""" - out = _op.copy(g.get_node(op.input('X')[0])) - g.add_node(op.output('Out')[0], out) + out = _op.copy(g.get_node(op.input("X")[0])) + g.add_node(op.output("Out")[0], out) def convert_batch_norm(g, op, block): """Operator converter for batch_norm.""" - ipt_name = op.input('X')[0] - scale_name = op.input('Scale')[0] - bias_name = op.input('Bias')[0] - mean_name = op.input('Mean')[0] - variance_name = op.input('Variance')[0] - epsilon = op.attr('epsilon') - momentum = op.attr('momentum') - out = _op.nn.batch_norm(g.get_node(ipt_name), - g.get_node(scale_name), - g.get_node(bias_name), - g.get_node(mean_name), - g.get_node(variance_name), - epsilon=epsilon) - g.add_node(op.output('Y')[0], out[0]) + ipt_name = op.input("X")[0] + scale_name = op.input("Scale")[0] + bias_name = op.input("Bias")[0] + mean_name = op.input("Mean")[0] + variance_name = op.input("Variance")[0] + epsilon = op.attr("epsilon") + momentum = op.attr("momentum") + out = _op.nn.batch_norm( + g.get_node(ipt_name), + g.get_node(scale_name), + g.get_node(bias_name), + g.get_node(mean_name), + g.get_node(variance_name), + epsilon=epsilon, + ) + g.add_node(op.output("Y")[0], out[0]) def convert_cast(g, op, block): """Operator converter for cast.""" - dtype = block.var(op.output('Out')[0]).dtype - dtype = str(dtype).strip().split('.')[1] - x = g.get_node(op.input('X')[0]) + dtype = block.var(op.output("Out")[0]).dtype + dtype = str(dtype).strip().split(".")[1] + x = g.get_node(op.input("X")[0]) out = _op.cast(x, dtype=dtype) - g.add_node(op.output('Out')[0], out) + g.add_node(op.output("Out")[0], out) def convert_concat(g, op, block): """Operator converter for concat.""" - inputs = [g.get_node(op.input('X')[i]) for i in range(len(op.input('X')))] - axis = op.attr('axis') + inputs = [g.get_node(op.input("X")[i]) for i in range(len(op.input("X")))] + axis = op.attr("axis") out = _op.concatenate(inputs, axis=axis) - g.add_node(op.output('Out')[0], out) + g.add_node(op.output("Out")[0], out) def convert_conv2d(g, op, block): """Operator converter for conv2d.""" - dilations = op.attr('dilations') - groups = op.attr('groups') - paddings = op.attr('paddings') - padding_algorithm = op.attr('padding_algorithm') - strides = op.attr('strides') - - kernel = g.get_node(op.input('Filter')[0]) - input = g.get_node(op.input('Input')[0]) + dilations = op.attr("dilations") + groups = op.attr("groups") + paddings = op.attr("paddings") + padding_algorithm = op.attr("padding_algorithm") + strides = op.attr("strides") + + kernel = g.get_node(op.input("Filter")[0]) + input = g.get_node(op.input("Input")[0]) out_channels, _, k_h, k_w = infer_shape(kernel) in_h, in_w = infer_shape(input)[2:] if padding_algorithm == "VALID": @@ -150,26 +152,28 @@ def convert_conv2d(g, op, block): msg = 'Value {} in attribute "padding" of operator Conv is not ' "valid." raise tvm.error.OpAttributeInvalid(msg.format(padding_algorithm)) - out = _op.nn.conv2d(input, - kernel, - strides=strides, - padding=paddings, - dilation=dilations, - groups=groups, - channels=out_channels, - kernel_size=[k_h, k_w]) - g.add_node(op.output('Output')[0], out) + out = _op.nn.conv2d( + input, + kernel, + strides=strides, + padding=paddings, + dilation=dilations, + groups=groups, + channels=out_channels, + kernel_size=[k_h, k_w], + ) + g.add_node(op.output("Output")[0], out) def convert_cumsum(g, op, block): """Operator converter for cumsum.""" - axis = op.attr('axis') - exclusive = op.attr('exclusive') - flatten = op.attr('flatten') - reverse = op.attr('reverse') + axis = op.attr("axis") + exclusive = op.attr("exclusive") + flatten = op.attr("flatten") + reverse = op.attr("reverse") - x = g.get_node(op.input('X')[0]) + x = g.get_node(op.input("X")[0]) if axis is None or flatten: x = _op.reshape(x, [-1]) if reverse: @@ -178,80 +182,78 @@ def convert_cumsum(g, op, block): out = _op.reverse(out, axis=axis) else: out = _op.cumsum(x, axis=axis, exclusive=exclusive) - g.add_node(op.output('Out')[0], out) + g.add_node(op.output("Out")[0], out) def convert_dropout(g, op, block): """Operator converter for dropout.""" - x = g.get_node(op.input('X')[0]) + x = g.get_node(op.input("X")[0]) out = _op.copy(x) - g.add_node(op.output('Out')[0], out) + g.add_node(op.output("Out")[0], out) def convert_elementwise_op(g, op, block): """Operator converter for all the elementwise operators.""" op_map = { - 'elementwise_div': lambda x, y: x / y, - 'elementwise_add': lambda x, y: x + y, - 'elementwise_mul': lambda x, y: x * y, - 'elementwise_sub': lambda x, y: x - y, - 'elementwise_mod': lambda x, y: x % y, + "elementwise_div": lambda x, y: x / y, + "elementwise_add": lambda x, y: x + y, + "elementwise_mul": lambda x, y: x * y, + "elementwise_sub": lambda x, y: x - y, + "elementwise_mod": lambda x, y: x % y, } op_func = op_map[op.type] - ipt0 = g.get_node(op.input('X')[0]) - ipt1 = g.get_node(op.input('Y')[0]) - ipt0_shape = block.var(op.input('X')[0]).shape - ipt1_shape = block.var(op.input('Y')[0]).shape - axis = op.attr('axis') + ipt0 = g.get_node(op.input("X")[0]) + ipt1 = g.get_node(op.input("Y")[0]) + ipt0_shape = block.var(op.input("X")[0]).shape + ipt1_shape = block.var(op.input("Y")[0]).shape + axis = op.attr("axis") if len(ipt0_shape) != len(ipt1_shape): if axis < 0: axis = axis + len(ipt0_shape) if axis != len(ipt0_shape) - 1: - ipt1 = _op.expand_dims(ipt1, - axis=axis, - num_newaxis=(len(ipt0_shape) - axis - 1)) + ipt1 = _op.expand_dims(ipt1, axis=axis, num_newaxis=(len(ipt0_shape) - axis - 1)) out = op_func(ipt0, ipt1) - g.add_node(op.output('Out')[0], out) + g.add_node(op.output("Out")[0], out) def convert_equal(g, op, block): """Operator converter for equal.""" - x = g.get_node(op.input('X')[0]) - y = g.get_node(op.input('Y')[0]) + x = g.get_node(op.input("X")[0]) + y = g.get_node(op.input("Y")[0]) out = _op.equal(x, y) - g.add_node(op.output('Out')[0], out) + g.add_node(op.output("Out")[0], out) def convert_activation(g, op, block): """Operator converter for all the activation.""" op_map = { - 'exp': _op.exp, - 'relu': _op.nn.relu, - 'tanh': _op.tanh, - 'sqrt': _op.sqrt, - 'erf': _op.erf, - 'abs': _op.abs, + "exp": _op.exp, + "relu": _op.nn.relu, + "tanh": _op.tanh, + "sqrt": _op.sqrt, + "erf": _op.erf, + "abs": _op.abs, } act_func = op_map[op.type] - out = act_func(g.get_node(op.input('X')[0])) - g.add_node(op.output('Out')[0], out) + out = act_func(g.get_node(op.input("X")[0])) + g.add_node(op.output("Out")[0], out) def convert_feed(g, op, block): """Converter for model input node.""" if block is not None: - ipt_name = op.output('Out')[0] + ipt_name = op.output("Out")[0] ipt_shape = block.var(ipt_name).shape ipt_dtype = block.var(ipt_name).dtype - ipt_dtype = str(ipt_dtype).strip().split('.')[1] + ipt_dtype = str(ipt_dtype).strip().split(".")[1] else: ipt_shape = op.shape - ipt_dtype = str(op.dtype).strip().split('.')[1] + ipt_dtype = str(op.dtype).strip().split(".")[1] ipt_name = op.name if g.shape_dict is not None: ipt_shape = g.shape_dict[ipt_name] @@ -262,92 +264,90 @@ def convert_feed(g, op, block): def convert_fill_any_like(g, op, block): """Operator converter for fill_any_like.""" - out_name = op.output('Out')[0] + out_name = op.output("Out")[0] out_dtype = block.var(out_name).dtype - out_dtype = str(out_dtype).strip().split('.')[1] - x = g.get_node(op.input('X')[0]) + out_dtype = str(out_dtype).strip().split(".")[1] + x = g.get_node(op.input("X")[0]) ipt_type = infer_type(x).checked_type - value = op.attr('value') + value = op.attr("value") if not _ty.is_dynamic(ipt_type): shape = infer_shape(x) const = np.ones(shape) * value out = _expr.const(const.astype(out_dtype)) else: out = _op.transform.full_like(x, value).astype(out_dtype) - g.add_node(op.output('Out')[0], out) + g.add_node(op.output("Out")[0], out) def convert_fill_constant(g, op, block): """Operator converter for fill_constant.""" - value = op.attr('value') - shape = block.var(op.output('Out')[0]).shape - dtype = block.var(op.output('Out')[0]).dtype - dtype = str(dtype).strip().split('.')[1] - if op.input('ValueTensor'): - shape = g.get_node(op.input('ValueTensor')[0]) + value = op.attr("value") + shape = block.var(op.output("Out")[0]).shape + dtype = block.var(op.output("Out")[0]).dtype + dtype = str(dtype).strip().split(".")[1] + if op.input("ValueTensor"): + shape = g.get_node(op.input("ValueTensor")[0]) shape = infer_value(shape, g.get_params()).numpy() - if op.input('ShapeTensor'): - shape = g.get_node(op.input('ShapeTensor')[0]) + if op.input("ShapeTensor"): + shape = g.get_node(op.input("ShapeTensor")[0]) shape = infer_value(shape, g.get_params()).numpy() value = np.full(shape, value, dtype) out = _expr.const(value.astype(dtype)).astype(dtype) - g.add_node(op.output('Out')[0], out) + g.add_node(op.output("Out")[0], out) def convert_gelu(g, op, block): """Operator converter for gelu.""" - x = g.get_node(op.input('X')[0]) - out = x * (_expr.const(0.5, dtype='float32') + - _op.erf(x * _expr.const(0.5**0.5, dtype='float32')) * - _expr.const(0.5, dtype='float32')) - g.add_node(op.output('Out')[0], out) + x = g.get_node(op.input("X")[0]) + out = x * ( + _expr.const(0.5, dtype="float32") + + _op.erf(x * _expr.const(0.5 ** 0.5, dtype="float32")) * _expr.const(0.5, dtype="float32") + ) + g.add_node(op.output("Out")[0], out) def convert_hard_sigmoid(g, op, block): """Operator converter for hard_sigmoid.""" - slope = op.attr('slope') - offset = op.attr('offset') - x = g.get_node(op.input('X')[0]) + slope = op.attr("slope") + offset = op.attr("offset") + x = g.get_node(op.input("X")[0]) out = x * _expr.const(slope) + _expr.const(0.5) out = _op.clip(out, 0, 1) - g.add_node(op.output('Out')[0], out) + g.add_node(op.output("Out")[0], out) def convert_hard_swish(g, op, block): """Operator converter for hard_swish.""" - offset = op.attr('offset') - scale = op.attr('scale') - threshold = op.attr('threshold') - assert np.isclose( - offset, 3.0), "Only support offset==3.0 for PaddlePaddle's hard_swish" - assert np.isclose( - scale, 6.0), "Only support scale==6.0 for PaddlePaddle's hard_swish" - assert np.isclose( - threshold, - 6.0), "Only support threshold==6.0 for PaddlePaddle's hard_swish" - x = g.get_node(op.input('X')[0]) + offset = op.attr("offset") + scale = op.attr("scale") + threshold = op.attr("threshold") + assert np.isclose(offset, 3.0), "Only support offset==3.0 for PaddlePaddle's hard_swish" + assert np.isclose(scale, 6.0), "Only support scale==6.0 for PaddlePaddle's hard_swish" + assert np.isclose(threshold, 6.0), "Only support threshold==6.0 for PaddlePaddle's hard_swish" + x = g.get_node(op.input("X")[0]) out = _op.clip(x, -1 * offset, offset) out = out / _expr.const(threshold) + _expr.const(0.5) out = x * out - g.add_node(op.output('Out')[0], out) + g.add_node(op.output("Out")[0], out) def convert_layer_norm(g, op, block): """Operator converter for layer_norm.""" - begin_norm_axis = op.attr('begin_norm_axis') - epsilon = op.attr('epsilon') - x = g.get_node(op.input('X')[0]) - bias_input = op.input('Bias') - scale_input = op.input('Scale') + begin_norm_axis = op.attr("begin_norm_axis") + epsilon = op.attr("epsilon") + x = g.get_node(op.input("X")[0]) + bias_input = op.input("Bias") + scale_input = op.input("Scale") x_shape = infer_shape(x) - assert begin_norm_axis == -1 or begin_norm_axis == len( - x_shape) - 1, "Support only normalization over last one dimension." + assert ( + begin_norm_axis == -1 or begin_norm_axis == len(x_shape) - 1 + ), "Support only normalization over last one dimension." if bias_input: bias = g.get_node(bias_input[0]) @@ -359,54 +359,50 @@ def convert_layer_norm(g, op, block): else: scale = _expr.const(np.ones(x_shape[begin_norm_axis])) - out = _op.nn.layer_norm(x, - gamma=scale, - beta=bias, - axis=begin_norm_axis, - epsilon=epsilon, - center=True, - scale=True) - g.add_node(op.output('Y')[0], out) + out = _op.nn.layer_norm( + x, gamma=scale, beta=bias, axis=begin_norm_axis, epsilon=epsilon, center=True, scale=True + ) + g.add_node(op.output("Y")[0], out) def convert_leaky_relu(g, op, block): """Operator converter for leaky_relu.""" - alpha = op.attr('alpha') - x = g.get_node(op.input('X')[0]) + alpha = op.attr("alpha") + x = g.get_node(op.input("X")[0]) out = _op.nn.leaky_relu(x, alpha=alpha) - g.add_node(op.output('Out')[0], out) + g.add_node(op.output("Out")[0], out) def convert_lookup_table(g, op, block): """Operator converter for lookup_table_v2.""" - indices = g.get_node(op.input('Ids')[0]) - padding_idx = op.attr('padding_idx') - is_sparse = op.attr('is_sparse') - height_sections = op.attr('height_sections') + indices = g.get_node(op.input("Ids")[0]) + padding_idx = op.attr("padding_idx") + is_sparse = op.attr("is_sparse") + height_sections = op.attr("height_sections") if padding_idx != -1: - g.get_params[op.input('W')[0]][padding_idx] = 0.0 - g.add_node(op.input('W')[0], _expr.const(g.params[op.input('W')[0]])) - weights = g.get_node(op.input('W')[0]) - out = _op.take(weights, indices.astype('int32'), axis=0) - g.add_node(op.output('Out')[0], out) + g.get_params[op.input("W")[0]][padding_idx] = 0.0 + g.add_node(op.input("W")[0], _expr.const(g.params[op.input("W")[0]])) + weights = g.get_node(op.input("W")[0]) + out = _op.take(weights, indices.astype("int32"), axis=0) + g.add_node(op.output("Out")[0], out) def convert_matmul(g, op, block): """Operator converter for matmul.""" - inputs = [g.get_node(op.input('X')[0]), g.get_node(op.input('Y')[0])] + inputs = [g.get_node(op.input("X")[0]), g.get_node(op.input("Y")[0])] a_shape = infer_shape(inputs[0]) b_shape = infer_shape(inputs[1]) try: # for matmul_v2 - trans_x = op.attr('trans_x') - trans_y = op.attr('trans_y') + trans_x = op.attr("trans_x") + trans_y = op.attr("trans_y") except: # for matmul - trans_x = op.attr('transpose_X') - trans_y = op.attr('transpose_Y') + trans_x = op.attr("transpose_X") + trans_y = op.attr("transpose_Y") if trans_x: perm = list(range(len(a_shape))) perm[-2] = len(a_shape) - 1 @@ -433,8 +429,7 @@ def flatten_to_nd(x, x_shape, nd=3): return x newshape = _op.concatenate( [ - _expr.const([-1], - dtype=infer_type(x_shape).checked_type.dtype), + _expr.const([-1], dtype=infer_type(x_shape).checked_type.dtype), _op.strided_slice(x_shape, [ndims - nd + 1], [ndims]), ], 0, @@ -469,7 +464,8 @@ def flatten_to_nd(x, x_shape, nd=3): _op.maximum( _op.strided_slice(a_shape, [i], [i + 1]), _op.strided_slice(b_shape, [i], [i + 1]), - ) for i in range(a_rank - 2) + ) + for i in range(a_rank - 2) ], 0, ) @@ -477,10 +473,12 @@ def flatten_to_nd(x, x_shape, nd=3): final_shape = _op.concatenate( [ out_batch, - _op.strided_slice(a_shape, [infer_shape(a_shape)[0] - 2], - [infer_shape(a_shape)[0] - 1]), - _op.strided_slice(b_shape, [infer_shape(b_shape)[0] - 1], - [infer_shape(b_shape)[0]]), + _op.strided_slice( + a_shape, [infer_shape(a_shape)[0] - 2], [infer_shape(a_shape)[0] - 1] + ), + _op.strided_slice( + b_shape, [infer_shape(b_shape)[0] - 1], [infer_shape(b_shape)[0]] + ), ], 0, ) @@ -494,21 +492,21 @@ def flatten_to_nd(x, x_shape, nd=3): if b_rank == 1: out = _op.squeeze(out, axis=[-1]) try: - alpha = op.attr('alpha') + alpha = op.attr("alpha") if not np.isclose(alpha, 1.0): - out = out * _expr.const(alpha).astype('float32') + out = out * _expr.const(alpha).astype("float32") except: pass - g.add_node(op.output('Out')[0], out) + g.add_node(op.output("Out")[0], out) def convert_mul(g, op, block): """Operator converter for mul.""" - x = g.get_node(op.input('X')[0]) - y = g.get_node(op.input('Y')[0]) - x_num_col_dims = op.attr('x_num_col_dims') - y_num_col_dims = op.attr('y_num_col_dims') + x = g.get_node(op.input("X")[0]) + y = g.get_node(op.input("Y")[0]) + x_num_col_dims = op.attr("x_num_col_dims") + y_num_col_dims = op.attr("y_num_col_dims") x_shape = shape_of(x) y_shape = shape_of(y) x_dim = infer_shape(x_shape)[0] @@ -520,24 +518,20 @@ def convert_mul(g, op, block): if x_num_col_dims == 1: x = _op.nn.batch_flatten(x) else: - pre_shape = _op.prod(_op.strided_slice(x_shape, [0], [x_num_col_dims], - [1]), - keepdims=True) - post_shape = _op.prod(_op.strided_slice(x_shape, [x_num_col_dims], - [x_dim], [1]), - keepdims=True) + pre_shape = _op.prod(_op.strided_slice(x_shape, [0], [x_num_col_dims], [1]), keepdims=True) + post_shape = _op.prod( + _op.strided_slice(x_shape, [x_num_col_dims], [x_dim], [1]), keepdims=True + ) new_shape = _op.concatenate([pre_shape, post_shape], axis=0) new_shape = fold_constant(new_shape) x = _op.reshape(x, new_shape) if y_num_col_dims == 1: y = _op.nn.batch_flatten(y) else: - pre_shape = _op.prod(_op.strided_slice(y_shape, [0], [y_num_col_dims], - [1]), - keepdims=True) - post_shape = _op.prod(_op.strided_slice(y_shape, [y_num_col_dims], - [y_dim], [1]), - keepdims=True) + pre_shape = _op.prod(_op.strided_slice(y_shape, [0], [y_num_col_dims], [1]), keepdims=True) + post_shape = _op.prod( + _op.strided_slice(y_shape, [y_num_col_dims], [y_dim], [1]), keepdims=True + ) new_shape = _op.concatenate([pre_shape, post_shape], axis=0) new_shape = fold_constant(new_shape) y = _op.reshape(y, new_shape) @@ -548,31 +542,31 @@ def convert_mul(g, op, block): out_shape = _op.concatenate([out_pre_shape, out_post_shape], axis=0) out_shape = fold_constant(out_shape) out = _op.reshape(out, out_shape) - g.add_node(op.output('Out')[0], out) + g.add_node(op.output("Out")[0], out) def convert_pool2d(g, op, block): """Operator converter for pool2d.""" - adaptive = op.attr('adaptive') - ceil_mode = op.attr('ceil_mode') - global_pooling = op.attr('global_pooling') - ksize = op.attr('ksize') - paddings = op.attr('paddings') - padding_algorithm = op.attr('padding_algorithm') - pooling_type = op.attr('pooling_type') + adaptive = op.attr("adaptive") + ceil_mode = op.attr("ceil_mode") + global_pooling = op.attr("global_pooling") + ksize = op.attr("ksize") + paddings = op.attr("paddings") + padding_algorithm = op.attr("padding_algorithm") + pooling_type = op.attr("pooling_type") if global_pooling: adaptive = True ksize = [1, 1] - input = g.get_node(op.input('X')[0]) + input = g.get_node(op.input("X")[0]) in_h, in_w = infer_shape(input)[2:] op_map = { - 'avg': 'avg_pool2d', - 'max': 'max_pool2d', + "avg": "avg_pool2d", + "max": "max_pool2d", } - strides = op.attr('strides') + strides = op.attr("strides") if isinstance(strides, int): strides = [strides, strides] if isinstance(ksize, int): @@ -595,25 +589,22 @@ def convert_pool2d(g, op, block): msg = 'Value {} in attribute "padding" of operator Pool2d is not ' "valid." raise tvm.error.OpAttributeInvalid(msg.format(padding_algorithm)) - x = g.get_node(op.input('X')[0]) + x = g.get_node(op.input("X")[0]) if not adaptive: - out = getattr(_op.nn, op_map[pooling_type])(x, - pool_size=ksize, - strides=strides, - padding=paddings, - ceil_mode=ceil_mode) + out = getattr(_op.nn, op_map[pooling_type])( + x, pool_size=ksize, strides=strides, padding=paddings, ceil_mode=ceil_mode + ) else: - out = getattr(_op.nn, - "adaptive_" + op_map[pooling_type])(x, output_size=ksize) - g.add_node(op.output('Out')[0], out) + out = getattr(_op.nn, "adaptive_" + op_map[pooling_type])(x, output_size=ksize) + g.add_node(op.output("Out")[0], out) def convert_reshape(g, op, block): """Operator converter for reshape.""" - input_shape = op.input('Shape') - input_shape_tensor = op.input('ShapeTensor') - data = g.get_node(op.input('X')[0]) + input_shape = op.input("Shape") + input_shape_tensor = op.input("ShapeTensor") + data = g.get_node(op.input("X")[0]) if input_shape: new_shape = g.get_node(input_shape[0]) elif input_shape_tensor: @@ -627,49 +618,51 @@ def convert_reshape(g, op, block): elif isinstance(shape, _expr.Expr): tmp_shape.append(shape) else: - tmp_shape.append(_expr.const(np.array(shape).astype('int64'))) + tmp_shape.append(_expr.const(np.array(shape).astype("int64"))) new_shape = _op.concatenate(tmp_shape, axis=0) else: - new_shape = op.attr('shape') + new_shape = op.attr("shape") out = _op.reshape(data, new_shape) - g.add_node(op.output('Out')[0], out) + g.add_node(op.output("Out")[0], out) def convert_scale(g, op, block): """Operator converter for scale.""" - scale = op.attr('scale') - bias = op.attr('bias') - bias_after_scale = op.attr('bias_after_scale') - x = g.get_node(op.input('X')[0]) + scale = op.attr("scale") + bias = op.attr("bias") + bias_after_scale = op.attr("bias_after_scale") + x = g.get_node(op.input("X")[0]) if np.isclose(scale, 1.0) and np.isclose(bias, 0.0): out = _op.copy(x) else: if np.isclose(bias, 0.0): - out = x * _expr.const(np.array(scale).astype('float32')) + out = x * _expr.const(np.array(scale).astype("float32")) elif np.isclose(scale, 1.0): - out = x + _expr.const(np.array(bias).astype('float32')) + out = x + _expr.const(np.array(bias).astype("float32")) else: if bias_after_scale: - out = x * _expr.const( - np.array(scale).astype('float32')) + _expr.const( - np.array(bias).astype('float32')) + out = x * _expr.const(np.array(scale).astype("float32")) + _expr.const( + np.array(bias).astype("float32") + ) else: - out = (x + _expr.const(np.array(bias).astype('float32')) - ) * _expr.const(np.array(scale).astype('float32')) - g.add_node(op.output('Out')[0], out) + out = (x + _expr.const(np.array(bias).astype("float32"))) * _expr.const( + np.array(scale).astype("float32") + ) + g.add_node(op.output("Out")[0], out) def convert_shape(g, op, block): """Operator converter for shape.""" - x = g.get_node(op.input('Input')[0]) + x = g.get_node(op.input("Input")[0]) out = shape_of(x) - g.add_node(op.output('Out')[0], out) + g.add_node(op.output("Out")[0], out) def convert_slice(g, op, block): """Operator converter for slice.""" + def parameter_process(starts, ends, axes, dshape): new_axes = [] new_starts = [] @@ -686,12 +679,12 @@ def parameter_process(starts, ends, axes, dshape): new_ends.append(dshape[i]) return new_starts, new_ends, new_axes - data = g.get_node(op.input('Input')[0]) + data = g.get_node(op.input("Input")[0]) dshape = infer_shape(data) - starts = op.attr('starts') - ends = op.attr('ends') - axes = op.attr('axes') - decrease_axis = op.attr('decrease_axis') + starts = op.attr("starts") + ends = op.attr("ends") + axes = op.attr("axes") + decrease_axis = op.attr("decrease_axis") if isinstance(starts, int): starts = [starts] if isinstance(ends, int): @@ -704,75 +697,76 @@ def parameter_process(starts, ends, axes, dshape): out = _op.strided_slice(data, begin=starts, end=ends) if decrease_axis: out = _op.squeeze(out, axis=decrease_axis) - g.add_node(op.output('Out')[0], out) + g.add_node(op.output("Out")[0], out) def convert_softmax(g, op, block): """Operator converter for softmax.""" - axis = op.attr('axis') - input_shape = block.var(op.input('X')[0]).shape + axis = op.attr("axis") + input_shape = block.var(op.input("X")[0]).shape if axis < 0: axis = len(input_shape) + axis - x = g.get_node(op.input('X')[0]) + x = g.get_node(op.input("X")[0]) m = _op.max(x, axis, keepdims=True) e = _op.exp(x - m) out = e / _op.sum(e, axis, keepdims=True) - g.add_node(op.output('Out')[0], out) + g.add_node(op.output("Out")[0], out) def convert_unsqueeze(g, op, block): """Operator converter for unsqueeze.""" - x = g.get_node(op.input('X')[0]) - axes = sorted(op.attr('axes')) + x = g.get_node(op.input("X")[0]) + axes = sorted(op.attr("axes")) for axis in axes: x = _op.expand_dims(x, axis=axis, num_newaxis=1) - g.add_node(op.output('Out')[0], x) + g.add_node(op.output("Out")[0], x) _convert_map = { - 'arg_max': convert_arg_max, - 'assign': convert_assign, - 'batch_norm': convert_batch_norm, - 'cast': convert_cast, - 'concat': convert_concat, - 'conv2d': convert_conv2d, - 'cumsum': convert_cumsum, - 'depthwise_conv2d': convert_conv2d, - 'dropout': convert_dropout, - 'elementwise_add': convert_elementwise_op, - 'elementwise_div': convert_elementwise_op, - 'elementwise_mul': convert_elementwise_op, - 'elementwise_sub': convert_elementwise_op, - 'equal': convert_equal, - 'exp': convert_activation, - 'feed': convert_feed, - 'fill_any_like': convert_fill_any_like, - 'fill_constant': convert_fill_constant, - 'gelu': convert_gelu, - 'hard_sigmoid': convert_hard_sigmoid, - 'hard_swish': convert_hard_swish, - 'layer_norm': convert_layer_norm, - 'leaky_relu': convert_leaky_relu, - 'lookup_table_v2': convert_lookup_table, - 'matmul': convert_matmul, - 'matmul_v2': convert_matmul, - 'mul': convert_mul, - 'pool2d': convert_pool2d, - 'relu': convert_activation, - 'reshape2': convert_reshape, - 'scale': convert_scale, - 'shape': convert_shape, - 'slice': convert_slice, - 'softmax': convert_softmax, - 'tanh': convert_activation, - 'unsqueeze2': convert_unsqueeze, + "arg_max": convert_arg_max, + "assign": convert_assign, + "batch_norm": convert_batch_norm, + "cast": convert_cast, + "concat": convert_concat, + "conv2d": convert_conv2d, + "cumsum": convert_cumsum, + "depthwise_conv2d": convert_conv2d, + "dropout": convert_dropout, + "elementwise_add": convert_elementwise_op, + "elementwise_div": convert_elementwise_op, + "elementwise_mul": convert_elementwise_op, + "elementwise_sub": convert_elementwise_op, + "equal": convert_equal, + "exp": convert_activation, + "feed": convert_feed, + "fill_any_like": convert_fill_any_like, + "fill_constant": convert_fill_constant, + "gelu": convert_gelu, + "hard_sigmoid": convert_hard_sigmoid, + "hard_swish": convert_hard_swish, + "layer_norm": convert_layer_norm, + "leaky_relu": convert_leaky_relu, + "lookup_table_v2": convert_lookup_table, + "matmul": convert_matmul, + "matmul_v2": convert_matmul, + "mul": convert_mul, + "pool2d": convert_pool2d, + "relu": convert_activation, + "reshape2": convert_reshape, + "scale": convert_scale, + "shape": convert_shape, + "slice": convert_slice, + "softmax": convert_softmax, + "tanh": convert_activation, + "unsqueeze2": convert_unsqueeze, } class GraphProto(object): - """ A helper class for handling relay functions from PaddlePaddle model.""" + """A helper class for handling relay functions from PaddlePaddle model.""" + def __init__(self): self.nodes = {} self.params = {} @@ -792,13 +786,13 @@ def get_params(self, name=None): return self.params[name] def extract_parameters(self, program, scope=None): - """ Extract all the weights from PaddlePaddle program.""" + """Extract all the weights from PaddlePaddle program.""" self.params = {} variables = program.global_block().vars for name in variables: var = program.global_block().var(name) - if name.endswith('feed') or name.endswith('fetch'): + if name.endswith("feed") or name.endswith("fetch"): continue if not var.persistable: continue @@ -809,24 +803,24 @@ def extract_parameters(self, program, scope=None): self.nodes[name] = _expr.const(self.params[name]) def check_input_shape(self, op, block): - """ Check the shape information of model's inputs, fixed shape is recommended.""" + """Check the shape information of model's inputs, fixed shape is recommended.""" ipt_name = op.input(op.input_names[0]) ipt_shape = block.var(ipt_name).shape for i in ipt_shape: if i < 0: - warning_msg = ( - "Input {}(shape={}) has unkown dimension shapes. Specifying static values may improve performance" - .format(ipt_name, ipt_shape)) + warning_msg = "Input {}(shape={}) has unkown dimension shapes. Specifying static values may improve performance".format( + ipt_name, ipt_shape + ) warings.warn(warning_msg) def check_unsupported_ops(self, program): - """ Check whether all the operators are supported.""" + """Check whether all the operators are supported.""" unsupported_ops = set() for block in program.blocks: for i, op in enumerate(block.ops): - if op.type == 'fetch': + if op.type == "fetch": continue if op.type not in _convert_map: unsupported_ops.add(op.type) @@ -836,24 +830,25 @@ def check_unsupported_ops(self, program): raise tvm.error.OpNotImplemented(msg) def ops_to_relay(self, program, input_specs=None): - """ Convert PaddlePaddle operators to TVM relay functions.""" + """Convert PaddlePaddle operators to TVM relay functions.""" if input_specs is not None: for input_spec in input_specs: convert_feed(self, input_spec, None) for block in program.blocks: for i, op in enumerate(block.ops): - if op.type == 'fetch': + if op.type == "fetch": continue convert_func = _convert_map[op.type] convert_func(self, op, block) def from_program(self, program, shape_dict, scope): - """ Construct the TVM relay expression from PaddlePaddle program.""" + """Construct the TVM relay expression from PaddlePaddle program.""" self.shape_dict = shape_dict if scope is None: import paddle + scope = paddle.fluid.global_scope() self.check_unsupported_ops(program) self.extract_parameters(program, scope) @@ -863,7 +858,7 @@ def from_program(self, program, shape_dict, scope): for block in program.blocks: for i, op in enumerate(block.ops): if op.type == "fetch": - output_names.append(op.input('X')[0]) + output_names.append(op.input("X")[0]) outputs = [self.nodes[name] for name in output_names] outputs = outputs[0] if len(outputs) == 1 else _expr.Tuple(outputs) @@ -874,7 +869,7 @@ def from_program(self, program, shape_dict, scope): return mod, self.params def from_translated_layer(self, layer, shape_dict): - """ Construct the TVM relay expression from PaddlePaddle TranslatedLayer.""" + """Construct the TVM relay expression from PaddlePaddle TranslatedLayer.""" self.shape_dict = shape_dict program = layer.program() @@ -899,13 +894,14 @@ def from_translated_layer(self, layer, shape_dict): def from_paddle(program_or_layer, shape_dict=None, scope=None): - """ Convert a PaddlePaddle model into an equivalent Relay Function. + """Convert a PaddlePaddle model into an equivalent Relay Function. - PaddlePaddle Program/TranslatedLayer represent the computation graph of PaddlePaddle model, - and PaddlePaddle scope stores all the weights of PaddlePaddle model. + PaddlePaddle Program/TranslatedLayer represent the computation graph of PaddlePaddle model, + and PaddlePaddle scope stores all the weights of PaddlePaddle model. """ import paddle + g = GraphProto() if isinstance(program_or_layer, paddle.fluid.dygraph.TranslatedLayer): # model is loaded by `paddle.jit.load` @@ -914,6 +910,5 @@ def from_paddle(program_or_layer, shape_dict=None, scope=None): # model is loaded by `paddle.static.load_inference_model` mod, params = g.from_program(program_or_layer, shape_dict, scope) else: - raise Exception( - "Only PaddlePaddle's Program and TranslatedLayer are supported.") + raise Exception("Only PaddlePaddle's Program and TranslatedLayer are supported.") return mod, params diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index 20a110f7d657..db07e07f9d83 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -28,8 +28,7 @@ import paddle import paddle.nn as nn -PADDLE_TEST_DATA_ROOT_PATH = Path( - Path("~").expanduser(), ".tvm_test_data", "paddle") +PADDLE_TEST_DATA_ROOT_PATH = Path(Path("~").expanduser(), ".tvm_test_data", "paddle") PADDLE_TEST_DATA_ROOT_PATH.mkdir(parents=True, exist_ok=True) @@ -61,9 +60,8 @@ def verify_model(func, input_data, rtol=1e-5, atol=1e-5): for idx, data in enumerate(input_data): input_name = "input{}".format(idx) input_spec.append( - paddle.static.InputSpec(dtype=data.dtype, - shape=data.shape, - name=input_name)) + paddle.static.InputSpec(dtype=data.dtype, shape=data.shape, name=input_name) + ) input_names.append(input_name) input_shape_dict[input_name] = data.shape if isinstance(data, np.ndarray): @@ -78,7 +76,7 @@ def verify_model(func, input_data, rtol=1e-5, atol=1e-5): if isinstance(baseline_outputs, (tuple, list)): baseline_outputs = tuple(out.numpy() for out in baseline_outputs) else: - baseline_outputs = (baseline_outputs.numpy(), ) + baseline_outputs = (baseline_outputs.numpy(),) mod, params = relay.frontend.from_paddle(baseline_model, input_shape_dict) parms_num = min(len(input_names), len(mod["main"].params)) @@ -99,10 +97,7 @@ def verify_model(func, input_data, rtol=1e-5, atol=1e-5): compiled_output = gmod.get_output(i).numpy() assert_shapes_match(baseline_output, compiled_output) - tvm.testing.assert_allclose(baseline_output, - compiled_output, - rtol=rtol, - atol=atol) + tvm.testing.assert_allclose(baseline_output, compiled_output, rtol=rtol, atol=atol) @tvm.testing.uses_gpu @@ -168,13 +163,19 @@ def assign(inputs): input_shape = [2, 3] input_data = paddle.rand(input_shape, dtype="float32") - verify_model(assign, [ - input_data, - ]) + verify_model( + assign, + [ + input_data, + ], + ) input_data2 = np.random.randint(100, size=input_shape) - verify_model(assign, [ - input_data2, - ]) + verify_model( + assign, + [ + input_data2, + ], + ) @tvm.testing.uses_gpu @@ -226,28 +227,32 @@ def cast2(inputs, dtype="int64"): input_shape = [2, 3] input_data = paddle.rand(input_shape, dtype="float32") * 100 - verify_model(cast1, [ - input_data, - ]) - verify_model(cast2, [ - input_data, - ]) + verify_model( + cast1, + [ + input_data, + ], + ) + verify_model( + cast2, + [ + input_data, + ], + ) @tvm.testing.uses_gpu def test_forward_concat_unsqueeze(): @paddle.jit.to_static def concat_unsqueeze1(inputs): - return paddle.concat( - [inputs[:, 0].unsqueeze(1), inputs[:, 1].unsqueeze(1)], axis=1) + return paddle.concat([inputs[:, 0].unsqueeze(1), inputs[:, 1].unsqueeze(1)], axis=1) @paddle.jit.to_static def concat_unsqueeze2(inputs): a = (inputs[:, :, 0] + 2) * 7 b = (inputs[:, :, 1] + 3) * 11 c = (inputs[:, :, 2] + 5) * 13 - return paddle.concat([paddle.unsqueeze(t, axis=2) for t in [a, b, c]], - axis=2) + return paddle.concat([paddle.unsqueeze(t, axis=2) for t in [a, b, c]], axis=2) input_shape = [1, 3, 10, 10] input_data = paddle.rand(input_shape, dtype="float32") @@ -272,12 +277,18 @@ def cusum3(inputs): input_data = paddle.randint(0, 100, (10, 10), dtype=paddle.int32) verify_model(cusum1, [input_data]) verify_model(cusum1, [input_data.astype(paddle.int64)]) - verify_model(cusum2, [ - input_data, - ]) - verify_model(cusum3, [ - input_data, - ]) + verify_model( + cusum2, + [ + input_data, + ], + ) + verify_model( + cusum3, + [ + input_data, + ], + ) @tvm.testing.uses_gpu @@ -390,10 +401,7 @@ def hard_swish(inputs): def test_forward_layer_norm(): @paddle.jit.to_static def layer_norm(inputs, weight, bias): - return nn.functional.layer_norm(inputs, - inputs.shape[-1], - weight=weight, - bias=bias) + return nn.functional.layer_norm(inputs, inputs.shape[-1], weight=weight, bias=bias) class LayerNorm(nn.Layer): def __init__(self): @@ -477,7 +485,7 @@ def forward(self, input1, input2): # matrix x vector input_data1 = paddle.randn((3, 4), dtype="float32") - input_data2 = paddle.randn((4, ), dtype="float32") + input_data2 = paddle.randn((4,), dtype="float32") verify_model(MatMul1(), input_data=[input_data1, input_data2]) # matrix x matrix @@ -500,10 +508,7 @@ def forward(self, input1, input2): def test_forward_pool2d(): @paddle.jit.to_static def pool2d1(inputs): - return nn.functional.avg_pool2d(inputs, - kernel_size=2, - stride=2, - padding=0) + return nn.functional.avg_pool2d(inputs, kernel_size=2, stride=2, padding=0) @paddle.jit.to_static def pool2d2(inputs): @@ -511,16 +516,11 @@ def pool2d2(inputs): @paddle.jit.to_static def pool2d3(inputs): - return nn.functional.max_pool2d(inputs, - kernel_size=2, - stride=2, - padding=0, - return_mask=True) - - input_data = paddle.uniform(shape=[1, 2, 32, 32], - dtype='float32', - min=-1, - max=1) + return nn.functional.max_pool2d( + inputs, kernel_size=2, stride=2, padding=0, return_mask=True + ) + + input_data = paddle.uniform(shape=[1, 2, 32, 32], dtype="float32", min=-1, max=1) verify_model(pool2d1, input_data=input_data) verify_model(pool2d2, input_data=input_data) # verify_model(pool2d3, input_data=input_data) @@ -577,10 +577,13 @@ def scale1(inputs): def scale2(inputs): return paddle.scale(inputs, scale=3, bias=2.1, act="gelu") - input_data = paddle.randn(shape=[2, 3], dtype='float32') - verify_model(scale1, input_data=[ - input_data, - ]) + input_data = paddle.randn(shape=[2, 3], dtype="float32") + verify_model( + scale1, + input_data=[ + input_data, + ], + ) verify_model(scale2, input_data=input_data) @@ -606,9 +609,12 @@ def slice4(inputs): input_shape = [1, 3, 10, 10] input_data = paddle.rand(input_shape, dtype="float32") - verify_model(slice1, input_data=[ - input_data, - ]) + verify_model( + slice1, + input_data=[ + input_data, + ], + ) verify_model(slice2, input_data=input_data) # need op "strided_slice" # verify_model(slice3, input_data=paddle.randn((4, 4))) From 618be3939b39d0a92edb446b2c3b162f435fc3b7 Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Tue, 17 Aug 2021 16:49:47 +0800 Subject: [PATCH 021/127] add interpolate op --- python/tvm/relay/frontend/paddlepaddle.py | 115 +++++++++++++++++- .../frontend/paddlepaddle/test_forward.py | 35 ++++++ 2 files changed, 149 insertions(+), 1 deletion(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index c67c8b9c39e0..0757c368d1c7 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -25,6 +25,7 @@ import tvm from tvm.ir import IRModule +from tvm.script.intrin import float32 from .. import analysis from .. import expr as _expr @@ -105,7 +106,116 @@ def convert_batch_norm(g, op, block): ) g.add_node(op.output("Y")[0], out[0]) - +def bilinear_interp_v2_get_shape(input_shape, layout): + dims = len(input_shape) + assert ( + dims > 2 and dims < 6 + ), "input shape({}) error on PaddlePaddle's bilinear_interp_v2".format(dims) + if dims == 3: + if layout == "NCHW": + return None, 1, input_shape[2] + else: + return None, 1, input_shape[1] + elif dims == 4: + if layout == "NCHW": + return None, input_shape[2], input_shape[3] + else: + return None, input_shape[1], input_shape[2] + elif dims == 5: + if layout == "NCHW": + return input_shape[2:] + else: + return input_shape[1:4] + +def bilinear_interp_get_mod(op): + interp_method = op.attr('interp_method') + align_corners = op.attr('align_corners') + align_mode = op.attr('align_mode') + + rounding_method = "" + if interp_method == "nearest": + interp_method = "nearest_neighbor" + coordinate_transformation_mode = "asymmetric" + rounding_method = "floor" + elif interp_method == "bilinear": + interp_method = "linear" + if align_mode == 0 and align_corners == False: + coordinate_transformation_mode = "half_pixel" + else: + if align_corners: + coordinate_transformation_mode = "align_corners" + else: + coordinate_transformation_mode = "asymmetric" + elif interp_method == "bicubic": + interp_method = "cubic" + if align_corners: + coordinate_transformation_mode = "align_corners" + else: + coordinate_transformation_mode = "half_pixel" + else: + msg = "interp_method {} is not supported for PaddlePaddle's bilinear_interp_v2" + raise tvm.error.OpAttributeInvalid(msg.format(interp_method)) + return rounding_method, interp_method, coordinate_transformation_mode + +def convert_bilinear_interp2D(g, op, x, input_shape): + layout = op.attr('data_layout') + if layout == "NCHW": + in_h, in_w = input_shape[2], input_shape[3] + else: + in_h, in_w = input_shape[1], input_shape[2] + + out_h = op.attr('out_h') + out_w = op.attr('out_w') + + OutSize = op.input('OutSize') + SizeTensor = op.input('SizeTensor') + Scale = op.input("Scale") + if SizeTensor: + outsize = g.get_node(SizeTensor[0]) + outsize = infer_value(outsize, g.get_params()).numpy().tolist() + out_h, out_w = outsize + elif OutSize: + outsize = g.get_node(OutSize[0]) + outsize = infer_value(outsize, g.get_params()).numpy().tolist() + out_h, out_w = outsize + elif Scale: + scale_data = g.get_node(Scale[0]) + scale_data = infer_value(scale_data, g.get_params()).numpy().tolist() + if len(scale_data) > 1: + out_h = int(scale_data[0] * in_h) + out_w = int(scale_data[1] * in_w) + else: + out_h = int(scale_data[0] * in_h) + out_w = int(scale_data[0] * in_w) + else: + scale = op.attr('scale') + scale = [float(i) for i in scale] + if len(scale) > 1: + out_h = int(scale[0] * in_h) + out_w = int(scale[1] * in_w) + + rounding_method, interp_method, coordinate_transformation_mode = bilinear_interp_get_mod(op) + out = _op.image.resize2d( + x, + [out_h, out_w], + layout=layout, + method=interp_method, + coordinate_transformation_mode=coordinate_transformation_mode, + rounding_method=rounding_method, + cubic_alpha=-0.75) + g.add_node(op.output('Out')[0], out) + +def convert_bilinear_interp_v2(g, op, block): + """Operator converter for bilinear_interp_v2.""" + x = g.get_node(op.input('X')[0]) + input_shape = infer_shape(x) + dims = len(input_shape) + if dims == 4: + convert_bilinear_interp2D(g, op, x, input_shape) + else: + msg = "input_shape {} is not supported for PaddlePaddle's bilinear_interp_v2" + raise tvm.error.OpAttributeInvalid(msg.format(dims)) + def convert_cast(g, op, block): """Operator converter for cast.""" @@ -728,6 +838,8 @@ def convert_unsqueeze(g, op, block): "arg_max": convert_arg_max, "assign": convert_assign, "batch_norm": convert_batch_norm, + "bicubic_interp_v2": convert_bilinear_interp_v2, + "bilinear_interp_v2": convert_bilinear_interp_v2, "cast": convert_cast, "concat": convert_concat, "conv2d": convert_conv2d, @@ -752,6 +864,7 @@ def convert_unsqueeze(g, op, block): "matmul": convert_matmul, "matmul_v2": convert_matmul, "mul": convert_mul, + "nearest_interp_v2": convert_bilinear_interp_v2, "pool2d": convert_pool2d, "relu": convert_activation, "reshape2": convert_reshape, diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index db07e07f9d83..2c3f8642efa0 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -396,6 +396,40 @@ def hard_swish(inputs): input_data = paddle.rand(input_shape, dtype="float32") verify_model(hard_swish, input_data=input_data) +@tvm.testing.uses_gpu +def test_forward_interpolate(): + class TestBilinear(nn.Layer): + def __init__(self): + super(TestBilinear, self).__init__() + self.conv = nn.Conv2D(3, 5, 3, stride=2) + + def forward(self, x): + shape = paddle.shape(x)[2:] + y = self.conv(x) + return nn.functional.interpolate(y, size=shape, mode='nearest') + + def bilinear_interp1(inputs): + return nn.functional.interpolate(inputs, size=[12, 12], mode='bilinear') + + @paddle.jit.to_static + def bilinear_interp2(inputs): + return nn.functional.interpolate(inputs, scale_factor=[2.0, 1.0], mode='bilinear', align_corners=True, align_mode=1) + + @paddle.jit.to_static + def bilinear_interp3(inputs): + return nn.functional.interpolate(inputs, scale_factor=[1.0, 2.0], mode='bicubic') + + @paddle.jit.to_static + def bilinear_interp4(inputs): + return nn.functional.interpolate(inputs, scale_factor=3.0, mode='bicubic', align_corners=True, align_mode=0) + + input_shape = [2, 3, 6, 12] + input_data = paddle.rand(input_shape, dtype="float32") + verify_model(TestBilinear(), input_data=input_data) + verify_model(bilinear_interp1, input_data=input_data) + verify_model(bilinear_interp2, input_data=input_data) + verify_model(bilinear_interp3, input_data=input_data) + verify_model(bilinear_interp4, input_data=input_data) @tvm.testing.uses_gpu def test_forward_layer_norm(): @@ -648,6 +682,7 @@ def tanh(inputs): test_forward_gelu() test_forward_hard_sigmoid() test_forward_hard_swish() + test_forward_interpolate() test_forward_layer_norm() test_forward_leaky_relu() test_forward_look_up() From 72d75b738bc3af9c6aa23315144db785b4288d4e Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Tue, 17 Aug 2021 16:50:38 +0800 Subject: [PATCH 022/127] add interpolate op --- python/tvm/relay/frontend/paddlepaddle.py | 58 ++++++++++--------- .../frontend/paddlepaddle/test_forward.py | 16 +++-- 2 files changed, 43 insertions(+), 31 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 0757c368d1c7..afa1c8a17d41 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -106,10 +106,11 @@ def convert_batch_norm(g, op, block): ) g.add_node(op.output("Y")[0], out[0]) + def bilinear_interp_v2_get_shape(input_shape, layout): dims = len(input_shape) assert ( - dims > 2 and dims < 6 + dims > 2 and dims < 6 ), "input shape({}) error on PaddlePaddle's bilinear_interp_v2".format(dims) if dims == 3: if layout == "NCHW": @@ -127,11 +128,12 @@ def bilinear_interp_v2_get_shape(input_shape, layout): else: return input_shape[1:4] + def bilinear_interp_get_mod(op): - interp_method = op.attr('interp_method') - align_corners = op.attr('align_corners') - align_mode = op.attr('align_mode') - + interp_method = op.attr("interp_method") + align_corners = op.attr("align_corners") + align_mode = op.attr("align_mode") + rounding_method = "" if interp_method == "nearest": interp_method = "nearest_neighbor" @@ -157,18 +159,19 @@ def bilinear_interp_get_mod(op): raise tvm.error.OpAttributeInvalid(msg.format(interp_method)) return rounding_method, interp_method, coordinate_transformation_mode + def convert_bilinear_interp2D(g, op, x, input_shape): - layout = op.attr('data_layout') + layout = op.attr("data_layout") if layout == "NCHW": in_h, in_w = input_shape[2], input_shape[3] else: in_h, in_w = input_shape[1], input_shape[2] - out_h = op.attr('out_h') - out_w = op.attr('out_w') + out_h = op.attr("out_h") + out_w = op.attr("out_w") - OutSize = op.input('OutSize') - SizeTensor = op.input('SizeTensor') + OutSize = op.input("OutSize") + SizeTensor = op.input("SizeTensor") Scale = op.input("Scale") if SizeTensor: outsize = g.get_node(SizeTensor[0]) @@ -183,31 +186,33 @@ def convert_bilinear_interp2D(g, op, x, input_shape): scale_data = infer_value(scale_data, g.get_params()).numpy().tolist() if len(scale_data) > 1: out_h = int(scale_data[0] * in_h) - out_w = int(scale_data[1] * in_w) + out_w = int(scale_data[1] * in_w) else: out_h = int(scale_data[0] * in_h) - out_w = int(scale_data[0] * in_w) - else: - scale = op.attr('scale') + out_w = int(scale_data[0] * in_w) + else: + scale = op.attr("scale") scale = [float(i) for i in scale] if len(scale) > 1: out_h = int(scale[0] * in_h) - out_w = int(scale[1] * in_w) - + out_w = int(scale[1] * in_w) + rounding_method, interp_method, coordinate_transformation_mode = bilinear_interp_get_mod(op) out = _op.image.resize2d( - x, - [out_h, out_w], - layout=layout, - method=interp_method, - coordinate_transformation_mode=coordinate_transformation_mode, - rounding_method=rounding_method, - cubic_alpha=-0.75) - g.add_node(op.output('Out')[0], out) + x, + [out_h, out_w], + layout=layout, + method=interp_method, + coordinate_transformation_mode=coordinate_transformation_mode, + rounding_method=rounding_method, + cubic_alpha=-0.75, + ) + g.add_node(op.output("Out")[0], out) + def convert_bilinear_interp_v2(g, op, block): """Operator converter for bilinear_interp_v2.""" - x = g.get_node(op.input('X')[0]) + x = g.get_node(op.input("X")[0]) input_shape = infer_shape(x) dims = len(input_shape) if dims == 4: @@ -215,7 +220,8 @@ def convert_bilinear_interp_v2(g, op, block): else: msg = "input_shape {} is not supported for PaddlePaddle's bilinear_interp_v2" raise tvm.error.OpAttributeInvalid(msg.format(dims)) - + + def convert_cast(g, op, block): """Operator converter for cast.""" diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index 2c3f8642efa0..2aa2db6b8c3c 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -396,6 +396,7 @@ def hard_swish(inputs): input_data = paddle.rand(input_shape, dtype="float32") verify_model(hard_swish, input_data=input_data) + @tvm.testing.uses_gpu def test_forward_interpolate(): class TestBilinear(nn.Layer): @@ -406,22 +407,26 @@ def __init__(self): def forward(self, x): shape = paddle.shape(x)[2:] y = self.conv(x) - return nn.functional.interpolate(y, size=shape, mode='nearest') + return nn.functional.interpolate(y, size=shape, mode="nearest") def bilinear_interp1(inputs): - return nn.functional.interpolate(inputs, size=[12, 12], mode='bilinear') + return nn.functional.interpolate(inputs, size=[12, 12], mode="bilinear") @paddle.jit.to_static def bilinear_interp2(inputs): - return nn.functional.interpolate(inputs, scale_factor=[2.0, 1.0], mode='bilinear', align_corners=True, align_mode=1) + return nn.functional.interpolate( + inputs, scale_factor=[2.0, 1.0], mode="bilinear", align_corners=True, align_mode=1 + ) @paddle.jit.to_static def bilinear_interp3(inputs): - return nn.functional.interpolate(inputs, scale_factor=[1.0, 2.0], mode='bicubic') + return nn.functional.interpolate(inputs, scale_factor=[1.0, 2.0], mode="bicubic") @paddle.jit.to_static def bilinear_interp4(inputs): - return nn.functional.interpolate(inputs, scale_factor=3.0, mode='bicubic', align_corners=True, align_mode=0) + return nn.functional.interpolate( + inputs, scale_factor=3.0, mode="bicubic", align_corners=True, align_mode=0 + ) input_shape = [2, 3, 6, 12] input_data = paddle.rand(input_shape, dtype="float32") @@ -431,6 +436,7 @@ def bilinear_interp4(inputs): verify_model(bilinear_interp3, input_data=input_data) verify_model(bilinear_interp4, input_data=input_data) + @tvm.testing.uses_gpu def test_forward_layer_norm(): @paddle.jit.to_static From e0aa61545b90fbdf861d6ae47d61d171e616e343 Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Tue, 17 Aug 2021 17:04:30 +0800 Subject: [PATCH 023/127] add interpolate op --- python/tvm/relay/frontend/paddlepaddle.py | 1 - 1 file changed, 1 deletion(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index afa1c8a17d41..fbd1a72aa2ce 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -25,7 +25,6 @@ import tvm from tvm.ir import IRModule -from tvm.script.intrin import float32 from .. import analysis from .. import expr as _expr From 202893c453d612fcdf268ca1210d186d34f8ee4c Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Tue, 17 Aug 2021 19:55:30 +0800 Subject: [PATCH 024/127] pylint check --- python/tvm/relay/frontend/paddlepaddle.py | 59 ++++++++++++----------- 1 file changed, 31 insertions(+), 28 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index c67c8b9c39e0..ab17c3b6daa4 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -17,9 +17,7 @@ # pylint: disable=invalid-name, import-self, len-as-condition, unused-argument, too-many-lines # pylint: disable=import-outside-toplevel """Paddle: PArallel Distributed Deep LEarning.""" -import copy import warnings -import six import numpy as np @@ -43,6 +41,8 @@ def shape_of(x, dtype="int32"): + """Get shape of a tensor""" + ttype = infer_type(x).checked_type if not _ty.is_dynamic(ttype): shape = list(ttype.shape) @@ -51,6 +51,8 @@ def shape_of(x, dtype="int32"): def _get_pad_size(in_size, dilated_kernel_size, stride_size): + """calculate the paddings size""" + if stride_size == 1 or in_size % stride_size == 0: pad = max(dilated_kernel_size - stride_size, 0) else: @@ -94,7 +96,6 @@ def convert_batch_norm(g, op, block): mean_name = op.input("Mean")[0] variance_name = op.input("Variance")[0] epsilon = op.attr("epsilon") - momentum = op.attr("momentum") out = _op.nn.batch_norm( g.get_node(ipt_name), g.get_node(scale_name), @@ -127,6 +128,7 @@ def convert_concat(g, op, block): def convert_conv2d(g, op, block): """Operator converter for conv2d.""" + dilations = op.attr("dilations") groups = op.attr("groups") paddings = op.attr("paddings") @@ -134,9 +136,9 @@ def convert_conv2d(g, op, block): strides = op.attr("strides") kernel = g.get_node(op.input("Filter")[0]) - input = g.get_node(op.input("Input")[0]) + input_x = g.get_node(op.input("Input")[0]) out_channels, _, k_h, k_w = infer_shape(kernel) - in_h, in_w = infer_shape(input)[2:] + in_h, in_w = infer_shape(input_x)[2:] if padding_algorithm == "VALID": paddings = [0, 0] elif padding_algorithm == "SAME": @@ -149,11 +151,11 @@ def convert_conv2d(g, op, block): if len(paddings) == 4: paddings = [paddings[0], paddings[2], paddings[1], paddings[3]] else: - msg = 'Value {} in attribute "padding" of operator Conv is not ' "valid." + msg = 'Value {} in attribute "padding" of operator Conv is not "valid."' raise tvm.error.OpAttributeInvalid(msg.format(padding_algorithm)) out = _op.nn.conv2d( - input, + input_x, kernel, strides=strides, padding=paddings, @@ -312,7 +314,6 @@ def convert_hard_sigmoid(g, op, block): """Operator converter for hard_sigmoid.""" slope = op.attr("slope") - offset = op.attr("offset") x = g.get_node(op.input("X")[0]) out = x * _expr.const(slope) + _expr.const(0.5) out = _op.clip(out, 0, 1) @@ -346,7 +347,7 @@ def convert_layer_norm(g, op, block): x_shape = infer_shape(x) assert ( - begin_norm_axis == -1 or begin_norm_axis == len(x_shape) - 1 + begin_norm_axis in (len(x_shape) - 1, -1) ), "Support only normalization over last one dimension." if bias_input: @@ -379,8 +380,6 @@ def convert_lookup_table(g, op, block): indices = g.get_node(op.input("Ids")[0]) padding_idx = op.attr("padding_idx") - is_sparse = op.attr("is_sparse") - height_sections = op.attr("height_sections") if padding_idx != -1: g.get_params[op.input("W")[0]][padding_idx] = 0.0 g.add_node(op.input("W")[0], _expr.const(g.params[op.input("W")[0]])) @@ -395,11 +394,11 @@ def convert_matmul(g, op, block): inputs = [g.get_node(op.input("X")[0]), g.get_node(op.input("Y")[0])] a_shape = infer_shape(inputs[0]) b_shape = infer_shape(inputs[1]) - try: + if op.has_attr("trans_x"): # for matmul_v2 trans_x = op.attr("trans_x") trans_y = op.attr("trans_y") - except: + else: # for matmul trans_x = op.attr("transpose_X") trans_y = op.attr("transpose_Y") @@ -491,12 +490,10 @@ def flatten_to_nd(x, x_shape, nd=3): out = _op.nn.dense(inputs[0], input_1_t) if b_rank == 1: out = _op.squeeze(out, axis=[-1]) - try: + if op.has_attr("alpha"): alpha = op.attr("alpha") if not np.isclose(alpha, 1.0): out = out * _expr.const(alpha).astype("float32") - except: - pass g.add_node(op.output("Out")[0], out) @@ -559,8 +556,8 @@ def convert_pool2d(g, op, block): adaptive = True ksize = [1, 1] - input = g.get_node(op.input("X")[0]) - in_h, in_w = infer_shape(input)[2:] + input_x = g.get_node(op.input("X")[0]) + in_h, in_w = infer_shape(input_x)[2:] op_map = { "avg": "avg_pool2d", @@ -586,16 +583,15 @@ def convert_pool2d(g, op, block): if len(paddings) == 4: paddings = [paddings[0], paddings[2], paddings[1], paddings[3]] else: - msg = 'Value {} in attribute "padding" of operator Pool2d is not ' "valid." + msg = 'Value {} in attribute "padding" of operator Pool2d is not "valid."' raise tvm.error.OpAttributeInvalid(msg.format(padding_algorithm)) - x = g.get_node(op.input("X")[0]) if not adaptive: out = getattr(_op.nn, op_map[pooling_type])( - x, pool_size=ksize, strides=strides, padding=paddings, ceil_mode=ceil_mode + input_x, pool_size=ksize, strides=strides, padding=paddings, ceil_mode=ceil_mode ) else: - out = getattr(_op.nn, "adaptive_" + op_map[pooling_type])(x, output_size=ksize) + out = getattr(_op.nn, "adaptive_" + op_map[pooling_type])(input_x, output_size=ksize) g.add_node(op.output("Out")[0], out) @@ -764,7 +760,7 @@ def convert_unsqueeze(g, op, block): } -class GraphProto(object): +class GraphProto: """A helper class for handling relay functions from PaddlePaddle model.""" def __init__(self): @@ -773,13 +769,19 @@ def __init__(self): self.shape_dict = None def get_node(self, name): + """get node from graph""" + assert name in self.nodes return self.nodes[name] def add_node(self, name, node): + """add a node to graph""" + self.nodes[name] = fold_constant(node) def get_params(self, name=None): + """get params from graph""" + if name is None: return self.params assert name in self.params @@ -809,17 +811,18 @@ def check_input_shape(self, op, block): ipt_shape = block.var(ipt_name).shape for i in ipt_shape: if i < 0: - warning_msg = "Input {}(shape={}) has unkown dimension shapes. Specifying static values may improve performance".format( + warning_msg = "Input {}(shape={}) has unkown dimension shapes. \ + Specifying static values may improve performance".format( ipt_name, ipt_shape ) - warings.warn(warning_msg) + warnings.warn(warning_msg) def check_unsupported_ops(self, program): """Check whether all the operators are supported.""" unsupported_ops = set() for block in program.blocks: - for i, op in enumerate(block.ops): + for op in block.ops: if op.type == "fetch": continue if op.type not in _convert_map: @@ -836,7 +839,7 @@ def ops_to_relay(self, program, input_specs=None): for input_spec in input_specs: convert_feed(self, input_spec, None) for block in program.blocks: - for i, op in enumerate(block.ops): + for op in block.ops: if op.type == "fetch": continue convert_func = _convert_map[op.type] @@ -856,7 +859,7 @@ def from_program(self, program, shape_dict, scope): output_names = list() for block in program.blocks: - for i, op in enumerate(block.ops): + for op in block.ops: if op.type == "fetch": output_names.append(op.input("X")[0]) From a281d602eca0a8a307e2788bcc388d14c9f94af8 Mon Sep 17 00:00:00 2001 From: jiangjiajun <928090362@qq.com> Date: Wed, 18 Aug 2021 02:27:59 +0000 Subject: [PATCH 025/127] Remove fluid api --- python/tvm/relay/frontend/paddlepaddle.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index ab17c3b6daa4..0b59f1d8ea58 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -906,10 +906,10 @@ def from_paddle(program_or_layer, shape_dict=None, scope=None): import paddle g = GraphProto() - if isinstance(program_or_layer, paddle.fluid.dygraph.TranslatedLayer): + if isinstance(program_or_layer, paddle.jit.TranslatedLayer): # model is loaded by `paddle.jit.load` mod, params = g.from_translated_layer(program_or_layer, shape_dict) - elif isinstance(program_or_layer, paddle.fluid.framework.Program): + elif isinstance(program_or_layer, paddle.static.Program): # model is loaded by `paddle.static.load_inference_model` mod, params = g.from_program(program_or_layer, shape_dict, scope) else: From be0e04ece30672c86b44009b27d1d253ee79e8a5 Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Wed, 18 Aug 2021 10:40:24 +0800 Subject: [PATCH 026/127] black format --- python/tvm/relay/frontend/paddlepaddle.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 0b59f1d8ea58..76a12691d2bf 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -346,8 +346,9 @@ def convert_layer_norm(g, op, block): scale_input = op.input("Scale") x_shape = infer_shape(x) - assert ( - begin_norm_axis in (len(x_shape) - 1, -1) + assert begin_norm_axis in ( + len(x_shape) - 1, + -1, ), "Support only normalization over last one dimension." if bias_input: From a7470aba4c4d4ddccb0beae888702052d3ffa177 Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Wed, 18 Aug 2021 15:44:46 +0800 Subject: [PATCH 027/127] formatting and add squeeze2 op --- python/tvm/relay/frontend/paddlepaddle.py | 64 +++++++++---------- .../frontend/paddlepaddle/test_forward.py | 29 ++++++++- 2 files changed, 56 insertions(+), 37 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 98475c8e92da..831e5cf146e7 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -107,29 +107,9 @@ def convert_batch_norm(g, op, block): g.add_node(op.output("Y")[0], out[0]) -def bilinear_interp_v2_get_shape(input_shape, layout): - dims = len(input_shape) - assert ( - dims > 2 and dims < 6 - ), "input shape({}) error on PaddlePaddle's bilinear_interp_v2".format(dims) - if dims == 3: - if layout == "NCHW": - return None, 1, input_shape[2] - else: - return None, 1, input_shape[1] - elif dims == 4: - if layout == "NCHW": - return None, input_shape[2], input_shape[3] - else: - return None, input_shape[1], input_shape[2] - elif dims == 5: - if layout == "NCHW": - return input_shape[2:] - else: - return input_shape[1:4] +def interpolate_get_mode(op): + """conver 'interp_method' attr of paddle to tvm""" - -def bilinear_interp_get_mod(op): interp_method = op.attr("interp_method") align_corners = op.attr("align_corners") align_mode = op.attr("align_mode") @@ -141,7 +121,7 @@ def bilinear_interp_get_mod(op): rounding_method = "floor" elif interp_method == "bilinear": interp_method = "linear" - if align_mode == 0 and align_corners == False: + if not align_corners and align_mode == 0: coordinate_transformation_mode = "half_pixel" else: if align_corners: @@ -155,12 +135,14 @@ def bilinear_interp_get_mod(op): else: coordinate_transformation_mode = "half_pixel" else: - msg = "interp_method {} is not supported for PaddlePaddle's bilinear_interp_v2" + msg = "interp_method {} is not supported for PaddlePaddle's interpolate" raise tvm.error.OpAttributeInvalid(msg.format(interp_method)) return rounding_method, interp_method, coordinate_transformation_mode -def convert_bilinear_interp2D(g, op, x, input_shape): +def convert_interpolate2D(g, op, x, input_shape): + """Operator converter for interpolate 2D(dims == 4).""" + layout = op.attr("data_layout") if layout == "NCHW": in_h, in_w = input_shape[2], input_shape[3] @@ -210,15 +192,16 @@ def convert_bilinear_interp2D(g, op, x, input_shape): g.add_node(op.output("Out")[0], out) -def convert_bilinear_interp_v2(g, op, block): - """Operator converter for bilinear_interp_v2.""" +def convert_interpolate(g, op, block): + """Operator converter for interpolate.""" + x = g.get_node(op.input("X")[0]) input_shape = infer_shape(x) dims = len(input_shape) if dims == 4: - convert_bilinear_interp2D(g, op, x, input_shape) + convert_interpolate2D(g, op, x, input_shape) else: - msg = "input_shape {} is not supported for PaddlePaddle's bilinear_interp_v2" + msg = "input_shape {} is not supported for PaddlePaddle's interpolate" raise tvm.error.OpAttributeInvalid(msg.format(dims)) @@ -461,8 +444,9 @@ def convert_layer_norm(g, op, block): scale_input = op.input("Scale") x_shape = infer_shape(x) - assert ( - begin_norm_axis in (len(x_shape) - 1, -1) + assert begin_norm_axis in ( + len(x_shape) - 1, + -1, ), "Support only normalization over last one dimension." if bias_input: @@ -825,6 +809,17 @@ def convert_softmax(g, op, block): g.add_node(op.output("Out")[0], out) +def convert_squeeze(g, op, block): + """Operator converter for squeeze2.""" + + x = g.get_node(op.input("X")[0]) + axes = op.attr("axes") + if not axes: + axes = None + x = _op.squeeze(x, axis=axes) + g.add_node(op.output("Out")[0], x) + + def convert_unsqueeze(g, op, block): """Operator converter for unsqueeze.""" @@ -839,8 +834,8 @@ def convert_unsqueeze(g, op, block): "arg_max": convert_arg_max, "assign": convert_assign, "batch_norm": convert_batch_norm, - "bicubic_interp_v2": convert_bilinear_interp_v2, - "bilinear_interp_v2": convert_bilinear_interp_v2, + "bicubic_interp_v2": convert_interpolate, + "bilinear_interp_v2": convert_interpolate, "cast": convert_cast, "concat": convert_concat, "conv2d": convert_conv2d, @@ -865,7 +860,7 @@ def convert_unsqueeze(g, op, block): "matmul": convert_matmul, "matmul_v2": convert_matmul, "mul": convert_mul, - "nearest_interp_v2": convert_bilinear_interp_v2, + "nearest_interp_v2": convert_interpolate, "pool2d": convert_pool2d, "relu": convert_activation, "reshape2": convert_reshape, @@ -873,6 +868,7 @@ def convert_unsqueeze(g, op, block): "shape": convert_shape, "slice": convert_slice, "softmax": convert_softmax, + "squeeze2": convert_squeeze, "tanh": convert_activation, "unsqueeze2": convert_unsqueeze, } diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index 2aa2db6b8c3c..85c6c610724f 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -14,19 +14,20 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. -import os from pathlib import Path import shutil import numpy as np + +import paddle +import paddle.nn as nn + import tvm import tvm.testing import tvm.topi.testing from tvm import relay from tvm.contrib import graph_executor -import paddle -import paddle.nn as nn PADDLE_TEST_DATA_ROOT_PATH = Path(Path("~").expanduser(), ".tvm_test_data", "paddle") PADDLE_TEST_DATA_ROOT_PATH.mkdir(parents=True, exist_ok=True) @@ -662,6 +663,27 @@ def slice4(inputs): # verify_model(slice4, input_data=input_data) +@tvm.testing.uses_gpu +def test_forward_squeeze2(): + @paddle.jit.to_static + def squeeze(inputs): + return paddle.squeeze(inputs) + + @paddle.jit.to_static + def squeeze2(inputs): + return paddle.squeeze(inputs, axis=0) + + @paddle.jit.to_static + def squeeze3(inputs): + return paddle.squeeze(inputs, axis=[0, -1]) + + input_shape = [1, 2, 1, 3, 1] + input_data = paddle.rand(input_shape, dtype="float32") + verify_model(squeeze, input_data=input_data) + verify_model(squeeze2, input_data=input_data) + verify_model(squeeze3, input_data=input_data) + + @tvm.testing.uses_gpu def test_forward_tanh(): @paddle.jit.to_static @@ -699,4 +721,5 @@ def tanh(inputs): test_forward_reshape() test_forward_scale() test_forward_slice() + test_forward_squeeze2() test_forward_tanh() From 3c4ce68e92a213c748a9a5dda0e78d3e3042d479 Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Wed, 18 Aug 2021 15:48:19 +0800 Subject: [PATCH 028/127] formatting --- python/tvm/relay/frontend/paddlepaddle.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 831e5cf146e7..3af1d4f496ec 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -107,7 +107,7 @@ def convert_batch_norm(g, op, block): g.add_node(op.output("Y")[0], out[0]) -def interpolate_get_mode(op): +def get_interpolate_mode(op): """conver 'interp_method' attr of paddle to tvm""" interp_method = op.attr("interp_method") @@ -179,7 +179,7 @@ def convert_interpolate2D(g, op, x, input_shape): out_h = int(scale[0] * in_h) out_w = int(scale[1] * in_w) - rounding_method, interp_method, coordinate_transformation_mode = bilinear_interp_get_mod(op) + rounding_method, interp_method, coordinate_transformation_mode = get_interpolate_mode(op) out = _op.image.resize2d( x, [out_h, out_w], From ff893f45c8dd0143d09b3c04b3b38a603ed48fff Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Fri, 20 Aug 2021 11:34:20 +0800 Subject: [PATCH 029/127] add pad op --- python/tvm/relay/frontend/paddlepaddle.py | 34 ++++++++++++++++ .../frontend/paddlepaddle/test_forward.py | 39 +++++++++++++++++++ 2 files changed, 73 insertions(+) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 3af1d4f496ec..db363e4512c8 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -694,6 +694,39 @@ def convert_pool2d(g, op, block): g.add_node(op.output("Out")[0], out) +def convert_padding(g, op, block): + """Operator converter for padding.""" + + input_x = g.get_node(op.input("X")[0]) + input_padding = op.input("Paddings") + if input_padding: + padding = g.get_node(input_padding[0]) + padding = infer_value(padding, g.get_params()).numpy().tolist() + else: + padding = op.attr("paddings") + padding = op.attr("paddings") + value = op.attr("value") + data_format = op.attr("data_format") + mode = op.attr("mode") + assert mode != "circular", "Don't support mod='circular' for PaddlePaddle's padding" + if mode == "replicate": + mode = "edge" + + new_pad_len = len(infer_shape(input_x)) * 2 + new_paddings = [0] * new_pad_len + for i in range(0, len(padding), 2): + index = -1 - i + if data_format[:2] != "NC": + index = -3 - i + new_paddings[index] = padding[i + 1] + new_paddings[index - 1] = padding[i] + + new_paddings = [new_paddings[i : i + 2] for i in range(0, len(new_paddings), 2)] + + out = _op.nn.pad(input_x, new_paddings, pad_value=value, pad_mode=mode) + g.add_node(op.output("Out")[0], out) + + def convert_reshape(g, op, block): """Operator converter for reshape.""" @@ -862,6 +895,7 @@ def convert_unsqueeze(g, op, block): "mul": convert_mul, "nearest_interp_v2": convert_interpolate, "pool2d": convert_pool2d, + "pad3d": convert_padding, "relu": convert_activation, "reshape2": convert_reshape, "scale": convert_scale, diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index 85c6c610724f..662cf268c667 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -567,6 +567,44 @@ def pool2d3(inputs): # verify_model(pool2d3, input_data=input_data) +@tvm.testing.uses_gpu +def test_forward_pad(): + class Pad1(nn.Layer): + def __init__(self): + super(Pad, self).__init__() + self.pad = nn.Pad3D(padding=[1, 2, 3, 4, 5, 6], mode="replicate", value=0.5) + + @paddle.jit.to_static + def forward(self, inputs): + return self.pad(inputs) + + @paddle.jit.to_static + def pad2(inputs): + return paddle.nn.functional.pad( + inputs, [1, 3, 1, 4, 1, 0], mode="constant", value=2.2, data_format="NDHWC" + ) + + @paddle.jit.to_static + def pad3(inputs): + return paddle.nn.functional.pad( + inputs, [2, 3, 1, 0], mode="reflect", value=2.0, data_format="NCHW" + ) + + @paddle.jit.to_static + def pad4(inputs): + return paddle.nn.functional.pad( + inputs, [2, 1], mode="replicate", value=2.0, data_format="NLC" + ) + + input_data = paddle.rand([2, 3, 6, 7, 8], dtype="float32") + verify_model(Pad1(), input_data=input_data) + verify_model(pad2, input_data=input_data) + input_data = paddle.rand([2, 4, 3, 5], dtype="float32") + verify_model(pad3, input_data=input_data) + input_data = paddle.rand([2, 4, 5], dtype="float32") + verify_model(pad4, input_data=input_data) + + @tvm.testing.uses_gpu def test_forward_relu(): @paddle.jit.to_static @@ -717,6 +755,7 @@ def tanh(inputs): test_forward_multiply() test_forward_matmul() test_forward_pool2d() + test_forward_pad() test_forward_relu() test_forward_reshape() test_forward_scale() From b31be857bf1f0c6c8108fc1513b04b33aed8feec Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Fri, 20 Aug 2021 11:38:37 +0800 Subject: [PATCH 030/127] add pad1d padd2d --- python/tvm/relay/frontend/paddlepaddle.py | 2 ++ tests/python/frontend/paddlepaddle/test_forward.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index db363e4512c8..702457ac71e6 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -895,6 +895,8 @@ def convert_unsqueeze(g, op, block): "mul": convert_mul, "nearest_interp_v2": convert_interpolate, "pool2d": convert_pool2d, + "pad1d": convert_padding, + "pad2d": convert_padding, "pad3d": convert_padding, "relu": convert_activation, "reshape2": convert_reshape, diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index 662cf268c667..e4756b040aa1 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -571,7 +571,7 @@ def pool2d3(inputs): def test_forward_pad(): class Pad1(nn.Layer): def __init__(self): - super(Pad, self).__init__() + super(Pad1, self).__init__() self.pad = nn.Pad3D(padding=[1, 2, 3, 4, 5, 6], mode="replicate", value=0.5) @paddle.jit.to_static From f7fcd84f868e36df3eaa6b9e201c120f5b913bd2 Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Fri, 20 Aug 2021 15:08:06 +0800 Subject: [PATCH 031/127] foramtting --- python/tvm/relay/frontend/paddlepaddle.py | 30 +++++++++++------------ 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 702457ac71e6..447b3a645a09 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -140,7 +140,7 @@ def get_interpolate_mode(op): return rounding_method, interp_method, coordinate_transformation_mode -def convert_interpolate2D(g, op, x, input_shape): +def convert_interpolate2d(g, op, x, input_shape): """Operator converter for interpolate 2D(dims == 4).""" layout = op.attr("data_layout") @@ -152,19 +152,19 @@ def convert_interpolate2D(g, op, x, input_shape): out_h = op.attr("out_h") out_w = op.attr("out_w") - OutSize = op.input("OutSize") - SizeTensor = op.input("SizeTensor") - Scale = op.input("Scale") - if SizeTensor: - outsize = g.get_node(SizeTensor[0]) - outsize = infer_value(outsize, g.get_params()).numpy().tolist() - out_h, out_w = outsize - elif OutSize: - outsize = g.get_node(OutSize[0]) - outsize = infer_value(outsize, g.get_params()).numpy().tolist() - out_h, out_w = outsize - elif Scale: - scale_data = g.get_node(Scale[0]) + input_out_size = op.input("OutSize") + input_size_tensor = op.input("SizeTensor") + input_scale = op.input("Scale") + if input_size_tensor: + out_size = g.get_node(input_size_tensor[0]) + out_size = infer_value(out_size, g.get_params()).numpy().tolist() + out_h, out_w = out_size + elif input_out_size: + out_size = g.get_node(input_out_size[0]) + out_size = infer_value(out_size, g.get_params()).numpy().tolist() + out_h, out_w = out_size + elif input_scale: + scale_data = g.get_node(input_scale[0]) scale_data = infer_value(scale_data, g.get_params()).numpy().tolist() if len(scale_data) > 1: out_h = int(scale_data[0] * in_h) @@ -199,7 +199,7 @@ def convert_interpolate(g, op, block): input_shape = infer_shape(x) dims = len(input_shape) if dims == 4: - convert_interpolate2D(g, op, x, input_shape) + convert_interpolate2d(g, op, x, input_shape) else: msg = "input_shape {} is not supported for PaddlePaddle's interpolate" raise tvm.error.OpAttributeInvalid(msg.format(dims)) From 272c8f970d91127bd13c3085596c5a962f0db6ab Mon Sep 17 00:00:00 2001 From: wjj19950828 Date: Fri, 20 Aug 2021 17:50:15 +0800 Subject: [PATCH 032/127] Add conv_transpose and sigmoid --- python/tvm/relay/frontend/paddlepaddle.py | 150 +++++++++++++----- .../frontend/paddlepaddle/test_forward.py | 107 ++++++++++--- 2 files changed, 192 insertions(+), 65 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index c67c8b9c39e0..7116bc2ad13e 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -17,9 +17,7 @@ # pylint: disable=invalid-name, import-self, len-as-condition, unused-argument, too-many-lines # pylint: disable=import-outside-toplevel """Paddle: PArallel Distributed Deep LEarning.""" -import copy import warnings -import six import numpy as np @@ -43,6 +41,8 @@ def shape_of(x, dtype="int32"): + """Get shape of a tensor""" + ttype = infer_type(x).checked_type if not _ty.is_dynamic(ttype): shape = list(ttype.shape) @@ -51,6 +51,8 @@ def shape_of(x, dtype="int32"): def _get_pad_size(in_size, dilated_kernel_size, stride_size): + """calculate the paddings size""" + if stride_size == 1 or in_size % stride_size == 0: pad = max(dilated_kernel_size - stride_size, 0) else: @@ -94,7 +96,6 @@ def convert_batch_norm(g, op, block): mean_name = op.input("Mean")[0] variance_name = op.input("Variance")[0] epsilon = op.attr("epsilon") - momentum = op.attr("momentum") out = _op.nn.batch_norm( g.get_node(ipt_name), g.get_node(scale_name), @@ -127,6 +128,7 @@ def convert_concat(g, op, block): def convert_conv2d(g, op, block): """Operator converter for conv2d.""" + dilations = op.attr("dilations") groups = op.attr("groups") paddings = op.attr("paddings") @@ -134,9 +136,9 @@ def convert_conv2d(g, op, block): strides = op.attr("strides") kernel = g.get_node(op.input("Filter")[0]) - input = g.get_node(op.input("Input")[0]) + input_x = g.get_node(op.input("Input")[0]) out_channels, _, k_h, k_w = infer_shape(kernel) - in_h, in_w = infer_shape(input)[2:] + in_h, in_w = infer_shape(input_x)[2:] if padding_algorithm == "VALID": paddings = [0, 0] elif padding_algorithm == "SAME": @@ -149,11 +151,54 @@ def convert_conv2d(g, op, block): if len(paddings) == 4: paddings = [paddings[0], paddings[2], paddings[1], paddings[3]] else: - msg = 'Value {} in attribute "padding" of operator Conv is not ' "valid." + msg = 'Value {} in attribute "padding" of operator Conv is not "valid."' raise tvm.error.OpAttributeInvalid(msg.format(padding_algorithm)) out = _op.nn.conv2d( - input, + input_x, + kernel, + strides=strides, + padding=paddings, + dilation=dilations, + groups=groups, + channels=out_channels, + kernel_size=[k_h, k_w], + ) + g.add_node(op.output("Output")[0], out) + + +def convert_conv2d_transpose(g, op, block): + """Operator converter for conv2d_transpose.""" + + dilations = op.attr("dilations") + groups = op.attr("groups") + paddings = op.attr("paddings") + padding_algorithm = op.attr("padding_algorithm") + strides = op.attr("strides") + output_padding = op.attr("output_padding") if op.attr( + "output_padding") else [0, 0] + + kernel = g.get_node(op.input("Filter")[0]) + input_x = g.get_node(op.input("Input")[0]) + _, out_channels, k_h, k_w = infer_shape(kernel) + in_h, in_w = infer_shape(input_x)[2:] + if padding_algorithm == "VALID": + paddings = [0, 0] + elif padding_algorithm == "SAME": + pad_h = _get_pad_size(in_h, (k_h - 1) * dilations[0] + 1, strides[0]) + pad_w = _get_pad_size(in_w, (k_w - 1) * dilations[1] + 1, strides[1]) + paddings = [pad_h[0], pad_w[0], pad_h[1], pad_w[1]] + elif padding_algorithm == "EXPLICIT": + if len(paddings) == 2: + paddings = [paddings[0], paddings[1], paddings[0], paddings[1]] + if len(paddings) == 4: + paddings = [paddings[0], paddings[2], paddings[1], paddings[3]] + else: + msg = 'Value {} in attribute "padding" of operator Conv is not "valid."' + raise tvm.error.OpAttributeInvalid(msg.format(padding_algorithm)) + + out = _op.nn.conv2d_transpose( + input_x, kernel, strides=strides, padding=paddings, @@ -161,6 +206,7 @@ def convert_conv2d(g, op, block): groups=groups, channels=out_channels, kernel_size=[k_h, k_w], + output_padding=output_padding, ) g.add_node(op.output("Output")[0], out) @@ -213,7 +259,8 @@ def convert_elementwise_op(g, op, block): if axis < 0: axis = axis + len(ipt0_shape) if axis != len(ipt0_shape) - 1: - ipt1 = _op.expand_dims(ipt1, axis=axis, num_newaxis=(len(ipt0_shape) - axis - 1)) + ipt1 = _op.expand_dims( + ipt1, axis=axis, num_newaxis=(len(ipt0_shape) - axis - 1)) out = op_func(ipt0, ipt1) g.add_node(op.output("Out")[0], out) @@ -303,7 +350,8 @@ def convert_gelu(g, op, block): x = g.get_node(op.input("X")[0]) out = x * ( _expr.const(0.5, dtype="float32") - + _op.erf(x * _expr.const(0.5 ** 0.5, dtype="float32")) * _expr.const(0.5, dtype="float32") + + _op.erf(x * _expr.const(0.5 ** 0.5, dtype="float32")) * + _expr.const(0.5, dtype="float32") ) g.add_node(op.output("Out")[0], out) @@ -312,7 +360,6 @@ def convert_hard_sigmoid(g, op, block): """Operator converter for hard_sigmoid.""" slope = op.attr("slope") - offset = op.attr("offset") x = g.get_node(op.input("X")[0]) out = x * _expr.const(slope) + _expr.const(0.5) out = _op.clip(out, 0, 1) @@ -325,9 +372,12 @@ def convert_hard_swish(g, op, block): offset = op.attr("offset") scale = op.attr("scale") threshold = op.attr("threshold") - assert np.isclose(offset, 3.0), "Only support offset==3.0 for PaddlePaddle's hard_swish" - assert np.isclose(scale, 6.0), "Only support scale==6.0 for PaddlePaddle's hard_swish" - assert np.isclose(threshold, 6.0), "Only support threshold==6.0 for PaddlePaddle's hard_swish" + assert np.isclose( + offset, 3.0), "Only support offset==3.0 for PaddlePaddle's hard_swish" + assert np.isclose( + scale, 6.0), "Only support scale==6.0 for PaddlePaddle's hard_swish" + assert np.isclose( + threshold, 6.0), "Only support threshold==6.0 for PaddlePaddle's hard_swish" x = g.get_node(op.input("X")[0]) out = _op.clip(x, -1 * offset, offset) out = out / _expr.const(threshold) + _expr.const(0.5) @@ -345,8 +395,9 @@ def convert_layer_norm(g, op, block): scale_input = op.input("Scale") x_shape = infer_shape(x) - assert ( - begin_norm_axis == -1 or begin_norm_axis == len(x_shape) - 1 + assert begin_norm_axis in ( + len(x_shape) - 1, + -1, ), "Support only normalization over last one dimension." if bias_input: @@ -379,8 +430,6 @@ def convert_lookup_table(g, op, block): indices = g.get_node(op.input("Ids")[0]) padding_idx = op.attr("padding_idx") - is_sparse = op.attr("is_sparse") - height_sections = op.attr("height_sections") if padding_idx != -1: g.get_params[op.input("W")[0]][padding_idx] = 0.0 g.add_node(op.input("W")[0], _expr.const(g.params[op.input("W")[0]])) @@ -395,11 +444,11 @@ def convert_matmul(g, op, block): inputs = [g.get_node(op.input("X")[0]), g.get_node(op.input("Y")[0])] a_shape = infer_shape(inputs[0]) b_shape = infer_shape(inputs[1]) - try: + if op.has_attr("trans_x"): # for matmul_v2 trans_x = op.attr("trans_x") trans_y = op.attr("trans_y") - except: + else: # for matmul trans_x = op.attr("transpose_X") trans_y = op.attr("transpose_Y") @@ -429,7 +478,8 @@ def flatten_to_nd(x, x_shape, nd=3): return x newshape = _op.concatenate( [ - _expr.const([-1], dtype=infer_type(x_shape).checked_type.dtype), + _expr.const( + [-1], dtype=infer_type(x_shape).checked_type.dtype), _op.strided_slice(x_shape, [ndims - nd + 1], [ndims]), ], 0, @@ -474,10 +524,12 @@ def flatten_to_nd(x, x_shape, nd=3): [ out_batch, _op.strided_slice( - a_shape, [infer_shape(a_shape)[0] - 2], [infer_shape(a_shape)[0] - 1] + a_shape, [infer_shape(a_shape)[0] - + 2], [infer_shape(a_shape)[0] - 1] ), _op.strided_slice( - b_shape, [infer_shape(b_shape)[0] - 1], [infer_shape(b_shape)[0]] + b_shape, [infer_shape(b_shape)[0] - + 1], [infer_shape(b_shape)[0]] ), ], 0, @@ -491,12 +543,10 @@ def flatten_to_nd(x, x_shape, nd=3): out = _op.nn.dense(inputs[0], input_1_t) if b_rank == 1: out = _op.squeeze(out, axis=[-1]) - try: + if op.has_attr("alpha"): alpha = op.attr("alpha") if not np.isclose(alpha, 1.0): out = out * _expr.const(alpha).astype("float32") - except: - pass g.add_node(op.output("Out")[0], out) @@ -518,7 +568,8 @@ def convert_mul(g, op, block): if x_num_col_dims == 1: x = _op.nn.batch_flatten(x) else: - pre_shape = _op.prod(_op.strided_slice(x_shape, [0], [x_num_col_dims], [1]), keepdims=True) + pre_shape = _op.prod(_op.strided_slice( + x_shape, [0], [x_num_col_dims], [1]), keepdims=True) post_shape = _op.prod( _op.strided_slice(x_shape, [x_num_col_dims], [x_dim], [1]), keepdims=True ) @@ -528,7 +579,8 @@ def convert_mul(g, op, block): if y_num_col_dims == 1: y = _op.nn.batch_flatten(y) else: - pre_shape = _op.prod(_op.strided_slice(y_shape, [0], [y_num_col_dims], [1]), keepdims=True) + pre_shape = _op.prod(_op.strided_slice( + y_shape, [0], [y_num_col_dims], [1]), keepdims=True) post_shape = _op.prod( _op.strided_slice(y_shape, [y_num_col_dims], [y_dim], [1]), keepdims=True ) @@ -559,8 +611,8 @@ def convert_pool2d(g, op, block): adaptive = True ksize = [1, 1] - input = g.get_node(op.input("X")[0]) - in_h, in_w = infer_shape(input)[2:] + input_x = g.get_node(op.input("X")[0]) + in_h, in_w = infer_shape(input_x)[2:] op_map = { "avg": "avg_pool2d", @@ -586,16 +638,16 @@ def convert_pool2d(g, op, block): if len(paddings) == 4: paddings = [paddings[0], paddings[2], paddings[1], paddings[3]] else: - msg = 'Value {} in attribute "padding" of operator Pool2d is not ' "valid." + msg = 'Value {} in attribute "padding" of operator Pool2d is not "valid."' raise tvm.error.OpAttributeInvalid(msg.format(padding_algorithm)) - x = g.get_node(op.input("X")[0]) if not adaptive: out = getattr(_op.nn, op_map[pooling_type])( - x, pool_size=ksize, strides=strides, padding=paddings, ceil_mode=ceil_mode + input_x, pool_size=ksize, strides=strides, padding=paddings, ceil_mode=ceil_mode ) else: - out = getattr(_op.nn, "adaptive_" + op_map[pooling_type])(x, output_size=ksize) + out = getattr(_op.nn, "adaptive_" + + op_map[pooling_type])(input_x, output_size=ksize) g.add_node(op.output("Out")[0], out) @@ -724,13 +776,23 @@ def convert_unsqueeze(g, op, block): g.add_node(op.output("Out")[0], x) +def convert_sigmoid(g, op, block): + """Operator converter for sigmoid.""" + + x = g.get_node(op.input("X")[0]) + out = _op.sigmoid(x) + g.add_node(op.output("Out")[0], out) + + _convert_map = { + "sigmoid": convert_sigmoid, "arg_max": convert_arg_max, "assign": convert_assign, "batch_norm": convert_batch_norm, "cast": convert_cast, "concat": convert_concat, "conv2d": convert_conv2d, + "conv2d_transpose": convert_conv2d_transpose, "cumsum": convert_cumsum, "depthwise_conv2d": convert_conv2d, "dropout": convert_dropout, @@ -764,7 +826,7 @@ def convert_unsqueeze(g, op, block): } -class GraphProto(object): +class GraphProto: """A helper class for handling relay functions from PaddlePaddle model.""" def __init__(self): @@ -773,13 +835,19 @@ def __init__(self): self.shape_dict = None def get_node(self, name): + """get node from graph""" + assert name in self.nodes return self.nodes[name] def add_node(self, name, node): + """add a node to graph""" + self.nodes[name] = fold_constant(node) def get_params(self, name=None): + """get params from graph""" + if name is None: return self.params assert name in self.params @@ -809,17 +877,18 @@ def check_input_shape(self, op, block): ipt_shape = block.var(ipt_name).shape for i in ipt_shape: if i < 0: - warning_msg = "Input {}(shape={}) has unkown dimension shapes. Specifying static values may improve performance".format( + warning_msg = "Input {}(shape={}) has unkown dimension shapes. \ + Specifying static values may improve performance".format( ipt_name, ipt_shape ) - warings.warn(warning_msg) + warnings.warn(warning_msg) def check_unsupported_ops(self, program): """Check whether all the operators are supported.""" unsupported_ops = set() for block in program.blocks: - for i, op in enumerate(block.ops): + for op in block.ops: if op.type == "fetch": continue if op.type not in _convert_map: @@ -836,7 +905,7 @@ def ops_to_relay(self, program, input_specs=None): for input_spec in input_specs: convert_feed(self, input_spec, None) for block in program.blocks: - for i, op in enumerate(block.ops): + for op in block.ops: if op.type == "fetch": continue convert_func = _convert_map[op.type] @@ -856,7 +925,7 @@ def from_program(self, program, shape_dict, scope): output_names = list() for block in program.blocks: - for i, op in enumerate(block.ops): + for op in block.ops: if op.type == "fetch": output_names.append(op.input("X")[0]) @@ -910,5 +979,6 @@ def from_paddle(program_or_layer, shape_dict=None, scope=None): # model is loaded by `paddle.static.load_inference_model` mod, params = g.from_program(program_or_layer, shape_dict, scope) else: - raise Exception("Only PaddlePaddle's Program and TranslatedLayer are supported.") + raise Exception( + "Only PaddlePaddle's Program and TranslatedLayer are supported.") return mod, params diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index db07e07f9d83..af925bd81ceb 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -320,6 +320,50 @@ def forward(self, inputs): verify_model(Conv2D2(), input_data=conv2d_input_data) +@tvm.testing.uses_gpu +def test_forward_conv_transpose(): + # Note we do not test with groups > 1 because that is not supported + # in tvm for conv transpose operations + + class Conv2DTranspose1(nn.Layer): + def __init__(self): + super(Conv2DTranspose1, self).__init__() + self.conv_transpose = nn.Conv2DTranspose(3, 5, 3) + + @paddle.jit.to_static + def forward(self, inputs): + return self.conv_transpose(inputs) + + class Conv2DTranspose2(nn.Layer): + def __init__(self): + super(Conv2DTranspose2, self).__init__() + self.conv_transpose = nn.Conv2DTranspose( + 3, 5, 3, stride=2, output_padding=1, bias_attr=True + ) + + @paddle.jit.to_static + def forward(self, inputs): + return self.conv_transpose(inputs) + + class Conv2DTranspose3(nn.Layer): + def __init__(self): + super(Conv2DTranspose3, self).__init__() + self.conv_transpose = nn.Conv2DTranspose( + 3, 5, 3, stride=3, output_padding=2, bias_attr=True + ) + + @paddle.jit.to_static + def forward(self, inputs): + return self.conv_transpose(inputs) + + # Conv 2D Transpose Tests + conv2d_transpose_input_shape = [1, 3, 128, 256] + conv2d_transpose_input_data = paddle.rand(conv2d_transpose_input_shape, dtype="float32") + verify_model(Conv2DTranspose1(), input_data=conv2d_transpose_input_data) + verify_model(Conv2DTranspose2(), input_data=conv2d_transpose_input_data) + verify_model(Conv2DTranspose3(), input_data=conv2d_transpose_input_data) + + @tvm.testing.uses_gpu def test_forward_dropout(): @paddle.jit.to_static @@ -633,29 +677,42 @@ def tanh(inputs): verify_model(tanh, input_data=input_data) +@tvm.testing.uses_gpu +def test_forward_sigmoid(): + @paddle.jit.to_static + def sigmoid(inputs): + return nn.functional.sigmoid(inputs) + + input_shape = [10, 10] + input_data = paddle.rand(input_shape, dtype="float32") + verify_model(sigmoid, input_data=input_data) + + if __name__ == "__main__": - test_forward_add_subtract() - test_forward_argmax() - test_forward_assign() - test_forward_batch_norm() - test_forward_cast() - test_forward_concat_unsqueeze() - test_forward_cumsum() - test_forward_conv() - test_forward_dropout() - test_forward_shape_full() - test_forward_ones_like() - test_forward_gelu() - test_forward_hard_sigmoid() - test_forward_hard_swish() - test_forward_layer_norm() - test_forward_leaky_relu() - test_forward_look_up() - test_forward_multiply() - test_forward_matmul() - test_forward_pool2d() - test_forward_relu() - test_forward_reshape() - test_forward_scale() - test_forward_slice() - test_forward_tanh() + # test_forward_add_subtract() + # test_forward_argmax() + # test_forward_assign() + # test_forward_batch_norm() + # test_forward_cast() + # test_forward_concat_unsqueeze() + # test_forward_cumsum() + # test_forward_conv() + # test_forward_dropout() + # test_forward_shape_full() + # test_forward_ones_like() + # test_forward_gelu() + # test_forward_hard_sigmoid() + # test_forward_hard_swish() + # test_forward_layer_norm() + # test_forward_leaky_relu() + # test_forward_look_up() + # test_forward_multiply() + # test_forward_matmul() + # test_forward_pool2d() + # test_forward_relu() + # test_forward_reshape() + # test_forward_scale() + # test_forward_slice() + # test_forward_tanh() + test_forward_conv_transpose() + test_forward_sigmoid() From e116cd5aefc67de31aa826f8f656c9f9e3bdb638 Mon Sep 17 00:00:00 2001 From: wjj19950828 Date: Fri, 20 Aug 2021 17:58:00 +0800 Subject: [PATCH 033/127] fixed bug --- .../frontend/paddlepaddle/test_forward.py | 50 +++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index af925bd81ceb..38609cc7a609 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -689,30 +689,30 @@ def sigmoid(inputs): if __name__ == "__main__": - # test_forward_add_subtract() - # test_forward_argmax() - # test_forward_assign() - # test_forward_batch_norm() - # test_forward_cast() - # test_forward_concat_unsqueeze() - # test_forward_cumsum() - # test_forward_conv() - # test_forward_dropout() - # test_forward_shape_full() - # test_forward_ones_like() - # test_forward_gelu() - # test_forward_hard_sigmoid() - # test_forward_hard_swish() - # test_forward_layer_norm() - # test_forward_leaky_relu() - # test_forward_look_up() - # test_forward_multiply() - # test_forward_matmul() - # test_forward_pool2d() - # test_forward_relu() - # test_forward_reshape() - # test_forward_scale() - # test_forward_slice() - # test_forward_tanh() + test_forward_add_subtract() + test_forward_argmax() + test_forward_assign() + test_forward_batch_norm() + test_forward_cast() + test_forward_concat_unsqueeze() + test_forward_cumsum() + test_forward_conv() + test_forward_dropout() + test_forward_shape_full() + test_forward_ones_like() + test_forward_gelu() + test_forward_hard_sigmoid() + test_forward_hard_swish() + test_forward_layer_norm() + test_forward_leaky_relu() + test_forward_look_up() + test_forward_multiply() + test_forward_matmul() + test_forward_pool2d() + test_forward_relu() + test_forward_reshape() + test_forward_scale() + test_forward_slice() + test_forward_tanh() test_forward_conv_transpose() test_forward_sigmoid() From dd8d08c45c33e458bb40be1165126bd1816f6ed6 Mon Sep 17 00:00:00 2001 From: wjj19950828 Date: Sun, 22 Aug 2021 15:30:04 +0800 Subject: [PATCH 034/127] fixed conflicts --- python/tvm/relay/frontend/paddlepaddle.py | 186 +++++++++++++++++++--- 1 file changed, 161 insertions(+), 25 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 7116bc2ad13e..68b09bba5447 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -107,6 +107,104 @@ def convert_batch_norm(g, op, block): g.add_node(op.output("Y")[0], out[0]) +def get_interpolate_mode(op): + """conver 'interp_method' attr of paddle to tvm""" + + interp_method = op.attr("interp_method") + align_corners = op.attr("align_corners") + align_mode = op.attr("align_mode") + + rounding_method = "" + if interp_method == "nearest": + interp_method = "nearest_neighbor" + coordinate_transformation_mode = "asymmetric" + rounding_method = "floor" + elif interp_method == "bilinear": + interp_method = "linear" + if not align_corners and align_mode == 0: + coordinate_transformation_mode = "half_pixel" + else: + if align_corners: + coordinate_transformation_mode = "align_corners" + else: + coordinate_transformation_mode = "asymmetric" + elif interp_method == "bicubic": + interp_method = "cubic" + if align_corners: + coordinate_transformation_mode = "align_corners" + else: + coordinate_transformation_mode = "half_pixel" + else: + msg = "interp_method {} is not supported for PaddlePaddle's interpolate" + raise tvm.error.OpAttributeInvalid(msg.format(interp_method)) + return rounding_method, interp_method, coordinate_transformation_mode + + +def convert_interpolate2d(g, op, x, input_shape): + """Operator converter for interpolate 2D(dims == 4).""" + + layout = op.attr("data_layout") + if layout == "NCHW": + in_h, in_w = input_shape[2], input_shape[3] + else: + in_h, in_w = input_shape[1], input_shape[2] + + out_h = op.attr("out_h") + out_w = op.attr("out_w") + + input_out_size = op.input("OutSize") + input_size_tensor = op.input("SizeTensor") + input_scale = op.input("Scale") + if input_size_tensor: + out_size = g.get_node(input_size_tensor[0]) + out_size = infer_value(out_size, g.get_params()).numpy().tolist() + out_h, out_w = out_size + elif input_out_size: + out_size = g.get_node(input_out_size[0]) + out_size = infer_value(out_size, g.get_params()).numpy().tolist() + out_h, out_w = out_size + elif input_scale: + scale_data = g.get_node(input_scale[0]) + scale_data = infer_value(scale_data, g.get_params()).numpy().tolist() + if len(scale_data) > 1: + out_h = int(scale_data[0] * in_h) + out_w = int(scale_data[1] * in_w) + else: + out_h = int(scale_data[0] * in_h) + out_w = int(scale_data[0] * in_w) + else: + scale = op.attr("scale") + scale = [float(i) for i in scale] + if len(scale) > 1: + out_h = int(scale[0] * in_h) + out_w = int(scale[1] * in_w) + + rounding_method, interp_method, coordinate_transformation_mode = get_interpolate_mode(op) + out = _op.image.resize2d( + x, + [out_h, out_w], + layout=layout, + method=interp_method, + coordinate_transformation_mode=coordinate_transformation_mode, + rounding_method=rounding_method, + cubic_alpha=-0.75, + ) + g.add_node(op.output("Out")[0], out) + + +def convert_interpolate(g, op, block): + """Operator converter for interpolate.""" + + x = g.get_node(op.input("X")[0]) + input_shape = infer_shape(x) + dims = len(input_shape) + if dims == 4: + convert_interpolate2d(g, op, x, input_shape) + else: + msg = "input_shape {} is not supported for PaddlePaddle's interpolate" + raise tvm.error.OpAttributeInvalid(msg.format(dims)) + + def convert_cast(g, op, block): """Operator converter for cast.""" @@ -259,8 +357,7 @@ def convert_elementwise_op(g, op, block): if axis < 0: axis = axis + len(ipt0_shape) if axis != len(ipt0_shape) - 1: - ipt1 = _op.expand_dims( - ipt1, axis=axis, num_newaxis=(len(ipt0_shape) - axis - 1)) + ipt1 = _op.expand_dims(ipt1, axis=axis, num_newaxis=(len(ipt0_shape) - axis - 1)) out = op_func(ipt0, ipt1) g.add_node(op.output("Out")[0], out) @@ -350,8 +447,7 @@ def convert_gelu(g, op, block): x = g.get_node(op.input("X")[0]) out = x * ( _expr.const(0.5, dtype="float32") - + _op.erf(x * _expr.const(0.5 ** 0.5, dtype="float32")) * - _expr.const(0.5, dtype="float32") + + _op.erf(x * _expr.const(0.5 ** 0.5, dtype="float32")) * _expr.const(0.5, dtype="float32") ) g.add_node(op.output("Out")[0], out) @@ -372,12 +468,9 @@ def convert_hard_swish(g, op, block): offset = op.attr("offset") scale = op.attr("scale") threshold = op.attr("threshold") - assert np.isclose( - offset, 3.0), "Only support offset==3.0 for PaddlePaddle's hard_swish" - assert np.isclose( - scale, 6.0), "Only support scale==6.0 for PaddlePaddle's hard_swish" - assert np.isclose( - threshold, 6.0), "Only support threshold==6.0 for PaddlePaddle's hard_swish" + assert np.isclose(offset, 3.0), "Only support offset==3.0 for PaddlePaddle's hard_swish" + assert np.isclose(scale, 6.0), "Only support scale==6.0 for PaddlePaddle's hard_swish" + assert np.isclose(threshold, 6.0), "Only support threshold==6.0 for PaddlePaddle's hard_swish" x = g.get_node(op.input("X")[0]) out = _op.clip(x, -1 * offset, offset) out = out / _expr.const(threshold) + _expr.const(0.5) @@ -478,8 +571,7 @@ def flatten_to_nd(x, x_shape, nd=3): return x newshape = _op.concatenate( [ - _expr.const( - [-1], dtype=infer_type(x_shape).checked_type.dtype), + _expr.const([-1], dtype=infer_type(x_shape).checked_type.dtype), _op.strided_slice(x_shape, [ndims - nd + 1], [ndims]), ], 0, @@ -524,12 +616,10 @@ def flatten_to_nd(x, x_shape, nd=3): [ out_batch, _op.strided_slice( - a_shape, [infer_shape(a_shape)[0] - - 2], [infer_shape(a_shape)[0] - 1] + a_shape, [infer_shape(a_shape)[0] - 2], [infer_shape(a_shape)[0] - 1] ), _op.strided_slice( - b_shape, [infer_shape(b_shape)[0] - - 1], [infer_shape(b_shape)[0]] + b_shape, [infer_shape(b_shape)[0] - 1], [infer_shape(b_shape)[0]] ), ], 0, @@ -568,8 +658,7 @@ def convert_mul(g, op, block): if x_num_col_dims == 1: x = _op.nn.batch_flatten(x) else: - pre_shape = _op.prod(_op.strided_slice( - x_shape, [0], [x_num_col_dims], [1]), keepdims=True) + pre_shape = _op.prod(_op.strided_slice(x_shape, [0], [x_num_col_dims], [1]), keepdims=True) post_shape = _op.prod( _op.strided_slice(x_shape, [x_num_col_dims], [x_dim], [1]), keepdims=True ) @@ -579,8 +668,7 @@ def convert_mul(g, op, block): if y_num_col_dims == 1: y = _op.nn.batch_flatten(y) else: - pre_shape = _op.prod(_op.strided_slice( - y_shape, [0], [y_num_col_dims], [1]), keepdims=True) + pre_shape = _op.prod(_op.strided_slice(y_shape, [0], [y_num_col_dims], [1]), keepdims=True) post_shape = _op.prod( _op.strided_slice(y_shape, [y_num_col_dims], [y_dim], [1]), keepdims=True ) @@ -646,8 +734,40 @@ def convert_pool2d(g, op, block): input_x, pool_size=ksize, strides=strides, padding=paddings, ceil_mode=ceil_mode ) else: - out = getattr(_op.nn, "adaptive_" + - op_map[pooling_type])(input_x, output_size=ksize) + out = getattr(_op.nn, "adaptive_" + op_map[pooling_type])(input_x, output_size=ksize) + g.add_node(op.output("Out")[0], out) + + +def convert_padding(g, op, block): + """Operator converter for padding.""" + + input_x = g.get_node(op.input("X")[0]) + input_padding = op.input("Paddings") + if input_padding: + padding = g.get_node(input_padding[0]) + padding = infer_value(padding, g.get_params()).numpy().tolist() + else: + padding = op.attr("paddings") + padding = op.attr("paddings") + value = op.attr("value") + data_format = op.attr("data_format") + mode = op.attr("mode") + assert mode != "circular", "Don't support mod='circular' for PaddlePaddle's padding" + if mode == "replicate": + mode = "edge" + + new_pad_len = len(infer_shape(input_x)) * 2 + new_paddings = [0] * new_pad_len + for i in range(0, len(padding), 2): + index = -1 - i + if data_format[:2] != "NC": + index = -3 - i + new_paddings[index] = padding[i + 1] + new_paddings[index - 1] = padding[i] + + new_paddings = [new_paddings[i : i + 2] for i in range(0, len(new_paddings), 2)] + + out = _op.nn.pad(input_x, new_paddings, pad_value=value, pad_mode=mode) g.add_node(op.output("Out")[0], out) @@ -766,6 +886,17 @@ def convert_softmax(g, op, block): g.add_node(op.output("Out")[0], out) +def convert_squeeze(g, op, block): + """Operator converter for squeeze2.""" + + x = g.get_node(op.input("X")[0]) + axes = op.attr("axes") + if not axes: + axes = None + x = _op.squeeze(x, axis=axes) + g.add_node(op.output("Out")[0], x) + + def convert_unsqueeze(g, op, block): """Operator converter for unsqueeze.""" @@ -789,6 +920,8 @@ def convert_sigmoid(g, op, block): "arg_max": convert_arg_max, "assign": convert_assign, "batch_norm": convert_batch_norm, + "bicubic_interp_v2": convert_interpolate, + "bilinear_interp_v2": convert_interpolate, "cast": convert_cast, "concat": convert_concat, "conv2d": convert_conv2d, @@ -814,13 +947,18 @@ def convert_sigmoid(g, op, block): "matmul": convert_matmul, "matmul_v2": convert_matmul, "mul": convert_mul, + "nearest_interp_v2": convert_interpolate, "pool2d": convert_pool2d, + "pad1d": convert_padding, + "pad2d": convert_padding, + "pad3d": convert_padding, "relu": convert_activation, "reshape2": convert_reshape, "scale": convert_scale, "shape": convert_shape, "slice": convert_slice, "softmax": convert_softmax, + "squeeze2": convert_squeeze, "tanh": convert_activation, "unsqueeze2": convert_unsqueeze, } @@ -964,7 +1102,6 @@ def from_translated_layer(self, layer, shape_dict): def from_paddle(program_or_layer, shape_dict=None, scope=None): """Convert a PaddlePaddle model into an equivalent Relay Function. - PaddlePaddle Program/TranslatedLayer represent the computation graph of PaddlePaddle model, and PaddlePaddle scope stores all the weights of PaddlePaddle model. """ @@ -979,6 +1116,5 @@ def from_paddle(program_or_layer, shape_dict=None, scope=None): # model is loaded by `paddle.static.load_inference_model` mod, params = g.from_program(program_or_layer, shape_dict, scope) else: - raise Exception( - "Only PaddlePaddle's Program and TranslatedLayer are supported.") + raise Exception("Only PaddlePaddle's Program and TranslatedLayer are supported.") return mod, params From 094e8ccd401e527d136fabede06d6da56984bf54 Mon Sep 17 00:00:00 2001 From: wjj19950828 Date: Sun, 22 Aug 2021 15:44:19 +0800 Subject: [PATCH 035/127] fixed bugs --- python/tvm/relay/frontend/paddlepaddle.py | 149 ---------------------- 1 file changed, 149 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 68b09bba5447..2e7d62e5b448 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -107,104 +107,6 @@ def convert_batch_norm(g, op, block): g.add_node(op.output("Y")[0], out[0]) -def get_interpolate_mode(op): - """conver 'interp_method' attr of paddle to tvm""" - - interp_method = op.attr("interp_method") - align_corners = op.attr("align_corners") - align_mode = op.attr("align_mode") - - rounding_method = "" - if interp_method == "nearest": - interp_method = "nearest_neighbor" - coordinate_transformation_mode = "asymmetric" - rounding_method = "floor" - elif interp_method == "bilinear": - interp_method = "linear" - if not align_corners and align_mode == 0: - coordinate_transformation_mode = "half_pixel" - else: - if align_corners: - coordinate_transformation_mode = "align_corners" - else: - coordinate_transformation_mode = "asymmetric" - elif interp_method == "bicubic": - interp_method = "cubic" - if align_corners: - coordinate_transformation_mode = "align_corners" - else: - coordinate_transformation_mode = "half_pixel" - else: - msg = "interp_method {} is not supported for PaddlePaddle's interpolate" - raise tvm.error.OpAttributeInvalid(msg.format(interp_method)) - return rounding_method, interp_method, coordinate_transformation_mode - - -def convert_interpolate2d(g, op, x, input_shape): - """Operator converter for interpolate 2D(dims == 4).""" - - layout = op.attr("data_layout") - if layout == "NCHW": - in_h, in_w = input_shape[2], input_shape[3] - else: - in_h, in_w = input_shape[1], input_shape[2] - - out_h = op.attr("out_h") - out_w = op.attr("out_w") - - input_out_size = op.input("OutSize") - input_size_tensor = op.input("SizeTensor") - input_scale = op.input("Scale") - if input_size_tensor: - out_size = g.get_node(input_size_tensor[0]) - out_size = infer_value(out_size, g.get_params()).numpy().tolist() - out_h, out_w = out_size - elif input_out_size: - out_size = g.get_node(input_out_size[0]) - out_size = infer_value(out_size, g.get_params()).numpy().tolist() - out_h, out_w = out_size - elif input_scale: - scale_data = g.get_node(input_scale[0]) - scale_data = infer_value(scale_data, g.get_params()).numpy().tolist() - if len(scale_data) > 1: - out_h = int(scale_data[0] * in_h) - out_w = int(scale_data[1] * in_w) - else: - out_h = int(scale_data[0] * in_h) - out_w = int(scale_data[0] * in_w) - else: - scale = op.attr("scale") - scale = [float(i) for i in scale] - if len(scale) > 1: - out_h = int(scale[0] * in_h) - out_w = int(scale[1] * in_w) - - rounding_method, interp_method, coordinate_transformation_mode = get_interpolate_mode(op) - out = _op.image.resize2d( - x, - [out_h, out_w], - layout=layout, - method=interp_method, - coordinate_transformation_mode=coordinate_transformation_mode, - rounding_method=rounding_method, - cubic_alpha=-0.75, - ) - g.add_node(op.output("Out")[0], out) - - -def convert_interpolate(g, op, block): - """Operator converter for interpolate.""" - - x = g.get_node(op.input("X")[0]) - input_shape = infer_shape(x) - dims = len(input_shape) - if dims == 4: - convert_interpolate2d(g, op, x, input_shape) - else: - msg = "input_shape {} is not supported for PaddlePaddle's interpolate" - raise tvm.error.OpAttributeInvalid(msg.format(dims)) - - def convert_cast(g, op, block): """Operator converter for cast.""" @@ -738,39 +640,6 @@ def convert_pool2d(g, op, block): g.add_node(op.output("Out")[0], out) -def convert_padding(g, op, block): - """Operator converter for padding.""" - - input_x = g.get_node(op.input("X")[0]) - input_padding = op.input("Paddings") - if input_padding: - padding = g.get_node(input_padding[0]) - padding = infer_value(padding, g.get_params()).numpy().tolist() - else: - padding = op.attr("paddings") - padding = op.attr("paddings") - value = op.attr("value") - data_format = op.attr("data_format") - mode = op.attr("mode") - assert mode != "circular", "Don't support mod='circular' for PaddlePaddle's padding" - if mode == "replicate": - mode = "edge" - - new_pad_len = len(infer_shape(input_x)) * 2 - new_paddings = [0] * new_pad_len - for i in range(0, len(padding), 2): - index = -1 - i - if data_format[:2] != "NC": - index = -3 - i - new_paddings[index] = padding[i + 1] - new_paddings[index - 1] = padding[i] - - new_paddings = [new_paddings[i : i + 2] for i in range(0, len(new_paddings), 2)] - - out = _op.nn.pad(input_x, new_paddings, pad_value=value, pad_mode=mode) - g.add_node(op.output("Out")[0], out) - - def convert_reshape(g, op, block): """Operator converter for reshape.""" @@ -886,17 +755,6 @@ def convert_softmax(g, op, block): g.add_node(op.output("Out")[0], out) -def convert_squeeze(g, op, block): - """Operator converter for squeeze2.""" - - x = g.get_node(op.input("X")[0]) - axes = op.attr("axes") - if not axes: - axes = None - x = _op.squeeze(x, axis=axes) - g.add_node(op.output("Out")[0], x) - - def convert_unsqueeze(g, op, block): """Operator converter for unsqueeze.""" @@ -920,8 +778,6 @@ def convert_sigmoid(g, op, block): "arg_max": convert_arg_max, "assign": convert_assign, "batch_norm": convert_batch_norm, - "bicubic_interp_v2": convert_interpolate, - "bilinear_interp_v2": convert_interpolate, "cast": convert_cast, "concat": convert_concat, "conv2d": convert_conv2d, @@ -947,18 +803,13 @@ def convert_sigmoid(g, op, block): "matmul": convert_matmul, "matmul_v2": convert_matmul, "mul": convert_mul, - "nearest_interp_v2": convert_interpolate, "pool2d": convert_pool2d, - "pad1d": convert_padding, - "pad2d": convert_padding, - "pad3d": convert_padding, "relu": convert_activation, "reshape2": convert_reshape, "scale": convert_scale, "shape": convert_shape, "slice": convert_slice, "softmax": convert_softmax, - "squeeze2": convert_squeeze, "tanh": convert_activation, "unsqueeze2": convert_unsqueeze, } From 26858fd742345c59e43579393b458b36317e88b3 Mon Sep 17 00:00:00 2001 From: wjj19950828 Date: Tue, 24 Aug 2021 20:10:52 +0800 Subject: [PATCH 036/127] fixed comments --- .../frontend/paddlepaddle/test_forward.py | 54 +++++++++---------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index 38609cc7a609..0a98e1b82644 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -338,7 +338,7 @@ class Conv2DTranspose2(nn.Layer): def __init__(self): super(Conv2DTranspose2, self).__init__() self.conv_transpose = nn.Conv2DTranspose( - 3, 5, 3, stride=2, output_padding=1, bias_attr=True + 3, 5, 3, stride=2, padding=[[0,0],[0,0],[1,2],[3,4]], output_padding=1, bias_attr=True ) @paddle.jit.to_static @@ -349,7 +349,7 @@ class Conv2DTranspose3(nn.Layer): def __init__(self): super(Conv2DTranspose3, self).__init__() self.conv_transpose = nn.Conv2DTranspose( - 3, 5, 3, stride=3, output_padding=2, bias_attr=True + 3, 5, 3, stride=3, padding='VALID', output_padding=2, bias_attr=True ) @paddle.jit.to_static @@ -689,30 +689,30 @@ def sigmoid(inputs): if __name__ == "__main__": - test_forward_add_subtract() - test_forward_argmax() - test_forward_assign() - test_forward_batch_norm() - test_forward_cast() - test_forward_concat_unsqueeze() - test_forward_cumsum() - test_forward_conv() - test_forward_dropout() - test_forward_shape_full() - test_forward_ones_like() - test_forward_gelu() - test_forward_hard_sigmoid() - test_forward_hard_swish() - test_forward_layer_norm() - test_forward_leaky_relu() - test_forward_look_up() - test_forward_multiply() - test_forward_matmul() - test_forward_pool2d() - test_forward_relu() - test_forward_reshape() - test_forward_scale() - test_forward_slice() - test_forward_tanh() + # test_forward_add_subtract() + # test_forward_argmax() + # test_forward_assign() + # test_forward_batch_norm() + # test_forward_cast() + # test_forward_concat_unsqueeze() + # test_forward_cumsum() + # test_forward_conv() + # test_forward_dropout() + # test_forward_shape_full() + # test_forward_ones_like() + # test_forward_gelu() + # test_forward_hard_sigmoid() + # test_forward_hard_swish() + # test_forward_layer_norm() + # test_forward_leaky_relu() + # test_forward_look_up() + # test_forward_multiply() + # test_forward_matmul() + # test_forward_pool2d() + # test_forward_relu() + # test_forward_reshape() + # test_forward_scale() + # test_forward_slice() + # test_forward_tanh() test_forward_conv_transpose() test_forward_sigmoid() From 428edac56047df13a3502df3742eb6beaab39d3e Mon Sep 17 00:00:00 2001 From: root Date: Mon, 30 Aug 2021 11:15:38 +0000 Subject: [PATCH 037/127] fix fill_constant --- python/tvm/relay/frontend/paddlepaddle.py | 56 ++++++++++------------- 1 file changed, 25 insertions(+), 31 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index f0686408047e..cdf3d9cc188c 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -64,6 +64,23 @@ def _get_pad_size(in_size, dilated_kernel_size, stride_size): return [pad_before, pad_after] +def convert_activation(g, op, block): + """Operator converter for all the activation.""" + + op_map = { + "exp": _op.exp, + "relu": _op.nn.relu, + "tanh": _op.tanh, + "sqrt": _op.sqrt, + "erf": _op.erf, + "abs": _op.abs, + "sigmoid": _op.sigmoid, + } + act_func = op_map[op.type] + out = act_func(g.get_node(op.input("X")[0])) + g.add_node(op.output("Out")[0], out) + + def convert_arg_max(g, op, block): """Operator converter for arg_max.""" @@ -371,22 +388,6 @@ def convert_equal(g, op, block): g.add_node(op.output("Out")[0], out) -def convert_activation(g, op, block): - """Operator converter for all the activation.""" - - op_map = { - "exp": _op.exp, - "relu": _op.nn.relu, - "tanh": _op.tanh, - "sqrt": _op.sqrt, - "erf": _op.erf, - "abs": _op.abs, - } - act_func = op_map[op.type] - out = act_func(g.get_node(op.input("X")[0])) - g.add_node(op.output("Out")[0], out) - - def convert_feed(g, op, block): """Converter for model input node.""" @@ -430,12 +431,13 @@ def convert_fill_constant(g, op, block): shape = block.var(op.output("Out")[0]).shape dtype = block.var(op.output("Out")[0]).dtype dtype = str(dtype).strip().split(".")[1] - if op.input("ValueTensor"): - shape = g.get_node(op.input("ValueTensor")[0]) - shape = infer_value(shape, g.get_params()).numpy() - if op.input("ShapeTensor"): - shape = g.get_node(op.input("ShapeTensor")[0]) - shape = infer_value(shape, g.get_params()).numpy() + if len(op.input_names) > 0: + if op.input("ValueTensor"): + shape = g.get_node(op.input("ValueTensor")[0]) + shape = infer_value(shape, g.get_params()).numpy() + if op.input("ShapeTensor"): + shape = g.get_node(op.input("ShapeTensor")[0]) + shape = infer_value(shape, g.get_params()).numpy() value = np.full(shape, value, dtype) out = _expr.const(value.astype(dtype)).astype(dtype) g.add_node(op.output("Out")[0], out) @@ -907,16 +909,7 @@ def convert_unsqueeze(g, op, block): g.add_node(op.output("Out")[0], x) -def convert_sigmoid(g, op, block): - """Operator converter for sigmoid.""" - - x = g.get_node(op.input("X")[0]) - out = _op.sigmoid(x) - g.add_node(op.output("Out")[0], out) - - _convert_map = { - "sigmoid": convert_sigmoid, "arg_max": convert_arg_max, "assign": convert_assign, "batch_norm": convert_batch_norm, @@ -956,6 +949,7 @@ def convert_sigmoid(g, op, block): "reshape2": convert_reshape, "scale": convert_scale, "shape": convert_shape, + "sigmoid": convert_activation, "slice": convert_slice, "softmax": convert_softmax, "squeeze2": convert_squeeze, From 4c83872561456c2fa9218198c8ed5ebc0394e2dd Mon Sep 17 00:00:00 2001 From: jiangjiajun Date: Mon, 30 Aug 2021 11:28:01 +0000 Subject: [PATCH 038/127] update paddlepaddle frontend --- python/tvm/relay/frontend/paddlepaddle.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index cdf3d9cc188c..a01c2158bd31 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -1096,8 +1096,9 @@ def from_translated_layer(self, layer, shape_dict): def from_paddle(program_or_layer, shape_dict=None, scope=None): """Convert a PaddlePaddle model into an equivalent Relay Function. - PaddlePaddle Program/TranslatedLayer represent the computation graph of PaddlePaddle model, - and PaddlePaddle scope stores all the weights of PaddlePaddle model. + PaddlePaddle Program/TranslatedLayer represent the computation + graph of PaddlePaddle model, and PaddlePaddle scope stores all the + weights of PaddlePaddle model. """ import paddle From 07ae88877a0026b3b523a87b44d26070a88e0021 Mon Sep 17 00:00:00 2001 From: jiangjiajun Date: Mon, 30 Aug 2021 13:11:55 +0000 Subject: [PATCH 039/127] add bmm and transpose --- python/tvm/relay/frontend/paddlepaddle.py | 89 +++++++++++++++-------- 1 file changed, 59 insertions(+), 30 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index a01c2158bd31..f8173c1e784f 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -124,42 +124,61 @@ def convert_batch_norm(g, op, block): g.add_node(op.output("Y")[0], out[0]) -def get_interpolate_mode(op): - """conver 'interp_method' attr of paddle to tvm""" - - interp_method = op.attr("interp_method") - align_corners = op.attr("align_corners") - align_mode = op.attr("align_mode") - - rounding_method = "" - if interp_method == "nearest": - interp_method = "nearest_neighbor" - coordinate_transformation_mode = "asymmetric" - rounding_method = "floor" - elif interp_method == "bilinear": - interp_method = "linear" - if not align_corners and align_mode == 0: - coordinate_transformation_mode = "half_pixel" - else: - if align_corners: - coordinate_transformation_mode = "align_corners" - else: - coordinate_transformation_mode = "asymmetric" - elif interp_method == "bicubic": - interp_method = "cubic" - if align_corners: - coordinate_transformation_mode = "align_corners" - else: - coordinate_transformation_mode = "half_pixel" +def convert_bmm(g, op, block): + """Operator converter for bmm.""" + + x = g.get_node(op.input('X')[0]) + y = g.get_node(op.input('Y')[0]) + x_shape = infer_shape(x) + y_shape = infer_shape(y) + if x_shape[0] == 1 and y_shape == 1: + x = _op.reshape(x, x_shape[1:]) + y = _op.reshape(y, y_shape[1:]) + y = _op.transpose(y, [1, 0]) + out = _op.nn.dense(x, y) + out = _op.expand_dims(out, axis=0) + g.add_node(op.output('Out')[0], out) else: - msg = "interp_method {} is not supported for PaddlePaddle's interpolate" - raise tvm.error.OpAttributeInvalid(msg.format(interp_method)) - return rounding_method, interp_method, coordinate_transformation_mode + y = _op.transpose(y, [0, 2, 1]) + out = _op.nn.batch_matmul(x, y) + g.add_node(op.output('Out')[0], out) def convert_interpolate2d(g, op, x, input_shape): """Operator converter for interpolate 2D(dims == 4).""" + def get_interpolate_mode(op): + """conver 'interp_method' attr of paddle to tvm""" + + interp_method = op.attr("interp_method") + align_corners = op.attr("align_corners") + align_mode = op.attr("align_mode") + + rounding_method = "" + if interp_method == "nearest": + interp_method = "nearest_neighbor" + coordinate_transformation_mode = "asymmetric" + rounding_method = "floor" + elif interp_method == "bilinear": + interp_method = "linear" + if not align_corners and align_mode == 0: + coordinate_transformation_mode = "half_pixel" + else: + if align_corners: + coordinate_transformation_mode = "align_corners" + else: + coordinate_transformation_mode = "asymmetric" + elif interp_method == "bicubic": + interp_method = "cubic" + if align_corners: + coordinate_transformation_mode = "align_corners" + else: + coordinate_transformation_mode = "half_pixel" + else: + msg = "interp_method {} is not supported for PaddlePaddle's interpolate" + raise tvm.error.OpAttributeInvalid(msg.format(interp_method)) + return rounding_method, interp_method, coordinate_transformation_mode + layout = op.attr("data_layout") if layout == "NCHW": in_h, in_w = input_shape[2], input_shape[3] @@ -899,6 +918,14 @@ def convert_squeeze(g, op, block): g.add_node(op.output("Out")[0], x) +def convert_transpose(g, op, block): + """Operator converter for transpose.""" + + perm = op.attr('axis') + out = _op.transpose(g.get_node(op.input('X')[0]), axes=perm) + g.add_node(op.output('Out')[0], out) + + def convert_unsqueeze(g, op, block): """Operator converter for unsqueeze.""" @@ -915,6 +942,7 @@ def convert_unsqueeze(g, op, block): "batch_norm": convert_batch_norm, "bicubic_interp_v2": convert_interpolate, "bilinear_interp_v2": convert_interpolate, + "bmm": convert_bmm, "cast": convert_cast, "concat": convert_concat, "conv2d": convert_conv2d, @@ -954,6 +982,7 @@ def convert_unsqueeze(g, op, block): "softmax": convert_softmax, "squeeze2": convert_squeeze, "tanh": convert_activation, + "transpose2": convert_transpose, "unsqueeze2": convert_unsqueeze, } From 38417d9d09f5003420e60dba2435824929b3bc13 Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Tue, 31 Aug 2021 16:49:21 +0800 Subject: [PATCH 040/127] add vm excutor --- python/tvm/relay/frontend/paddlepaddle.py | 130 +++++++++++------- .../frontend/paddlepaddle/test_forward.py | 56 ++++++-- 2 files changed, 122 insertions(+), 64 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 447b3a645a09..8da1a3d7c17f 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -43,10 +43,10 @@ def shape_of(x, dtype="int32"): """Get shape of a tensor""" - ttype = infer_type(x).checked_type - if not _ty.is_dynamic(ttype): - shape = list(ttype.shape) - return _expr.const(shape, dtype) + # ttype = infer_type(x).checked_type + # if not _ty.is_dynamic(ttype): + # shape = list(ttype.shape) + # return _expr.const(shape, dtype) return _op.shape_of(x, dtype) @@ -64,6 +64,26 @@ def _get_pad_size(in_size, dilated_kernel_size, stride_size): return [pad_before, pad_after] +def _infer_value(x, params): + try: + if isinstance(x, _expr.Constant): + return np.atleast_1d(x.data.numpy()) + return params[x.name_hint].numpy() + except (IndexError, KeyError, AttributeError): + try: + return infer_value(x, params).numpy().tolist() + except Exception: + return x + + +def _infer_shape(x, mod=None): + try: + shape = infer_shape(x, mod) + return (shape, True) + except Exception as e: + return (e, False) + + def convert_arg_max(g, op, block): """Operator converter for arg_max.""" @@ -140,49 +160,51 @@ def get_interpolate_mode(op): return rounding_method, interp_method, coordinate_transformation_mode -def convert_interpolate2d(g, op, x, input_shape): +def convert_interpolate2d(g, op, x): """Operator converter for interpolate 2D(dims == 4).""" layout = op.attr("data_layout") - if layout == "NCHW": - in_h, in_w = input_shape[2], input_shape[3] - else: - in_h, in_w = input_shape[1], input_shape[2] - out_h = op.attr("out_h") out_w = op.attr("out_w") + out_size = [out_h, out_w] input_out_size = op.input("OutSize") input_size_tensor = op.input("SizeTensor") input_scale = op.input("Scale") if input_size_tensor: out_size = g.get_node(input_size_tensor[0]) - out_size = infer_value(out_size, g.get_params()).numpy().tolist() - out_h, out_w = out_size + out_size = _infer_value(out_size, g.get_params()) elif input_out_size: out_size = g.get_node(input_out_size[0]) - out_size = infer_value(out_size, g.get_params()).numpy().tolist() - out_h, out_w = out_size - elif input_scale: - scale_data = g.get_node(input_scale[0]) - scale_data = infer_value(scale_data, g.get_params()).numpy().tolist() - if len(scale_data) > 1: - out_h = int(scale_data[0] * in_h) - out_w = int(scale_data[1] * in_w) - else: - out_h = int(scale_data[0] * in_h) - out_w = int(scale_data[0] * in_w) + out_size = _infer_value(out_size, g.get_params()) else: - scale = op.attr("scale") - scale = [float(i) for i in scale] - if len(scale) > 1: - out_h = int(scale[0] * in_h) - out_w = int(scale[1] * in_w) + input_shape = infer_shape(x) + if layout == "NCHW": + in_h, in_w = input_shape[2], input_shape[3] + else: + in_h, in_w = input_shape[1], input_shape[2] + if input_scale: + scale_data = g.get_node(input_scale[0]) + scale_data = infer_value(scale_data, g.get_params()).numpy().tolist() + if len(scale_data) > 1: + out_h = int(scale_data[0] * in_h) + out_w = int(scale_data[1] * in_w) + else: + out_h = int(scale_data[0] * in_h) + out_w = int(scale_data[0] * in_w) + out_size = [out_h, out_w] + else: + scale = op.attr("scale") + scale = [float(i) for i in scale] + if len(scale) > 1: + out_h = int(scale[0] * in_h) + out_w = int(scale[1] * in_w) + out_size = [out_h, out_w] rounding_method, interp_method, coordinate_transformation_mode = get_interpolate_mode(op) out = _op.image.resize2d( x, - [out_h, out_w], + size=out_size, layout=layout, method=interp_method, coordinate_transformation_mode=coordinate_transformation_mode, @@ -196,13 +218,12 @@ def convert_interpolate(g, op, block): """Operator converter for interpolate.""" x = g.get_node(op.input("X")[0]) - input_shape = infer_shape(x) - dims = len(input_shape) - if dims == 4: - convert_interpolate2d(g, op, x, input_shape) + layout = op.attr("data_layout") + if layout in ("NCHW", "NHWC"): + convert_interpolate2d(g, op, x) else: - msg = "input_shape {} is not supported for PaddlePaddle's interpolate" - raise tvm.error.OpAttributeInvalid(msg.format(dims)) + msg = "layout {} is not supported for PaddlePaddle's interpolate" + raise tvm.error.OpAttributeInvalid(msg.format(layout)) def convert_cast(g, op, block): @@ -236,12 +257,20 @@ def convert_conv2d(g, op, block): kernel = g.get_node(op.input("Filter")[0]) input_x = g.get_node(op.input("Input")[0]) out_channels, _, k_h, k_w = infer_shape(kernel) - in_h, in_w = infer_shape(input_x)[2:] if padding_algorithm == "VALID": paddings = [0, 0] elif padding_algorithm == "SAME": - pad_h = _get_pad_size(in_h, (k_h - 1) * dilations[0] + 1, strides[0]) - pad_w = _get_pad_size(in_w, (k_w - 1) * dilations[1] + 1, strides[1]) + if strides[0] == 0 and strides[1] == 0: + pad_h = _get_pad_size(0, (k_h - 1) * dilations[0] + 1, strides[0]) + pad_w = _get_pad_size(0, (k_w - 1) * dilations[1] + 1, strides[1]) + else: + input_shape, is_succeed = _infer_shape(input_x) + assert is_succeed, "{} \n SAME Padding of conv2d only support fixed shape.".format( + input_shape + ) + in_h, in_w = input_shape[2:] + pad_h = _get_pad_size(in_h, (k_h - 1) * dilations[0] + 1, strides[0]) + pad_w = _get_pad_size(in_w, (k_w - 1) * dilations[1] + 1, strides[1]) paddings = [pad_h[0], pad_w[0], pad_h[1], pad_w[1]] elif padding_algorithm == "EXPLICIT": if len(paddings) == 2: @@ -388,12 +417,14 @@ def convert_fill_constant(g, op, block): dtype = str(dtype).strip().split(".")[1] if op.input("ValueTensor"): shape = g.get_node(op.input("ValueTensor")[0]) - shape = infer_value(shape, g.get_params()).numpy() + shape = _infer_value(shape, g.get_params()) if op.input("ShapeTensor"): shape = g.get_node(op.input("ShapeTensor")[0]) - shape = infer_value(shape, g.get_params()).numpy() - value = np.full(shape, value, dtype) - out = _expr.const(value.astype(dtype)).astype(dtype) + shape = _infer_value(shape, g.get_params()) + print("------", dtype) + out = _op.full(value, shape, dtype="float") + # value = np.full(shape, value, dtype) + # out = _expr.const(value.astype(dtype)).astype(dtype) g.add_node(op.output("Out")[0], out) @@ -656,7 +687,6 @@ def convert_pool2d(g, op, block): ksize = [1, 1] input_x = g.get_node(op.input("X")[0]) - in_h, in_w = infer_shape(input_x)[2:] op_map = { "avg": "avg_pool2d", @@ -673,6 +703,7 @@ def convert_pool2d(g, op, block): if padding_algorithm == "VALID": paddings = [0, 0] elif padding_algorithm == "SAME": + in_h, in_w = infer_shape(input_x)[2:] pad_h = _get_pad_size(in_h, ksize[0], strides[0]) pad_w = _get_pad_size(in_w, ksize[1], strides[1]) paddings = [pad_h[0], pad_w[0], pad_h[1], pad_w[1]] @@ -712,9 +743,9 @@ def convert_padding(g, op, block): if mode == "replicate": mode = "edge" - new_pad_len = len(infer_shape(input_x)) * 2 - new_paddings = [0] * new_pad_len - for i in range(0, len(padding), 2): + pad_len = len(padding) + new_paddings = [0] * (pad_len + 4) + for i in range(0, pad_len, 2): index = -1 - i if data_format[:2] != "NC": index = -3 - i @@ -791,7 +822,7 @@ def convert_shape(g, op, block): def convert_slice(g, op, block): """Operator converter for slice.""" - def parameter_process(starts, ends, axes, dshape): + def parameter_process(starts, ends, axes): new_axes = [] new_starts = [] new_ends = [] @@ -804,11 +835,10 @@ def parameter_process(starts, ends, axes, dshape): pop_index += 1 else: new_starts.append(0) - new_ends.append(dshape[i]) + new_ends.append(np.iinfo(np.int32).max) return new_starts, new_ends, new_axes data = g.get_node(op.input("Input")[0]) - dshape = infer_shape(data) starts = op.attr("starts") ends = op.attr("ends") axes = op.attr("axes") @@ -821,7 +851,7 @@ def parameter_process(starts, ends, axes, dshape): axes = [axes] if isinstance(decrease_axis, int): decrease_axis = [decrease_axis] - starts, ends, axes = parameter_process(starts, ends, axes, dshape) + starts, ends, axes = parameter_process(starts, ends, axes) out = _op.strided_slice(data, begin=starts, end=ends) if decrease_axis: out = _op.squeeze(out, axis=decrease_axis) diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index e4756b040aa1..eb8b654eb346 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -50,7 +50,34 @@ def get_paddle_model(func, input_spec): return baseline_model -def verify_model(func, input_data, rtol=1e-5, atol=1e-5): +def get_tvm_output_with_vm(mod, params, target, device, input_data): + """Generic function to execute and get tvm output with vm executor""" + + ex = relay.create_executor("vm", mod=mod, device=device, target=target) + params.update(input_data) + result = ex.evaluate()(**params) + if isinstance(result, tvm.runtime.NDArray): + return [ + result.numpy(), + ] + return [r.numpy() for r in result] + + +def get_tvm_output(mod, params, target, device, input_data, compiled_names, num): + """Generic function to execute and get tvm output""" + + lib = relay.build(mod, target=target, params=params) + gmod = graph_executor.GraphModule(lib["default"](device)) + for name in compiled_names: + gmod.set_input(name, input_data[name]) + gmod.run() + outputs = [] + for i in range(num): + outputs.append(gmod.get_output(i).numpy()) + return outputs + + +def verify_model(func, input_data, rtol=1e-5, atol=1e-5, input_shape=None): if not (isinstance(input_data, (tuple, list))): input_data = [input_data] @@ -60,11 +87,13 @@ def verify_model(func, input_data, rtol=1e-5, atol=1e-5): compiled_input = {} for idx, data in enumerate(input_data): input_name = "input{}".format(idx) - input_spec.append( - paddle.static.InputSpec(dtype=data.dtype, shape=data.shape, name=input_name) - ) + if input_shape: + shape = input_shape[idx] + else: + shape = data.shape + input_shape_dict[input_name] = shape + input_spec.append(paddle.static.InputSpec(dtype=data.dtype, shape=shape, name=input_name)) input_names.append(input_name) - input_shape_dict[input_name] = data.shape if isinstance(data, np.ndarray): compiled_input[input_name] = data else: @@ -88,15 +117,14 @@ def verify_model(func, input_data, rtol=1e-5, atol=1e-5): with tvm.transform.PassContext(opt_level=3): for target, dev in tvm.testing.enabled_targets(): - lib = relay.build(mod, target=target, params=params) - gmod = graph_executor.GraphModule(lib["default"](dev)) - for name in compiled_names: - gmod.set_input(name, compiled_input[name]) - gmod.run() - - for i, baseline_output in enumerate(baseline_outputs): - compiled_output = gmod.get_output(i).numpy() - + if input_shape: + tvm_output = get_tvm_output_with_vm(mod, params, target, dev, compiled_input) + else: + tvm_output = get_tvm_output( + mod, params, target, dev, compiled_input, compiled_names, len(baseline_outputs) + ) + + for baseline_output, compiled_output in zip(baseline_outputs, tvm_output): assert_shapes_match(baseline_output, compiled_output) tvm.testing.assert_allclose(baseline_output, compiled_output, rtol=rtol, atol=atol) From 30e433b23e8abd301b167cc7c3669eac7e2cf4ba Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Wed, 1 Sep 2021 15:12:01 +0800 Subject: [PATCH 041/127] add vm excutor --- python/tvm/relay/frontend/paddlepaddle.py | 40 +++++-------------- .../frontend/paddlepaddle/test_forward.py | 14 +++++-- 2 files changed, 20 insertions(+), 34 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 8da1a3d7c17f..b247497f9338 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -43,10 +43,6 @@ def shape_of(x, dtype="int32"): """Get shape of a tensor""" - # ttype = infer_type(x).checked_type - # if not _ty.is_dynamic(ttype): - # shape = list(ttype.shape) - # return _expr.const(shape, dtype) return _op.shape_of(x, dtype) @@ -65,10 +61,13 @@ def _get_pad_size(in_size, dilated_kernel_size, stride_size): def _infer_value(x, params): + """Try running infer_value, and if successful, return the inferred value. + Otherwise, return input""" + try: if isinstance(x, _expr.Constant): - return np.atleast_1d(x.data.numpy()) - return params[x.name_hint].numpy() + return x.data.numpy().tolist() + return params[x.name_hint].numpy().tolist() except (IndexError, KeyError, AttributeError): try: return infer_value(x, params).numpy().tolist() @@ -76,14 +75,6 @@ def _infer_value(x, params): return x -def _infer_shape(x, mod=None): - try: - shape = infer_shape(x, mod) - return (shape, True) - except Exception as e: - return (e, False) - - def convert_arg_max(g, op, block): """Operator converter for arg_max.""" @@ -264,11 +255,7 @@ def convert_conv2d(g, op, block): pad_h = _get_pad_size(0, (k_h - 1) * dilations[0] + 1, strides[0]) pad_w = _get_pad_size(0, (k_w - 1) * dilations[1] + 1, strides[1]) else: - input_shape, is_succeed = _infer_shape(input_x) - assert is_succeed, "{} \n SAME Padding of conv2d only support fixed shape.".format( - input_shape - ) - in_h, in_w = input_shape[2:] + in_h, in_w = infer_shape(input_x)[2:] pad_h = _get_pad_size(in_h, (k_h - 1) * dilations[0] + 1, strides[0]) pad_w = _get_pad_size(in_w, (k_w - 1) * dilations[1] + 1, strides[1]) paddings = [pad_h[0], pad_w[0], pad_h[1], pad_w[1]] @@ -397,14 +384,8 @@ def convert_fill_any_like(g, op, block): out_dtype = block.var(out_name).dtype out_dtype = str(out_dtype).strip().split(".")[1] x = g.get_node(op.input("X")[0]) - ipt_type = infer_type(x).checked_type value = op.attr("value") - if not _ty.is_dynamic(ipt_type): - shape = infer_shape(x) - const = np.ones(shape) * value - out = _expr.const(const.astype(out_dtype)) - else: - out = _op.transform.full_like(x, value).astype(out_dtype) + out = _op.transform.full_like(x, value).astype(out_dtype) g.add_node(op.output("Out")[0], out) @@ -415,16 +396,15 @@ def convert_fill_constant(g, op, block): shape = block.var(op.output("Out")[0]).shape dtype = block.var(op.output("Out")[0]).dtype dtype = str(dtype).strip().split(".")[1] + value = _expr.const(value).astype(dtype) if op.input("ValueTensor"): shape = g.get_node(op.input("ValueTensor")[0]) shape = _infer_value(shape, g.get_params()) if op.input("ShapeTensor"): shape = g.get_node(op.input("ShapeTensor")[0]) shape = _infer_value(shape, g.get_params()) - print("------", dtype) - out = _op.full(value, shape, dtype="float") - # value = np.full(shape, value, dtype) - # out = _expr.const(value.astype(dtype)).astype(dtype) + + out = _op.full(value, shape=shape, dtype=dtype) g.add_node(op.output("Out")[0], out) diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index eb8b654eb346..ce86b10a807f 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -89,6 +89,7 @@ def verify_model(func, input_data, rtol=1e-5, atol=1e-5, input_shape=None): input_name = "input{}".format(idx) if input_shape: shape = input_shape[idx] + input_shape_dict[input_name] = [relay.Any()] * len(shape) else: shape = data.shape input_shape_dict[input_name] = shape @@ -371,10 +372,15 @@ def full1(inputs): def full2(inputs): return paddle.full(paddle.shape(inputs), 1.0, dtype=inputs.dtype) + @paddle.jit.to_static + def shape1(inputs): + return paddle.shape(inputs) + input_shape = [1, 3, 10, 10] input_data = paddle.rand(input_shape, dtype="float32") - verify_model(full1, input_data=[input_data]) - verify_model(full2, input_data=[input_data]) + verify_model(shape1, input_data=[input_data], input_shape=[[-1, 3, 10, 10]]) + # verify_model(full1, input_data=[input_data]) + verify_model(full2, input_data=[input_data], input_shape=[[-1, 3, 10, 10]]) @tvm.testing.uses_gpu @@ -641,7 +647,7 @@ def relu(inputs): input_shape = [10, 10] input_data = paddle.rand(input_shape, dtype="float32") - verify_model(relu, input_data=input_data) + verify_model(relu, input_data=input_data, input_shape=[[-1, -1]]) @tvm.testing.uses_gpu @@ -658,7 +664,7 @@ def reshape2(inputs): @paddle.jit.to_static def reshape3(inputs): data_shape = inputs.shape - return inputs.reshape([data_shape[0] * data_shape[1], data_shape[2]]) + return inputs.reshape([data_shape[1], data_shape[2], data_shape[0]]) @paddle.jit.to_static def reshape4(inputs, x): From 771e3c90f3aa463a17d1037c205dc2c6c872a970 Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Wed, 1 Sep 2021 17:06:42 +0800 Subject: [PATCH 042/127] delete input_shape params on test case --- python/tvm/relay/frontend/paddlepaddle.py | 2 +- tests/python/frontend/paddlepaddle/test_forward.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 7c035f1dfdba..60c8e4937742 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -448,7 +448,7 @@ def convert_fill_any_like(g, op, block): out_dtype = block.var(out_name).dtype out_dtype = str(out_dtype).strip().split(".")[1] x = g.get_node(op.input("X")[0]) - value = op.attr("value") + value = _expr.const(op.attr("value")) out = _op.transform.full_like(x, value).astype(out_dtype) g.add_node(op.output("Out")[0], out) diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index 38be3f78ba9d..51534f3f5f2f 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -422,9 +422,9 @@ def shape1(inputs): input_shape = [1, 3, 10, 10] input_data = paddle.rand(input_shape, dtype="float32") - verify_model(shape1, input_data=[input_data], input_shape=[[-1, 3, 10, 10]]) + verify_model(shape1, input_data=[input_data]) # verify_model(full1, input_data=[input_data]) - verify_model(full2, input_data=[input_data], input_shape=[[-1, 3, 10, 10]]) + verify_model(full2, input_data=[input_data]) @tvm.testing.uses_gpu @@ -691,7 +691,7 @@ def relu(inputs): input_shape = [10, 10] input_data = paddle.rand(input_shape, dtype="float32") - verify_model(relu, input_data=input_data, input_shape=[[-1, -1]]) + verify_model(relu, input_data=input_data) @tvm.testing.uses_gpu From 7fa1e1740fe5571d92504ad69f6ccece1753d41b Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Thu, 2 Sep 2021 14:37:49 +0800 Subject: [PATCH 043/127] add unary_op test case --- python/tvm/relay/frontend/paddlepaddle.py | 48 ++++++------ .../frontend/paddlepaddle/test_forward.py | 73 +++++++++---------- 2 files changed, 57 insertions(+), 64 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 60c8e4937742..c684a67b57a8 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -31,6 +31,7 @@ from .. import op as _op from .common import ( fold_constant, + get_relay_op, infer_shape, infer_type, infer_value, @@ -75,19 +76,14 @@ def _infer_value(x, params): return x -def convert_activation(g, op, block): +def convert_unary_op(g, op, block): """Operator converter for all the activation.""" - op_map = { - "exp": _op.exp, - "relu": _op.nn.relu, - "tanh": _op.tanh, - "sqrt": _op.sqrt, - "erf": _op.erf, - "abs": _op.abs, - "sigmoid": _op.sigmoid, - } - act_func = op_map[op.type] + op_map = {} + if op.type in op_map: + act_func = op_map[op.type] + else: + act_func = get_relay_op(op.type) out = act_func(g.get_node(op.input("X")[0])) g.add_node(op.output("Out")[0], out) @@ -138,8 +134,8 @@ def convert_batch_norm(g, op, block): def convert_bmm(g, op, block): """Operator converter for bmm.""" - x = g.get_node(op.input('X')[0]) - y = g.get_node(op.input('Y')[0]) + x = g.get_node(op.input("X")[0]) + y = g.get_node(op.input("Y")[0]) x_shape = infer_shape(x) y_shape = infer_shape(y) if x_shape[0] == 1 and y_shape == 1: @@ -148,11 +144,11 @@ def convert_bmm(g, op, block): y = _op.transpose(y, [1, 0]) out = _op.nn.dense(x, y) out = _op.expand_dims(out, axis=0) - g.add_node(op.output('Out')[0], out) + g.add_node(op.output("Out")[0], out) else: y = _op.transpose(y, [0, 2, 1]) out = _op.nn.batch_matmul(x, y) - g.add_node(op.output('Out')[0], out) + g.add_node(op.output("Out")[0], out) def convert_interpolate2d(g, op, x): @@ -160,11 +156,11 @@ def convert_interpolate2d(g, op, x): def get_interpolate_mode(op): """conver 'interp_method' attr of paddle to tvm""" - + interp_method = op.attr("interp_method") align_corners = op.attr("align_corners") align_mode = op.attr("align_mode") - + rounding_method = "" if interp_method == "nearest": interp_method = "nearest_neighbor" @@ -325,8 +321,7 @@ def convert_conv2d_transpose(g, op, block): paddings = op.attr("paddings") padding_algorithm = op.attr("padding_algorithm") strides = op.attr("strides") - output_padding = op.attr("output_padding") if op.attr( - "output_padding") else [0, 0] + output_padding = op.attr("output_padding") if op.attr("output_padding") else [0, 0] kernel = g.get_node(op.input("Filter")[0]) input_x = g.get_node(op.input("Input")[0]) @@ -930,9 +925,9 @@ def convert_squeeze(g, op, block): def convert_transpose(g, op, block): """Operator converter for transpose.""" - perm = op.attr('axis') - out = _op.transpose(g.get_node(op.input('X')[0]), axes=perm) - g.add_node(op.output('Out')[0], out) + perm = op.attr("axis") + out = _op.transpose(g.get_node(op.input("X")[0]), axes=perm) + g.add_node(op.output("Out")[0], out) def convert_unsqueeze(g, op, block): @@ -946,6 +941,7 @@ def convert_unsqueeze(g, op, block): _convert_map = { + "abs": convert_unary_op, "arg_max": convert_arg_max, "assign": convert_assign, "batch_norm": convert_batch_norm, @@ -964,7 +960,7 @@ def convert_unsqueeze(g, op, block): "elementwise_mul": convert_elementwise_op, "elementwise_sub": convert_elementwise_op, "equal": convert_equal, - "exp": convert_activation, + "exp": convert_unary_op, "feed": convert_feed, "fill_any_like": convert_fill_any_like, "fill_constant": convert_fill_constant, @@ -982,15 +978,15 @@ def convert_unsqueeze(g, op, block): "pad1d": convert_padding, "pad2d": convert_padding, "pad3d": convert_padding, - "relu": convert_activation, + "relu": convert_unary_op, "reshape2": convert_reshape, "scale": convert_scale, "shape": convert_shape, - "sigmoid": convert_activation, + "sigmoid": convert_unary_op, "slice": convert_slice, "softmax": convert_softmax, "squeeze2": convert_squeeze, - "tanh": convert_activation, + "tanh": convert_unary_op, "transpose2": convert_transpose, "unsqueeze2": convert_unsqueeze, } diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index 51534f3f5f2f..a11f947449ad 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -130,6 +130,32 @@ def verify_model(func, input_data, rtol=1e-5, atol=1e-5, input_shape=None): tvm.testing.assert_allclose(baseline_output, compiled_output, rtol=rtol, atol=atol) +@tvm.testing.uses_gpu +def test_forward_unary_op(): + class UnaryOp(nn.Layer): + def __init__(self, op_name): + super(UnaryOp, self).__init__() + for candidate in (paddle, paddle.nn.functional): + self.func = getattr(candidate, op_name, None) + if not self.func: + break + + @paddle.jit.to_static + def forward(self, inputs): + return self.func(inputs) + + input_data = paddle.rand([1, 2, 5, 5], dtype="float32") + op_list = [ + "abs", + "exp", + "relu", + "sigmoid", + "tanh", + ] + for op_name in op_list: + verify_model(UnaryOp(op_name), input_data) + + @tvm.testing.uses_gpu def test_forward_add_subtract(): input_shape = [10] @@ -368,7 +394,13 @@ class Conv2DTranspose2(nn.Layer): def __init__(self): super(Conv2DTranspose2, self).__init__() self.conv_transpose = nn.Conv2DTranspose( - 3, 5, 3, stride=2, padding=[[0,0],[0,0],[1,2],[3,4]], output_padding=1, bias_attr=True + 3, + 5, + 3, + stride=2, + padding=[[0, 0], [0, 0], [1, 2], [3, 4]], + output_padding=1, + bias_attr=True, ) @paddle.jit.to_static @@ -379,7 +411,7 @@ class Conv2DTranspose3(nn.Layer): def __init__(self): super(Conv2DTranspose3, self).__init__() self.conv_transpose = nn.Conv2DTranspose( - 3, 5, 3, stride=3, padding='VALID', output_padding=2, bias_attr=True + 3, 5, 3, stride=3, padding="VALID", output_padding=2, bias_attr=True ) @paddle.jit.to_static @@ -683,17 +715,6 @@ def pad4(inputs): verify_model(pad4, input_data=input_data) -@tvm.testing.uses_gpu -def test_forward_relu(): - @paddle.jit.to_static - def relu(inputs): - return nn.functional.relu(inputs) - - input_shape = [10, 10] - input_data = paddle.rand(input_shape, dtype="float32") - verify_model(relu, input_data=input_data) - - @tvm.testing.uses_gpu def test_forward_reshape(): @paddle.jit.to_static @@ -800,28 +821,6 @@ def squeeze3(inputs): verify_model(squeeze3, input_data=input_data) -@tvm.testing.uses_gpu -def test_forward_tanh(): - @paddle.jit.to_static - def tanh(inputs): - return paddle.tanh(inputs) - - input_shape = [1, 3, 10, 10] - input_data = paddle.rand(input_shape, dtype="float32") - verify_model(tanh, input_data=input_data) - - -@tvm.testing.uses_gpu -def test_forward_sigmoid(): - @paddle.jit.to_static - def sigmoid(inputs): - return nn.functional.sigmoid(inputs) - - input_shape = [10, 10] - input_data = paddle.rand(input_shape, dtype="float32") - verify_model(sigmoid, input_data=input_data) - - if __name__ == "__main__": test_forward_add_subtract() test_forward_argmax() @@ -845,11 +844,9 @@ def sigmoid(inputs): test_forward_matmul() test_forward_pool2d() test_forward_pad() - test_forward_relu() test_forward_reshape() test_forward_scale() test_forward_slice() test_forward_squeeze2() - test_forward_tanh() test_forward_conv_transpose() - test_forward_sigmoid() + test_forward_unary_op() From d45eac0f4406885fbee33a99fe4db8419fbf887a Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Thu, 2 Sep 2021 15:01:02 +0800 Subject: [PATCH 044/127] fix judge bug --- tests/python/frontend/paddlepaddle/test_forward.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index a11f947449ad..2e9cc113fe85 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -137,7 +137,7 @@ def __init__(self, op_name): super(UnaryOp, self).__init__() for candidate in (paddle, paddle.nn.functional): self.func = getattr(candidate, op_name, None) - if not self.func: + if self.func: break @paddle.jit.to_static From 6f3cdc11449dac46aa64c70c9ca929c7213ad014 Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Thu, 2 Sep 2021 15:28:22 +0800 Subject: [PATCH 045/127] add abs isinf sin tan op --- python/tvm/relay/frontend/paddlepaddle.py | 5 +++++ tests/python/frontend/paddlepaddle/test_forward.py | 7 +++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index c684a67b57a8..72a46b113f06 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -952,6 +952,7 @@ def convert_unsqueeze(g, op, block): "concat": convert_concat, "conv2d": convert_conv2d, "conv2d_transpose": convert_conv2d_transpose, + "cosh": convert_unary_op, "cumsum": convert_cumsum, "depthwise_conv2d": convert_conv2d, "dropout": convert_dropout, @@ -964,9 +965,11 @@ def convert_unsqueeze(g, op, block): "feed": convert_feed, "fill_any_like": convert_fill_any_like, "fill_constant": convert_fill_constant, + "floor": convert_unary_op, "gelu": convert_gelu, "hard_sigmoid": convert_hard_sigmoid, "hard_swish": convert_hard_swish, + "isinf": convert_unary_op, "layer_norm": convert_layer_norm, "leaky_relu": convert_leaky_relu, "lookup_table_v2": convert_lookup_table, @@ -983,10 +986,12 @@ def convert_unsqueeze(g, op, block): "scale": convert_scale, "shape": convert_shape, "sigmoid": convert_unary_op, + "sin": convert_unary_op, "slice": convert_slice, "softmax": convert_softmax, "squeeze2": convert_squeeze, "tanh": convert_unary_op, + "tan": convert_unary_op, "transpose2": convert_transpose, "unsqueeze2": convert_unsqueeze, } diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index 2e9cc113fe85..7c5140c50788 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -147,10 +147,13 @@ def forward(self, inputs): input_data = paddle.rand([1, 2, 5, 5], dtype="float32") op_list = [ "abs", - "exp", + "cosh" "exp", + "floor", + "isinf", "relu", "sigmoid", - "tanh", + "sin" "tanh", + "tan", ] for op_name in op_list: verify_model(UnaryOp(op_name), input_data) From 0ac6d2f91c12ca9b1d05941ccfddf2705c4edc91 Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Thu, 2 Sep 2021 16:25:38 +0800 Subject: [PATCH 046/127] add log log10 log1p op --- python/tvm/relay/frontend/paddlepaddle.py | 21 +++++++++++++----- .../frontend/paddlepaddle/test_forward.py | 22 ++++++++++++++++--- 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 72a46b113f06..42bba6084226 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -79,12 +79,8 @@ def _infer_value(x, params): def convert_unary_op(g, op, block): """Operator converter for all the activation.""" - op_map = {} - if op.type in op_map: - act_func = op_map[op.type] - else: - act_func = get_relay_op(op.type) - out = act_func(g.get_node(op.input("X")[0])) + unary_func = get_relay_op(op.type) + out = unary_func(g.get_node(op.input("X")[0])) g.add_node(op.output("Out")[0], out) @@ -557,6 +553,16 @@ def convert_lookup_table(g, op, block): g.add_node(op.output("Out")[0], out) +def convert_log1p(g, op, block): + """Operator converter for log1p.""" + + x = g.get_node(op.input("X")[0]) + dtype = infer_type(x).checked_type.dtype + one = _expr.const(1, dtype=dtype) + out = _op.log(x + one) + g.add_node(op.output("Out")[0], out) + + def convert_matmul(g, op, block): """Operator converter for matmul.""" @@ -973,6 +979,9 @@ def convert_unsqueeze(g, op, block): "layer_norm": convert_layer_norm, "leaky_relu": convert_leaky_relu, "lookup_table_v2": convert_lookup_table, + "log": convert_unary_op, + "log10": convert_unary_op, + "log1p": convert_log1p, "matmul": convert_matmul, "matmul_v2": convert_matmul, "mul": convert_mul, diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index 7c5140c50788..0e5919bd2ccb 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -147,12 +147,16 @@ def forward(self, inputs): input_data = paddle.rand([1, 2, 5, 5], dtype="float32") op_list = [ "abs", - "cosh" "exp", + "cosh", + "exp", "floor", - "isinf", + "log", + "log10", + "log1p", "relu", "sigmoid", - "sin" "tanh", + "sin", + "tanh", "tan", ] for op_name in op_list: @@ -511,6 +515,17 @@ def hard_swish(inputs): verify_model(hard_swish, input_data=input_data) +@tvm.testing.uses_gpu +def test_forward_isinf(): + @paddle.jit.to_static + def isinf(inputs): + return paddle.cast(paddle.isinf(inputs), "int") + + input_shape = [5, 5] + input_data = paddle.rand(input_shape, dtype="float32") + verify_model(isinf, input_data=input_data) + + @tvm.testing.uses_gpu def test_forward_interpolate(): class TestBilinear(nn.Layer): @@ -840,6 +855,7 @@ def squeeze3(inputs): test_forward_hard_sigmoid() test_forward_hard_swish() test_forward_interpolate() + test_forward_isinf() test_forward_layer_norm() test_forward_leaky_relu() test_forward_look_up() From cccef531f7a9a9388d8dfcab052df76dfdb94e43 Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Thu, 2 Sep 2021 16:44:00 +0800 Subject: [PATCH 047/127] add isinf isinf_v2 op --- python/tvm/relay/frontend/paddlepaddle.py | 9 ++++++++- tests/python/frontend/paddlepaddle/test_forward.py | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 42bba6084226..eb20581a2df4 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -79,7 +79,13 @@ def _infer_value(x, params): def convert_unary_op(g, op, block): """Operator converter for all the activation.""" - unary_func = get_relay_op(op.type) + op_map = { + "isinf_v2": _op.isinf, + } + if op.type in op_map: + unary_func = op_map[op.type] + else: + unary_func = get_relay_op(op.type) out = unary_func(g.get_node(op.input("X")[0])) g.add_node(op.output("Out")[0], out) @@ -976,6 +982,7 @@ def convert_unsqueeze(g, op, block): "hard_sigmoid": convert_hard_sigmoid, "hard_swish": convert_hard_swish, "isinf": convert_unary_op, + "isinf_v2": convert_unary_op, "layer_norm": convert_layer_norm, "leaky_relu": convert_leaky_relu, "lookup_table_v2": convert_lookup_table, diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index 0e5919bd2ccb..f2922075fe71 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -519,7 +519,7 @@ def hard_swish(inputs): def test_forward_isinf(): @paddle.jit.to_static def isinf(inputs): - return paddle.cast(paddle.isinf(inputs), "int") + return paddle.cast(paddle.isinf(inputs), "int32") input_shape = [5, 5] input_data = paddle.rand(input_shape, dtype="float32") From 03f4f5d8f9297cb89cf1cf54d5e6f154c9b24c30 Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Fri, 3 Sep 2021 14:58:53 +0800 Subject: [PATCH 048/127] delete infer_shape of bmm --- python/tvm/relay/frontend/paddlepaddle.py | 20 +++++-------------- .../frontend/paddlepaddle/test_forward.py | 2 +- 2 files changed, 6 insertions(+), 16 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index eb20581a2df4..968059e1a4d8 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -138,19 +138,9 @@ def convert_bmm(g, op, block): x = g.get_node(op.input("X")[0]) y = g.get_node(op.input("Y")[0]) - x_shape = infer_shape(x) - y_shape = infer_shape(y) - if x_shape[0] == 1 and y_shape == 1: - x = _op.reshape(x, x_shape[1:]) - y = _op.reshape(y, y_shape[1:]) - y = _op.transpose(y, [1, 0]) - out = _op.nn.dense(x, y) - out = _op.expand_dims(out, axis=0) - g.add_node(op.output("Out")[0], out) - else: - y = _op.transpose(y, [0, 2, 1]) - out = _op.nn.batch_matmul(x, y) - g.add_node(op.output("Out")[0], out) + y = _op.transpose(y, [0, 2, 1]) + out = _op.nn.batch_matmul(x, y) + g.add_node(op.output("Out")[0], out) def convert_interpolate2d(g, op, x): @@ -328,10 +318,10 @@ def convert_conv2d_transpose(g, op, block): kernel = g.get_node(op.input("Filter")[0]) input_x = g.get_node(op.input("Input")[0]) _, out_channels, k_h, k_w = infer_shape(kernel) - in_h, in_w = infer_shape(input_x)[2:] if padding_algorithm == "VALID": paddings = [0, 0] elif padding_algorithm == "SAME": + in_h, in_w = infer_shape(input_x)[2:] pad_h = _get_pad_size(in_h, (k_h - 1) * dilations[0] + 1, strides[0]) pad_w = _get_pad_size(in_w, (k_w - 1) * dilations[1] + 1, strides[1]) paddings = [pad_h[0], pad_w[0], pad_h[1], pad_w[1]] @@ -1006,8 +996,8 @@ def convert_unsqueeze(g, op, block): "slice": convert_slice, "softmax": convert_softmax, "squeeze2": convert_squeeze, - "tanh": convert_unary_op, "tan": convert_unary_op, + "tanh": convert_unary_op, "transpose2": convert_transpose, "unsqueeze2": convert_unsqueeze, } diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index f2922075fe71..cb5c17f758f8 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -156,8 +156,8 @@ def forward(self, inputs): "relu", "sigmoid", "sin", - "tanh", "tan", + "tanh", ] for op_name in op_list: verify_model(UnaryOp(op_name), input_data) From 9d8de1963ee5f6fcf73581d76a310f77b8be7e87 Mon Sep 17 00:00:00 2001 From: wjj19950828 Date: Mon, 6 Sep 2021 12:46:16 +0800 Subject: [PATCH 049/127] Add paddle_frontend ops --- python/tvm/relay/frontend/paddlepaddle.py | 283 ++++++++++++++++++ .../frontend/paddlepaddle/test_forward.py | 150 +++++++++- 2 files changed, 432 insertions(+), 1 deletion(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 968059e1a4d8..769213fbe335 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -90,6 +90,32 @@ def convert_unary_op(g, op, block): g.add_node(op.output("Out")[0], out) +def convert_addmm(g, op, block): + """Operator converter for addmm.""" + + input = g.get_node(op.input('Input')[0]) + x = g.get_node(op.input('X')[0]) + y = g.get_node(op.input('Y')[0]) + + alpha = op.attr('Alpha') + beta = op.attr('Beta') + dtype = block.var(op.output('Out')[0]).dtype + dtype = str(dtype).strip().split('.')[1] + + if not isinstance(alpha, _expr.Expr) and alpha != 1: + alpha = _expr.const(alpha, dtype) + x *= alpha + + if not isinstance(beta, _expr.Expr) and beta != 1: + beta = _expr.const(beta, dtype) + input *= beta + + transposed_y = _op.transpose(y, axes=[1, 0]) + dense_out = _op.nn.dense(x, transposed_y) + out = dense_out + input + g.add_node(op.output('Out')[0], out) + + def convert_arg_max(g, op, block): """Operator converter for arg_max.""" @@ -106,6 +132,22 @@ def convert_arg_max(g, op, block): g.add_node(op.output("Out")[0], out) +def convert_arg_min(g, op, block): + """Operator converter for arg_min.""" + + axis = op.attr("axis") + keepdims = op.attr("keepdims") + flatten = op.attr("flatten") + + x = g.get_node(op.input("X")[0]) + if axis is None or flatten: + x = _op.reshape(x, [-1]) + out = _op.argmin(x, axis=None, keepdims=True) + else: + out = _op.argmin(x, axis=axis, keepdims=keepdims) + g.add_node(op.output("Out")[0], out) + + def convert_assign(g, op, block): """Operator converter for assign.""" @@ -348,6 +390,23 @@ def convert_conv2d_transpose(g, op, block): g.add_node(op.output("Output")[0], out) +def convert_crop(g, op, block): + """Operator converter for crop.""" + + x = g.get_node(op.input('X')[0]) + offsets = op.attr('offsets') + shape = op.attr('shape') + + crop_len = len(shape) + slice_start = [0] * crop_len + slice_end = shape + for i in range(crop_len): + slice_start[i] += offsets[i] + slice_end[i] += offsets[i] + out = _op.strided_slice(x, slice_start, slice_end) + g.add_node(op.output('Out')[0], out) + + def convert_cumsum(g, op, block): """Operator converter for cumsum.""" @@ -376,6 +435,16 @@ def convert_dropout(g, op, block): g.add_node(op.output("Out")[0], out) +def convert_dot(g, op, block): + """Operator converter for dot.""" + + x = g.get_node(op.input('X')[0]) + y = g.get_node(op.input('Y')[0]) + + out = _op.sum(_op.multiply(x, y), axis=[-1], keepdims=True) + g.add_node(op.output('Out')[0], out) + + def convert_elementwise_op(g, op, block): """Operator converter for all the elementwise operators.""" @@ -410,6 +479,31 @@ def convert_equal(g, op, block): g.add_node(op.output("Out")[0], out) +def convert_expand(g, op, block): + """Operator converter for expand.""" + + x = g.get_node(op.input('X')[0]) + input_shape = list(infer_shape(x)) + + ndims = len(input_shape) + sizes = op.attr('shape') + out = x + + out_dims = len(sizes) + if ndims < out_dims: + num_newaxis = out_dims - ndims + out = _op.expand_dims(out, axis=0, num_newaxis=num_newaxis) + input_shape = [1] * num_newaxis + input_shape + + for i in range(out_dims): + if sizes[i] != -1 and input_shape[i] == 1: + if not isinstance(sizes[i], int): + sizes[i] = int(infer_value(sizes[i], {}).numpy()) + out = _op.repeat(out, sizes[i], axis=i) + + g.add_node(op.output('Out')[0], out) + + def convert_feed(g, op, block): """Converter for model input node.""" @@ -459,6 +553,50 @@ def convert_fill_constant(g, op, block): g.add_node(op.output("Out")[0], out) +def convert_fill_constant_batch_size_like(g, op, block): + """Operator converter for fill_constant_batch_size_like.""" + + x = g.get_node(op.input('Input')[0]) + input_shape = infer_shape(x) + out_shape = op.attr('shape') + input_dim_idx = op.attr('input_dim_idx') + output_dim_idx = op.attr('output_dim_idx') + value = op.attr('value') + dtype = block.var(op.output('Out')[0]).dtype + dtype = str(dtype).strip().split('.')[1] + out_shape[output_dim_idx] = input_shape[input_dim_idx] + value = np.full(out_shape, value, dtype) + out = _expr.const(value.astype(dtype)).astype(dtype) + g.add_node(op.output('Out')[0], out) + + +def convert_flatten(g, op, block): + """Operator converter for flatten.""" + + x = g.get_node(op.input('X')[0]) + input_shape = list(infer_shape(x)) + + start = op.attr('start_axis') + end = op.attr('stop_axis') + ndim = len(input_shape) + if end < 0: + end += ndim + new_shape = [0] * start + + new_shape.append(-1) + squeeze_axes = [] + for i in range(start + 1, end + 1): + new_shape.append(1) + squeeze_axes.append(i) + for _ in range(end + 1, ndim): + new_shape.append(0) + out = _op.reshape(x, new_shape) + if squeeze_axes: + out = _op.squeeze(out, axis=squeeze_axes) + + g.add_node(op.output('Out')[0], out) + + def convert_gelu(g, op, block): """Operator converter for gelu.""" @@ -826,6 +964,137 @@ def convert_reshape(g, op, block): g.add_node(op.output("Out")[0], out) +def convert_rnn(g, op, block): + """Operator converter for rnn.""" + + def generate_lstm(X_steps, H_t, C_t, W, R, WB, RB, f_act, g_act, h_act, backwards=False): + h_list = [] + seq_length = len(X_steps) + for i in range(seq_length): + step = X_steps[i] if not backwards else X_steps[seq_length - (i + 1)] + step = _op.squeeze(step, axis=[0]) + gates = _op.nn.dense(step, W) + _op.nn.dense(H_t, R) + if WB is not None: + gates += WB + if RB is not None: + gates += RB + i, f, c, o = _op.split(gates, 4, axis=-1) + + i = f_act(i) + f = f_act(f) + + c = g_act(c) + C = f * C_t + i * c + + o = f_act(o) + + H = o * h_act(C) + + H_t = H + C_t = C + h_list.append(_op.expand_dims(H, axis=0)) + + if backwards: + h_list = h_list[::-1] + + # Concatenate outputs and add back in direction axis. + concatenated = _op.concatenate(h_list, 0) + output = _op.expand_dims(concatenated, axis=1) + H_t = _op.expand_dims(H_t, axis=0) + C_t = _op.expand_dims(C_t, axis=0) + + return output, H_t, C_t + + def make_param_inputs(g, node, layer, hidden_size, num_layers): + bidirect_len = 4 if node.attr('is_bidirec') else 2 + all_layer_param_len = len(node.input('WeightList')) + weight_list = node.input('WeightList')[:all_layer_param_len // 2] + bias_list = node.input('WeightList')[all_layer_param_len // 2:] + single_layer_param_len = all_layer_param_len // num_layers + + layer_weight_list = weight_list[layer * bidirect_len:layer * + bidirect_len + bidirect_len] + layer_bias_list = bias_list[layer * bidirect_len:layer * bidirect_len + + bidirect_len] + param_list = layer_weight_list + layer_bias_list + param_list_len = len(param_list) + + input_weights = param_list[0:param_list_len // 2:2] + hidden_weights = param_list[1:param_list_len // 2:2] + + input_bias = param_list[param_list_len // 2:param_list_len:2] + hidden_bias = param_list[param_list_len // 2 + 1:param_list_len:2] + + return input_weights, hidden_weights, input_bias, hidden_bias + + def make_init_param_inputs(g, node, layer): + all_init_h, all_init_c = node.input('PreState') + bidirect_len = 2 if node.attr('is_bidirec') else 1 + init_h = _op.strided_slice(g.get_node(all_init_h), [layer * bidirect_len], + [layer * bidirect_len + bidirect_len], axes=[0]) + init_c = _op.strided_slice(g.get_node(all_init_c), [layer * bidirect_len], + [layer * bidirect_len + bidirect_len], axes=[0]) + return init_h, init_c + + dropout_prob = op.attr('dropout_prob') + hidden_size = op.attr('hidden_size') + input_size = op.attr('input_size') + num_layers = op.attr('num_layers') + is_bidirec = op.attr('is_bidirec') + + input_x = g.get_node(op.input('Input')[0]) + + num_directions = 1 + if is_bidirec: + num_directions = 2 + + X_shape = infer_shape(input_x) + time_steps = X_shape[0] + X_steps = _op.split(input_x, indices_or_sections=time_steps, axis=0) + for layer in range(num_layers): + input_weights, hidden_weights, input_bias, hidden_bias = make_param_inputs(g, op, layer, hidden_size, num_layers) + + init_h, init_c = make_init_param_inputs(g, op, layer) + init_hs = _op.split(init_h, num_directions) + init_cs = _op.split(init_c, num_directions) + result_output = [] + result_H = [] + result_C = [] + for i in range(num_directions): + H_t = _op.squeeze(init_hs[i], axis=[0]) + C_t = _op.squeeze(init_cs[i], axis=[0]) + W = g.get_node(input_weights[i]) + R = g.get_node(hidden_weights[i]) + WB = g.get_node(input_bias[i]) + RB = g.get_node(hidden_bias[i]) + output, H, C = generate_lstm( + X_steps=X_steps, + H_t=H_t, + C_t=C_t, + W=W, + R=R, + WB=WB, + RB=RB, + f_act=_op.sigmoid, + g_act=_op.tanh, + h_act=_op.tanh, + backwards=i == 1 + ) + result_output.append(output) + result_H.append(H) + result_C.append(C) + output = _op.concatenate(result_output, axis=1) + H = _op.concatenate(result_H, axis=0) + C = _op.concatenate(result_C, axis=0) + + output = _op.transpose(output, axes=[0, 2, 1, 3]) + output = _op.reshape(output, newshape=(0, 0, -1)) + X_steps = output + X_steps = _op.split(X_steps, indices_or_sections=time_steps, axis=0) + + g.add_node(op.output('Out')[0], output) + + def convert_scale(g, op, block): """Operator converter for scale.""" @@ -944,19 +1213,28 @@ def convert_unsqueeze(g, op, block): _convert_map = { "abs": convert_unary_op, + "acos": convert_unary_op, + "addmm": convert_addmm, "arg_max": convert_arg_max, + "arg_min": convert_arg_min, + "asin": convert_unary_op, "assign": convert_assign, + "atan": convert_unary_op, "batch_norm": convert_batch_norm, "bicubic_interp_v2": convert_interpolate, "bilinear_interp_v2": convert_interpolate, "bmm": convert_bmm, "cast": convert_cast, + "ceil": convert_unary_op, "concat": convert_concat, "conv2d": convert_conv2d, "conv2d_transpose": convert_conv2d_transpose, + "cos": convert_unary_op, "cosh": convert_unary_op, + "crop_tensor": convert_crop, "cumsum": convert_cumsum, "depthwise_conv2d": convert_conv2d, + "dot": convert_dot, "dropout": convert_dropout, "elementwise_add": convert_elementwise_op, "elementwise_div": convert_elementwise_op, @@ -964,9 +1242,12 @@ def convert_unsqueeze(g, op, block): "elementwise_sub": convert_elementwise_op, "equal": convert_equal, "exp": convert_unary_op, + "expand_v2": convert_expand, "feed": convert_feed, "fill_any_like": convert_fill_any_like, "fill_constant": convert_fill_constant, + 'fill_constant_batch_size_like': convert_fill_constant_batch_size_like, + "flatten_contiguous_range": convert_flatten, "floor": convert_unary_op, "gelu": convert_gelu, "hard_sigmoid": convert_hard_sigmoid, @@ -975,6 +1256,7 @@ def convert_unsqueeze(g, op, block): "isinf_v2": convert_unary_op, "layer_norm": convert_layer_norm, "leaky_relu": convert_leaky_relu, + "lookup_table": convert_lookup_table, "lookup_table_v2": convert_lookup_table, "log": convert_unary_op, "log10": convert_unary_op, @@ -989,6 +1271,7 @@ def convert_unsqueeze(g, op, block): "pad3d": convert_padding, "relu": convert_unary_op, "reshape2": convert_reshape, + "rnn": convert_rnn, "scale": convert_scale, "shape": convert_shape, "sigmoid": convert_unary_op, diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index cb5c17f758f8..88c279974d58 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -147,6 +147,11 @@ def forward(self, inputs): input_data = paddle.rand([1, 2, 5, 5], dtype="float32") op_list = [ "abs", + "acos", + "asin", + "atan", + "ceil", + "cos", "cosh", "exp", "floor", @@ -187,6 +192,21 @@ def add_subtract3(inputs1, inputs2): verify_model(add_subtract3, [input_data, input_data2]) +@tvm.testing.uses_gpu +def test_forward_addmm(): + @paddle.jit.to_static + def addmm(input, x, y, alpha=1, beta=1): + return paddle.addmm(input, x, y, alpha, beta) + + input_shape = [10, 10] + x_shape = [10, 3] + y_shape = [3, 10] + input_data = paddle.rand(input_shape, dtype="float32") + x_data = paddle.rand(x_shape, dtype="float32") + y_data = paddle.rand(y_shape, dtype="float32") + verify_model(addmm, input_data=[input_data, x_data, y_data]) + + @tvm.testing.uses_gpu def test_forward_argmax(): input_shape = [1, 3, 10, 10] @@ -218,6 +238,37 @@ def forward(self, inputs): verify_model(ArgMax3(), input_data=input_data) +@tvm.testing.uses_gpu +def test_forward_argmin(): + input_shape = [1, 3, 10, 10] + + class ArgMin(nn.Layer): + @paddle.jit.to_static + def forward(self, inputs): + return paddle.argmin(inputs) + + class ArgMin1(nn.Layer): + @paddle.jit.to_static + def forward(self, inputs): + return inputs.argmin(axis=1) + + class ArgMin2(nn.Layer): + @paddle.jit.to_static + def forward(self, inputs): + return inputs.argmin(axis=1, keepdim=False) + + class ArgMin3(nn.Layer): + @paddle.jit.to_static + def forward(self, inputs): + return inputs.argmin(axis=2, keepdim=True) + + input_data = paddle.rand(input_shape, dtype="float32") + verify_model(ArgMin(), input_data=input_data) + verify_model(ArgMin1(), input_data=input_data) + verify_model(ArgMin2(), input_data=input_data) + verify_model(ArgMin3(), input_data=input_data) + + @tvm.testing.uses_gpu def test_forward_assign(): @paddle.jit.to_static @@ -323,6 +374,37 @@ def concat_unsqueeze2(inputs): verify_model(concat_unsqueeze2, input_data=input_data) +@tvm.testing.uses_gpu +def test_forward_crop(): + input_shape = [10, 10] + + class Crop(nn.Layer): + @paddle.jit.to_static + def forward(self, inputs): + return paddle.crop(inputs, shape=[2, 2]) + + class Crop1(nn.Layer): + @paddle.jit.to_static + def forward(self, inputs): + return paddle.crop(inputs, shape=[3, 3], offsets=[0, 1]) + + class Crop2(nn.Layer): + @paddle.jit.to_static + def forward(self, inputs): + return paddle.crop(inputs, shape=[3, 3], offsets=[1, 0]) + + class Crop3(nn.Layer): + @paddle.jit.to_static + def forward(self, inputs): + return paddle.crop(inputs, shape=[3, 3], offsets=[1, 1]) + + input_data = paddle.rand(input_shape, dtype="float32") + verify_model(Crop(), input_data=input_data) + verify_model(Crop1(), input_data=input_data) + verify_model(Crop2(), input_data=input_data) + verify_model(Crop3(), input_data=input_data) + + @tvm.testing.uses_gpu def test_forward_cumsum(): @paddle.jit.to_static @@ -433,6 +515,19 @@ def forward(self, inputs): verify_model(Conv2DTranspose3(), input_data=conv2d_transpose_input_data) +@tvm.testing.uses_gpu +def test_forward_dot(): + @paddle.jit.to_static + def dot(x, y): + return paddle.dot(x, y) + + x_shape = [10, 3] + y_shape = [10, 3] + x_data = paddle.rand(x_shape, dtype="float32") + y_data = paddle.rand(y_shape, dtype="float32") + verify_model(dot, input_data=[x_data, y_data]) + + @tvm.testing.uses_gpu def test_forward_dropout(): @paddle.jit.to_static @@ -445,6 +540,32 @@ def dropout(inputs): verify_model(dropout, input_data=input_data) +@tvm.testing.uses_gpu +def test_forward_expand(): + @paddle.jit.to_static + def expand(inputs): + return paddle.expand(inputs, shape=[2, 3]) + + x_shape = [3] + x_data = paddle.rand(x_shape, dtype="float32") + verify_model(expand, input_data=[x_data]) + + +@tvm.testing.uses_gpu +def test_forward_flatten(): + @paddle.jit.to_static + def flatten1(inputs): + return paddle.flatten(inputs, start_axis=1, stop_axis=2) + + def flatten2(inputs): + return paddle.flatten(inputs, start_axis=0, stop_axis=-1) + + x_shape = [3, 100, 100, 4] + x_data = paddle.rand(x_shape, dtype="float32") + verify_model(flatten1, input_data=[x_data]) + verify_model(flatten2, input_data=[x_data]) + + @tvm.testing.uses_gpu def test_forward_shape_full(): @paddle.jit.to_static @@ -623,6 +744,26 @@ def forward(self, inputs): verify_model(LookUp(), input_data=input_data) +@tvm.testing.uses_gpu +def test_forward_lstm(): + lstm_input_shape = [25, 1, 288] + + class LSTM1(nn.Layer): + def __init__(self): + super(LSTM1, self).__init__() + self.lstm = nn.LSTM(288, 48, 2, direction="bidirect", time_major=True) + + @paddle.jit.to_static + def forward(self, inputs, prev_h, prev_c): + y, (h, c) = self.lstm(inputs, (prev_h, prev_c)) + return y + + lstm_input_data = paddle.rand(lstm_input_shape, dtype="float32") + prev_h = paddle.rand([4, 1, 48], dtype="float32") + prev_c = paddle.rand([4, 1, 48], dtype="float32") + verify_model(LSTM1(), input_data=[lstm_input_data, prev_h, prev_c]) + + @tvm.testing.uses_gpu def test_forward_multiply(): @paddle.jit.to_static @@ -841,14 +982,20 @@ def squeeze3(inputs): if __name__ == "__main__": test_forward_add_subtract() + test_forward_addmm() test_forward_argmax() + test_forward_argmin() test_forward_assign() test_forward_batch_norm() test_forward_cast() test_forward_concat_unsqueeze() - test_forward_cumsum() test_forward_conv() + test_forward_crop() + test_forward_cumsum() + test_forward_dot() test_forward_dropout() + test_forward_expand() + test_forward_flatten() test_forward_shape_full() test_forward_ones_like() test_forward_gelu() @@ -859,6 +1006,7 @@ def squeeze3(inputs): test_forward_layer_norm() test_forward_leaky_relu() test_forward_look_up() + test_forward_lstm() test_forward_multiply() test_forward_matmul() test_forward_pool2d() From 406e16cedd6a59d2395bab13cc616587a0cf0013 Mon Sep 17 00:00:00 2001 From: wjj19950828 Date: Mon, 6 Sep 2021 13:52:22 +0800 Subject: [PATCH 050/127] fixed for pylint --- python/tvm/relay/frontend/paddlepaddle.py | 81 ++++++++++++++--------- 1 file changed, 49 insertions(+), 32 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 769213fbe335..eac11738a7f9 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -93,7 +93,7 @@ def convert_unary_op(g, op, block): def convert_addmm(g, op, block): """Operator converter for addmm.""" - input = g.get_node(op.input('Input')[0]) + input_x = g.get_node(op.input('Input')[0]) x = g.get_node(op.input('X')[0]) y = g.get_node(op.input('Y')[0]) @@ -108,11 +108,11 @@ def convert_addmm(g, op, block): if not isinstance(beta, _expr.Expr) and beta != 1: beta = _expr.const(beta, dtype) - input *= beta + input_x *= beta transposed_y = _op.transpose(y, axes=[1, 0]) dense_out = _op.nn.dense(x, transposed_y) - out = dense_out + input + out = dense_out + input_x g.add_node(op.output('Out')[0], out) @@ -242,7 +242,8 @@ def get_interpolate_mode(op): in_h, in_w = input_shape[1], input_shape[2] if input_scale: scale_data = g.get_node(input_scale[0]) - scale_data = infer_value(scale_data, g.get_params()).numpy().tolist() + scale_data = infer_value( + scale_data, g.get_params()).numpy().tolist() if len(scale_data) > 1: out_h = int(scale_data[0] * in_h) out_w = int(scale_data[1] * in_w) @@ -258,7 +259,8 @@ def get_interpolate_mode(op): out_w = int(scale[1] * in_w) out_size = [out_h, out_w] - rounding_method, interp_method, coordinate_transformation_mode = get_interpolate_mode(op) + rounding_method, interp_method, coordinate_transformation_mode = get_interpolate_mode( + op) out = _op.image.resize2d( x, size=out_size, @@ -322,8 +324,10 @@ def convert_conv2d(g, op, block): pad_w = _get_pad_size(0, (k_w - 1) * dilations[1] + 1, strides[1]) else: in_h, in_w = infer_shape(input_x)[2:] - pad_h = _get_pad_size(in_h, (k_h - 1) * dilations[0] + 1, strides[0]) - pad_w = _get_pad_size(in_w, (k_w - 1) * dilations[1] + 1, strides[1]) + pad_h = _get_pad_size( + in_h, (k_h - 1) * dilations[0] + 1, strides[0]) + pad_w = _get_pad_size( + in_w, (k_w - 1) * dilations[1] + 1, strides[1]) paddings = [pad_h[0], pad_w[0], pad_h[1], pad_w[1]] elif padding_algorithm == "EXPLICIT": if len(paddings) == 2: @@ -355,7 +359,8 @@ def convert_conv2d_transpose(g, op, block): paddings = op.attr("paddings") padding_algorithm = op.attr("padding_algorithm") strides = op.attr("strides") - output_padding = op.attr("output_padding") if op.attr("output_padding") else [0, 0] + output_padding = op.attr("output_padding") if op.attr( + "output_padding") else [0, 0] kernel = g.get_node(op.input("Filter")[0]) input_x = g.get_node(op.input("Input")[0]) @@ -465,7 +470,8 @@ def convert_elementwise_op(g, op, block): if axis < 0: axis = axis + len(ipt0_shape) if axis != len(ipt0_shape) - 1: - ipt1 = _op.expand_dims(ipt1, axis=axis, num_newaxis=(len(ipt0_shape) - axis - 1)) + ipt1 = _op.expand_dims( + ipt1, axis=axis, num_newaxis=(len(ipt0_shape) - axis - 1)) out = op_func(ipt0, ipt1) g.add_node(op.output("Out")[0], out) @@ -603,7 +609,8 @@ def convert_gelu(g, op, block): x = g.get_node(op.input("X")[0]) out = x * ( _expr.const(0.5, dtype="float32") - + _op.erf(x * _expr.const(0.5 ** 0.5, dtype="float32")) * _expr.const(0.5, dtype="float32") + + _op.erf(x * _expr.const(0.5 ** 0.5, dtype="float32")) * + _expr.const(0.5, dtype="float32") ) g.add_node(op.output("Out")[0], out) @@ -624,9 +631,12 @@ def convert_hard_swish(g, op, block): offset = op.attr("offset") scale = op.attr("scale") threshold = op.attr("threshold") - assert np.isclose(offset, 3.0), "Only support offset==3.0 for PaddlePaddle's hard_swish" - assert np.isclose(scale, 6.0), "Only support scale==6.0 for PaddlePaddle's hard_swish" - assert np.isclose(threshold, 6.0), "Only support threshold==6.0 for PaddlePaddle's hard_swish" + assert np.isclose( + offset, 3.0), "Only support offset==3.0 for PaddlePaddle's hard_swish" + assert np.isclose( + scale, 6.0), "Only support scale==6.0 for PaddlePaddle's hard_swish" + assert np.isclose( + threshold, 6.0), "Only support threshold==6.0 for PaddlePaddle's hard_swish" x = g.get_node(op.input("X")[0]) out = _op.clip(x, -1 * offset, offset) out = out / _expr.const(threshold) + _expr.const(0.5) @@ -737,7 +747,8 @@ def flatten_to_nd(x, x_shape, nd=3): return x newshape = _op.concatenate( [ - _expr.const([-1], dtype=infer_type(x_shape).checked_type.dtype), + _expr.const( + [-1], dtype=infer_type(x_shape).checked_type.dtype), _op.strided_slice(x_shape, [ndims - nd + 1], [ndims]), ], 0, @@ -782,10 +793,12 @@ def flatten_to_nd(x, x_shape, nd=3): [ out_batch, _op.strided_slice( - a_shape, [infer_shape(a_shape)[0] - 2], [infer_shape(a_shape)[0] - 1] + a_shape, [infer_shape(a_shape)[0] - + 2], [infer_shape(a_shape)[0] - 1] ), _op.strided_slice( - b_shape, [infer_shape(b_shape)[0] - 1], [infer_shape(b_shape)[0]] + b_shape, [infer_shape(b_shape)[0] - + 1], [infer_shape(b_shape)[0]] ), ], 0, @@ -824,7 +837,8 @@ def convert_mul(g, op, block): if x_num_col_dims == 1: x = _op.nn.batch_flatten(x) else: - pre_shape = _op.prod(_op.strided_slice(x_shape, [0], [x_num_col_dims], [1]), keepdims=True) + pre_shape = _op.prod(_op.strided_slice( + x_shape, [0], [x_num_col_dims], [1]), keepdims=True) post_shape = _op.prod( _op.strided_slice(x_shape, [x_num_col_dims], [x_dim], [1]), keepdims=True ) @@ -834,7 +848,8 @@ def convert_mul(g, op, block): if y_num_col_dims == 1: y = _op.nn.batch_flatten(y) else: - pre_shape = _op.prod(_op.strided_slice(y_shape, [0], [y_num_col_dims], [1]), keepdims=True) + pre_shape = _op.prod(_op.strided_slice( + y_shape, [0], [y_num_col_dims], [1]), keepdims=True) post_shape = _op.prod( _op.strided_slice(y_shape, [y_num_col_dims], [y_dim], [1]), keepdims=True ) @@ -900,7 +915,8 @@ def convert_pool2d(g, op, block): input_x, pool_size=ksize, strides=strides, padding=paddings, ceil_mode=ceil_mode ) else: - out = getattr(_op.nn, "adaptive_" + op_map[pooling_type])(input_x, output_size=ksize) + out = getattr(_op.nn, "adaptive_" + + op_map[pooling_type])(input_x, output_size=ksize) g.add_node(op.output("Out")[0], out) @@ -931,7 +947,8 @@ def convert_padding(g, op, block): new_paddings[index] = padding[i + 1] new_paddings[index - 1] = padding[i] - new_paddings = [new_paddings[i : i + 2] for i in range(0, len(new_paddings), 2)] + new_paddings = [new_paddings[i: i + 2] + for i in range(0, len(new_paddings), 2)] out = _op.nn.pad(input_x, new_paddings, pad_value=value, pad_mode=mode) g.add_node(op.output("Out")[0], out) @@ -966,12 +983,13 @@ def convert_reshape(g, op, block): def convert_rnn(g, op, block): """Operator converter for rnn.""" - + def generate_lstm(X_steps, H_t, C_t, W, R, WB, RB, f_act, g_act, h_act, backwards=False): h_list = [] seq_length = len(X_steps) for i in range(seq_length): - step = X_steps[i] if not backwards else X_steps[seq_length - (i + 1)] + step = X_steps[i] if not backwards else X_steps[seq_length - + (i + 1)] step = _op.squeeze(step, axis=[0]) gates = _op.nn.dense(step, W) + _op.nn.dense(H_t, R) if WB is not None: @@ -985,7 +1003,7 @@ def generate_lstm(X_steps, H_t, C_t, W, R, WB, RB, f_act, g_act, h_act, backward c = g_act(c) C = f * C_t + i * c - + o = f_act(o) H = o * h_act(C) @@ -1010,7 +1028,6 @@ def make_param_inputs(g, node, layer, hidden_size, num_layers): all_layer_param_len = len(node.input('WeightList')) weight_list = node.input('WeightList')[:all_layer_param_len // 2] bias_list = node.input('WeightList')[all_layer_param_len // 2:] - single_layer_param_len = all_layer_param_len // num_layers layer_weight_list = weight_list[layer * bidirect_len:layer * bidirect_len + bidirect_len] @@ -1031,14 +1048,12 @@ def make_init_param_inputs(g, node, layer): all_init_h, all_init_c = node.input('PreState') bidirect_len = 2 if node.attr('is_bidirec') else 1 init_h = _op.strided_slice(g.get_node(all_init_h), [layer * bidirect_len], - [layer * bidirect_len + bidirect_len], axes=[0]) + [layer * bidirect_len + bidirect_len], axes=[0]) init_c = _op.strided_slice(g.get_node(all_init_c), [layer * bidirect_len], - [layer * bidirect_len + bidirect_len], axes=[0]) + [layer * bidirect_len + bidirect_len], axes=[0]) return init_h, init_c - dropout_prob = op.attr('dropout_prob') hidden_size = op.attr('hidden_size') - input_size = op.attr('input_size') num_layers = op.attr('num_layers') is_bidirec = op.attr('is_bidirec') @@ -1047,12 +1062,13 @@ def make_init_param_inputs(g, node, layer): num_directions = 1 if is_bidirec: num_directions = 2 - + X_shape = infer_shape(input_x) time_steps = X_shape[0] X_steps = _op.split(input_x, indices_or_sections=time_steps, axis=0) for layer in range(num_layers): - input_weights, hidden_weights, input_bias, hidden_bias = make_param_inputs(g, op, layer, hidden_size, num_layers) + input_weights, hidden_weights, input_bias, hidden_bias = make_param_inputs( + g, op, layer, hidden_size, num_layers) init_h, init_c = make_init_param_inputs(g, op, layer) init_hs = _op.split(init_h, num_directions) @@ -1091,7 +1107,7 @@ def make_init_param_inputs(g, node, layer): output = _op.reshape(output, newshape=(0, 0, -1)) X_steps = output X_steps = _op.split(X_steps, indices_or_sections=time_steps, axis=0) - + g.add_node(op.output('Out')[0], output) @@ -1439,5 +1455,6 @@ def from_paddle(program_or_layer, shape_dict=None, scope=None): # model is loaded by `paddle.static.load_inference_model` mod, params = g.from_program(program_or_layer, shape_dict, scope) else: - raise Exception("Only PaddlePaddle's Program and TranslatedLayer are supported.") + raise Exception( + "Only PaddlePaddle's Program and TranslatedLayer are supported.") return mod, params From baf11fe3072e972727b603b51be158f3f344cdb6 Mon Sep 17 00:00:00 2001 From: jiangjiajun Date: Mon, 6 Sep 2021 07:18:25 +0000 Subject: [PATCH 051/127] add gather, gather_nd, assign_value --- python/tvm/relay/frontend/paddlepaddle.py | 236 ++++++++++-------- .../frontend/paddlepaddle/test_forward.py | 38 +++ 2 files changed, 168 insertions(+), 106 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index eac11738a7f9..3d3264b6c592 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -41,12 +41,6 @@ __all__ = ["from_paddle"] -def shape_of(x, dtype="int32"): - """Get shape of a tensor""" - - return _op.shape_of(x, dtype) - - def _get_pad_size(in_size, dilated_kernel_size, stride_size): """calculate the paddings size""" @@ -93,14 +87,14 @@ def convert_unary_op(g, op, block): def convert_addmm(g, op, block): """Operator converter for addmm.""" - input_x = g.get_node(op.input('Input')[0]) - x = g.get_node(op.input('X')[0]) - y = g.get_node(op.input('Y')[0]) + input_x = g.get_node(op.input("Input")[0]) + x = g.get_node(op.input("X")[0]) + y = g.get_node(op.input("Y")[0]) - alpha = op.attr('Alpha') - beta = op.attr('Beta') - dtype = block.var(op.output('Out')[0]).dtype - dtype = str(dtype).strip().split('.')[1] + alpha = op.attr("Alpha") + beta = op.attr("Beta") + dtype = block.var(op.output("Out")[0]).dtype + dtype = str(dtype).strip().split(".")[1] if not isinstance(alpha, _expr.Expr) and alpha != 1: alpha = _expr.const(alpha, dtype) @@ -113,7 +107,7 @@ def convert_addmm(g, op, block): transposed_y = _op.transpose(y, axes=[1, 0]) dense_out = _op.nn.dense(x, transposed_y) out = dense_out + input_x - g.add_node(op.output('Out')[0], out) + g.add_node(op.output("Out")[0], out) def convert_arg_max(g, op, block): @@ -155,6 +149,22 @@ def convert_assign(g, op, block): g.add_node(op.output("Out")[0], out) +def convert_assign_value(g, op, block): + """Operator converter for assign_value.""" + + keys = ["fp32_values", "int32_values", "int64_values"] + for key in keys: + value = np.array(op.attr(key)) + if value is not None and value.size >= 1: + break + shape = op.attr("shape") + dtype = block.var(op.output("Out")[0]).dtype + dtype = str(dtype).strip().split(".")[1] + value = value.reshape(shape) + out = _op.const(value) + g.add_node(op.output("Out")[0], out) + + def convert_batch_norm(g, op, block): """Operator converter for batch_norm.""" @@ -242,8 +252,7 @@ def get_interpolate_mode(op): in_h, in_w = input_shape[1], input_shape[2] if input_scale: scale_data = g.get_node(input_scale[0]) - scale_data = infer_value( - scale_data, g.get_params()).numpy().tolist() + scale_data = infer_value(scale_data, g.get_params()).numpy().tolist() if len(scale_data) > 1: out_h = int(scale_data[0] * in_h) out_w = int(scale_data[1] * in_w) @@ -259,8 +268,7 @@ def get_interpolate_mode(op): out_w = int(scale[1] * in_w) out_size = [out_h, out_w] - rounding_method, interp_method, coordinate_transformation_mode = get_interpolate_mode( - op) + rounding_method, interp_method, coordinate_transformation_mode = get_interpolate_mode(op) out = _op.image.resize2d( x, size=out_size, @@ -324,10 +332,8 @@ def convert_conv2d(g, op, block): pad_w = _get_pad_size(0, (k_w - 1) * dilations[1] + 1, strides[1]) else: in_h, in_w = infer_shape(input_x)[2:] - pad_h = _get_pad_size( - in_h, (k_h - 1) * dilations[0] + 1, strides[0]) - pad_w = _get_pad_size( - in_w, (k_w - 1) * dilations[1] + 1, strides[1]) + pad_h = _get_pad_size(in_h, (k_h - 1) * dilations[0] + 1, strides[0]) + pad_w = _get_pad_size(in_w, (k_w - 1) * dilations[1] + 1, strides[1]) paddings = [pad_h[0], pad_w[0], pad_h[1], pad_w[1]] elif padding_algorithm == "EXPLICIT": if len(paddings) == 2: @@ -359,8 +365,7 @@ def convert_conv2d_transpose(g, op, block): paddings = op.attr("paddings") padding_algorithm = op.attr("padding_algorithm") strides = op.attr("strides") - output_padding = op.attr("output_padding") if op.attr( - "output_padding") else [0, 0] + output_padding = op.attr("output_padding") if op.attr("output_padding") else [0, 0] kernel = g.get_node(op.input("Filter")[0]) input_x = g.get_node(op.input("Input")[0]) @@ -398,9 +403,9 @@ def convert_conv2d_transpose(g, op, block): def convert_crop(g, op, block): """Operator converter for crop.""" - x = g.get_node(op.input('X')[0]) - offsets = op.attr('offsets') - shape = op.attr('shape') + x = g.get_node(op.input("X")[0]) + offsets = op.attr("offsets") + shape = op.attr("shape") crop_len = len(shape) slice_start = [0] * crop_len @@ -409,7 +414,7 @@ def convert_crop(g, op, block): slice_start[i] += offsets[i] slice_end[i] += offsets[i] out = _op.strided_slice(x, slice_start, slice_end) - g.add_node(op.output('Out')[0], out) + g.add_node(op.output("Out")[0], out) def convert_cumsum(g, op, block): @@ -443,11 +448,11 @@ def convert_dropout(g, op, block): def convert_dot(g, op, block): """Operator converter for dot.""" - x = g.get_node(op.input('X')[0]) - y = g.get_node(op.input('Y')[0]) + x = g.get_node(op.input("X")[0]) + y = g.get_node(op.input("Y")[0]) out = _op.sum(_op.multiply(x, y), axis=[-1], keepdims=True) - g.add_node(op.output('Out')[0], out) + g.add_node(op.output("Out")[0], out) def convert_elementwise_op(g, op, block): @@ -470,8 +475,7 @@ def convert_elementwise_op(g, op, block): if axis < 0: axis = axis + len(ipt0_shape) if axis != len(ipt0_shape) - 1: - ipt1 = _op.expand_dims( - ipt1, axis=axis, num_newaxis=(len(ipt0_shape) - axis - 1)) + ipt1 = _op.expand_dims(ipt1, axis=axis, num_newaxis=(len(ipt0_shape) - axis - 1)) out = op_func(ipt0, ipt1) g.add_node(op.output("Out")[0], out) @@ -488,11 +492,11 @@ def convert_equal(g, op, block): def convert_expand(g, op, block): """Operator converter for expand.""" - x = g.get_node(op.input('X')[0]) + x = g.get_node(op.input("X")[0]) input_shape = list(infer_shape(x)) ndims = len(input_shape) - sizes = op.attr('shape') + sizes = op.attr("shape") out = x out_dims = len(sizes) @@ -507,7 +511,7 @@ def convert_expand(g, op, block): sizes[i] = int(infer_value(sizes[i], {}).numpy()) out = _op.repeat(out, sizes[i], axis=i) - g.add_node(op.output('Out')[0], out) + g.add_node(op.output("Out")[0], out) def convert_feed(g, op, block): @@ -562,28 +566,28 @@ def convert_fill_constant(g, op, block): def convert_fill_constant_batch_size_like(g, op, block): """Operator converter for fill_constant_batch_size_like.""" - x = g.get_node(op.input('Input')[0]) + x = g.get_node(op.input("Input")[0]) input_shape = infer_shape(x) - out_shape = op.attr('shape') - input_dim_idx = op.attr('input_dim_idx') - output_dim_idx = op.attr('output_dim_idx') - value = op.attr('value') - dtype = block.var(op.output('Out')[0]).dtype - dtype = str(dtype).strip().split('.')[1] + out_shape = op.attr("shape") + input_dim_idx = op.attr("input_dim_idx") + output_dim_idx = op.attr("output_dim_idx") + value = op.attr("value") + dtype = block.var(op.output("Out")[0]).dtype + dtype = str(dtype).strip().split(".")[1] out_shape[output_dim_idx] = input_shape[input_dim_idx] value = np.full(out_shape, value, dtype) out = _expr.const(value.astype(dtype)).astype(dtype) - g.add_node(op.output('Out')[0], out) + g.add_node(op.output("Out")[0], out) def convert_flatten(g, op, block): """Operator converter for flatten.""" - x = g.get_node(op.input('X')[0]) + x = g.get_node(op.input("X")[0]) input_shape = list(infer_shape(x)) - start = op.attr('start_axis') - end = op.attr('stop_axis') + start = op.attr("start_axis") + end = op.attr("stop_axis") ndim = len(input_shape) if end < 0: end += ndim @@ -600,7 +604,30 @@ def convert_flatten(g, op, block): if squeeze_axes: out = _op.squeeze(out, axis=squeeze_axes) - g.add_node(op.output('Out')[0], out) + g.add_node(op.output("Out")[0], out) + + +def convert_gather(g, op, block): + """Operator converter for gather.""" + + x = g.get_node(op.input("X")[0]) + index = g.get_node(op.input("Index")[0]) + axis = op.attr("axis") + out = _op.take(x, index, axis) + g.add_node(op.output("Out")[0], out) + + +def convert_gather_nd(g, op, block): + """Operator converter for gather_nd.""" + + x = g.get_node(op.input("X")[0]) + index = g.get_node(op.input("Index")[0]) + shape = infer_shape(index) + perm = list(range(0, len(shape) - 1)) + perm.insert(0, len(shape) - 1) + index = _op.transpose(index, axes=perm) + out = _op.gather_nd(x, index, 0, shape[-1]) + g.add_node(op.output("Out")[0], out) def convert_gelu(g, op, block): @@ -609,8 +636,7 @@ def convert_gelu(g, op, block): x = g.get_node(op.input("X")[0]) out = x * ( _expr.const(0.5, dtype="float32") - + _op.erf(x * _expr.const(0.5 ** 0.5, dtype="float32")) * - _expr.const(0.5, dtype="float32") + + _op.erf(x * _expr.const(0.5 ** 0.5, dtype="float32")) * _expr.const(0.5, dtype="float32") ) g.add_node(op.output("Out")[0], out) @@ -631,12 +657,9 @@ def convert_hard_swish(g, op, block): offset = op.attr("offset") scale = op.attr("scale") threshold = op.attr("threshold") - assert np.isclose( - offset, 3.0), "Only support offset==3.0 for PaddlePaddle's hard_swish" - assert np.isclose( - scale, 6.0), "Only support scale==6.0 for PaddlePaddle's hard_swish" - assert np.isclose( - threshold, 6.0), "Only support threshold==6.0 for PaddlePaddle's hard_swish" + assert np.isclose(offset, 3.0), "Only support offset==3.0 for PaddlePaddle's hard_swish" + assert np.isclose(scale, 6.0), "Only support scale==6.0 for PaddlePaddle's hard_swish" + assert np.isclose(threshold, 6.0), "Only support threshold==6.0 for PaddlePaddle's hard_swish" x = g.get_node(op.input("X")[0]) out = _op.clip(x, -1 * offset, offset) out = out / _expr.const(threshold) + _expr.const(0.5) @@ -734,9 +757,9 @@ def convert_matmul(g, op, block): # This implemention almost keeps same with ONNX # Need to check input shape as batch matmul must be supported. - a_shape = shape_of(inputs[0]) + a_shape = _op.shape_of(inputs[0]) a_rank = infer_shape(a_shape)[0] - b_shape = shape_of(inputs[1]) + b_shape = _op.shape_of(inputs[1]) b_rank = infer_shape(b_shape)[0] # When performing a batch matmul, we need to properly handle N-dim shapes. if a_rank > 2 or b_rank > 2: @@ -747,8 +770,7 @@ def flatten_to_nd(x, x_shape, nd=3): return x newshape = _op.concatenate( [ - _expr.const( - [-1], dtype=infer_type(x_shape).checked_type.dtype), + _expr.const([-1], dtype=infer_type(x_shape).checked_type.dtype), _op.strided_slice(x_shape, [ndims - nd + 1], [ndims]), ], 0, @@ -793,12 +815,10 @@ def flatten_to_nd(x, x_shape, nd=3): [ out_batch, _op.strided_slice( - a_shape, [infer_shape(a_shape)[0] - - 2], [infer_shape(a_shape)[0] - 1] + a_shape, [infer_shape(a_shape)[0] - 2], [infer_shape(a_shape)[0] - 1] ), _op.strided_slice( - b_shape, [infer_shape(b_shape)[0] - - 1], [infer_shape(b_shape)[0]] + b_shape, [infer_shape(b_shape)[0] - 1], [infer_shape(b_shape)[0]] ), ], 0, @@ -826,8 +846,8 @@ def convert_mul(g, op, block): y = g.get_node(op.input("Y")[0]) x_num_col_dims = op.attr("x_num_col_dims") y_num_col_dims = op.attr("y_num_col_dims") - x_shape = shape_of(x) - y_shape = shape_of(y) + x_shape = _op.shape_of(x) + y_shape = _op.shape_of(y) x_dim = infer_shape(x_shape)[0] y_dim = infer_shape(y_shape)[0] if x_num_col_dims < 0: @@ -837,8 +857,7 @@ def convert_mul(g, op, block): if x_num_col_dims == 1: x = _op.nn.batch_flatten(x) else: - pre_shape = _op.prod(_op.strided_slice( - x_shape, [0], [x_num_col_dims], [1]), keepdims=True) + pre_shape = _op.prod(_op.strided_slice(x_shape, [0], [x_num_col_dims], [1]), keepdims=True) post_shape = _op.prod( _op.strided_slice(x_shape, [x_num_col_dims], [x_dim], [1]), keepdims=True ) @@ -848,8 +867,7 @@ def convert_mul(g, op, block): if y_num_col_dims == 1: y = _op.nn.batch_flatten(y) else: - pre_shape = _op.prod(_op.strided_slice( - y_shape, [0], [y_num_col_dims], [1]), keepdims=True) + pre_shape = _op.prod(_op.strided_slice(y_shape, [0], [y_num_col_dims], [1]), keepdims=True) post_shape = _op.prod( _op.strided_slice(y_shape, [y_num_col_dims], [y_dim], [1]), keepdims=True ) @@ -915,8 +933,7 @@ def convert_pool2d(g, op, block): input_x, pool_size=ksize, strides=strides, padding=paddings, ceil_mode=ceil_mode ) else: - out = getattr(_op.nn, "adaptive_" + - op_map[pooling_type])(input_x, output_size=ksize) + out = getattr(_op.nn, "adaptive_" + op_map[pooling_type])(input_x, output_size=ksize) g.add_node(op.output("Out")[0], out) @@ -947,8 +964,7 @@ def convert_padding(g, op, block): new_paddings[index] = padding[i + 1] new_paddings[index - 1] = padding[i] - new_paddings = [new_paddings[i: i + 2] - for i in range(0, len(new_paddings), 2)] + new_paddings = [new_paddings[i : i + 2] for i in range(0, len(new_paddings), 2)] out = _op.nn.pad(input_x, new_paddings, pad_value=value, pad_mode=mode) g.add_node(op.output("Out")[0], out) @@ -988,8 +1004,7 @@ def generate_lstm(X_steps, H_t, C_t, W, R, WB, RB, f_act, g_act, h_act, backward h_list = [] seq_length = len(X_steps) for i in range(seq_length): - step = X_steps[i] if not backwards else X_steps[seq_length - - (i + 1)] + step = X_steps[i] if not backwards else X_steps[seq_length - (i + 1)] step = _op.squeeze(step, axis=[0]) gates = _op.nn.dense(step, W) + _op.nn.dense(H_t, R) if WB is not None: @@ -1024,40 +1039,46 @@ def generate_lstm(X_steps, H_t, C_t, W, R, WB, RB, f_act, g_act, h_act, backward return output, H_t, C_t def make_param_inputs(g, node, layer, hidden_size, num_layers): - bidirect_len = 4 if node.attr('is_bidirec') else 2 - all_layer_param_len = len(node.input('WeightList')) - weight_list = node.input('WeightList')[:all_layer_param_len // 2] - bias_list = node.input('WeightList')[all_layer_param_len // 2:] - - layer_weight_list = weight_list[layer * bidirect_len:layer * - bidirect_len + bidirect_len] - layer_bias_list = bias_list[layer * bidirect_len:layer * bidirect_len + - bidirect_len] + bidirect_len = 4 if node.attr("is_bidirec") else 2 + all_layer_param_len = len(node.input("WeightList")) + weight_list = node.input("WeightList")[: all_layer_param_len // 2] + bias_list = node.input("WeightList")[all_layer_param_len // 2 :] + + layer_weight_list = weight_list[layer * bidirect_len : layer * bidirect_len + bidirect_len] + layer_bias_list = bias_list[layer * bidirect_len : layer * bidirect_len + bidirect_len] param_list = layer_weight_list + layer_bias_list param_list_len = len(param_list) - input_weights = param_list[0:param_list_len // 2:2] - hidden_weights = param_list[1:param_list_len // 2:2] + input_weights = param_list[0 : param_list_len // 2 : 2] + hidden_weights = param_list[1 : param_list_len // 2 : 2] - input_bias = param_list[param_list_len // 2:param_list_len:2] - hidden_bias = param_list[param_list_len // 2 + 1:param_list_len:2] + input_bias = param_list[param_list_len // 2 : param_list_len : 2] + hidden_bias = param_list[param_list_len // 2 + 1 : param_list_len : 2] return input_weights, hidden_weights, input_bias, hidden_bias def make_init_param_inputs(g, node, layer): - all_init_h, all_init_c = node.input('PreState') - bidirect_len = 2 if node.attr('is_bidirec') else 1 - init_h = _op.strided_slice(g.get_node(all_init_h), [layer * bidirect_len], - [layer * bidirect_len + bidirect_len], axes=[0]) - init_c = _op.strided_slice(g.get_node(all_init_c), [layer * bidirect_len], - [layer * bidirect_len + bidirect_len], axes=[0]) + all_init_h, all_init_c = node.input("PreState") + bidirect_len = 2 if node.attr("is_bidirec") else 1 + init_h = _op.strided_slice( + g.get_node(all_init_h), + [layer * bidirect_len], + [layer * bidirect_len + bidirect_len], + axes=[0], + ) + init_c = _op.strided_slice( + g.get_node(all_init_c), + [layer * bidirect_len], + [layer * bidirect_len + bidirect_len], + axes=[0], + ) return init_h, init_c - hidden_size = op.attr('hidden_size') - num_layers = op.attr('num_layers') - is_bidirec = op.attr('is_bidirec') + hidden_size = op.attr("hidden_size") + num_layers = op.attr("num_layers") + is_bidirec = op.attr("is_bidirec") - input_x = g.get_node(op.input('Input')[0]) + input_x = g.get_node(op.input("Input")[0]) num_directions = 1 if is_bidirec: @@ -1068,7 +1089,8 @@ def make_init_param_inputs(g, node, layer): X_steps = _op.split(input_x, indices_or_sections=time_steps, axis=0) for layer in range(num_layers): input_weights, hidden_weights, input_bias, hidden_bias = make_param_inputs( - g, op, layer, hidden_size, num_layers) + g, op, layer, hidden_size, num_layers + ) init_h, init_c = make_init_param_inputs(g, op, layer) init_hs = _op.split(init_h, num_directions) @@ -1094,7 +1116,7 @@ def make_init_param_inputs(g, node, layer): f_act=_op.sigmoid, g_act=_op.tanh, h_act=_op.tanh, - backwards=i == 1 + backwards=i == 1, ) result_output.append(output) result_H.append(H) @@ -1108,7 +1130,7 @@ def make_init_param_inputs(g, node, layer): X_steps = output X_steps = _op.split(X_steps, indices_or_sections=time_steps, axis=0) - g.add_node(op.output('Out')[0], output) + g.add_node(op.output("Out")[0], output) def convert_scale(g, op, block): @@ -1141,7 +1163,7 @@ def convert_shape(g, op, block): """Operator converter for shape.""" x = g.get_node(op.input("Input")[0]) - out = shape_of(x) + out = _op.shape_of(x) g.add_node(op.output("Out")[0], out) @@ -1235,6 +1257,7 @@ def convert_unsqueeze(g, op, block): "arg_min": convert_arg_min, "asin": convert_unary_op, "assign": convert_assign, + "assign_value": convert_assign_value, "atan": convert_unary_op, "batch_norm": convert_batch_norm, "bicubic_interp_v2": convert_interpolate, @@ -1262,9 +1285,11 @@ def convert_unsqueeze(g, op, block): "feed": convert_feed, "fill_any_like": convert_fill_any_like, "fill_constant": convert_fill_constant, - 'fill_constant_batch_size_like': convert_fill_constant_batch_size_like, + "fill_constant_batch_size_like": convert_fill_constant_batch_size_like, "flatten_contiguous_range": convert_flatten, "floor": convert_unary_op, + "gather": convert_gather, + "gather_nd": convert_gather_nd, "gelu": convert_gelu, "hard_sigmoid": convert_hard_sigmoid, "hard_swish": convert_hard_swish, @@ -1455,6 +1480,5 @@ def from_paddle(program_or_layer, shape_dict=None, scope=None): # model is loaded by `paddle.static.load_inference_model` mod, params = g.from_program(program_or_layer, shape_dict, scope) else: - raise Exception( - "Only PaddlePaddle's Program and TranslatedLayer are supported.") + raise Exception("Only PaddlePaddle's Program and TranslatedLayer are supported.") return mod, params diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index 88c279974d58..6ba0e10ff3bd 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -603,6 +603,42 @@ def ones_like2(inputs): verify_model(ones_like2, input_data=input_data) +@tvm.testing.uses_gpu +def test_forward_gather_assign_value(): + @paddle.jit.to_static + def gather1(x): + index = paddle.to_tensor(np.array([1, 3, 5, 7, 9]).astype("int64")) + return paddle.gather(x, index, axis=None) + + @paddle.jit.to_static + def gather2(x): + index = paddle.to_tensor(np.array([1, 3, 5, 7, 9]).astype("int64")) + return paddle.gather(x, index, axis=1) + + x_shape = [30, 40] + x_data = paddle.rand(x_shape, dtype="float32") + verify_model(gather1, input_data=[x_data]) + verify_model(gather2, input_data=[x_data]) + + +@tvm.testing.uses_gpu +def test_forward_gather_nd(): + @paddle.jit.to_static + def gather_nd1(x): + index = paddle.to_tensor(np.array([[0, 1]]).astype("int64")) + return paddle.gather_nd(x, index) + + @paddle.jit.to_static + def gather_nd2(x): + index = paddle.to_tensor(np.array([[0, 1], [1, 2]]).astype("int32")) + return paddle.gather_nd(x, index) + + x_shape = [30, 40, 20] + x_data = paddle.rand(x_shape, dtype="float32") + verify_model(gather_nd1, input_data=[x_data]) + verify_model(gather_nd2, input_data=[x_data]) + + @tvm.testing.uses_gpu def test_forward_gelu(): @paddle.jit.to_static @@ -998,6 +1034,8 @@ def squeeze3(inputs): test_forward_flatten() test_forward_shape_full() test_forward_ones_like() + test_forward_gather_assign_value() + test_forward_gather_nd() test_forward_gelu() test_forward_hard_sigmoid() test_forward_hard_swish() From 035eb4e8aa38b38bdbbbff79ce1ebfcdd4741e72 Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Mon, 6 Sep 2021 18:46:34 +0800 Subject: [PATCH 052/127] add reduce op --- python/tvm/relay/frontend/paddlepaddle.py | 18 +++++++++++ .../frontend/paddlepaddle/test_forward.py | 30 +++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 968059e1a4d8..24ddde0f8fe6 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -799,6 +799,23 @@ def convert_padding(g, op, block): g.add_node(op.output("Out")[0], out) +def convert_reduce(op_name): + """Operator converter for reduce.""" + + def _impl(g, op, block): + input_x = g.get_node(op.input("X")[0]) + axis = op.attr("dim") + if op.attr("reduce_all"): + axis = None + keepdims = op.attr("keep_dim") + out = get_relay_op(op_name)(input_x, axis=axis, keepdims=keepdims) + if not axis and not keepdims: + out = _op.expand_dims(out, axis=0) + g.add_node(op.output("Out")[0], out) + + return _impl + + def convert_reshape(g, op, block): """Operator converter for reshape.""" @@ -987,6 +1004,7 @@ def convert_unsqueeze(g, op, block): "pad1d": convert_padding, "pad2d": convert_padding, "pad3d": convert_padding, + "reduce_all": convert_reduce("all"), "relu": convert_unary_op, "reshape2": convert_reshape, "scale": convert_scale, diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index cb5c17f758f8..c9f7b018f106 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -733,6 +733,35 @@ def pad4(inputs): verify_model(pad4, input_data=input_data) +@tvm.testing.uses_gpu +def test_forward_reduce(): + @paddle.jit.to_static + def reduce_all(inputs): + inputs = paddle.assign(inputs) + inputs = paddle.cast(inputs, "bool") + inputs = paddle.all(inputs) + return paddle.cast(inputs, "int32") + + @paddle.jit.to_static + def reduce_all2(inputs): + inputs = paddle.assign(inputs) + inputs = paddle.cast(inputs, "bool") + inputs = paddle.all(inputs, axis=0) + return paddle.cast(inputs, "int32") + + @paddle.jit.to_static + def reduce_all3(inputs): + inputs = paddle.assign(inputs) + inputs = paddle.cast(inputs, "bool") + inputs = paddle.all(inputs, axis=[0, 1, -1], keepdim=True) + return paddle.cast(inputs, "int32") + + input_data = paddle.randn([1, 2, 3]) + verify_model(reduce_all, input_data=input_data) + verify_model(reduce_all2, input_data=input_data) + verify_model(reduce_all3, input_data=input_data) + + @tvm.testing.uses_gpu def test_forward_reshape(): @paddle.jit.to_static @@ -863,6 +892,7 @@ def squeeze3(inputs): test_forward_matmul() test_forward_pool2d() test_forward_pad() + test_forward_reduce() test_forward_reshape() test_forward_scale() test_forward_slice() From 9d2beccb6fffa69fa0d5acc42d1c6578db7f6acb Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Mon, 6 Sep 2021 19:49:20 +0800 Subject: [PATCH 053/127] _impl to op_map --- python/tvm/relay/frontend/paddlepaddle.py | 28 ++++++++++++----------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index b27029c183c7..051f653fe3a7 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -970,21 +970,23 @@ def convert_padding(g, op, block): g.add_node(op.output("Out")[0], out) -def convert_reduce(op_name): +def convert_reduce(g, op, block): """Operator converter for reduce.""" - def _impl(g, op, block): - input_x = g.get_node(op.input("X")[0]) - axis = op.attr("dim") - if op.attr("reduce_all"): - axis = None - keepdims = op.attr("keep_dim") - out = get_relay_op(op_name)(input_x, axis=axis, keepdims=keepdims) - if not axis and not keepdims: - out = _op.expand_dims(out, axis=0) - g.add_node(op.output("Out")[0], out) - - return _impl + op_map = { + "reduce_all" : "all", + } + op_name = op_map[op.type] + input_x = g.get_node(op.input("X")[0]) + axis = op.attr("dim") + if op.attr("reduce_all"): + axis = None + keepdims = op.attr("keep_dim") + out = get_relay_op(op_name)(input_x, axis=axis, keepdims=keepdims) + if not axis and not keepdims: + out = _op.expand_dims(out, axis=0) + g.add_node(op.output("Out")[0], out) + def convert_reshape(g, op, block): From 7ff02a07b00751b6caaec747e68c43b5b3753eb9 Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Mon, 6 Sep 2021 19:52:43 +0800 Subject: [PATCH 054/127] reduce all --- python/tvm/relay/frontend/paddlepaddle.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 051f653fe3a7..91e3b9cbf12e 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -974,7 +974,7 @@ def convert_reduce(g, op, block): """Operator converter for reduce.""" op_map = { - "reduce_all" : "all", + "reduce_all": "all", } op_name = op_map[op.type] input_x = g.get_node(op.input("X")[0]) @@ -988,7 +988,6 @@ def convert_reduce(g, op, block): g.add_node(op.output("Out")[0], out) - def convert_reshape(g, op, block): """Operator converter for reshape.""" @@ -1329,7 +1328,7 @@ def convert_unsqueeze(g, op, block): "pad1d": convert_padding, "pad2d": convert_padding, "pad3d": convert_padding, - "reduce_all": convert_reduce("all"), + "reduce_all": convert_reduce, "relu": convert_unary_op, "reshape2": convert_reshape, "rnn": convert_rnn, From 6352ad48d8ddd9d590671078413ae51cfc9ce986 Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Mon, 6 Sep 2021 22:59:32 +0800 Subject: [PATCH 055/127] add arange op --- python/tvm/relay/frontend/paddlepaddle.py | 22 +++++++++++++++++++ .../frontend/paddlepaddle/test_forward.py | 18 +++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 91e3b9cbf12e..98b780fceb2a 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -970,6 +970,27 @@ def convert_padding(g, op, block): g.add_node(op.output("Out")[0], out) +def convert_range(g, op, block): + """Operator converter for range.""" + + start = g.get_node(op.input("Start")[0]) + stop = g.get_node(op.input("End")[0]) + step = g.get_node(op.input("Step")[0]) + dtype = infer_type(start).checked_type.dtype + + attr_list = [] + for attr in (start, stop, step): + attr = _infer_value(attr, g.get_params()) + if isinstance(attr, _expr.Expr): + attr = _op.squeeze(attr) + else: + attr = _op.const(attr[0], dtype=dtype) + attr_list.append(attr) + + out = _op.transform.arange(attr_list[0], attr_list[1], attr_list[2], dtype=dtype) + g.add_node(op.output("Out")[0], out) + + def convert_reduce(g, op, block): """Operator converter for reduce.""" @@ -1328,6 +1349,7 @@ def convert_unsqueeze(g, op, block): "pad1d": convert_padding, "pad2d": convert_padding, "pad3d": convert_padding, + "range": convert_range, "reduce_all": convert_reduce, "relu": convert_unary_op, "reshape2": convert_reshape, diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index 395dde0d5dae..f5f0fba92810 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -23,6 +23,7 @@ import paddle.nn as nn import tvm +from tvm.contrib.sparse import array import tvm.testing import tvm.topi.testing from tvm import relay @@ -207,6 +208,22 @@ def addmm(input, x, y, alpha=1, beta=1): verify_model(addmm, input_data=[input_data, x_data, y_data]) +@tvm.testing.uses_gpu +def test_forward_arange(): + @paddle.jit.to_static + def arange(inputs): + return paddle.arange(paddle.shape(inputs)[0], 9, 2.0) + + @paddle.jit.to_static + def arange2(inputs): + return paddle.arange(0, 10.0, paddle.shape(inputs)[1], dtype="float32") + + input_shape = [2, 2] + input_data = paddle.rand(input_shape, dtype="float32") + verify_model(arange, input_data) + verify_model(arange2, input_data=input_data) + + @tvm.testing.uses_gpu def test_forward_argmax(): input_shape = [1, 3, 10, 10] @@ -1048,6 +1065,7 @@ def squeeze3(inputs): if __name__ == "__main__": test_forward_add_subtract() test_forward_addmm() + test_forward_arange() test_forward_argmax() test_forward_argmin() test_forward_assign() From 38d0caed4e0b30c398870e31a53b66ed84b2903c Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Tue, 7 Sep 2021 10:53:11 +0800 Subject: [PATCH 056/127] add tile op --- python/tvm/relay/frontend/paddlepaddle.py | 29 +++++++++++++++++ .../frontend/paddlepaddle/test_forward.py | 32 +++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 98b780fceb2a..f5dc764db76d 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -1270,6 +1270,34 @@ def convert_squeeze(g, op, block): g.add_node(op.output("Out")[0], x) +def convert_tile(g, op, block): + """Operator converter for tile.""" + + print("op:", op) + input_x = g.get_node(op.input("X")[0]) + repeat_times = op.input("RepeatTimes") + repeat_times_tensor = op.input("repeat_times_tensor") + if repeat_times: + repeat_times = g.get_node(repeat_times[0]) + elif repeat_times_tensor: + tmp_shape = [] + for shape_name in repeat_times_tensor: + shape = g.get_node(shape_name) + if len(infer_shape(shape)) == 0: + shape = _op.reshape(shape, [-1]) + if isinstance(shape, _expr.Constant): + tmp_shape.append(shape) + elif isinstance(shape, _expr.Expr): + tmp_shape.append(shape) + else: + tmp_shape.append(_expr.const(np.array(shape).astype("int32"))) + repeat_times = _op.concatenate(tmp_shape, axis=0) + else: + repeat_times = op.attr("repeat_times") + out = _op.tile(input_x, repeat_times) + g.add_node(op.output("Out")[0], out) + + def convert_transpose(g, op, block): """Operator converter for transpose.""" @@ -1363,6 +1391,7 @@ def convert_unsqueeze(g, op, block): "squeeze2": convert_squeeze, "tan": convert_unary_op, "tanh": convert_unary_op, + "tile": convert_tile, "transpose2": convert_transpose, "unsqueeze2": convert_unsqueeze, } diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index f5f0fba92810..58d7a322007f 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -1062,6 +1062,37 @@ def squeeze3(inputs): verify_model(squeeze3, input_data=input_data) +@tvm.testing.uses_gpu +def test_forward_tile(): + @paddle.jit.to_static + def tile(inputs): + return paddle.tile(inputs, [3, 2]) + + @paddle.jit.to_static + def tile2(inputs, inputs2): + inputs2 = paddle.shape(inputs2) + inputs2 = paddle.cast(inputs2, "int32") + return paddle.tile(inputs, inputs2) + + @paddle.jit.to_static + def tile3(inputs, inputs2): + inputs2 = paddle.shape(inputs2)[0] + inputs2 = paddle.cast(inputs2, "int32") + return paddle.tile(inputs, [inputs2, 3]) + + input_shape = [2, 2] + input_data = paddle.rand(input_shape, dtype="float32") + verify_model( + tile, + input_data=[ + input_data, + ], + ) + input_data2 = paddle.rand([1, 2], dtype="float32") + verify_model(tile2, input_data=[input_data, input_data2]) + verify_model(tile3, input_data=[input_data, input_data2]) + + if __name__ == "__main__": test_forward_add_subtract() test_forward_addmm() @@ -1101,5 +1132,6 @@ def squeeze3(inputs): test_forward_scale() test_forward_slice() test_forward_squeeze2() + test_forward_tile() test_forward_conv_transpose() test_forward_unary_op() From 13093d3e9451daeb82d472368ad04f25ca371c5e Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Tue, 7 Sep 2021 11:16:04 +0800 Subject: [PATCH 057/127] add stack op --- python/tvm/relay/frontend/paddlepaddle.py | 12 +++++++++++- .../frontend/paddlepaddle/test_forward.py | 18 ++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index f5dc764db76d..54f065597764 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -1270,10 +1270,19 @@ def convert_squeeze(g, op, block): g.add_node(op.output("Out")[0], x) +def convert_stack(g, op, block): + """Operator converter for stack.""" + + x = op.input("X") + x = [g.get_node(i) for i in x] + axis = op.attr("axis") + out = _op.stack(x, axis) + g.add_node(op.output("Y")[0], out) + + def convert_tile(g, op, block): """Operator converter for tile.""" - print("op:", op) input_x = g.get_node(op.input("X")[0]) repeat_times = op.input("RepeatTimes") repeat_times_tensor = op.input("repeat_times_tensor") @@ -1389,6 +1398,7 @@ def convert_unsqueeze(g, op, block): "slice": convert_slice, "softmax": convert_softmax, "squeeze2": convert_squeeze, + "stack": convert_stack, "tan": convert_unary_op, "tanh": convert_unary_op, "tile": convert_tile, diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index 58d7a322007f..5e63b96cb576 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -1062,6 +1062,24 @@ def squeeze3(inputs): verify_model(squeeze3, input_data=input_data) +@tvm.testing.uses_gpu +def test_forward_stack(): + @paddle.jit.to_static + def stack(input1, input2, input3): + return paddle.stack([input1, input2, input3]) + + @paddle.jit.to_static + def stack2(input1, input2, input3): + return paddle.stack([input1, input2, input3], axis=-1) + + input_shape = [2, 3] + input_data = paddle.rand(input_shape, dtype="float32") + input_data2 = paddle.rand(input_shape, dtype="float32") + input_data3 = paddle.rand(input_shape, dtype="float32") + verify_model(stack, input_data=[input_data, input_data2, input_data3]) + verify_model(stack2, input_data=[input_data, input_data2, input_data3]) + + @tvm.testing.uses_gpu def test_forward_tile(): @paddle.jit.to_static From dad1d75477f404c3ff4852e49257cc1f43725a03 Mon Sep 17 00:00:00 2001 From: wjj19950828 Date: Tue, 7 Sep 2021 14:40:25 +0800 Subject: [PATCH 058/127] Fixed Tensor and Dynamic input --- python/tvm/relay/frontend/paddlepaddle.py | 67 +++++++++++++++---- .../frontend/paddlepaddle/test_forward.py | 57 +++++++++------- 2 files changed, 84 insertions(+), 40 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 3d3264b6c592..1f10785944e4 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -55,6 +55,16 @@ def _get_pad_size(in_size, dilated_kernel_size, stride_size): return [pad_before, pad_after] +def shape_of(x, dtype="int32"): + """Get shape of a tensor""" + + ttype = infer_type(x).checked_type + if not _ty.is_dynamic(ttype): + shape = list(ttype.shape) + return _expr.const(shape, dtype) + return _op.shape_of(x, dtype) + + def _infer_value(x, params): """Try running infer_value, and if successful, return the inferred value. Otherwise, return input""" @@ -404,8 +414,19 @@ def convert_crop(g, op, block): """Operator converter for crop.""" x = g.get_node(op.input("X")[0]) - offsets = op.attr("offsets") - shape = op.attr("shape") + input_shape = op.input("Shape") + input_offsets = op.input("Offsets") + if input_shape: + shape = g.get_node(input_shape[0]) + shape = infer_value(shape, g.get_params()).numpy().tolist() + else: + shape = op.attr("shape") + + if input_offsets: + offsets = g.get_node(input_offsets[0]) + offsets = infer_value(offsets, g.get_params()).numpy().tolist() + else: + offsets = op.attr("offsets") crop_len = len(shape) slice_start = [0] * crop_len @@ -496,9 +517,13 @@ def convert_expand(g, op, block): input_shape = list(infer_shape(x)) ndims = len(input_shape) - sizes = op.attr("shape") - out = x + if op.input("Shape"): + sizes = g.get_node(op.input("Shape")[0]) + sizes = infer_value(sizes, g.get_params()).numpy().tolist() + else: + sizes = op.attr("shape") + out = x out_dims = len(sizes) if ndims < out_dims: num_newaxis = out_dims - ndims @@ -567,16 +592,28 @@ def convert_fill_constant_batch_size_like(g, op, block): """Operator converter for fill_constant_batch_size_like.""" x = g.get_node(op.input("Input")[0]) - input_shape = infer_shape(x) - out_shape = op.attr("shape") + value = op.attr("value") + shape = op.attr("shape") input_dim_idx = op.attr("input_dim_idx") output_dim_idx = op.attr("output_dim_idx") - value = op.attr("value") + dtype = block.var(op.output("Out")[0]).dtype dtype = str(dtype).strip().split(".")[1] - out_shape[output_dim_idx] = input_shape[input_dim_idx] - value = np.full(out_shape, value, dtype) - out = _expr.const(value.astype(dtype)).astype(dtype) + input_shape = shape_of(x) + batch = _op.strided_slice(input_shape, begin=[input_dim_idx], end=[input_dim_idx+1]).astype("int32") + shape_before = shape[:output_dim_idx] + shape_before = _expr.const(shape_before, dtype="int32") + shape_after = shape[output_dim_idx+1:] + shape_after = _expr.const(shape_after, dtype="int32") + + out_shape = _op.concatenate([shape_before, batch, shape_after], axis=0) + constant = _expr.const(value, dtype=dtype).astype(dtype) + out = _op.full(constant, out_shape, dtype=dtype) + + # reshape for dynamic + shape[output_dim_idx] = -1 + out = _op.reshape(out, shape) + g.add_node(op.output("Out")[0], out) @@ -757,9 +794,9 @@ def convert_matmul(g, op, block): # This implemention almost keeps same with ONNX # Need to check input shape as batch matmul must be supported. - a_shape = _op.shape_of(inputs[0]) + a_shape = shape_of(inputs[0]) a_rank = infer_shape(a_shape)[0] - b_shape = _op.shape_of(inputs[1]) + b_shape = shape_of(inputs[1]) b_rank = infer_shape(b_shape)[0] # When performing a batch matmul, we need to properly handle N-dim shapes. if a_rank > 2 or b_rank > 2: @@ -1343,8 +1380,10 @@ def get_node(self, name): def add_node(self, name, node): """add a node to graph""" - - self.nodes[name] = fold_constant(node) + if self.shape_dict: + self.nodes[name] = fold_constant(node) + else: + self.nodes[name] = node def get_params(self, name=None): """get params from graph""" diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index 6ba0e10ff3bd..a9567827e6ba 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -376,33 +376,32 @@ def concat_unsqueeze2(inputs): @tvm.testing.uses_gpu def test_forward_crop(): - input_shape = [10, 10] - - class Crop(nn.Layer): - @paddle.jit.to_static - def forward(self, inputs): - return paddle.crop(inputs, shape=[2, 2]) + @paddle.jit.to_static + def crop1(inputs): + return paddle.crop(inputs, shape=[2, 2]) - class Crop1(nn.Layer): - @paddle.jit.to_static - def forward(self, inputs): - return paddle.crop(inputs, shape=[3, 3], offsets=[0, 1]) + @paddle.jit.to_static + def crop2(inputs): + shape = paddle.to_tensor(np.array([3, 3]).astype("int32")) + return paddle.crop(inputs, shape=shape, offsets=[0, 1]) - class Crop2(nn.Layer): - @paddle.jit.to_static - def forward(self, inputs): - return paddle.crop(inputs, shape=[3, 3], offsets=[1, 0]) + @paddle.jit.to_static + def crop3(inputs): + offsets = paddle.to_tensor(np.array([1, 0]).astype("int32")) + return paddle.crop(inputs, shape=[3, 3], offsets=offsets) - class Crop3(nn.Layer): - @paddle.jit.to_static - def forward(self, inputs): - return paddle.crop(inputs, shape=[3, 3], offsets=[1, 1]) + @paddle.jit.to_static + def crop4(inputs): + shape = paddle.to_tensor(np.array([3, 3]).astype("int32")) + offsets = paddle.to_tensor(np.array([1, 1]).astype("int32")) + return paddle.crop(inputs, shape=shape, offsets=offsets) + input_shape = [10, 10] input_data = paddle.rand(input_shape, dtype="float32") - verify_model(Crop(), input_data=input_data) - verify_model(Crop1(), input_data=input_data) - verify_model(Crop2(), input_data=input_data) - verify_model(Crop3(), input_data=input_data) + verify_model(crop1, input_data=[input_data]) + verify_model(crop2, input_data=[input_data]) + verify_model(crop3, input_data=[input_data]) + verify_model(crop4, input_data=[input_data]) @tvm.testing.uses_gpu @@ -543,12 +542,18 @@ def dropout(inputs): @tvm.testing.uses_gpu def test_forward_expand(): @paddle.jit.to_static - def expand(inputs): + def expand1(inputs): return paddle.expand(inputs, shape=[2, 3]) + @paddle.jit.to_static + def expand2(inputs): + shape = paddle.to_tensor(np.array([2, 3]).astype("int32")) + return paddle.expand(inputs, shape=shape) + x_shape = [3] x_data = paddle.rand(x_shape, dtype="float32") - verify_model(expand, input_data=[x_data]) + verify_model(expand1, input_data=[x_data]) + verify_model(expand2, input_data=[x_data]) @tvm.testing.uses_gpu @@ -583,7 +588,7 @@ def shape1(inputs): input_shape = [1, 3, 10, 10] input_data = paddle.rand(input_shape, dtype="float32") verify_model(shape1, input_data=[input_data]) - # verify_model(full1, input_data=[input_data]) + verify_model(full1, input_data=[input_data]) verify_model(full2, input_data=[input_data]) @@ -869,7 +874,7 @@ def pool2d3(inputs): input_data = paddle.uniform(shape=[1, 2, 32, 32], dtype="float32", min=-1, max=1) verify_model(pool2d1, input_data=input_data) verify_model(pool2d2, input_data=input_data) - # verify_model(pool2d3, input_data=input_data) + verify_model(pool2d3, input_data=input_data) @tvm.testing.uses_gpu From aec532fdafec72e65bfd1e06a368ad1ebaf8d233 Mon Sep 17 00:00:00 2001 From: wjj19950828 Date: Tue, 7 Sep 2021 15:36:35 +0800 Subject: [PATCH 059/127] deal with comments --- python/tvm/relay/frontend/paddlepaddle.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 1f10785944e4..4a8b27da1254 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -418,13 +418,13 @@ def convert_crop(g, op, block): input_offsets = op.input("Offsets") if input_shape: shape = g.get_node(input_shape[0]) - shape = infer_value(shape, g.get_params()).numpy().tolist() + shape = _infer_value(shape, g.get_params()) else: shape = op.attr("shape") if input_offsets: offsets = g.get_node(input_offsets[0]) - offsets = infer_value(offsets, g.get_params()).numpy().tolist() + offsets = _infer_value(offsets, g.get_params()) else: offsets = op.attr("offsets") @@ -519,7 +519,7 @@ def convert_expand(g, op, block): ndims = len(input_shape) if op.input("Shape"): sizes = g.get_node(op.input("Shape")[0]) - sizes = infer_value(sizes, g.get_params()).numpy().tolist() + sizes = _infer_value(sizes, g.get_params()) else: sizes = op.attr("shape") From 8022bb8e3538d9dd4b157e4a0f39ad30ba8d63df Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Wed, 8 Sep 2021 16:49:35 +0800 Subject: [PATCH 060/127] attr to param --- python/tvm/relay/frontend/paddlepaddle.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 54f065597764..e3d4ec4af536 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -978,16 +978,16 @@ def convert_range(g, op, block): step = g.get_node(op.input("Step")[0]) dtype = infer_type(start).checked_type.dtype - attr_list = [] - for attr in (start, stop, step): - attr = _infer_value(attr, g.get_params()) - if isinstance(attr, _expr.Expr): - attr = _op.squeeze(attr) + params = [] + for param in (start, stop, step): + param = _infer_value(param, g.get_params()) + if isinstance(param, _expr.Expr): + param = _op.squeeze(param) else: - attr = _op.const(attr[0], dtype=dtype) - attr_list.append(attr) + param = _op.const(param[0], dtype=dtype) + params.append(param) - out = _op.transform.arange(attr_list[0], attr_list[1], attr_list[2], dtype=dtype) + out = _op.transform.arange(params[0], params[1], params[2], dtype=dtype) g.add_node(op.output("Out")[0], out) From 5d5211252f9743408b160f5dc0a3887d49913a45 Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Wed, 8 Sep 2021 17:48:49 +0800 Subject: [PATCH 061/127] add greather_than op --- python/tvm/relay/frontend/paddlepaddle.py | 3 +++ tests/python/frontend/paddlepaddle/test_forward.py | 13 +++++++++++++ 2 files changed, 16 insertions(+) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index e3d4ec4af536..98cafd4257f0 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -464,6 +464,7 @@ def convert_elementwise_op(g, op, block): "elementwise_mul": lambda x, y: x * y, "elementwise_sub": lambda x, y: x - y, "elementwise_mod": lambda x, y: x % y, + "greater_than": "greater", } op_func = op_map[op.type] ipt0 = g.get_node(op.input("X")[0]) @@ -476,6 +477,8 @@ def convert_elementwise_op(g, op, block): axis = axis + len(ipt0_shape) if axis != len(ipt0_shape) - 1: ipt1 = _op.expand_dims(ipt1, axis=axis, num_newaxis=(len(ipt0_shape) - axis - 1)) + if isinstance(op_func, str): + op_func = get_relay_op(op_func) out = op_func(ipt0, ipt1) g.add_node(op.output("Out")[0], out) diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index 5e63b96cb576..a400b672f598 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -620,6 +620,18 @@ def ones_like2(inputs): verify_model(ones_like2, input_data=input_data) +@tvm.testing.uses_gpu +def test_forward_greater_than(): + @paddle.jit.to_static + def greater_than(input, input2): + paddle.greater_than(input, input2) + + input_shape = [1, 3, 10, 10] + input_data = paddle.rand(input_shape, dtype="float32") + input_data2 = paddle.rand(input_shape, dtype="float32") + verify_model(greater_than, input_data=[input_data, input_data2]) + + @tvm.testing.uses_gpu def test_forward_gather_assign_value(): @paddle.jit.to_static @@ -1130,6 +1142,7 @@ def tile3(inputs, inputs2): test_forward_flatten() test_forward_shape_full() test_forward_ones_like() + test_forward_greater_than() test_forward_gather_assign_value() test_forward_gather_nd() test_forward_gelu() From 2fbbad212cb60de463b5cdc238f6e6cf9f5e54ad Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Wed, 8 Sep 2021 18:00:54 +0800 Subject: [PATCH 062/127] add greather_than op --- python/tvm/relay/frontend/paddlepaddle.py | 1 + tests/python/frontend/paddlepaddle/test_forward.py | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 98cafd4257f0..867ffd34f9dd 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -1370,6 +1370,7 @@ def convert_unsqueeze(g, op, block): "gather": convert_gather, "gather_nd": convert_gather_nd, "gelu": convert_gelu, + "greater_than": convert_elementwise_op, "hard_sigmoid": convert_hard_sigmoid, "hard_swish": convert_hard_swish, "isinf": convert_unary_op, diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index a400b672f598..1507cdfa4130 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -623,8 +623,9 @@ def ones_like2(inputs): @tvm.testing.uses_gpu def test_forward_greater_than(): @paddle.jit.to_static - def greater_than(input, input2): - paddle.greater_than(input, input2) + def greater_than(input1, input2): + y = paddle.greater_than(input1, input2) + return paddle.cast(y, "int32") input_shape = [1, 3, 10, 10] input_data = paddle.rand(input_shape, dtype="float32") @@ -1142,10 +1143,10 @@ def tile3(inputs, inputs2): test_forward_flatten() test_forward_shape_full() test_forward_ones_like() - test_forward_greater_than() test_forward_gather_assign_value() test_forward_gather_nd() test_forward_gelu() + test_forward_greater_than() test_forward_hard_sigmoid() test_forward_hard_swish() test_forward_interpolate() From 5992e076102f4b587995bdd488c69312e47ab95b Mon Sep 17 00:00:00 2001 From: wjj19950828 Date: Wed, 8 Sep 2021 21:03:04 +0800 Subject: [PATCH 063/127] Add ops for kunlun --- python/tvm/relay/frontend/paddlepaddle.py | 86 +++++- .../frontend/paddlepaddle/test_forward.py | 245 ++++++++++++++++-- 2 files changed, 305 insertions(+), 26 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 95d83e6ad67c..bf445e3d7725 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -484,7 +484,9 @@ def convert_elementwise_op(g, op, block): "elementwise_add": lambda x, y: x + y, "elementwise_mul": lambda x, y: x * y, "elementwise_sub": lambda x, y: x - y, - "elementwise_mod": lambda x, y: x % y, + "elementwise_mod": _op.mod, + "elementwise_pow": _op.power, + "elementwise_floordiv": _op.floor_divide } op_func = op_map[op.type] ipt0 = g.get_node(op.input("X")[0]) @@ -744,6 +746,15 @@ def convert_leaky_relu(g, op, block): g.add_node(op.output("Out")[0], out) +def convert_less_than(g, op, block): + """Operator converter for less_than.""" + + x = g.get_node(op.input("X")[0]) + y = g.get_node(op.input("Y")[0]) + out = _op.less(x, y) + g.add_node(op.output("Out")[0], out) + + def convert_lookup_table(g, op, block): """Operator converter for lookup_table_v2.""" @@ -767,6 +778,20 @@ def convert_log1p(g, op, block): g.add_node(op.output("Out")[0], out) +def convert_logsumexp(g, op, block): + """Operator converter for logsumexp.""" + + input_x = g.get_node(op.input("X")[0]) + axis = op.attr("axis") + if op.attr("reduce_all"): + axis = None + keepdims = op.attr("keepdim") + out = get_relay_op("logsumexp")(input_x, axis=axis, keepdims=keepdims) + if not axis and not keepdims: + out = _op.expand_dims(out, axis=0) + g.add_node(op.output("Out")[0], out) + + def convert_matmul(g, op, block): """Operator converter for matmul.""" @@ -921,6 +946,15 @@ def convert_mul(g, op, block): g.add_node(op.output("Out")[0], out) +def convert_not_equal(g, op, block): + """Operator converter for not_equal.""" + + x = g.get_node(op.input("X")[0]) + y = g.get_node(op.input("Y")[0]) + out = _op.not_equal(x, y) + g.add_node(op.output("Out")[0], out) + + def convert_pool2d(g, op, block): """Operator converter for pool2d.""" @@ -1007,11 +1041,28 @@ def convert_padding(g, op, block): g.add_node(op.output("Out")[0], out) +def convert_pow(g, op, block): + """Operator converter for pow.""" + + x = g.get_node(op.input("X")[0]) + factor = op.attr("factor") + factor = _expr.const(factor, dtype="float32").astype("float32") + + out = _op.power(x, factor) + g.add_node(op.output("Out")[0], out) + + def convert_reduce(g, op, block): """Operator converter for reduce.""" op_map = { "reduce_all": "all", + "reduce_any": "any", + "reduce_max": "max", + "reduce_min": "min", + "reduce_prod": "prod", + "reduce_sum": "sum", + "reduce_mean": "mean", } op_name = op_map[op.type] input_x = g.get_node(op.input("X")[0]) @@ -1286,6 +1337,25 @@ def convert_squeeze(g, op, block): g.add_node(op.output("Out")[0], x) +def convert_topk(g, op, block): + """Operator converter for topk.""" + + x = g.get_node(op.input("X")[0]) + axis = op.attr("axis") + largest = op.attr("largest") + is_ascend = not bool(largest) + k_node = op.input("K") + if k_node: + k_node = g.get_node(k_node[0]) + k = _infer_value(k_node, g.get_params()) + else: + k = op.attr("k") + outs = _op.topk(x, k=k, axis=axis, is_ascend=is_ascend, ret_type="both", dtype="int32") + + g.add_node(op.output("Out")[0], outs[0]) + g.add_node(op.output("Indices")[0], outs[1]) + + def convert_transpose(g, op, block): """Operator converter for transpose.""" @@ -1334,6 +1404,9 @@ def convert_unsqueeze(g, op, block): "elementwise_div": convert_elementwise_op, "elementwise_mul": convert_elementwise_op, "elementwise_sub": convert_elementwise_op, + "elementwise_mod": convert_elementwise_op, + "elementwise_pow": convert_elementwise_op, + "elementwise_floordiv": convert_elementwise_op, "equal": convert_equal, "exp": convert_unary_op, "expand_v2": convert_expand, @@ -1352,20 +1425,30 @@ def convert_unsqueeze(g, op, block): "isinf_v2": convert_unary_op, "layer_norm": convert_layer_norm, "leaky_relu": convert_leaky_relu, + "less_than": convert_less_than, "lookup_table": convert_lookup_table, "lookup_table_v2": convert_lookup_table, "log": convert_unary_op, "log10": convert_unary_op, "log1p": convert_log1p, + "logsumexp": convert_logsumexp, "matmul": convert_matmul, "matmul_v2": convert_matmul, "mul": convert_mul, "nearest_interp_v2": convert_interpolate, + "not_equal": convert_not_equal, "pool2d": convert_pool2d, "pad1d": convert_padding, "pad2d": convert_padding, "pad3d": convert_padding, + "pow": convert_pow, "reduce_all": convert_reduce, + "reduce_any": convert_reduce, + "reduce_max": convert_reduce, + "reduce_min": convert_reduce, + "reduce_prod": convert_reduce, + "reduce_sum": convert_reduce, + "reduce_mean": convert_reduce, "relu": convert_unary_op, "reshape2": convert_reshape, "rnn": convert_rnn, @@ -1378,6 +1461,7 @@ def convert_unsqueeze(g, op, block): "squeeze2": convert_squeeze, "tan": convert_unary_op, "tanh": convert_unary_op, + "top_k_v2": convert_topk, "transpose2": convert_transpose, "unsqueeze2": convert_unsqueeze, } diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index eede8a6164ab..635b379e5bf3 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -42,8 +42,8 @@ def assert_shapes_match(tru, est): def get_paddle_model(func, input_spec): global PADDLE_TEST_DATA_ROOT_PATH model_path = Path(PADDLE_TEST_DATA_ROOT_PATH, "model") - paddle.jit.save(func, str(model_path), input_spec=input_spec) + paddle.jit.save(func, "/paddle/pr_for_tvm/0905/tvm/inference_model_test/inference", input_spec=input_spec) baseline_model = paddle.jit.load(str(model_path)) shutil.rmtree(str(PADDLE_TEST_DATA_ROOT_PATH)) @@ -571,6 +571,29 @@ def flatten2(inputs): verify_model(flatten2, input_data=[x_data]) +@tvm.testing.uses_gpu +def test_forward_floor_divide(): + class Floor_divide(nn.Layer): + @paddle.jit.to_static + def forward(self, x, y): + return paddle.floor_divide(x, y) + + x_shape = [10] + y_shape = [10] + x_data = paddle.randint(1, 10, x_shape, dtype="int32") + y_data = paddle.randint(1, 10, y_shape, dtype="int32") + x_data_1 = paddle.randint(1, 10, x_shape, dtype="int64") + y_data_1 = paddle.randint(1, 10, y_shape, dtype="int64") + verify_model(Floor_divide(), input_data=[x_data, y_data]) + verify_model(Floor_divide(), input_data=[x_data_1, y_data_1]) + # For broadcast + x_shape_1 = [10] + y_shape_1 = [10, 1] + x_data_2 = paddle.randint(1, 10, x_shape_1, dtype="int32") + y_data_2 = paddle.randint(1, 10, y_shape_1, dtype="int32") + verify_model(Floor_divide(), input_data=[x_data_2, y_data_2]) + + @tvm.testing.uses_gpu def test_forward_shape_full(): @paddle.jit.to_static @@ -763,6 +786,31 @@ def leaky_relu(inputs): verify_model(leaky_relu, input_data=input_data) +@tvm.testing.uses_gpu +def test_forward_less_than(): + class Less_than(nn.Layer): + @paddle.jit.to_static + def forward(self, x, y): + output = paddle.less_than(x, y) + output = paddle.cast(output, "int32") + return output + + x_shape = [10] + y_shape = [10] + x_data = paddle.randint(1, 10, x_shape, dtype="int32") + y_data = paddle.randint(1, 10, y_shape, dtype="int32") + x_data_1 = paddle.randint(1, 10, x_shape, dtype="int64") + y_data_1 = paddle.randint(1, 10, y_shape, dtype="int64") + verify_model(Less_than(), input_data=[x_data, y_data]) + verify_model(Less_than(), input_data=[x_data_1, y_data_1]) + # For broadcast + x_shape_1 = [10] + y_shape_1 = [10, 1] + x_data_2 = paddle.rand(x_shape_1, dtype="float32") + y_data_2 = paddle.rand(y_shape_1, dtype="float32") + verify_model(Less_than(), input_data=[x_data_2, y_data_2]) + + @tvm.testing.uses_gpu def test_forward_look_up(): @paddle.jit.to_static @@ -855,6 +903,32 @@ def forward(self, input1, input2): verify_model(MatMul1(), input_data=[input_data1, input_data2]) +@tvm.testing.uses_gpu +def test_forward_not_equal(): + class Not_equal(nn.Layer): + @paddle.jit.to_static + def forward(self, x, y): + output = paddle.not_equal(x, y) + output = paddle.cast(output, "int32") + return output + + x_shape = [10] + y_shape = [10] + x_data = paddle.randint(1, 10, x_shape, dtype="int32") + y_data = paddle.randint(1, 10, y_shape, dtype="int32") + x_data_1 = paddle.randint(1, 10, x_shape, dtype="int64") + y_data_1 = paddle.randint(1, 10, y_shape, dtype="int64") + verify_model(Not_equal(), input_data=[x_data, y_data]) + verify_model(Not_equal(), input_data=[x_data_1, y_data_1]) + # For broadcast + x_shape_1 = [10] + y_shape_1 = [10, 1] + x_data_2 = paddle.rand(x_shape_1, dtype="float32") + y_data_2 = paddle.rand(y_shape_1, dtype="float32") + verify_model(Not_equal(), input_data=[x_data_2, y_data_2]) + + + @tvm.testing.uses_gpu def test_forward_pool2d(): @paddle.jit.to_static @@ -916,32 +990,106 @@ def pad4(inputs): @tvm.testing.uses_gpu -def test_forward_reduce(): - @paddle.jit.to_static - def reduce_all(inputs): - inputs = paddle.assign(inputs) - inputs = paddle.cast(inputs, "bool") - inputs = paddle.all(inputs) - return paddle.cast(inputs, "int32") +def test_forward_pow(): + class Pow(nn.Layer): + @paddle.jit.to_static + def forward(self, x): + output = paddle.pow(x, 2) + return output - @paddle.jit.to_static - def reduce_all2(inputs): - inputs = paddle.assign(inputs) - inputs = paddle.cast(inputs, "bool") - inputs = paddle.all(inputs, axis=0) - return paddle.cast(inputs, "int32") + class Pow1(nn.Layer): + @paddle.jit.to_static + def forward(self, x): + output = paddle.pow(x, 2.5) + return output - @paddle.jit.to_static - def reduce_all3(inputs): - inputs = paddle.assign(inputs) - inputs = paddle.cast(inputs, "bool") - inputs = paddle.all(inputs, axis=[0, 1, -1], keepdim=True) - return paddle.cast(inputs, "int32") + class Pow2(nn.Layer): + @paddle.jit.to_static + def forward(self, x, y): + output = paddle.pow(x, y) + return output + + x_data = paddle.to_tensor([1, 2, 3], dtype='float32') + y_data = paddle.to_tensor([2], dtype='float32') + verify_model(Pow(), input_data=[x_data]) + verify_model(Pow1(), input_data=[x_data]) + verify_model(Pow2(), input_data=[x_data, y_data]) + + +@tvm.testing.uses_gpu +def test_forward_reduce_op(): + class ReduceOp_Bool(nn.Layer): + def __init__(self, op_name): + super(ReduceOp_Bool, self).__init__() + self.func = getattr(paddle, op_name, None) + + @paddle.jit.to_static + def forward(self, inputs): + inputs = paddle.cast(inputs, "bool") + output = self.func(inputs) + output = paddle.cast(output, "int32") + return output + + class ReduceOp_Bool1(ReduceOp_Bool): + @paddle.jit.to_static + def forward(self, inputs): + inputs = paddle.cast(inputs, "bool") + output = self.func(inputs, axis=0) + output = paddle.cast(output, "int32") + return output + + class ReduceOp_Bool2(ReduceOp_Bool): + @paddle.jit.to_static + def forward(self, inputs): + inputs = paddle.cast(inputs, "bool") + output = self.func(inputs, axis=[0, 1, -1], keepdim=True) + output = paddle.cast(output, "int32") + return output + + class ReduceOp_Math(nn.Layer): + def __init__(self, op_name): + super(ReduceOp_Math, self).__init__() + self.func = getattr(paddle, op_name, None) + + @paddle.jit.to_static + def forward(self, inputs): + output = self.func(inputs) + return output + + class ReduceOp_Math1(ReduceOp_Math): + @paddle.jit.to_static + def forward(self, inputs): + output = self.func(inputs, axis=0) + return output + + class ReduceOp_Math2(ReduceOp_Math): + @paddle.jit.to_static + def forward(self, inputs): + output = self.func(inputs, axis=[0, 1], keepdim=True) + return output input_data = paddle.randn([1, 2, 3]) - verify_model(reduce_all, input_data=input_data) - verify_model(reduce_all2, input_data=input_data) - verify_model(reduce_all3, input_data=input_data) + op_list_bool = [ + "all", + "any", + ] + for op_name in op_list_bool: + verify_model(ReduceOp_Bool(op_name), input_data) + verify_model(ReduceOp_Bool1(op_name), input_data) + verify_model(ReduceOp_Bool2(op_name), input_data) + input_data1 = paddle.rand([2, 4, 5], dtype="float32") + op_list_math = [ + "max", + "min", + "prod", + "sum", + "mean", + "logsumexp", + ] + for op_name in op_list_math: + verify_model(ReduceOp_Math(op_name), input_data1) + verify_model(ReduceOp_Math1(op_name), input_data1) + verify_model(ReduceOp_Math2(op_name), input_data1) @tvm.testing.uses_gpu @@ -1050,6 +1198,48 @@ def squeeze3(inputs): verify_model(squeeze3, input_data=input_data) +@tvm.testing.uses_gpu +def test_forward_topk(): + class Topk1(nn.Layer): + @paddle.jit.to_static + def forward(self, inputs): + return paddle.topk(inputs, k=3) + + class Topk2(nn.Layer): + @paddle.jit.to_static + def forward(self, inputs): + return paddle.topk(inputs, k=3, axis=-2) + + class Topk3(nn.Layer): + @paddle.jit.to_static + def forward(self, inputs): + return paddle.topk(inputs, k=3, axis=3) + + class Topk4(nn.Layer): + @paddle.jit.to_static + def forward(self, inputs): + return paddle.topk(inputs, k=3, largest=True) + + class Topk5(nn.Layer): + @paddle.jit.to_static + def forward(self, inputs): + return paddle.topk(inputs, k=3, largest=False) + + class Topk6(nn.Layer): + @paddle.jit.to_static + def forward(self, inputs): + return paddle.topk(inputs, k=3, sorted=True) + + input_shape = [1, 3, 10, 10] + input_data = paddle.rand(input_shape, dtype="float32") + verify_model(Topk1(), input_data=input_data) + verify_model(Topk2(), input_data=input_data) + verify_model(Topk3(), input_data=input_data) + verify_model(Topk4(), input_data=input_data) + verify_model(Topk5(), input_data=input_data) + verify_model(Topk6(), input_data=input_data) + + if __name__ == "__main__": test_forward_add_subtract() test_forward_addmm() @@ -1066,6 +1256,7 @@ def squeeze3(inputs): test_forward_dropout() test_forward_expand() test_forward_flatten() + test_forward_floor_divide() test_forward_shape_full() test_forward_ones_like() test_forward_gather_assign_value() @@ -1077,16 +1268,20 @@ def squeeze3(inputs): test_forward_isinf() test_forward_layer_norm() test_forward_leaky_relu() + test_forward_less_than() test_forward_look_up() test_forward_lstm() - test_forward_multiply() test_forward_matmul() + test_forward_multiply() + test_forward_not_equal() test_forward_pool2d() test_forward_pad() - test_forward_reduce() + test_forward_pow() + test_forward_reduce_op() test_forward_reshape() test_forward_scale() test_forward_slice() test_forward_squeeze2() + test_forward_topk() test_forward_conv_transpose() test_forward_unary_op() From 707a9a51390db4b22caeba148fb3e514601a03c8 Mon Sep 17 00:00:00 2001 From: wjj19950828 Date: Wed, 8 Sep 2021 21:15:32 +0800 Subject: [PATCH 064/127] Fixed bugs --- tests/python/frontend/paddlepaddle/test_forward.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index 635b379e5bf3..962e6cf6abad 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -43,7 +43,6 @@ def get_paddle_model(func, input_spec): global PADDLE_TEST_DATA_ROOT_PATH model_path = Path(PADDLE_TEST_DATA_ROOT_PATH, "model") paddle.jit.save(func, str(model_path), input_spec=input_spec) - paddle.jit.save(func, "/paddle/pr_for_tvm/0905/tvm/inference_model_test/inference", input_spec=input_spec) baseline_model = paddle.jit.load(str(model_path)) shutil.rmtree(str(PADDLE_TEST_DATA_ROOT_PATH)) From 33b050bec29ef3a7ffcce120a4ba25902d743e28 Mon Sep 17 00:00:00 2001 From: wjj19950828 Date: Thu, 9 Sep 2021 14:59:25 +0800 Subject: [PATCH 065/127] Fixed bugs --- python/tvm/relay/frontend/paddlepaddle.py | 1 + 1 file changed, 1 insertion(+) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 684dae767e31..9698f7aa53c8 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -1049,6 +1049,7 @@ def convert_pow(g, op, block): factor = _expr.const(factor, dtype="float32").astype("float32") out = _op.power(x, factor) + g.add_node(op.output("Out")[0], out) def convert_range(g, op, block): From 47a0e6795f10febbda8f7c105faf91fdb6d45a7c Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Thu, 9 Sep 2021 16:07:37 +0800 Subject: [PATCH 066/127] add split rsqrt square floor_mod op --- python/tvm/relay/frontend/paddlepaddle.py | 72 ++++++++++++++++--- .../frontend/paddlepaddle/test_forward.py | 64 +++++++++++++---- 2 files changed, 112 insertions(+), 24 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index b408638dca30..de22c164648c 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -480,12 +480,13 @@ def convert_elementwise_op(g, op, block): """Operator converter for all the elementwise operators.""" op_map = { - "elementwise_div": lambda x, y: x / y, - "elementwise_add": lambda x, y: x + y, - "elementwise_mul": lambda x, y: x * y, - "elementwise_sub": lambda x, y: x - y, - "elementwise_mod": lambda x, y: x % y, + "elementwise_div": "divide", + "elementwise_add": "add", + "elementwise_mul": "multiply", + "elementwise_sub": "subtract", + "elementwise_mod": "mod", "greater_than": "greater", + "less_equal": "less_equal", } op_func = op_map[op.type] ipt0 = g.get_node(op.input("X")[0]) @@ -498,8 +499,7 @@ def convert_elementwise_op(g, op, block): axis = axis + len(ipt0_shape) if axis != len(ipt0_shape) - 1: ipt1 = _op.expand_dims(ipt1, axis=axis, num_newaxis=(len(ipt0_shape) - axis - 1)) - if isinstance(op_func, str): - op_func = get_relay_op(op_func) + op_func = get_relay_op(op_func) out = op_func(ipt0, ipt1) g.add_node(op.output("Out")[0], out) @@ -603,10 +603,12 @@ def convert_fill_constant_batch_size_like(g, op, block): dtype = block.var(op.output("Out")[0]).dtype dtype = str(dtype).strip().split(".")[1] input_shape = shape_of(x) - batch = _op.strided_slice(input_shape, begin=[input_dim_idx], end=[input_dim_idx+1]).astype("int32") + batch = _op.strided_slice(input_shape, begin=[input_dim_idx], end=[input_dim_idx + 1]).astype( + "int32" + ) shape_before = shape[:output_dim_idx] shape_before = _expr.const(shape_before, dtype="int32") - shape_after = shape[output_dim_idx+1:] + shape_after = shape[output_dim_idx + 1 :] shape_after = _expr.const(shape_after, dtype="int32") out_shape = _op.concatenate([shape_before, batch, shape_after], axis=0) @@ -1299,6 +1301,52 @@ def convert_softmax(g, op, block): g.add_node(op.output("Out")[0], out) +def convert_split(g, op, block): + """Operator converter for split.""" + + x = g.get_node(op.input("X")[0]) + axis = op.input("AxisTensor") + if axis: + axis = g.get_node(axis[0]) + axis = infer_value(axis, g.get_params()).numpy().tolist()[0] + else: + axis = op.attr("axis") + + sections = op.input("SectionsTensorList") + if sections: + tmp_section = [] + for i in sections: + i = g.get_node(i) + i = infer_value(i, g.get_params()).numpy().tolist() + tmp_section.extend(i) + sections = tmp_section + else: + sections = op.attr("sections") + if sections: + indices = [] + split_index = 0 + for i in sections[:-1]: + if i == -1: + input_shape = infer_shape(x)[axis] + i = input_shape - np.sum(sections) - 1 + split_index += i + indices.append(split_index) + else: + indices = op.attr("num") + + out = _op.split(x, indices, axis) + for i, out_i in enumerate(out): + g.add_node(op.output("Out")[i], out_i) + + +def convert_square(g, op, block): + """Operator converter for square.""" + + x = g.get_node(op.input("X")[0]) + out = _op.multiply(x, x) + g.add_node(op.output("Out")[0], out) + + def convert_squeeze(g, op, block): """Operator converter for squeeze2.""" @@ -1395,6 +1443,7 @@ def convert_unsqueeze(g, op, block): "elementwise_div": convert_elementwise_op, "elementwise_mul": convert_elementwise_op, "elementwise_sub": convert_elementwise_op, + "elementwise_mod": convert_elementwise_op, "equal": convert_equal, "exp": convert_unary_op, "expand_v2": convert_expand, @@ -1404,6 +1453,7 @@ def convert_unsqueeze(g, op, block): "fill_constant_batch_size_like": convert_fill_constant_batch_size_like, "flatten_contiguous_range": convert_flatten, "floor": convert_unary_op, + "floor_mod": convert_unary_op, "gather": convert_gather, "gather_nd": convert_gather_nd, "gelu": convert_gelu, @@ -1414,6 +1464,7 @@ def convert_unsqueeze(g, op, block): "isinf_v2": convert_unary_op, "layer_norm": convert_layer_norm, "leaky_relu": convert_leaky_relu, + "less_equal": convert_elementwise_op, "lookup_table": convert_lookup_table, "lookup_table_v2": convert_lookup_table, "log": convert_unary_op, @@ -1432,12 +1483,15 @@ def convert_unsqueeze(g, op, block): "relu": convert_unary_op, "reshape2": convert_reshape, "rnn": convert_rnn, + "rsqrt": convert_unary_op, "scale": convert_scale, "shape": convert_shape, "sigmoid": convert_unary_op, "sin": convert_unary_op, "slice": convert_slice, "softmax": convert_softmax, + "split": convert_split, + "square": convert_square, "squeeze2": convert_squeeze, "stack": convert_stack, "tan": convert_unary_op, diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index a47c09a19429..61ecd913c593 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -156,12 +156,15 @@ def forward(self, inputs): "cosh", "exp", "floor", + "floor_mod", "log", "log10", "log1p", "relu", + "rsqrt", "sigmoid", "sin", + "square", "tan", "tanh", ] @@ -626,16 +629,31 @@ def ones_like2(inputs): @tvm.testing.uses_gpu -def test_forward_greater_than(): - @paddle.jit.to_static - def greater_than(input1, input2): - y = paddle.greater_than(input1, input2) - return paddle.cast(y, "int32") +def test_forward_than(): + class ThanOp(nn.Layer): + def __init__(self, op_name): + super(ThanOp, self).__init__() + for candidate in (paddle, paddle.nn.functional): + self.func = getattr(candidate, op_name, None) + if self.func: + break + + @paddle.jit.to_static + def forward(self, input1, input2): + y = self.func(input1, input2) + return paddle.cast(y, "int32") + + op_list = [ + "greater_than", + "less_than", + "less_equal", + ] input_shape = [1, 3, 10, 10] input_data = paddle.rand(input_shape, dtype="float32") input_data2 = paddle.rand(input_shape, dtype="float32") - verify_model(greater_than, input_data=[input_data, input_data2]) + for op_name in op_list: + verify_model(ThanOp(op_name), [input_data, input_data2]) @tvm.testing.uses_gpu @@ -1046,17 +1064,32 @@ def slice4(inputs): input_shape = [1, 3, 10, 10] input_data = paddle.rand(input_shape, dtype="float32") - verify_model( - slice1, - input_data=[ - input_data, - ], - ) + verify_model(slice1, input_data=input_data) verify_model(slice2, input_data=input_data) # need op "strided_slice" # verify_model(slice3, input_data=paddle.randn((4, 4))) - # need op "assign_value" - # verify_model(slice4, input_data=input_data) + verify_model(slice4, input_data=input_data) + + +@tvm.testing.uses_gpu +def test_forward_split(): + @paddle.jit.to_static + def split(inputs): + return paddle.split(inputs, 2, axis=paddle.to_tensor([0], "int32")) + + @paddle.jit.to_static + def split2(inputs): + return paddle.split(inputs, [1, 2, -1], axis=1) + + @paddle.jit.to_static + def split3(inputs): + return paddle.split(inputs, [paddle.to_tensor([2]), 1, paddle.to_tensor(3)], axis=0) + + input_shape = [6, 10] + input_data = paddle.rand(input_shape, dtype="float32") + verify_model(split, input_data=input_data) + verify_model(split2, input_data=input_data) + verify_model(split3, input_data=input_data) @tvm.testing.uses_gpu @@ -1151,7 +1184,6 @@ def tile3(inputs, inputs2): test_forward_gather_assign_value() test_forward_gather_nd() test_forward_gelu() - test_forward_greater_than() test_forward_hard_sigmoid() test_forward_hard_swish() test_forward_interpolate() @@ -1168,7 +1200,9 @@ def tile3(inputs, inputs2): test_forward_reshape() test_forward_scale() test_forward_slice() + test_forward_split() test_forward_squeeze2() + test_forward_than() test_forward_tile() test_forward_conv_transpose() test_forward_unary_op() From e80aa2cd4b45663683884e1cfcb177c0fc331c7f Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Thu, 9 Sep 2021 17:33:11 +0800 Subject: [PATCH 067/127] fix slice op bug --- python/tvm/relay/frontend/paddlepaddle.py | 46 ++++++++++++++---- .../frontend/paddlepaddle/test_forward.py | 48 +++++-------------- 2 files changed, 50 insertions(+), 44 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index b6c90cc3c136..805fdd4fa522 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -485,8 +485,9 @@ def convert_elementwise_op(g, op, block): "elementwise_mul": "multiply", "elementwise_sub": "subtract", "elementwise_mod": "mod", - "elementwise_pow": "pow", + "elementwise_pow": "power", "elementwise_floordiv": "floor_divide", + "floor_mod": "floor_mod", "equal": "equal", "greater_than": "greater", "less_equal": "less_equal", @@ -1295,16 +1296,43 @@ def parameter_process(starts, ends, axes): return new_starts, new_ends, new_axes data = g.get_node(op.input("Input")[0]) - starts = op.attr("starts") - ends = op.attr("ends") + + starts = op.input("StartsTensor") + if starts: + starts = g.get_node(starts[0]) + starts = infer_value(starts, g.get_params()).numpy().tolist() + elif op.input("StartsTensorList"): + starts = [] + for start_index in op.input("StartsTensorList"): + start_index = g.get_node(start_index) + if isinstance(start_index, _expr.Expr): + start_index = infer_value(start_index, g.get_params()).numpy().tolist() + starts.extend(start_index) + else: + starts = op.attr("starts") + if isinstance(starts, int): + starts = [starts] + + ends = op.input("EndsTensor") + if ends: + ends = g.get_node(ends[0]) + ends = infer_value(ends, g.get_params()).numpy().tolist() + elif op.input("EndsTensorList"): + ends = [] + for end_index in op.input("EndsTensorList"): + end_index = g.get_node(end_index) + if isinstance(end_index, _expr.Expr): + end_index = infer_value(end_index, g.get_params()).numpy().tolist() + ends.extend(end_index) + else: + ends = op.attr("ends") + if isinstance(ends, int): + ends = [ends] + axes = op.attr("axes") - decrease_axis = op.attr("decrease_axis") - if isinstance(starts, int): - starts = [starts] - if isinstance(ends, int): - ends = [ends] if isinstance(axes, int): axes = [axes] + decrease_axis = op.attr("decrease_axis") if isinstance(decrease_axis, int): decrease_axis = [decrease_axis] starts, ends, axes = parameter_process(starts, ends, axes) @@ -1501,7 +1529,7 @@ def convert_unsqueeze(g, op, block): "fill_constant_batch_size_like": convert_fill_constant_batch_size_like, "flatten_contiguous_range": convert_flatten, "floor": convert_unary_op, - "floor_mod": convert_unary_op, + "floor_mod": convert_elementwise_op, "gather": convert_gather, "gather_nd": convert_gather_nd, "gelu": convert_gelu, diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index 49b8423d65df..9d06a025ca84 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -21,6 +21,7 @@ import paddle import paddle.nn as nn +from frontend.mxnet.test_forward import test_forward_elemwise_ops import tvm from tvm.contrib.sparse import array @@ -155,7 +156,6 @@ def forward(self, inputs): "cosh", "exp", "floor", - "floor_mod", "log", "log10", "log1p", @@ -590,29 +590,6 @@ def flatten2(inputs): verify_model(flatten2, input_data=[x_data]) -@tvm.testing.uses_gpu -def test_forward_floor_divide(): - class Floor_divide(nn.Layer): - @paddle.jit.to_static - def forward(self, x, y): - return paddle.floor_divide(x, y) - - x_shape = [10] - y_shape = [10] - x_data = paddle.randint(1, 10, x_shape, dtype="int32") - y_data = paddle.randint(1, 10, y_shape, dtype="int32") - x_data_1 = paddle.randint(1, 10, x_shape, dtype="int64") - y_data_1 = paddle.randint(1, 10, y_shape, dtype="int64") - verify_model(Floor_divide(), input_data=[x_data, y_data]) - verify_model(Floor_divide(), input_data=[x_data_1, y_data_1]) - # For broadcast - x_shape_1 = [10] - y_shape_1 = [10, 1] - x_data_2 = paddle.randint(1, 10, x_shape_1, dtype="int32") - y_data_2 = paddle.randint(1, 10, y_shape_1, dtype="int32") - verify_model(Floor_divide(), input_data=[x_data_2, y_data_2]) - - @tvm.testing.uses_gpu def test_forward_shape_full(): @paddle.jit.to_static @@ -651,10 +628,10 @@ def ones_like2(inputs): @tvm.testing.uses_gpu -def test_forward_than(): - class ThanOp(nn.Layer): +def test_forward_elemwise(): + class ElemwiseOp(nn.Layer): def __init__(self, op_name): - super(ThanOp, self).__init__() + super(ElemwiseOp, self).__init__() for candidate in (paddle, paddle.nn.functional): self.func = getattr(candidate, op_name, None) if self.func: @@ -666,7 +643,8 @@ def forward(self, input1, input2): return paddle.cast(y, "int32") op_list = [ - "equal", + "floor_divide", + "floor_mod" "equal", "greater_than", "less_equal", "less_than", @@ -678,11 +656,11 @@ def forward(self, input1, input2): ] x_data = paddle.rand(input_shape, dtype="float32") y_data = paddle.rand(input_shape_2, dtype="float32") - x_data_2 = paddle.rand(input_shape_2, dtype="int32") - y_data_2 = paddle.rand(input_shape, dtype="int32") + x_data_2 = paddle.randint(1, 100, input_shape_2, dtype="int32") + y_data_2 = paddle.randint(1, 100, input_shape, dtype="int32") for op_name in op_list: - verify_model(ThanOp(op_name), [x_data, y_data]) - verify_model(ThanOp(op_name), [x_data_2, y_data_2]) + verify_model(ElemwiseOp(op_name), [x_data, y_data]) + verify_model(ElemwiseOp(op_name), [x_data_2, y_data_2]) @tvm.testing.uses_gpu @@ -951,7 +929,8 @@ def pool2d3(inputs): input_data = paddle.uniform(shape=[1, 2, 32, 32], dtype="float32", min=-1, max=1) verify_model(pool2d1, input_data=input_data) verify_model(pool2d2, input_data=input_data) - verify_model(pool2d3, input_data=input_data) + # need op max_pool2d_with_index + # verify_model(pool2d3, input_data=input_data) @tvm.testing.uses_gpu @@ -1322,9 +1301,9 @@ def tile3(inputs, inputs2): test_forward_cumsum() test_forward_dot() test_forward_dropout() + test_forward_elemwise() test_forward_expand() test_forward_flatten() - test_forward_floor_divide() test_forward_shape_full() test_forward_ones_like() test_forward_gather_assign_value() @@ -1349,7 +1328,6 @@ def tile3(inputs, inputs2): test_forward_slice() test_forward_split() test_forward_squeeze2() - test_forward_than() test_forward_topk() test_forward_tile() test_forward_conv_transpose() From ea993c00f71ff17b94bb68d58845553655541eed Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Thu, 9 Sep 2021 17:36:23 +0800 Subject: [PATCH 068/127] fix slice op bug --- tests/python/frontend/paddlepaddle/test_forward.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index 9d06a025ca84..bebcb77d0546 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -21,7 +21,6 @@ import paddle import paddle.nn as nn -from frontend.mxnet.test_forward import test_forward_elemwise_ops import tvm from tvm.contrib.sparse import array From 01f23eedf9cdf0d93f46b515955c6b9d2e2d5a84 Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Thu, 9 Sep 2021 17:44:46 +0800 Subject: [PATCH 069/127] fix floor_divide test bug --- tests/python/frontend/paddlepaddle/test_forward.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index bebcb77d0546..f7ced14d7c69 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -643,7 +643,8 @@ def forward(self, input1, input2): op_list = [ "floor_divide", - "floor_mod" "equal", + "floor_mod", + "equal", "greater_than", "less_equal", "less_than", @@ -658,7 +659,8 @@ def forward(self, input1, input2): x_data_2 = paddle.randint(1, 100, input_shape_2, dtype="int32") y_data_2 = paddle.randint(1, 100, input_shape, dtype="int32") for op_name in op_list: - verify_model(ElemwiseOp(op_name), [x_data, y_data]) + if op_name not in ["floor_divide"]: + verify_model(ElemwiseOp(op_name), [x_data, y_data]) verify_model(ElemwiseOp(op_name), [x_data_2, y_data_2]) From 82d0307ae870d69c6ca5d1979a76bc6e8d19bb18 Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Thu, 9 Sep 2021 21:47:40 +0800 Subject: [PATCH 070/127] del slice infer_value --- python/tvm/relay/frontend/paddlepaddle.py | 68 +++++++++++------------ 1 file changed, 33 insertions(+), 35 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 805fdd4fa522..5c3f50a12caa 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -1279,63 +1279,61 @@ def convert_shape(g, op, block): def convert_slice(g, op, block): """Operator converter for slice.""" - def parameter_process(starts, ends, axes): - new_axes = [] - new_starts = [] - new_ends = [] - pop_index = 0 - for i in range(max(axes) + 1): - new_axes.append(i) - if i in axes: - new_starts.append(starts[pop_index]) - new_ends.append(ends[pop_index]) - pop_index += 1 - else: - new_starts.append(0) - new_ends.append(np.iinfo(np.int32).max) - return new_starts, new_ends, new_axes - data = g.get_node(op.input("Input")[0]) + dims = len(block.var(op.input("Input")[0]).shape) + dtype = "int64" + + axes = op.attr("axes") + axes = _op.const(axes) + decrease_axis = op.attr("decrease_axis") + if isinstance(decrease_axis, int): + decrease_axis = [decrease_axis] starts = op.input("StartsTensor") if starts: starts = g.get_node(starts[0]) - starts = infer_value(starts, g.get_params()).numpy().tolist() elif op.input("StartsTensorList"): starts = [] for start_index in op.input("StartsTensorList"): start_index = g.get_node(start_index) - if isinstance(start_index, _expr.Expr): - start_index = infer_value(start_index, g.get_params()).numpy().tolist() - starts.extend(start_index) + if not isinstance(start_index, _expr.Expr): + start_index = _expr.const(start_index, dtype=dtype) + else: + start_index = start_index.astype(dtype) + starts.append(start_index) + starts = _op.concatenate(starts, axis=0) else: starts = op.attr("starts") - if isinstance(starts, int): - starts = [starts] + starts = _expr.const(starts) + if isinstance(starts, _expr.Expr): + starts = _op.scatter( + _op.const([0] * dims, dtype=infer_type(starts).checked_type.dtype), + axes, + starts, + axis=0, + ) + data_shape = shape_of(data) ends = op.input("EndsTensor") if ends: ends = g.get_node(ends[0]) - ends = infer_value(ends, g.get_params()).numpy().tolist() elif op.input("EndsTensorList"): ends = [] + data_shape = data_shape.astype(dtype) for end_index in op.input("EndsTensorList"): end_index = g.get_node(end_index) - if isinstance(end_index, _expr.Expr): - end_index = infer_value(end_index, g.get_params()).numpy().tolist() - ends.extend(end_index) + if not isinstance(end_index, _expr.Expr): + end_index = _expr.const(end_index, dtype=dtype) + else: + end_index = end_index.astype(dtype) + ends.append(end_index) + ends = _op.concatenate(ends, axis=0) else: ends = op.attr("ends") - if isinstance(ends, int): - ends = [ends] + ends = _expr.const(ends) + if isinstance(ends, _expr.Expr): + ends = _op.scatter(data_shape, axes, ends, axis=0) - axes = op.attr("axes") - if isinstance(axes, int): - axes = [axes] - decrease_axis = op.attr("decrease_axis") - if isinstance(decrease_axis, int): - decrease_axis = [decrease_axis] - starts, ends, axes = parameter_process(starts, ends, axes) out = _op.strided_slice(data, begin=starts, end=ends) if decrease_axis: out = _op.squeeze(out, axis=decrease_axis) From 0f3a200a37b90e70b962e9b385879da10d7725d5 Mon Sep 17 00:00:00 2001 From: wjj19950828 Date: Fri, 10 Sep 2021 10:41:21 +0800 Subject: [PATCH 071/127] add paddle ops --- python/tvm/relay/frontend/paddlepaddle.py | 43 +++++- .../frontend/paddlepaddle/test_forward.py | 130 ++++++++++++++++++ 2 files changed, 172 insertions(+), 1 deletion(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 9698f7aa53c8..ca96ef779e6f 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -706,6 +706,17 @@ def convert_hard_swish(g, op, block): g.add_node(op.output("Out")[0], out) +def convert_index_select(g, op, block): + """Operator converter for index_select.""" + + dim = op.attr("dim") + x = g.get_node(op.input("X")[0]) + index = g.get_node(op.input("Index")[0]) + out = _op.take(x, indices=index, axis=dim, mode="clip") + + g.add_node(op.output("Out")[0], out) + + def convert_layer_norm(g, op, block): """Operator converter for layer_norm.""" @@ -1051,7 +1062,34 @@ def convert_pow(g, op, block): out = _op.power(x, factor) g.add_node(op.output("Out")[0], out) - + +def convert_norm(g, op, block): + """Operator converter for norm.""" + + x = g.get_node(op.input("X")[0]) + dtype = infer_type(x).checked_type.dtype + axis = op.attr("axis") + keepdim = op.attr("keepdim") + if op.attr("asvector"): + axis = None + order = op.attr("porder") + if order == np.inf: + out = _op.reduce.max(_op.abs(x), axis=axis, keepdims=keepdim) + elif order == np.NINF: + out = _op.reduce.min(_op.abs(x), axis=axis, keepdims=keepdim) + else: + reci_order = _expr.const(1.0 / order, dtype=dtype) + order = _expr.const(order) + out = _op.power( + _op.reduce.sum(_op.power(_op.abs(x), order), axis=axis, keepdims=keepdim), + reci_order, + ) + if op.attr("asvector") and not keepdim: + out = _op.expand_dims(out, axis=0) + + g.add_node(op.output("Out")[0], out) + + def convert_range(g, op, block): """Operator converter for range.""" @@ -1479,6 +1517,7 @@ def convert_unsqueeze(g, op, block): "gelu": convert_gelu, "hard_sigmoid": convert_hard_sigmoid, "hard_swish": convert_hard_swish, + "index_select": convert_index_select, "isinf": convert_unary_op, "isinf_v2": convert_unary_op, "layer_norm": convert_layer_norm, @@ -1487,6 +1526,7 @@ def convert_unsqueeze(g, op, block): "lookup_table": convert_lookup_table, "lookup_table_v2": convert_lookup_table, "log": convert_unary_op, + "log2": convert_unary_op, "log10": convert_unary_op, "log1p": convert_log1p, "logsumexp": convert_logsumexp, @@ -1500,6 +1540,7 @@ def convert_unsqueeze(g, op, block): "pad2d": convert_padding, "pad3d": convert_padding, "pow": convert_pow, + "p_norm": convert_norm, "range": convert_range, "reduce_all": convert_reduce, "reduce_any": convert_reduce, diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index fd55e916f866..cf96d2220976 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -156,6 +156,7 @@ def forward(self, inputs): "exp", "floor", "log", + "log2", "log10", "log1p", "relu", @@ -647,6 +648,27 @@ def ones_like2(inputs): verify_model(ones_like2, input_data=input_data) +@tvm.testing.uses_gpu +def test_forward_ones(): + @paddle.jit.to_static + def ones1(inputs): + ones = paddle.ones([1, 3, 10, 10]) + out = inputs + ones + return out + + @paddle.jit.to_static + def ones2(inputs): + shape = paddle.to_tensor([1, 3, 10, 10], dtype="int32") + ones = paddle.ones(shape) + out = inputs + ones + return out + + input_shape = [1, 3, 10, 10] + input_data = paddle.rand(input_shape, dtype="float32") + verify_model(ones1, input_data=input_data) + verify_model(ones2, input_data=input_data) + + @tvm.testing.uses_gpu def test_forward_gather_assign_value(): @paddle.jit.to_static @@ -716,6 +738,23 @@ def hard_swish(inputs): verify_model(hard_swish, input_data=input_data) +@tvm.testing.uses_gpu +def test_forward_index_select(): + @paddle.jit.to_static + def index_select1(x, index): + return paddle.index_select(x, index) + + @paddle.jit.to_static + def index_select2(x, index): + return paddle.index_select(x, index, axis=1) + + input_shape = [3, 10] + input_data = paddle.rand(input_shape, dtype="float32") + index = paddle.to_tensor(np.array([0, 1, 1]).astype('int32')) + verify_model(index_select1, input_data=[input_data, index]) + verify_model(index_select2, input_data=[input_data, index]) + + @tvm.testing.uses_gpu def test_forward_isinf(): @paddle.jit.to_static @@ -919,6 +958,72 @@ def forward(self, input1, input2): verify_model(MatMul1(), input_data=[input_data1, input_data2]) +@tvm.testing.uses_gpu +def test_forward_norm(): + class Norm1(nn.Layer): + @paddle.jit.to_static + def forward(self, inputs): + return paddle.norm(inputs, p=float("inf"), axis=None, keepdim=False) + + class Norm2(nn.Layer): + @paddle.jit.to_static + def forward(self, inputs): + return paddle.norm(inputs, p=float("-inf"), axis=None, keepdim=False) + + class Norm3(nn.Layer): + @paddle.jit.to_static + def forward(self, inputs): + return paddle.norm(inputs, p=float("-inf"), axis=None, keepdim=True) + + class Norm4(nn.Layer): + @paddle.jit.to_static + def forward(self, inputs): + return paddle.norm(inputs, p=float("inf"), axis=[1, 2], keepdim=False) + + class Norm5(nn.Layer): + @paddle.jit.to_static + def forward(self, inputs): + return paddle.norm(inputs, p=float("inf"), axis=-1, keepdim=True) + + class Norm6(nn.Layer): + @paddle.jit.to_static + def forward(self, inputs): + return paddle.norm(inputs, p=float(0.5), axis=1, keepdim=True) + + class Norm7(nn.Layer): + @paddle.jit.to_static + def forward(self, inputs): + return paddle.norm(inputs, p=float(1), axis=None, keepdim=False) + + class Norm8(nn.Layer): + @paddle.jit.to_static + def forward(self, inputs): + return paddle.norm(inputs, p=float(2.0), axis=1, keepdim=False) + + class Norm9(nn.Layer): + @paddle.jit.to_static + def forward(self, inputs): + return paddle.norm(inputs, p=float(-0.5), axis=[1, 2], keepdim=False) + + class Norm10(nn.Layer): + @paddle.jit.to_static + def forward(self, inputs): + return paddle.norm(inputs, p=float(-2), axis=(1), keepdim=False) + + input_shape = [1, 3, 10, 10] + input_data = paddle.rand(input_shape, dtype="float32") + verify_model(Norm1(), input_data=input_data) + verify_model(Norm2(), input_data=input_data) + verify_model(Norm3(), input_data=input_data) + verify_model(Norm4(), input_data=input_data) + verify_model(Norm5(), input_data=input_data) + verify_model(Norm6(), input_data=input_data) + verify_model(Norm7(), input_data=input_data) + verify_model(Norm8(), input_data=input_data) + verify_model(Norm9(), input_data=input_data) + verify_model(Norm10(), input_data=input_data) + + @tvm.testing.uses_gpu def test_forward_not_equal(): class Not_equal(nn.Layer): @@ -1305,6 +1410,27 @@ def tile3(inputs, inputs2): verify_model(tile3, input_data=[input_data, input_data2]) +@tvm.testing.uses_gpu +def test_forward_zeros(): + @paddle.jit.to_static + def zeros1(inputs): + zeros = paddle.zeros([1, 3, 10, 10]) + out = inputs + zeros + return out + + @paddle.jit.to_static + def zeros2(inputs): + shape = paddle.to_tensor([1, 3, 10, 10], dtype="int32") + zeros = paddle.zeros(shape) + out = inputs + zeros + return out + + input_shape = [1, 3, 10, 10] + input_data = paddle.rand(input_shape, dtype="float32") + verify_model(zeros1, input_data=input_data) + verify_model(zeros2, input_data=input_data) + + if __name__ == "__main__": test_forward_add_subtract() test_forward_addmm() @@ -1324,12 +1450,14 @@ def tile3(inputs, inputs2): test_forward_flatten() test_forward_floor_divide() test_forward_shape_full() + test_forward_ones() test_forward_ones_like() test_forward_gather_assign_value() test_forward_gather_nd() test_forward_gelu() test_forward_hard_sigmoid() test_forward_hard_swish() + test_forward_index_select() test_forward_interpolate() test_forward_isinf() test_forward_layer_norm() @@ -1340,6 +1468,7 @@ def tile3(inputs, inputs2): test_forward_matmul() test_forward_multiply() test_forward_not_equal() + test_forward_norm() test_forward_pool2d() test_forward_pad() test_forward_pow() @@ -1352,3 +1481,4 @@ def tile3(inputs, inputs2): test_forward_tile() test_forward_conv_transpose() test_forward_unary_op() + test_forward_zeros() From 359b2ab7c5c7b188509ecbacb46b50a4fb38d4b2 Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Fri, 10 Sep 2021 17:01:23 +0800 Subject: [PATCH 072/127] add maxinum mininum nonzero op --- python/tvm/relay/frontend/paddlepaddle.py | 37 ++++++++++++++++++- .../frontend/paddlepaddle/test_forward.py | 30 +++++++++++++-- 2 files changed, 63 insertions(+), 4 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 5c3f50a12caa..a402eaa2b06c 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -485,6 +485,8 @@ def convert_elementwise_op(g, op, block): "elementwise_mul": "multiply", "elementwise_sub": "subtract", "elementwise_mod": "mod", + "elementwise_max": "maximum", + "elementwise_min": "minimum", "elementwise_pow": "power", "elementwise_floordiv": "floor_divide", "floor_mod": "floor_mod", @@ -937,6 +939,25 @@ def convert_mul(g, op, block): g.add_node(op.output("Out")[0], out) +def convert_numel(g, op, block): + """Operator converter for numel.""" + + input_x = g.get_node(op.input("Input")[0]) + out = _op.ndarray_size(input_x) + out = _op.expand_dims(out, axis=0) + g.add_node(op.output("Out")[0], out) + + +def convert_nonzero(g, op, block): + """Operator converter for nonzero.""" + + input_x = g.get_node(op.input("Condition")[0]) + out = _op.transform.argwhere(input_x) + # Paddle NonZero always outputs int64 + out = _op.cast(out, "int64") + g.add_node(op.output("Out")[0], out) + + def convert_pool2d(g, op, block): """Operator converter for pool2d.""" @@ -1055,6 +1076,15 @@ def convert_range(g, op, block): g.add_node(op.output("Out")[0], out) +def convert_reciprocal(g, op, block): + """Operator converter for reciprocal.""" + + x = g.get_node(op.input("X")[0]) + dtype = infer_type(x).checked_type.dtype + out = _expr.const(1.0, dtype) / x + g.add_node(op.output("Out")[0], out) + + def convert_reduce(g, op, block): """Operator converter for reduce.""" @@ -1250,7 +1280,7 @@ def convert_scale(g, op, block): bias_after_scale = op.attr("bias_after_scale") x = g.get_node(op.input("X")[0]) if np.isclose(scale, 1.0) and np.isclose(bias, 0.0): - out = _op.copy(x) + out = x else: if np.isclose(bias, 0.0): out = x * _expr.const(np.array(scale).astype("float32")) @@ -1516,6 +1546,8 @@ def convert_unsqueeze(g, op, block): "elementwise_mul": convert_elementwise_op, "elementwise_sub": convert_elementwise_op, "elementwise_mod": convert_elementwise_op, + "elementwise_max": convert_elementwise_op, + "elementwise_min": convert_elementwise_op, "elementwise_pow": convert_elementwise_op, "elementwise_floordiv": convert_elementwise_op, "equal": convert_elementwise_op, @@ -1557,6 +1589,7 @@ def convert_unsqueeze(g, op, block): "pad3d": convert_padding, "pow": convert_pow, "range": convert_range, + "reciprocal": convert_reciprocal, "reduce_all": convert_reduce, "reduce_any": convert_reduce, "reduce_max": convert_reduce, @@ -1572,6 +1605,7 @@ def convert_unsqueeze(g, op, block): "shape": convert_shape, "sigmoid": convert_unary_op, "sin": convert_unary_op, + "size": convert_numel, "slice": convert_slice, "softmax": convert_softmax, "split": convert_split, @@ -1584,6 +1618,7 @@ def convert_unsqueeze(g, op, block): "tile": convert_tile, "transpose2": convert_transpose, "unsqueeze2": convert_unsqueeze, + "where_index": convert_nonzero, } diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index f7ced14d7c69..8ba52627ccdc 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -89,10 +89,9 @@ def verify_model(func, input_data, rtol=1e-5, atol=1e-5, input_shape=None): input_name = "input{}".format(idx) if input_shape: shape = input_shape[idx] - input_shape_dict[input_name] = [relay.Any()] * len(shape) else: shape = data.shape - input_shape_dict[input_name] = shape + input_shape_dict[input_name] = shape input_spec.append(paddle.static.InputSpec(dtype=data.dtype, shape=shape, name=input_name)) input_names.append(input_name) if isinstance(data, np.ndarray): @@ -158,6 +157,8 @@ def forward(self, inputs): "log", "log10", "log1p", + "numel", + "reciprocal", "relu", "rsqrt", "sigmoid", @@ -631,6 +632,7 @@ def test_forward_elemwise(): class ElemwiseOp(nn.Layer): def __init__(self, op_name): super(ElemwiseOp, self).__init__() + self.op_name_ = op_name for candidate in (paddle, paddle.nn.functional): self.func = getattr(candidate, op_name, None) if self.func: @@ -639,11 +641,15 @@ def __init__(self, op_name): @paddle.jit.to_static def forward(self, input1, input2): y = self.func(input1, input2) - return paddle.cast(y, "int32") + if "equal" in self.op_name_ or "than" in self.op_name_: + y = paddle.cast(y, "int32") + return y op_list = [ "floor_divide", "floor_mod", + "maximum", + "minimum", "equal", "greater_than", "less_equal", @@ -911,6 +917,23 @@ def forward(self, input1, input2): verify_model(MatMul1(), input_data=[input_data1, input_data2]) +@tvm.testing.uses_gpu +def test_forward_nonzero(): + class Nonzero(nn.Layer): + def __init__(self, as_tuple=False): + super().__init__() + self.as_tuple = as_tuple + + def forward(self, inputs): + return paddle.nonzero(inputs, self.as_tuple) + + x1 = paddle.to_tensor([[1.0, 0.0, 0.0, 2.0], [0.0, 2.0, 0.0, 1.1], [0.0, 0.0, 3.0, 0.0]]) + verify_model(Nonzero(), x1, input_shape=[[3, 4]]) + verify_model(Nonzero(True), x1, input_shape=[[3, 4]]) + x2 = paddle.to_tensor([0, 1, 0, 3]) + verify_model(Nonzero(), x2, input_shape=[[3, 4]]) + + @tvm.testing.uses_gpu def test_forward_pool2d(): @paddle.jit.to_static @@ -1320,6 +1343,7 @@ def tile3(inputs, inputs2): test_forward_lstm() test_forward_matmul() test_forward_multiply() + test_forward_nonzero() test_forward_pool2d() test_forward_pad() test_forward_pow() From fe26401be4027d9a836b386e4025bc118f8358a8 Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Fri, 10 Sep 2021 17:49:11 +0800 Subject: [PATCH 073/127] add slice strides params --- python/tvm/relay/frontend/paddlepaddle.py | 11 ++++++----- tests/python/frontend/paddlepaddle/test_forward.py | 11 ++++++++++- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index a402eaa2b06c..8bc4d77a20a3 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -1310,7 +1310,7 @@ def convert_slice(g, op, block): """Operator converter for slice.""" data = g.get_node(op.input("Input")[0]) - dims = len(block.var(op.input("Input")[0]).shape) + dims = len(infer_shape(data)) dtype = "int64" axes = op.attr("axes") @@ -1335,21 +1335,20 @@ def convert_slice(g, op, block): else: starts = op.attr("starts") starts = _expr.const(starts) + start_dtype = infer_type(starts).checked_type.dtype if isinstance(starts, _expr.Expr): starts = _op.scatter( - _op.const([0] * dims, dtype=infer_type(starts).checked_type.dtype), + _op.const([0] * dims, dtype=start_dtype), axes, starts, axis=0, ) - data_shape = shape_of(data) ends = op.input("EndsTensor") if ends: ends = g.get_node(ends[0]) elif op.input("EndsTensorList"): ends = [] - data_shape = data_shape.astype(dtype) for end_index in op.input("EndsTensorList"): end_index = g.get_node(end_index) if not isinstance(end_index, _expr.Expr): @@ -1362,9 +1361,11 @@ def convert_slice(g, op, block): ends = op.attr("ends") ends = _expr.const(ends) if isinstance(ends, _expr.Expr): + data_shape = shape_of(data, infer_type(ends).checked_type.dtype) ends = _op.scatter(data_shape, axes, ends, axis=0) - out = _op.strided_slice(data, begin=starts, end=ends) + strides = _op.const([1] * dims, dtype=start_dtype) + out = _op.strided_slice(data, begin=starts, end=ends, strides=strides) if decrease_axis: out = _op.squeeze(out, axis=decrease_axis) g.add_node(op.output("Out")[0], out) diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index 8ba52627ccdc..655e12de9330 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -924,6 +924,7 @@ def __init__(self, as_tuple=False): super().__init__() self.as_tuple = as_tuple + @paddle.jit.to_static def forward(self, inputs): return paddle.nonzero(inputs, self.as_tuple) @@ -931,7 +932,15 @@ def forward(self, inputs): verify_model(Nonzero(), x1, input_shape=[[3, 4]]) verify_model(Nonzero(True), x1, input_shape=[[3, 4]]) x2 = paddle.to_tensor([0, 1, 0, 3]) - verify_model(Nonzero(), x2, input_shape=[[3, 4]]) + verify_model( + Nonzero(), + x2, + input_shape=[ + [ + 4, + ] + ], + ) @tvm.testing.uses_gpu From 84fcb9743e7309513915912571b626fc8bbb821a Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Mon, 13 Sep 2021 15:21:35 +0800 Subject: [PATCH 074/127] add convert int_dtype to string --- python/tvm/relay/frontend/paddlepaddle.py | 36 +++++++++++++++++------ 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 665c88629517..00f215bdd514 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -80,6 +80,26 @@ def _infer_value(x, params): return x +def _convert_dtype_value(val): + """converts a Paddle type id to a string.""" + + convert_dtype_map = { + 21: "int8", + 20: "uint8", + 6: "float64", + 5: "float32", + 4: "float16", + 3: "int64", + 2: "int32", + 1: "int16", + 0: "bool", + } + if val not in convert_dtype_map: + msg = "Paddle data type value %d is not handled yet." % (val) + raise NotImplementedError(msg) + return convert_dtype_map[val] + + def convert_unary_op(g, op, block): """Operator converter for all the activation.""" @@ -162,14 +182,12 @@ def convert_assign(g, op, block): def convert_assign_value(g, op, block): """Operator converter for assign_value.""" - keys = ["fp32_values", "int32_values", "int64_values"] + keys = ["bool_values", "fp32_values", "int32_values", "int64_values"] for key in keys: value = np.array(op.attr(key)) if value is not None and value.size >= 1: break shape = op.attr("shape") - dtype = block.var(op.output("Out")[0]).dtype - dtype = str(dtype).strip().split(".")[1] value = value.reshape(shape) out = _op.const(value) g.add_node(op.output("Out")[0], out) @@ -306,8 +324,8 @@ def convert_interpolate(g, op, block): def convert_cast(g, op, block): """Operator converter for cast.""" - dtype = block.var(op.output("Out")[0]).dtype - dtype = str(dtype).strip().split(".")[1] + dtype = op.attr("out_dtype") + dtype = _convert_dtype_value(dtype) x = g.get_node(op.input("X")[0]) out = _op.cast(x, dtype=dtype) g.add_node(op.output("Out")[0], out) @@ -576,8 +594,8 @@ def convert_fill_constant(g, op, block): value = op.attr("value") shape = block.var(op.output("Out")[0]).shape - dtype = block.var(op.output("Out")[0]).dtype - dtype = str(dtype).strip().split(".")[1] + dtype = op.attr("dtype") + dtype = _convert_dtype_value(dtype) value = _expr.const(value).astype(dtype) if op.input("ValueTensor"): shape = g.get_node(op.input("ValueTensor")[0]) @@ -598,9 +616,9 @@ def convert_fill_constant_batch_size_like(g, op, block): shape = op.attr("shape") input_dim_idx = op.attr("input_dim_idx") output_dim_idx = op.attr("output_dim_idx") + dtype = op.attr("dtype") - dtype = block.var(op.output("Out")[0]).dtype - dtype = str(dtype).strip().split(".")[1] + dtype = _convert_dtype_value(dtype) input_shape = shape_of(x) batch = _op.strided_slice(input_shape, begin=[input_dim_idx], end=[input_dim_idx + 1]).astype( "int32" From 6defe8d105705d95d0cf16a6e33ca142d7506687 Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Mon, 13 Sep 2021 16:04:50 +0800 Subject: [PATCH 075/127] add logical op --- python/tvm/relay/frontend/paddlepaddle.py | 4 ++- .../frontend/paddlepaddle/test_forward.py | 34 +++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 665c88629517..cce747fe6db1 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -162,7 +162,7 @@ def convert_assign(g, op, block): def convert_assign_value(g, op, block): """Operator converter for assign_value.""" - keys = ["fp32_values", "int32_values", "int64_values"] + keys = ["bool_values", "fp32_values", "int32_values", "int64_values"] for key in keys: value = np.array(op.attr(key)) if value is not None and value.size >= 1: @@ -495,6 +495,8 @@ def convert_elementwise_op(g, op, block): "less_equal": "less_equal", "less_than": "less", "not_equal": "not_equal", + "logical_or": "logical_or", + "logical_and": "logical_and", } op_func = op_map[op.type] ipt0 = g.get_node(op.input("X")[0]) diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index cc63da231804..aca6f8f814dc 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -863,6 +863,39 @@ def leaky_relu(inputs): verify_model(leaky_relu, input_data=input_data) +@tvm.testing.uses_gpu +def test_forward_logical_op(): + class LogicalOp(nn.Layer): + def __init__(self, op_name, out=False): + super(LogicalOp, self).__init__() + self.out = out + for candidate in (paddle, paddle.nn.functional): + self.func = getattr(candidate, op_name, None) + if self.func: + break + + @paddle.jit.to_static + def forward(self, x, y): + if self.out: + out = paddle.to_tensor([True, True, True]) + z = self.func(x, y, out=out) + else: + z = self.func(x, y) + return paddle.cast(z, "int32") + + op_list = [ + "logical_or", + "logical_and", + ] + x_data = np.array([True, False], dtype=np.bool).reshape(2, 1) + y_data = np.array([True, False, True, False], dtype=np.bool).reshape(2, 2) + x = paddle.to_tensor(x_data) + y = paddle.to_tensor(y_data) + for op_name in op_list: + verify_model(LogicalOp(op_name, False), [x, y]) + verify_model(LogicalOp(op_name, True), [x, y]) + + @tvm.testing.uses_gpu def test_forward_look_up(): @paddle.jit.to_static @@ -1474,6 +1507,7 @@ def zeros2(inputs): test_forward_isinf() test_forward_layer_norm() test_forward_leaky_relu() + test_forward_logical_op() test_forward_look_up() test_forward_lstm() test_forward_matmul() From 05e97bd0e79ef167c5bde668ab311d36bf995e3a Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Mon, 13 Sep 2021 16:11:39 +0800 Subject: [PATCH 076/127] add logical op --- python/tvm/relay/frontend/paddlepaddle.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index cce747fe6db1..aa5d086c7fc0 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -1620,6 +1620,8 @@ def convert_unsqueeze(g, op, block): "log2": convert_unary_op, "log10": convert_unary_op, "log1p": convert_log1p, + "logical_and": convert_elementwise_op, + "logical_or": convert_elementwise_op, "logsumexp": convert_logsumexp, "matmul": convert_matmul, "matmul_v2": convert_matmul, From a41d64fdfb887e7ba31820d2f24a76b0a6499dbd Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Mon, 13 Sep 2021 17:10:33 +0800 Subject: [PATCH 077/127] add logical op --- python/tvm/relay/frontend/paddlepaddle.py | 16 ++++++++++++---- .../python/frontend/paddlepaddle/test_forward.py | 6 ++---- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index aa5d086c7fc0..7596beaf4a5d 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -495,8 +495,6 @@ def convert_elementwise_op(g, op, block): "less_equal": "less_equal", "less_than": "less", "not_equal": "not_equal", - "logical_or": "logical_or", - "logical_and": "logical_and", } op_func = op_map[op.type] ipt0 = g.get_node(op.input("X")[0]) @@ -784,6 +782,16 @@ def convert_log1p(g, op, block): g.add_node(op.output("Out")[0], out) +def convert_logical_op(g, op, block): + """Operator converter for logical op.""" + + ipt0 = g.get_node(op.input("X")[0]) + ipt1 = g.get_node(op.input("Y")[0]) + op_func = get_relay_op(op.type) + out = op_func(ipt0, ipt1) + g.add_node(op.output("Out")[0], out) + + def convert_logsumexp(g, op, block): """Operator converter for logsumexp.""" @@ -1620,8 +1628,8 @@ def convert_unsqueeze(g, op, block): "log2": convert_unary_op, "log10": convert_unary_op, "log1p": convert_log1p, - "logical_and": convert_elementwise_op, - "logical_or": convert_elementwise_op, + "logical_and": convert_logical_op, + "logical_or": convert_logical_op, "logsumexp": convert_logsumexp, "matmul": convert_matmul, "matmul_v2": convert_matmul, diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index aca6f8f814dc..935a17044dea 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -887,10 +887,8 @@ def forward(self, x, y): "logical_or", "logical_and", ] - x_data = np.array([True, False], dtype=np.bool).reshape(2, 1) - y_data = np.array([True, False, True, False], dtype=np.bool).reshape(2, 2) - x = paddle.to_tensor(x_data) - y = paddle.to_tensor(y_data) + x = paddle.to_tensor([True]) + y = paddle.to_tensor([True, False, True, False]) for op_name in op_list: verify_model(LogicalOp(op_name, False), [x, y]) verify_model(LogicalOp(op_name, True), [x, y]) From 409cd54fc8d2514edf4d5f55d40612a7a2c1f6b6 Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Mon, 13 Sep 2021 20:39:32 +0800 Subject: [PATCH 078/127] add expand_as erf dist op --- python/tvm/relay/frontend/paddlepaddle.py | 39 ++++++++++++++++ .../frontend/paddlepaddle/test_forward.py | 46 +++++++++++++++++++ 2 files changed, 85 insertions(+) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 7596beaf4a5d..34ed90d0a66f 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -466,6 +466,29 @@ def convert_dropout(g, op, block): g.add_node(op.output("Out")[0], out) +def convert_dist(g, op, block): + """Operator converter for dist.""" + + x = g.get_node(op.input("X")[0]) + y = g.get_node(op.input("Y")[0]) + dtype = infer_type(x).checked_type.dtype + p = op.attr("p") + + x -= y + if p == np.inf: + out = _op.reduce.max(_op.abs(x)) + elif p == np.NINF: + out = _op.reduce.min(_op.abs(x)) + else: + reci_order = _expr.const(1.0 / p, dtype=dtype) + p = _expr.const(p) + out = _op.power( + _op.reduce.sum(_op.power(_op.abs(x), p)), + reci_order, + ) + g.add_node(op.output("Out")[0], out) + + def convert_dot(g, op, block): """Operator converter for dot.""" @@ -541,6 +564,19 @@ def convert_expand(g, op, block): g.add_node(op.output("Out")[0], out) +def convert_expand_as(g, op, block): + """Operator converter for expand_as.""" + + x = g.get_node(op.input("X")[0]) + y = g.get_node(op.input("X")[0]) + x_type = infer_type(x).dtype + y_type = infer_type(y).dtype + if str(x_type) != str(y_type): + y = _op.cast(y, x_type) + out = _op.broadcast_to_like(x, y) + g.add_node(op.output("Out")[0], out) + + def convert_feed(g, op, block): """Converter for model input node.""" @@ -1588,6 +1624,7 @@ def convert_unsqueeze(g, op, block): "crop_tensor": convert_crop, "cumsum": convert_cumsum, "depthwise_conv2d": convert_conv2d, + "dist": convert_dist, "dot": convert_dot, "dropout": convert_dropout, "elementwise_add": convert_elementwise_op, @@ -1600,8 +1637,10 @@ def convert_unsqueeze(g, op, block): "elementwise_pow": convert_elementwise_op, "elementwise_floordiv": convert_elementwise_op, "equal": convert_elementwise_op, + "erf": convert_unary_op, "exp": convert_unary_op, "expand_v2": convert_expand, + "expand_as": convert_expand_as, "feed": convert_feed, "fill_any_like": convert_fill_any_like, "fill_constant": convert_fill_constant, diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index 935a17044dea..50a4b8100154 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -20,6 +20,7 @@ import numpy as np import paddle +from paddle.framework import dtype import paddle.nn as nn import tvm @@ -152,6 +153,7 @@ def forward(self, inputs): "ceil", "cos", "cosh", + "erf", "exp", "floor", "log", @@ -534,6 +536,36 @@ def forward(self, inputs): verify_model(Conv2DTranspose3(), input_data=conv2d_transpose_input_data) +@tvm.testing.uses_gpu +def test_forward_dist(): + @paddle.jit.to_static + def dist(x, y): + return paddle.dist(x, y, p=2) + + @paddle.jit.to_static + def dist2(x, y): + return paddle.dist(x, y, p=20) + + @paddle.jit.to_static + def dist3(x, y): + return paddle.dist(x, y, p=float("-inf")) + + @paddle.jit.to_static + def dist4(x, y): + return paddle.dist(x, y, p=float("inf")) + + x_shape = [10, 3] + y_shape = [ + 10, + ] + x_data = paddle.rand(x_shape, dtype="float32") + y_data = paddle.rand(y_shape, dtype="float32") + verify_model(dist, input_data=[x_data, y_data]) + verify_model(dist2, input_data=[x_data, y_data]) + verify_model(dist3, input_data=[x_data, y_data]) + verify_model(dist4, input_data=[x_data, y_data]) + + @tvm.testing.uses_gpu def test_forward_dot(): @paddle.jit.to_static @@ -576,6 +608,19 @@ def expand2(inputs): verify_model(expand2, input_data=[x_data]) +@tvm.testing.uses_gpu +def test_forward_expand_as(): + @paddle.jit.to_static + def expand_as(x, y): + z = paddle.expand(x, y) + z += y + return z + + data_x = paddle.to_tensor([1, 2, 3], dtype="int32") + data_y = paddle.to_tensor([[1, 2, 3], [4, 5, 6]], dtype="float32") + verify_model(expand_as, [data_x, data_y]) + + @tvm.testing.uses_gpu def test_forward_flatten(): @paddle.jit.to_static @@ -1491,6 +1536,7 @@ def zeros2(inputs): test_forward_dropout() test_forward_elemwise() test_forward_expand() + test_forward_expand_as() test_forward_flatten() test_forward_shape_full() test_forward_ones() From 3ea47757f9d5574472e85d49f2baa97ad7dd3184 Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Mon, 13 Sep 2021 21:03:11 +0800 Subject: [PATCH 079/127] add expand_as op --- python/tvm/relay/frontend/paddlepaddle.py | 11 ++++------- tests/python/frontend/paddlepaddle/test_forward.py | 7 +++---- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 34ed90d0a66f..f0e25169b6db 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -486,6 +486,7 @@ def convert_dist(g, op, block): _op.reduce.sum(_op.power(_op.abs(x), p)), reci_order, ) + out = _op.expand_dims(out, axis=0) g.add_node(op.output("Out")[0], out) @@ -568,12 +569,8 @@ def convert_expand_as(g, op, block): """Operator converter for expand_as.""" x = g.get_node(op.input("X")[0]) - y = g.get_node(op.input("X")[0]) - x_type = infer_type(x).dtype - y_type = infer_type(y).dtype - if str(x_type) != str(y_type): - y = _op.cast(y, x_type) - out = _op.broadcast_to_like(x, y) + target_shape = op.attr("target_shape") + out = _op.broadcast_to(x, target_shape) g.add_node(op.output("Out")[0], out) @@ -1640,7 +1637,7 @@ def convert_unsqueeze(g, op, block): "erf": convert_unary_op, "exp": convert_unary_op, "expand_v2": convert_expand, - "expand_as": convert_expand_as, + "expand_as_v2": convert_expand_as, "feed": convert_feed, "fill_any_like": convert_fill_any_like, "fill_constant": convert_fill_constant, diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index 50a4b8100154..18eac042a34e 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -555,9 +555,7 @@ def dist4(x, y): return paddle.dist(x, y, p=float("inf")) x_shape = [10, 3] - y_shape = [ - 10, - ] + y_shape = [10, 1] x_data = paddle.rand(x_shape, dtype="float32") y_data = paddle.rand(y_shape, dtype="float32") verify_model(dist, input_data=[x_data, y_data]) @@ -612,7 +610,7 @@ def expand2(inputs): def test_forward_expand_as(): @paddle.jit.to_static def expand_as(x, y): - z = paddle.expand(x, y) + z = paddle.expand_as(x, y) z += y return z @@ -1532,6 +1530,7 @@ def zeros2(inputs): test_forward_conv() test_forward_crop() test_forward_cumsum() + test_forward_dist() test_forward_dot() test_forward_dropout() test_forward_elemwise() From 0353c1b5907519a75601fac6acb81ea7d7387495 Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Mon, 13 Sep 2021 21:56:56 +0800 Subject: [PATCH 080/127] add dtype check --- tests/python/frontend/paddlepaddle/test_forward.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index 18eac042a34e..43cd810c51cb 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -39,6 +39,9 @@ def assert_shapes_match(tru, est): if tru.shape != est.shape: msg = "Output shapes {} and {} don't match" raise AssertionError(msg.format(tru.shape, est.shape)) + if tru.dtype != est.dtype: + msg = "Output dtype {} and {} don't match" + raise AssertionError(msg.format(tru.dtype, est.dtype)) def get_paddle_model(func, input_spec): From a71fdc9fa39afdfe56dd7daef03d46274598c833 Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Mon, 13 Sep 2021 22:40:25 +0800 Subject: [PATCH 081/127] add dtype check and fix dtype --- python/tvm/relay/frontend/paddlepaddle.py | 34 ++++++++++++-- .../frontend/paddlepaddle/test_forward.py | 44 ++++++++++--------- 2 files changed, 55 insertions(+), 23 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index f0e25169b6db..54ab91017d50 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -80,6 +80,26 @@ def _infer_value(x, params): return x +def _convert_dtype_value(val): + """converts a Paddle type id to a string.""" + + convert_dtype_map = { + 21: "int8", + 20: "uint8", + 6: "float64", + 5: "float32", + 4: "float16", + 3: "int64", + 2: "int32", + 1: "int16", + 0: "bool", + } + if val not in convert_dtype_map: + msg = "Paddle data type value %d is not handled yet." % (val) + raise NotImplementedError(msg) + return convert_dtype_map[val] + + def convert_unary_op(g, op, block): """Operator converter for all the activation.""" @@ -126,6 +146,8 @@ def convert_arg_max(g, op, block): axis = op.attr("axis") keepdims = op.attr("keepdims") flatten = op.attr("flatten") + dtype = op.attr("dtype") + dtype = _convert_dtype_value(dtype) x = g.get_node(op.input("X")[0]) if axis is None or flatten: @@ -133,6 +155,8 @@ def convert_arg_max(g, op, block): out = _op.argmax(x, axis=None, keepdims=True) else: out = _op.argmax(x, axis=axis, keepdims=keepdims) + if dtype != infer_type(out).checked_type.dtype: + out = _op.cast(out, dtype) g.add_node(op.output("Out")[0], out) @@ -142,6 +166,8 @@ def convert_arg_min(g, op, block): axis = op.attr("axis") keepdims = op.attr("keepdims") flatten = op.attr("flatten") + dtype = op.attr("dtype") + dtype = _convert_dtype_value(dtype) x = g.get_node(op.input("X")[0]) if axis is None or flatten: @@ -149,13 +175,15 @@ def convert_arg_min(g, op, block): out = _op.argmin(x, axis=None, keepdims=True) else: out = _op.argmin(x, axis=axis, keepdims=keepdims) + if dtype != infer_type(out).checked_type.dtype: + out = _op.cast(out, dtype) g.add_node(op.output("Out")[0], out) def convert_assign(g, op, block): """Operator converter for assign.""" - out = _op.copy(g.get_node(op.input("X")[0])) + out = g.get_node(op.input("X")[0]) g.add_node(op.output("Out")[0], out) @@ -997,7 +1025,7 @@ def convert_numel(g, op, block): """Operator converter for numel.""" input_x = g.get_node(op.input("Input")[0]) - out = _op.ndarray_size(input_x) + out = _op.ndarray_size(input_x, dtype="int64") out = _op.expand_dims(out, axis=0) g.add_node(op.output("Out")[0], out) @@ -1536,7 +1564,7 @@ def convert_topk(g, op, block): k = _infer_value(k_node, g.get_params()) else: k = op.attr("k") - outs = _op.topk(x, k=k, axis=axis, is_ascend=is_ascend, ret_type="both", dtype="int32") + outs = _op.topk(x, k=k, axis=axis, is_ascend=is_ascend, ret_type="both", dtype="int64") g.add_node(op.output("Out")[0], outs[0]) g.add_node(op.output("Indices")[0], outs[1]) diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index 43cd810c51cb..9143c8c19c70 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -37,10 +37,10 @@ def assert_shapes_match(tru, est): if tru.shape != est.shape: - msg = "Output shapes {} and {} don't match" + msg = "Paddle Output shapes {} and TVM shapes {} don't match" raise AssertionError(msg.format(tru.shape, est.shape)) if tru.dtype != est.dtype: - msg = "Output dtype {} and {} don't match" + msg = "Paddle Output dtype {} and TVM dtype {} don't match" raise AssertionError(msg.format(tru.dtype, est.dtype)) @@ -296,21 +296,22 @@ def forward(self, inputs): @tvm.testing.uses_gpu def test_forward_assign(): - @paddle.jit.to_static - def assign(inputs): - return paddle.assign(inputs) + class Assign(nn.Layer): + @paddle.jit.to_static + def forward(self, inputs): + return paddle.assign(inputs) input_shape = [2, 3] input_data = paddle.rand(input_shape, dtype="float32") verify_model( - assign, + Assign(), [ input_data, ], ) input_data2 = np.random.randint(100, size=input_shape) verify_model( - assign, + Assign(), [ input_data2, ], @@ -431,29 +432,32 @@ def crop4(inputs): @tvm.testing.uses_gpu def test_forward_cumsum(): - @paddle.jit.to_static - def cusum1(inputs): - return paddle.cumsum(inputs) + class Cusum1(nn.Layer): + @paddle.jit.to_static + def forward(inputs): + return paddle.cumsum(inputs) - @paddle.jit.to_static - def cusum2(inputs): - return paddle.cumsum(inputs, axis=0) + class Cusum2(nn.Layer): + @paddle.jit.to_static + def forward(inputs): + return paddle.cumsum(inputs, axis=0) - @paddle.jit.to_static - def cusum3(inputs): - return paddle.cumsum(inputs, axis=1) + class Cusum3(nn.Layer): + @paddle.jit.to_static + def forward(inputs): + return paddle.cumsum(inputs, axis=1) input_data = paddle.randint(0, 100, (10, 10), dtype=paddle.int32) - verify_model(cusum1, [input_data]) - verify_model(cusum1, [input_data.astype(paddle.int64)]) + verify_model(Cusum1, [input_data]) + verify_model(Cusum1, [input_data.astype(paddle.int64)]) verify_model( - cusum2, + Cusum2, [ input_data, ], ) verify_model( - cusum3, + Cusum3, [ input_data, ], From a7563707dccbbcfae5c8f0d78655358e3aa5d8ac Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Mon, 13 Sep 2021 22:43:29 +0800 Subject: [PATCH 082/127] fix cusum dtype --- tests/python/frontend/paddlepaddle/test_forward.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index 9143c8c19c70..5b89b0f84517 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -434,17 +434,17 @@ def crop4(inputs): def test_forward_cumsum(): class Cusum1(nn.Layer): @paddle.jit.to_static - def forward(inputs): + def forward(self, inputs): return paddle.cumsum(inputs) class Cusum2(nn.Layer): @paddle.jit.to_static - def forward(inputs): + def forward(self, inputs): return paddle.cumsum(inputs, axis=0) class Cusum3(nn.Layer): @paddle.jit.to_static - def forward(inputs): + def forward(self, inputs): return paddle.cumsum(inputs, axis=1) input_data = paddle.randint(0, 100, (10, 10), dtype=paddle.int32) From c1097ae167a7712ee4e341d74e3797ea4af68b9d Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Mon, 13 Sep 2021 22:47:29 +0800 Subject: [PATCH 083/127] fix cusum dtype --- tests/python/frontend/paddlepaddle/test_forward.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index 5b89b0f84517..1a6565599787 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -448,16 +448,16 @@ def forward(self, inputs): return paddle.cumsum(inputs, axis=1) input_data = paddle.randint(0, 100, (10, 10), dtype=paddle.int32) - verify_model(Cusum1, [input_data]) - verify_model(Cusum1, [input_data.astype(paddle.int64)]) + verify_model(Cusum1(), [input_data]) + verify_model(Cusum1(), [input_data.astype(paddle.int64)]) verify_model( - Cusum2, + Cusum2(), [ input_data, ], ) verify_model( - Cusum3, + Cusum3(), [ input_data, ], From d330473fa4e840a71b4404b78e4c21eaf2cf83ed Mon Sep 17 00:00:00 2001 From: wjj19950828 Date: Tue, 14 Sep 2021 14:45:23 +0800 Subject: [PATCH 084/127] fixed code format --- python/tvm/relay/frontend/paddlepaddle.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index ca96ef779e6f..47b20c8af84e 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -486,7 +486,7 @@ def convert_elementwise_op(g, op, block): "elementwise_sub": lambda x, y: x - y, "elementwise_mod": _op.mod, "elementwise_pow": _op.power, - "elementwise_floordiv": _op.floor_divide + "elementwise_floordiv": _op.floor_divide, } op_func = op_map[op.type] ipt0 = g.get_node(op.input("X")[0]) @@ -602,10 +602,12 @@ def convert_fill_constant_batch_size_like(g, op, block): dtype = block.var(op.output("Out")[0]).dtype dtype = str(dtype).strip().split(".")[1] input_shape = shape_of(x) - batch = _op.strided_slice(input_shape, begin=[input_dim_idx], end=[input_dim_idx+1]).astype("int32") + batch = _op.strided_slice(input_shape, begin=[input_dim_idx], end=[input_dim_idx + 1]).astype( + "int32" + ) shape_before = shape[:output_dim_idx] shape_before = _expr.const(shape_before, dtype="int32") - shape_after = shape[output_dim_idx+1:] + shape_after = shape[output_dim_idx + 1 :] shape_after = _expr.const(shape_after, dtype="int32") out_shape = _op.concatenate([shape_before, batch, shape_after], axis=0) @@ -1413,7 +1415,7 @@ def convert_topk(g, op, block): g.add_node(op.output("Out")[0], outs[0]) g.add_node(op.output("Indices")[0], outs[1]) - + def convert_stack(g, op, block): """Operator converter for stack.""" From 3179ba2bea3b1984524fa0dd4ae9e0f453d60ff6 Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Tue, 14 Sep 2021 16:22:59 +0800 Subject: [PATCH 085/127] add where strided_slice addn argsort op --- python/tvm/relay/frontend/paddlepaddle.py | 195 ++++++++++-------- .../frontend/paddlepaddle/test_forward.py | 153 ++++++++++---- 2 files changed, 221 insertions(+), 127 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 54ab91017d50..8314639ab0f9 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -140,6 +140,16 @@ def convert_addmm(g, op, block): g.add_node(op.output("Out")[0], out) +def convert_addn(g, op, block): + """Operator converter for sum(add_n).""" + + inputs = op.input("X") + out = g.get_node(inputs[0]) + for i in range(1, len(inputs)): + out += g.get_node(inputs[i]) + g.add_node(op.output("Out")[0], out) + + def convert_arg_max(g, op, block): """Operator converter for arg_max.""" @@ -180,6 +190,16 @@ def convert_arg_min(g, op, block): g.add_node(op.output("Out")[0], out) +def convert_argsort(g, op, block): + """Operator converter for argsort.""" + + x = g.get_node(op.inputs("X")[0]) + axis = op.attr("axis") + descending = op.attr("descending") + out = _op.argsort(x, axis, not descending, dtype="int64") + g.add_node(op.output("Indices")[0], out) + + def convert_assign(g, op, block): """Operator converter for assign.""" @@ -341,6 +361,24 @@ def convert_cast(g, op, block): g.add_node(op.output("Out")[0], out) +def convert_clip(g, op, block): + """Operator converter for clip.""" + + x = g.get_node(op.input("X")[0]) + if op.input("Min"): + Min = g.get_node(op.input("Min")[0]) + Min = infer_value(x, g.get_params()).numpy().tolist()[0] + else: + Min = op.attr("min") + if op.input("Max"): + Max = g.get_node(op.input("Max")[0]) + Max = infer_value(Max, g.get_params()).numpy().tolist()[0] + else: + Max = op.attr("max") + out = _op.clip(x, Min, Max) + g.add_node(op.output("Out")[0], out) + + def convert_concat(g, op, block): """Operator converter for concat.""" @@ -1420,118 +1458,92 @@ def convert_slice(g, op, block): data = g.get_node(op.input("Input")[0]) dims = len(infer_shape(data)) - dtype = "int64" axes = op.attr("axes") - axes = _op.const(axes) + indices = _expr.const(axes, dtype="int64") + decrease_axis = op.attr("decrease_axis") if isinstance(decrease_axis, int): decrease_axis = [decrease_axis] - starts = op.input("StartsTensor") - if starts: - starts = g.get_node(starts[0]) + if op.input("StartsTensor"): + starts = g.get_node(op.input("StartsTensor")[0]) + starts = _infer_value(starts, g.get_params()) elif op.input("StartsTensorList"): starts = [] for start_index in op.input("StartsTensorList"): - start_index = g.get_node(start_index) - if not isinstance(start_index, _expr.Expr): - start_index = _expr.const(start_index, dtype=dtype) - else: - start_index = start_index.astype(dtype) + start_index = g.get_node(start_index).astype("int64") starts.append(start_index) starts = _op.concatenate(starts, axis=0) + starts = _infer_value(starts, g.get_params()) else: starts = op.attr("starts") - starts = _expr.const(starts) - start_dtype = infer_type(starts).checked_type.dtype - if isinstance(starts, _expr.Expr): - starts = _op.scatter( - _op.const([0] * dims, dtype=start_dtype), - axes, - starts, - axis=0, - ) - ends = op.input("EndsTensor") - if ends: - ends = g.get_node(ends[0]) + if len(axes) < dims: + if isinstance(starts, _expr.Expr): + starts = _op.scatter( + _op.const([0] * dims, dtype=infer_type(starts).checked_type.dtype), + indices, + starts, + axis=0, + ) + else: + base = [0] * dims + for i, axis in enumerate(axes): + base[axis] = starts[i] + starts = base + + if op.input("EndsTensor"): + ends = g.get_node(op.input("EndsTensor")[0]) + ends = _infer_value(ends, g.get_params()) elif op.input("EndsTensorList"): ends = [] for end_index in op.input("EndsTensorList"): - end_index = g.get_node(end_index) - if not isinstance(end_index, _expr.Expr): - end_index = _expr.const(end_index, dtype=dtype) - else: - end_index = end_index.astype(dtype) + end_index = g.get_node(end_index).astype("int64") ends.append(end_index) ends = _op.concatenate(ends, axis=0) + ends = _infer_value(ends, g.get_params()) else: ends = op.attr("ends") - ends = _expr.const(ends) - if isinstance(ends, _expr.Expr): - data_shape = shape_of(data, infer_type(ends).checked_type.dtype) - ends = _op.scatter(data_shape, axes, ends, axis=0) - strides = _op.const([1] * dims, dtype=start_dtype) + if len(axes) < dims: + if isinstance(ends, _expr.Expr): + ends = _op.scatter( + _expr.const( + np.array([np.iinfo(np.int32).max] * dims), + dtype=infer_type(ends).checked_type.dtype, + ), + indices, + ends, + axis=0, + ) + else: + base = [np.iinfo(np.int32).max] * dims + for i, axis in enumerate(axes): + base[axis] = ends[i] + ends = base + + if "StridesTensor" in op.input_names and op.input("StridesTensor"): + strides = g.get_node(op.input("StridesTensor")[0]) + strides = _infer_value(strides, g.get_params()) + elif "StridesTensorList" in op.input_names and op.input("StridesTensorList"): + strides = [] + for strides_index in op.input("StridesTensorList"): + strides_index = g.get_node(strides_index).astype("int64") + strides.append(strides_index) + strides = _op.concatenate(strides, axis=0) + strides = _infer_value(strides, g.get_params()) + elif op.has_attr("strides"): + strides = op.attr("strides") + else: + strides = _op.const([1] * dims, dtype="int64") + out = _op.strided_slice(data, begin=starts, end=ends, strides=strides) if decrease_axis: out = _op.squeeze(out, axis=decrease_axis) g.add_node(op.output("Out")[0], out) -def convert_softmax(g, op, block): - """Operator converter for softmax.""" - - axis = op.attr("axis") - input_shape = block.var(op.input("X")[0]).shape - if axis < 0: - axis = len(input_shape) + axis - x = g.get_node(op.input("X")[0]) - m = _op.max(x, axis, keepdims=True) - e = _op.exp(x - m) - out = e / _op.sum(e, axis, keepdims=True) - g.add_node(op.output("Out")[0], out) - - -def convert_split(g, op, block): - """Operator converter for split.""" - - x = g.get_node(op.input("X")[0]) - axis = op.input("AxisTensor") - if axis: - axis = g.get_node(axis[0]) - axis = infer_value(axis, g.get_params()).numpy().tolist()[0] - else: - axis = op.attr("axis") - - sections = op.input("SectionsTensorList") - if sections: - tmp_section = [] - for i in sections: - i = g.get_node(i) - i = infer_value(i, g.get_params()).numpy().tolist() - tmp_section.extend(i) - sections = tmp_section - else: - sections = op.attr("sections") - if sections: - indices = [] - split_index = 0 - for i in sections[:-1]: - if i == -1: - input_shape = infer_shape(x)[axis] - i = input_shape - np.sum(sections) - 1 - split_index += i - indices.append(split_index) - else: - indices = op.attr("num") - - out = _op.split(x, indices, axis) - for i, out_i in enumerate(out): - g.add_node(op.output("Out")[i], out_i) - - def convert_square(g, op, block): """Operator converter for square.""" @@ -1625,12 +1637,23 @@ def convert_unsqueeze(g, op, block): g.add_node(op.output("Out")[0], x) +def convert_where(g, op, block): + """Operator converter for where.""" + + condition = g.get_node(op.input("Condition")[0]) + x = g.get_node(op.input("X")[0]) + y = g.get_node(op.input("Y")[0]) + out = _op.where(condition, x, y) + g.add_node(op.output("Out")[0], out) + + _convert_map = { "abs": convert_unary_op, "acos": convert_unary_op, "addmm": convert_addmm, "arg_max": convert_arg_max, "arg_min": convert_arg_min, + "argsort": convert_argsort, "asin": convert_unary_op, "assign": convert_assign, "assign_value": convert_assign_value, @@ -1641,6 +1664,7 @@ def convert_unsqueeze(g, op, block): "bmm": convert_bmm, "cast": convert_cast, "ceil": convert_unary_op, + "clip": convert_clip, "concat": convert_concat, "conv2d": convert_conv2d, "conv2d_transpose": convert_conv2d_transpose, @@ -1730,12 +1754,15 @@ def convert_unsqueeze(g, op, block): "square": convert_square, "squeeze2": convert_squeeze, "stack": convert_stack, + "strided_slice": convert_slice, + "sum": convert_addn, "tan": convert_unary_op, "tanh": convert_unary_op, "top_k_v2": convert_topk, "tile": convert_tile, "transpose2": convert_transpose, "unsqueeze2": convert_unsqueeze, + "where": convert_where, "where_index": convert_nonzero, } diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index 1a6565599787..7ba1d93a00ad 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -216,6 +216,40 @@ def addmm(input, x, y, alpha=1, beta=1): verify_model(addmm, input_data=[input_data, x_data, y_data]) +@tvm.testing.uses_gpu +def test_forward_addn(): + @paddle.jit.to_static + def addn(a, b, c): + return paddle.add_n([a, b, c]) + + @paddle.jit.to_static + def addn2(a, b): + return paddle.add_n([a, b]) + + @paddle.jit.to_static + def addn3(a): + return paddle.add_n([a]) + + input_shape = [1, 3, 10, 10] + a = paddle.rand(input_shape, dtype="float32") + b = paddle.rand(input_shape, dtype="float32") + c = paddle.rand(input_shape, dtype="float32") + verify_model(addn, [a, b, c]) + verify_model( + addn2, + [ + a, + b, + ], + ) + verify_model( + addn3, + [ + a, + ], + ) + + @tvm.testing.uses_gpu def test_forward_arange(): @paddle.jit.to_static @@ -294,6 +328,23 @@ def forward(self, inputs): verify_model(ArgMin3(), input_data=input_data) +@tvm.testing.uses_gpu +def test_forward_argsort(): + @paddle.jit.to_static + def argsort(inputs): + return paddle.argsort(inputs) + + @paddle.jit.to_static + def argsort2(inputs): + return paddle.argsort(inputs, axis=0, descending=True) + + input_shape = [2, 3, 5] + input_data = paddle.rand(input_shape, dtype="float32") + verify_model(argsort, input_data) + input_data2 = np.random.randint(100, size=input_shape) + verify_model(argsort2, input_data2) + + @tvm.testing.uses_gpu def test_forward_assign(): class Assign(nn.Layer): @@ -303,19 +354,9 @@ def forward(self, inputs): input_shape = [2, 3] input_data = paddle.rand(input_shape, dtype="float32") - verify_model( - Assign(), - [ - input_data, - ], - ) + verify_model(Assign(), [input_data]) input_data2 = np.random.randint(100, size=input_shape) - verify_model( - Assign(), - [ - input_data2, - ], - ) + verify_model(Assign(), [input_data2]) @tvm.testing.uses_gpu @@ -367,18 +408,30 @@ def cast2(inputs, dtype="int64"): input_shape = [2, 3] input_data = paddle.rand(input_shape, dtype="float32") * 100 - verify_model( - cast1, - [ - input_data, - ], - ) - verify_model( - cast2, - [ - input_data, - ], - ) + verify_model(cast1, [input_data]) + verify_model(cast2, [input_data]) + + +@tvm.testing.uses_gpu +def test_forward_clip(): + @paddle.jit.to_static + def clip(inputs): + return paddle.clip(inputs) + + @paddle.jit.to_static + def clip2(inputs): + return paddle.clip(inputs, min=3.5, max=5.0) + + @paddle.jit.to_static + def clip3(inputs): + Max = np.array([5], dtype="int32") + return paddle.clip(inputs, max=paddle.to_tensor(Max)) + + x = np.array([[1.2, 3.5], [4.5, 6.4]]) + x1 = paddle.to_tensor(x, dtype="float32") + verify_model(clip, x1) + verify_model(clip2, x1) + verify_model(clip3, paddle.to_tensor([[1, 2], [4, 6]], dtype="int32")) @tvm.testing.uses_gpu @@ -432,36 +485,26 @@ def crop4(inputs): @tvm.testing.uses_gpu def test_forward_cumsum(): - class Cusum1(nn.Layer): + class Cumsum1(nn.Layer): @paddle.jit.to_static def forward(self, inputs): return paddle.cumsum(inputs) - class Cusum2(nn.Layer): + class Cumsum2(nn.Layer): @paddle.jit.to_static def forward(self, inputs): return paddle.cumsum(inputs, axis=0) - class Cusum3(nn.Layer): + class Cumsum3(nn.Layer): @paddle.jit.to_static def forward(self, inputs): return paddle.cumsum(inputs, axis=1) input_data = paddle.randint(0, 100, (10, 10), dtype=paddle.int32) - verify_model(Cusum1(), [input_data]) - verify_model(Cusum1(), [input_data.astype(paddle.int64)]) - verify_model( - Cusum2(), - [ - input_data, - ], - ) - verify_model( - Cusum3(), - [ - input_data, - ], - ) + verify_model(Cumsum1(), input_data) + verify_model(Cumsum1(), [input_data.astype(paddle.int64)]) + verify_model(Cumsum2(), input_data) + verify_model(Cumsum3(), input_data) @tvm.testing.uses_gpu @@ -1361,13 +1404,18 @@ def slice4(inputs): x1 = paddle.to_tensor([3]) + paddle.to_tensor([1]) return inputs[:, x0:, 1:x1, :] + @paddle.jit.to_static + def slice5(inputs): + x0 = paddle.to_tensor([3]) + return inputs[0, 1::1, 2::x0, 4:10] + input_shape = [1, 3, 10, 10] input_data = paddle.rand(input_shape, dtype="float32") verify_model(slice1, input_data=input_data) verify_model(slice2, input_data=input_data) - # need op "strided_slice" - # verify_model(slice3, input_data=paddle.randn((4, 4))) + verify_model(slice3, input_data=paddle.randn((4, 4))) verify_model(slice4, input_data=input_data) + verify_model(slice5, input_data=input_data) @tvm.testing.uses_gpu @@ -1524,15 +1572,33 @@ def zeros2(inputs): verify_model(zeros2, input_data=input_data) +@tvm.testing.uses_gpu +def test_forward_where(): + class Where(nn.Layer): + @paddle.jit.to_static + def forward(self, c, x, y): + return paddle.where(c, x, y) + + x = paddle.to_tensor([0.9383, 0.1983, 3.2, 1.2]) + y = paddle.to_tensor([1.0, 1.0, 1.0, 1.0]) + verify_model(Where(), [x < 1, x, y]) + input_shape = [1, 3, 10, 10] + x = paddle.rand(input_shape, dtype="float32") + y = paddle.rand(input_shape, dtype="float32") + verify_model(Where(), [x < y, x, y]) + + if __name__ == "__main__": test_forward_add_subtract() test_forward_addmm() + test_forward_addn() test_forward_arange() test_forward_argmax() test_forward_argmin() test_forward_assign() test_forward_batch_norm() test_forward_cast() + test_forward_clip() test_forward_concat_unsqueeze() test_forward_conv() test_forward_crop() @@ -1578,3 +1644,4 @@ def zeros2(inputs): test_forward_conv_transpose() test_forward_unary_op() test_forward_zeros() + test_forward_where() From 86d9561bf6ac7f100f98790f8dc995c3934e7dee Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Tue, 14 Sep 2021 16:27:49 +0800 Subject: [PATCH 086/127] add back deleted code by mistake --- python/tvm/relay/frontend/paddlepaddle.py | 52 +++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 8314639ab0f9..620d6a015859 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -1544,6 +1544,58 @@ def convert_slice(g, op, block): g.add_node(op.output("Out")[0], out) +def convert_softmax(g, op, block): + """Operator converter for softmax.""" + + axis = op.attr("axis") + input_shape = block.var(op.input("X")[0]).shape + if axis < 0: + axis = len(input_shape) + axis + x = g.get_node(op.input("X")[0]) + m = _op.max(x, axis, keepdims=True) + e = _op.exp(x - m) + out = e / _op.sum(e, axis, keepdims=True) + g.add_node(op.output("Out")[0], out) + + +def convert_split(g, op, block): + """Operator converter for split.""" + + x = g.get_node(op.input("X")[0]) + axis = op.input("AxisTensor") + if axis: + axis = g.get_node(axis[0]) + axis = infer_value(axis, g.get_params()).numpy().tolist()[0] + else: + axis = op.attr("axis") + + sections = op.input("SectionsTensorList") + if sections: + tmp_section = [] + for i in sections: + i = g.get_node(i) + i = infer_value(i, g.get_params()).numpy().tolist() + tmp_section.extend(i) + sections = tmp_section + else: + sections = op.attr("sections") + if sections: + indices = [] + split_index = 0 + for i in sections[:-1]: + if i == -1: + input_shape = infer_shape(x)[axis] + i = input_shape - np.sum(sections) - 1 + split_index += i + indices.append(split_index) + else: + indices = op.attr("num") + + out = _op.split(x, indices, axis) + for i, out_i in enumerate(out): + g.add_node(op.output("Out")[i], out_i) + + def convert_square(g, op, block): """Operator converter for square.""" From 0590833240a04497deb9aa561abcd81da7e7358e Mon Sep 17 00:00:00 2001 From: wjj19950828 Date: Tue, 14 Sep 2021 16:53:48 +0800 Subject: [PATCH 087/127] add greater_equal isfinite and isnan ops --- python/tvm/relay/frontend/paddlepaddle.py | 20 +++ .../frontend/paddlepaddle/test_forward.py | 157 ++++++++++++------ 2 files changed, 127 insertions(+), 50 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 665c88629517..b865fefa2b1e 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -85,6 +85,8 @@ def convert_unary_op(g, op, block): op_map = { "isinf_v2": _op.isinf, + "isfinite_v2": _op.isfinite, + "isnan_v2": _op.isnan, } if op.type in op_map: unary_func = op_map[op.type] @@ -491,6 +493,7 @@ def convert_elementwise_op(g, op, block): "elementwise_floordiv": "floor_divide", "floor_mod": "floor_mod", "equal": "equal", + "greater_equal": "greater_equal", "greater_than": "greater", "less_equal": "less_equal", "less_than": "less", @@ -782,6 +785,16 @@ def convert_log1p(g, op, block): g.add_node(op.output("Out")[0], out) +def convert_logical_op(g, op, block): + """Operator converter for logical op.""" + + ipt0 = g.get_node(op.input("X")[0]) + ipt1 = g.get_node(op.input("Y")[0]) + op_func = get_relay_op(op.type) + out = op_func(ipt0, ipt1) + g.add_node(op.output("Out")[0], out) + + def convert_logsumexp(g, op, block): """Operator converter for logsumexp.""" @@ -1602,12 +1615,17 @@ def convert_unsqueeze(g, op, block): "gather": convert_gather, "gather_nd": convert_gather_nd, "gelu": convert_gelu, + "greater_equal": convert_elementwise_op, "greater_than": convert_elementwise_op, "hard_sigmoid": convert_hard_sigmoid, "hard_swish": convert_hard_swish, "index_select": convert_index_select, + "isfinite": convert_unary_op, + "isfinite_v2": convert_unary_op, "isinf": convert_unary_op, "isinf_v2": convert_unary_op, + "isnan": convert_unary_op, + "isnan_v2": convert_unary_op, "layer_norm": convert_layer_norm, "leaky_relu": convert_leaky_relu, "less_equal": convert_elementwise_op, @@ -1619,6 +1637,8 @@ def convert_unsqueeze(g, op, block): "log10": convert_unary_op, "log1p": convert_log1p, "logsumexp": convert_logsumexp, + "logical_and": convert_logical_op, + "logical_or": convert_logical_op, "matmul": convert_matmul, "matmul_v2": convert_matmul, "mul": convert_mul, diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index cc63da231804..925a8329a0e5 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -672,6 +672,7 @@ def forward(self, input1, input2): "maximum", "minimum", "equal", + "greater_equal", "greater_than", "less_equal", "less_than", @@ -777,6 +778,17 @@ def index_select2(x, index): verify_model(index_select2, input_data=[input_data, index]) +@tvm.testing.uses_gpu +def test_forward_isfinite(): + @paddle.jit.to_static + def isfinite(inputs): + return paddle.cast(paddle.isfinite(inputs), "int32") + + input_shape = [5, 5] + input_data = paddle.rand(input_shape, dtype="float32") + verify_model(isfinite, input_data=input_data) + + @tvm.testing.uses_gpu def test_forward_isinf(): @paddle.jit.to_static @@ -788,6 +800,17 @@ def isinf(inputs): verify_model(isinf, input_data=input_data) +@tvm.testing.uses_gpu +def test_forward_isnan(): + @paddle.jit.to_static + def isnan(inputs): + return paddle.cast(paddle.isnan(inputs), "int32") + + input_shape = [5, 5] + input_data = paddle.rand(input_shape, dtype="float32") + verify_model(isnan, input_data=input_data) + + @tvm.testing.uses_gpu def test_forward_interpolate(): class TestBilinear(nn.Layer): @@ -863,6 +886,37 @@ def leaky_relu(inputs): verify_model(leaky_relu, input_data=input_data) +@tvm.testing.uses_gpu +def test_forward_logical_op(): + class LogicalOp(nn.Layer): + def __init__(self, op_name, out=False): + super(LogicalOp, self).__init__() + self.out = out + for candidate in (paddle, paddle.nn.functional): + self.func = getattr(candidate, op_name, None) + if self.func: + break + + @paddle.jit.to_static + def forward(self, x, y): + if self.out: + out = paddle.to_tensor([True, True, True]) + z = self.func(x, y, out=out) + else: + z = self.func(x, y) + return paddle.cast(z, "int32") + + op_list = [ + "logical_and", + "logical_or", + ] + x = paddle.to_tensor([True]) + y = paddle.to_tensor([True, False, True, False]) + for op_name in op_list: + verify_model(LogicalOp(op_name, False), [x, y]) + verify_model(LogicalOp(op_name, True), [x, y]) + + @tvm.testing.uses_gpu def test_forward_look_up(): @paddle.jit.to_static @@ -1444,53 +1498,56 @@ def zeros2(inputs): if __name__ == "__main__": - test_forward_add_subtract() - test_forward_addmm() - test_forward_arange() - test_forward_argmax() - test_forward_argmin() - test_forward_assign() - test_forward_batch_norm() - test_forward_cast() - test_forward_concat_unsqueeze() - test_forward_conv() - test_forward_crop() - test_forward_cumsum() - test_forward_dot() - test_forward_dropout() - test_forward_elemwise() - test_forward_expand() - test_forward_flatten() - test_forward_shape_full() - test_forward_ones() - test_forward_ones_like() - test_forward_gather_assign_value() - test_forward_gather_nd() - test_forward_gelu() - test_forward_hard_sigmoid() - test_forward_hard_swish() - test_forward_index_select() - test_forward_interpolate() - test_forward_isinf() - test_forward_layer_norm() - test_forward_leaky_relu() - test_forward_look_up() - test_forward_lstm() - test_forward_matmul() - test_forward_multiply() - test_forward_nonzero() - test_forward_norm() - test_forward_pool2d() - test_forward_pad() - test_forward_pow() - test_forward_reduce_op() - test_forward_reshape() - test_forward_scale() - test_forward_slice() - test_forward_split() - test_forward_squeeze2() - test_forward_topk() - test_forward_tile() - test_forward_conv_transpose() - test_forward_unary_op() - test_forward_zeros() + # test_forward_add_subtract() + # test_forward_addmm() + # test_forward_arange() + # test_forward_argmax() + # test_forward_argmin() + # test_forward_assign() + # test_forward_batch_norm() + # test_forward_cast() + # test_forward_concat_unsqueeze() + # test_forward_conv() + # test_forward_crop() + # test_forward_cumsum() + # test_forward_dot() + # test_forward_dropout() + # test_forward_elemwise() + # test_forward_expand() + # test_forward_flatten() + # test_forward_shape_full() + # test_forward_ones() + # test_forward_ones_like() + # test_forward_gather_assign_value() + # test_forward_gather_nd() + # test_forward_gelu() + # test_forward_hard_sigmoid() + # test_forward_hard_swish() + # test_forward_index_select() + # test_forward_interpolate() + # test_forward_isfinite() + # test_forward_isinf() + # test_forward_isnan() + # test_forward_layer_norm() + # test_forward_leaky_relu() + test_forward_logical_op() + # test_forward_look_up() + # test_forward_lstm() + # test_forward_matmul() + # test_forward_multiply() + # test_forward_nonzero() + # test_forward_norm() + # test_forward_pool2d() + # test_forward_pad() + # test_forward_pow() + # test_forward_reduce_op() + # test_forward_reshape() + # test_forward_scale() + # test_forward_slice() + # test_forward_split() + # test_forward_squeeze2() + # test_forward_topk() + # test_forward_tile() + # test_forward_conv_transpose() + # test_forward_unary_op() + # test_forward_zeros() From 207a463dec1c9d2115d1c4ac110b7990a851177c Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Tue, 14 Sep 2021 18:06:54 +0800 Subject: [PATCH 088/127] clip support dynamic --- python/tvm/relay/frontend/paddlepaddle.py | 35 +++++++++++++++---- .../frontend/paddlepaddle/test_forward.py | 24 ++++++++----- 2 files changed, 43 insertions(+), 16 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 620d6a015859..c45e9988f038 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -365,17 +365,38 @@ def convert_clip(g, op, block): """Operator converter for clip.""" x = g.get_node(op.input("X")[0]) + dtype = infer_type(x).checked_type.dtype + is_dynamic = False if op.input("Min"): - Min = g.get_node(op.input("Min")[0]) - Min = infer_value(x, g.get_params()).numpy().tolist()[0] + min_value = g.get_node(op.input("Min")[0]) + min_value = _infer_value(min_value, g.get_params()) + if isinstance(min_value, _expr.Expr): + is_dynamic = True + else: + min_value = min_value[0] else: - Min = op.attr("min") + min_value = op.attr("min") if op.input("Max"): - Max = g.get_node(op.input("Max")[0]) - Max = infer_value(Max, g.get_params()).numpy().tolist()[0] + max_value = g.get_node(op.input("Max")[0]) + max_value = _infer_value(max_value, g.get_params()) + if isinstance(max_value, _expr.Expr): + if not is_dynamic: + is_dynamic = True + min_value = _op.const(min_value, dtype) + else: + max_value = max_value[0] + if is_dynamic: + max_value = _op.const(max_value, dtype) + else: + max_value = op.attr("max") + if is_dynamic: + max_value = _op.const(max_value, dtype) + + if not is_dynamic: + out = _op.clip(x, min_value, max_value) else: - Max = op.attr("max") - out = _op.clip(x, Min, Max) + out = _op.maximum(x, min_value) + out = _op.minimum(out, max_value) g.add_node(op.output("Out")[0], out) diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index 7ba1d93a00ad..e64b00e7facb 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -416,22 +416,28 @@ def cast2(inputs, dtype="int64"): def test_forward_clip(): @paddle.jit.to_static def clip(inputs): - return paddle.clip(inputs) + return paddle.clip(inputs, min=3, max=5) @paddle.jit.to_static - def clip2(inputs): - return paddle.clip(inputs, min=3.5, max=5.0) + def clip2(inputs, max_value): + return paddle.clip(inputs, max=max_value) @paddle.jit.to_static - def clip3(inputs): - Max = np.array([5], dtype="int32") - return paddle.clip(inputs, max=paddle.to_tensor(Max)) + def clip3(inputs, min_value): + return paddle.clip(inputs, min=min_value) + @paddle.jit.to_static + def clip4(inputs, min_value, max_value): + return paddle.clip(inputs, min=min_value, max=max_value) + + verify_model(clip, paddle.to_tensor([[1, 2], [4, 6]], dtype="int32")) x = np.array([[1.2, 3.5], [4.5, 6.4]]) x1 = paddle.to_tensor(x, dtype="float32") - verify_model(clip, x1) - verify_model(clip2, x1) - verify_model(clip3, paddle.to_tensor([[1, 2], [4, 6]], dtype="int32")) + min_value = paddle.to_tensor(np.array([2.1]), dtype="float32") + max_value = paddle.to_tensor(np.array([4.5]), dtype="float32") + verify_model(clip2, [x1, max_value]) + verify_model(clip3, [x1, min_value]) + verify_model(clip4, [x1, min_value, max_value]) @tvm.testing.uses_gpu From 9647a89c9b63b7e2e3737689aaa7b94c6f50b9be Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Tue, 14 Sep 2021 18:57:05 +0800 Subject: [PATCH 089/127] fix stride bug --- python/tvm/relay/frontend/paddlepaddle.py | 20 ++++++++++++++++++- .../frontend/paddlepaddle/test_forward.py | 2 +- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index c45e9988f038..5921798f83b6 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -1544,6 +1544,7 @@ def convert_slice(g, op, block): base[axis] = ends[i] ends = base + strides = None if "StridesTensor" in op.input_names and op.input("StridesTensor"): strides = g.get_node(op.input("StridesTensor")[0]) strides = _infer_value(strides, g.get_params()) @@ -1556,7 +1557,24 @@ def convert_slice(g, op, block): strides = _infer_value(strides, g.get_params()) elif op.has_attr("strides"): strides = op.attr("strides") - else: + + if len(axes) < dims: + if isinstance(strides, _expr.Expr): + strides = _op.scatter( + _expr.const( + np.array([1] * dims), + dtype=infer_type(strides).checked_type.dtype, + ), + indices, + strides, + axis=0, + ) + elif strides: + base = [1] * dims + for i, axis in enumerate(axes): + base[axis] = strides[i] + strides = base + if not strides: strides = _op.const([1] * dims, dtype="int64") out = _op.strided_slice(data, begin=starts, end=ends, strides=strides) diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index e64b00e7facb..6f2991e5925f 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -1413,7 +1413,7 @@ def slice4(inputs): @paddle.jit.to_static def slice5(inputs): x0 = paddle.to_tensor([3]) - return inputs[0, 1::1, 2::x0, 4:10] + return inputs[:, 1::1, 2::x0, 4:10] input_shape = [1, 3, 10, 10] input_data = paddle.rand(input_shape, dtype="float32") From d3f29eb7c52e19df868939cc84a8912b28f48249 Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Wed, 15 Sep 2021 11:28:29 +0800 Subject: [PATCH 090/127] add elu groupnorm hardtanh hardshrink instance_norm op --- python/tvm/relay/frontend/paddlepaddle.py | 79 ++++++++++++++++++- .../frontend/paddlepaddle/test_forward.py | 61 ++++++++++---- 2 files changed, 123 insertions(+), 17 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 5921798f83b6..6331dbdef61d 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -549,7 +549,17 @@ def convert_dropout(g, op, block): """Operator converter for dropout.""" x = g.get_node(op.input("X")[0]) - out = _op.copy(x) + g.add_node(op.output("Out")[0], x) + + +def convert_elu(g, op, block): + """Operator converter for elu.""" + + x = g.get_node(op.input("X")[0]) + dtype = infer_type(x).checked_type.dtype + alpha = op.attr("alpha") + alpha = _expr.const(alpha, dtype=dtype) + out = alpha * _op.nn.relu(_expr.const(1, dtype=dtype) - _op.exp(x)) + _op.nn.relu(x) g.add_node(op.output("Out")[0], out) @@ -802,12 +812,46 @@ def convert_gelu(g, op, block): g.add_node(op.output("Out")[0], out) +def convert_group_norm(g, op, block): + """Operator converter for group_norm.""" + + x = g.get_node(op.input("X")[0]) + num_groups = op.attr("groups") + epsilon = op.attr("epsilon") + gamma = g.get_node(op.input("Scale")[0]) + beta = g.get_node(op.input("Bias")[0]) + out = _op.nn.group_norm( + x, + gamma=gamma, + beta=beta, + num_groups=num_groups, + axis=1, + epsilon=epsilon, + center=True, + scale=True, + ) + g.add_node(op.output("Y")[0], out) + + +def convert_hard_shrink(g, op, block): + """Operator converter for hard_shrink.""" + + x = g.get_node(op.input("X")[0]) + dtype = infer_type(x).checked_type.dtype + threshold = op.attr("threshold") + threshold = _op.const(threshold, dtype) + out = _op.logical_or(x < _op.const(-1.0, dtype) * threshold, x > threshold) + out = _op.cast(out, dtype) * x + g.add_node(op.output("Out")[0], out) + + def convert_hard_sigmoid(g, op, block): """Operator converter for hard_sigmoid.""" slope = op.attr("slope") x = g.get_node(op.input("X")[0]) - out = x * _expr.const(slope) + _expr.const(0.5) + dtype = infer_type(x).checked_type.dtype + out = x * _expr.const(slope, dtype) + _expr.const(0.5, dtype) out = _op.clip(out, 0, 1) g.add_node(op.output("Out")[0], out) @@ -822,12 +866,23 @@ def convert_hard_swish(g, op, block): assert np.isclose(scale, 6.0), "Only support scale==6.0 for PaddlePaddle's hard_swish" assert np.isclose(threshold, 6.0), "Only support threshold==6.0 for PaddlePaddle's hard_swish" x = g.get_node(op.input("X")[0]) + dtype = infer_type(x).checked_type.dtype out = _op.clip(x, -1 * offset, offset) - out = out / _expr.const(threshold) + _expr.const(0.5) + out = out / _expr.const(threshold, dtype) + _expr.const(0.5, dtype) out = x * out g.add_node(op.output("Out")[0], out) +def convert_hard_tanh(g, op, block): + """Operator converter for hard_tanh.""" + + x = g.get_node(op.input("X")[0]) + t_max = op.attr("t_max") + t_min = op.attr("t_min") + out = _op.tensor.clip(x, t_min, t_max) + g.add_node(op.output("Out")[0], out) + + def convert_index_select(g, op, block): """Operator converter for index_select.""" @@ -839,6 +894,19 @@ def convert_index_select(g, op, block): g.add_node(op.output("Out")[0], out) +def convert_instance_norm(g, op, block): + """Operator converter for instance_norm.""" + + x = g.get_node(op.input("X")[0]) + gamma = g.get_node(op.input("Scale")[0]) + beta = g.get_node(op.input("Bias")[0]) + epsilon = op.attr("epsilon") + + scale = center = True + out = _op.nn.instance_norm(x, gamma, beta, axis=1, epsilon=epsilon, center=center, scale=scale) + g.add_node(op.output("Y")[0], out) + + def convert_layer_norm(g, op, block): """Operator converter for layer_norm.""" @@ -1753,6 +1821,7 @@ def convert_where(g, op, block): "bicubic_interp_v2": convert_interpolate, "bilinear_interp_v2": convert_interpolate, "bmm": convert_bmm, + "brelu": convert_hard_tanh, "cast": convert_cast, "ceil": convert_unary_op, "clip": convert_clip, @@ -1776,6 +1845,7 @@ def convert_where(g, op, block): "elementwise_min": convert_elementwise_op, "elementwise_pow": convert_elementwise_op, "elementwise_floordiv": convert_elementwise_op, + "elu": convert_elu, "equal": convert_elementwise_op, "erf": convert_unary_op, "exp": convert_unary_op, @@ -1792,9 +1862,12 @@ def convert_where(g, op, block): "gather_nd": convert_gather_nd, "gelu": convert_gelu, "greater_than": convert_elementwise_op, + "group_norm": convert_group_norm, + "hard_shrink": convert_hard_shrink, "hard_sigmoid": convert_hard_sigmoid, "hard_swish": convert_hard_swish, "index_select": convert_index_select, + "instance_norm": convert_instance_norm, "isinf": convert_unary_op, "isinf_v2": convert_unary_op, "layer_norm": convert_layer_norm, diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index 6f2991e5925f..0f25581e69ab 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -838,25 +838,42 @@ def gelu(inputs): @tvm.testing.uses_gpu -def test_forward_hard_sigmoid(): - @paddle.jit.to_static - def hard_sigmoid(inputs): - return nn.functional.hardsigmoid(inputs) +def test_forward_group_norm(): + class GroupNorm(nn.Layer): + def __init__(self, channels, groups): + super(GroupNorm).__init__() + self.group_norm = paddle.nn.GroupNorm(num_channels=channels, num_groups=groups) - input_shape = [1, 3, 10, 10] - input_data = paddle.rand(input_shape, dtype="float32") - verify_model(hard_sigmoid, input_data=input_data) + def forward(self, inputs): + self.group_norm(inputs) + + x_data = np.random.random(size=(2, 6, 2, 2)).astype("float32") + x = paddle.to_tensor(x_data) + verify_model(GroupNorm(6, 6), x) @tvm.testing.uses_gpu -def test_forward_hard_swish(): - @paddle.jit.to_static - def hard_swish(inputs): - return nn.functional.hardswish(inputs) +def test_forward_hard_activation(): + class Activation(nn.Layer): + def __init__(self, op_name): + super(Activation, self).__init__() + self.op_name_ = op_name + for candidate in (paddle.nn.functional, paddle): + self.func = getattr(candidate, op_name, None) + if self.func: + break + + @paddle.jit.to_static + def forward(self, inputs): + return self.func(inputs) input_shape = [1, 3, 10, 10] input_data = paddle.rand(input_shape, dtype="float32") - verify_model(hard_swish, input_data=input_data) + input_data_2 = paddle.randint(1, 100, input_shape, dtype="int32") + op_list = ["elu", "hardshrink", "hardsigmoid", "hardswish", "hardtanh"] + for op_name in op_list: + verify_model(Activation(op_name), input_data=input_data) + verify_model(Activation(op_name), input_data=input_data_2) @tvm.testing.uses_gpu @@ -876,6 +893,21 @@ def index_select2(x, index): verify_model(index_select2, input_data=[input_data, index]) +@tvm.testing.uses_gpu +def test_forward_instance_norm(): + class InstanceNorm(nn.Layer): + def __init__(self): + super(InstanceNorm, self).__init__() + self.instance_norm = paddle.nn.InstanceNorm2D(2) + + def forward(self, inputs): + return self.instance_norm(inputs) + + input_shape = [2, 2, 2, 3] + input_data = paddle.rand(input_shape, dtype="float32") + verify_model(InstanceNorm(), input_data) + + @tvm.testing.uses_gpu def test_forward_isinf(): @paddle.jit.to_static @@ -1622,9 +1654,10 @@ def forward(self, c, x, y): test_forward_gather_assign_value() test_forward_gather_nd() test_forward_gelu() - test_forward_hard_sigmoid() - test_forward_hard_swish() + test_forward_group_norm() + test_forward_hard_activation() test_forward_index_select() + test_forward_instance_norm() test_forward_interpolate() test_forward_isinf() test_forward_layer_norm() From 4f96c08158733f2301fcecf15e2eae835fe56044 Mon Sep 17 00:00:00 2001 From: wjj19950828 Date: Wed, 15 Sep 2021 21:26:10 +0800 Subject: [PATCH 091/127] add logical op --- python/tvm/relay/frontend/paddlepaddle.py | 11 +++++++++++ tests/python/frontend/paddlepaddle/test_forward.py | 13 +++++++++++++ 2 files changed, 24 insertions(+) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index d79367fb120b..bc1fb682eaa2 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -981,6 +981,15 @@ def convert_logical_op(g, op, block): g.add_node(op.output("Out")[0], out) +def convert_logical_not(g, op, block): + """Operator converter for logical_not op.""" + + ipt0 = g.get_node(op.input("X")[0]) + op_func = get_relay_op(op.type) + out = op_func(ipt0) + g.add_node(op.output("Out")[0], out) + + def convert_logsumexp(g, op, block): """Operator converter for logsumexp.""" @@ -1887,7 +1896,9 @@ def convert_where(g, op, block): "log10": convert_unary_op, "log1p": convert_log1p, "logical_and": convert_logical_op, + "logical_not": convert_logical_not, "logical_or": convert_logical_op, + "logical_xor": convert_logical_op, "logsumexp": convert_logsumexp, "matmul": convert_matmul, "matmul_v2": convert_matmul, diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index 39ca424002e8..8d2bd742ba7f 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -1036,8 +1036,19 @@ def forward(self, x, y): z = self.func(x, y) return paddle.cast(z, "int32") + class LogicalOp_not(LogicalOp): + @paddle.jit.to_static + def forward(self, x): + if self.out: + out = paddle.to_tensor([True, True, True]) + z = self.func(x, out=out) + else: + z = self.func(x) + return paddle.cast(z, "int32") + op_list = [ "logical_or", + "logical_xor", "logical_and", ] x = paddle.to_tensor([True]) @@ -1045,6 +1056,8 @@ def forward(self, x, y): for op_name in op_list: verify_model(LogicalOp(op_name, False), [x, y]) verify_model(LogicalOp(op_name, True), [x, y]) + verify_model(LogicalOp_not("logical_not", False), [y]) + verify_model(LogicalOp_not("logical_not", True), [y]) @tvm.testing.uses_gpu From e73f99773ca6376a8b79b8582e14271df21cb704 Mon Sep 17 00:00:00 2001 From: jiangjiajun Date: Thu, 16 Sep 2021 04:53:50 +0000 Subject: [PATCH 092/127] add control flow support --- python/tvm/relay/frontend/paddlepaddle.py | 209 ++++++++++++++---- .../frontend/paddlepaddle/test_forward.py | 15 +- 2 files changed, 179 insertions(+), 45 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index ac3860eb6ace..29f3257f18d1 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -26,6 +26,7 @@ from .. import analysis from .. import expr as _expr +from ..loops import while_loop from .. import function as _function from .. import ty as _ty from .. import op as _op @@ -41,6 +42,80 @@ __all__ = ["from_paddle"] +class ControlFlow: + """Control flow converter for PaddlePaddle.""" + + operators = [ + "while", + ] + + @classmethod + def convert_block(cls, graph, block): + for i, op in enumerate(block.ops): + if op.type in ControlFlow.operators: + raise Exception("Nested Control Flow Not Support Yet.") + else: + convert_func = _convert_map[op.type] + convert_func(graph, op, block) + + @classmethod + def convert(cls, graph, op, program): + func = getattr(cls, "convert_{}".format(op.type)) + return func(graph, op, program) + + @classmethod + def convert_while(cls, graph, op, program): + sub_block_id = op.attr("sub_block").id + sub_block = program.blocks[sub_block_id] + input_names = op.input("X") + output_names = op.output("Out") + cond_name = op.input("Condition")[0] + + for name in output_names: + if name == cond_name: + continue + if name not in input_names: + raise Exception("Output '{}' not in inputs".format(name)) + inputs = [graph.get_node(x) for x in op.input("X")] + + sub_graph = GraphProto(graph.freeze_params) + sub_graph.set_params(graph.get_params()) + cond_var = _expr.var(cond_name, shape=[1], dtype="bool") + loop_vars = list() + loop_vars.append(cond_var) + for i, name in enumerate(op.input("X")): + a = graph.get_node(name) + shape = infer_shape(graph.get_node(name)) + dtype = program.blocks[0].var(name).dtype + dtype = str(dtype).strip().split(".")[1] + var = _expr.var(name, shape=shape, dtype=dtype) + loop_vars.append(var) + + def cond_fn(*loop_inputs): + squeezed_cond = _op.squeeze(loop_inputs[0]) + return _op.equal(squeezed_cond, _expr.const(True, "bool")) + + def body_fn(*loop_inputs): + cond = loop_inputs[0] + body_inputs = loop_inputs[1:] + for i, ipt in enumerate(body_inputs): + sub_graph.add_node(input_names[i], ipt) + cls.convert_block(sub_graph, sub_block) + sub_outputs = [sub_graph.get_node(cond_name)] + sub_outputs += [sub_graph.get_node(name) for name in input_names] + return sub_outputs + + loop = while_loop(cond_fn, loop_vars, body_fn) + + init_cond = graph.get_node(op.input("Condition")[0]) + init_inputs = [graph.get_node(x) for x in op.input("X")] + init_loop_vars = init_inputs + + loop_vals = loop(init_cond, *init_loop_vars) + for i, name in enumerate(input_names): + graph.add_node(name, _expr.TupleGetItem(loop_vals, i + 1)) + + def _get_pad_size(in_size, dilated_kernel_size, stride_size): """calculate the paddings size""" @@ -55,13 +130,34 @@ def _get_pad_size(in_size, dilated_kernel_size, stride_size): return [pad_before, pad_after] +def _dtype_shape_promotion(inputs): + """promote data type and shape for list of tensors.""" + + dtype_order = ["bool", "int8", "int16", "int32", "int64", "float32", "float64"] + + ranks = [len(infer_shape(x)) for x in inputs] + if set(ranks) == set([1, 0]): + for i, r in enumerate(ranks): + if r == 0: + inputs[i] = _op.expand_dims(inputs[i], axis=0) + + dtypes = set([dtype_order.index(infer_type(x).checked_type.dtype) for x in inputs]) + if len(dtypes) == 1: + return inputs + max_dtype = dtype_order(max(dtypes)) + for i in range(len(inputs)): + if infer_type(inputs[i]).checked_type.dtype != max_dtype: + inputs[i] = inputs[i].astype(max_dtype) + return inputs + + def shape_of(x, dtype="int32"): """Get shape of a tensor""" ttype = infer_type(x).checked_type if not _ty.is_dynamic(ttype): shape = list(ttype.shape) - return _expr.const(shape, dtype) + return _expr.const(np.array(shape), dtype) return _op.shape_of(x, dtype) @@ -211,13 +307,15 @@ def convert_assign_value(g, op, block): """Operator converter for assign_value.""" keys = ["bool_values", "fp32_values", "int32_values", "int64_values"] - for key in keys: - value = np.array(op.attr(key)) + dtypes = ["bool", "float32", "int32", "int64"] + for i, key in enumerate(keys): + dtype = dtypes[i] + value = np.array(op.attr(key)).astype(dtype) if value is not None and value.size >= 1: break shape = op.attr("shape") value = value.reshape(shape) - out = _op.const(value) + out = _op.const(value, dtype=dtype) g.add_node(op.output("Out")[0], out) @@ -403,7 +501,9 @@ def convert_concat(g, op, block): inputs = [g.get_node(op.input("X")[i]) for i in range(len(op.input("X")))] axis = op.attr("axis") + inputs = _dtype_shape_promotion(inputs) out = _op.concatenate(inputs, axis=axis) + infer_shape(out) g.add_node(op.output("Out")[0], out) @@ -608,8 +708,8 @@ def convert_elementwise_op(g, op, block): op_func = op_map[op.type] ipt0 = g.get_node(op.input("X")[0]) ipt1 = g.get_node(op.input("Y")[0]) - ipt0_shape = block.var(op.input("X")[0]).shape - ipt1_shape = block.var(op.input("Y")[0]).shape + ipt0_shape = infer_shape(ipt0) + ipt1_shape = infer_shape(ipt1) axis = op.attr("axis") if len(ipt0_shape) != len(ipt1_shape): if axis < 0: @@ -697,10 +797,10 @@ def convert_fill_constant(g, op, block): dtype = op.attr("dtype") dtype = _convert_dtype_value(dtype) value = _expr.const(value).astype(dtype) - if op.input("ValueTensor"): + if "ValueTensor" in op.input_names and op.input("ValueTensor"): shape = g.get_node(op.input("ValueTensor")[0]) shape = _infer_value(shape, g.get_params()) - if op.input("ShapeTensor"): + if "ShapeTensor" in op.input_names and op.input("ShapeTensor"): shape = g.get_node(op.input("ShapeTensor")[0]) shape = _infer_value(shape, g.get_params()) @@ -729,12 +829,14 @@ def convert_fill_constant_batch_size_like(g, op, block): shape_after = _expr.const(shape_after, dtype="int32") out_shape = _op.concatenate([shape_before, batch, shape_after], axis=0) + out_shape = _infer_value(out_shape, g.get_params()) constant = _expr.const(value, dtype=dtype).astype(dtype) out = _op.full(constant, out_shape, dtype=dtype) # reshape for dynamic - shape[output_dim_idx] = -1 - out = _op.reshape(out, shape) + if isinstance(out_shape, _expr.Expr): + shape[output_dim_idx] = -1 + out = _op.reshape(out, shape) g.add_node(op.output("Out")[0], out) @@ -882,10 +984,19 @@ def convert_lookup_table(g, op, block): indices = g.get_node(op.input("Ids")[0]) padding_idx = op.attr("padding_idx") - if padding_idx != -1: - g.get_params[op.input("W")[0]][padding_idx] = 0.0 - g.add_node(op.input("W")[0], _expr.const(g.params[op.input("W")[0]])) weights = g.get_node(op.input("W")[0]) + if padding_idx != -1: + if op.input("W")[0] in g.get_params(): + weights = g.get_params(op.input("W")[0]) + weights[padding_idx] = 0.0 + weights = _expr.const(weights) + else: + shape = _infer_value(shape_of(weights), g.get_params()) + assert not isinstance(shape, _expr.Expr), "Shape of weight has to be fixed for PaddlePaddle's lookup_table" + filters = np.ones(shape).astype(infer_type(weights).checked_type.dtype) + filters[padding_idx] = 0.0 + filters = _expr.const(filters) + weights = weights * filters out = _op.take(weights, indices.astype("int32"), axis=0) g.add_node(op.output("Out")[0], out) @@ -1232,10 +1343,12 @@ def convert_range(g, op, block): params = [] for param in (start, stop, step): param = _infer_value(param, g.get_params()) + if isinstance(param, list): + param = param[0] if isinstance(param, _expr.Expr): param = _op.squeeze(param) else: - param = _op.const(param[0], dtype=dtype) + param = _op.const(param, dtype=dtype) params.append(param) out = _op.transform.arange(params[0], params[1], params[2], dtype=dtype) @@ -1284,18 +1397,14 @@ def convert_reshape(g, op, block): if input_shape: new_shape = g.get_node(input_shape[0]) elif input_shape_tensor: - tmp_shape = [] + new_shape = [] for shape_name in input_shape_tensor: shape = g.get_node(shape_name) if len(infer_shape(shape)) == 0: shape = _op.reshape(shape, [-1]) - if isinstance(shape, _expr.Constant): - tmp_shape.append(shape) - elif isinstance(shape, _expr.Expr): - tmp_shape.append(shape) - else: - tmp_shape.append(_expr.const(np.array(shape).astype("int64"))) - new_shape = _op.concatenate(tmp_shape, axis=0) + new_shape.append(shape.astype("int64")) + new_shape = _op.concatenate(new_shape, axis=0) + new_shape = _infer_value(new_shape, g.get_params()) else: new_shape = op.attr("shape") out = _op.reshape(data, new_shape) @@ -1448,6 +1557,9 @@ def convert_scale(g, op, block): if np.isclose(scale, 1.0) and np.isclose(bias, 0.0): out = x else: + x_dtype = infer_type(x).checked_type.dtype + if x_dtype != "float32": + x = x.astype("float32") if np.isclose(bias, 0.0): out = x * _expr.const(np.array(scale).astype("float32")) elif np.isclose(scale, 1.0): @@ -1461,6 +1573,8 @@ def convert_scale(g, op, block): out = (x + _expr.const(np.array(bias).astype("float32"))) * _expr.const( np.array(scale).astype("float32") ) + if x_dtype != "float32": + out = out.astype(x_dtype) g.add_node(op.output("Out")[0], out) @@ -1468,7 +1582,7 @@ def convert_shape(g, op, block): """Operator converter for shape.""" x = g.get_node(op.input("Input")[0]) - out = _op.shape_of(x) + out = shape_of(x) g.add_node(op.output("Out")[0], out) @@ -1674,10 +1788,11 @@ def convert_topk(g, op, block): def convert_stack(g, op, block): """Operator converter for stack.""" - x = op.input("X") - x = [g.get_node(i) for i in x] + inputs = op.input("X") + inputs = [g.get_node(i) for i in inputs] axis = op.attr("axis") - out = _op.stack(x, axis) + inputs = _dtype_shape_promotion(inputs) + out = _op.stack(inputs, axis) g.add_node(op.output("Y")[0], out) @@ -1859,15 +1974,16 @@ def convert_where(g, op, block): class GraphProto: """A helper class for handling relay functions from PaddlePaddle model.""" - def __init__(self): + def __init__(self, freeze_params=False): self.nodes = {} self.params = {} self.shape_dict = None + self.freeze_params = freeze_params def get_node(self, name): """get node from graph""" - assert name in self.nodes + assert name in self.nodes, "Node: {} not found".format(name) return self.nodes[name] def add_node(self, name, node): @@ -1885,6 +2001,11 @@ def get_params(self, name=None): assert name in self.params return self.params[name] + def set_params(self, params): + """set params for graph""" + + self.params = params + def extract_parameters(self, program, scope=None): """Extract all the weights from PaddlePaddle program.""" @@ -1900,7 +2021,10 @@ def extract_parameters(self, program, scope=None): self.params[name] = scope[name] else: self.params[name] = np.array(scope.var(name).get_tensor()) - self.nodes[name] = _expr.const(self.params[name]) + if self.freeze_params: + self.nodes[name] = _expr.const(self.params[name]) + else: + self.nodes[name] = _expr.var(name, shape=self.params[name].shape, dtype=str(self.params[name].dtype)) def check_input_shape(self, op, block): """Check the shape information of model's inputs, fixed shape is recommended.""" @@ -1923,6 +2047,8 @@ def check_unsupported_ops(self, program): for op in block.ops: if op.type == "fetch": continue + if op.type in ControlFlow.operators: + continue if op.type not in _convert_map: unsupported_ops.add(op.type) if len(unsupported_ops) > 0: @@ -1936,12 +2062,15 @@ def ops_to_relay(self, program, input_specs=None): if input_specs is not None: for input_spec in input_specs: convert_feed(self, input_spec, None) - for block in program.blocks: - for op in block.ops: - if op.type == "fetch": - continue + global_block = program.blocks[0] + for i, op in enumerate(global_block.ops): + if op.type == "fetch": + continue + if op.type in ControlFlow.operators: + ControlFlow.convert(self, op, program) + else: convert_func = _convert_map[op.type] - convert_func(self, op, block) + convert_func(self, op, global_block) def from_program(self, program, shape_dict, scope): """Construct the TVM relay expression from PaddlePaddle program.""" @@ -1961,12 +2090,14 @@ def from_program(self, program, shape_dict, scope): if op.type == "fetch": output_names.append(op.input("X")[0]) - outputs = [self.nodes[name] for name in output_names] + outputs = [self.get_node(name) for name in output_names] outputs = outputs[0] if len(outputs) == 1 else _expr.Tuple(outputs) free_vars = analysis.free_vars(outputs) func = _function.Function(free_vars, outputs) mod = IRModule.from_expr(func) + if self.freeze_params: + self.params = {} return mod, self.params def from_translated_layer(self, layer, shape_dict): @@ -1985,16 +2116,18 @@ def from_translated_layer(self, layer, shape_dict): output_names = [x.name for x in layer._output_spec()] - outputs = [self.nodes[name] for name in output_names] + outputs = [self.get_node(name) for name in output_names] outputs = outputs[0] if len(outputs) == 1 else _expr.Tuple(outputs) free_vars = analysis.free_vars(outputs) func = _function.Function(free_vars, outputs) mod = IRModule.from_expr(func) + if self.freeze_params: + self.params = {} return mod, self.params -def from_paddle(program_or_layer, shape_dict=None, scope=None): +def from_paddle(program_or_layer, shape_dict=None, scope=None, freeze_params=False): """Convert a PaddlePaddle model into an equivalent Relay Function. PaddlePaddle Program/TranslatedLayer represent the computation graph of PaddlePaddle model, and PaddlePaddle scope stores all the @@ -2003,7 +2136,7 @@ def from_paddle(program_or_layer, shape_dict=None, scope=None): import paddle - g = GraphProto() + g = GraphProto(freeze_params) if isinstance(program_or_layer, paddle.jit.TranslatedLayer): # model is loaded by `paddle.jit.load` mod, params = g.from_translated_layer(program_or_layer, shape_dict) diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index 6f2991e5925f..08a416f40770 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -115,9 +115,10 @@ def verify_model(func, input_data, rtol=1e-5, atol=1e-5, input_shape=None): mod, params = relay.frontend.from_paddle(baseline_model, input_shape_dict) parms_num = min(len(input_names), len(mod["main"].params)) compiled_names = [] - for arg in mod["main"].params[:parms_num]: - assert arg.name_hint in input_names - compiled_names.append(arg.name_hint) + for arg in mod["main"].params: + assert arg.name_hint in input_names or arg.name_hint in params + if arg.name_hint in input_names: + compiled_names.append(arg.name_hint) with tvm.transform.PassContext(opt_level=3): for target, dev in tvm.testing.enabled_targets(): @@ -1417,10 +1418,10 @@ def slice5(inputs): input_shape = [1, 3, 10, 10] input_data = paddle.rand(input_shape, dtype="float32") - verify_model(slice1, input_data=input_data) - verify_model(slice2, input_data=input_data) - verify_model(slice3, input_data=paddle.randn((4, 4))) - verify_model(slice4, input_data=input_data) + #verify_model(slice1, input_data=input_data) + #verify_model(slice2, input_data=input_data) + #verify_model(slice3, input_data=paddle.randn((4, 4))) + #verify_model(slice4, input_data=input_data) verify_model(slice5, input_data=input_data) From ad15233b13b303c843abd5a1165af85c51993feb Mon Sep 17 00:00:00 2001 From: jiangjiajun Date: Thu, 16 Sep 2021 07:18:21 +0000 Subject: [PATCH 093/127] Add control flow support --- python/tvm/relay/frontend/paddlepaddle.py | 29 +++++++ .../frontend/paddlepaddle/test_forward.py | 81 ++++++++++++++----- 2 files changed, 90 insertions(+), 20 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 5a7e73ddc0b1..97dfd8dcba61 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -25,6 +25,7 @@ from tvm.ir import IRModule from .. import analysis +from .. import ty as _ty from .. import expr as _expr from ..loops import while_loop from .. import function as _function @@ -786,6 +787,9 @@ def convert_feed(g, op, block): ipt_name = op.name if g.shape_dict is not None: ipt_shape = g.shape_dict[ipt_name] + for i, s in enumerate(ipt_shape): + if s < 0: + ipt_shape[i] = _ty.Any() out = new_var(ipt_name, shape=ipt_shape, dtype=ipt_dtype) g.add_node(ipt_name, out) @@ -1101,6 +1105,29 @@ def convert_logical_not(g, op, block): g.add_node(op.output("Out")[0], out) +def convert_logsigmoid(g, op, block): + """Operator converter for logsigmoid.""" + + x = g.get_node(op.input("X")[0]) + out = _op.log(_op.tensor.sigmoid(x)) + g.add_node(op.output("Out")[0], out) + + +def convert_logsoftmax(g, op, block): + """Operator converter for logsoftmax.""" + + x = g.get_node(op.input("X")[0]) + axis = op.attr("axis") + ndim = len(infer_shape(x)) + if axis < 0: + axis += ndim + m = _op.max(x, [axis], keepdims=True) + e = _op.exp(x - m) + s = _op.sum(e, [axis], keepdims=True) + out = x - m - _op.log(s) + g.add_node(op.output("Out")[0], out) + + def convert_logsumexp(g, op, block): """Operator converter for logsumexp.""" @@ -2014,6 +2041,8 @@ def convert_where(g, op, block): "logical_not": convert_logical_not, "logical_or": convert_logical_op, "logical_xor": convert_logical_op, + "logsigmoid": convert_logsigmoid, + "log_softmax": convert_logsoftmax, "logsumexp": convert_logsumexp, "matmul": convert_matmul, "matmul_v2": convert_matmul, diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index 34b9921d5449..4fb5cff394c3 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -135,10 +135,10 @@ def verify_model(func, input_data, rtol=1e-5, atol=1e-5, input_shape=None): @tvm.testing.uses_gpu -def test_forward_unary_op(): - class UnaryOp(nn.Layer): +def test_forward_math(): + class MathOp(nn.Layer): def __init__(self, op_name): - super(UnaryOp, self).__init__() + super(MathOp, self).__init__() for candidate in (paddle, paddle.nn.functional): self.func = getattr(candidate, op_name, None) if self.func: @@ -166,16 +166,14 @@ def forward(self, inputs): "log1p", "numel", "reciprocal", - "relu", "rsqrt", - "sigmoid", "sin", "square", "tan", "tanh", ] for op_name in op_list: - verify_model(UnaryOp(op_name), input_data) + verify_model(MathOp(op_name), input_data) @tvm.testing.uses_gpu @@ -516,7 +514,6 @@ def forward(self, inputs): @tvm.testing.uses_gpu def test_forward_conv(): - conv2d_input_shape = [1, 3, 10, 10] class Conv2D1(nn.Layer): def __init__(self): @@ -528,6 +525,7 @@ def __init__(self): def forward(self, inputs): return self.softmax(self.conv(inputs)) + class Conv2D2(nn.Layer): def __init__(self): super(Conv2D2, self).__init__() @@ -538,9 +536,32 @@ def __init__(self): def forward(self, inputs): return self.softmax(self.conv(inputs)) + + class Conv2D3(nn.Layer): + def __init__(self): + super(Conv2D3, self).__init__() + self.conv = nn.Conv2D(3, 6, 7, groups=3, bias_attr=False, padding="SAME") + + @paddle.jit.to_static + def forward(self, inputs): + return self.conv(inputs) + + + class Conv2D4(nn.Layer): + def __init__(self): + super(Conv2D4, self).__init__() + self.conv = nn.Conv2D(3, 6, 7, groups=3, bias_attr=False, padding=[1, 2, 0, 1], stride=2, dilation=2) + + @paddle.jit.to_static + def forward(self, inputs): + return self.conv(inputs) + + conv2d_input_shape = [1, 3, 112, 112] conv2d_input_data = paddle.rand(conv2d_input_shape, dtype="float32") verify_model(Conv2D1(), input_data=conv2d_input_data) verify_model(Conv2D2(), input_data=conv2d_input_data) + verify_model(Conv2D3(), input_data=conv2d_input_data) + verify_model(Conv2D4(), input_data=conv2d_input_data) @tvm.testing.uses_gpu @@ -843,19 +864,19 @@ def gelu(inputs): def test_forward_group_norm(): class GroupNorm(nn.Layer): def __init__(self, channels, groups): - super(GroupNorm).__init__() + super(GroupNorm, self).__init__() self.group_norm = paddle.nn.GroupNorm(num_channels=channels, num_groups=groups) def forward(self, inputs): - self.group_norm(inputs) + return self.group_norm(inputs) - x_data = np.random.random(size=(2, 6, 2, 2)).astype("float32") - x = paddle.to_tensor(x_data) + input_shape = [2, 6, 2, 2] + x = paddle.rand(input_shape, dtype="float32") verify_model(GroupNorm(6, 6), x) @tvm.testing.uses_gpu -def test_forward_hard_activation(): +def test_forward_activation(): class Activation(nn.Layer): def __init__(self, op_name): super(Activation, self).__init__() @@ -871,11 +892,11 @@ def forward(self, inputs): input_shape = [1, 3, 10, 10] input_data = paddle.rand(input_shape, dtype="float32") - input_data_2 = paddle.randint(1, 100, input_shape, dtype="int32") - op_list = ["elu", "hardshrink", "hardsigmoid", "hardswish", "hardtanh"] + input_data_2 = paddle.rand(1, 100, input_shape).astype("float16") + op_list = ["elu", "hardshrink", "hardsigmoid", "hardswish", "hardtanh", "relu", "sigmoid"] for op_name in op_list: verify_model(Activation(op_name), input_data=input_data) - verify_model(Activation(op_name), input_data=input_data_2) + verify_model(Activation(op_name), input_data=input_data_2, rtol=1e-3, atol=1e-3) @tvm.testing.uses_gpu @@ -1485,10 +1506,10 @@ def slice5(inputs): input_shape = [1, 3, 10, 10] input_data = paddle.rand(input_shape, dtype="float32") - #verify_model(slice1, input_data=input_data) - #verify_model(slice2, input_data=input_data) - #verify_model(slice3, input_data=paddle.randn((4, 4))) - #verify_model(slice4, input_data=input_data) + verify_model(slice1, input_data=input_data) + verify_model(slice2, input_data=input_data) + verify_model(slice3, input_data=paddle.randn((4, 4))) + verify_model(slice4, input_data=input_data) verify_model(slice5, input_data=input_data) @@ -1662,6 +1683,24 @@ def forward(self, c, x, y): verify_model(Where(), [x < y, x, y]) +@tvm.testing.uses_gpu +def test_forward_while(): + class While(nn.Layer): + def __init__(self): + super(While, self).__init__() + + def forward(self, x): + s = paddle.shape(x) + i = paddle.slice(s, axes=[0], starts=[0], ends=[1]) + y = paddle.to_tensor(np.array([5]).astype("int32")) + while i < y: + i *= np.array([3], dtype="int32") + return i + + input_data1 = paddle.rand([1, 3, 224, 224], dtype="float32") + verify_model(While(), input_data=[input_data1], input_shape=[[-1, 3, -1, -1]]) + + if __name__ == "__main__": test_forward_add_subtract() test_forward_addmm() @@ -1691,7 +1730,8 @@ def forward(self, c, x, y): test_forward_gather_nd() test_forward_gelu() test_forward_group_norm() - test_forward_hard_activation() + test_forward_math() + test_forward_activation() test_forward_index_select() test_forward_instance_norm() test_forward_interpolate() @@ -1720,3 +1760,4 @@ def forward(self, c, x, y): test_forward_unary_op() test_forward_zeros() test_forward_where() + test_forward_while() From 5180d28e681b7ec6934bf391333c5149400f8207 Mon Sep 17 00:00:00 2001 From: jiangjiajun Date: Thu, 16 Sep 2021 07:24:01 +0000 Subject: [PATCH 094/127] remove useless code --- python/tvm/relay/frontend/paddlepaddle.py | 1 - 1 file changed, 1 deletion(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 97dfd8dcba61..34cd2a26ef22 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -506,7 +506,6 @@ def convert_concat(g, op, block): axis = op.attr("axis") inputs = _dtype_shape_promotion(inputs) out = _op.concatenate(inputs, axis=axis) - infer_shape(out) g.add_node(op.output("Out")[0], out) From 13edb27a6479b096501821ba5c43e0e847ab0a0e Mon Sep 17 00:00:00 2001 From: jiangjiajun Date: Thu, 16 Sep 2021 08:43:05 +0000 Subject: [PATCH 095/127] code format and remove wrong code --- python/tvm/relay/frontend/paddlepaddle.py | 9 ++++++--- tests/python/frontend/paddlepaddle/test_forward.py | 4 ++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 34cd2a26ef22..b29d97f6aff0 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -85,7 +85,6 @@ def convert_while(cls, graph, op, program): loop_vars = list() loop_vars.append(cond_var) for i, name in enumerate(op.input("X")): - a = graph.get_node(name) shape = infer_shape(graph.get_node(name)) dtype = program.blocks[0].var(name).dtype dtype = str(dtype).strip().split(".")[1] @@ -1066,7 +1065,9 @@ def convert_lookup_table(g, op, block): weights = _expr.const(weights) else: shape = _infer_value(shape_of(weights), g.get_params()) - assert not isinstance(shape, _expr.Expr), "Shape of weight has to be fixed for PaddlePaddle's lookup_table" + assert not isinstance( + shape, _expr.Expr + ), "Shape of weight has to be fixed for PaddlePaddle's lookup_table" filters = np.ones(shape).astype(infer_type(weights).checked_type.dtype) filters[padding_idx] = 0.0 filters = _expr.const(filters) @@ -2144,7 +2145,9 @@ def extract_parameters(self, program, scope=None): if self.freeze_params: self.nodes[name] = _expr.const(self.params[name]) else: - self.nodes[name] = _expr.var(name, shape=self.params[name].shape, dtype=str(self.params[name].dtype)) + self.nodes[name] = _expr.var( + name, shape=self.params[name].shape, dtype=str(self.params[name].dtype) + ) def check_input_shape(self, op, block): """Check the shape information of model's inputs, fixed shape is recommended.""" diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index 4fb5cff394c3..1e4eacd9056b 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -892,7 +892,7 @@ def forward(self, inputs): input_shape = [1, 3, 10, 10] input_data = paddle.rand(input_shape, dtype="float32") - input_data_2 = paddle.rand(1, 100, input_shape).astype("float16") + input_data_2 = paddle.rand(input_shape).astype("float16") op_list = ["elu", "hardshrink", "hardsigmoid", "hardswish", "hardtanh", "relu", "sigmoid"] for op_name in op_list: verify_model(Activation(op_name), input_data=input_data) @@ -1757,7 +1757,7 @@ def forward(self, x): test_forward_topk() test_forward_tile() test_forward_conv_transpose() - test_forward_unary_op() + test_forward_math() test_forward_zeros() test_forward_where() test_forward_while() From f0b41fc207d2557dcbcd4d76b11cfdbc183c03bb Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Thu, 16 Sep 2021 18:01:19 +0800 Subject: [PATCH 096/127] add PixelShuffle PRELU RELU6 SELU op --- python/tvm/relay/frontend/paddlepaddle.py | 52 ++++++++++++++- .../frontend/paddlepaddle/test_forward.py | 65 ++++++++++++++++--- 2 files changed, 108 insertions(+), 9 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index b29d97f6aff0..316158ca6b51 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -20,6 +20,7 @@ import warnings import numpy as np +from paddle.nn.functional.common import alpha_dropout import tvm from tvm.ir import IRModule @@ -1401,17 +1402,43 @@ def convert_padding(g, op, block): g.add_node(op.output("Out")[0], out) +def convert_pixel_shuffle(g, op, block): + """Operator converter for pixel_shuffle.""" + + x = g.get_node(op.input("X")[0]) + upscale_factor = op.attr("upscale_factor") + out = _op.nn.depth_to_space(x, upscale_factor, mode="CRD") + g.add_node(op.output("Out")[0], out) + + def convert_pow(g, op, block): """Operator converter for pow.""" x = g.get_node(op.input("X")[0]) factor = op.attr("factor") factor = _expr.const(factor, dtype="float32").astype("float32") - out = _op.power(x, factor) g.add_node(op.output("Out")[0], out) +def convert_prelu(g, op, block): + """Operator converter for prelu.""" + + x = g.get_node(op.input("X")[0]) + alpha = g.get_node(op.input("Alpha")[0]) + ndims = len(infer_shape(x)) + axis = 0 if ndims <= 1 else 1 + mode = op.attr("mode") + if mode == "all": + if ndims == 1: + shape = _op.strided_slice(shape_of(x), [0], [1]) + else: + shape = _op.strided_slice(shape_of(x), [1], [2]) + alpha = _op.broadcast_to(alpha, shape) + out = _op.nn.prelu(x, alpha, axis) + g.add_node(op.output("Out")[0], out) + + def convert_norm(g, op, block): """Operator converter for norm.""" @@ -1495,6 +1522,14 @@ def convert_reduce(g, op, block): g.add_node(op.output("Out")[0], out) +def convert_relu6(g, op, block): + """Operator converter for relu6.""" + + x = g.get_node(op.input("X")[0]) + out = _op.clip(x, 0.0, 6.0) + g.add_node(op.output("Out")[0], out) + + def convert_reshape(g, op, block): """Operator converter for reshape.""" @@ -1685,6 +1720,17 @@ def convert_scale(g, op, block): g.add_node(op.output("Out")[0], out) +def convert_selu(g, op, block): + """Operator converter for selu.""" + + x = g.get_node(op.input("Input")[0]) + dtype = infer_type(x).checked_type.dtype + alpha = _op.const(op.attr("alpha"), dtype) + scale = _op.const(op.attr("scale"), dtype) + out = scale * (alpha * _op.nn.relu(_expr.const(1.0, dtype=dtype) - _op.exp(x)) + _op.nn.relu(x)) + g.add_node(op.output("Out")[0], out) + + def convert_shape(g, op, block): """Operator converter for shape.""" @@ -2053,7 +2099,9 @@ def convert_where(g, op, block): "pad1d": convert_padding, "pad2d": convert_padding, "pad3d": convert_padding, + "pixel_shuffle": convert_pixel_shuffle, "pow": convert_pow, + "prelu": convert_prelu, "p_norm": convert_norm, "range": convert_range, "reciprocal": convert_reciprocal, @@ -2065,10 +2113,12 @@ def convert_where(g, op, block): "reduce_sum": convert_reduce, "reduce_mean": convert_reduce, "relu": convert_unary_op, + "relu6": convert_relu6, "reshape2": convert_reshape, "rnn": convert_rnn, "rsqrt": convert_unary_op, "scale": convert_scale, + "selu": convert_selu, "shape": convert_shape, "sigmoid": convert_unary_op, "sin": convert_unary_op, diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index 1e4eacd9056b..426515342421 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -514,7 +514,6 @@ def forward(self, inputs): @tvm.testing.uses_gpu def test_forward_conv(): - class Conv2D1(nn.Layer): def __init__(self): super(Conv2D1, self).__init__() @@ -525,7 +524,6 @@ def __init__(self): def forward(self, inputs): return self.softmax(self.conv(inputs)) - class Conv2D2(nn.Layer): def __init__(self): super(Conv2D2, self).__init__() @@ -536,7 +534,6 @@ def __init__(self): def forward(self, inputs): return self.softmax(self.conv(inputs)) - class Conv2D3(nn.Layer): def __init__(self): super(Conv2D3, self).__init__() @@ -546,11 +543,12 @@ def __init__(self): def forward(self, inputs): return self.conv(inputs) - class Conv2D4(nn.Layer): def __init__(self): super(Conv2D4, self).__init__() - self.conv = nn.Conv2D(3, 6, 7, groups=3, bias_attr=False, padding=[1, 2, 0, 1], stride=2, dilation=2) + self.conv = nn.Conv2D( + 3, 6, 7, groups=3, bias_attr=False, padding=[1, 2, 0, 1], stride=2, dilation=2 + ) @paddle.jit.to_static def forward(self, inputs): @@ -891,9 +889,21 @@ def forward(self, inputs): return self.func(inputs) input_shape = [1, 3, 10, 10] - input_data = paddle.rand(input_shape, dtype="float32") - input_data_2 = paddle.rand(input_shape).astype("float16") - op_list = ["elu", "hardshrink", "hardsigmoid", "hardswish", "hardtanh", "relu", "sigmoid"] + input_data = paddle.normal(shape=input_shape) * 10.0 + input_data_2 = paddle.normal(shape=input_shape).astype("float16") * 10.0 + op_list = [ + "elu", + "hardshrink", + "hardsigmoid", + "hardswish", + "hardtanh", + "log_sigmoid", + "log_softmax", + "relu", + "relu6", + "selu", + "sigmoid", + ] for op_name in op_list: verify_model(Activation(op_name), input_data=input_data) verify_model(Activation(op_name), input_data=input_data_2, rtol=1e-3, atol=1e-3) @@ -1326,6 +1336,43 @@ def pad4(inputs): verify_model(pad4, input_data=input_data) +@tvm.testing.uses_gpu +def test_forward_pixel_shuffle(): + class PixelShuffle(nn.Layer): + def __init__(self, upscale_factor): + super(PixelShuffle, self).__init__() + self.pixel_shuffle = paddle.nn.PixelShuffle(upscale_factor) + + @paddle.jit.to_static + def forward(self, x): + return self.pixel_shuffle(x) + + x = paddle.rand([2, 9, 5, 5], dtype="float32") + verify_model(PixelShuffle(3), x) + x2 = paddle.rand([3, 8, 9, 9], dtype="float32") + verify_model(PixelShuffle(2), x2) + + +@tvm.testing.uses_gpu +def test_forward_prelu(): + class PRelu(nn.Layer): + @paddle.jit.to_static + def forward(self, x, w): + return paddle.nn.functional.prelu(x, w) + + x = paddle.normal(shape=[4, 3, 5, 5]) + w = paddle.to_tensor( + np.array( + [ + 0.25, + ] + ).astype("float32") + ) + verify_model(PRelu(), [x, w]) + w2 = paddle.to_tensor(np.array([0.25, 0.5, 0.8]).astype("float32")) + verify_model(PRelu(), [x, w2]) + + @tvm.testing.uses_gpu def test_forward_pow(): class Pow(nn.Layer): @@ -1747,6 +1794,8 @@ def forward(self, x): test_forward_norm() test_forward_pool2d() test_forward_pad() + test_forward_pixel_shuffle() + test_forward_prelu() test_forward_pow() test_forward_reduce_op() test_forward_reshape() From 7e47d36ced8581e44a2f5109d661beb9da44cb10 Mon Sep 17 00:00:00 2001 From: wjj19950828 Date: Thu, 16 Sep 2021 19:15:19 +0800 Subject: [PATCH 097/127] add ops and testcases --- python/tvm/relay/frontend/paddlepaddle.py | 26 +- .../frontend/paddlepaddle/test_forward.py | 224 ++++++++++++++++-- 2 files changed, 227 insertions(+), 23 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index bc1fb682eaa2..49c52cb001d3 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -195,11 +195,14 @@ def convert_arg_min(g, op, block): def convert_argsort(g, op, block): """Operator converter for argsort.""" - x = g.get_node(op.inputs("X")[0]) + x = g.get_node(op.input("X")[0]) axis = op.attr("axis") descending = op.attr("descending") - out = _op.argsort(x, axis, not descending, dtype="int64") - g.add_node(op.output("Indices")[0], out) + + out = _op.sort(x, axis, not descending) + out_indice = _op.argsort(x, axis, not descending, dtype="int64") + g.add_node(op.output("Out")[0], out) + g.add_node(op.output("Indices")[0], out_indice) def convert_assign(g, op, block): @@ -1158,6 +1161,18 @@ def convert_mul(g, op, block): g.add_node(op.output("Out")[0], out) +def convert_mv(g, op, block): + """Operator converter for mv.""" + + x = g.get_node(op.input("X")[0]) + y = g.get_node(op.input("Vec")[0]) + y = _op.expand_dims(y, axis=-1) + y = _op.transpose(y) + out = _op.nn.dense(x, y) + out = _op.squeeze(out, axis=[-1]) + g.add_node(op.output("Out")[0], out) + + def convert_numel(g, op, block): """Operator converter for numel.""" @@ -1902,6 +1917,7 @@ def convert_where(g, op, block): "logsumexp": convert_logsumexp, "matmul": convert_matmul, "matmul_v2": convert_matmul, + "mv": convert_mv, "mul": convert_mul, "nearest_interp_v2": convert_interpolate, "not_equal": convert_elementwise_op, @@ -1923,15 +1939,19 @@ def convert_where(g, op, block): "relu": convert_unary_op, "reshape2": convert_reshape, "rnn": convert_rnn, + "round": convert_unary_op, "rsqrt": convert_unary_op, "scale": convert_scale, "shape": convert_shape, "sigmoid": convert_unary_op, + "sign": convert_unary_op, "sin": convert_unary_op, + "sinh": convert_unary_op, "size": convert_numel, "slice": convert_slice, "softmax": convert_softmax, "split": convert_split, + "sqrt": convert_unary_op, "square": convert_square, "squeeze2": convert_squeeze, "stack": convert_stack, diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index 8d2bd742ba7f..8bf0f5661380 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -48,6 +48,7 @@ def get_paddle_model(func, input_spec): global PADDLE_TEST_DATA_ROOT_PATH model_path = Path(PADDLE_TEST_DATA_ROOT_PATH, "model") paddle.jit.save(func, str(model_path), input_spec=input_spec) + paddle.jit.save(func, "/paddle/pr_for_tvm/0905/tvm/inference_model_test/inference", input_spec=input_spec) baseline_model = paddle.jit.load(str(model_path)) shutil.rmtree(str(PADDLE_TEST_DATA_ROOT_PATH)) @@ -166,10 +167,14 @@ def forward(self, inputs): "numel", "reciprocal", "relu", + "round", "rsqrt", "sigmoid", + "sign", "sin", + "sinh", "square", + "sqrt", "tan", "tanh", ] @@ -1152,6 +1157,45 @@ def forward(self, input1, input2): verify_model(MatMul1(), input_data=[input_data1, input_data2]) +@tvm.testing.uses_gpu +def test_forward_mm(): + class Mm(nn.Layer): + def forward(self, input1, input2): + return paddle.mm(input1, input2) + + # matrix x vector + input_data1 = paddle.randn((3, 4), dtype="float32") + input_data2 = paddle.randn((4,), dtype="float32") + verify_model(Mm(), input_data=[input_data1, input_data2]) + + # matrix x matrix + input_data1 = paddle.randn((5, 4), dtype="float32") + input_data2 = paddle.randn((4, 5), dtype="float32") + verify_model(Mm(), input_data=[input_data1, input_data2]) + + # batched matrix x batched matrix + input_data1 = paddle.randn((10, 3, 4), dtype="float32") + input_data2 = paddle.randn((10, 4, 5), dtype="float32") + verify_model(Mm(), input_data=[input_data1, input_data2]) + + # batched matrix x broadcasted matrix + input_data1 = paddle.randn((10, 3, 4), dtype="float32") + input_data2 = paddle.randn((4, 5), dtype="float32") + verify_model(Mm(), input_data=[input_data1, input_data2]) + + +@tvm.testing.uses_gpu +def test_forward_mv(): + class Mv(nn.Layer): + def forward(self, input1, input2): + return paddle.mv(input1, input2) + + # matrix x vector + input_data1 = paddle.randn((3, 4), dtype="float32") + input_data2 = paddle.randn((4,), dtype="float32") + verify_model(Mv(), input_data=[input_data1, input_data2]) + + @tvm.testing.uses_gpu def test_forward_nonzero(): class Nonzero(nn.Layer): @@ -1331,6 +1375,21 @@ def forward(self, x, y): verify_model(Pow2(), input_data=[x_data, y_data]) +@tvm.testing.uses_gpu +def test_forward_rank(): + class Rank(nn.Layer): + @paddle.jit.to_static + def forward(self, inputs): + rank = paddle.rank(inputs) + rank = paddle.unsqueeze(rank, axis=0) + output = inputs + rank + return output + + input_shape = [1, 2, 1, 3, 1] + input_data = paddle.rand(input_shape, dtype="float32") + verify_model(Rank(), input_data=input_data) + + @tvm.testing.uses_gpu def test_forward_reduce_op(): class ReduceOp_Bool(nn.Layer): @@ -1491,6 +1550,23 @@ def slice5(inputs): verify_model(slice5, input_data=input_data) +@tvm.testing.uses_gpu +def test_forward_sort(): + @paddle.jit.to_static + def sort(inputs): + return paddle.sort(inputs) + + @paddle.jit.to_static + def sort2(inputs): + return paddle.sort(inputs, axis=0, descending=True) + + input_shape = [2, 3, 5] + input_data = paddle.rand(input_shape, dtype="float32") + verify_model(sort, input_data) + input_data2 = np.random.randint(100, size=input_shape) + verify_model(sort2, input_data2) + + @tvm.testing.uses_gpu def test_forward_split(): @paddle.jit.to_static @@ -1513,7 +1589,7 @@ def split3(inputs): @tvm.testing.uses_gpu -def test_forward_squeeze2(): +def test_forward_squeeze(): @paddle.jit.to_static def squeeze(inputs): return paddle.squeeze(inputs) @@ -1533,6 +1609,102 @@ def squeeze3(inputs): verify_model(squeeze3, input_data=input_data) +@tvm.testing.uses_gpu +def test_forward_stack(): + @paddle.jit.to_static + def stack(input1, input2, input3): + return paddle.stack([input1, input2, input3]) + + @paddle.jit.to_static + def stack2(input1, input2, input3): + return paddle.stack([input1, input2, input3], axis=-1) + + input_shape = [2, 3] + input_data = paddle.rand(input_shape, dtype="float32") + input_data2 = paddle.rand(input_shape, dtype="float32") + input_data3 = paddle.rand(input_shape, dtype="float32") + verify_model(stack, input_data=[input_data, input_data2, input_data3]) + verify_model(stack2, input_data=[input_data, input_data2, input_data3]) + + +@tvm.testing.uses_gpu +def test_forward_std(): + class Std1(nn.Layer): + @paddle.jit.to_static + def forward(self, inputs): + return paddle.std(inputs, 1, unbiased=False) + + class Std2(nn.Layer): + @paddle.jit.to_static + def forward(self, inputs): + return paddle.std(inputs, axis=-2, keepdim=False, unbiased=False) + + class Std3(nn.Layer): + @paddle.jit.to_static + def forward(self, inputs): + return paddle.std(inputs, axis=3, keepdim=True, unbiased=False) + + class Std4(nn.Layer): + @paddle.jit.to_static + def forward(self, inputs): + return paddle.std(inputs, axis=[2, 3], keepdim=True, unbiased=False) + + class Std5(nn.Layer): + @paddle.jit.to_static + def forward(self, inputs): + return paddle.std(inputs, axis=[2, 3], keepdim=False, unbiased=False) + + class Std6(nn.Layer): + @paddle.jit.to_static + def forward(self, inputs): + return paddle.std(inputs, unbiased=False) + + class Std7(nn.Layer): + @paddle.jit.to_static + def forward(self, inputs): + return paddle.std(inputs, unbiased=True) + + input_shape = [1, 3, 10, 10] + input_data = paddle.rand(input_shape, dtype="float32") + verify_model(Std1(), input_data=input_data) + verify_model(Std2(), input_data=input_data) + verify_model(Std3(), input_data=input_data) + verify_model(Std4(), input_data=input_data) + verify_model(Std5(), input_data=input_data) + verify_model(Std6(), input_data=input_data) + verify_model(Std7(), input_data=input_data) + + +@tvm.testing.uses_gpu +def test_forward_subtract(): + class Subtract(nn.Layer): + @paddle.jit.to_static + def forward(self, x, y): + return paddle.subtract(x, y) + + input_data1 = paddle.to_tensor([2, np.nan, 5], dtype='float32') + input_data2 = paddle.to_tensor([1, 4, np.nan], dtype='float32') + verify_model(Subtract(), input_data=[input_data1, input_data2]) + + input_data1 = paddle.randint(0, 10, (3, 4), dtype="int32") + input_data2 = paddle.randint(0, 10, (4,), dtype="int32") + verify_model(Subtract(), input_data=[input_data1, input_data2]) + + input_data1 = paddle.randint(0, 10, (10, 3, 4), dtype="int64") + input_data2 = paddle.randint(0, 10, (3, 4), dtype="int64") + verify_model(Subtract(), input_data=[input_data1, input_data2]) + + +@tvm.testing.uses_gpu +def test_forward_t(): + class T(nn.Layer): + def forward(self, x): + return paddle.t(x) + + input_data1 = paddle.randn((3, 4), dtype="float32") + verify_model(T(), input_data=[input_data1]) + + @tvm.testing.uses_gpu def test_forward_topk(): class Topk1(nn.Layer): @@ -1575,24 +1747,6 @@ def forward(self, inputs): verify_model(Topk6(), input_data=input_data) -@tvm.testing.uses_gpu -def test_forward_stack(): - @paddle.jit.to_static - def stack(input1, input2, input3): - return paddle.stack([input1, input2, input3]) - - @paddle.jit.to_static - def stack2(input1, input2, input3): - return paddle.stack([input1, input2, input3], axis=-1) - - input_shape = [2, 3] - input_data = paddle.rand(input_shape, dtype="float32") - input_data2 = paddle.rand(input_shape, dtype="float32") - input_data3 = paddle.rand(input_shape, dtype="float32") - verify_model(stack, input_data=[input_data, input_data2, input_data3]) - verify_model(stack2, input_data=[input_data, input_data2, input_data3]) - - @tvm.testing.uses_gpu def test_forward_tile(): @paddle.jit.to_static @@ -1624,6 +1778,27 @@ def tile3(inputs, inputs2): verify_model(tile3, input_data=[input_data, input_data2]) +@tvm.testing.uses_gpu +def test_forward_unstack(): + @paddle.jit.to_static + def unstack1(x): + return paddle.unstack(x) + + @paddle.jit.to_static + def unstack2(x): + return paddle.unstack(x, axis=-1) + + @paddle.jit.to_static + def unstack3(x): + return paddle.unstack(x, axis=-1, num=3) + + input_shape = [2, 3] + input_data = paddle.rand(input_shape, dtype="float32") + verify_model(unstack1, input_data=[input_data]) + verify_model(unstack2, input_data=[input_data]) + verify_model(unstack3, input_data=[input_data]) + + @tvm.testing.uses_gpu def test_forward_zeros(): @paddle.jit.to_static @@ -1668,6 +1843,7 @@ def forward(self, c, x, y): test_forward_arange() test_forward_argmax() test_forward_argmin() + test_forward_argsort() test_forward_assign() test_forward_batch_norm() test_forward_cast() @@ -1701,21 +1877,29 @@ def forward(self, c, x, y): test_forward_look_up() test_forward_lstm() test_forward_matmul() + test_forward_mm() + test_forward_mv() test_forward_multiply() test_forward_nonzero() test_forward_norm() test_forward_pool2d() test_forward_pad() test_forward_pow() + test_forward_rank() test_forward_reduce_op() test_forward_reshape() test_forward_scale() test_forward_slice() + test_forward_sort() test_forward_split() - test_forward_squeeze2() + test_forward_squeeze() + test_forward_std() + test_forward_subtract() + test_forward_t() test_forward_topk() test_forward_tile() test_forward_conv_transpose() test_forward_unary_op() + test_forward_unstack() test_forward_zeros() test_forward_where() From 72ca1cfb2ed9007c76c6bbd15f0c0df2ba3d63d4 Mon Sep 17 00:00:00 2001 From: wjj19950828 Date: Thu, 16 Sep 2021 19:16:31 +0800 Subject: [PATCH 098/127] code format --- python/tvm/relay/frontend/paddlepaddle.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 49c52cb001d3..a2266f6928e9 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -1164,7 +1164,7 @@ def convert_mul(g, op, block): def convert_mv(g, op, block): """Operator converter for mv.""" - x = g.get_node(op.input("X")[0]) + x = g.get_node(op.input("X")[0]) y = g.get_node(op.input("Vec")[0]) y = _op.expand_dims(y, axis=-1) y = _op.transpose(y) From 5c74d860385d7318271a517b8e7f1e5caea48cc2 Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Thu, 16 Sep 2021 23:09:05 +0800 Subject: [PATCH 099/127] add softplus softshrink softsign swish tanhshrink thresholded_relu op --- python/tvm/relay/frontend/paddlepaddle.py | 73 ++++++++++++++++++- .../frontend/paddlepaddle/test_forward.py | 10 ++- 2 files changed, 78 insertions(+), 5 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 316158ca6b51..3502be8a5999 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -658,7 +658,7 @@ def convert_elu(g, op, block): x = g.get_node(op.input("X")[0]) dtype = infer_type(x).checked_type.dtype alpha = op.attr("alpha") - alpha = _expr.const(alpha, dtype=dtype) + alpha = _expr.const(-1.0 * alpha, dtype=dtype) out = alpha * _op.nn.relu(_expr.const(1, dtype=dtype) - _op.exp(x)) + _op.nn.relu(x) g.add_node(op.output("Out")[0], out) @@ -1723,11 +1723,16 @@ def convert_scale(g, op, block): def convert_selu(g, op, block): """Operator converter for selu.""" - x = g.get_node(op.input("Input")[0]) + x = g.get_node(op.input("x")[0]) dtype = infer_type(x).checked_type.dtype alpha = _op.const(op.attr("alpha"), dtype) scale = _op.const(op.attr("scale"), dtype) - out = scale * (alpha * _op.nn.relu(_expr.const(1.0, dtype=dtype) - _op.exp(x)) + _op.nn.relu(x)) + out = ( + _expr.const(-1.0, dtype=dtype) + * alpha + * _op.nn.relu(_expr.const(1.0, dtype=dtype) - _op.exp(x)) + ) + out = scale * (out + _op.nn.relu(x)) g.add_node(op.output("Out")[0], out) @@ -1862,6 +1867,62 @@ def convert_softmax(g, op, block): g.add_node(op.output("Out")[0], out) +def convert_softplus(g, op, block): + """Operator converter for softplus.""" + + x = g.get_node(op.input("X")[0]) + dtype = infer_type(x).checked_type.dtype + beta = op.attr("beta") + beta = _expr.const(beta, dtype=dtype) + out = _op.log(_op.exp(x * beta) + _expr.const(1.0, dtype=dtype)) / beta + g.add_node(op.output("Out")[0], out) + + +def convert_softshrink(g, op, block): + """Operator converter for softshrink.""" + + x = g.get_node(op.input("X")[0]) + threshold = op.attr("lambda") + out = x - _op.clip(x, -1.0 * threshold, threshold) + g.add_node(op.output("Out")[0], out) + + +def convert_softsign(g, op, block): + """Operator converter for softsign.""" + + x = g.get_node(op.input("X")[0]) + dtype = infer_type(x).checked_type.dtype + out = x / (_op.const(1.0, dtype) + _op.abs(x)) + g.add_node(op.output("Out")[0], out) + + +def convert_swish(g, op, block): + """Operator converter for swish.""" + + x = g.get_node(op.input("X")[0]) + dtype = infer_type(x).checked_type.dtype + out = x / (_op.const(1.0, dtype) + _op.exp(_op.const(-1.0, dtype) * x)) + g.add_node(op.output("Out")[0], out) + + +def convert_tanhshrink(g, op, block): + """Operator converter for swish.""" + + x = g.get_node(op.input("X")[0]) + out = x - _op.tanh(x) + g.add_node(op.output("Out")[0], out) + + +def convert_thresholded_relu(g, op, block): + """Operator converter for thresholded_relu.""" + + x = g.get_node(op.input("X")[0]) + dtype = infer_type(x).checked_type.dtype + threshold = _op.const(op.attr("threshold"), dtype) + out = _op.where(_op.greater(x, threshold), x, _op.const(0.0, dtype)) + g.add_node(op.output("Out")[0], out) + + def convert_split(g, op, block): """Operator converter for split.""" @@ -2125,14 +2186,20 @@ def convert_where(g, op, block): "size": convert_numel, "slice": convert_slice, "softmax": convert_softmax, + "softplus": convert_softplus, + "softshrink": convert_softshrink, + "softsign": convert_softsign, "split": convert_split, "square": convert_square, "squeeze2": convert_squeeze, "stack": convert_stack, "strided_slice": convert_slice, "sum": convert_addn, + "swish": convert_swish, "tan": convert_unary_op, "tanh": convert_unary_op, + "tanh_shrink": convert_tanhshrink, + "thresholded_relu": convert_thresholded_relu, "top_k_v2": convert_topk, "tile": convert_tile, "transpose2": convert_transpose, diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index 426515342421..bf731d65a781 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -890,7 +890,7 @@ def forward(self, inputs): input_shape = [1, 3, 10, 10] input_data = paddle.normal(shape=input_shape) * 10.0 - input_data_2 = paddle.normal(shape=input_shape).astype("float16") * 10.0 + input_data_2 = paddle.normal(shape=input_shape).astype("float64") * 10.0 op_list = [ "elu", "hardshrink", @@ -903,10 +903,16 @@ def forward(self, inputs): "relu6", "selu", "sigmoid", + "softplus", + "softshrink", + "softsign", + "swish", + "tanhshrink", + "thresholded_relu", ] for op_name in op_list: verify_model(Activation(op_name), input_data=input_data) - verify_model(Activation(op_name), input_data=input_data_2, rtol=1e-3, atol=1e-3) + verify_model(Activation(op_name), input_data=input_data_2, rtol=1e-9, atol=1e-6) @tvm.testing.uses_gpu From beb425e18ef21f5a8fdd839af462b28b2379c4c4 Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Thu, 16 Sep 2021 23:11:40 +0800 Subject: [PATCH 100/127] fix bug --- python/tvm/relay/frontend/paddlepaddle.py | 1 - 1 file changed, 1 deletion(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 3502be8a5999..fd52f15eafd2 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -20,7 +20,6 @@ import warnings import numpy as np -from paddle.nn.functional.common import alpha_dropout import tvm from tvm.ir import IRModule From 2355adde3db7574f498cb460c81d0ed0c19e1b36 Mon Sep 17 00:00:00 2001 From: wjj19950828 Date: Fri, 17 Sep 2021 10:58:58 +0800 Subject: [PATCH 101/127] finished common api --- python/tvm/relay/frontend/paddlepaddle.py | 60 +++++++++++++++++-- .../frontend/paddlepaddle/test_forward.py | 48 ++++++++++++++- 2 files changed, 101 insertions(+), 7 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 4ae9b2cfdf17..ae4a37cf335d 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -1620,9 +1620,9 @@ def make_init_param_inputs(g, node, layer): if is_bidirec: num_directions = 2 - X_shape = infer_shape(input_x) - time_steps = X_shape[0] - X_steps = _op.split(input_x, indices_or_sections=time_steps, axis=0) + x_shape = infer_shape(input_x) + time_steps = x_shape[0] + x_steps = _op.split(input_x, indices_or_sections=time_steps, axis=0) for layer in range(num_layers): input_weights, hidden_weights, input_bias, hidden_bias = make_param_inputs( g, op, layer, hidden_size, num_layers @@ -1642,7 +1642,7 @@ def make_init_param_inputs(g, node, layer): WB = g.get_node(input_bias[i]) RB = g.get_node(hidden_bias[i]) output, H, C = generate_lstm( - X_steps=X_steps, + X_steps=x_steps, H_t=H_t, C_t=C_t, W=W, @@ -1663,8 +1663,7 @@ def make_init_param_inputs(g, node, layer): output = _op.transpose(output, axes=[0, 2, 1, 3]) output = _op.reshape(output, newshape=(0, 0, -1)) - X_steps = output - X_steps = _op.split(X_steps, indices_or_sections=time_steps, axis=0) + x_steps = _op.split(output, indices_or_sections=time_steps, axis=0) g.add_node(op.output("Out")[0], output) @@ -1963,6 +1962,53 @@ def convert_unsqueeze(g, op, block): g.add_node(op.output("Out")[0], x) +def convert_unstack(g, op, block): + """Operator converter for unstack.""" + + x = g.get_node(op.input("X")[0]) + axis = op.attr("axis") + num = op.attr("num") + out = _op.split(x, num, axis=axis) + for i, out_i in enumerate(out): + out_i = _op.squeeze(out_i, axis=[axis]) + g.add_node(op.output("Y")[i], out_i) + + +def convert_unique(g, op, block): + """Operator converter for unique.""" + + x = g.get_node(op.input("X")[0]) + ndim = len(infer_shape(x)) + assert ndim == 1, "Only support 1D Tensor for PaddlePaddle's unique" + is_sorted = op.attr("is_sorted") + return_counts = op.attr("return_counts") + return_index = op.attr("return_index") + return_inverse = op.attr("return_inverse") + if return_counts: + [unique, indices, inverse_indices, num_uniq, counts] = _op.unique( + x, is_sorted=is_sorted, return_counts=True + ) + unique_sliced = _op.strided_slice(unique, begin=[0], end=num_uniq, slice_mode="size") + counts_sliced = _op.strided_slice(counts, begin=[0], end=num_uniq, slice_mode="size") + indices_sliced = _op.strided_slice(indices, begin=[0], end=num_uniq, slice_mode="size") + counts_sliced = _op.cast(counts_sliced, "int64") + g.add_node(op.output("Counts")[0], counts_sliced) + else: + [unique, indices, inverse_indices, num_uniq] = _op.unique( + x, is_sorted=is_sorted, return_counts=False + ) + unique_sliced = _op.strided_slice(unique, begin=[0], end=num_uniq, slice_mode="size") + indices_sliced = _op.strided_slice(indices, begin=[0], end=num_uniq, slice_mode="size") + + inverse_indices = _op.cast(inverse_indices, "int64") + indices_sliced = _op.cast(indices_sliced, "int64") + g.add_node(op.output("Out")[0], unique_sliced) + if return_index: + g.add_node(op.output("Indices")[0], indices_sliced) + if return_inverse: + g.add_node(op.output("Index")[0], inverse_indices) + + def convert_where(g, op, block): """Operator converter for where.""" @@ -2107,6 +2153,8 @@ def convert_where(g, op, block): "tile": convert_tile, "transpose2": convert_transpose, "unsqueeze2": convert_unsqueeze, + "unstack": convert_unstack, + "unique": convert_unique, "where": convert_where, "where_index": convert_nonzero, } diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index 26c928f13ef6..85b95a57cc60 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -48,7 +48,6 @@ def get_paddle_model(func, input_spec): global PADDLE_TEST_DATA_ROOT_PATH model_path = Path(PADDLE_TEST_DATA_ROOT_PATH, "model") paddle.jit.save(func, str(model_path), input_spec=input_spec) - paddle.jit.save(func, "/paddle/pr_for_tvm/0905/tvm/inference_model_test/inference", input_spec=input_spec) baseline_model = paddle.jit.load(str(model_path)) shutil.rmtree(str(PADDLE_TEST_DATA_ROOT_PATH)) @@ -1824,6 +1823,52 @@ def unstack3(x): verify_model(unstack3, input_data=[input_data]) +@tvm.testing.uses_gpu +def test_forward_unique(): + @paddle.jit.to_static + def unique1(x): + return paddle.unique(x) + + @paddle.jit.to_static + def unique2(x): + return paddle.unique(x, return_index=True, return_inverse=False, return_counts=False) + + @paddle.jit.to_static + def unique3(x): + return paddle.unique(x, return_index=False, return_inverse=True, return_counts=False) + + @paddle.jit.to_static + def unique4(x): + return paddle.unique(x, return_index=False, return_inverse=False, return_counts=True) + + @paddle.jit.to_static + def unique5(x): + return paddle.unique(x, return_index=True, return_inverse=True, return_counts=False) + + @paddle.jit.to_static + def unique6(x): + return paddle.unique(x, return_index=False, return_inverse=True, return_counts=True) + + @paddle.jit.to_static + def unique7(x): + return paddle.unique(x, return_index=True, return_inverse=False, return_counts=True) + + @paddle.jit.to_static + def unique8(x): + return paddle.unique(x, return_index=True, return_inverse=True, return_counts=True) + + input_data = np.array([2, 3, 3, 1, 5, 3]) + input_data = paddle.to_tensor(input_data) + verify_model(unique1, input_data=[input_data], input_shape=[[6]]) + verify_model(unique2, input_data=[input_data], input_shape=[[6]]) + verify_model(unique3, input_data=[input_data], input_shape=[[6]]) + verify_model(unique4, input_data=[input_data], input_shape=[[6]]) + verify_model(unique5, input_data=[input_data], input_shape=[[6]]) + verify_model(unique6, input_data=[input_data], input_shape=[[6]]) + verify_model(unique7, input_data=[input_data], input_shape=[[6]]) + verify_model(unique8, input_data=[input_data], input_shape=[[6]]) + + @tvm.testing.uses_gpu def test_forward_zeros(): @paddle.jit.to_static @@ -1944,6 +1989,7 @@ def forward(self, x): test_forward_tile() test_forward_conv_transpose() test_forward_unstack() + test_forward_unique() test_forward_math() test_forward_zeros() test_forward_where() From 317a78abbad4a4eb1599adccc38e212a1a6f889c Mon Sep 17 00:00:00 2001 From: wjj19950828 Date: Fri, 17 Sep 2021 21:02:21 +0800 Subject: [PATCH 102/127] save for rnn --- python/tvm/relay/frontend/paddlepaddle.py | 1 + .../frontend/paddlepaddle/test_forward.py | 229 ++++++++++++------ 2 files changed, 159 insertions(+), 71 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index ae4a37cf335d..dbe11e0ab3a9 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -1613,6 +1613,7 @@ def make_init_param_inputs(g, node, layer): hidden_size = op.attr("hidden_size") num_layers = op.attr("num_layers") is_bidirec = op.attr("is_bidirec") + mode = op.attr("mode") input_x = g.get_node(op.input("Input")[0]) diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index 85b95a57cc60..f147e1128d18 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -48,6 +48,7 @@ def get_paddle_model(func, input_spec): global PADDLE_TEST_DATA_ROOT_PATH model_path = Path(PADDLE_TEST_DATA_ROOT_PATH, "model") paddle.jit.save(func, str(model_path), input_spec=input_spec) + paddle.jit.save(func, "/paddle/pr_for_tvm/0905/tvm/inference_model_test/inference", input_spec=input_spec) baseline_model = paddle.jit.load(str(model_path)) shutil.rmtree(str(PADDLE_TEST_DATA_ROOT_PATH)) @@ -1113,8 +1114,6 @@ def forward(self, inputs): @tvm.testing.uses_gpu def test_forward_lstm(): - lstm_input_shape = [25, 1, 288] - class LSTM1(nn.Layer): def __init__(self): super(LSTM1, self).__init__() @@ -1125,10 +1124,95 @@ def forward(self, inputs, prev_h, prev_c): y, (h, c) = self.lstm(inputs, (prev_h, prev_c)) return y + class LSTM2(nn.Layer): + def __init__(self): + super(LSTM2, self).__init__() + self.lstm = nn.LSTMCell(16, 32) + + @paddle.jit.to_static + def forward(self, inputs, prev_h, prev_c): + y, (h, c) = self.lstm(inputs, (prev_h, prev_c)) + return y + + lstm_input_shape = [25, 1, 288] lstm_input_data = paddle.rand(lstm_input_shape, dtype="float32") prev_h = paddle.rand([4, 1, 48], dtype="float32") prev_c = paddle.rand([4, 1, 48], dtype="float32") verify_model(LSTM1(), input_data=[lstm_input_data, prev_h, prev_c]) + lstm_input_shape = [4, 16] + lstm_input_data = paddle.rand(lstm_input_shape, dtype="float32") + prev_h = paddle.rand([4, 32], dtype="float32") + prev_c = paddle.rand([4, 32], dtype="float32") + verify_model(LSTM2(), input_data=[lstm_input_data, prev_h, prev_c]) + + +@tvm.testing.uses_gpu +def test_forward_gru(): + class GRU1(nn.Layer): + def __init__(self): + super(GRU1, self).__init__() + self.gru = nn.GRU(288, 48, 2, direction="bidirect", time_major=True) + + @paddle.jit.to_static + def forward(self, inputs, prev_h): + y, h = self.gru(inputs, prev_h) + return y + + class GRU2(nn.Layer): + def __init__(self): + super(GRU2, self).__init__() + self.gru = nn.GRUCell(16, 32) + + @paddle.jit.to_static + def forward(self, inputs, prev_h): + y, h = self.gru(inputs, prev_h) + return y + + gru_input_shape = [25, 1, 288] + gru_input_data = paddle.rand(gru_input_shape, dtype="float32") + prev_h = paddle.rand([4, 1, 48], dtype="float32") + verify_model(GRU1(), input_data=[gru_input_data, prev_h]) + # gru_input_shape = [4, 16] + # gru_input_data = paddle.rand(gru_input_shape, dtype="float32") + # prev_h = paddle.rand([4, 32], dtype="float32") + # prev_c = paddle.rand([4, 32], dtype="float32") + # verify_model(GRU2(), input_data=[gru_input_data, prev_h, prev_c]) + + +# @tvm.testing.uses_gpu +# def test_forward_birnn(): +# class BiRNN(nn.Layer): +# def __init__(self): +# super(BiRNN, self).__init__() +# cell_fw = nn.LSTMCell(16, 32) +# cell_bw = nn.LSTMCell(16, 32) +# self.rnn = nn.BiRNN(cell_fw, cell_bw) + +# @paddle.jit.to_static +# def forward(self, inputs): +# outputs, final_states = self.rnn(inputs) +# return outputs + +# input_data = paddle.rand((2, 23, 16)) +# verify_model(BiRNN(), input_data=[input_data]) + + +@tvm.testing.uses_gpu +def test_forward_rnn(): + class RNN(nn.Layer): + def __init__(self): + super(RNN, self).__init__() + cell = nn.SimpleRNNCell(16, 32) + self.rnn = nn.RNN(cell) + + @paddle.jit.to_static + def forward(self, inputs, prev_h): + outputs, final_states = self.rnn(inputs, prev_h) + return outputs + + input_data = paddle.rand((4, 23, 16)) + prev_h = paddle.randn((4, 32)) + verify_model(RNN(), input_data=[input_data, prev_h]) @tvm.testing.uses_gpu @@ -1925,72 +2009,75 @@ def forward(self, x): if __name__ == "__main__": - test_forward_add_subtract() - test_forward_addmm() - test_forward_addn() - test_forward_arange() - test_forward_argmax() - test_forward_argmin() - test_forward_argsort() - test_forward_assign() - test_forward_batch_norm() - test_forward_cast() - test_forward_clip() - test_forward_concat_unsqueeze() - test_forward_conv() - test_forward_crop() - test_forward_cumsum() - test_forward_dist() - test_forward_dot() - test_forward_dropout() - test_forward_elemwise() - test_forward_expand() - test_forward_expand_as() - test_forward_flatten() - test_forward_shape_full() - test_forward_ones() - test_forward_ones_like() - test_forward_gather_assign_value() - test_forward_gather_nd() - test_forward_gelu() - test_forward_group_norm() - test_forward_math() - test_forward_activation() - test_forward_index_select() - test_forward_instance_norm() - test_forward_interpolate() - test_forward_isinf() - test_forward_layer_norm() - test_forward_leaky_relu() - test_forward_logical_op() - test_forward_look_up() - test_forward_lstm() - test_forward_matmul() - test_forward_mm() - test_forward_mv() - test_forward_multiply() - test_forward_nonzero() - test_forward_norm() - test_forward_pool2d() - test_forward_pad() - test_forward_pow() - test_forward_rank() - test_forward_reduce_op() - test_forward_reshape() - test_forward_scale() - test_forward_slice() - test_forward_sort() - test_forward_split() - test_forward_squeeze() - test_forward_std() - test_forward_subtract() - test_forward_t() - test_forward_topk() - test_forward_tile() - test_forward_conv_transpose() - test_forward_unstack() - test_forward_unique() - test_forward_math() - test_forward_zeros() - test_forward_where() - test_forward_while() + # test_forward_add_subtract() + # test_forward_addmm() + # test_forward_addn() + # test_forward_arange() + # test_forward_argmax() + # test_forward_argmin() + # test_forward_argsort() + # test_forward_assign() + # test_forward_batch_norm() + # test_forward_cast() + # test_forward_clip() + # test_forward_concat_unsqueeze() + # test_forward_conv() + # test_forward_crop() + # test_forward_cumsum() + # test_forward_dist() + # test_forward_dot() + # test_forward_dropout() + # test_forward_elemwise() + # test_forward_expand() + # test_forward_expand_as() + # test_forward_flatten() + # test_forward_shape_full() + # test_forward_ones() + # test_forward_ones_like() + # test_forward_gather_assign_value() + # test_forward_gather_nd() + # test_forward_gelu() + # test_forward_group_norm() + # test_forward_math() + # test_forward_activation() + # test_forward_index_select() + # test_forward_instance_norm() + # test_forward_interpolate() + # test_forward_isinf() + # test_forward_layer_norm() + # test_forward_leaky_relu() + # test_forward_logical_op() + # test_forward_look_up() + # test_forward_lstm() + test_forward_gru() + # test_forward_birnn() + # test_forward_rnn() + # test_forward_matmul() + # test_forward_mm() + # test_forward_mv() + # test_forward_multiply() + # test_forward_nonzero() + # test_forward_norm() + # test_forward_pool2d() + # test_forward_pad() + # test_forward_pow() + # test_forward_rank() + # test_forward_reduce_op() + # test_forward_reshape() + # test_forward_scale() + # test_forward_slice() + # test_forward_sort() + # test_forward_split() + # test_forward_squeeze() + # test_forward_std() + # test_forward_subtract() + # test_forward_t() + # test_forward_topk() + # test_forward_tile() + # test_forward_conv_transpose() + # test_forward_unstack() + # test_forward_unique() + # test_forward_math() + # test_forward_zeros() + # test_forward_where() + # test_forward_while() From 891f4721ad7fc3dc007692818ca4e292ea07ad69 Mon Sep 17 00:00:00 2001 From: wjj19950828 Date: Sat, 18 Sep 2021 13:06:31 +0800 Subject: [PATCH 103/127] support for textcnn --- python/tvm/relay/frontend/paddlepaddle.py | 31 +++++++++++++++++++ .../frontend/paddlepaddle/test_forward.py | 6 ++-- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index a3f959a391c1..d1ce5c2e2987 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -1383,6 +1383,36 @@ def convert_pool2d(g, op, block): g.add_node(op.output("Out")[0], out) +def convert_max_pool2d_with_index(g, op, block): + """Operator converter for max_pool2d_with_index.""" + + adaptive = op.attr("adaptive") + global_pooling = op.attr("global_pooling") + ksize = op.attr("ksize") + paddings = op.attr("paddings") + if global_pooling: + adaptive = True + ksize = [1, 1] + + input_x = g.get_node(op.input("X")[0]) + + strides = op.attr("strides") + if isinstance(strides, int): + strides = [strides, strides] + if isinstance(ksize, int): + ksize = [ksize, ksize] + if isinstance(paddings, int): + paddings = [paddings] * 2 + + if not adaptive: + out = getattr(_op.nn, "max_pool2d")( + input_x, pool_size=ksize, strides=strides, padding=paddings + ) + else: + out = getattr(_op.nn, "adaptive_max_pool2d")(input_x, output_size=ksize) + g.add_node(op.output("Out")[0], out) + + def convert_padding(g, op, block): """Operator converter for padding.""" @@ -2218,6 +2248,7 @@ def convert_where(g, op, block): "nearest_interp_v2": convert_interpolate, "not_equal": convert_elementwise_op, "pool2d": convert_pool2d, + "max_pool2d_with_index": convert_max_pool2d_with_index, "pad1d": convert_padding, "pad2d": convert_padding, "pad3d": convert_padding, diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index 7caedeff75f5..86d45e4d550f 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -48,6 +48,7 @@ def get_paddle_model(func, input_spec): global PADDLE_TEST_DATA_ROOT_PATH model_path = Path(PADDLE_TEST_DATA_ROOT_PATH, "model") paddle.jit.save(func, str(model_path), input_spec=input_spec) + paddle.jit.save(func, "/paddle/pr_for_tvm/0905/tvm/inference_model_test/inference", input_spec=input_spec) baseline_model = paddle.jit.load(str(model_path)) shutil.rmtree(str(PADDLE_TEST_DATA_ROOT_PATH)) @@ -1339,15 +1340,16 @@ def pool2d2(inputs): @paddle.jit.to_static def pool2d3(inputs): - return nn.functional.max_pool2d( + output, max_indices = nn.functional.max_pool2d( inputs, kernel_size=2, stride=2, padding=0, return_mask=True ) + return output input_data = paddle.uniform(shape=[1, 2, 32, 32], dtype="float32", min=-1, max=1) verify_model(pool2d1, input_data=input_data) verify_model(pool2d2, input_data=input_data) # need op max_pool2d_with_index - # verify_model(pool2d3, input_data=input_data) + verify_model(pool2d3, input_data=input_data) @tvm.testing.uses_gpu From 52e706331799006b94def2efe09a778ecefa3ddb Mon Sep 17 00:00:00 2001 From: wjj19950828 Date: Sat, 18 Sep 2021 13:10:28 +0800 Subject: [PATCH 104/127] fixed bug --- tests/python/frontend/paddlepaddle/test_forward.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index 86d45e4d550f..cb314cb6b187 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -48,7 +48,6 @@ def get_paddle_model(func, input_spec): global PADDLE_TEST_DATA_ROOT_PATH model_path = Path(PADDLE_TEST_DATA_ROOT_PATH, "model") paddle.jit.save(func, str(model_path), input_spec=input_spec) - paddle.jit.save(func, "/paddle/pr_for_tvm/0905/tvm/inference_model_test/inference", input_spec=input_spec) baseline_model = paddle.jit.load(str(model_path)) shutil.rmtree(str(PADDLE_TEST_DATA_ROOT_PATH)) From ca200ffccafb5d9f32f42a7918542f4b7c41906f Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Sat, 18 Sep 2021 14:25:42 +0800 Subject: [PATCH 105/127] add masked_select meshgrid scatter scatter_nd_add op --- python/tvm/relay/frontend/paddlepaddle.py | 83 ++++++++++++++--- .../frontend/paddlepaddle/test_forward.py | 89 ++++++++++++++++++- 2 files changed, 158 insertions(+), 14 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index fd52f15eafd2..c72408be8c42 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -52,12 +52,11 @@ class ControlFlow: @classmethod def convert_block(cls, graph, block): - for i, op in enumerate(block.ops): + for op in block.ops: if op.type in ControlFlow.operators: raise Exception("Nested Control Flow Not Support Yet.") - else: - convert_func = _convert_map[op.type] - convert_func(graph, op, block) + convert_func = _convert_map[op.type] + convert_func(graph, op, block) @classmethod def convert(cls, graph, op, program): @@ -66,6 +65,8 @@ def convert(cls, graph, op, program): @classmethod def convert_while(cls, graph, op, program): + """Operator converter for while.""" + sub_block_id = op.attr("sub_block").id sub_block = program.blocks[sub_block_id] input_names = op.input("X") @@ -77,7 +78,6 @@ def convert_while(cls, graph, op, program): continue if name not in input_names: raise Exception("Output '{}' not in inputs".format(name)) - inputs = [graph.get_node(x) for x in op.input("X")] sub_graph = GraphProto(graph.freeze_params) sub_graph.set_params(graph.get_params()) @@ -96,7 +96,6 @@ def cond_fn(*loop_inputs): return _op.equal(squeezed_cond, _expr.const(True, "bool")) def body_fn(*loop_inputs): - cond = loop_inputs[0] body_inputs = loop_inputs[1:] for i, ipt in enumerate(body_inputs): sub_graph.add_node(input_names[i], ipt) @@ -141,13 +140,13 @@ def _dtype_shape_promotion(inputs): if r == 0: inputs[i] = _op.expand_dims(inputs[i], axis=0) - dtypes = set([dtype_order.index(infer_type(x).checked_type.dtype) for x in inputs]) + dtypes = set(dtype_order.index(infer_type(x).checked_type.dtype) for x in inputs) if len(dtypes) == 1: return inputs - max_dtype = dtype_order(max(dtypes)) - for i in range(len(inputs)): - if infer_type(inputs[i]).checked_type.dtype != max_dtype: - inputs[i] = inputs[i].astype(max_dtype) + max_dtype = dtype_order[max(dtypes)] + for i, input_op in enumerate(inputs): + if infer_type(input_op).checked_type.dtype != max_dtype: + inputs[i] = input_op.astype(max_dtype) return inputs @@ -1142,6 +1141,20 @@ def convert_logsumexp(g, op, block): g.add_node(op.output("Out")[0], out) +def convert_masked_select(g, op, block): + """Operator converter for masked_select.""" + + x = g.get_node(op.input("X")[0]) + mask = g.get_node(op.input("Mask")[0]) + index = _op.transform.argwhere(mask) + shape = infer_shape(index) + perm = list(range(0, len(shape) - 1)) + perm.insert(0, len(shape) - 1) + index = _op.transpose(index, axes=perm) + out = _op.gather_nd(x, index, 0, shape[-1]) + g.add_node(op.output("Y")[0], out) + + def convert_matmul(g, op, block): """Operator converter for matmul.""" @@ -1251,6 +1264,16 @@ def flatten_to_nd(x, x_shape, nd=3): g.add_node(op.output("Out")[0], out) +def convert_meshgrid(g, op, block): + """Operator converter for meshgrid.""" + + inputs = op.input("X") + x = [g.get_node(i) for i in inputs] + outs = _op.meshgrid(x, indexing="ij") + for i, out in enumerate(outs): + g.add_node(op.output("Out")[i], out) + + def convert_mul(g, op, block): """Operator converter for mul.""" @@ -1719,6 +1742,39 @@ def convert_scale(g, op, block): g.add_node(op.output("Out")[0], out) +def convert_scatter(g, op, block): + """Operator converter for scatter.""" + + x = g.get_node(op.input("X")[0]) + index = g.get_node(op.input("Ids")[0]) + updates = g.get_node(op.input("Updates")[0]) + overwrite = op.attr("overwrite") + + shape = infer_shape(updates) + ndims = len(shape) + index = _op.expand_dims(index, axis=-1, num_newaxis=ndims - 1) + index = _op.transform.broadcast_to(index, shape) + + if overwrite: + out = _op.scatter(x, index, updates, axis=0) + else: + out = _op.scatter_add(_op.zeros_like(x), index, updates, axis=0) + g.add_node(op.output("Out")[0], out) + + +def convert_scatter_nd_add(g, op, block): + """Operator converter for scatter_nd_add.""" + + x = g.get_node(op.input("X")[0]) + index = g.get_node(op.input("Index")[0]) + updates = g.get_node(op.input("Updates")[0]) + indices_dim = len(infer_shape(index)) + axes = list(range(indices_dim)) + index = _op.transpose(index, axes[-1:] + axes[:-1]) + out = _op.scatter_nd(x, index, updates, mode="add") + g.add_node(op.output("Out")[0], out) + + def convert_selu(g, op, block): """Operator converter for selu.""" @@ -2150,8 +2206,10 @@ def convert_where(g, op, block): "logsigmoid": convert_logsigmoid, "log_softmax": convert_logsoftmax, "logsumexp": convert_logsumexp, + "masked_select": convert_masked_select, "matmul": convert_matmul, "matmul_v2": convert_matmul, + "meshgrid": convert_meshgrid, "mul": convert_mul, "nearest_interp_v2": convert_interpolate, "not_equal": convert_elementwise_op, @@ -2178,6 +2236,7 @@ def convert_where(g, op, block): "rnn": convert_rnn, "rsqrt": convert_unary_op, "scale": convert_scale, + "scatter": convert_scatter, "selu": convert_selu, "shape": convert_shape, "sigmoid": convert_unary_op, @@ -2302,7 +2361,7 @@ def ops_to_relay(self, program, input_specs=None): for input_spec in input_specs: convert_feed(self, input_spec, None) global_block = program.blocks[0] - for i, op in enumerate(global_block.ops): + for op in global_block.ops: if op.type == "fetch": continue if op.type in ControlFlow.operators: diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index bf731d65a781..bc07d5449b51 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -899,7 +899,6 @@ def forward(self, inputs): "hardtanh", "log_sigmoid", "log_softmax", - "relu", "relu6", "selu", "sigmoid", @@ -912,7 +911,7 @@ def forward(self, inputs): ] for op_name in op_list: verify_model(Activation(op_name), input_data=input_data) - verify_model(Activation(op_name), input_data=input_data_2, rtol=1e-9, atol=1e-6) + verify_model(Activation(op_name), input_data=input_data_2) @tvm.testing.uses_gpu @@ -1163,6 +1162,32 @@ def multiply3(inputs, inputs2): verify_model(multiply3, input_data=[input_data, input_data2]) +@tvm.testing.uses_gpu +def test_forward_masked_select(): + @paddle.jit.to_static + def masked_select(x): + mask_data = np.array( + [[True, False, False, False], [True, True, False, False], [True, False, False, False]] + ).astype("bool") + mask = paddle.to_tensor(mask_data) + mask = paddle.logical_not(mask) + return paddle.masked_select(x, mask) + + @paddle.jit.to_static + def masked_select2(x, mask): + return paddle.masked_select(x, mask) + + data = np.array([[1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0], [9.0, 10.0, 11.0, 12.0]]).astype( + "float32" + ) + x = paddle.to_tensor(data) + verify_model(masked_select, x) + input_shape = [2, 3, 10] + x = paddle.rand(input_shape, dtype="float32") + mask = paddle.randint(0, 2, input_shape).astype("bool") + verify_model(masked_select2, [x, mask], input_shape=[input_shape, input_shape]) + + @tvm.testing.uses_gpu def test_forward_matmul(): class MatMul1(nn.Layer): @@ -1190,6 +1215,18 @@ def forward(self, input1, input2): verify_model(MatMul1(), input_data=[input_data1, input_data2]) +@tvm.testing.uses_gpu +def test_forward_meshgrid(): + @paddle.jit.to_static + def t(x, y, z): + return paddle.meshgrid(x, y, z) + + x = paddle.randint(low=0, high=100, shape=[2]) + y = paddle.randint(low=0, high=100, shape=[3]) + z = paddle.randint(low=0, high=100, shape=[5]) + verify_model(t, [x, y, z]) + + @tvm.testing.uses_gpu def test_forward_nonzero(): class Nonzero(nn.Layer): @@ -1532,6 +1569,50 @@ def scale2(inputs): verify_model(scale2, input_data=input_data) +@tvm.testing.uses_gpu +def test_forward_scatter(): + @paddle.jit.to_static + def scatter(x, index, updates): + return paddle.scatter(x, index, updates, overwrite=True) + + @paddle.jit.to_static + def scatter2(x, index, updates): + return paddle.scatter(x, index, updates, overwrite=False) + + x = paddle.rand([10, 8, 5], dtype="float32") + index = paddle.to_tensor( + [ + 2, + 1, + 0, + 6, + ] + ) + updates = paddle.rand([4, 8, 5], dtype="float32") + verify_model(scatter, [x, index, updates]) + verify_model(scatter2, [x, index, updates]) + + +def test_forward_scatter_nd(): + @paddle.jit.to_static + def scatter_nd(index, updates): + shape = [3, 5, 9, 10] + return paddle.scatter_nd(index, updates, shape) + + @paddle.jit.to_static + def scatter_nd_add(x, index, updates): + return paddle.scatter_nd_add(x, index, updates) + + index_data = np.array([[1, 1], [0, 1], [1, 3]]).astype(np.int64) + index = paddle.to_tensor(index_data) + updates = paddle.rand(shape=[3, 9, 10], dtype="float32") + verify_model(scatter_nd, [index, updates]) + x = paddle.rand(shape=[3, 5, 4, 9, 10], dtype="float32") + updates = paddle.rand(shape=[3, 2, 9, 10], dtype="float32") + index_data = paddle.randint(0, 4, shape=[3, 2, 3]) + verify_model(scatter_nd_add, [x, index, updates]) + + @tvm.testing.uses_gpu def test_forward_slice(): @paddle.jit.to_static @@ -1794,7 +1875,9 @@ def forward(self, x): test_forward_logical_op() test_forward_look_up() test_forward_lstm() + test_forward_masked_select() test_forward_matmul() + test_forward_meshgrid test_forward_multiply() test_forward_nonzero() test_forward_norm() @@ -1806,6 +1889,8 @@ def forward(self, x): test_forward_reduce_op() test_forward_reshape() test_forward_scale() + test_forward_scatter() + test_forward_scatter_nd() test_forward_slice() test_forward_split() test_forward_squeeze2() From 19a2979fad3acd66bd7c382e805343c7f9725b44 Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Sat, 18 Sep 2021 14:55:00 +0800 Subject: [PATCH 106/127] merge from jiajun --- python/tvm/relay/frontend/paddlepaddle.py | 3 ++- tests/python/frontend/paddlepaddle/test_forward.py | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 195afd84a6e9..9d4a33ee5df2 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -1773,6 +1773,7 @@ def convert_scatter(g, op, block): out = _op.scatter(x, index, updates, axis=0) else: out = _op.scatter_add(_op.zeros_like(x), index, updates, axis=0) + out += _op.scatter(x, index, _op.zeros_like(updates), axis=0) g.add_node(op.output("Out")[0], out) @@ -1792,7 +1793,7 @@ def convert_scatter_nd_add(g, op, block): def convert_selu(g, op, block): """Operator converter for selu.""" - x = g.get_node(op.input("x")[0]) + x = g.get_node(op.input("X")[0]) dtype = infer_type(x).checked_type.dtype alpha = _op.const(op.attr("alpha"), dtype) scale = _op.const(op.attr("scale"), dtype) diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index 26d4335cb730..577a295e7297 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -875,9 +875,9 @@ def __init__(self, channels, groups): def forward(self, inputs): return self.group_norm(inputs) - input_shape = [2, 6, 2, 2] + input_shape = [2, 6, 10, 10] x = paddle.rand(input_shape, dtype="float32") - verify_model(GroupNorm(6, 6), x) + verify_model(GroupNorm(6, 6), x, rtol=1e-4, atol=1e-4) @tvm.testing.uses_gpu From 15b44d8645faf543591845353a493747229e0096 Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Sat, 18 Sep 2021 15:07:48 +0800 Subject: [PATCH 107/127] fix scatter test case --- python/tvm/relay/frontend/paddlepaddle.py | 1 + tests/python/frontend/paddlepaddle/test_forward.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 9d4a33ee5df2..ffbc0173a1c4 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -2301,6 +2301,7 @@ def convert_where(g, op, block): "rsqrt": convert_unary_op, "scale": convert_scale, "scatter": convert_scatter, + "scatter_nd_add": convert_scatter_nd_add, "selu": convert_selu, "shape": convert_shape, "sigmoid": convert_unary_op, diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index 577a295e7297..2e9a81f30b3b 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -1669,7 +1669,7 @@ def scatter_nd_add(x, index, updates): verify_model(scatter_nd, [index, updates]) x = paddle.rand(shape=[3, 5, 4, 9, 10], dtype="float32") updates = paddle.rand(shape=[3, 2, 9, 10], dtype="float32") - index_data = paddle.randint(0, 4, shape=[3, 2, 3]) + index = paddle.randint(0, 4, shape=[3, 2, 3]) verify_model(scatter_nd_add, [x, index, updates]) From 3f24ea001ea8b8db883184ccb9048752cc02ba56 Mon Sep 17 00:00:00 2001 From: wjj19950828 Date: Sat, 18 Sep 2021 17:39:33 +0800 Subject: [PATCH 108/127] format code --- python/tvm/relay/frontend/paddlepaddle.py | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index b2396c05f92b..5b6bdd78721b 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -1623,7 +1623,19 @@ def convert_reshape(g, op, block): def convert_rnn(g, op, block): """Operator converter for rnn.""" - def generate_lstm(input_seqs, hidden_state, cell_state, w_inp, w_hid, b_inp, b_hid, f_act, g_act, h_act, backwards=False): + def generate_lstm( + input_seqs, + hidden_state, + cell_state, + w_inp, + w_hid, + b_inp, + b_hid, + f_act, + g_act, + h_act, + backwards=False, + ): """Implementation of LSTM cell for paddlepaddle of TVM""" h_list = [] @@ -1663,7 +1675,9 @@ def generate_lstm(input_seqs, hidden_state, cell_state, w_inp, w_hid, b_inp, b_h return output, hidden_state, cell_state - def generate_gru(input_seqs, hidden_state, w_inp, w_hid, b_inp, b_hid, rz_act, n_act, backwards=False): + def generate_gru( + input_seqs, hidden_state, w_inp, w_hid, b_inp, b_hid, rz_act, n_act, backwards=False + ): """Implementation of GRU cell for paddlepaddle of TVM""" h_list = [] @@ -1738,7 +1752,7 @@ def make_init_param_inputs(g, node, layer): axes=[0], ) return init_h, init_c - elif mode == "GRU": + else: all_init_h = node.input("PreState")[0] bidirect_len = 2 if node.attr("is_bidirec") else 1 init_h = _op.strided_slice( From 1af716859e00d74782cb4f243f5539441474ce76 Mon Sep 17 00:00:00 2001 From: wjj19950828 Date: Sat, 18 Sep 2021 17:44:20 +0800 Subject: [PATCH 109/127] fixed bug --- tests/python/frontend/paddlepaddle/test_forward.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index 1e15242f8dd0..b7c850574bc0 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -2148,7 +2148,7 @@ def forward(self, x): test_forward_gru() test_forward_masked_select() test_forward_matmul() - test_forward_meshgrid + test_forward_meshgrid() test_forward_mm() test_forward_mv() test_forward_multiply() From ea680bb0c40bc88fbd6f75bb14818217708c4e81 Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Wed, 22 Sep 2021 11:35:47 +0800 Subject: [PATCH 110/127] test dynamic shape --- .../frontend/paddlepaddle/test_forward.py | 75 +++++++++++-------- 1 file changed, 43 insertions(+), 32 deletions(-) diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index 2e9a81f30b3b..fecf83564006 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -25,6 +25,7 @@ import tvm from tvm.contrib.sparse import array +from tvm.relay.frontend.paddlepaddle import shape_of import tvm.testing import tvm.topi.testing from tvm import relay @@ -266,10 +267,15 @@ def arange(inputs): def arange2(inputs): return paddle.arange(0, 10.0, paddle.shape(inputs)[1], dtype="float32") + @paddle.jit.to_static + def arange3(inputs): + return paddle.arange(0, inputs, 2.0, dtype="float32") + input_shape = [2, 2] input_data = paddle.rand(input_shape, dtype="float32") verify_model(arange, input_data) verify_model(arange2, input_data=input_data) + verify_model(arange3, paddle.to_tensor(np.array([10], dtype="int32")), input_shape=[[1]]) @tvm.testing.uses_gpu @@ -362,7 +368,7 @@ def forward(self, inputs): input_data = paddle.rand(input_shape, dtype="float32") verify_model(Assign(), [input_data]) input_data2 = np.random.randint(100, size=input_shape) - verify_model(Assign(), [input_data2]) + verify_model(Assign(), [input_data2], input_shape=[[-1, -1]]) @tvm.testing.uses_gpu @@ -472,8 +478,7 @@ def crop1(inputs): return paddle.crop(inputs, shape=[2, 2]) @paddle.jit.to_static - def crop2(inputs): - shape = paddle.to_tensor(np.array([3, 3]).astype("int32")) + def crop2(inputs, shape): return paddle.crop(inputs, shape=shape, offsets=[0, 1]) @paddle.jit.to_static @@ -490,7 +495,8 @@ def crop4(inputs): input_shape = [10, 10] input_data = paddle.rand(input_shape, dtype="float32") verify_model(crop1, input_data=[input_data]) - verify_model(crop2, input_data=[input_data]) + shape = paddle.to_tensor(np.array([3, 3], "int32")) + verify_model(crop2, [input_data, shape], input_shape=[[-1, -1], [-1, -1]]) verify_model(crop3, input_data=[input_data]) verify_model(crop4, input_data=[input_data]) @@ -567,6 +573,7 @@ def forward(self, inputs): verify_model(Conv2D2(), input_data=conv2d_input_data) verify_model(Conv2D3(), input_data=conv2d_input_data) verify_model(Conv2D4(), input_data=conv2d_input_data) + verify_model(Conv2D1(), conv2d_input_data, input_shape=[[-1, 3, 112, 112]]) @tvm.testing.uses_gpu @@ -679,14 +686,14 @@ def expand1(inputs): return paddle.expand(inputs, shape=[2, 3]) @paddle.jit.to_static - def expand2(inputs): - shape = paddle.to_tensor(np.array([2, 3]).astype("int32")) + def expand2(inputs, shape): return paddle.expand(inputs, shape=shape) x_shape = [3] x_data = paddle.rand(x_shape, dtype="float32") verify_model(expand1, input_data=[x_data]) - verify_model(expand2, input_data=[x_data]) + shape = paddle.to_tensor(np.array([2, 3]).astype("int32")) + verify_model(expand2, [x_data, shape], input_shape=[[3], [2]]) @tvm.testing.uses_gpu @@ -699,7 +706,7 @@ def expand_as(x, y): data_x = paddle.to_tensor([1, 2, 3], dtype="int32") data_y = paddle.to_tensor([[1, 2, 3], [4, 5, 6]], dtype="float32") - verify_model(expand_as, [data_x, data_y]) + verify_model(expand_as, [data_x, data_y], input_shape=[[-1], [-1, -1]]) @tvm.testing.uses_gpu @@ -721,7 +728,7 @@ def flatten2(inputs): def test_forward_shape_full(): @paddle.jit.to_static def full1(inputs): - return paddle.full(paddle.shape(inputs), 3.14) + return paddle.full(inputs, 3.14) @paddle.jit.to_static def full2(inputs): @@ -734,7 +741,8 @@ def shape1(inputs): input_shape = [1, 3, 10, 10] input_data = paddle.rand(input_shape, dtype="float32") verify_model(shape1, input_data=[input_data]) - verify_model(full1, input_data=[input_data]) + shape = paddle.to_tensor(np.array(input_shape, "int32")) + verify_model(full1, input_data=[shape], input_shape=[[4]]) verify_model(full2, input_data=[input_data]) @@ -751,7 +759,7 @@ def ones_like2(inputs): input_shape = [1, 3, 10, 10] input_data = paddle.rand(input_shape, dtype="float32") verify_model(ones_like1, input_data=input_data) - verify_model(ones_like2, input_data=input_data) + verify_model(ones_like2, input_data, input_shape=[[-1, -1, -1, -1]]) @tvm.testing.uses_gpu @@ -821,8 +829,7 @@ def forward(self, input1, input2): @tvm.testing.uses_gpu def test_forward_gather_assign_value(): @paddle.jit.to_static - def gather1(x): - index = paddle.to_tensor(np.array([1, 3, 5, 7, 9]).astype("int64")) + def gather1(x, index): return paddle.gather(x, index, axis=None) @paddle.jit.to_static @@ -832,15 +839,15 @@ def gather2(x): x_shape = [30, 40] x_data = paddle.rand(x_shape, dtype="float32") - verify_model(gather1, input_data=[x_data]) + index = paddle.to_tensor(np.array([1, 3, 5, 7, 9]).astype("int64")) + verify_model(gather1, [x_data, index], input_shape=[[30, 40], [5]]) verify_model(gather2, input_data=[x_data]) @tvm.testing.uses_gpu def test_forward_gather_nd(): @paddle.jit.to_static - def gather_nd1(x): - index = paddle.to_tensor(np.array([[0, 1]]).astype("int64")) + def gather_nd1(x, index): return paddle.gather_nd(x, index) @paddle.jit.to_static @@ -850,7 +857,8 @@ def gather_nd2(x): x_shape = [30, 40, 20] x_data = paddle.rand(x_shape, dtype="float32") - verify_model(gather_nd1, input_data=[x_data]) + index = paddle.to_tensor(np.array([[0, 1]]).astype("int64")) + verify_model(gather_nd1, [x_data, index], input_shape=[[30, 40, 20], [2]]) verify_model(gather_nd2, input_data=[x_data]) @@ -992,10 +1000,9 @@ def __init__(self): super(TestBilinear, self).__init__() self.conv = nn.Conv2D(3, 5, 3, stride=2) - def forward(self, x): - shape = paddle.shape(x)[2:] + def forward(self, x, size): y = self.conv(x) - return nn.functional.interpolate(y, size=shape, mode="nearest") + return nn.functional.interpolate(y, size=size, mode="nearest") def bilinear_interp1(inputs): return nn.functional.interpolate(inputs, size=[12, 12], mode="bilinear") @@ -1018,7 +1025,8 @@ def bilinear_interp4(inputs): input_shape = [2, 3, 6, 12] input_data = paddle.rand(input_shape, dtype="float32") - verify_model(TestBilinear(), input_data=input_data) + size = paddle.to_tensor(np.array([15, 15], "int32")) + verify_model(TestBilinear(), [input_data, size], input_shape=[input_shape, [2]]) verify_model(bilinear_interp1, input_data=input_data) verify_model(bilinear_interp2, input_data=input_data) verify_model(bilinear_interp3, input_data=input_data) @@ -1123,7 +1131,7 @@ def forward(self, inputs): input_data = paddle.randint(0, 10, input_shape, dtype="int32") weight = paddle.rand([10, 4], dtype="float32") verify_model(look_up, input_data=[input_data, weight]) - verify_model(LookUp(), input_data=input_data) + verify_model(LookUp(), input_data, input_shape=[[-1, -1, -1, -1]]) @tvm.testing.uses_gpu @@ -1380,7 +1388,7 @@ def pool2d3(inputs): ) input_data = paddle.uniform(shape=[1, 2, 32, 32], dtype="float32", min=-1, max=1) - verify_model(pool2d1, input_data=input_data) + verify_model(pool2d1, input_data, input_shape=[[-1, 2, 32, 32]]) verify_model(pool2d2, input_data=input_data) # need op max_pool2d_with_index # verify_model(pool2d3, input_data=input_data) @@ -1582,8 +1590,7 @@ def forward(self, inputs): @tvm.testing.uses_gpu def test_forward_reshape(): @paddle.jit.to_static - def reshape1(inputs, x): - new_shape = paddle.shape(x) + def reshape1(inputs, new_shape): return paddle.reshape(inputs, new_shape) @paddle.jit.to_static @@ -1603,7 +1610,8 @@ def reshape4(inputs, x): input_shape = [2, 1, 10, 1, 10] input_data = paddle.rand(input_shape, dtype="float32") input_data2 = paddle.randn([2, 1, 10, 10]) - verify_model(reshape1, input_data=[input_data, input_data2]) + new_shape = paddle.shape(input_data2) + verify_model(reshape1, [input_data, new_shape], input_shape=[[2, 1, 10, 1, 10], [4]]) verify_model(reshape2, input_data=input_data) verify_model(reshape3, input_data=paddle.randn((2, 3, 4))) verify_model(reshape4, input_data=[input_data, input_data2]) @@ -1649,7 +1657,7 @@ def scatter2(x, index, updates): ] ) updates = paddle.rand([4, 8, 5], dtype="float32") - verify_model(scatter, [x, index, updates]) + verify_model(scatter, [x, index, updates], input_shape=[[-1, 8, 5], [4], [4, 8, 5]]) verify_model(scatter2, [x, index, updates]) @@ -1676,8 +1684,8 @@ def scatter_nd_add(x, index, updates): @tvm.testing.uses_gpu def test_forward_slice(): @paddle.jit.to_static - def slice1(inputs): - return inputs[:, :, :, :3] + def slice1(inputs, end): + return inputs[:, :, :, :end] @paddle.jit.to_static def slice2(inputs): @@ -1700,7 +1708,8 @@ def slice5(inputs): input_shape = [1, 3, 10, 10] input_data = paddle.rand(input_shape, dtype="float32") - verify_model(slice1, input_data=input_data) + end = paddle.to_tensor(np.array([3])) + verify_model(slice1, [input_data, end], input_shape=[[1, 3, 10, 10], [1]]) verify_model(slice2, input_data=input_data) verify_model(slice3, input_data=paddle.randn((4, 4))) verify_model(slice4, input_data=input_data) @@ -1907,8 +1916,8 @@ def forward(self, inputs): @tvm.testing.uses_gpu def test_forward_tile(): @paddle.jit.to_static - def tile(inputs): - return paddle.tile(inputs, [3, 2]) + def tile(inputs, shape): + return paddle.tile(inputs, shape) @paddle.jit.to_static def tile2(inputs, inputs2): @@ -1931,6 +1940,8 @@ def tile3(inputs, inputs2): ], ) input_data2 = paddle.rand([1, 2], dtype="float32") + shape = paddle.to_tensor(np.array([3, 2])) + verify_model(tile, [input_data, shape], input_shape=[[2, 2], [2]]) verify_model(tile2, input_data=[input_data, input_data2]) verify_model(tile3, input_data=[input_data, input_data2]) From f6fb9f58b92f63aaabb99b7c3a4a2fa41264d932 Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Wed, 22 Sep 2021 15:16:26 +0800 Subject: [PATCH 111/127] test dynamic shape --- .../frontend/paddlepaddle/test_forward.py | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index fecf83564006..3e695b71199f 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -24,8 +24,6 @@ import paddle.nn as nn import tvm -from tvm.contrib.sparse import array -from tvm.relay.frontend.paddlepaddle import shape_of import tvm.testing import tvm.topi.testing from tvm import relay @@ -496,7 +494,7 @@ def crop4(inputs): input_data = paddle.rand(input_shape, dtype="float32") verify_model(crop1, input_data=[input_data]) shape = paddle.to_tensor(np.array([3, 3], "int32")) - verify_model(crop2, [input_data, shape], input_shape=[[-1, -1], [-1, -1]]) + # verify_model(crop2, [input_data, shape], input_shape=[[-1, -1], [2]]) verify_model(crop3, input_data=[input_data]) verify_model(crop4, input_data=[input_data]) @@ -693,7 +691,7 @@ def expand2(inputs, shape): x_data = paddle.rand(x_shape, dtype="float32") verify_model(expand1, input_data=[x_data]) shape = paddle.to_tensor(np.array([2, 3]).astype("int32")) - verify_model(expand2, [x_data, shape], input_shape=[[3], [2]]) + # verify_model(expand2, [x_data, shape], input_shape=[[3], [2]]) @tvm.testing.uses_gpu @@ -706,7 +704,7 @@ def expand_as(x, y): data_x = paddle.to_tensor([1, 2, 3], dtype="int32") data_y = paddle.to_tensor([[1, 2, 3], [4, 5, 6]], dtype="float32") - verify_model(expand_as, [data_x, data_y], input_shape=[[-1], [-1, -1]]) + verify_model(expand_as, [data_x, data_y]) @tvm.testing.uses_gpu @@ -858,7 +856,7 @@ def gather_nd2(x): x_shape = [30, 40, 20] x_data = paddle.rand(x_shape, dtype="float32") index = paddle.to_tensor(np.array([[0, 1]]).astype("int64")) - verify_model(gather_nd1, [x_data, index], input_shape=[[30, 40, 20], [2]]) + verify_model(gather_nd1, [x_data, index]) verify_model(gather_nd2, input_data=[x_data]) @@ -1933,14 +1931,8 @@ def tile3(inputs, inputs2): input_shape = [2, 2] input_data = paddle.rand(input_shape, dtype="float32") - verify_model( - tile, - input_data=[ - input_data, - ], - ) input_data2 = paddle.rand([1, 2], dtype="float32") - shape = paddle.to_tensor(np.array([3, 2])) + shape = paddle.to_tensor(np.array([3, 2], "int32")) verify_model(tile, [input_data, shape], input_shape=[[2, 2], [2]]) verify_model(tile2, input_data=[input_data, input_data2]) verify_model(tile3, input_data=[input_data, input_data2]) From 5734c01b339e958173ecbb17d09ab003c869363e Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Wed, 22 Sep 2021 15:33:58 +0800 Subject: [PATCH 112/127] test dynamic shape --- tests/python/frontend/paddlepaddle/test_forward.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index 3e695b71199f..2eeec47105e1 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -856,7 +856,7 @@ def gather_nd2(x): x_shape = [30, 40, 20] x_data = paddle.rand(x_shape, dtype="float32") index = paddle.to_tensor(np.array([[0, 1]]).astype("int64")) - verify_model(gather_nd1, [x_data, index]) + verify_model(gather_nd1, [x_data, index], input_shape=[[-1, 40, 20], [1, 2]]) verify_model(gather_nd2, input_data=[x_data]) From 91190a3a3190a86aecd260f1a0a2c91376b7a095 Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Wed, 22 Sep 2021 16:04:44 +0800 Subject: [PATCH 113/127] fix scatter_nd test case bug --- tests/python/frontend/paddlepaddle/test_forward.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index 2eeec47105e1..6c12e957604b 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -1675,7 +1675,7 @@ def scatter_nd_add(x, index, updates): verify_model(scatter_nd, [index, updates]) x = paddle.rand(shape=[3, 5, 4, 9, 10], dtype="float32") updates = paddle.rand(shape=[3, 2, 9, 10], dtype="float32") - index = paddle.randint(0, 4, shape=[3, 2, 3]) + index = paddle.randint(0, 3, shape=[3, 2, 3]) verify_model(scatter_nd_add, [x, index, updates]) From 385917c8035795d1563fe6c9f26558c9d032012a Mon Sep 17 00:00:00 2001 From: wjj19950828 Date: Wed, 22 Sep 2021 17:41:26 +0800 Subject: [PATCH 114/127] Add Simplernn op --- python/tvm/relay/frontend/paddlepaddle.py | 57 +++++++++++++++++++ .../frontend/paddlepaddle/test_forward.py | 33 +++++++++++ 2 files changed, 90 insertions(+) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 5b6bdd78721b..988a32a399bc 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -1711,6 +1711,38 @@ def generate_gru( return output, hidden_state + def generate_simplernn( + input_seqs, hidden_state, w_inp, w_hid, b_inp, b_hid, n_act, backwards=False + ): + """Implementation of SimpleRNN cell for paddlepaddle of TVM""" + + h_list = [] + seq_length = len(input_seqs) + for i in range(seq_length): + step = input_seqs[i] if not backwards else input_seqs[seq_length - (i + 1)] + step = _op.squeeze(step, axis=[0]) + xwt = _op.nn.dense(step, w_inp) + hwt = _op.nn.dense(hidden_state, w_hid) + if b_inp is not None: + xwt += b_inp + if b_hid is not None: + hwt += b_hid + + n_gate = n_act(xwt + hwt) + + hidden_state = n_gate + h_list.append(_op.expand_dims(hidden_state, axis=0)) + + if backwards: + h_list = h_list[::-1] + + # Concatenate outputs and add back in direction axis. + concatenated = _op.concatenate(h_list, 0) + output = _op.expand_dims(concatenated, axis=1) + hidden_state = _op.expand_dims(hidden_state, axis=0) + + return output, hidden_state + def make_param_inputs(g, node, layer, hidden_size, num_layers): """Param for weight and bias.""" @@ -1840,6 +1872,31 @@ def make_init_param_inputs(g, node, layer): result_H.append(H) output = _op.concatenate(result_output, axis=1) H = _op.concatenate(result_H, axis=0) + elif mode == "RNN_TANH": + init_h = make_init_param_inputs(g, op, layer) + init_hs = _op.split(init_h, num_directions) + result_output = [] + result_H = [] + for i in range(num_directions): + H_t = _op.squeeze(init_hs[i], axis=[0]) + W = g.get_node(input_weights[i]) + R = g.get_node(hidden_weights[i]) + WB = g.get_node(input_bias[i]) + RB = g.get_node(hidden_bias[i]) + output, H = generate_simplernn( + input_seqs=x_steps, + hidden_state=H_t, + w_inp=W, + w_hid=R, + b_inp=WB, + b_hid=RB, + n_act=_op.tanh, + backwards=i == 1, + ) + result_output.append(output) + result_H.append(H) + output = _op.concatenate(result_output, axis=1) + H = _op.concatenate(result_H, axis=0) output = _op.transpose(output, axes=[0, 2, 1, 3]) output = _op.reshape(output, newshape=(0, 0, -1)) diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index b7c850574bc0..73530623d3c5 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -1192,6 +1192,38 @@ def forward(self, inputs, prev_h): verify_model(GRU2(), input_data=[gru_input_data, prev_h]) +@tvm.testing.uses_gpu +def test_forward_simplernn(): + class SimpleRNN1(nn.Layer): + def __init__(self): + super(SimpleRNN1, self).__init__() + self.simplernn = nn.SimpleRNN(288, 48, 2, direction="bidirect", time_major=True) + + @paddle.jit.to_static + def forward(self, inputs, prev_h): + y, h = self.simplernn(inputs, prev_h) + return y + + class SimpleRNN2(nn.Layer): + def __init__(self): + super(SimpleRNN2, self).__init__() + self.simplernn = nn.SimpleRNNCell(16, 32) + + @paddle.jit.to_static + def forward(self, inputs, prev_h): + y, h = self.simplernn(inputs, prev_h) + return y + + gru_input_shape = [25, 1, 288] + gru_input_data = paddle.rand(gru_input_shape, dtype="float32") + prev_h = paddle.rand([4, 1, 48], dtype="float32") + verify_model(SimpleRNN1(), input_data=[gru_input_data, prev_h]) + gru_input_shape = [4, 16] + gru_input_data = paddle.rand(gru_input_shape, dtype="float32") + prev_h = paddle.rand([4, 32], dtype="float32") + verify_model(SimpleRNN2(), input_data=[gru_input_data, prev_h]) + + @tvm.testing.uses_gpu def test_forward_multiply(): @paddle.jit.to_static @@ -2146,6 +2178,7 @@ def forward(self, x): test_forward_look_up() test_forward_lstm() test_forward_gru() + test_forward_simplernn() test_forward_masked_select() test_forward_matmul() test_forward_meshgrid() From dea5609598e029637db9b8af679449e8dd5725d0 Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Wed, 22 Sep 2021 20:17:46 +0800 Subject: [PATCH 115/127] pylint check --- python/tvm/relay/frontend/paddlepaddle.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 988a32a399bc..d981b7dbf635 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -1784,16 +1784,15 @@ def make_init_param_inputs(g, node, layer): axes=[0], ) return init_h, init_c - else: - all_init_h = node.input("PreState")[0] - bidirect_len = 2 if node.attr("is_bidirec") else 1 - init_h = _op.strided_slice( - g.get_node(all_init_h), - [layer * bidirect_len], - [layer * bidirect_len + bidirect_len], - axes=[0], - ) - return init_h + all_init_h = node.input("PreState")[0] + bidirect_len = 2 if node.attr("is_bidirec") else 1 + init_h = _op.strided_slice( + g.get_node(all_init_h), + [layer * bidirect_len], + [layer * bidirect_len + bidirect_len], + axes=[0], + ) + return init_h hidden_size = op.attr("hidden_size") num_layers = op.attr("num_layers") From d110b5f06cb4850d79c037bda0f9a31da4c4eabb Mon Sep 17 00:00:00 2001 From: wjj19950828 Date: Wed, 22 Sep 2021 21:44:30 +0800 Subject: [PATCH 116/127] Fixed Dynamic bugs --- python/tvm/relay/frontend/paddlepaddle.py | 34 ++++++------------- .../frontend/paddlepaddle/test_forward.py | 11 +++--- 2 files changed, 16 insertions(+), 29 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 988a32a399bc..7de1ed4698fc 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -602,6 +602,7 @@ def convert_crop(g, op, block): """Operator converter for crop.""" x = g.get_node(op.input("X")[0]) + dims = len(infer_shape(x)) input_shape = op.input("Shape") input_offsets = op.input("Offsets") if input_shape: @@ -616,13 +617,15 @@ def convert_crop(g, op, block): else: offsets = op.attr("offsets") - crop_len = len(shape) - slice_start = [0] * crop_len - slice_end = shape - for i in range(crop_len): - slice_start[i] += offsets[i] - slice_end[i] += offsets[i] - out = _op.strided_slice(x, slice_start, slice_end) + if not isinstance(shape, _expr.Expr): + shape = _op.const(shape, "int32") + if not isinstance(offsets, _expr.Expr): + offsets = _op.const(offsets, "int32") + slice_start = offsets + slice_end = _op.add(shape, offsets) + strides = _op.const([1] * dims, dtype="int32") + + out = _op.strided_slice(x, slice_start, slice_end, strides) g.add_node(op.output("Out")[0], out) @@ -739,28 +742,13 @@ def convert_expand(g, op, block): """Operator converter for expand.""" x = g.get_node(op.input("X")[0]) - input_shape = list(infer_shape(x)) - - ndims = len(input_shape) if op.input("Shape"): sizes = g.get_node(op.input("Shape")[0]) sizes = _infer_value(sizes, g.get_params()) else: sizes = op.attr("shape") - out = x - out_dims = len(sizes) - if ndims < out_dims: - num_newaxis = out_dims - ndims - out = _op.expand_dims(out, axis=0, num_newaxis=num_newaxis) - input_shape = [1] * num_newaxis + input_shape - - for i in range(out_dims): - if sizes[i] != -1 and input_shape[i] == 1: - if not isinstance(sizes[i], int): - sizes[i] = int(infer_value(sizes[i], {}).numpy()) - out = _op.repeat(out, sizes[i], axis=i) - + out = _op.broadcast_to(x, sizes) g.add_node(op.output("Out")[0], out) diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index 625340618a2d..63e4ef6172c2 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -485,18 +485,17 @@ def crop3(inputs): return paddle.crop(inputs, shape=[3, 3], offsets=offsets) @paddle.jit.to_static - def crop4(inputs): - shape = paddle.to_tensor(np.array([3, 3]).astype("int32")) - offsets = paddle.to_tensor(np.array([1, 1]).astype("int32")) + def crop4(inputs, shape, offsets): return paddle.crop(inputs, shape=shape, offsets=offsets) input_shape = [10, 10] input_data = paddle.rand(input_shape, dtype="float32") verify_model(crop1, input_data=[input_data]) shape = paddle.to_tensor(np.array([3, 3], "int32")) - # verify_model(crop2, [input_data, shape], input_shape=[[-1, -1], [2]]) + verify_model(crop2, [input_data, shape], input_shape=[[-1, -1], [2]]) verify_model(crop3, input_data=[input_data]) - verify_model(crop4, input_data=[input_data]) + offsets = paddle.to_tensor(np.array([1, 1]).astype("int32")) + verify_model(crop4, input_data=[input_data, shape, offsets], input_shape=[[-1, -1], [2], [2]]) @tvm.testing.uses_gpu @@ -691,7 +690,7 @@ def expand2(inputs, shape): x_data = paddle.rand(x_shape, dtype="float32") verify_model(expand1, input_data=[x_data]) shape = paddle.to_tensor(np.array([2, 3]).astype("int32")) - # verify_model(expand2, [x_data, shape], input_shape=[[3], [2]]) + verify_model(expand2, [x_data, shape], input_shape=[[3], [2]]) @tvm.testing.uses_gpu From 81a83f494d4ccb18ad3777a53638c885a2ec2c6f Mon Sep 17 00:00:00 2001 From: wjj19950828 Date: Wed, 22 Sep 2021 22:07:24 +0800 Subject: [PATCH 117/127] fixed conflicts --- python/tvm/relay/frontend/paddlepaddle.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 7de1ed4698fc..56a99fd2b226 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -1772,16 +1772,15 @@ def make_init_param_inputs(g, node, layer): axes=[0], ) return init_h, init_c - else: - all_init_h = node.input("PreState")[0] - bidirect_len = 2 if node.attr("is_bidirec") else 1 - init_h = _op.strided_slice( - g.get_node(all_init_h), - [layer * bidirect_len], - [layer * bidirect_len + bidirect_len], - axes=[0], - ) - return init_h + all_init_h = node.input("PreState")[0] + bidirect_len = 2 if node.attr("is_bidirec") else 1 + init_h = _op.strided_slice( + g.get_node(all_init_h), + [layer * bidirect_len], + [layer * bidirect_len + bidirect_len], + axes=[0], + ) + return init_h hidden_size = op.attr("hidden_size") num_layers = op.attr("num_layers") From 4bdbb38cacb00d69cce0b7f994b42107f13c802c Mon Sep 17 00:00:00 2001 From: wjj19950828 Date: Thu, 23 Sep 2021 16:57:16 +0800 Subject: [PATCH 118/127] fixed pool2d bug --- python/tvm/relay/frontend/paddlepaddle.py | 8 +++++++- tests/python/frontend/paddlepaddle/test_forward.py | 11 ++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 56a99fd2b226..f970fcf77266 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -1356,6 +1356,7 @@ def convert_pool2d(g, op, block): ksize = [1, 1] input_x = g.get_node(op.input("X")[0]) + input_shape = infer_shape(input_x) op_map = { "avg": "avg_pool2d", @@ -1372,7 +1373,7 @@ def convert_pool2d(g, op, block): if padding_algorithm == "VALID": paddings = [0, 0] elif padding_algorithm == "SAME": - in_h, in_w = infer_shape(input_x)[2:] + in_h, in_w = input_shape[2:] pad_h = _get_pad_size(in_h, ksize[0], strides[0]) pad_w = _get_pad_size(in_w, ksize[1], strides[1]) paddings = [pad_h[0], pad_w[0], pad_h[1], pad_w[1]] @@ -1385,6 +1386,11 @@ def convert_pool2d(g, op, block): msg = 'Value {} in attribute "padding" of operator Pool2d is not "valid."' raise tvm.error.OpAttributeInvalid(msg.format(padding_algorithm)) + if input_shape[2] < ksize[0]: + ksize[0] = input_shape[2] + if input_shape[3] < ksize[1]: + ksize[1] = input_shape[3] + if not adaptive: out = getattr(_op.nn, op_map[pooling_type])( input_x, pool_size=ksize, strides=strides, padding=paddings, ceil_mode=ceil_mode diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index 63e4ef6172c2..03d5b600dde1 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -1458,6 +1458,13 @@ def pool2d2(inputs): @paddle.jit.to_static def pool2d3(inputs): + output = nn.functional.max_pool2d( + inputs, kernel_size=2, stride=2, padding=0 + ) + return output + + @paddle.jit.to_static + def pool2d4(inputs): output, max_indices = nn.functional.max_pool2d( inputs, kernel_size=2, stride=2, padding=0, return_mask=True ) @@ -1466,8 +1473,10 @@ def pool2d3(inputs): input_data = paddle.uniform(shape=[1, 2, 32, 32], dtype="float32", min=-1, max=1) verify_model(pool2d1, input_data, input_shape=[[-1, 2, 32, 32]]) verify_model(pool2d2, input_data=input_data) + input_data1 = paddle.uniform(shape=[1, 2, 1, 50], dtype="float32", min=-1, max=1) + verify_model(pool2d3, input_data=input_data1) # need op max_pool2d_with_index - verify_model(pool2d3, input_data=input_data) + verify_model(pool2d4, input_data=input_data) @tvm.testing.uses_gpu From 5e1a4deff3fd04dfff52c3b0b1c640b0ba25c1b5 Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Thu, 23 Sep 2021 17:56:51 +0800 Subject: [PATCH 119/127] fix conv bug --- python/tvm/relay/frontend/paddlepaddle.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index d981b7dbf635..bf2faca28809 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -529,7 +529,12 @@ def convert_conv2d(g, op, block): pad_h = _get_pad_size(0, (k_h - 1) * dilations[0] + 1, strides[0]) pad_w = _get_pad_size(0, (k_w - 1) * dilations[1] + 1, strides[1]) else: - in_h, in_w = infer_shape(input_x)[2:] + input_shape = shape_of(input_x) + try: + _, _, in_h, in_w = infer_value(input_shape, g.get_params()).numpy().tolist() + except Exception: + msg = "The SAME padding algorithm of Conv not support dynamic shape" + raise tvm.error.OpAttributeInvalid(msg) pad_h = _get_pad_size(in_h, (k_h - 1) * dilations[0] + 1, strides[0]) pad_w = _get_pad_size(in_w, (k_w - 1) * dilations[1] + 1, strides[1]) paddings = [pad_h[0], pad_w[0], pad_h[1], pad_w[1]] @@ -787,6 +792,9 @@ def convert_feed(g, op, block): ipt_name = op.name if g.shape_dict is not None: ipt_shape = g.shape_dict[ipt_name] + + if isinstance(ipt_shape, tuple): + ipt_shape = list(ipt_shape) for i, s in enumerate(ipt_shape): if s < 0: ipt_shape[i] = _ty.Any() @@ -1397,6 +1405,7 @@ def convert_pool2d(g, op, block): msg = 'Value {} in attribute "padding" of operator Pool2d is not "valid."' raise tvm.error.OpAttributeInvalid(msg.format(padding_algorithm)) + if not adaptive: out = getattr(_op.nn, op_map[pooling_type])( input_x, pool_size=ksize, strides=strides, padding=paddings, ceil_mode=ceil_mode From 65b652f2c6271ebf1c60e84e66e160d3b4b6434c Mon Sep 17 00:00:00 2001 From: jiangjiajun Date: Fri, 24 Sep 2021 05:57:48 +0000 Subject: [PATCH 120/127] code format for test_forward.py --- tests/python/frontend/paddlepaddle/test_forward.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/python/frontend/paddlepaddle/test_forward.py b/tests/python/frontend/paddlepaddle/test_forward.py index 03d5b600dde1..00fe97f3146d 100644 --- a/tests/python/frontend/paddlepaddle/test_forward.py +++ b/tests/python/frontend/paddlepaddle/test_forward.py @@ -1458,9 +1458,7 @@ def pool2d2(inputs): @paddle.jit.to_static def pool2d3(inputs): - output = nn.functional.max_pool2d( - inputs, kernel_size=2, stride=2, padding=0 - ) + output = nn.functional.max_pool2d(inputs, kernel_size=2, stride=2, padding=0) return output @paddle.jit.to_static From fd02e46c8b19a7451a3f92b68288a121760e1a4c Mon Sep 17 00:00:00 2001 From: jiangjiajun Date: Fri, 24 Sep 2021 06:48:40 +0000 Subject: [PATCH 121/127] modify util function _infer_value --- python/tvm/relay/frontend/paddlepaddle.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 502449990d36..b36d7a76bc25 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -165,14 +165,10 @@ def _infer_value(x, params): Otherwise, return input""" try: - if isinstance(x, _expr.Constant): - return x.data.numpy().tolist() - return params[x.name_hint].numpy().tolist() - except (IndexError, KeyError, AttributeError): - try: - return infer_value(x, params).numpy().tolist() - except Exception: - return x + value = infer_value(x, params) + return value.numpy().tolist() + except Exception: + return x def _convert_dtype_value(val): From ca636ef1d9387161a6e9a0bd426a01739ee9fc25 Mon Sep 17 00:00:00 2001 From: jiangjiajun Date: Fri, 24 Sep 2021 06:57:28 +0000 Subject: [PATCH 122/127] fix pylint problem --- python/tvm/relay/frontend/paddlepaddle.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index b36d7a76bc25..2a17514bc626 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -167,7 +167,7 @@ def _infer_value(x, params): try: value = infer_value(x, params) return value.numpy().tolist() - except Exception: + except Exception: # pylint: disable=broad-except return x From b06bad2454a2f1d12095f9b40d28ba513e5a166b Mon Sep 17 00:00:00 2001 From: jiangjiajun Date: Fri, 24 Sep 2021 07:10:26 +0000 Subject: [PATCH 123/127] fix pylint problem --- python/tvm/relay/frontend/paddlepaddle.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 2a17514bc626..fa46c84a1f92 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -167,7 +167,7 @@ def _infer_value(x, params): try: value = infer_value(x, params) return value.numpy().tolist() - except Exception: # pylint: disable=broad-except + except Exception: # pylint: disable=broad-except return x From 686277e06bb0627bba725be7ab9ae7f3609fac1f Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Fri, 24 Sep 2021 19:25:31 +0800 Subject: [PATCH 124/127] fix conv strides bug --- python/tvm/relay/frontend/paddlepaddle.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 502449990d36..339744f8591d 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -525,7 +525,7 @@ def convert_conv2d(g, op, block): if padding_algorithm == "VALID": paddings = [0, 0] elif padding_algorithm == "SAME": - if strides[0] == 0 and strides[1] == 0: + if strides[0] == 1 and strides[1] == 1: pad_h = _get_pad_size(0, (k_h - 1) * dilations[0] + 1, strides[0]) pad_w = _get_pad_size(0, (k_w - 1) * dilations[1] + 1, strides[1]) else: From 552ee2a354e810e948b1a6fbe1d7e4883579e1e0 Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Fri, 24 Sep 2021 19:45:26 +0800 Subject: [PATCH 125/127] SAME of padding_algorithm --- python/tvm/relay/frontend/paddlepaddle.py | 34 +++++++++++++++++++---- 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 339744f8591d..f2211df6c9a6 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -530,8 +530,9 @@ def convert_conv2d(g, op, block): pad_w = _get_pad_size(0, (k_w - 1) * dilations[1] + 1, strides[1]) else: input_shape = shape_of(input_x) + h_w = _op.strided_slice(input_shape, [2], [4]) try: - _, _, in_h, in_w = infer_value(input_shape, g.get_params()).numpy().tolist() + in_h, in_w = infer_value(h_w, g.get_params()).numpy().tolist() except Exception as e: msg = "The SAME padding algorithm of Conv not support dynamic shape" raise tvm.error.OpAttributeInvalid(msg) from e @@ -576,9 +577,19 @@ def convert_conv2d_transpose(g, op, block): if padding_algorithm == "VALID": paddings = [0, 0] elif padding_algorithm == "SAME": - in_h, in_w = infer_shape(input_x)[2:] - pad_h = _get_pad_size(in_h, (k_h - 1) * dilations[0] + 1, strides[0]) - pad_w = _get_pad_size(in_w, (k_w - 1) * dilations[1] + 1, strides[1]) + if strides[0] == 1 and strides[1] == 1: + pad_h = _get_pad_size(0, (k_h - 1) * dilations[0] + 1, strides[0]) + pad_w = _get_pad_size(0, (k_w - 1) * dilations[1] + 1, strides[1]) + else: + input_shape = shape_of(input_x) + h_w = _op.strided_slice(input_shape, [2], [4]) + try: + in_h, in_w = infer_value(h_w, g.get_params()).numpy().tolist() + except Exception as e: + msg = "The SAME padding algorithm of Conv_Transpose not support dynamic shape" + raise tvm.error.OpAttributeInvalid(msg) from e + pad_h = _get_pad_size(in_h, (k_h - 1) * dilations[0] + 1, strides[0]) + pad_w = _get_pad_size(in_w, (k_w - 1) * dilations[1] + 1, strides[1]) paddings = [pad_h[0], pad_w[0], pad_h[1], pad_w[1]] elif padding_algorithm == "EXPLICIT": if len(paddings) == 2: @@ -1381,8 +1392,19 @@ def convert_pool2d(g, op, block): if padding_algorithm == "VALID": paddings = [0, 0] elif padding_algorithm == "SAME": - pad_h = _get_pad_size(in_h, ksize[0], strides[0]) - pad_w = _get_pad_size(in_w, ksize[1], strides[1]) + if strides[0] == 1 and strides[1] == 1: + pad_h = _get_pad_size(0, ksize[0], strides[0]) + pad_w = _get_pad_size(0, ksize[1], strides[1]) + else: + input_shape = shape_of(input_x) + h_w = _op.strided_slice(input_shape, [2], [4]) + try: + in_h, in_w = infer_value(h_w, g.get_params()).numpy().tolist() + except Exception as e: + msg = "The SAME padding algorithm of Conv not support dynamic shape" + raise tvm.error.OpAttributeInvalid(msg) from e + pad_h = _get_pad_size(in_h, ksize[0], strides[0]) + pad_w = _get_pad_size(in_w, ksize[1], strides[1]) paddings = [pad_h[0], pad_w[0], pad_h[1], pad_w[1]] elif padding_algorithm == "EXPLICIT": if len(paddings) == 2: From 04c58f2c2be1df496f267507db907a5a5af1876a Mon Sep 17 00:00:00 2001 From: wjj19950828 Date: Sun, 26 Sep 2021 18:00:28 +0800 Subject: [PATCH 126/127] fixed fillanylike bug --- python/tvm/relay/frontend/paddlepaddle.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index 8e820ea1112b..a2d97bcfbf6b 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -800,12 +800,11 @@ def convert_feed(g, op, block): def convert_fill_any_like(g, op, block): """Operator converter for fill_any_like.""" - out_name = op.output("Out")[0] - out_dtype = block.var(out_name).dtype - out_dtype = str(out_dtype).strip().split(".")[1] + dtype = op.attr("dtype") + dtype = _convert_dtype_value(dtype) x = g.get_node(op.input("X")[0]) - value = _expr.const(op.attr("value")) - out = _op.transform.full_like(x, value).astype(out_dtype) + value = _expr.const(op.attr("value"), dtype=dtype) + out = _op.transform.full_like(x, value) g.add_node(op.output("Out")[0], out) From 4c36393186372257b1700a5074f1367292fda9e5 Mon Sep 17 00:00:00 2001 From: wjj19950828 Date: Mon, 27 Sep 2021 10:57:03 +0800 Subject: [PATCH 127/127] fixed ones_like bug --- python/tvm/relay/frontend/paddlepaddle.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/tvm/relay/frontend/paddlepaddle.py b/python/tvm/relay/frontend/paddlepaddle.py index a2d97bcfbf6b..0aaa3c434edb 100644 --- a/python/tvm/relay/frontend/paddlepaddle.py +++ b/python/tvm/relay/frontend/paddlepaddle.py @@ -804,7 +804,7 @@ def convert_fill_any_like(g, op, block): dtype = _convert_dtype_value(dtype) x = g.get_node(op.input("X")[0]) value = _expr.const(op.attr("value"), dtype=dtype) - out = _op.transform.full_like(x, value) + out = _op.transform.full_like(x, value).astype(dtype) g.add_node(op.output("Out")[0], out)