# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Test set_value op in static graph mode import sys import unittest import numpy as np sys.path.append("../") from get_test_cover_info import ( XPUOpTestWrapper, create_test_class, get_xpu_op_support_types, ) from op_test import convert_float_to_uint16 from op_test_xpu import XPUOpTest import paddle class XPUTestSetValueOp(XPUOpTestWrapper): def __init__(self): self.op_name = 'set_value' self.use_dynamic_create_class = False class XPUTestSetValueBase(XPUOpTest): def setUp(self): paddle.enable_static() self.__class__.op_type = "set_value" self.__class__.no_need_check_grad = True self.place = paddle.XPUPlace(0) self.set_dtype() self.set_value() self.set_shape() dtype = self.dtype if self.dtype == "bfloat16": dtype = "float32" self.data = np.ones(self.shape).astype(dtype) self.program = paddle.static.Program() def set_shape(self): self.shape = [2, 3, 4] def set_value(self): self.value = 6 def set_dtype(self): self.dtype = self.in_type if self.in_type == np.bool_: self.dtype = "bool" elif self.in_type == np.uint16: self.dtype = "bfloat16" def _call_setitem(self, x): x[0, 0] = self.value def _call_setitem_static_api(self, x): x = paddle.static.setitem(x, (0, 0), self.value) return x def _get_answer(self): self.data[0, 0] = self.value class XPUTestSetValueApi(XPUTestSetValueBase): def _run_static(self): paddle.enable_static() with paddle.static.program_guard(self.program): x = paddle.ones(shape=self.shape, dtype=self.dtype) x = self._call_setitem_static_api(x) exe = paddle.static.Executor(self.place) out = exe.run(self.program, fetch_list=[x]) paddle.disable_static() return out def _run_dynamic(self): paddle.disable_static() x = paddle.ones(shape=self.shape, dtype=self.dtype) self._call_setitem(x) out = x.numpy() paddle.enable_static() return out def test_api(self): self._get_answer() static_out = self._run_static() dynamic_out = self._run_dynamic() if self.dtype == "bfloat16": self.data = convert_float_to_uint16(self.data) error_msg = ( "\nIn {} mode: \nExpected res = \n{}, \n\nbut received : \n{}" ) self.assertTrue( (self.data == static_out).all(), msg=error_msg.format("static", self.data, static_out), ) self.assertTrue( (self.data == dynamic_out).all(), msg=error_msg.format("dynamic", self.data, dynamic_out), ) # 1. Test different type of item: int, Python slice, Paddle Tensor # 1.1 item is int class XPUTestSetValueItemInt(XPUTestSetValueApi): def _call_setitem(self, x): x[0] = self.value def _call_setitem_static_api(self, x): x = paddle.static.setitem(x, 0, self.value) return x def _get_answer(self): self.data[0] = self.value class XPUTestSetValueItemInt2(XPUTestSetValueApi): def set_shape(self): self.shape = [6, 6, 6, 6, 6] def _call_setitem(self, x): x[0, 3, 4] = self.value def _call_setitem_static_api(self, x): x = paddle.static.setitem(x, (0, 3, 4), self.value) return x def _get_answer(self): self.data[0, 3, 4] = self.value class XPUTestSetValueItemInt3(XPUTestSetValueApi): def set_shape(self): self.shape = [6, 6, 6, 6, 6] def _call_setitem(self, x): x[1] = self.value def _call_setitem_static_api(self, x): x = paddle.static.setitem(x, (1), self.value) return x def _get_answer(self): self.data[1] = self.value # 1.2 item is slice # 1.2.1 step is 1 class XPUTestSetValueItemSlice(XPUTestSetValueApi): def _call_setitem(self, x): x[0:2] = self.value def _call_setitem_static_api(self, x): x = paddle.static.setitem(x, slice(0, 2), self.value) return x def _get_answer(self): self.data[0:2] = self.value class XPUTestSetValueItemSlice2(XPUTestSetValueApi): def _call_setitem(self, x): x[0:-1] = self.value def _call_setitem_static_api(self, x): x = paddle.static.setitem(x, slice(0, -1), self.value) return x def _get_answer(self): self.data[0:-1] = self.value class XPUTestSetValueItemSlice3(XPUTestSetValueApi): def _call_setitem(self, x): x[0:-1, 0:2] = self.value def _call_setitem_static_api(self, x): x = paddle.static.setitem( x, (slice(0, -1), slice(0, 2)), self.value ) return x def _get_answer(self): self.data[0:-1, 0:2] = self.value class XPUTestSetValueItemSlice4(XPUTestSetValueApi): def _call_setitem(self, x): x[0:, 1:2, :] = self.value def _call_setitem_static_api(self, x): x = paddle.static.setitem( x, (slice(0, None), slice(1, 2), slice(None, None, None)), self.value, ) return x def _get_answer(self): self.data[0:, 1:2, :] = self.value class XPUTestSetValueItemSlice5(XPUTestSetValueApi): def _call_setitem(self, x): x[0:, 1:1, :] = self.value def _call_setitem_static_api(self, x): x = paddle.static.setitem( x, (slice(0), slice(1, 1), slice(None, None, None)), self.value ) return x def _get_answer(self): self.data[0:, 1:1, :] = self.value class XPUTestSetValueItemSliceInWhile(XPUTestSetValueApi): def set_dtype(self): if self.in_type == np.float16: self.dtype = "float32" elif self.in_type == np.bool_: self.dtype = "bool" elif self.in_type == np.uint16: self.dtype = "bfloat16" else: self.dtype = self.in_type def _call_setitem(self, x): def cond(i, x): return i < 1 def body(i, x): x[i] = self.value i = i + 1 return i, x i = paddle.zeros(shape=[], dtype='int32') i, x = paddle.static.nn.while_loop(cond, body, [i, x]) def _call_setitem_static_api(self, x): def cond(i, x): return i < 1 def body(i, x): x = paddle.static.setitem(x, i, self.value) i = i + 1 return i, x i = paddle.zeros(shape=[], dtype='int32') i, x = paddle.static.nn.while_loop(cond, body, [i, x]) return x def _get_answer(self): self.data[0] = self.value # 1.2.2 step > 1 class XPUTestSetValueItemSliceStep(XPUTestSetValueApi): def set_shape(self): self.shape = [5, 5, 5] def _call_setitem(self, x): x[0:2:2] = self.value def _call_setitem_static_api(self, x): x = paddle.static.setitem(x, slice(0, 2, 2), self.value) return x def _get_answer(self): self.data[0:2:2] = self.value class XPUTestSetValueItemSliceStep2(XPUTestSetValueApi): def set_shape(self): self.shape = [7, 5, 5] def _call_setitem(self, x): x[0:-1:3] = self.value def _call_setitem_static_api(self, x): x = paddle.static.setitem(x, slice(0, -1, 3), self.value) return x def _get_answer(self): self.data[0:-1:3] = self.value class XPUTestSetValueItemSliceStep3(XPUTestSetValueApi): def _call_setitem(self, x): x[0:-1, 0:2, ::2] = self.value def _call_setitem_static_api(self, x): x = paddle.static.setitem( x, (slice(0, -1), slice(0, 2), slice(None, None, 2)), self.value ) return x def _get_answer(self): self.data[0:-1, 0:2, ::2] = self.value class XPUTestSetValueItemSliceStep4(XPUTestSetValueApi): def _call_setitem(self, x): x[0:, 1:2:2, :] = self.value def _call_setitem_static_api(self, x): x = paddle.static.setitem( x, (slice(0, None), slice(1, 2, 2), slice(None, None, None)), self.value, ) return x def _get_answer(self): self.data[0:, 1:2:2, :] = self.value # 1.2.3 step < 0 class XPUTestSetValueItemSliceNegativeStep(XPUTestSetValueApi): def set_dtype(self): if self.in_type in [np.float16, np.uint16]: self.dtype = "float32" elif self.in_type == np.bool_: self.dtype = "bool" else: self.dtype = self.in_type def set_shape(self): self.shape = [5, 2] def set_value(self): self.value = np.array([3, 4]) def _call_setitem(self, x): x[5:2:-1] = self.value def _call_setitem_static_api(self, x): x = paddle.static.setitem(x, slice(5, 2, -1), self.value) return x def _get_answer(self): self.data[5:2:-1] = self.value class XPUTestSetValueItemSliceNegativeStep2( XPUTestSetValueItemSliceNegativeStep ): def set_shape(self): self.shape = [5] def set_value(self): self.value = np.array([3, 4]) # print("self.value: \n", self.value) def _call_setitem(self, x): x[1::-1] = self.value def _call_setitem_static_api(self, x): x = paddle.static.setitem(x, slice(1, None, -1), self.value) return x def _get_answer(self): self.data[1::-1] = self.value class XPUTestSetValueItemSliceNegativeStep3( XPUTestSetValueItemSliceNegativeStep ): def set_shape(self): self.shape = [3] def set_value(self): self.value = np.array([3, 4, 5]) def _call_setitem(self, x): x[::-1] = self.value def _call_setitem_static_api(self, x): x = paddle.static.setitem(x, slice(None, None, -1), self.value) return x def _get_answer(self): self.data[::-1] = self.value class XPUTestSetValueItemSliceNegativeStep4(XPUTestSetValueApi): def set_dtype(self): if self.in_type == np.float16: self.dtype = "float32" elif self.in_type == np.bool_: self.dtype = "bool" elif self.in_type == np.uint16: self.dtype = "bfloat16" else: self.dtype = self.in_type def set_shape(self): self.shape = [3, 4, 5] def _call_setitem(self, x): x[2:0:-1, 0:2, ::-1] = self.value def _call_setitem_static_api(self, x): x = paddle.static.setitem( x, (slice(2, 0, -1), slice(0, 2), slice(None, None, -1)), self.value, ) return x def _get_answer(self): self.data[2:0:-1, 0:2, ::-1] = self.value # 1.2.3 step < 0 and stride < -1 class XPUTestSetValueItemSliceNegativeStep5(XPUTestSetValueApi): def set_dtype(self): if self.in_type == np.float16: self.dtype = "float32" elif self.in_type == np.bool_: self.dtype = "bool" else: self.dtype = self.in_type def set_shape(self): self.shape = [5, 5, 5] def _call_setitem(self, x): x[2:-1:-2] = self.value def _call_setitem_static_api(self, x): x = paddle.static.setitem(x, slice(2, -1, -2), self.value) return x def _get_answer(self): paddle.enable_static() with paddle.static.program_guard(self.program): x = paddle.ones(shape=self.shape, dtype=self.dtype) x = self._call_setitem_static_api(x) exe = paddle.static.Executor(paddle.CPUPlace()) self.data = exe.run(self.program, fetch_list=[x]) paddle.disable_static() def test_api(self): self._get_answer() static_out = self._run_static() dynamic_out = self._run_dynamic() error_msg = ( "\nIn {} mode: \nExpected res = \n{}, \n\nbut received : \n{}" ) self.assertTrue( (self.data[0] == static_out[0]).all(), msg=error_msg.format("static", self.data, static_out), ) self.assertTrue( (self.data == dynamic_out).all(), msg=error_msg.format("dynamic", self.data, dynamic_out), ) # 1.3 item is Ellipsis class XPUTestSetValueItemEllipsis1(XPUTestSetValueApi): def _call_setitem(self, x): x[0:, ..., 1:] = self.value def _call_setitem_static_api(self, x): x = paddle.static.setitem( x, (slice(0, None), ..., slice(1, None)), self.value ) return x def _get_answer(self): self.data[0:, ..., 1:] = self.value class XPUTestSetValueItemEllipsis2(XPUTestSetValueApi): def _call_setitem(self, x): x[0:, ...] = self.value def _call_setitem_static_api(self, x): x = paddle.static.setitem(x, (slice(0, None), ...), self.value) return x def _get_answer(self): self.data[0:, ...] = self.value class XPUTestSetValueItemEllipsis3(XPUTestSetValueApi): def _call_setitem(self, x): x[..., 1:] = self.value def _call_setitem_static_api(self, x): x = paddle.static.setitem(x, (..., slice(1, None)), self.value) return x def _get_answer(self): self.data[..., 1:] = self.value class XPUTestSetValueItemEllipsis4(XPUTestSetValueApi): def _call_setitem(self, x): x[...] = self.value def _call_setitem_static_api(self, x): x = paddle.static.setitem(x, (...), self.value) return x def _get_answer(self): self.data[...] = self.value # 1.4 item is Paddle Tensor class XPUTestSetValueItemTensor(XPUTestSetValueApi): def set_dtype(self): if self.in_type == np.float16: self.dtype = "float32" elif self.in_type == np.bool_: self.dtype = "bool" elif self.in_type == np.uint16: self.dtype = "bfloat16" else: self.dtype = self.in_type def _call_setitem(self, x): zero = paddle.full([], 0, dtype="int32") x[zero] = self.value def _call_setitem_static_api(self, x): zero = paddle.full([], 0, dtype="int32") x = paddle.static.setitem(x, zero, self.value) return x def _get_answer(self): self.data[0] = self.value class XPUTestSetValueItemTensor2(XPUTestSetValueItemTensor): def _call_setitem(self, x): zero = paddle.full([], 0, dtype="int32") two = paddle.full([], 2, dtype="int64") x[zero:two] = self.value def _call_setitem_static_api(self, x): zero = paddle.full([], 0, dtype="int32") two = paddle.full([], 2, dtype="int64") x = paddle.static.setitem(x, slice(zero, two), self.value) return x def _get_answer(self): self.data[0:2] = self.value class XPUTestSetValueItemTensor3(XPUTestSetValueItemTensor): def _call_setitem(self, x): zero = paddle.full([], 0, dtype="int32") two = paddle.full([], 2, dtype="int64") x[zero:-1, 0:two] = self.value def _call_setitem_static_api(self, x): zero = paddle.full([], 0, dtype="int32") two = paddle.full([], 2, dtype="int64") x = paddle.static.setitem( x, (slice(zero, -1), slice(0, two)), self.value ) return x def _get_answer(self): self.data[0:-1, 0:2] = self.value class XPUTestSetValueItemTensor4(XPUTestSetValueItemTensor): def _call_setitem(self, x): zero = paddle.full([], 0, dtype="int32") two = paddle.full([], 2, dtype="int64") x[0:-1, zero:2, 0:6:two] = self.value def _call_setitem_static_api(self, x): zero = paddle.full([], 0, dtype="int32") two = paddle.full([], 2, dtype="int64") x = paddle.static.setitem( x, (slice(0, -1), slice(zero, 2), slice(0, 6, two)), self.value ) return x def _get_answer(self): self.data[0:-1, 0:2, ::2] = self.value class XPUTestSetValueItemTensor5(XPUTestSetValueItemTensor): def _call_setitem(self, x): zero = paddle.full([], 0, dtype="int32") two = paddle.full([], 2, dtype="int64") x[zero:, 1:2:two, :] = self.value def _call_setitem_static_api(self, x): zero = paddle.full([], 0, dtype="int32") two = paddle.full([], 2, dtype="int64") x = paddle.static.setitem( x, (slice(zero, None), slice(1, 2, two), slice(None, None, None)), self.value, ) return x def _get_answer(self): self.data[0:, 1:2:2, :] = self.value class XPUTestSetValueItemTensor6(XPUTestSetValueItemTensor): def set_shape(self): self.shape = [3, 4, 5] def _call_setitem(self, x): minus1 = paddle.full([], -1, dtype="int32") zero = paddle.full([], 0, dtype="int32") x[2:zero:minus1, 0:2, 10:-6:minus1] = self.value def _call_setitem_static_api(self, x): minus1 = paddle.full([], -1, dtype="int32") zero = paddle.full([], 0, dtype="int32") x = paddle.static.setitem( x, (slice(2, zero, minus1), slice(0, 2), slice(10, -6, minus1)), self.value, ) return x def _get_answer(self): self.data[2:0:-1, 0:2, ::-1] = self.value # 1.5 item is None class XPUTestSetValueItemNone1(XPUTestSetValueApi): def set_dtype(self): if self.in_type in [np.float16, np.uint16]: self.dtype = "float32" elif self.in_type == np.bool_: self.dtype = "bool" else: self.dtype = self.in_type def _call_setitem(self, x): x[None] = self.value def _call_setitem_static_api(self, x): x = paddle.static.setitem(x, None, self.value) return x def _get_answer(self): self.data[None] = self.value class XPUTestSetValueItemNone2(XPUTestSetValueItemNone1): def _call_setitem(self, x): x[0, None, 1] = self.value def _call_setitem_static_api(self, x): x = paddle.static.setitem(x, (0, None, 1), self.value) return x def _get_answer(self): self.data[0, None, 1] = self.value class XPUTestSetValueItemNone3(XPUTestSetValueItemNone1): def _call_setitem(self, x): x[:, None, None, 1] = self.value def _call_setitem_static_api(self, x): x = paddle.static.setitem( x, (slice(None, None, None), None, None, 1), self.value ) return x def _get_answer(self): self.data[:, None, None, 1] = self.value class XPUTestSetValueItemNone4(XPUTestSetValueItemNone1): def _call_setitem(self, x): x[0, 0, None, 1] = self.value def _call_setitem_static_api(self, x): x = paddle.static.setitem(x, (0, 0, None, 1), self.value) return x def _get_answer(self): self.data[0, 0, None, 1] = self.value class XPUTestSetValueItemNone5(XPUTestSetValueItemNone1): def _call_setitem(self, x): x[0, None, 0, None, 1] = self.value def _call_setitem_static_api(self, x): x = paddle.static.setitem(x, (0, None, 0, None, 1), self.value) return x def _get_answer(self): self.data[0, None, 0, None, 1] = self.value class XPUTestSetValueItemNone6(XPUTestSetValueItemNone1): def _call_setitem(self, x): x[None, 0, 0, None, 0] = self.value def _call_setitem_static_api(self, x): x = paddle.static.setitem(x, (None, 0, 0, None, 0), self.value) return x def _get_answer(self): self.data[None, 0, 0, None, 0] = self.value class XPUTestSetValueItemNone7(XPUTestSetValueItemNone1): def _call_setitem(self, x): x[:, None, 1] = np.zeros(self.shape)[:, None, 0] def _call_setitem_static_api(self, x): x = paddle.static.setitem( x, (slice(None, None, None), None, 1), np.zeros(self.shape)[:, None, 0], ) return x def _get_answer(self): self.data[:, None, 1] = np.zeros(self.shape)[:, None, 0] class XPUTestSetValueItemNone8(XPUTestSetValueItemNone1): def _call_setitem(self, x): x[:, 1, None] = np.zeros(self.shape)[:, 0, None] def _call_setitem_static_api(self, x): x = paddle.static.setitem( x, (slice(None, None, None), 1, None), np.zeros(self.shape)[:, 0, None], ) return x def _get_answer(self): self.data[:, 1, None] = np.zeros(self.shape)[:, 0, None] class XPUTestSetValueItemNone9(XPUTestSetValueItemNone1): def _call_setitem(self, x): x[None, :, 1, ..., None] = np.zeros(self.shape)[0, 0, :, None] def _call_setitem_static_api(self, x): x = paddle.static.setitem( x, (None, slice(None, None, None), 1, ..., None), np.zeros(self.shape)[0, 0, :, None], ) return x def _get_answer(self): self.data[None, :, 1, ..., None] = np.zeros(self.shape)[ 0, 0, :, None ] class XPUTestSetValueItemNone10(XPUTestSetValueItemNone1): def _call_setitem(self, x): x[..., None, :, None] = np.zeros(self.shape)[..., None, :, None] def _call_setitem_static_api(self, x): x = paddle.static.setitem( x, (..., None, slice(None, None, None), None), np.zeros(self.shape)[..., None, :, None], ) return x def _get_answer(self): self.data[..., None, :, None] = np.zeros(self.shape)[ ..., None, :, None ] # 1.6 item is list or Tensor of bol class XPUTestSetValueItemBool1(XPUTestSetValueApi): def set_dtype(self): self.dtype = "float32" def _call_setitem(self, x): x[[True, False]] = self.value def _call_setitem_static_api(self, x): x = paddle.static.setitem(x, [True, False], self.value) return x def _get_answer(self): self.data[[True, False]] = self.value class XPUTestSetValueItemBool2(XPUTestSetValueApi): def set_dtype(self): self.dtype = "float32" def _call_setitem(self, x): x[[False, False]] = self.value def _call_setitem_static_api(self, x): x = paddle.static.setitem(x, [False, False], self.value) return x def _get_answer(self): self.data[[False, False]] = self.value class XPUTestSetValueItemBool3(XPUTestSetValueApi): def set_dtype(self): self.dtype = "float32" def _call_setitem(self, x): x[[False, True]] = np.zeros(self.shape[2]) def _call_setitem_static_api(self, x): x = paddle.static.setitem(x, [False, True], np.zeros(self.shape[2])) return x def _get_answer(self): self.data[[False, True]] = np.zeros(self.shape[2]) class XPUTestSetValueItemBool4(XPUTestSetValueApi): def set_dtype(self): self.dtype = "float32" def _call_setitem(self, x): idx = paddle.assign(np.array([False, True])) x[idx] = np.zeros(self.shape[2]) def _call_setitem_static_api(self, x): idx = paddle.assign(np.array([False, True])) x = paddle.static.setitem(x, idx, np.zeros(self.shape[2])) return x def _get_answer(self): self.data[np.array([False, True])] = np.zeros(self.shape[2]) class XPUTestSetValueItemBool5(XPUTestSetValueApi): def set_dtype(self): self.dtype = "float32" def _call_setitem(self, x): idx = paddle.assign( np.array([[False, True, False], [True, True, False]]) ) x[idx] = self.value def _call_setitem_static_api(self, x): idx = paddle.assign( np.array([[False, True, False], [True, True, False]]) ) x = paddle.static.setitem(x, idx, self.value) return x def _get_answer(self): self.data[np.array([[False, True, False], [True, True, False]])] = ( self.value ) class XPUTestSetValueItemBool6(XPUTestSetValueApi): def set_dtype(self): self.dtype = "float32" def _call_setitem(self, x): x[0, ...] = 0 x[x > 0] = self.value def _call_setitem_static_api(self, x): x = paddle.static.setitem(x, (0, ...), 0) x = paddle.static.setitem(x, x > 0, self.value) return x def _get_answer(self): self.data[0, ...] = 0 self.data[self.data > 0] = self.value # 2. Test different type of value: Tensor # 2.1 value is a Paddle Tensor (int32, int64, float32, bool) def create_test_value_tensor_int32(parent): class XPUTestValueInt(parent): def set_dtype(self): self.dtype = "int32" def _call_setitem(self, x): value = paddle.full(shape=[1], fill_value=3, dtype=self.dtype) x[0, 1] = value def _call_setitem_static_api(self, x): value = paddle.full(shape=[1], fill_value=3, dtype=self.dtype) x = paddle.static.setitem(x, (0, 1), value) return x def _get_answer(self): self.data[0, 1] = 3 cls_name = "{}_{}".format(parent.__name__, "ValueTensorInt32") XPUTestValueInt.__name__ = cls_name globals()[cls_name] = XPUTestValueInt create_test_value_tensor_int32(XPUTestSetValueItemInt) create_test_value_tensor_int32(XPUTestSetValueItemSlice) create_test_value_tensor_int32(XPUTestSetValueItemSlice2) create_test_value_tensor_int32(XPUTestSetValueItemSlice3) create_test_value_tensor_int32(XPUTestSetValueItemSlice4) def create_test_value_tensor_int64(parent): class XPUTestValueInt(parent): def set_dtype(self): self.dtype = "int64" def _call_setitem(self, x): value = paddle.full(shape=[1], fill_value=3, dtype=self.dtype) x[0, 1] = value def _call_setitem_static_api(self, x): value = paddle.full(shape=[1], fill_value=3, dtype=self.dtype) x = paddle.static.setitem(x, (0, 1), value) return x def _get_answer(self): self.data[0, 1] = 3 cls_name = "{}_{}".format(parent.__name__, "ValueTensorInt64") XPUTestValueInt.__name__ = cls_name globals()[cls_name] = XPUTestValueInt create_test_value_tensor_int64(XPUTestSetValueItemInt) create_test_value_tensor_int64(XPUTestSetValueItemSlice) create_test_value_tensor_int64(XPUTestSetValueItemSlice2) create_test_value_tensor_int64(XPUTestSetValueItemSlice3) create_test_value_tensor_int64(XPUTestSetValueItemSlice4) def create_test_value_tensor_fp32(parent): class XPUTestValueInt(parent): def set_dtype(self): self.dtype = "float32" def _call_setitem(self, x): value = paddle.full(shape=[1], fill_value=3, dtype=self.dtype) x[0, 1] = value def _call_setitem_static_api(self, x): value = paddle.full(shape=[1], fill_value=3, dtype=self.dtype) x = paddle.static.setitem(x, (0, 1), value) return x def _get_answer(self): self.data[0, 1] = 3 cls_name = "{}_{}".format(parent.__name__, "ValueTensorFp32") XPUTestValueInt.__name__ = cls_name globals()[cls_name] = XPUTestValueInt create_test_value_tensor_fp32(XPUTestSetValueItemInt) create_test_value_tensor_fp32(XPUTestSetValueItemSlice) create_test_value_tensor_fp32(XPUTestSetValueItemSlice2) create_test_value_tensor_fp32(XPUTestSetValueItemSlice3) create_test_value_tensor_fp32(XPUTestSetValueItemSlice4) def create_test_value_tensor_bool(parent): class XPUTestValueInt(parent): def set_dtype(self): self.dtype = "bool" def _call_setitem(self, x): value = paddle.full( shape=[1], fill_value=False, dtype=self.dtype ) x[0, 1] = value def _call_setitem_static_api(self, x): value = paddle.full( shape=[1], fill_value=False, dtype=self.dtype ) x = paddle.static.setitem(x, (0, 1), value) return x def _get_answer(self): self.data[0, 1] = False cls_name = "{}_{}".format(parent.__name__, "ValueTensorBool") XPUTestValueInt.__name__ = cls_name globals()[cls_name] = XPUTestValueInt create_test_value_tensor_bool(XPUTestSetValueItemInt) create_test_value_tensor_bool(XPUTestSetValueItemSlice) create_test_value_tensor_bool(XPUTestSetValueItemSlice2) create_test_value_tensor_bool(XPUTestSetValueItemSlice3) create_test_value_tensor_bool(XPUTestSetValueItemSlice4) # 3. Test different shape of value class XPUTestSetValueValueShape1(XPUTestSetValueApi): def set_dtype(self): if self.in_type in [np.float16, np.uint16]: self.dtype = "float32" elif self.in_type == np.bool_: self.dtype = "bool" else: self.dtype = self.in_type def set_value(self): self.value = np.array([3, 4, 5, 6]) # shape is (4,) def _call_setitem(self, x): x[0] = self.value def _call_setitem_static_api(self, x): x = paddle.static.setitem(x, 0, self.value) return x def _get_answer(self): self.data[0] = self.value class XPUTestSetValueValueShape2(XPUTestSetValueValueShape1): def set_value(self): self.value = np.array([[3, 4, 5, 6]]) # shape is (1,4) def _call_setitem(self, x): x[0:1] = self.value def _call_setitem_static_api(self, x): x = paddle.static.setitem(x, slice(0, 1), self.value) return x def _get_answer(self): self.data[0:1] = self.value class XPUTestSetValueValueShape3(XPUTestSetValueValueShape1): def set_value(self): self.value = np.array( [[1, 1, 1, 1], [2, 2, 2, 2], [3, 3, 3, 3]] ) # shape is (3,4) def _call_setitem(self, x): x[0] = self.value def _call_setitem_static_api(self, x): x = paddle.static.setitem(x, 0, self.value) return x def _get_answer(self): self.data[0] = self.value class XPUTestSetValueValueShape4(XPUTestSetValueValueShape1): def set_value(self): self.value = np.array( [[1, 1, 1, 1], [2, 2, 2, 2], [3, 3, 3, 3]] ).astype(self.dtype) # shape is (3,4) def _call_setitem(self, x): x[0] = paddle.assign(self.value) # x is Paddle.Tensor def _call_setitem_static_api(self, x): x = paddle.static.setitem(x, 0, paddle.assign(self.value)) return x def _get_answer(self): self.data[0] = self.value class XPUTestSetValueValueShape5(XPUTestSetValueValueShape1): def set_value(self): self.value = np.array([3, 3, 3]).astype(self.dtype) def set_shape(self): self.shape = [3, 4] def _call_setitem(self, x): x[:, 0] = paddle.assign(self.value) # x is Paddle.Tensor def _call_setitem_static_api(self, x): x = paddle.static.setitem( x, (slice(None, None, None), 0), paddle.assign(self.value) ) return x def _get_answer(self): self.data[:, 0] = self.value # 4. Test error class XPUTestError(XPUTestSetValueBase): def _value_type_error(self): with self.assertRaisesRegex( TypeError, "Only support to assign an integer, float, numpy.ndarray or paddle.Tensor", ): x = paddle.ones(shape=self.shape, dtype=self.dtype) value = [1] if paddle.in_dynamic_mode(): x[0] = value else: x = paddle.static.setitem(x, 0, value) def _dtype_error(self): with self.assertRaisesRegex( TypeError, "When assign a numpy.ndarray, integer or float to a paddle.Tensor, ", ): y = paddle.ones(shape=self.shape, dtype="float16") y[0] = 1 def _step_error(self): with self.assertRaisesRegex(ValueError, "step can not be 0"): x = paddle.ones(shape=self.shape, dtype=self.dtype) if paddle.in_dynamic_mode(): x[0:1:0] = self.value else: x = paddle.static.setitem(x, slice(0, 1, 0), self.value) def _ellipsis_error(self): with self.assertRaisesRegex( IndexError, "An index can only have a single ellipsis" ): x = paddle.ones(shape=self.shape, dtype=self.dtype) x[..., ...] = self.value with self.assertRaisesRegex(ValueError, "the start or end is None"): x = paddle.ones(shape=self.shape, dtype=self.dtype) one = paddle.ones([1]) x[::one] = self.value def _bool_list_error(self): with self.assertRaises(IndexError): x = paddle.ones(shape=self.shape, dtype=self.dtype) if paddle.in_dynamic_mode(): x[[True, False], [True, False]] = 0 else: x = paddle.static.setitem( x, ([True, False], [True, False]), 0 ) def _bool_tensor_error(self): with self.assertRaises(IndexError): x = paddle.ones(shape=self.shape, dtype=self.dtype) idx = paddle.assign([True, False, True]) if paddle.in_dynamic_mode(): x[idx] = 0 else: x = paddle.static.setitem(x, idx, 0) def _broadcast_mismatch(self): program = paddle.static.Program() with paddle.static.program_guard(program): x = paddle.ones(shape=self.shape, dtype=self.dtype) value = np.array([3, 4, 5, 6, 7]) x = paddle.static.setitem(x, 0, value) exe = paddle.static.Executor(paddle.XPUPlace(0)) with self.assertRaises(ValueError): exe.run(program) def test_error(self): paddle.enable_static() with paddle.static.program_guard(self.program): self._value_type_error() self._bool_list_error() self._bool_tensor_error() self._broadcast_mismatch() # 5. Test backward class XPUTestBackward(XPUOpTest): def setUp(self): self.__class__.op_type = "set_value" self.__class__.no_need_check_grad = True self.place = paddle.XPUPlace(0) def test_static(self): paddle.enable_static() main_program = paddle.static.Program() startup_program = paddle.static.Program() x_np = np.random.random(size=(4, 4)).astype('float32') y_np = np.random.random(size=(4, 4)).astype('float32') label_np = np.random.randint(2, size=(4, 1)).astype('int64') with paddle.static.program_guard(main_program, startup_program): x = paddle.static.data(name="x", shape=[4, 4], dtype='float32') y = paddle.static.data(name="y", shape=[4, 4], dtype='float32') x.stop_gradient = False y.stop_gradient = False label = paddle.static.data( name="label", shape=[4, 1], dtype='int64' ) z = paddle.add(x, y) var = y[0, :] z = paddle.static.setitem(z, (0, slice(None)), var) prediction = paddle.static.nn.fc( x=z, size=2, activation='softmax' ) cost = paddle.nn.functional.cross_entropy( input=prediction, label=label ) loss = paddle.mean(cost) sgd = paddle.optimizer.SGD(learning_rate=0.01) sgd.minimize(loss) exe = paddle.static.Executor(self.place) exe.run(startup_program) if paddle.framework.use_pir_api(): exe.run( main_program, feed={"x": x_np, "y": y_np, "label": label_np}, fetch_list=[], ) else: var_grad, z_grad = exe.run( main_program, feed={"x": x_np, "y": y_np, "label": label_np}, fetch_list=[var.name + "@GRAD", z.name + "@GRAD"], ) self.assertTrue((var_grad == z_grad[0, :]).all()) paddle.disable_static() class XPUTestGradientTruncated(XPUOpTest): def setUp(self): self.__class__.op_type = "set_value" self.__class__.no_need_check_grad = True self.place = paddle.XPUPlace(0) def test_consistent_with_competitor(self): paddle.disable_static() def set_value(t, value): a = t * t a[0, 1] = value y = a * a return y.sum() # case 1 array = np.arange(1, 1 + 2 * 3 * 4, dtype="float32").reshape( [1, 2, 1, 3, 1, 4] ) value = np.arange(100, 104, dtype="float32").reshape(1, 4) inps = paddle.to_tensor(array, stop_gradient=False) value = paddle.to_tensor(value, stop_gradient=False) loss = set_value(inps, value) loss.backward() value_grad = np.array([[600.0, 606.0, 612.0, 618.0]]) input_grad = np.array( [ [ [ [ [[4.0, 32.0, 108.0, 256.0]], [[500.0, 864.0, 1372.0, 2048.0]], [[2916.0, 4000.0, 5324.0, 6912.0]], ] ], [ [ [[0.0, 0.0, 0.0, 0.0]], [[0.0, 0.0, 0.0, 0.0]], [[0.0, 0.0, 0.0, 0.0]], ] ], ] ] ) np.testing.assert_array_equal( inps.grad.numpy(), input_grad, err_msg=f'The gradient of value should be \n{input_grad},\n but received {inps.grad.numpy()}', ) np.testing.assert_array_equal( value.grad.numpy(), value_grad, err_msg=f'The gradient of input should be \n{value_grad},\n but received {value.grad.numpy()}', ) # case 2 array = np.arange(1, 2 * 3 * 4 + 1, dtype="float32").reshape( [4, 2, 3] ) value = np.arange(100, 100 + 1, dtype="float32") inps2 = paddle.to_tensor(array, stop_gradient=False) value2 = paddle.to_tensor(value, stop_gradient=False) loss = set_value(inps2, value2) loss.backward() value_grad2 = np.array([600.0]) input_grad2 = np.array( [ [[4.0, 32.0, 108.0], [0.0, 0.0, 0.0]], [[1372.0, 2048.0, 2916.0], [4000.0, 5324.0, 6912.0]], [[8788.0, 10976.0, 13500.0], [16384.0, 19652.0, 23328.0]], [[27436.0, 32000.0, 37044.0], [42592.0, 48668.0, 55296.0]], ] ) np.testing.assert_array_equal( inps2.grad.numpy(), input_grad2, err_msg=f'The gradient of value should be \n{input_grad},\n but received {inps2.grad.numpy()}', ) np.testing.assert_array_equal( value2.grad.numpy(), value_grad2, err_msg=f'The gradient of input should be \n{value_grad},\n but received {value2.grad.numpy()}', ) # case 3 def set_value3(t, value): a = t * t a[0, :, 0, :] = value y = a * a return y.sum() array = np.arange(1, 1 + 2 * 3 * 4, dtype="float32").reshape( [4, 3, 1, 1, 2, 1] ) value = np.arange(100, 100 + 2, dtype="float32").reshape(1, 2, 1) inps = paddle.to_tensor(array, stop_gradient=False) value = paddle.to_tensor(value, stop_gradient=False) loss = set_value3(inps, value) loss.backward() value_grad = np.array([[[600.0], [606.0]]]) input_grad = np.array( [ [ [[[[0.0], [0.0]]]], [[[[0.0], [0.0]]]], [[[[0.0], [0.0]]]], ], [ [[[[1372.0], [2048.0]]]], [[[[2916.0], [4000.0]]]], [[[[5324.0], [6912.0]]]], ], [ [[[[8788.0], [10976.0]]]], [[[[13500.0], [16384.0]]]], [[[[19652.0], [23328.0]]]], ], [ [[[[27436.0], [32000.0]]]], [[[[37044.0], [42592.0]]]], [[[[48668.0], [55296.0]]]], ], ] ) np.testing.assert_array_equal( inps.grad.numpy(), input_grad, err_msg=f'The gradient of value should be \n{input_grad},\n but received {inps.grad.numpy()}', ) np.testing.assert_array_equal( value.grad.numpy(), value_grad, err_msg=f'The gradient of input should be \n{value_grad},\n but received {value.grad.numpy()}', ) # case 4: step >0 def set_value4(t, value): a = t * t a[0, :, 0, ::3] = value y = a * a return y.sum() array = np.arange(1, 1 + 2 * 3 * 4, dtype="float32").reshape( [2, 3, 1, 4, 1] ) value = np.arange(100, 100 + 2, dtype="float32").reshape(1, 2, 1) inps = paddle.to_tensor(array, stop_gradient=False) value = paddle.to_tensor(value, stop_gradient=False) loss = set_value4(inps, value) loss.backward() value_grad = np.array([[[600.0], [606.0]]]) input_grad = np.array( [ [ [[[0.0], [32.0], [108.0], [0.0]]], [[[0.0], [864.0], [1372.0], [0.0]]], [[[0.0], [4000.0], [5324.0], [0.0]]], ], [ [[[8788.0], [10976.0], [13500.0], [16384.0]]], [[[19652.0], [23328.0], [27436.0], [32000.0]]], [[[37044.0], [42592.0], [48668.0], [55296.0]]], ], ] ) np.testing.assert_array_equal( inps.grad.numpy(), input_grad, err_msg=f'The gradient of value should be \n{input_grad},\n but received {inps.grad.numpy()}', ) np.testing.assert_array_equal( value.grad.numpy(), value_grad, err_msg=f'The gradient of input should be \n{value_grad},\n but received {value.grad.numpy()}', ) # case 5:a[0].shape==value.shape def set_value5(t, value): a = t * t a[0] = value y = a * a return y.sum() array = np.arange(1, 1 + 2 * 3 * 4, dtype="float32").reshape( [2, 3, 4] ) value = np.arange(100, 100 + 12, dtype="float32").reshape(3, 4) inps = paddle.to_tensor(array, stop_gradient=False) value = paddle.to_tensor(value, stop_gradient=False) loss = set_value5(inps, value) loss.backward() value_grad = np.array( [ [200.0, 202.0, 204.0, 206.0], [208.0, 210.0, 212.0, 214.0], [216.0, 218.0, 220.0, 222.0], ] ) input_grad = np.array( [ [ [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], ], [ [8788.0, 10976.0, 13500.0, 16384.0], [19652.0, 23328.0, 27436.0, 32000.0], [37044.0, 42592.0, 48668.0, 55296.0], ], ] ) np.testing.assert_array_equal( inps.grad.numpy(), input_grad, err_msg=f'The gradient of value should be \n{input_grad},\n but received {inps.grad.numpy()}', ) np.testing.assert_array_equal( value.grad.numpy(), value_grad, err_msg=f'The gradient of input should be \n{value_grad},\n but received {value.grad.numpy()}', ) # case 6: pass stop_gradient from value to x x = paddle.zeros([8, 8], dtype='float32') value = paddle.to_tensor([10], dtype='float32', stop_gradient=False) self.assertTrue(x.stop_gradient) self.assertTrue(x.is_leaf) x[0, :] = value self.assertTrue(not x.stop_gradient) self.assertTrue(not x.is_leaf) class XPUTestSetValueInplace(XPUOpTest): def setUp(self): self.__class__.op_type = "set_value" self.__class__.no_need_check_grad = True self.place = paddle.XPUPlace(0) def test_inplace(self): paddle.disable_static() with paddle.base.dygraph.guard(): paddle.seed(100) a = paddle.rand(shape=[1, 4]) a.stop_gradient = False b = a[:] * 1 c = b b[paddle.zeros([], dtype='int32')] = 1.0 self.assertTrue(id(b) == id(c)) np.testing.assert_array_equal(b.numpy(), c.numpy()) self.assertEqual(b.inplace_version, 1) paddle.enable_static() class XPUTestSetValueInplaceLeafVar(XPUOpTest): def setUp(self): self.__class__.op_type = "set_value" self.__class__.no_need_check_grad = True self.place = paddle.XPUPlace(0) def test_inplace_var_become_leaf_var(self): paddle.disable_static() a_grad_1, b_grad_1, a_grad_2, b_grad_2 = 0, 1, 2, 3 with paddle.base.dygraph.guard(): paddle.seed(100) a = paddle.rand(shape=[1, 4]) b = paddle.rand(shape=[1, 4]) a.stop_gradient = False b.stop_gradient = False c = a / b c.sum().backward() a_grad_1 = a.grad.numpy() b_grad_1 = b.grad.numpy() with paddle.base.dygraph.guard(): paddle.seed(100) a = paddle.rand(shape=[1, 4]) b = paddle.rand(shape=[1, 4]) a.stop_gradient = False b.stop_gradient = False c = a / b d = paddle.zeros((4, 4)) self.assertTrue(d.stop_gradient) d[0, :] = c self.assertFalse(d.stop_gradient) d[0, :].sum().backward() a_grad_2 = a.grad.numpy() b_grad_2 = b.grad.numpy() np.testing.assert_array_equal(a_grad_1, a_grad_2) np.testing.assert_array_equal(b_grad_1, b_grad_2) paddle.enable_static() support_types = get_xpu_op_support_types('set_value') for stype in support_types: create_test_class(globals(), XPUTestSetValueOp, stype) if __name__ == '__main__': unittest.main()