254 lines
7.2 KiB
Python
254 lines
7.2 KiB
Python
# Copyright (c) 2019 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.
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
from collections.abc import Callable
|
|
from functools import wraps
|
|
|
|
import numpy as np
|
|
|
|
import paddle
|
|
from paddle import base, get_flags, set_flags, static
|
|
from paddle.base import core
|
|
from paddle.base.framework import _dygraph_guard
|
|
from paddle.base.wrapped_decorator import signature_safe_contextmanager
|
|
from paddle.pir_utils import DygraphOldIrGuard
|
|
from paddle.utils.environments import (
|
|
BooleanEnvironmentVariable,
|
|
EnvironmentVariableGuard,
|
|
)
|
|
|
|
__all__ = ['DyGraphProgramDescTracerTestHelper', 'is_equal_program']
|
|
|
|
|
|
def is_equal_program(prog1, prog2):
|
|
with _dygraph_guard(None):
|
|
return _is_equal_program(prog1, prog2)
|
|
|
|
|
|
def _is_equal_program(prog1, prog2):
|
|
block_num = prog1.num_blocks
|
|
if block_num != prog2.num_blocks:
|
|
return False
|
|
|
|
for block_id in range(block_num):
|
|
block1 = prog1.block(block_id)
|
|
block2 = prog2.block(block_id)
|
|
|
|
if len(block1.ops) != len(block2.ops):
|
|
return False
|
|
|
|
if len(block1.vars) != len(block2.vars):
|
|
return False
|
|
|
|
for op1, op2 in zip(block1.ops, block2.ops):
|
|
if op1.input_arg_names != op2.input_arg_names:
|
|
return False
|
|
|
|
if op1.output_arg_names != op2.output_arg_names:
|
|
return False
|
|
|
|
attr1 = op1.all_attrs()
|
|
attr2 = op2.all_attrs()
|
|
|
|
if len(attr1) != len(attr2):
|
|
return False
|
|
|
|
for key1, value1 in attr1.items():
|
|
if key1 not in attr2:
|
|
return False
|
|
|
|
if value1 != attr2.get(key1):
|
|
return False
|
|
|
|
for var1 in block1.vars.values():
|
|
if var1.name not in block2.vars:
|
|
return False
|
|
|
|
var2 = block2.vars.get(var1.name)
|
|
if var1.name != var2.name:
|
|
return False
|
|
|
|
if var1.type != var2.type:
|
|
return False
|
|
|
|
if var1.dtype != var2.dtype:
|
|
return False
|
|
|
|
if var1.lod_level != var2.lod_level:
|
|
return False
|
|
|
|
if var1.persistable != var2.persistable:
|
|
return False
|
|
|
|
return True
|
|
|
|
|
|
def load_dygraph_vars_to_scope(model_path, scope, place):
|
|
def load_dict_to_scope(scope, dictionary):
|
|
if scope is None:
|
|
scope = base.global_scope()
|
|
|
|
for k, v in dictionary.items():
|
|
dst_t = scope.var(k).get_tensor()
|
|
src_t = v.value().get_tensor()
|
|
dst_t.set(np.array(src_t), place)
|
|
dst_t.set_lod(src_t.lod())
|
|
|
|
param_dict = paddle.load(model_path + '.pdparams')
|
|
opti_dict = paddle.load(model_path + '.pdopt')
|
|
if param_dict:
|
|
load_dict_to_scope(scope, param_dict)
|
|
|
|
if opti_dict:
|
|
load_dict_to_scope(scope, opti_dict)
|
|
|
|
|
|
class DyGraphProgramDescTracerTestHelper:
|
|
def __init__(self, unittest_obj):
|
|
self.unittest_obj = unittest_obj
|
|
|
|
def assertEachVar(self, out_dygraph, out_static_graph, func=None):
|
|
if func is None:
|
|
func = lambda x, y: np.array_equal(x, y)
|
|
|
|
if not isinstance(out_dygraph, (list, tuple)):
|
|
out_dygraph = [out_dygraph]
|
|
|
|
if not isinstance(out_static_graph, (list, tuple)):
|
|
out_static_graph = [out_static_graph]
|
|
|
|
for v1, v2 in zip(out_dygraph, out_static_graph):
|
|
self.unittest_obj.assertTrue(func(v1.numpy(), v2))
|
|
|
|
|
|
@signature_safe_contextmanager
|
|
def dygraph_guard():
|
|
in_dygraph_outside = paddle.base.framework.in_dygraph_mode()
|
|
try:
|
|
if not in_dygraph_outside:
|
|
paddle.disable_static()
|
|
yield
|
|
finally:
|
|
if not in_dygraph_outside:
|
|
paddle.enable_static()
|
|
|
|
|
|
@signature_safe_contextmanager
|
|
def static_guard():
|
|
in_dygraph_outside = paddle.base.framework.in_dygraph_mode()
|
|
try:
|
|
if in_dygraph_outside:
|
|
paddle.enable_static()
|
|
yield
|
|
finally:
|
|
if in_dygraph_outside:
|
|
paddle.disable_static()
|
|
|
|
|
|
@signature_safe_contextmanager
|
|
def pir_executor_guard():
|
|
tmp_env = os.environ.get("FLAGS_enable_pir_in_executor")
|
|
tmp_cpp = get_flags("FLAGS_enable_pir_in_executor")[
|
|
"FLAGS_enable_pir_in_executor"
|
|
]
|
|
try:
|
|
os.environ["FLAGS_enable_pir_in_executor"] = 'True'
|
|
set_flags({"FLAGS_enable_pir_in_executor": True})
|
|
yield
|
|
finally:
|
|
if tmp_env is None:
|
|
del os.environ["FLAGS_enable_pir_in_executor"]
|
|
else:
|
|
os.environ["FLAGS_enable_pir_in_executor"] = tmp_env
|
|
set_flags({"FLAGS_enable_pir_in_executor": tmp_cpp})
|
|
|
|
|
|
ENV_ENABLE_PIR_WITH_PT = BooleanEnvironmentVariable(
|
|
"FLAGS_enable_pir_in_executor", False
|
|
)
|
|
|
|
|
|
def to_pir_pt_test(fn):
|
|
@wraps(fn)
|
|
def impl(*args, **kwargs):
|
|
with DygraphOldIrGuard():
|
|
pt_flag = ENV_ENABLE_PIR_WITH_PT.name
|
|
original_flag_value = get_flags(pt_flag)[pt_flag]
|
|
if os.environ.get('FLAGS_use_stride_kernel', False):
|
|
return
|
|
with (
|
|
static.scope_guard(static.Scope()),
|
|
static.program_guard(static.Program()),
|
|
EnvironmentVariableGuard(ENV_ENABLE_PIR_WITH_PT, True),
|
|
):
|
|
try:
|
|
set_flags({pt_flag: True})
|
|
ir_outs = fn(*args, **kwargs)
|
|
finally:
|
|
set_flags({pt_flag: original_flag_value})
|
|
return ir_outs
|
|
|
|
return impl
|
|
|
|
|
|
def compare_legacy_with_pt(fn):
|
|
@wraps(fn)
|
|
def impl(*args, **kwargs):
|
|
outs = fn(*args, **kwargs)
|
|
if core._is_bwd_prim_enabled() or core._is_fwd_prim_enabled():
|
|
return outs
|
|
ir_outs = to_pir_pt_test(fn)(*args, **kwargs)
|
|
np.testing.assert_equal(
|
|
outs,
|
|
ir_outs,
|
|
err_msg=f'Dy2St Unittest Check ({fn.__name__}) has diff \n'
|
|
+ f'Expect {outs}\n'
|
|
+ f'But Got {ir_outs}',
|
|
)
|
|
return outs
|
|
|
|
return impl
|
|
|
|
|
|
FuncType = Callable[[], bool]
|
|
PlaceType = paddle.CPUPlace | paddle.CUDAPlace | str
|
|
|
|
|
|
def convert_place(place: PlaceType) -> str:
|
|
if isinstance(place, paddle.CPUPlace):
|
|
return 'cpu'
|
|
if isinstance(place, paddle.CUDAPlace):
|
|
return 'gpu'
|
|
return place
|
|
|
|
|
|
def get_places(
|
|
func: FuncType = lambda: True, isStr: bool = False
|
|
) -> list[PlaceType]:
|
|
places: list[PlaceType] = []
|
|
if paddle.is_compiled_with_cuda() and func():
|
|
places.append(paddle.CUDAPlace(0))
|
|
if (
|
|
os.environ.get('FLAGS_CI_both_cpu_and_gpu', 'False').lower()
|
|
in ['1', 'true', 'on']
|
|
or not places
|
|
):
|
|
places.insert(0, paddle.CPUPlace())
|
|
if isStr:
|
|
places = [convert_place(place) for place in places]
|
|
return places
|