diff --git a/cinn/frontend/net_builder.h b/cinn/frontend/net_builder.h index 6a5e534476..be7f34b95a 100644 --- a/cinn/frontend/net_builder.h +++ b/cinn/frontend/net_builder.h @@ -685,6 +685,7 @@ class NetBuilder { * @param ends The ending indices of corresponding axis in axes. Default: None. * @param infer_flags Whether the output shape can be infered in compile time. Now only support all 1. Default: None. * @param strides The slice step of corresponding axis in axes. Default: None. + * @param decrease_axis Eliminate the specified dimension. Default: None. * @return A variable with the same dimension as x. The data type is same as x. */ Variable Slice(const Variable& x, diff --git a/python/tests/ops/test_select_op.py b/python/tests/ops/test_select_op.py index 4c208cf5a1..68f2b653c0 100644 --- a/python/tests/ops/test_select_op.py +++ b/python/tests/ops/test_select_op.py @@ -12,28 +12,26 @@ # See the License for the specific language governing permissions and # limitations under the License. -import unittest -import numpy as np -from op_test import OpTest, OpTestTool import paddle -import cinn from cinn.frontend import * from cinn.common import * -import logging -import os +from op_test import OpTest, OpTestTool +from op_test_helper import TestCaseHelper @OpTestTool.skip_if(not is_compiled_with_cuda(), "x86 test will be skipped due to timeout.") class TestSelectOp(OpTest): def setUp(self): - self.init_case() + print(f"\nRunning {self.__class__.__name__}: {self.case}") + self.inputs = {} + self.prepare_inputs() - def init_case(self): + def prepare_inputs(self): self.inputs = { - "Condition": np.zeros(100).astype('bool'), - "X": np.random.uniform((-3), 5, 100).astype('float32'), - "Y": np.random.uniform((-3), 5, 100).astype('float32') + "Condition": self.random(self.case["shape"], "bool", 0, 2), + "X": self.random(self.case["shape"], self.case["dtype"]), + "Y": self.random(self.case["shape"], self.case["dtype"]) } def build_paddle_program(self, target): @@ -46,10 +44,15 @@ def build_paddle_program(self, target): def build_cinn_program(self, target): builder = NetBuilder("select") - c = builder.create_input(Bool(), self.inputs["Condition"].shape, - "Condition") - x = builder.create_input(Float(32), self.inputs["X"].shape, "X") - y = builder.create_input(Float(32), self.inputs["Y"].shape, "Y") + c = builder.create_input( + self.nptype2cinntype(self.inputs["Condition"].dtype), + self.inputs["Condition"].shape, "Condition") + x = builder.create_input( + self.nptype2cinntype(self.inputs["X"].dtype), + self.inputs["X"].shape, "X") + y = builder.create_input( + self.nptype2cinntype(self.inputs["Y"].dtype), + self.inputs["Y"].shape, "Y") out = builder.select(c, x, y) prog = builder.build() @@ -63,19 +66,113 @@ def test_check_results(self): self.check_outputs_and_grads(all_equal=True) -class TestSelectOp1(TestSelectOp): - def init_config(self): - self.x = np.random.uniform((-5), 5, (60, 2)).astype('float32') - self.y = np.random.uniform((-5), 5, (60, 2)).astype('float32') - self.cond = np.ones((60, 2)).astype('bool') +class TestSelectOpShape(TestCaseHelper): + def init_attrs(self): + self.class_name = "TestSelectOpShape" + self.cls = TestSelectOp + self.inputs = [ + { + "shape": [10], + }, + { + "shape": [8, 5], + }, + { + "shape": [10, 3, 5], + }, + { + "shape": [80, 40, 5, 7], + }, + { + "shape": [80, 1, 5, 7], + }, + { + "shape": [80, 3, 1024, 7], + }, + { + "shape": [10, 5, 1024, 2048], + }, + { + "shape": [1], + }, + { + "shape": [512], + }, + { + "shape": [1024], + }, + { + "shape": [2048], + }, + { + "shape": [1, 1, 1, 1], + }, + ] + self.dtypes = [ + { + "dtype": "float32" + }, + ] + self.attrs = [] -class TestSelectOp2(TestSelectOp): - def init_config(self): - self.x = np.random.uniform((-3), 5, (20, 2, 4)).astype('float32') - self.y = np.random.uniform((-3), 5, (20, 2, 4)).astype('float32') - self.cond = np.array(np.random.randint(2, size=(20, 2, 4)), dtype=bool) +class TestSelectOpDtype(TestCaseHelper): + def init_attrs(self): + self.class_name = "TestSelectOpDtype" + self.cls = TestSelectOp + self.inputs = [ + { + "shape": [1], + }, + { + "shape": [5], + }, + { + "shape": [80, 40, 5, 7], + }, + ] + self.dtypes = [ + { + "dtype": "float16" + }, + { + "dtype": "float32" + }, + { + "dtype": "float64" + }, + { + "dtype": "int32" + }, + { + "dtype": "int64" + }, + { + "dtype": "uint16" + }, + # Paddle does not support the following data type + # { + # "dtype": "bool" + # }, + # { + # "dtype": "int8" + # }, + # { + # "dtype": "int16" + # }, + # { + # "dtype": "uint8" + # }, + # { + # "dtype": "uint32" + # }, + # { + # "dtype": "uint64" + # }, + ] + self.attrs = [] if __name__ == "__main__": - unittest.main() + TestSelectOpShape().run() + TestSelectOpDtype().run() diff --git a/python/tests/ops/test_sigmoid_op.py b/python/tests/ops/test_sigmoid_op.py index daa8608582..4b9ccd1378 100644 --- a/python/tests/ops/test_sigmoid_op.py +++ b/python/tests/ops/test_sigmoid_op.py @@ -14,28 +14,25 @@ # See the License for the specific language governing permissions and # limitations under the License. -import unittest -import numpy as np -from op_test import OpTest, OpTestTool import paddle import paddle.nn.functional as F -import cinn from cinn.frontend import * from cinn.common import * +from op_test import OpTest, OpTestTool +from op_test_helper import TestCaseHelper @OpTestTool.skip_if(not is_compiled_with_cuda(), "x86 test will be skipped due to timeout.") class TestSigmoidOp(OpTest): def setUp(self): - self.init_case() + print(f"\nRunning {self.__class__.__name__}: {self.case}") + self.inputs = {} + self.prepare_inputs() - def init_case(self): + def prepare_inputs(self): self.inputs = { - "x": np.random.random([ - 32, - 64, - ]).astype("float32") + "x": self.random(self.case["shape"], self.case["dtype"], -1.0, 1.0) } def build_paddle_program(self, target): @@ -48,7 +45,9 @@ def build_paddle_program(self, target): # the forward result will be incorrect. def build_cinn_program(self, target): builder = NetBuilder("sigmoid") - x = builder.create_input(Float(32), self.inputs["x"].shape, "x") + x = builder.create_input( + self.nptype2cinntype(self.inputs["x"].dtype), + self.inputs["x"].shape, "x") out = builder.sigmoid(x) prog = builder.build() @@ -61,5 +60,85 @@ def test_check_results(self): self.check_outputs_and_grads() +class TestSigmoidOpShape(TestCaseHelper): + def init_attrs(self): + self.class_name = "TestSigmoidOpShape" + self.cls = TestSigmoidOp + self.inputs = [ + { + "shape": [10], + }, + { + "shape": [8, 5], + }, + { + "shape": [10, 3, 5], + }, + { + "shape": [80, 40, 5, 7], + }, + { + "shape": [80, 1, 5, 7], + }, + { + "shape": [80, 3, 1024, 7], + }, + { + "shape": [10, 5, 1024, 2048], + }, + { + "shape": [1], + }, + { + "shape": [512], + }, + { + "shape": [1024], + }, + { + "shape": [2048], + }, + { + "shape": [1, 1, 1, 1], + }, + ] + self.dtypes = [ + { + "dtype": "float32" + }, + ] + self.attrs = [] + + +class TestSigmoidOpDtype(TestCaseHelper): + def init_attrs(self): + self.class_name = "TestSigmoidOpDtype" + self.cls = TestSigmoidOp + self.inputs = [ + { + "shape": [1], + }, + { + "shape": [5], + }, + { + "shape": [80, 40, 5, 7], + }, + ] + self.dtypes = [ + { + "dtype": "float16" + }, + { + "dtype": "float32" + }, + { + "dtype": "float64" + }, + ] + self.attrs = [] + + if __name__ == "__main__": - unittest.main() + TestSigmoidOpShape().run() + TestSigmoidOpDtype().run() diff --git a/python/tests/ops/test_sign_op.py b/python/tests/ops/test_sign_op.py index 6b9f02627d..920cda2564 100644 --- a/python/tests/ops/test_sign_op.py +++ b/python/tests/ops/test_sign_op.py @@ -14,24 +14,25 @@ # See the License for the specific language governing permissions and # limitations under the License. -import unittest import numpy as np -from op_test import OpTest, OpTestTool import paddle -import cinn from cinn.frontend import * from cinn.common import * +from op_test import OpTest, OpTestTool +from op_test_helper import TestCaseHelper @OpTestTool.skip_if(not is_compiled_with_cuda(), "x86 test will be skipped due to timeout.") class TestSignOp(OpTest): def setUp(self): - self.init_case() + print(f"\nRunning {self.__class__.__name__}: {self.case}") + self.inputs = {} + self.prepare_inputs() - def init_case(self): + def prepare_inputs(self): self.inputs = { - "x": np.random.uniform(-10, 10, (10, 10)).astype("float32") + "x": self.random(self.case["shape"], self.case["dtype"], -10, 10) } def build_paddle_program(self, target): @@ -42,7 +43,9 @@ def build_paddle_program(self, target): def build_cinn_program(self, target): builder = NetBuilder("sign") - x = builder.create_input(Float(32), self.inputs["x"].shape, "x") + x = builder.create_input( + self.nptype2cinntype(self.inputs["x"].dtype), + self.inputs["x"].shape, "x") out = builder.sign(x) prog = builder.build() @@ -63,5 +66,81 @@ def init_case(self): } +class TestSignOpShape(TestCaseHelper): + def init_attrs(self): + self.class_name = "TestSignOpShape" + self.cls = TestSignOp + self.inputs = [ + { + "shape": [10], + }, + { + "shape": [8, 5], + }, + { + "shape": [10, 3, 5], + }, + { + "shape": [80, 40, 5, 7], + }, + { + "shape": [80, 1, 5, 7], + }, + { + "shape": [80, 3, 1024, 7], + }, + { + "shape": [10, 5, 1024, 2048], + }, + { + "shape": [1], + }, + { + "shape": [512], + }, + { + "shape": [1024], + }, + { + "shape": [2048], + }, + { + "shape": [1, 1, 1, 1], + }, + ] + self.dtypes = [ + { + "dtype": "float32" + }, + ] + self.attrs = [] + + +class TestSignOpDtype(TestCaseHelper): + def init_attrs(self): + self.class_name = "TestSignOpDtype" + self.cls = TestSignOp + self.inputs = [ + { + "shape": [1], + }, + { + "shape": [5], + }, + { + "shape": [80, 40, 5, 7], + }, + ] + self.dtypes = [{ + "dtype": "float16" + }, { + "dtype": "float32" + }, { + "dtype": "float64" + }] + self.attrs = [] + + if __name__ == "__main__": - unittest.main() + TestSignOpShape().run() + TestSignOpDtype().run() diff --git a/python/tests/ops/test_slice_assign_op.py b/python/tests/ops/test_slice_assign_op.py index 3510ff0c00..ff16a12bd6 100644 --- a/python/tests/ops/test_slice_assign_op.py +++ b/python/tests/ops/test_slice_assign_op.py @@ -14,74 +14,78 @@ # See the License for the specific language governing permissions and # limitations under the License. -import unittest -import numpy as np -from op_test import OpTest, OpTestTool import paddle -import cinn +import numpy as np from cinn.frontend import * from cinn.common import * +from op_test import OpTest, OpTestTool +from op_test_helper import TestCaseHelper + + +def paddle_slice_assign(data, update, axes, starts, ends, strides): + assert len(axes) == len(starts) == len(ends) == len(strides) + + # prepare + for i in range(len(ends)): + input_len = data.shape[axes[i]] + if ends[i] < 0: + ends[i] += input_len + elif ends[i] > input_len: + ends[i] = input_len + if starts[i] < 0: + starts[i] += input_len + elif starts[i] > input_len: + starts[i] = input_len - 1 + + # slice & assign + dims = len(data.shape) + slices = ['::'] * dims + for i, axis in enumerate(axes): + slices[axis] = str(starts[i]) + ':' + str(ends[i]) + ':' + str( + strides[i]) + res = data.clone() + exec(f"res[{','.join(slices)}] = update") + return res @OpTestTool.skip_if(not is_compiled_with_cuda(), "x86 test will be skipped due to timeout.") class TestSliceAssignOp(OpTest): def setUp(self): - self.init_case() - self.prepare_case() + print(f"\nRunning {self.__class__.__name__}: {self.case}") + self.inputs = {} + self.prepare_inputs() - def init_case(self): + def prepare_inputs(self): self.inputs = { - "inputs": np.random.random([10, 12]).astype("float32"), - "assign": np.zeros([3, 3]).astype("float32") + "inputs": self.random(self.case["inputs_shape"], + self.case["dtype"]), + "assign": self.random(self.case["assign_shape"], + self.case["dtype"]), } - self.axes = [0, 1] - self.starts = [2, 2] - self.ends = [5, 5] - self.strides = [1, 1] - - def prepare_case(self): - for i in range(len(self.ends)): - input_len = self.inputs["inputs"].shape[i] - if self.ends[i] < 0: - self.ends[i] += input_len - elif self.ends[i] > input_len: - self.ends[i] = input_len - if self.starts[i] < 0: - self.starts[i] += input_len - elif self.starts[i] > input_len: - self.starts[i] = input_len - 1 - - def num_of_slice(self, start, end, stride): - if stride < 0: - start, end = end, start - stride = -stride - num = 0 - while start < end: - start += stride - num += 1 - return num + if self.case["assign_zeros"]: + self.inputs["assign"] = np.zeros(self.case["assign_shape"]).astype( + self.case["dtype"]) + self.axes = self.case["axes"] + self.starts = self.case["starts"] + self.ends = self.case["ends"] + self.strides = self.case["strides"] def build_paddle_program(self, target): - res = self.inputs["inputs"].copy() - - row_len = self.num_of_slice(self.starts[0], self.ends[0], - self.strides[0]) - - for row_id in range(row_len): - res[self.starts[0] + self.strides[0] * - row_id][self.starts[1]:self.ends[1]:self. - strides[1]] = self.inputs["assign"][row_id] - - pd_res = paddle.to_tensor(res, stop_gradient=True) - self.paddle_outputs = [pd_res] + inputs = paddle.to_tensor(self.inputs["inputs"], stop_gradient=True) + assign = paddle.to_tensor(self.inputs["assign"], stop_gradient=True) + res = paddle_slice_assign(inputs, assign, self.axes, self.starts, + self.ends, self.strides) + self.paddle_outputs = [res] def build_cinn_program(self, target): builder = NetBuilder("slice_assign") inputs = builder.create_input( - Float(32), self.inputs["inputs"].shape, "inputs") + self.nptype2cinntype(self.inputs["inputs"].dtype), + self.inputs["inputs"].shape, "inputs") assign = builder.create_input( - Float(32), self.inputs["assign"].shape, "assign") + self.nptype2cinntype(self.inputs["assign"].dtype), + self.inputs["assign"].shape, "assign") out = builder.slice_assign( inputs, assign, @@ -100,150 +104,321 @@ def test_check_results(self): self.check_outputs_and_grads(all_equal=True) -class TestSliceAssignCase1(TestSliceAssignOp): - def init_case(self): - self.inputs = { - "inputs": np.random.random([10, 12]).astype("float32"), - "assign": np.zeros([5, 5]).astype("float32") - } - self.axes = [0, 1] - self.starts = [1, 2] - self.ends = [6, 1000] - self.strides = [1, 2] - - -class TestSliceAssignCase2(TestSliceAssignOp): - def init_case(self): - self.inputs = { - "inputs": np.random.random([10, 12]).astype("float32"), - "assign": np.zeros([3, 3]).astype("float32") - } - self.axes = [0, 1] - self.starts = [2, 1] - self.ends = [-1, 7] - self.strides = [3, 2] - - -class TestSliceAssignCase3(TestSliceAssignOp): - def init_case(self): - self.inputs = { - "inputs": np.random.random([10, 12]).astype("float32"), - "assign": np.zeros([7, 5]).astype("float32") - } - self.axes = [0, 1] - self.starts = [2, 1000] - self.ends = [8, 1] - self.strides = [1, -2] - - -class TestSliceAssignCase4(TestSliceAssignOp): - def init_case(self): - self.inputs = { - "inputs": np.random.random([10, 12]).astype("float32"), - "assign": np.zeros([4, 3]).astype("float32") - } - self.axes = [0, 1] - self.starts = [-1, -2] - self.ends = [-5, -8] - self.strides = [-1, -2] - - -class TestSliceAssignAxes1Op(TestSliceAssignOp): - def init_case(self): - self.inputs = { - "inputs": np.random.random([121, 2]).astype("float32"), - "assign": np.zeros([121, 1]).astype("float32") - } - self.axes = [1] - self.starts = [0] - self.ends = [1] - self.strides = [1] - - def build_paddle_program(self, target): - res = self.inputs["inputs"].copy() - - for row_id in range(self.inputs["inputs"].shape[0]): - res[row_id][self.starts[0]:self.ends[0]:self. - strides[0]] = self.inputs["assign"][row_id] - - pd_res = paddle.to_tensor(res, stop_gradient=True) - self.paddle_outputs = [pd_res] - - -class TestSliceAssignAxes1Case1(TestSliceAssignAxes1Op): - def init_case(self): - self.inputs = { - "inputs": np.random.random([121, 2]).astype("float32"), - "assign": np.zeros([121, 1]).astype("float32") - } - self.axes = [1] - self.starts = [1] - self.ends = [2] - self.strides = [1] - - -class TestSliceAssignAxes1Case2(TestSliceAssignAxes1Op): - def init_case(self): - self.inputs = { - "inputs": np.random.random([121, 2]).astype("float32"), - "assign": np.zeros([121, 1]).astype("float32") - } - self.axes = [1] - self.starts = [1] - self.ends = [0] - self.strides = [-1] - - -class TestSliceAssignAxes2Op(TestSliceAssignOp): - def init_case(self): - self.inputs = { - "inputs": np.random.random([121, 2, 2]).astype("float32"), - "assign": np.zeros([121, 2, 1]).astype("float32") - } - self.axes = [2] - self.starts = [0] - self.ends = [1] - self.strides = [1] - - def build_paddle_program(self, target): - res = self.inputs["inputs"].copy() - - row_len = self.num_of_slice(self.starts[0], self.ends[0], - self.strides[0]) - - for row_id in range(self.inputs["inputs"].shape[0]): - for col_id in range(self.inputs["inputs"].shape[1]): - res[row_id][col_id][self.starts[0]:self.ends[0]:self. - strides[0]] = self.inputs["assign"][ - row_id][col_id] - - pd_res = paddle.to_tensor(res, stop_gradient=True) - self.paddle_outputs = [pd_res] - - -class TestSliceAssignAxes2Case1(TestSliceAssignAxes2Op): - def init_case(self): - self.inputs = { - "inputs": np.random.random([121, 2, 2]).astype("float32"), - "assign": np.zeros([121, 2, 1]).astype("float32") - } - self.axes = [2] - self.starts = [1] - self.ends = [2] - self.strides = [1] - - -class TestSliceAssignAxes2Case2(TestSliceAssignAxes2Op): - def init_case(self): - self.inputs = { - "inputs": np.random.random([121, 2, 2]).astype("float32"), - "assign": np.zeros([121, 2, 1]).astype("float32") - } - self.axes = [2] - self.starts = [1] - self.ends = [0] - self.strides = [-1] +class TestSliceAssignOpLegacyTest(TestCaseHelper): + def init_attrs(self): + self.class_name = "TestSliceAssignOpLegacyTest" + self.cls = TestSliceAssignOp + self.inputs = [ + { + "inputs_shape": [10, 12], + "assign_shape": [3, 3], + "axes": [0, 1], + "starts": [2, 2], + "ends": [5, 5], + "strides": [1, 1] + }, + { + "inputs_shape": [10, 12], + "assign_shape": [5, 5], + "axes": [0, 1], + "starts": [1, 2], + "ends": [6, 1000], + "strides": [1, 2] + }, + { + "inputs_shape": [10, 12], + "assign_shape": [3, 3], + "axes": [0, 1], + "starts": [2, 1], + "ends": [-1, 7], + "strides": [3, 2] + }, + { + "inputs_shape": [10, 12], + "assign_shape": [6, 5], + "axes": [0, 1], + "starts": [2, 1000], + "ends": [8, 1], + "strides": [1, -2] + }, + { + "inputs_shape": [10, 12], + "assign_shape": [4, 3], + "axes": [0, 1], + "starts": [-1, -2], + "ends": [-5, -8], + "strides": [-1, -2] + }, + { + "inputs_shape": [121, 2], + "assign_shape": [121, 1], + "axes": [1], + "starts": [0], + "ends": [1], + "strides": [1] + }, + { + "inputs_shape": [121, 2], + "assign_shape": [121, 1], + "axes": [1], + "starts": [1], + "ends": [2], + "strides": [1] + }, + { + "inputs_shape": [121, 2], + "assign_shape": [121, 1], + "axes": [1], + "starts": [1], + "ends": [0], + "strides": [-1] + }, + { + "inputs_shape": [121, 2, 2], + "assign_shape": [121, 2, 1], + "axes": [2], + "starts": [0], + "ends": [1], + "strides": [1] + }, + { + "inputs_shape": [121, 2, 2], + "assign_shape": [121, 2, 1], + "axes": [2], + "starts": [1], + "ends": [2], + "strides": [1] + }, + { + "inputs_shape": [121, 2, 2], + "assign_shape": [121, 2, 1], + "axes": [2], + "starts": [1], + "ends": [0], + "strides": [-1] + }, + ] + self.dtypes = [{"dtype": "float32"}] + self.attrs = [ + { + "assign_zeros": True, + }, + { + "assign_zeros": False, + }, + ] + + +class TestSliceAssignOpShapeTest(TestCaseHelper): + def init_attrs(self): + self.class_name = "TestSliceAssignOpShapeTest" + self.cls = TestSliceAssignOp + self.inputs = [ + { + "inputs_shape": [64], + "assign_shape": [3], + "axes": [0], + "starts": [2], + "ends": [5], + "strides": [1] + }, + { + "inputs_shape": [128, 32], + "assign_shape": [32, 16], + "axes": [0, 1], + "starts": [24, 10], + "ends": [56, 26], + "strides": [1, 1] + }, + { + "inputs_shape": [32, 10, 64], + "assign_shape": [8, 4, 16], + "axes": [0, 1, 2], + "starts": [24, 4, 0], + "ends": [32, 8, 64], + "strides": [1, 1, 4] + }, + { + "inputs_shape": [10, 12, 9, 5], + "assign_shape": [3, 5, 4, 5], + "axes": [0, 1, 2], + "starts": [2, 4, 0], + "ends": [5, 9, 7], + "strides": [1, 1, 2] + }, + { + "inputs_shape": [1], + "assign_shape": [1], + "axes": [0], + "starts": [0], + "ends": [1], + "strides": [1] + }, + { + "inputs_shape": [1, 1, 1, 1, 1], + "assign_shape": [1, 1, 1, 1, 1], + "axes": [0], + "starts": [0], + "ends": [1], + "strides": [1] + }, + { + "inputs_shape": [1024, 1, 2], + "assign_shape": [512, 1, 2], + "axes": [0], + "starts": [128], + "ends": [640], + "strides": [1] + }, + { + "inputs_shape": [2, 4096, 8], + "assign_shape": [2, 2048, 8], + "axes": [1], + "starts": [1024], + "ends": [3072], + "strides": [1] + }, + ] + self.dtypes = [ + { + "dtype": "float32" + }, + ] + self.attrs = [ + { + "assign_zeros": False, + }, + ] + + +class TestSliceAssignOpDtypeTest(TestCaseHelper): + def init_attrs(self): + self.class_name = "TestSliceAssignOpDtypeTest" + self.cls = TestSliceAssignOp + self.inputs = [ + { + "inputs_shape": [10, 12, 9, 5], + "assign_shape": [3, 5, 4, 5], + "axes": [0, 1, 2], + "starts": [2, 4, 0], + "ends": [5, 9, 7], + "strides": [1, 1, 2] + }, + ] + self.dtypes = [ + { + "dtype": "float16" + }, + { + "dtype": "float32" + }, + { + "dtype": "float64" + }, + { + "dtype": "int32" + }, + { + "dtype": "int64" + }, + { + "dtype": "bool" + }, + ] + self.attrs = [ + { + "assign_zeros": False, + }, + ] + + +class TestSliceAssignOpAxesTest(TestCaseHelper): + def init_attrs(self): + self.class_name = "TestSliceAssignOpAxesTest" + self.cls = TestSliceAssignOp + self.inputs = [ + { + "inputs_shape": [128, 32], + "assign_shape": [128, 16], + "axes": [1], + "starts": [10], + "ends": [26], + "strides": [1] + }, + { + "inputs_shape": [32, 10, 64], + "assign_shape": [8, 10, 16], + "axes": [0, 2], + "starts": [24, 0], + "ends": [32, 64], + "strides": [1, 4] + }, + { + "inputs_shape": [10, 12, 9, 5], + "assign_shape": [3, 12, 9, 3], + "axes": [0, 3], + "starts": [2, 0], + "ends": [5, 3], + "strides": [1, 1] + }, + ] + self.dtypes = [ + { + "dtype": "float32" + }, + ] + self.attrs = [ + { + "assign_zeros": False, + }, + ] + + +class TestSliceAssignOpStridesTest(TestCaseHelper): + def init_attrs(self): + self.class_name = "TestSliceAssignOpStridesTest" + self.cls = TestSliceAssignOp + self.inputs = [ + { + "inputs_shape": [128, 32], + "assign_shape": [8, 16], + "axes": [0, 1], + "starts": [0, 0], + "ends": [128, 32], + "strides": [16, 2] + }, + { + "inputs_shape": [32, 10, 64], + "assign_shape": [8, 10, 16], + "axes": [0, 2], + "starts": [16, 0], + "ends": [32, 64], + "strides": [2, 4] + }, + { + "inputs_shape": [8, 16, 32, 64, 128], + "assign_shape": [8, 8, 8, 8, 8], + "axes": [0, 1, 2, 3, 4], + "starts": [0, 0, 0, 0, 0], + "ends": [8, 16, 32, 64, 128], + "strides": [1, 2, 4, 8, 16] + }, + ] + self.dtypes = [ + { + "dtype": "float32" + }, + ] + self.attrs = [ + { + "assign_zeros": False, + }, + ] if __name__ == "__main__": - unittest.main() + TestSliceAssignOpLegacyTest().run() + TestSliceAssignOpShapeTest().run() + TestSliceAssignOpDtypeTest().run() + TestSliceAssignOpAxesTest().run() + TestSliceAssignOpStridesTest().run() diff --git a/python/tests/ops/test_slice_op.py b/python/tests/ops/test_slice_op.py index 50cebc89e9..1867e4f140 100644 --- a/python/tests/ops/test_slice_op.py +++ b/python/tests/ops/test_slice_op.py @@ -14,44 +14,59 @@ # See the License for the specific language governing permissions and # limitations under the License. -import unittest -import numpy as np -from op_test import OpTest, OpTestTool import paddle -import cinn from cinn.frontend import * from cinn.common import * +from op_test import OpTest, OpTestTool +from op_test_helper import TestCaseHelper @OpTestTool.skip_if(not is_compiled_with_cuda(), "x86 test will be skipped due to timeout.") class TestSliceOp(OpTest): def setUp(self): - self.init_case() + print(f"\nRunning {self.__class__.__name__}: {self.case}") + self.inputs = {} + self.prepare_inputs() - def init_case(self): - self.inputs = {"inputs": np.random.random([10, 12]).astype("float32")} - self.axes = [0, 1] - self.starts = [2, 2] - self.ends = [5, 5] - self.strides = [1, 1] + def prepare_inputs(self): + self.inputs = { + "inputs": self.random(self.case["shape"], self.case["dtype"]) + } + self.axes = self.case["axes"] + self.starts = self.case["starts"] + self.ends = self.case["ends"] + self.strides = self.case["strides"] + self.decrease_axis = self.case["decrease_axis"] def build_paddle_program(self, target): x = paddle.to_tensor(self.inputs["inputs"], stop_gradient=True) res = paddle.strided_slice(x, self.axes, self.starts, self.ends, self.strides) + out_shape = [] + for i in range(len(res.shape)): + if i in self.decrease_axis: + self.assertEqual(res.shape[i], 1) + else: + out_shape.append(res.shape[i]) + + if len(out_shape) == 0: + out_shape = [1] + res = paddle.reshape(res, out_shape) self.paddle_outputs = [res] def build_cinn_program(self, target): builder = NetBuilder("slice") inputs = builder.create_input( - Float(32), self.inputs["inputs"].shape, "inputs") + self.nptype2cinntype(self.inputs["inputs"].dtype), + self.inputs["inputs"].shape, "inputs") out = builder.slice( inputs, axes=self.axes, starts=self.starts, ends=self.ends, - strides=self.strides) + strides=self.strides, + decrease_axis=self.decrease_axis) prog = builder.build() res = self.get_cinn_output(prog, target, [inputs], @@ -62,102 +77,305 @@ def test_check_results(self): self.check_outputs_and_grads(all_equal=True) -class TestSliceCase1(TestSliceOp): - def init_case(self): - self.inputs = {"inputs": np.random.random([10, 12]).astype("float32")} - self.axes = [0, 1] - self.starts = [1, 2] - self.ends = [6, 1000] - self.strides = [1, 2] - +class TestSliceOpLegacyTestCase(TestCaseHelper): + def init_attrs(self): + self.class_name = "TestSliceOpLegacyTestCase" + self.cls = TestSliceOp + self.inputs = [ + { + "shape": [10, 12], + "axes": [0, 1], + "starts": [2, 2], + "ends": [5, 5], + "strides": [1, 1], + "decrease_axis": [] + }, + { + "shape": [10, 12], + "axes": [0, 1], + "starts": [1, 2], + "ends": [6, 1000], + "strides": [1, 2], + "decrease_axis": [] + }, + { + "shape": [10, 12], + "axes": [0, 1], + "starts": [2, 1], + "ends": [-1, 7], + "strides": [3, 2], + "decrease_axis": [] + }, + { + "shape": [10, 12], + "axes": [0, 1], + "starts": [2, 1000], + "ends": [8, 1], + "strides": [1, -2], + "decrease_axis": [] + }, + { + "shape": [10, 12], + "axes": [0, 1], + "starts": [-1, -2], + "ends": [-5, -8], + "strides": [-1, -2], + "decrease_axis": [] + }, + { + "shape": [10, 12], + "axes": [0, 1], + "starts": [2, 2], + "ends": [5, 3], + "strides": [1, 1], + "decrease_axis": [1], + }, + { + "shape": [10, 12], + "axes": [0, 1], + "starts": [2, 2], + "ends": [3, 3], + "strides": [1, 1], + "decrease_axis": [0, 1], + }, + ] + self.dtypes = [{"dtype": "float32"}] + self.attrs = [] -class TestSliceCase2(TestSliceOp): - def init_case(self): - self.inputs = {"inputs": np.random.random([10, 12]).astype("float32")} - self.axes = [0, 1] - self.starts = [2, 1] - self.ends = [-1, 7] - self.strides = [3, 2] +class TestSliceOpShapeTest(TestCaseHelper): + def init_attrs(self): + self.class_name = "TestSliceOpShapeTest" + self.cls = TestSliceOp + self.inputs = [ + { + "shape": [64], + "axes": [0], + "starts": [2], + "ends": [5], + "strides": [1], + "decrease_axis": [] + }, + { + "shape": [128, 32], + "axes": [0, 1], + "starts": [24, 10], + "ends": [56, 26], + "strides": [1, 1], + "decrease_axis": [] + }, + { + "shape": [32, 10, 64], + "axes": [0, 1, 2], + "starts": [24, 4, 0], + "ends": [32, 8, 64], + "strides": [1, 1, 4], + "decrease_axis": [] + }, + { + "shape": [10, 12, 9, 5], + "axes": [0, 1, 2], + "starts": [2, 4, 0], + "ends": [5, 9, 7], + "strides": [1, 1, 2], + "decrease_axis": [] + }, + { + "shape": [1], + "axes": [0], + "starts": [0], + "ends": [1], + "strides": [1], + "decrease_axis": [] + }, + { + "shape": [1, 1, 1, 1, 1], + "axes": [0], + "starts": [0], + "ends": [1], + "strides": [1], + "decrease_axis": [] + }, + { + "shape": [1024, 1, 2], + "axes": [0], + "starts": [128], + "ends": [640], + "strides": [1], + "decrease_axis": [] + }, + { + "shape": [2, 4096, 8], + "axes": [1], + "starts": [1024], + "ends": [3072], + "strides": [1], + "decrease_axis": [] + }, + ] + self.dtypes = [{"dtype": "float32"}] + self.attrs = [] -class TestSliceCase3(TestSliceOp): - def init_case(self): - self.inputs = {"inputs": np.random.random([10, 12]).astype("float32")} - self.axes = [0, 1] - self.starts = [2, 1000] - self.ends = [8, 1] - self.strides = [1, -2] +class TestSliceOpDtypeTest(TestCaseHelper): + def init_attrs(self): + self.class_name = "TestSliceOpDtypeTest" + self.cls = TestSliceOp + self.inputs = [ + { + "shape": [9, 5, 4, 7], + "axes": [0, 1, 3], + "starts": [2, 2, 0], + "ends": [5, 5, 6], + "strides": [1, 2, 4], + "decrease_axis": [] + }, + ] + self.dtypes = [ + { + "dtype": "float16" + }, + { + "dtype": "float32" + }, + { + "dtype": "float64" + }, + { + "dtype": "int32" + }, + { + "dtype": "int64" + }, + { + "dtype": "bool" + }, + ] + self.attrs = [] -class TestSliceCase4(TestSliceOp): - def init_case(self): - self.inputs = {"inputs": np.random.random([10, 12]).astype("float32")} - self.axes = [0, 1] - self.starts = [-1, -2] - self.ends = [-5, -8] - self.strides = [-1, -2] +class TestSliceOpAxesTest(TestCaseHelper): + def init_attrs(self): + self.class_name = "TestSliceOpAxesTest" + self.cls = TestSliceOp + self.inputs = [ + { + "shape": [128, 32], + "axes": [1], + "starts": [10], + "ends": [26], + "strides": [1], + "decrease_axis": [] + }, + { + "shape": [32, 10, 64], + "axes": [0, 2], + "starts": [24, 0], + "ends": [32, 64], + "strides": [1, 4], + "decrease_axis": [] + }, + { + "shape": [10, 12, 9, 5], + "axes": [0, 3], + "starts": [2, 0], + "ends": [5, 3], + "strides": [1, 1], + "decrease_axis": [] + }, + ] + self.dtypes = [{"dtype": "float32"}] + self.attrs = [] -@OpTestTool.skip_if(not is_compiled_with_cuda(), - "x86 test will be skipped due to timeout.") -class TestSliceOpWithDecreaseAxis(OpTest): - def setUp(self): - self.init_case() - def init_case(self): - self.inputs = {"inputs": np.random.random([10, 12]).astype("float32")} - self.axes = [0, 1] - self.starts = [2, 2] - self.ends = [5, 3] - self.strides = [1, 1] - self.decrease_axis = [1] - - def build_paddle_program(self, target): - x = paddle.to_tensor(self.inputs["inputs"], stop_gradient=True) - y = paddle.strided_slice(x, self.axes, self.starts, self.ends, - self.strides) - out_shape = [] - for i in range(len(y.shape)): - if i in self.decrease_axis: - self.assertEqual(y.shape[i], 1) - else: - out_shape.append(y.shape[i]) - - if len(out_shape) == 0: - out_shape = [1] - res = paddle.reshape(y, out_shape) - self.paddle_outputs = [res] - - def build_cinn_program(self, target): - builder = NetBuilder("slice") - inputs = builder.create_input( - Float(32), self.inputs["inputs"].shape, "inputs") - out = builder.slice( - inputs, - axes=self.axes, - starts=self.starts, - ends=self.ends, - strides=self.strides, - decrease_axis=self.decrease_axis) - - prog = builder.build() - res = self.get_cinn_output(prog, target, [inputs], - [self.inputs["inputs"]], [out]) - self.cinn_outputs = res - - def test_check_results(self): - self.check_outputs_and_grads(all_equal=True) +class TestSliceOpStridesTest(TestCaseHelper): + def init_attrs(self): + self.class_name = "TestSliceOpStridesTest" + self.cls = TestSliceOp + self.inputs = [ + { + "shape": [128, 32], + "axes": [0, 1], + "starts": [0, 0], + "ends": [128, 32], + "strides": [16, 2], + "decrease_axis": [] + }, + { + "shape": [32, 10, 64], + "axes": [0, 2], + "starts": [16, 0], + "ends": [32, 64], + "strides": [2, 4], + "decrease_axis": [] + }, + { + "shape": [8, 16, 32, 64, 128], + "axes": [0, 1, 2, 3, 4], + "starts": [0, 0, 0, 0, 0], + "ends": [8, 16, 32, 64, 128], + "strides": [1, 2, 4, 8, 16], + "decrease_axis": [] + }, + ] + self.dtypes = [{"dtype": "float32"}] + self.attrs = [] -class TestSliceOpWithDecreaseAxisCase1(TestSliceOpWithDecreaseAxis): - def init_case(self): - self.inputs = {"inputs": np.random.random([10, 12]).astype("float32")} - self.axes = [0, 1] - self.starts = [2, 2] - self.ends = [3, 3] - self.strides = [1, 1] - self.decrease_axis = [0, 1] +class TestSliceOpDecreaseAxisTest(TestCaseHelper): + def init_attrs(self): + self.class_name = "TestSliceOpDecreaseAxisTest" + self.cls = TestSliceOp + self.inputs = [ + { + "shape": [1], + "axes": [0], + "starts": [0], + "ends": [1], + "strides": [1], + "decrease_axis": [0] + }, + { + "shape": [1, 1, 1, 1, 1], + "axes": [0], + "starts": [0], + "ends": [1], + "strides": [1], + "decrease_axis": [1, 2, 3] + }, + { + "shape": [1, 1, 1, 1, 1], + "axes": [0], + "starts": [0], + "ends": [1], + "strides": [1], + "decrease_axis": [0, 1, 2, 3, 4] + }, + { + "shape": [128, 32], + "axes": [0, 1], + "starts": [127, 0], + "ends": [128, 32], + "strides": [16, 2], + "decrease_axis": [0] + }, + { + "shape": [32, 10, 64], + "axes": [0, 2], + "starts": [31, 32], + "ends": [32, 33], + "strides": [2, 4], + "decrease_axis": [0, 2] + }, + ] + self.dtypes = [{"dtype": "float32"}] + self.attrs = [] if __name__ == "__main__": - unittest.main() + TestSliceOpLegacyTestCase().run() + TestSliceOpShapeTest().run() + TestSliceOpDtypeTest().run() + TestSliceOpAxesTest().run() + TestSliceOpStridesTest().run() + TestSliceOpDecreaseAxisTest().run()