chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,514 @@
|
||||
# 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.
|
||||
import itertools
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
import numpy as np
|
||||
from op_test import get_device, get_device_place, is_custom_device
|
||||
|
||||
import paddle
|
||||
from paddle.base import core
|
||||
|
||||
RTOL = 1e-5
|
||||
ATOL = 1e-8
|
||||
DTYPE_ALL = [
|
||||
'float16',
|
||||
'float32',
|
||||
'float64',
|
||||
'int32',
|
||||
'int64',
|
||||
'bfloat16',
|
||||
]
|
||||
|
||||
DTYPE_COLUMN_STACK = DTYPE_ALL
|
||||
|
||||
PLACES = [('cpu', paddle.CPUPlace())] + (
|
||||
[(get_device(), get_device_place())]
|
||||
if (core.is_compiled_with_cuda() or is_custom_device())
|
||||
else []
|
||||
)
|
||||
|
||||
|
||||
def rearrange_data(*inputs):
|
||||
data = list(zip(*inputs))
|
||||
return [list(itertools.chain(*data[i])) for i in range(4)]
|
||||
|
||||
|
||||
def generate_data(shape, count=1, dtype='int32'):
|
||||
"""generate test data
|
||||
|
||||
Args:
|
||||
shape(list of int): shape of inputs
|
||||
count(int): input count for each dim
|
||||
dtype(str): dtype
|
||||
|
||||
Returns:
|
||||
a list of data like:
|
||||
[[data, dtype, shape, name], [data, dtype, shape, name] ... ]
|
||||
"""
|
||||
return list(
|
||||
zip(
|
||||
*[
|
||||
[
|
||||
# bfloat16 convert to uint16 for numpy
|
||||
np.random.randint(0, 255, size=shape).astype(
|
||||
dtype if dtype != 'bfloat16' else 'uint16'
|
||||
),
|
||||
dtype,
|
||||
shape,
|
||||
f'{shape}d_{idx}_{dtype}',
|
||||
]
|
||||
for idx in range(count)
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class BaseTest(unittest.TestCase):
|
||||
"""Test in each `PLACES` and in `static/dygraph`"""
|
||||
|
||||
def _test_static_api(
|
||||
self,
|
||||
func_paddle,
|
||||
func_numpy,
|
||||
inputs: list,
|
||||
dtypes: list,
|
||||
shapes: list,
|
||||
names: list,
|
||||
):
|
||||
"""Test `static`, convert `Tensor` to `numpy array` before feed into graph"""
|
||||
# convert grad value to bool if dtype is bool
|
||||
grad_value = 123.0 if dtypes[0] != 'bool' else True
|
||||
if dtypes[0] == 'bfloat16':
|
||||
grad_value = paddle.to_tensor(grad_value, dtype=dtypes[0]).numpy()
|
||||
paddle.enable_static()
|
||||
|
||||
for device, place in PLACES:
|
||||
paddle.set_device(device)
|
||||
|
||||
exe = paddle.static.Executor(place)
|
||||
new_scope = paddle.static.Scope()
|
||||
main_program = paddle.static.Program()
|
||||
with (
|
||||
paddle.static.scope_guard(new_scope),
|
||||
paddle.static.program_guard(main_program),
|
||||
):
|
||||
x = []
|
||||
feed = {}
|
||||
for i in range(len(inputs)):
|
||||
input = inputs[i]
|
||||
shape = shapes[i]
|
||||
dtype = dtypes[i]
|
||||
name = names[i]
|
||||
|
||||
_x = paddle.static.data(name, shape, dtype)
|
||||
_x.stop_gradient = False
|
||||
x.append(_x)
|
||||
|
||||
# the data feeded should NOT be a Tensor
|
||||
feed[name] = input
|
||||
|
||||
out = func_paddle(x)
|
||||
out.stop_gradient = False
|
||||
|
||||
y = out * 123
|
||||
|
||||
# not check old ir
|
||||
if paddle.framework.in_pir_mode():
|
||||
fetch_list = [out]
|
||||
grads = paddle.autograd.ir_backward.grad(y, x)
|
||||
fetch_list.append(grads)
|
||||
|
||||
exe = paddle.static.Executor(place)
|
||||
res, *res_grad = exe.run(feed=feed, fetch_list=fetch_list)
|
||||
|
||||
np.testing.assert_allclose(
|
||||
res_grad[0], np.ones(x[0].shape) * grad_value
|
||||
)
|
||||
|
||||
out_ref = func_numpy(inputs)
|
||||
for n, p in zip(out_ref, res):
|
||||
np.testing.assert_allclose(n, p, rtol=RTOL, atol=ATOL)
|
||||
|
||||
def _test_dygraph_api(
|
||||
self,
|
||||
func_paddle,
|
||||
func_numpy,
|
||||
inputs: list,
|
||||
dtypes: list,
|
||||
shapes: list,
|
||||
names: list,
|
||||
):
|
||||
"""Test `dygraph`, and check grads"""
|
||||
paddle.disable_static()
|
||||
|
||||
for device, place in PLACES:
|
||||
paddle.set_device(device)
|
||||
|
||||
out = func_paddle(
|
||||
[
|
||||
paddle.to_tensor(inputs[i]).astype(dtypes[i])
|
||||
for i in range(len(inputs))
|
||||
]
|
||||
)
|
||||
out_ref = func_numpy(inputs)
|
||||
|
||||
for n, p in zip(out_ref, out):
|
||||
np.testing.assert_allclose(n, p.numpy(), rtol=RTOL, atol=ATOL)
|
||||
|
||||
# check grads
|
||||
if len(inputs) == 1:
|
||||
out = [out]
|
||||
|
||||
for y in out:
|
||||
y.stop_gradient = False
|
||||
z = y * 123
|
||||
grads = paddle.grad(z, y)
|
||||
self.assertTrue(len(grads), 1)
|
||||
self.assertEqual(grads[0].dtype, y.dtype)
|
||||
self.assertEqual(grads[0].shape, y.shape)
|
||||
|
||||
def _test_all(self, args, dtype=''):
|
||||
self._test_dygraph_api(self.func_paddle, self.func_numpy, *args)
|
||||
self._test_static_api(self.func_paddle, self.func_numpy, *args)
|
||||
|
||||
|
||||
class BaseCases:
|
||||
def test_0d(self):
|
||||
self._test_all(generate_data([], count=1, dtype='float64'))
|
||||
|
||||
def test_1d(self):
|
||||
self._test_all(generate_data([1], count=1, dtype='float64'))
|
||||
|
||||
def test_2d(self):
|
||||
self._test_all(generate_data([1, 1], count=1, dtype='float64'))
|
||||
self._test_all(generate_data([3, 2], count=1, dtype='float64'))
|
||||
|
||||
def test_3d(self):
|
||||
self._test_all(generate_data([1, 1, 1], count=1, dtype='float64'))
|
||||
self._test_all(generate_data([3, 4, 2], count=1, dtype='float64'))
|
||||
|
||||
def test_4d(self):
|
||||
self._test_all(generate_data([1, 1, 1, 1], count=1, dtype='float64'))
|
||||
self._test_all(generate_data([3, 4, 2, 5], count=1, dtype='float64'))
|
||||
|
||||
def test_0d_more(self):
|
||||
self._test_all(generate_data([], count=3, dtype='float64'))
|
||||
|
||||
def test_1d_more(self):
|
||||
self._test_all(generate_data([1], count=3, dtype='float64'))
|
||||
self._test_all(generate_data([5], count=3, dtype='float64'))
|
||||
|
||||
def test_2d_more(self):
|
||||
self._test_all(generate_data([1, 1], count=3, dtype='float64'))
|
||||
self._test_all(generate_data([3, 2], count=3, dtype='float64'))
|
||||
|
||||
def test_3d_more(self):
|
||||
self._test_all(generate_data([1, 1, 1], count=3, dtype='float64'))
|
||||
self._test_all(generate_data([3, 4, 2], count=3, dtype='float64'))
|
||||
|
||||
def test_4d_more(self):
|
||||
self._test_all(generate_data([1, 1, 1, 1], count=3, dtype='float64'))
|
||||
self._test_all(generate_data([3, 4, 2, 5], count=3, dtype='float64'))
|
||||
|
||||
|
||||
class TestHStack(BaseTest, BaseCases):
|
||||
def setUp(self):
|
||||
self.func_paddle = paddle.hstack
|
||||
self.func_numpy = np.hstack
|
||||
|
||||
def test_mix_ndim(self):
|
||||
d0 = generate_data([], count=1, dtype='float64')
|
||||
d1 = generate_data([2], count=1, dtype='float64')
|
||||
self._test_all(rearrange_data(d0, d1))
|
||||
|
||||
def test_dtype(self):
|
||||
for dtype in DTYPE_ALL:
|
||||
if dtype == 'float16' and (
|
||||
not (core.is_compiled_with_cuda() or is_custom_device())
|
||||
or (
|
||||
not core.is_float16_supported(get_device_place())
|
||||
or sys.platform == 'win32'
|
||||
)
|
||||
):
|
||||
continue
|
||||
|
||||
if dtype == 'bfloat16' and (
|
||||
not (core.is_compiled_with_cuda() or is_custom_device())
|
||||
or (
|
||||
not core.is_bfloat16_supported(get_device_place())
|
||||
or sys.platform == 'win32'
|
||||
)
|
||||
):
|
||||
continue
|
||||
|
||||
self._test_all(
|
||||
generate_data([], count=1, dtype=dtype),
|
||||
dtype,
|
||||
)
|
||||
|
||||
|
||||
class TestHStackZeroDim1(TestHStack):
|
||||
def test_mix_ndim(self):
|
||||
d0 = generate_data([0, 1, 1], count=1, dtype='float64')
|
||||
self._test_all(d0)
|
||||
|
||||
|
||||
class TestHStackZeroDim2(TestHStack):
|
||||
def test_mix_ndim(self):
|
||||
d0 = generate_data([1, 0, 1, 1], count=1, dtype='float64')
|
||||
self._test_all(d0)
|
||||
|
||||
|
||||
class TestVStack(BaseTest, BaseCases):
|
||||
def setUp(self):
|
||||
self.func_paddle = paddle.vstack
|
||||
self.func_numpy = np.vstack
|
||||
|
||||
def test_mix_ndim(self):
|
||||
d0 = generate_data([2], count=1, dtype='float64')
|
||||
d1 = generate_data([1, 2], count=1, dtype='float64')
|
||||
self._test_all(rearrange_data(d0, d1))
|
||||
|
||||
def test_dtype(self):
|
||||
for dtype in DTYPE_ALL:
|
||||
if dtype == 'float16' and (
|
||||
not (core.is_compiled_with_cuda() or is_custom_device())
|
||||
or (
|
||||
not core.is_float16_supported(get_device_place())
|
||||
or sys.platform == 'win32'
|
||||
)
|
||||
):
|
||||
continue
|
||||
|
||||
if dtype == 'bfloat16' and (
|
||||
not (core.is_compiled_with_cuda() or is_custom_device())
|
||||
or (
|
||||
not core.is_bfloat16_supported(get_device_place())
|
||||
or sys.platform == 'win32'
|
||||
)
|
||||
):
|
||||
continue
|
||||
|
||||
self._test_all(
|
||||
generate_data([], count=1, dtype=dtype),
|
||||
dtype,
|
||||
)
|
||||
|
||||
|
||||
class TestDStack(BaseTest, BaseCases):
|
||||
def setUp(self):
|
||||
self.func_paddle = paddle.dstack
|
||||
self.func_numpy = np.dstack
|
||||
|
||||
def test_mix_ndim(self):
|
||||
d0 = generate_data([2], count=1, dtype='float64')
|
||||
d1 = generate_data([1, 2], count=1, dtype='float64')
|
||||
self._test_all(rearrange_data(d0, d1))
|
||||
|
||||
d0 = generate_data([2], count=1, dtype='float64')
|
||||
d1 = generate_data([1, 2, 1], count=1, dtype='float64')
|
||||
self._test_all(rearrange_data(d0, d1))
|
||||
|
||||
def test_dtype(self):
|
||||
for dtype in DTYPE_ALL:
|
||||
if dtype == 'float16' and (
|
||||
not (core.is_compiled_with_cuda() or is_custom_device())
|
||||
or (
|
||||
not core.is_float16_supported(get_device_place())
|
||||
or sys.platform == 'win32'
|
||||
)
|
||||
):
|
||||
continue
|
||||
|
||||
if dtype == 'bfloat16' and (
|
||||
not (core.is_compiled_with_cuda() or is_custom_device())
|
||||
or (
|
||||
not core.is_bfloat16_supported(get_device_place())
|
||||
or sys.platform == 'win32'
|
||||
)
|
||||
):
|
||||
continue
|
||||
|
||||
self._test_all(
|
||||
generate_data([], count=1, dtype=dtype),
|
||||
dtype,
|
||||
)
|
||||
|
||||
|
||||
class TestColumnStack(BaseTest, BaseCases):
|
||||
def setUp(self):
|
||||
self.func_paddle = paddle.column_stack
|
||||
self.func_numpy = np.column_stack
|
||||
|
||||
def test_mix_ndim(self):
|
||||
d0 = generate_data([2], count=1, dtype='float64')
|
||||
d1 = generate_data([2, 1], count=1, dtype='float64')
|
||||
self._test_all(rearrange_data(d0, d1))
|
||||
|
||||
def test_dtype(self):
|
||||
for dtype in DTYPE_COLUMN_STACK:
|
||||
if dtype == 'float16' and (
|
||||
not (core.is_compiled_with_cuda() or is_custom_device())
|
||||
or (
|
||||
not core.is_float16_supported(get_device_place())
|
||||
or sys.platform == 'win32'
|
||||
)
|
||||
):
|
||||
continue
|
||||
|
||||
if dtype == 'bfloat16' and (
|
||||
not (core.is_compiled_with_cuda() or is_custom_device())
|
||||
or (
|
||||
not core.is_bfloat16_supported(get_device_place())
|
||||
or sys.platform == 'win32'
|
||||
)
|
||||
):
|
||||
continue
|
||||
|
||||
self._test_all(
|
||||
generate_data([], count=1, dtype=dtype),
|
||||
dtype=dtype,
|
||||
)
|
||||
|
||||
|
||||
class TestRowStack(BaseTest, BaseCases):
|
||||
def setUp(self):
|
||||
self.func_paddle = paddle.row_stack
|
||||
self.func_numpy = np.vstack
|
||||
|
||||
def test_mix_ndim(self):
|
||||
d0 = generate_data([2], count=1, dtype='float64')
|
||||
d1 = generate_data([1, 2], count=1, dtype='float64')
|
||||
self._test_all(rearrange_data(d0, d1))
|
||||
|
||||
def test_dtype(self):
|
||||
for dtype in DTYPE_ALL:
|
||||
if dtype == 'float16' and (
|
||||
not (core.is_compiled_with_cuda() or is_custom_device())
|
||||
or (
|
||||
not core.is_float16_supported(get_device_place())
|
||||
or sys.platform == 'win32'
|
||||
)
|
||||
):
|
||||
continue
|
||||
|
||||
if dtype == 'bfloat16' and (
|
||||
not (core.is_compiled_with_cuda() or is_custom_device())
|
||||
or (
|
||||
not core.is_bfloat16_supported(get_device_place())
|
||||
or sys.platform == 'win32'
|
||||
)
|
||||
):
|
||||
continue
|
||||
|
||||
self._test_all(
|
||||
generate_data([], count=1, dtype=dtype),
|
||||
dtype,
|
||||
)
|
||||
|
||||
|
||||
class ErrorCases:
|
||||
def test_mix_dtype(self):
|
||||
with self.assertRaises(ValueError):
|
||||
d0 = generate_data([2], count=1, dtype='float32')
|
||||
d1 = generate_data([2], count=1, dtype='float64')
|
||||
self._test_dygraph_api(
|
||||
self.func_paddle, self.func_numpy, *rearrange_data(d0, d1)
|
||||
)
|
||||
|
||||
with self.assertRaises(TypeError):
|
||||
d0 = generate_data([2], count=1, dtype='float32')
|
||||
d1 = generate_data([2], count=1, dtype='float64')
|
||||
self._test_static_api(
|
||||
self.func_paddle, self.func_numpy, *rearrange_data(d0, d1)
|
||||
)
|
||||
|
||||
def test_1d_2d(self):
|
||||
with self.assertRaises(ValueError):
|
||||
d0 = generate_data([2, 1], count=1, dtype='float64')
|
||||
d1 = generate_data([3], count=1, dtype='float64')
|
||||
self._test_all(rearrange_data(d0, d1))
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
d0 = generate_data([1, 2], count=1, dtype='float64')
|
||||
d1 = generate_data([3], count=1, dtype='float64')
|
||||
self._test_all(rearrange_data(d0, d1))
|
||||
|
||||
def test_1d_3d(self):
|
||||
with self.assertRaises(ValueError):
|
||||
d0 = generate_data([2, 3, 1], count=1, dtype='float64')
|
||||
d1 = generate_data([3], count=1, dtype='float64')
|
||||
self._test_all(rearrange_data(d0, d1))
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
d0 = generate_data([1, 1, 1], count=1, dtype='float64')
|
||||
d1 = generate_data([2], count=1, dtype='float64')
|
||||
self._test_all(rearrange_data(d0, d1))
|
||||
|
||||
def test_2d_3d(self):
|
||||
with self.assertRaises(ValueError):
|
||||
d0 = generate_data([2, 3, 1], count=1, dtype='float64')
|
||||
d1 = generate_data([1, 3], count=1, dtype='float64')
|
||||
self._test_all(rearrange_data(d0, d1))
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
d0 = generate_data([1, 1, 1], count=1, dtype='float64')
|
||||
d1 = generate_data([1, 2], count=1, dtype='float64')
|
||||
self._test_all(rearrange_data(d0, d1))
|
||||
|
||||
|
||||
class ErrorCases0d1d(ErrorCases):
|
||||
"""hstack works fine with 0d & 1d"""
|
||||
|
||||
def test_vstack_0d_1d(self):
|
||||
with self.assertRaises(ValueError):
|
||||
d0 = generate_data([], count=1, dtype='float64')
|
||||
d1 = generate_data([2], count=1, dtype='float64')
|
||||
self._test_all(rearrange_data(d0, d1))
|
||||
|
||||
|
||||
class TestErrorHStack(BaseTest, ErrorCases):
|
||||
def setUp(self):
|
||||
self.func_paddle = paddle.hstack
|
||||
self.func_numpy = np.hstack
|
||||
|
||||
|
||||
class TestErrorVStack(BaseTest, ErrorCases0d1d):
|
||||
def setUp(self):
|
||||
self.func_paddle = paddle.vstack
|
||||
self.func_numpy = np.vstack
|
||||
|
||||
|
||||
class TestErrorDStack(BaseTest, ErrorCases0d1d):
|
||||
def setUp(self):
|
||||
self.func_paddle = paddle.dstack
|
||||
self.func_numpy = np.dstack
|
||||
|
||||
|
||||
class TestErrorColumnStack(BaseTest, ErrorCases0d1d):
|
||||
def setUp(self):
|
||||
self.func_paddle = paddle.column_stack
|
||||
self.func_numpy = np.column_stack
|
||||
|
||||
|
||||
class TestErrorRowStack(BaseTest, ErrorCases0d1d):
|
||||
def setUp(self):
|
||||
self.func_paddle = paddle.row_stack
|
||||
self.func_numpy = np.vstack
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user