653 lines
21 KiB
Python
653 lines
21 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.
|
|
|
|
import os
|
|
import platform
|
|
import site
|
|
import sys
|
|
import warnings
|
|
|
|
has_paddle_dy_lib = False
|
|
|
|
dy_lib_name = 'libpaddle'
|
|
dy_lib_suffix = 'so'
|
|
if os.name == 'nt':
|
|
dy_lib_suffix = 'pyd'
|
|
|
|
current_path = os.path.abspath(os.path.dirname(__file__))
|
|
if os.path.exists(current_path + os.sep + dy_lib_name + '.' + dy_lib_suffix):
|
|
has_paddle_dy_lib = True
|
|
|
|
|
|
try:
|
|
if os.name == 'nt':
|
|
third_lib_path = current_path + os.sep + '..' + os.sep + 'libs'
|
|
# Will load shared library from 'path' on windows
|
|
os.environ['path'] = (
|
|
current_path + ';' + third_lib_path + ';' + os.environ['path']
|
|
)
|
|
sys.path.insert(0, third_lib_path)
|
|
# Note: from python3.8, PATH will not take effect
|
|
# https://github.com/python/cpython/pull/12302
|
|
# Use add_dll_directory to specify dll resolution path
|
|
os.add_dll_directory(third_lib_path)
|
|
|
|
except ImportError as e:
|
|
if os.name == 'nt':
|
|
executable_path = os.path.abspath(os.path.dirname(sys.executable))
|
|
raise ImportError(
|
|
f"""NOTE: You may need to run \"set PATH={executable_path};%PATH%\"
|
|
if you encounters \"DLL load failed\" errors. If you have python
|
|
installed in other directory, replace \"{executable_path}\" with your own
|
|
directory. The original error is: \n {e}"""
|
|
)
|
|
else:
|
|
raise ImportError(
|
|
"""NOTE: You may need to run \"export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH\"
|
|
if you encounters \"libmkldnn.so not found\" errors. If you have python
|
|
installed in other directory, replace \"/usr/local/lib\" with your own
|
|
directory. The original error is: \n"""
|
|
+ str(e)
|
|
)
|
|
except Exception as e:
|
|
raise e
|
|
|
|
|
|
def avx_supported():
|
|
"""
|
|
Whether current system(Linux, MacOS, Windows) is supported with AVX.
|
|
"""
|
|
sysstr = platform.system().lower()
|
|
has_avx = False
|
|
if sysstr == 'linux':
|
|
try:
|
|
pipe = os.popen('cat /proc/cpuinfo | grep -i avx')
|
|
has_avx = pipe.read() != ''
|
|
pipe.close()
|
|
except Exception as e:
|
|
sys.stderr.write(
|
|
'Can not get the AVX flag from /proc/cpuinfo.\n'
|
|
f'The original error is: {e}\n'
|
|
)
|
|
return has_avx
|
|
elif sysstr == 'darwin':
|
|
try:
|
|
pipe = os.popen('sysctl machdep.cpu.features | grep -i avx')
|
|
has_avx = pipe.read() != ''
|
|
pipe.close()
|
|
except Exception as e:
|
|
sys.stderr.write(
|
|
'Can not get the AVX flag from machdep.cpu.features.\n'
|
|
f'The original error is: {e}\n'
|
|
)
|
|
if not has_avx:
|
|
import subprocess
|
|
|
|
pipe = subprocess.Popen(
|
|
'sysctl machdep.cpu.leaf7_features | grep -i avx',
|
|
shell=True,
|
|
stdout=subprocess.PIPE,
|
|
stderr=subprocess.PIPE,
|
|
)
|
|
_ = pipe.communicate()
|
|
has_avx = True if pipe.returncode == 0 else False
|
|
return has_avx
|
|
elif sysstr == 'windows':
|
|
import ctypes
|
|
|
|
ONE_PAGE = ctypes.c_size_t(0x1000)
|
|
|
|
def asm_func(code_str, restype=ctypes.c_uint32, argtypes=()):
|
|
# Call the code_str as a function
|
|
# Alloc 1 page to ensure the protection
|
|
pfnVirtualAlloc = ctypes.windll.kernel32.VirtualAlloc
|
|
pfnVirtualAlloc.restype = ctypes.c_void_p
|
|
MEM_COMMIT = ctypes.c_ulong(0x1000)
|
|
PAGE_READWRITE = ctypes.c_ulong(0x4)
|
|
address = pfnVirtualAlloc(
|
|
None, ONE_PAGE, MEM_COMMIT, PAGE_READWRITE
|
|
)
|
|
if not address:
|
|
raise Exception("Failed to VirtualAlloc")
|
|
|
|
# Copy the code into the memory segment
|
|
memmove = ctypes.CFUNCTYPE(
|
|
ctypes.c_void_p,
|
|
ctypes.c_void_p,
|
|
ctypes.c_void_p,
|
|
ctypes.c_size_t,
|
|
)(ctypes._memmove_addr)
|
|
if memmove(address, code_str, len(code_str)) < 0:
|
|
raise Exception("Failed to memmove")
|
|
|
|
# Enable execute permissions
|
|
PAGE_EXECUTE = ctypes.c_ulong(0x10)
|
|
pfnVirtualProtect = ctypes.windll.kernel32.VirtualProtect
|
|
res = pfnVirtualProtect(
|
|
ctypes.c_void_p(address),
|
|
ONE_PAGE,
|
|
PAGE_EXECUTE,
|
|
ctypes.byref(ctypes.c_ulong(0)),
|
|
)
|
|
if not res:
|
|
raise Exception("Failed VirtualProtect")
|
|
|
|
# Flush instruction cache
|
|
pfnGetCurrentProcess = ctypes.windll.kernel32.GetCurrentProcess
|
|
pfnGetCurrentProcess.restype = ctypes.c_void_p
|
|
prochandle = ctypes.c_void_p(pfnGetCurrentProcess())
|
|
res = ctypes.windll.kernel32.FlushInstructionCache(
|
|
prochandle, ctypes.c_void_p(address), ONE_PAGE
|
|
)
|
|
if not res:
|
|
raise Exception("Failed FlushInstructionCache")
|
|
|
|
# Cast the memory to function
|
|
functype = ctypes.CFUNCTYPE(restype, *argtypes)
|
|
func = functype(address)
|
|
return func, address
|
|
|
|
# http://en.wikipedia.org/wiki/CPUID#EAX.3D1:_Processor_Info_and_Feature_Bits
|
|
# mov eax,0x1; cpuid; mov cx, ax; ret
|
|
code_str = b"\xb8\x01\x00\x00\x00\x0f\xa2\x89\xc8\xc3"
|
|
avx_bit = 28
|
|
retval = 0
|
|
try:
|
|
# Convert the code_str into a function that returns uint
|
|
func, address = asm_func(code_str)
|
|
retval = func()
|
|
ctypes.windll.kernel32.VirtualFree(
|
|
ctypes.c_void_p(address), ctypes.c_size_t(0), ONE_PAGE
|
|
)
|
|
except Exception as e:
|
|
sys.stderr.write(
|
|
'Failed getting the AVX flag on Windows.\n'
|
|
f'The original error is: {e}\n'
|
|
)
|
|
return (retval & (1 << avx_bit)) > 0
|
|
else:
|
|
sys.stderr.write(f'Do not get AVX flag on {sysstr}\n')
|
|
return False
|
|
|
|
|
|
def run_shell_command(cmd):
|
|
import subprocess
|
|
|
|
out, err = subprocess.Popen(
|
|
cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True
|
|
).communicate()
|
|
if err:
|
|
return None
|
|
else:
|
|
return out.decode('utf-8').strip()
|
|
|
|
|
|
def get_dso_path(core_so, dso_name):
|
|
if core_so and dso_name:
|
|
return run_shell_command(
|
|
f"ldd {core_so}|grep {dso_name}|awk '{{print $3}}'"
|
|
)
|
|
else:
|
|
return None
|
|
|
|
|
|
def load_dso(dso_absolute_path):
|
|
if dso_absolute_path:
|
|
try:
|
|
from ctypes import cdll
|
|
|
|
cdll.LoadLibrary(dso_absolute_path)
|
|
except:
|
|
warnings.warn(f"Load {dso_absolute_path} failed")
|
|
|
|
|
|
def pre_load(dso_name):
|
|
if has_paddle_dy_lib:
|
|
core_so = current_path + os.sep + dy_lib_name + '.' + dy_lib_suffix
|
|
else:
|
|
core_so = None
|
|
dso_path = get_dso_path(core_so, dso_name)
|
|
load_dso(dso_path)
|
|
|
|
|
|
def get_libc_ver():
|
|
ldd_glibc = run_shell_command("ldd --version | awk '/ldd/{print $NF}'")
|
|
if ldd_glibc is not None:
|
|
return ("glibc", ldd_glibc)
|
|
|
|
ldd_musl = run_shell_command("ldd 2>&1 | awk '/Version/{print $NF}'")
|
|
if ldd_musl is not None:
|
|
return ("musl", ldd_musl)
|
|
return (None, None)
|
|
|
|
|
|
def less_than_ver(a, b):
|
|
if a is None or b is None:
|
|
return False
|
|
|
|
import operator
|
|
import re
|
|
|
|
def to_list(s):
|
|
s = re.sub(r'(\.0+)+$', '', s)
|
|
return [int(x) for x in s.split('.')]
|
|
|
|
return operator.lt(to_list(a), to_list(b))
|
|
|
|
|
|
# NOTE(zhiqiu): An error may occurs when import paddle in linux platform with glibc < 2.22,
|
|
# the error message of which is "dlopen: cannot load any more object with static TLS".
|
|
# This happens when:
|
|
# (1) the number of dynamic shared libraries (DSO) loaded > 14,
|
|
# (2) after that, load a dynamic shared library (DSO) with static TLS.
|
|
# For paddle, the problem is that 'libgomp' is a DSO with static TLS, and it is loaded after 14 DSOs.
|
|
# So, here is a tricky way to solve the problem by pre load 'libgomp' before 'libpaddle.so'.
|
|
# The final solution is to upgrade glibc to > 2.22 on the target system.
|
|
if platform.system().lower() == 'linux':
|
|
libc_type, libc_ver = get_libc_ver()
|
|
if libc_type == 'glibc' and less_than_ver(libc_ver, '2.23'):
|
|
try:
|
|
pre_load('libgomp')
|
|
except Exception as e:
|
|
# NOTE(zhiqiu): do not abort if failed, since it may success when import libpaddle.so
|
|
sys.stderr.write('Error: Can not preload libgomp.so')
|
|
|
|
try:
|
|
from . import libpaddle
|
|
|
|
if avx_supported() and not libpaddle.is_compiled_with_avx():
|
|
sys.stderr.write(
|
|
"Hint: Your machine support AVX, but the installed paddlepaddle doesn't have avx core. "
|
|
"Hence, no-avx core with worse performance will be imported.\nIf you like, you could "
|
|
"reinstall paddlepaddle by 'python -m pip install --force-reinstall paddlepaddle-gpu[==version]' "
|
|
"to get better performance.\n"
|
|
)
|
|
|
|
# assign tensor alias
|
|
libpaddle.LoDTensor = libpaddle.DenseTensor
|
|
libpaddle.Tensor = libpaddle.DenseTensor
|
|
libpaddle.VarDesc.VarType.LOD_TENSOR = (
|
|
libpaddle.VarDesc.VarType.DENSE_TENSOR
|
|
)
|
|
libpaddle.VarDesc.VarType.LOD_TENSOR_ARRAY = (
|
|
libpaddle.VarDesc.VarType.DENSE_TENSOR_ARRAY
|
|
)
|
|
|
|
from .libpaddle import * # noqa: F403
|
|
from .libpaddle import ( # noqa: F401
|
|
__doc__,
|
|
__file__,
|
|
__name__,
|
|
__package__,
|
|
__unittest_throw_exception__,
|
|
_append_python_callable_object_and_return_id,
|
|
_check_last_cuda_error,
|
|
_cleanup,
|
|
_create_loaded_parameter,
|
|
_cuda_synchronize,
|
|
_device_synchronize,
|
|
_dygraph_debug_level,
|
|
_get_all_register_op_kernels,
|
|
_get_amp_attrs,
|
|
_get_amp_op_list,
|
|
_get_current_stream,
|
|
_get_eager_deletion_vars,
|
|
_get_legacy_default_stream,
|
|
_get_phi_kernel_name,
|
|
_get_registered_phi_kernels,
|
|
_get_stream_from_external,
|
|
_get_use_default_grad_op_desc_maker_ops,
|
|
_has_grad,
|
|
_is_compiled_with_heterps,
|
|
_is_dygraph_debug_enabled,
|
|
_is_program_version_supported,
|
|
_Profiler,
|
|
_ProfilerResult,
|
|
_promote_types_if_complex_exists,
|
|
_RecordEvent,
|
|
_Scope,
|
|
_set_amp_op_list,
|
|
_set_current_stream,
|
|
_set_eager_deletion_mode,
|
|
_set_fuse_parameter_group_size,
|
|
_set_fuse_parameter_memory_size,
|
|
_set_has_grad,
|
|
_set_paddle_lib_path,
|
|
_set_warmup,
|
|
_switch_tracer,
|
|
_test_enforce_gpu_success,
|
|
_xpu_device_synchronize,
|
|
_xpu_get_current_stream,
|
|
_xpu_set_current_stream,
|
|
)
|
|
|
|
# isort: off
|
|
|
|
# custom device
|
|
from .libpaddle import ( # noqa: F401
|
|
CustomDeviceEvent,
|
|
CustomDeviceStream,
|
|
_get_current_custom_device_stream,
|
|
_set_current_custom_device_stream,
|
|
_synchronize_custom_device,
|
|
)
|
|
|
|
# prim controller flags
|
|
from .libpaddle import ( # noqa: F401
|
|
__set_all_prim_enabled,
|
|
__set_bwd_prim_enabled,
|
|
__set_eager_prim_enabled,
|
|
__set_fwd_prim_enabled,
|
|
_add_skip_comp_ops,
|
|
_is_bwd_prim_enabled,
|
|
_is_eager_prim_enabled,
|
|
_is_fwd_prim_enabled,
|
|
_is_all_prim_enabled,
|
|
_remove_skip_comp_ops,
|
|
_set_bwd_prim_blacklist,
|
|
_set_prim_target_grad_name,
|
|
)
|
|
|
|
# type promotion
|
|
|
|
# isort: on
|
|
if sys.platform != 'win32':
|
|
from .libpaddle import ( # noqa: F401
|
|
_array_to_share_memory_tensor,
|
|
_cleanup_mmap_fds,
|
|
_convert_to_tensor_list,
|
|
_erase_process_pids,
|
|
_remove_tensor_list_mmap_fds,
|
|
_set_max_memory_map_allocation_pool_size,
|
|
_set_process_pids,
|
|
_set_process_signal_handler,
|
|
_throw_error_if_process_failed,
|
|
)
|
|
|
|
except Exception as e:
|
|
if has_paddle_dy_lib:
|
|
sys.stderr.write(
|
|
'Error: Can not import paddle core while this file exists: '
|
|
+ current_path
|
|
+ os.sep
|
|
+ 'libpaddle.'
|
|
+ dy_lib_suffix
|
|
+ '\n'
|
|
)
|
|
if not avx_supported() and libpaddle.is_compiled_with_avx():
|
|
sys.stderr.write(
|
|
"Error: Your machine doesn't support AVX, but the installed PaddlePaddle is avx core, "
|
|
"you should reinstall paddlepaddle with no-avx core.\n"
|
|
)
|
|
raise e
|
|
|
|
|
|
def set_paddle_custom_device_lib_path(lib_dir):
|
|
if os.environ.get('CUSTOM_DEVICE_ROOT', None) is not None:
|
|
# use set environment value
|
|
return
|
|
path1 = os.path.normpath(
|
|
os.path.join(lib_dir, '..', 'paddle_custom_device')
|
|
)
|
|
if os.path.exists(path1):
|
|
# set CUSTOM_DEVICE_ROOT default path (lib_dir/../paddle_custom_device)
|
|
os.environ['CUSTOM_DEVICE_ROOT'] = path1
|
|
else:
|
|
path2 = os.path.normpath(
|
|
os.path.join(lib_dir, '..', '..', 'paddle_custom_device')
|
|
)
|
|
if os.path.exists(path2):
|
|
# set CUSTOM_DEVICE_ROOT default path (lib_dir/../../paddle_custom_device)
|
|
os.environ['CUSTOM_DEVICE_ROOT'] = path2
|
|
else:
|
|
os.environ['CUSTOM_DEVICE_ROOT'] = ''
|
|
|
|
|
|
# set paddle lib path
|
|
def set_paddle_lib_path():
|
|
site_dirs = site.getsitepackages()
|
|
for site_dir in site_dirs:
|
|
lib_dir = os.path.sep.join([site_dir, 'paddle', 'libs'])
|
|
if os.path.exists(lib_dir):
|
|
_set_paddle_lib_path(lib_dir)
|
|
set_paddle_custom_device_lib_path(lib_dir)
|
|
return
|
|
if hasattr(site, 'USER_SITE') and site.USER_SITE:
|
|
lib_dir = os.path.sep.join([site.USER_SITE, 'paddle', 'libs'])
|
|
if os.path.exists(lib_dir):
|
|
_set_paddle_lib_path(lib_dir)
|
|
set_paddle_custom_device_lib_path(lib_dir)
|
|
|
|
|
|
set_paddle_lib_path()
|
|
|
|
|
|
# This api is used for check of model output.
|
|
# In some cases, model does not straightly return data which can be used for check.
|
|
# When this flag is set true, required data should be returned in model.
|
|
def _model_return_data():
|
|
flag = os.getenv("FLAGS_model_return_data")
|
|
if flag and flag.lower() in ("1", "true"):
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
|
|
# This api is used for check whether prim is on
|
|
def _prim_return_log():
|
|
flag = os.getenv("FLAGS_prim_log")
|
|
if flag and flag.lower() in ("1", "true"):
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
|
|
# ops in forward_blacklist will not be replaced by composite ops.
|
|
prim_config = {
|
|
"forward_blacklist": set(),
|
|
"composite_ops_record": set(),
|
|
"backward_blacklist": set(),
|
|
}
|
|
|
|
|
|
def _get_batch_norm_none_var(op):
|
|
"""Some outputs of batch_norm's replaced composite rule are not needed and will be removed."""
|
|
use_run_stat = (
|
|
op.attr("is_test") and (not op.attr("trainable_statistics"))
|
|
) or op.attr("use_global_stats")
|
|
if use_run_stat:
|
|
return ["ReserveSpace", "SavedMean", "SavedVariance"]
|
|
else:
|
|
return ["ReserveSpace"]
|
|
|
|
|
|
# In some case, inputs and outputs of composite op or its replaced composite rule might be None.
|
|
# It means such arg will be no longer required in processed program by composite mechanism.
|
|
# Therefore, such special ops should be recorded in advance and be released in args check.
|
|
ops_contain_none = {
|
|
"batch_norm": _get_batch_norm_none_var,
|
|
"flatten_contiguous_range": ["XShape"],
|
|
"squeeze2": ["XShape"],
|
|
"unsqueeze2": ["XShape"],
|
|
}
|
|
|
|
|
|
# some intermediate outputs like xshape will no longer used after decomp, but return none to keep output num the same as origin op
|
|
# key is the name of op, and value is the index of output in op.outputs
|
|
decomp_ops_contain_unused_output = {
|
|
"pd_op.squeeze": [1],
|
|
"pd_op.unsqueeze": [1],
|
|
"pd_op.batch_norm": [5],
|
|
}
|
|
|
|
|
|
# This api is used for development for dynamic shape in prim, and will be removed in future.
|
|
def _enable_prim_skip_dynamic_shape():
|
|
from paddle.base.framework import get_flags
|
|
|
|
return get_flags("FLAGS_prim_skip_dynamic")["FLAGS_prim_skip_dynamic"]
|
|
|
|
|
|
def _enable_prim_dynamic_shape():
|
|
from paddle.base.framework import get_flags
|
|
|
|
return get_flags("FLAGS_prim_enable_dynamic")["FLAGS_prim_enable_dynamic"]
|
|
|
|
|
|
def _enable_dist_prim_all():
|
|
flag = os.getenv("FLAGS_dist_prim_all")
|
|
if flag and flag.lower() in ("1", "true"):
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
|
|
def _enable_auto_recompute():
|
|
flag = os.getenv("FLAGS_enable_auto_recompute")
|
|
|
|
# NOTE(chenxi67): open recompute when cinn is enabled
|
|
from paddle.base.framework import in_cinn_mode
|
|
|
|
if in_cinn_mode():
|
|
if flag and flag.lower() in ("0", "false"):
|
|
return False
|
|
else:
|
|
return True
|
|
if flag and flag.lower() in ("1", "true"):
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
|
|
def _set_prim_forward_blacklist(*args):
|
|
for item in args:
|
|
if not isinstance(item, str):
|
|
raise TypeError("ops set in forward_blacklist must belong to str")
|
|
else:
|
|
prim_config["forward_blacklist"].add(item)
|
|
|
|
|
|
# Currently, this function is not utilized anywhere in the codebase.
|
|
# It may be intended for future use or could be removed if unnecessary.
|
|
# def _reset_prim_forward_blacklist():
|
|
# prim_config["forward_blacklist"] = set()
|
|
|
|
|
|
def _set_prim_backward_blacklist(*args):
|
|
ops = set(args)
|
|
new_ops = set()
|
|
for item in ops:
|
|
if not isinstance(item, str):
|
|
raise TypeError("All items in set must be strings.")
|
|
item = item.removeprefix("pd_op.")
|
|
prim_config["backward_blacklist"].add(item)
|
|
new_ops.add(item)
|
|
_set_bwd_prim_blacklist(new_ops)
|
|
|
|
|
|
def _set_prim_backward_enabled(value: bool, print_flag: bool = False):
|
|
assert isinstance(value, bool), (
|
|
f"value should be bool, but got {type(value)}"
|
|
)
|
|
__set_bwd_prim_enabled(value)
|
|
if _prim_return_log() or print_flag:
|
|
print("backward prim enabled: ", bool(_is_bwd_prim_enabled()))
|
|
|
|
|
|
def _set_prim_forward_enabled(value: bool, print_flag: bool = False):
|
|
assert isinstance(value, bool), (
|
|
f"value should be bool, but got {type(value)}"
|
|
)
|
|
__set_fwd_prim_enabled(value)
|
|
if _prim_return_log() or print_flag:
|
|
print("forward prim enabled: ", bool(_is_fwd_prim_enabled()))
|
|
|
|
|
|
def set_prim_eager_enabled(value: bool, print_flag: bool = False):
|
|
assert isinstance(value, bool), (
|
|
f"value should be bool, but got {type(value)}"
|
|
)
|
|
__set_eager_prim_enabled(value)
|
|
if _prim_return_log() or print_flag:
|
|
print("eager prim enabled: ", bool(_is_eager_prim_enabled()))
|
|
|
|
|
|
def _set_prim_all_enabled(value: bool, print_flag: bool = False):
|
|
assert isinstance(value, bool), (
|
|
f"value should be bool, but got {type(value)}"
|
|
)
|
|
__set_all_prim_enabled(value)
|
|
if _prim_return_log() or print_flag:
|
|
print(
|
|
"all prim enabled: ",
|
|
bool(_is_all_prim_enabled()),
|
|
)
|
|
|
|
|
|
def __check_and_set_prim_all_enabled(print_flag=False):
|
|
from paddle.utils.environments import strtobool
|
|
|
|
prim_all_env = os.getenv("FLAGS_prim_all")
|
|
prim_fwd_env = os.getenv("FLAGS_prim_forward")
|
|
prim_bwd_env = os.getenv("FLAGS_prim_backward")
|
|
if prim_all_env is not None:
|
|
prim_all_flag = strtobool(prim_all_env)
|
|
_set_prim_all_enabled(prim_all_flag, print_flag)
|
|
|
|
if prim_fwd_env is not None:
|
|
prim_fwd_flag = strtobool(prim_fwd_env)
|
|
_set_prim_forward_enabled(prim_fwd_flag, print_flag)
|
|
|
|
if prim_bwd_env is not None:
|
|
prim_bwd_flag = strtobool(prim_bwd_env)
|
|
_set_prim_backward_enabled(prim_bwd_flag, print_flag)
|
|
|
|
|
|
__check_and_set_prim_all_enabled(print_flag=True)
|
|
|
|
|
|
SKIPPED_PRIM_VJP_DEFAULT_OPS = ["matmul_grad"]
|
|
|
|
|
|
def _clear_prim_vjp_skip_default_ops():
|
|
for item in SKIPPED_PRIM_VJP_DEFAULT_OPS:
|
|
_remove_skip_comp_ops(item)
|
|
|
|
|
|
# Since some decomposition of special ops like matmul_grad will reduce performance and is difficult to optimize currently by CINN.
|
|
# This api is used for development for in prim and cinn, and will be removed in future.
|
|
def _check_and_set_prim_vjp_skip_default_ops():
|
|
flag = os.getenv("FLAGS_prim_vjp_skip_default_ops", "1")
|
|
if flag and flag.lower() in ("1", "true"):
|
|
_set_prim_backward_blacklist(*SKIPPED_PRIM_VJP_DEFAULT_OPS)
|
|
return True
|
|
else:
|
|
_clear_prim_vjp_skip_default_ops()
|
|
return False
|
|
|
|
|
|
_check_and_set_prim_vjp_skip_default_ops()
|
|
|
|
|
|
def _check_prim_vjp_ops():
|
|
ops_org = os.getenv("FLAGS_prim_backward_blacklist", "")
|
|
if ops_org:
|
|
ops = []
|
|
for item in ops_org.split(";"):
|
|
ops.append(item.strip())
|
|
_set_prim_backward_blacklist(*ops)
|
|
|
|
|
|
_check_prim_vjp_ops()
|