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

413 lines
14 KiB
Python

# Copyright (c) 2024 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 os
import tempfile
import unittest
import paddle
from paddle import base
from paddle.vision.models import ResNet
from paddle.vision.models.resnet import BottleneckBlock
class TestSaveModuleWithCommonOp(unittest.TestCase):
def setUp(self):
self.temp_dir = tempfile.TemporaryDirectory()
paddle.enable_static()
def tearDown(self):
self.temp_dir.cleanup()
def test_save_load(self):
main_program = paddle.static.Program()
with paddle.static.program_guard(main_program):
input = paddle.full(
shape=[1, 512, 64], fill_value=0.5, dtype='float32'
)
weight = paddle.full(
shape=[64, 64], fill_value=0.5, dtype='float32'
)
bias = paddle.full(shape=[64], fill_value=1.0, dtype='float32')
x = paddle.matmul(input, weight)
y = paddle.add(x, bias)
file_path = os.path.join(self.temp_dir.name, "test_save_program1.json")
pir_version = 1
base.core.serialize_pir_program(
main_program, file_path, True, False, True, pir_version
)
recover_program = paddle.static.Program()
base.core.deserialize_pir_program(
file_path, recover_program, pir_version
)
self.assertEqual(
len(main_program.global_block().ops),
len(recover_program.global_block().ops),
)
for i in range(len(main_program.global_block().ops)):
self.assertEqual(
main_program.global_block().ops[i].name(),
recover_program.global_block().ops[i].name(),
)
def test_save_no_trainable(self):
# check save with trainable=False, no stopgradient info
main_program = paddle.static.Program()
with paddle.static.program_guard(main_program):
input = paddle.full(
shape=[1, 512, 64], fill_value=0.5, dtype='float32'
)
weight = paddle.full(
shape=[64, 64], fill_value=0.5, dtype='float32'
)
input.stop_gradient = False
bias = paddle.full(shape=[64], fill_value=1.0, dtype='float32')
x = paddle.matmul(input, weight)
y = paddle.add(x, bias)
file_path = os.path.join(
self.temp_dir.name, "test_save_program1_0.json"
)
pir_version = 1
base.core.serialize_pir_program(
main_program, file_path, True, True, False, pir_version
)
recover_program = paddle.static.Program()
base.core.deserialize_pir_program(
file_path, recover_program, pir_version
)
self.assertEqual(
main_program.global_block().ops[-1].result(0).stop_gradient,
False,
)
self.assertEqual(
recover_program.global_block().ops[-1].result(0).stop_gradient,
True,
)
def test_builtin_save(self):
main_program = paddle.static.Program()
with paddle.static.program_guard(main_program):
x_2 = paddle.static.data(shape=[4, 5], dtype='int32', name='x_2')
out1, out2 = paddle.split(x=x_2, num_or_sections=2, axis=0)
out = paddle.concat([out1, out2], axis=1)
file_path = os.path.join(self.temp_dir.name, "test_save_program2.json")
pir_version = 1
base.core.serialize_pir_program(
main_program, file_path, True, True, True, pir_version
)
recover_program = paddle.static.Program()
base.core.deserialize_pir_program(
file_path, recover_program, pir_version
)
self.assertEqual(
len(main_program.global_block().ops),
len(recover_program.global_block().ops),
)
for i in range(len(main_program.global_block().ops)):
self.assertEqual(
main_program.global_block().ops[i].name(),
recover_program.global_block().ops[i].name(),
)
def true_func():
a = paddle.full(shape=[1, 2], dtype='float32', fill_value=1)
b = paddle.full(shape=[2, 3], dtype='int64', fill_value=1)
return a, b
def false_func():
a = paddle.full(shape=[1, 2], dtype='float32', fill_value=3)
b = paddle.full(shape=[2, 3], dtype='int64', fill_value=2)
return a, b
class TestSaveModuleWithIfOp(unittest.TestCase):
def setUp(self):
self.temp_dir = tempfile.TemporaryDirectory()
paddle.enable_static()
def tearDown(self):
self.temp_dir.cleanup()
def construct_program_with_if(self):
main_program = paddle.static.Program()
startup_program = paddle.static.Program()
with paddle.static.program_guard(main_program, startup_program):
x = paddle.static.data(name="x", shape=[6, 1], dtype="float32")
y = paddle.static.data(name="y", shape=[6, 1], dtype="float32")
x.stop_gradient = False
y.stop_gradient = False
paddle.static.nn.cond(x < y, lambda: x + y, lambda: x - y)
return main_program
def check_block(self, org_block, load_block):
self.assertEqual(len(org_block.ops), len(load_block.ops))
for i in range(len(org_block.ops)):
org_op = org_block.ops[i]
load_op = load_block.ops[i]
self.assertEqual(
org_op.name(),
load_op.name(),
)
for org_block_in, load_block_in in zip(
org_op.blocks(), load_op.blocks()
):
self.check_block(org_block_in, load_block_in)
def test_if_with_single_output(self):
main_program = self.construct_program_with_if()
file_path = os.path.join(
self.temp_dir.name, "test_save_program_if.json"
)
pir_version = 1
base.core.serialize_pir_program(
main_program, file_path, True, False, True, pir_version
)
recover_program = paddle.static.Program()
base.core.deserialize_pir_program(
file_path, recover_program, pir_version
)
self.check_block(
main_program.global_block(), recover_program.global_block()
)
def test_if_with_multiple_output(self):
main_program = self.construct_program_with_if()
cond_value = main_program.global_block().ops[-1].operand_source(0)
with paddle.pir.core.program_guard(main_program):
paddle.static.nn.cond(cond_value, true_func, false_func)
file_path = os.path.join(
self.temp_dir.name, "test_save_program_if2.json"
)
pir_version = 1
base.core.serialize_pir_program(
main_program, file_path, True, False, True, pir_version
)
recover_program = paddle.static.Program()
base.core.deserialize_pir_program(
file_path, recover_program, pir_version
)
self.check_block(
main_program.global_block(), recover_program.global_block()
)
def cond(i, ten):
return i < ten
def body(i, ten):
i = i + 1
(i,) = paddle.static.nn.while_loop(
lambda p: p < ten, lambda p: [p + 3], [i]
)
return [i, ten]
class TestSaveModuleWithwhileOp(unittest.TestCase):
def setUp(self):
self.temp_dir = tempfile.TemporaryDirectory()
paddle.enable_static()
def tearDown(self):
self.temp_dir.cleanup()
def check_block(self, org_block, load_block):
self.assertEqual(len(org_block.ops), len(load_block.ops))
for i in range(len(org_block.ops)):
org_op = org_block.ops[i]
load_op = load_block.ops[i]
self.assertEqual(
org_op.name(),
load_op.name(),
)
for org_block_in, load_block_in in zip(
org_op.blocks(), load_op.blocks()
):
self.check_block(org_block_in, load_block_in)
def construct_program_with_while(self):
main_program = paddle.static.Program()
with paddle.pir.core.program_guard(main_program):
i = paddle.full(
shape=[1], fill_value=0, dtype='int64'
) # loop counter
ten = paddle.full(
shape=[1], fill_value=10, dtype='int64'
) # loop length
i.stop_gradient = False
i, ten = paddle.static.nn.while_loop(cond, body, [i, ten])
return main_program
def test_while_base(self):
main_program = self.construct_program_with_while()
file_path = os.path.join(
self.temp_dir.name, "test_save_program_while.json"
)
pir_version = 1
base.core.serialize_pir_program(
main_program, file_path, True, False, True, pir_version
)
recover_program = paddle.static.Program()
base.core.deserialize_pir_program(
file_path, recover_program, pir_version
)
self.check_block(
main_program.global_block(), recover_program.global_block()
)
def test_get_used_external_value(self):
main_program = paddle.static.Program()
with paddle.pir.core.program_guard(main_program):
i = paddle.full(shape=[1], fill_value=0)
x = paddle.full(shape=[1], fill_value=10)
y = paddle.full(shape=[1], fill_value=5)
# i, x = paddle.static.nn.while_loop(cond, body, [i, ten])
paddle.static.nn.while_loop(
lambda p, q: p < q, lambda p, q: [p + y, q + i], [i, x]
)
file_path = os.path.join(
self.temp_dir.name, "test_save_program_while.json"
)
pir_version = 1
base.core.serialize_pir_program(
main_program, file_path, True, False, True, pir_version
)
recover_program = paddle.static.Program()
base.core.deserialize_pir_program(
file_path, recover_program, pir_version
)
self.check_block(
main_program.global_block(), recover_program.global_block()
)
def test_nested_net(self):
def external_cond(i, j, init, sums):
return paddle.less_than(i, loop_len1)
def external_body(i, j, init, sums):
def internal_cond(j, init, sums):
return paddle.less_than(j, loop_len2)
def internal_body(j, init, sums):
init = paddle.add(x=init, y=ones)
sums = paddle.add(x=init, y=sums)
j = paddle.increment(j)
return [j, init, sums]
result = paddle.static.nn.while_loop(
internal_cond, internal_body, [j, init, sums]
)
j = result[0]
init = result[1]
sums = result[2]
sums = paddle.add(x=init, y=sums)
i = paddle.increment(i)
return [i, j, init, sums]
main_program = paddle.static.Program()
startup_program = paddle.static.Program()
with paddle.static.program_guard(main_program, startup_program):
i = paddle.zeros(shape=[1], dtype='int64')
j = paddle.zeros(shape=[1], dtype='int64')
init = paddle.static.data(
name='init', shape=[3, 3], dtype='float32'
)
sums = paddle.static.data(
name='sums', shape=[3, 3], dtype='float32'
)
loop_len1 = paddle.tensor.fill_constant(
shape=[1], dtype='int64', value=2
)
loop_len2 = paddle.tensor.fill_constant(
shape=[1], dtype='int64', value=3
)
ones = paddle.tensor.fill_constant(
shape=[3, 3], dtype='float32', value=1
)
out = paddle.static.nn.while_loop(
external_cond, external_body, [i, j, init, sums]
)
file_path = os.path.join(
self.temp_dir.name, "test_save_program_while_nest.json"
)
pir_version = 1
base.core.serialize_pir_program(
main_program, file_path, True, False, True, pir_version
)
recover_program = paddle.static.Program()
base.core.deserialize_pir_program(
file_path, recover_program, pir_version
)
self.check_block(
main_program.global_block(), recover_program.global_block()
)
class TestJsonToPdmodel(unittest.TestCase):
def setUp(self):
self.temp_dir = tempfile.TemporaryDirectory()
paddle.disable_static()
def tearDown(self):
self.temp_dir.cleanup()
def test_json_to_pdmodel(self):
net = ResNet(BottleneckBlock, 50)
net = paddle.jit.to_static(net, full_graph=True)
save_json = os.path.join(self.temp_dir.name, 'save1')
save_model = os.path.join(self.temp_dir.name, 'save2')
input_spec = [
paddle.static.InputSpec(shape=[1, 3, 224, 224], dtype='float32')
]
paddle.jit.save(net, save_json, input_spec)
# load and save to pdmodel
with paddle.pir_utils.OldIrGuard():
input_spec = [
paddle.static.InputSpec(shape=[1, 3, 224, 224], dtype='float32')
]
paddle.jit.json_to_pdmodel(net, input_spec, save_json, save_model)
self.assertTrue(os.path.exists(save_model + '.pdmodel'))
if __name__ == '__main__':
unittest.main()