Files
2026-07-13 12:40:42 +08:00

364 lines
8.5 KiB
Python

# 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.
# GET_ITER (new)
# FOR_ITER (new)
from __future__ import annotations
import unittest
from test_case_base import (
TestCaseBase,
test_instruction_translator_cache_context,
)
import paddle
from paddle.jit import sot
from paddle.jit.sot import symbolic_translate
from paddle.jit.sot.utils import strict_mode_guard
def gener():
yield 1
yield 2
yield 3
def for_list_1(x: paddle.Tensor):
for i in [1, 2, 3]:
x += i
if x > 2:
x += 1
else:
x -= 1
return x
def for_list_2(x: paddle.Tensor):
for i in [1, 2, 3]:
x += i
if i > 2:
x += 1
else:
x -= 1
return x
def for_dict(x: paddle.Tensor):
map = {1: 2, 3: 4}
for k in map.keys():
x += k
for v in map.values():
x += v
for k, v in map.items():
x += k
x += v
return x
def for_iter(x, it):
for item in it:
x += item
return x
def for_for_fallback(x, it):
for i in [1, 2, 3]:
for item in it:
x += item
return x
def for_break(x: paddle.Tensor, it):
for i in [1, 2, 3]:
x += i
if i == 2:
break
for i in it:
x += i
if i == 2:
break
return x
def for_continue(x: paddle.Tensor, it):
for i in [1, 2, 3]:
if i == 2:
continue
x += i
for i in it:
if i == 2:
continue
x += i
return x
def for_enumerate_var_with_nested_range(x_array):
x = paddle.tensor.fill_constant([1], 'int32', 0)
x_array = paddle.to_tensor(x_array)
for i, num in enumerate(x_array):
for idx in range(num):
x = x + num
return x
def for_create_tmp_in_loop(x, it):
s = x
for i in it:
tmp = i
s += tmp
return s, tmp
def for_without_zero_iter(self_res_dict, output):
res_dict = {"logits": output}
for res_key in list(self_res_dict):
res_dict[res_key] = self_res_dict.pop(res_key)
return res_dict
def for_reconstruct_range_iter():
for i in range(3):
sot.psdb.breakgraph()
global_var_name = None
def for_tmp_var_with_same_name_as_global_var():
total = 0
for i in range(3):
global_var_name = i + 3
sot.psdb.breakgraph()
total += global_var_name
return total
def for_layer_list(layer_list, x):
for net in layer_list:
x = net(x)
return x
class TestForLoop(TestCaseBase):
@strict_mode_guard(False)
def test_list(self):
a = paddle.to_tensor(1)
self.assert_results(for_list_1, a)
def test_list_with_fallback(self):
a = paddle.to_tensor(1)
self.assert_results(for_list_2, a)
def test_dict(self):
a = paddle.to_tensor(1)
self.assert_results(for_dict, a)
@strict_mode_guard(False)
def test_fallback(self):
a = paddle.to_tensor(1)
sym_output = symbolic_translate(for_iter)(a, gener())
paddle_output = for_iter(a, gener())
self.assert_nest_match(sym_output, paddle_output)
@strict_mode_guard(False)
def test_for_iter_fallback(self):
a = paddle.to_tensor(1)
sym_output = symbolic_translate(for_iter)(a, gener())
paddle_output = for_iter(a, gener())
self.assert_nest_match(sym_output, paddle_output)
@strict_mode_guard(False)
def test_for_break(self):
a = paddle.to_tensor(1)
sym_output = symbolic_translate(for_break)(a, gener())
paddle_output = for_break(a, gener())
self.assert_nest_match(sym_output, paddle_output)
@strict_mode_guard(False)
def test_for_continue(self):
a = paddle.to_tensor(1)
sym_output = symbolic_translate(for_continue)(a, gener())
paddle_output = for_continue(a, gener())
self.assert_nest_match(sym_output, paddle_output)
@strict_mode_guard(False)
def test_create_var_in_loop(self):
x = paddle.to_tensor(1, dtype="float32")
a = [1, 2, 3]
self.assert_results(for_create_tmp_in_loop, x, a)
sym_output = symbolic_translate(for_create_tmp_in_loop)(x, iter(a))
paddle_output = for_create_tmp_in_loop(x, iter(a))
self.assert_nest_match(sym_output, paddle_output)
@strict_mode_guard(False)
def test_create_var_in_loop_with_same_name_as_global(self):
self.assert_results(for_tmp_var_with_same_name_as_global_var)
def test_for_without_zero_iter(self):
self_res_dict = {}
output = paddle.to_tensor(2)
self.assert_results(for_without_zero_iter, self_res_dict, output)
@strict_mode_guard(False)
def test_reconstruct_range_iter(self):
self.assert_results(for_reconstruct_range_iter)
def test_layer_list(self):
layers = paddle.nn.LayerList()
for i in range(5):
layers.append(paddle.nn.Linear(5, 5))
x = paddle.rand([5], dtype="float32")
self.assert_results(for_layer_list, layers, x)
def run_list_comp(x):
out = [s.chunk(2, axis=1) for s in x]
return out
class TestListComp(TestCaseBase):
def test_list_comp(self):
x = [paddle.randn([1, 4]), paddle.randn([1, 4])]
self.assert_results(run_list_comp, x)
def for_enumerate_cache(func_list, x):
out = None
for idx, func in enumerate(func_list):
out = func(x[idx])
return out
class TestEnumerateCache(TestCaseBase):
def test_run(self):
func_list = [
paddle.nn.Linear(10, 10),
]
x = [
paddle.randn([5, 10]),
]
with test_instruction_translator_cache_context() as ctx:
out = symbolic_translate(for_enumerate_cache)(func_list, x)
out = symbolic_translate(for_enumerate_cache)(func_list, x)
self.assertEqual(ctx.translate_count, 1)
# after_loop_fn need zzz, and zzz is created as UndefinedVar when generating loop body
# do not set zzz as UndefinedVar again
def undefined_var_case_0():
for i in [1, 2]:
sot.psdb.breakgraph()
zzz = i
zzz = zzz + 1
return zzz
# after_loop_fn need create zzz as UndefinedVar
def undefined_var_case_1():
for i in [1, 2]:
sot.psdb.breakgraph()
aaa = i
for i in [1, 3]:
zzz = i
zzz = zzz + 1
return zzz
class TestUndefinedVarInRiskyCodes(TestCaseBase):
@strict_mode_guard(False)
def test_undefined_var_case_0(self):
self.assert_results(undefined_var_case_0)
@strict_mode_guard(False)
def test_undefined_var_case_1(self):
self.assert_results(undefined_var_case_1)
def comp_with_fallback(x):
paddle.jit.sot.psdb.fallback()
y = [len(t) for t in x]
return paddle.to_tensor(y)
class TestListCompWithFallback(TestCaseBase):
@strict_mode_guard(False)
def test_list_comp_with_fallback(self):
x = [paddle.randn([4, 6])]
self.assert_results(comp_with_fallback, x)
def for_arange(x):
for i in paddle.arange(0, 5):
x = x + i
return x
class TestArange(TestCaseBase):
def test_arange(self):
x = paddle.to_tensor(1)
self.assert_results(for_arange, x)
def for_break_with_load_same_consts(x: paddle.Tensor):
y = None
z = None
for i in [1, 2, 3]:
if y is None:
y = i
if z is None:
z = i
x += y + z
sot.psdb.breakgraph()
return x
class TestForBreakWithLoadSameConsts(TestCaseBase):
@strict_mode_guard(False)
def test_for_break_with_load_same_consts(self):
x = paddle.to_tensor(1)
self.assert_results(for_break_with_load_same_consts, x)
def for_break_with_write_pre_defined_name(x: paddle.Tensor):
y = None
for i in [1, 2, 3]:
y = i
sot.psdb.breakgraph()
return x + 1
class TestForBreakWithWritePreDefinedName(TestCaseBase):
@strict_mode_guard(False)
def test_for_break_with_write_pre_defined_name(self):
x = paddle.to_tensor(1)
self.assert_results(for_break_with_write_pre_defined_name, x)
if __name__ == "__main__":
unittest.main()