Files
paddlepaddle--paddle/test/legacy_test/test_zero_size.py
T
2026-07-13 12:40:42 +08:00

487 lines
17 KiB
Python

# Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import unittest
from op_test import get_device, is_custom_device
import paddle
from paddle.framework import core
def contiguous_strides(shape):
strides = [0] * len(shape)
running = 1
for i in range(len(shape) - 1, -1, -1):
strides[i] = running
running *= shape[i]
return strides
class TestZeroSizeParameter(unittest.TestCase):
def setUp(self):
self.places = [
"cpu",
]
if (
paddle.device.is_compiled_with_cuda() or is_custom_device()
) and paddle.device.cuda.device_count() > 0:
self.places.append(get_device())
self.parameter_dtypes = [
'float16',
'float32',
'float64',
]
self.zero_size_shapes = [
[0, 4],
[0, 0],
[4, 0],
[0, 5, 6],
[6, 5, 0, 0],
[0, 0, 0, 12],
]
def test_create_parameter(self):
for place in self.places:
paddle.device.set_device(place)
for parameter_dtype in self.parameter_dtypes:
for zero_size_shape in self.zero_size_shapes:
class Model(paddle.nn.Layer):
def __init__(self) -> None:
super().__init__()
self.dummy_linear = paddle.nn.Linear(3, 4)
self.w = self.create_parameter(
shape=zero_size_shape, dtype=parameter_dtype
)
model = Model()
model = model
self.assertEqual(
model.w.shape,
zero_size_shape,
msg=f"Check failed at: {parameter_dtype}, {zero_size_shape}",
)
self.assertEqual(
model.w.data_ptr(),
0,
msg=f"Check failed at: {parameter_dtype}, {zero_size_shape}",
)
self.assertEqual(
str(model.w.place),
str(model.dummy_linear.weight.place),
msg=f"Check failed at: {parameter_dtype}, {zero_size_shape}",
)
self.assertEqual(
model.w.strides,
contiguous_strides(zero_size_shape),
msg=f"Check failed at: {parameter_dtype}, {zero_size_shape}",
)
self.assertEqual(
model.w.is_contiguous(),
True,
msg=f"Check failed at: {parameter_dtype}, {zero_size_shape}",
)
class TestZeroSizeForward(unittest.TestCase):
def setUp(self):
self.places = [
"cpu",
]
if (
paddle.device.is_compiled_with_cuda() or is_custom_device()
) and paddle.device.cuda.device_count() > 0:
self.places.append(get_device())
self.dtypes = [
'bool',
'uint8',
'int8',
'int16',
'int32',
'int64',
'float16',
'float32',
'float64',
'complex64',
'complex128',
]
self.zero_size_shapes = [
[0, 4],
[0, 0],
[4, 0],
[0, 5, 6],
[6, 5, 0, 0],
[0, 0, 0, 12],
]
def test_forward_eager(self):
"""Test for simple API call"""
for place in self.places:
paddle.device.set_device(place)
for dtype in self.dtypes:
for zero_size_shape in self.zero_size_shapes:
x = paddle.ones(zero_size_shape, dtype=dtype)
self.assertEqual(x.data_ptr(), 0)
if x.dtype == paddle.bool:
y = ~x
else:
y = x + 1
self.assertEqual(
y.shape,
zero_size_shape,
msg=f"Check failed at: {dtype}, {zero_size_shape}",
)
self.assertEqual(
y.data_ptr(),
0,
msg=f"Check failed at: {dtype}, {zero_size_shape}",
)
self.assertEqual(
y.strides,
contiguous_strides(zero_size_shape),
msg=f"Check failed at: {dtype}, {zero_size_shape}",
)
self.assertEqual(
str(y.place),
str(x.place),
msg=f"Check failed at: {dtype}, {zero_size_shape}",
)
self.assertEqual(
y.dtype,
x.dtype,
msg=f"Check failed at: {dtype}, {zero_size_shape}",
)
self.assertEqual(
y.is_contiguous(),
x.is_contiguous(),
msg=f"Check failed at: {dtype}, {zero_size_shape}",
)
def test_forward_static(self):
"""Test for simple API call"""
def forward_func(x):
if x.dtype == paddle.bool:
y = ~x
else:
y = x + 1
return y
for place in self.places:
paddle.device.set_device(place)
static_forward_func = paddle.jit.to_static(
forward_func, full_graph=True, backend=None
)
for dtype in self.dtypes:
for zero_size_shape in self.zero_size_shapes:
x = paddle.ones(zero_size_shape, dtype=dtype)
self.assertEqual(x.data_ptr(), 0)
y = static_forward_func(x)
self.assertEqual(
y.shape,
zero_size_shape,
msg=f"Check failed at: {dtype}, {zero_size_shape}",
)
self.assertEqual(
y.data_ptr(),
0,
msg=f"Check failed at: {dtype}, {zero_size_shape}",
)
self.assertEqual(
y.strides,
contiguous_strides(zero_size_shape),
msg=f"Check failed at: {dtype}, {zero_size_shape}",
)
self.assertEqual(
str(y.place),
str(x.place),
msg=f"Check failed at: {dtype}, {zero_size_shape}",
)
self.assertEqual(
y.dtype,
x.dtype,
msg=f"Check failed at: {dtype}, {zero_size_shape}",
)
self.assertEqual(
y.is_contiguous(),
x.is_contiguous(),
msg=f"Check failed at: {dtype}, {zero_size_shape}",
)
@unittest.skipIf(core.is_compiled_with_xpu(), "Skip XPU for xpu place issue")
class TestZeroSizeBackward(unittest.TestCase):
def setUp(self):
self.places = [
"cpu",
]
if (
paddle.device.is_compiled_with_cuda() or is_custom_device()
) and paddle.device.cuda.device_count() > 0:
self.places.append(get_device())
# Only floating and complex needs gradient
self.dtypes = [
'float16',
'float32',
'float64',
'complex64',
'complex128',
]
self.zero_size_shapes = [
[0, 4],
[0, 0],
[4, 0],
[0, 5, 6],
[6, 5, 0, 0],
[0, 0, 0, 12],
]
def test_backward_eager(self):
"""Test for simple API call"""
for place in self.places:
paddle.device.set_device(place)
for dtype in self.dtypes:
for zero_size_shape in self.zero_size_shapes:
x = paddle.ones(zero_size_shape, dtype=dtype)
x.stop_gradient = False
self.assertEqual(x.data_ptr(), 0)
y = x * 2 + 1
(x_grad,) = paddle.grad(y, x, create_graph=True)
self.assertEqual(
x_grad.shape,
zero_size_shape,
msg=f"Check failed at: {dtype}, {zero_size_shape}",
)
self.assertEqual(
x_grad.data_ptr(),
0,
msg=f"Check failed at: {dtype}, {zero_size_shape}",
)
self.assertEqual(
x_grad.strides,
contiguous_strides(zero_size_shape),
msg=f"Check failed at: {dtype}, {zero_size_shape}",
)
self.assertEqual(
str(x_grad.place),
str(x.place),
msg=f"Check failed at: {dtype}, {zero_size_shape}",
)
self.assertEqual(
x_grad.dtype,
x.dtype,
msg=f"Check failed at: {dtype}, {zero_size_shape}",
)
self.assertEqual(
x_grad.is_contiguous(),
x.is_contiguous(),
msg=f"Check failed at: {dtype}, {zero_size_shape}",
)
def test_backward_static(self):
"""Test for simple API call"""
def gradient_func(x):
y = x * 2 + 1
return paddle.grad(y, x)
for place in self.places:
paddle.device.set_device(place)
for dtype in self.dtypes:
for zero_size_shape in self.zero_size_shapes:
x = paddle.ones(zero_size_shape, dtype=dtype)
x.stop_gradient = False
self.assertEqual(x.data_ptr(), 0)
static_gradient_func = paddle.jit.to_static(
gradient_func, full_graph=True, backend=None
)
(x_grad,) = static_gradient_func(x)
self.assertEqual(
x_grad.shape,
zero_size_shape,
msg=f"Check failed at: {dtype}, {zero_size_shape}",
)
self.assertEqual(
x_grad.data_ptr(),
0,
msg=f"Check failed at: {dtype}, {zero_size_shape}",
)
self.assertEqual(
x_grad.strides,
contiguous_strides(zero_size_shape),
msg=f"Check failed at: {dtype}, {zero_size_shape}",
)
self.assertEqual(
str(x_grad.place),
str(x.place),
msg=f"Check failed at: {dtype}, {zero_size_shape}",
)
self.assertEqual(
x_grad.dtype,
x.dtype,
msg=f"Check failed at: {dtype}, {zero_size_shape}",
)
self.assertEqual(
x_grad.is_contiguous(),
x.is_contiguous(),
msg=f"Check failed at: {dtype}, {zero_size_shape}",
)
@unittest.skipIf(core.is_compiled_with_xpu(), "Skip XPU for xpu place issue")
class TestZeroSizeBackwardWithGradientAccumulation(unittest.TestCase):
def setUp(self):
self.places = [
"cpu",
]
if (
paddle.device.is_compiled_with_cuda() or is_custom_device()
) and paddle.device.cuda.device_count() > 0:
self.places.append(get_device())
# Only floating and complex needs gradient
self.dtypes = [
# 'float16',
'float32',
'float64',
'complex64',
'complex128',
]
self.zero_size_shapes = [
[0, 4],
[4, 0],
[0, 5, 6],
[6, 12, 0, 0],
[0, 0, 0, 12],
]
def test_backward_eager(self):
"""Test for simple API call"""
for place in self.places:
paddle.device.set_device(place)
for dtype in self.dtypes:
for zero_size_shape in self.zero_size_shapes:
x = paddle.ones(zero_size_shape, dtype=dtype)
x.stop_gradient = False
self.assertEqual(x.data_ptr(), 0)
def forward_func(x):
y1 = x / 2
y2 = x + 1
return y1 + y2
(x_grad,) = paddle.grad(
forward_func(x), x, create_graph=True
)
self.assertEqual(
x_grad.shape,
zero_size_shape,
msg=f"Check failed at: {dtype}, {zero_size_shape}",
)
self.assertEqual(
x_grad.data_ptr(),
0,
msg=f"Check failed at: {dtype}, {zero_size_shape}",
)
self.assertEqual(
x_grad.strides,
contiguous_strides(zero_size_shape),
msg=f"Check failed at: {dtype}, {zero_size_shape}",
)
self.assertEqual(
str(x_grad.place),
str(x.place),
msg=f"Check failed at: {dtype}, {zero_size_shape}",
)
self.assertEqual(
x_grad.dtype,
x.dtype,
msg=f"Check failed at: {dtype}, {zero_size_shape}",
)
self.assertEqual(
x_grad.is_contiguous(),
x.is_contiguous(),
msg=f"Check failed at: {dtype}, {zero_size_shape}",
)
def test_backward_static(self):
"""Test for simple API call"""
def gradient_func(x):
y1 = x / 2
y2 = x + 1
out = y1 + y2
return paddle.grad(out, x)
for place in self.places:
paddle.device.set_device(place)
for dtype in self.dtypes:
for zero_size_shape in self.zero_size_shapes:
x = paddle.ones(zero_size_shape, dtype=dtype)
x.stop_gradient = False
self.assertEqual(x.data_ptr(), 0)
static_gradient_func = paddle.jit.to_static(
gradient_func, full_graph=True, backend=None
)
(x_grad,) = static_gradient_func(x)
self.assertEqual(
x_grad.shape,
zero_size_shape,
msg=f"Check failed at: {dtype}, {zero_size_shape}",
)
self.assertEqual(
x_grad.data_ptr(),
0,
msg=f"Check failed at: {dtype}, {zero_size_shape}",
)
self.assertEqual(
x_grad.strides,
contiguous_strides(zero_size_shape),
msg=f"Check failed at: {dtype}, {zero_size_shape}",
)
self.assertEqual(
str(x_grad.place),
str(x.place),
msg=f"Check failed at: {dtype}, {zero_size_shape}",
)
self.assertEqual(
x_grad.dtype,
x.dtype,
msg=f"Check failed at: {dtype}, {zero_size_shape}",
)
self.assertEqual(
x_grad.is_contiguous(),
x.is_contiguous(),
msg=f"Check failed at: {dtype}, {zero_size_shape}",
)
if __name__ == '__main__':
unittest.main()