chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 12:40:42 +08:00
commit e25996e7db
15472 changed files with 3536181 additions and 0 deletions
+102
View File
@@ -0,0 +1,102 @@
# Copyright (c) 2020 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.
# TODO: import framework api under this directory
from ..base import core # noqa: F401
from ..base.core import ( # noqa: F401
CPUPlace,
CUDAPinnedPlace,
CUDAPlace,
CustomPlace,
IPUPlace,
XPUPinnedPlace,
XPUPlace,
)
from ..base.dygraph import base # noqa: F401
from ..base.dygraph.base import ( # noqa: F401
disable_dygraph as enable_static,
enable_dygraph as disable_static,
grad,
no_grad_ as no_grad,
)
from ..base.framework import ( # noqa: F401
Block,
IrGraph,
OpProtoHolder,
Parameter,
Program,
_apply_pass,
_create_tensor,
_current_expected_place,
_current_expected_place_,
_dygraph_tracer,
_get_paddle_place,
_global_flags,
_set_expected_place,
_stride_in_no_check_dy2st_diff as _no_check_dy2st_diff,
_to_pinned_place,
convert_nptype_to_datatype_or_vartype,
convert_nptype_to_vartype,
convert_to_datatype,
convert_to_vartype,
deprecate_stat_dict,
disable_signal_handler,
dygraph_not_support,
dygraph_only,
generate_control_dev_var_name,
get_flags,
in_dygraph_mode as in_dynamic_mode,
in_dynamic_or_pir_mode,
in_pir_executor_mode,
in_pir_mode,
set_flags,
switch_main_program,
switch_startup_program,
use_pir_api,
)
from ..base.layer_helper import LayerHelper # noqa: F401
from .io import async_save, clear_async_save_task_queue # noqa: F401
# isort: off
# Do the *DUPLICATED* monkey-patch for the tensor object.
# We need remove the duplicated code here once we fix
# the illogical implement in the monkey-patch methods later.
from ..base.dygraph.math_op_patch import monkey_patch_math_tensor # noqa: F401
from ..base.layers.math_op_patch import monkey_patch_variable # noqa: F401
# isort: on
from ..base.param_attr import ParamAttr # noqa: F401
from . import random # noqa: F401
from .framework import ( # noqa: F401
get_default_dtype,
set_default_dtype,
set_default_tensor_type,
)
from .io import load, save # noqa: F401
from .io_utils import ( # noqa: F401
_clone_var_in_block_,
_load_program_scope,
_open_file_buffer,
_pack_loaded_dict,
_pickle_loads_mac,
_unpack_saved_dict,
is_belong_to_optimizer,
is_parameter,
is_persistable,
)
from .random import seed # noqa: F401
__all__ = []
+358
View File
@@ -0,0 +1,358 @@
# Copyright (c) 2021 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
from typing import TYPE_CHECKING
import numpy as np
import paddle
from paddle.utils.decorator_utils import param_one_alias
from ..base import framework
from ..base.core import (
DataType,
VarDesc,
finfo as core_finfo,
iinfo as core_iinfo,
size_of_dtype,
)
if TYPE_CHECKING:
from paddle._typing import DTypeLike
def bind_vartype():
global dtype
global uint8
global uint16
global uint32
global uint64
global int8
global short
global int16
global int
global int32
global long
global int64
global float
global float32
global double
global float64
global half
global float16
global bfloat16
global float8_e4m3fn
global float8_e5m2
global cfloat
global complex64
global cdouble
global complex128
global bool
global pstring
global raw
dtype = VarDesc.VarType
dtype.__qualname__ = "dtype"
dtype.__module__ = "paddle"
dtype.itemsize = property(
lambda self: size_of_dtype(self),
doc="The size in bytes of a single scalar value of this dtype.",
)
uint8 = VarDesc.VarType.UINT8
uint16 = VarDesc.VarType.UINT16
uint32 = VarDesc.VarType.UINT32
uint64 = VarDesc.VarType.UINT64
int8 = VarDesc.VarType.INT8
int16 = VarDesc.VarType.INT16
short = int16
int32 = VarDesc.VarType.INT32
int = int32
int64 = VarDesc.VarType.INT64
long = int64
float32 = VarDesc.VarType.FP32
float = float32
float64 = VarDesc.VarType.FP64
double = float64
float16 = VarDesc.VarType.FP16
half = float16
bfloat16 = VarDesc.VarType.BF16
float8_e4m3fn = VarDesc.VarType.FP8_E4M3FN
float8_e5m2 = VarDesc.VarType.FP8_E5M2
complex64 = VarDesc.VarType.COMPLEX64
cfloat = complex64
complex128 = VarDesc.VarType.COMPLEX128
cdouble = complex128
bool = VarDesc.VarType.BOOL
pstring = VarDesc.VarType.STRING
raw = VarDesc.VarType.RAW
paddle.dtype = dtype
paddle.uint8 = uint8
paddle.uint16 = uint16
paddle.uint32 = uint32
paddle.uint64 = uint64
paddle.int8 = int8
paddle.int16 = int16
paddle.short = short
paddle.int32 = int32
paddle.int = int
paddle.int64 = int64
paddle.long = long
paddle.float32 = float32
paddle.float = float
paddle.float64 = float64
paddle.double = double
paddle.float16 = float16
paddle.half = half
paddle.bfloat16 = bfloat16
paddle.float8_e4m3fn = float8_e4m3fn
paddle.float8_e5m2 = float8_e5m2
paddle.complex64 = complex64
paddle.cfloat = cfloat
paddle.complex128 = complex128
paddle.cdouble = cdouble
paddle.bool = bool
paddle.pstring = pstring
paddle.raw = raw
def bind_datatype():
global dtype
global uint8
global uint16
global uint32
global uint64
global int8
global short
global int16
global int
global int32
global long
global int64
global float
global float32
global double
global float64
global half
global float16
global bfloat16
global float8_e4m3fn
global float8_e5m2
global cfloat
global complex64
global cdouble
global complex128
global bool
global pstring
global raw
dtype = DataType
dtype.__qualname__ = "dtype"
dtype.__module__ = "paddle"
dtype.itemsize = property(
lambda self: size_of_dtype(self),
doc="The size in bytes of a single scalar value of this dtype.",
)
uint8 = DataType.UINT8
uint16 = DataType.UINT16
uint32 = DataType.UINT32
uint64 = DataType.UINT64
int8 = DataType.INT8
int16 = DataType.INT16
short = int16
int32 = DataType.INT32
int = int32
int64 = DataType.INT64
long = int64
float32 = DataType.FLOAT32
float = float32
float64 = DataType.FLOAT64
double = float64
float16 = DataType.FLOAT16
half = float16
bfloat16 = DataType.BFLOAT16
float8_e4m3fn = DataType.FLOAT8_E4M3FN
float8_e5m2 = DataType.FLOAT8_E5M2
complex64 = DataType.COMPLEX64
cfloat = complex64
complex128 = DataType.COMPLEX128
cdouble = complex128
bool = DataType.BOOL
pstring = DataType.PSTRING
raw = DataType.ALL_DTYPE # refer to TransToPhiDataType
paddle.dtype = dtype
paddle.uint8 = uint8
paddle.uint16 = uint16
paddle.uint32 = uint32
paddle.uint64 = uint64
paddle.int8 = int8
paddle.short = short
paddle.int16 = int16
paddle.int = int
paddle.int32 = int32
paddle.long = long
paddle.int64 = int64
paddle.float = float
paddle.float32 = float32
paddle.float64 = float64
paddle.double = double
paddle.float16 = float16
paddle.half = half
paddle.bfloat16 = bfloat16
paddle.float8_e4m3fn = float8_e4m3fn
paddle.float8_e5m2 = float8_e5m2
paddle.complex64 = complex64
paddle.cfloat = cfloat
paddle.complex128 = complex128
paddle.cdouble = cdouble
paddle.bool = bool
paddle.pstring = pstring
paddle.raw = raw
enable_pir_api = framework.get_flags("FLAGS_enable_pir_api")[
"FLAGS_enable_pir_api"
]
if enable_pir_api:
bind_datatype()
else:
bind_vartype()
@param_one_alias(["dtype", "type"])
def iinfo(dtype: DTypeLike) -> core_iinfo:
"""
paddle.iinfo is a function that returns an object that represents the numerical properties of
an integer paddle.dtype.
This is similar to `numpy.iinfo <https://numpy.org/doc/stable/reference/generated/numpy.iinfo.html#numpy-iinfo>`_.
Args:
dtype(str|paddle.dtype|np.dtype): One of paddle.uint8, paddle.uint16, paddle.uint32, paddle.uint64,
paddle.int8, paddle.int16, paddle.int32, and paddle.int64. Alias: ``type``.
Returns:
An iinfo object, which has the following 4 attributes:
- min: int, The smallest representable integer number.
- max: int, The largest representable integer number.
- bits: int, The number of bits occupied by the type.
- dtype: str, The string name of the argument dtype.
Examples:
.. code-block:: pycon
>>> import paddle
>>> iinfo_uint8 = paddle.iinfo(paddle.uint8)
>>> print(iinfo_uint8)
paddle.iinfo(min=0, max=255, bits=8, dtype=uint8)
>>> print(iinfo_uint8.min)
0
>>> print(iinfo_uint8.max)
255
>>> print(iinfo_uint8.bits)
8
>>> print(iinfo_uint8.dtype)
uint8
"""
if isinstance(dtype, str):
if dtype.lower().strip() == "uint16":
dtype = DataType.UINT16
else:
dtype = framework.convert_to_datatype(dtype)
elif not isinstance(dtype, (DataType, VarDesc.VarType)):
np_dtype = np.dtype(dtype)
if np_dtype == np.dtype("uint16"):
dtype = DataType.UINT16
else:
dtype = framework.convert_to_datatype(np_dtype)
else:
dtype = framework.convert_to_datatype(dtype)
return core_iinfo(dtype)
@param_one_alias(["dtype", "type"])
def finfo(dtype: DTypeLike) -> core_finfo:
"""
``paddle.finfo`` is a function that returns an object that represents the numerical properties of a floating point
``paddle.dtype``.
This is similar to `numpy.finfo <https://numpy.org/doc/stable/reference/generated/numpy.finfo.html#numpy-finfo>`_.
.. note::
Alias Support: The parameter name ``type`` can be used as an alias for ``dtype``.
For example, ``type=paddle.float32`` is equivalent to ``dtype=paddle.float32``.
Args:
dtype(str|paddle.dtype|np.dtype): One of ``paddle.float16``, ``paddle.float32``, ``paddle.float64``, ``paddle.bfloat16``,
``paddle.complex64``, and ``paddle.complex128``.
type: An alias for ``dtype`` , with identical behavior.
Returns:
An ``finfo`` object, which has the following 8 attributes:
- min(double): The smallest representable number (typically `-max`).
- max(double): The largest representable number.
- eps(double): The smallest representable number such that `1.0 + eps ≠ 1.0`.
- resolution(double): The approximate decimal resolution of this type, i.e., `10**-precision`.
- smallest_normal(double): The smallest positive normal number.
- tiny(double): The smallest positive normal number. Equivalent to smallest_normal.
- bits(int): The number of bits occupied by the type.
- dtype(str): The string name of the argument dtype.
Examples:
.. code-block:: pycon
>>> import paddle
>>> finfo_float32 = paddle.finfo(paddle.float32)
>>> print(finfo_float32.min)
-3.4028234663852886e+38
>>> print(finfo_float32.max)
3.4028234663852886e+38
>>> print(finfo_float32.eps)
1.1920928955078125e-07
>>> print(finfo_float32.resolution)
1e-06
>>> print(finfo_float32.smallest_normal)
1.1754943508222875e-38
>>> print(finfo_float32.tiny)
1.1754943508222875e-38
>>> print(finfo_float32.bits)
32
>>> print(finfo_float32.dtype)
float32
"""
dtype = framework.convert_to_datatype(dtype)
return core_finfo(dtype)
+50
View File
@@ -0,0 +1,50 @@
# 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.
from ..base.core import (
finfo as core_finfo,
iinfo as core_iinfo,
)
class dtype: ...
uint8: dtype
uint16: dtype
uint32: dtype
uint64: dtype
int8: dtype
int16: dtype
int32: dtype
int64: dtype
float32: dtype
float: dtype
float64: dtype
double: dtype
float16: dtype
half: dtype
bfloat16: dtype
cfloat: dtype
complex64: dtype
cdouble: dtype
complex128: dtype
bool: dtype
float8_e4m3fn: dtype
float8_e5m2: dtype
def finfo(dtype: dtype | str) -> core_finfo: ...
def iinfo(dtype: dtype | str) -> core_iinfo: ...
+142
View File
@@ -0,0 +1,142 @@
# Copyright (c) 2020 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
from typing import TYPE_CHECKING
import numpy as np
import paddle
from paddle.base.data_feeder import convert_dtype
from paddle.base.layer_helper_base import LayerHelperBase
if TYPE_CHECKING:
from paddle._typing.dtype_like import DTypeLike, _DTypeLiteral
__all__ = []
def set_default_dtype(d: DTypeLike) -> None:
"""
Set default dtype. The default dtype is initially float32.
Args:
d(string|paddle.dtype|np.dtype): the dtype to make the default. It only
supports float16, bfloat16, float32 and float64.
Returns:
None.
Examples:
.. code-block:: pycon
>>> import paddle
>>> paddle.set_default_dtype("float32")
"""
if isinstance(d, type):
# This branch is for np.dtype
if d in [np.float16, np.float32, np.float64]:
d = d.__name__
else:
raise TypeError(
"set_default_dtype only supports [float16, float32, float64] "
f", but received {d.__name__}"
)
else:
if isinstance(d, paddle.dtype):
d = convert_dtype(d)
# NOTE(Xuxinyi04) The underlying implementation type of
# paddle.bfloat16 is 'uint16'. In order to make the implementation
# transparent to users, it is artificially converted to 'bfloat16'.
d = 'bfloat16' if d == 'uint16' else d
# This branch is for str
if d in ['float16', 'float32', 'float64', 'bfloat16']:
# NOTE(SigureMo): Since the np.dtype object is not an instance of
# type, so it will not be handled by the previous branch. We need
# to convert it to str here.
d = str(d)
else:
raise TypeError(
"set_default_dtype only supports [float16, float32, float64, bfloat16] "
f", but received {d}"
)
LayerHelperBase.set_default_dtype(d)
def set_default_tensor_type(t: DTypeLike | str, /) -> None:
"""
Set the default tensor type.
.. warning::
This API is deprecated. Please use ``paddle.set_default_dtype`` instead.
Args:
t (dtype or str): The default tensor type. It can be a dtype like
``paddle.float32`` or a string like ``"paddle.float32"`` or
``"paddle.FloatTensor"``. Only float dtypes are supported.
Returns:
None.
Examples:
.. code-block:: pycon
>>> import paddle
>>> paddle.set_default_tensor_type("paddle.FloatTensor")
>>> paddle.set_default_tensor_type(paddle.FloatTensor)
"""
if isinstance(t, type):
t = t.__name__
if isinstance(t, str):
t = t.replace('torch.', '').replace('paddle.', '').replace('cuda.', '')
dtype_map = {
"FloatTensor": "float32",
"DoubleTensor": "float64",
"HalfTensor": "float16",
"BFloat16Tensor": "bfloat16",
}
if t in dtype_map:
t = dtype_map[t]
else:
raise TypeError(
f"set_default_tensor_type only supports DtypeTensor, but received {t}"
)
else:
raise TypeError(
f"set_default_tensor_type only supports DtypeTensor or str, but received {t}"
)
set_default_dtype(t)
def get_default_dtype() -> _DTypeLiteral:
"""
Get the current default dtype. The default dtype is initially float32.
Args:
None.
Returns:
str, this global dtype only supports float16, float32, float64.
Examples:
.. code-block:: pycon
>>> import paddle
>>> paddle.get_default_dtype()
"""
return LayerHelperBase.get_default_dtype()
File diff suppressed because it is too large Load Diff
+378
View File
@@ -0,0 +1,378 @@
# 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 logging
import math
import os
import pickle
import sys
from io import BytesIO
from types import FunctionType, MethodType
import numpy as np
import paddle
from paddle.base import core, global_scope
from paddle.base.framework import Parameter, Variable, static_only
from paddle.base.log_helper import get_logger
from paddle.base.wrapped_decorator import signature_safe_contextmanager
from paddle.framework import in_pir_mode
_logger = get_logger(
__name__, logging.INFO, fmt='%(asctime)s-%(levelname)s: %(message)s'
)
# This file contains various utility functions that are used in static.io(io related api that used in static graph)
# and framework.io(io related api that used in dygraph)
class _open_buffer:
def __init__(self, buffer):
self.buffer = buffer
def __enter__(self):
return self.buffer
class _buffer_reader(_open_buffer):
def __init__(self, buffer):
super().__init__(buffer)
self.initial_tell = self.buffer.tell()
def __exit__(self, *args):
# `args[0]` is type of exception. When the `read` is abnormal, the file pointer returns to the initial position.
if args[0] is not None:
self.buffer.seek(self.initial_tell)
class _buffer_writer(_open_buffer):
def __exit__(self, *args):
self.buffer.flush()
def _is_file_path(path):
return isinstance(path, str)
def _open_file_buffer(path_or_buffer, mode):
if _is_file_path(path_or_buffer):
return open(path_or_buffer, mode)
else:
if 'w' in mode:
return _buffer_writer(path_or_buffer)
elif 'r' in mode:
return _buffer_reader(path_or_buffer)
else:
raise ValueError(f"Expected 'r' or 'w' in mode but got {mode}")
def _is_memory_buffer(buffer):
return isinstance(buffer, BytesIO)
def is_persistable(var):
"""
Check whether the given variable is persistable.
Args:
var(Variable): The variable to be checked.
Returns:
bool: True if the given `var` is persistable
False if not.
Examples:
.. code-block:: pycon
>>> # doctest: +SKIP('ValueError: var fc.b not in this block')
>>> import paddle
>>> import paddle.base as base
>>> paddle.enable_static()
>>> param = base.default_main_program().global_block().var('fc.b')
>>> res = base.io.is_persistable(param)
"""
if (
var.desc.type() == core.VarDesc.VarType.FEED_MINIBATCH
or var.desc.type() == core.VarDesc.VarType.FETCH_LIST
or var.desc.type() == core.VarDesc.VarType.READER
):
return False
return var.persistable
def is_parameter(var):
"""
Check whether the given variable is an instance of Parameter.
Args:
var(Variable): The variable to be checked.
Returns:
bool: True if the given `var` is an instance of Parameter,
False if not.
Examples:
.. code-block:: pycon
>>> # doctest: +SKIP('ValueError: var fc.w not in this block')
>>> import paddle
>>> import paddle.base as base
>>> paddle.enable_static()
>>> param = base.default_main_program().global_block().var('fc.w')
>>> res = base.io.is_parameter(param)
"""
return isinstance(var, Parameter)
def is_belong_to_optimizer(var):
if not (isinstance(var, Parameter) or var.desc.need_check_feed()):
return is_persistable(var)
return False
def _clone_var_in_block_(block, var):
assert isinstance(var, Variable)
if var.desc.type() == core.VarDesc.VarType.DENSE_TENSOR:
return block.create_var(
name=var.name,
shape=var.shape,
dtype=var.dtype,
type=var.type,
lod_level=var.lod_level,
persistable=True,
)
else:
return block.create_var(
name=var.name,
shape=var.shape,
dtype=var.dtype,
type=var.type,
persistable=True,
)
@signature_safe_contextmanager
def _load_program_scope(main=None, startup=None, scope=None):
prog = main if main else paddle.base.Program()
startup_prog = startup if startup else paddle.base.Program()
scope = scope if scope else paddle.base.core.Scope()
with (
paddle.base.scope_guard(scope),
paddle.base.program_guard(prog, startup_prog),
paddle.base.unique_name.guard(),
paddle.base.framework._dygraph_guard(None),
):
yield
@static_only
def _legacy_static_save(param_dict, model_path, protocol=2):
def get_tensor(var):
if isinstance(var, (paddle.Tensor, core.DenseTensor)):
return np.array(var)
return var
param_dict = {name: get_tensor(param_dict[name]) for name in param_dict}
# When value of dict is lager than 4GB ,there is a Bug on 'MAC python3'
if (
_is_file_path(model_path)
and sys.platform == 'darwin'
and sys.version_info.major == 3
):
pickle_bytes = pickle.dumps(param_dict, protocol=protocol)
with open(model_path, 'wb') as f:
max_bytes = 2**30
f.writelines(
pickle_bytes[i : i + max_bytes]
for i in range(0, len(pickle_bytes), max_bytes)
)
else:
with _open_file_buffer(model_path, 'wb') as f:
pickle.dump(param_dict, f, protocol=protocol)
def _reconstruct_dense_tensor_data(data):
"""Safe reconstruction function for DenseTensor data during unpickling.
This replaces the previous use of eval() in reduce_DenseTensor,
which was a security concern (CWE-502).
Args:
data: numpy array containing the tensor data.
Returns:
The data unchanged (identity function for pickle reconstruction).
"""
return data
def _pickle_loads_mac(path, f):
pickle_bytes = bytearray(0)
file_size = os.path.getsize(path)
max_bytes = 2**30
for _ in range(0, file_size, max_bytes):
pickle_bytes += f.read(max_bytes)
from .restricted_unpickler import safe_loads_pickle
load_result = safe_loads_pickle(pickle_bytes, encoding='latin1')
return load_result
def _pack_loaded_dict(load_obj):
if isinstance(load_obj, dict):
unpack_info = 'UnpackBigParamInfor@@' # typos: disable-line
if unpack_info in load_obj:
removes = []
for key, value in load_obj[unpack_info].items():
slices = [load_obj[part] for part in value["slices"]]
load_obj[key] = np.concatenate(slices).reshape(
value["OriginShape"]
)
removes += value["slices"]
for key in removes:
load_obj.pop(key)
load_obj.pop(unpack_info)
return load_obj
def _unpack_saved_dict(saved_obj, protocol):
temp_saved_obj = {}
unpack_info = {}
# When pickle protocol=2 or protocol=3 the serialized object cannot be larger than 4G.
if 1 < protocol < 4:
if isinstance(saved_obj, dict):
for key, value in saved_obj.items():
if isinstance(value, np.ndarray):
MAX_NUMBER_OF_ELEMENT = int(
(2**30 - 1) / value.dtype.itemsize
)
num_element = np.prod(value.shape)
if num_element > MAX_NUMBER_OF_ELEMENT:
unpack_info[key] = {}
unpack_info[key]["OriginShape"] = value.shape
unpack_info[key]["slices"] = []
value = value.flatten()
for i in range(
int(
math.ceil(
num_element * 1.0 / MAX_NUMBER_OF_ELEMENT
)
)
):
part_name = key + "@@." + str(i)
unpack_info[key]["slices"].append(part_name)
temp_saved_obj[part_name] = value[
i
* MAX_NUMBER_OF_ELEMENT : MAX_NUMBER_OF_ELEMENT
* (i + 1)
]
if unpack_info:
for key, value in unpack_info.items():
if key in saved_obj:
saved_obj.pop(key)
for part in value['slices']:
saved_obj[part] = temp_saved_obj[part]
saved_obj['UnpackBigParamInfor@@'] = unpack_info # typos: disable-line
return saved_obj
def set_value(var, value, scope=None):
if not (isinstance(value, np.ndarray) or hasattr(value, "__array__")):
raise TypeError(
f"`value` should be `numpy.ndarray` or `DenseTensor`, but received {type(value)}."
)
if scope is not None and not isinstance(scope, core._Scope):
raise TypeError(
f"`scope` should be None or `paddle.static.Scope` type, but received {type(scope)}."
)
if scope is None:
scope = global_scope()
var_temp = scope.find_var(var.name)
if var_temp is None:
raise ValueError(f"Can not find Variable '{var.name}' in the Scope.")
t = var_temp.get_tensor()
if hasattr(value, "shape"):
if isinstance(value.shape, (MethodType, FunctionType)):
value_shape = value.shape()
else:
value_shape = value.shape
if list(t.shape()) != list(value_shape):
raise ValueError(
f"{var.name} expected a shape {list(t.shape())}, but the received shape is {list(value_shape)}."
)
p = t._place()
if p.is_cpu_place():
place = core.CPUPlace()
elif p.is_cuda_pinned_place():
place = core.CUDAPinnedPlace()
elif p.is_xpu_place():
p = core.Place()
p.set_place(t._place())
place = core.XPUPlace(p.xpu_device_id())
elif p.is_custom_place():
p = core.Place()
p.set_place(t._place())
place = core.CustomPlace(p.custom_device_type(), p.custom_device_id())
else:
p = core.Place()
p.set_place(t._place())
place = core.CUDAPlace(p.gpu_device_id())
t.set(value, place)
def get_value(var, scope=None):
"""
Get the value of variable or value in given scope.
Args:
scope(Scope, optional) : If `scope` is None, it will be set to global scope
obtained through 'paddle.static.global_scope()'. Otherwise, use `scope`.
Default: None
Returns:
Tensor, the value in given scope.
"""
if scope is not None and not isinstance(scope, core._Scope):
raise TypeError(
f"`scope` should be None or `paddle.static.Scope` type, but received {type(scope)}."
)
if scope is None:
scope = global_scope()
var_temp = scope.find_var(var.name)
if var_temp is None:
raise ValueError(f"Can not find Variable '{var.name}' in the Scope.")
t = var_temp.get_tensor()
return t
def is_pir_fetch_var(value):
if in_pir_mode() and value.get_defining_op().name() == "pd_op.fetch":
return True
return False
+125
View File
@@ -0,0 +1,125 @@
# Copyright (c) 2021 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 ..base.framework import _apply_pass
from . import core
def get_data_vars(program):
data_vars = []
for var_name, var in program.global_block().vars.items():
if var.is_data:
data_vars.append(var_name)
return data_vars
def _update_grad_persistable(main_program):
grad_merge_attr_name = "grad_merge_cond_name"
op_role_var_attr_name = core.op_proto_and_checker_maker.kOpRoleVarAttrName()
has_grad_merge = False
has_persistable_grad_var = False
grad_vars = []
for block_id in range(main_program.num_blocks):
block = main_program.block(block_id)
for op in block.ops:
if grad_merge_attr_name in op.attr_names:
has_grad_merge = True
if op_role_var_attr_name not in op.attr_names:
continue
p_g = op.attr(op_role_var_attr_name)
for g in p_g[1::2]:
g_var = block._find_var_recursive(g)
if g_var is None:
continue
grad_vars.append(g_var)
if g_var.persistable:
has_persistable_grad_var = True
if has_grad_merge and has_persistable_grad_var:
for g_var in grad_vars:
g_var.persistable = True
def apply_build_strategy(
main_program, startup_program, build_strategy, pass_attrs
):
def update_attr(attrs, attr_types, name, value, typ=None):
if name not in attrs:
attrs[name] = value
if typ:
attr_types[name] = typ
def apply_pass(name):
attrs = dict(pass_attrs)
attr_types = {}
update_attr(attrs, attr_types, "nranks", 1, "size_t")
update_attr(attrs, attr_types, "use_cuda", False, "bool")
# TODO(zjl): how to skip fetch variables ?
update_attr(
attrs,
attr_types,
"mem_opt_skip_vars",
get_data_vars(main_program),
"list[str]",
)
_apply_pass(main_program, startup_program, name, attrs, attr_types)
_update_grad_persistable(main_program)
use_cuda = pass_attrs.get("use_cuda", False)
build_strategy = build_strategy._copy()
if build_strategy.sync_batch_norm:
apply_pass("sync_batch_norm_pass")
build_strategy.sync_batch_norm = False
if build_strategy.fuse_relu_depthwise_conv and use_cuda:
apply_pass("fuse_relu_depthwise_conv_pass")
build_strategy.fuse_relu_depthwise_conv = False
if build_strategy.fuse_resunit:
apply_pass("fuse_resunit_pass")
build_strategy.fuse_resunit = False
if build_strategy.fuse_bn_act_ops and use_cuda:
apply_pass("fuse_bn_act_pass")
build_strategy.fuse_bn_act_ops = False
if build_strategy.fuse_bn_add_act_ops and use_cuda:
apply_pass("fuse_bn_add_act_pass")
build_strategy.fuse_bn_add_act_ops = False
if build_strategy.enable_auto_fusion and use_cuda:
apply_pass("fusion_group_pass")
build_strategy.enable_auto_fusion = False
if build_strategy.fuse_gemm_epilogue:
apply_pass("fuse_gemm_epilogue_pass")
build_strategy.fuse_gemm_epilogue = False
if build_strategy.fuse_dot_product_attention:
apply_pass("fuse_dot_product_attention_pass")
build_strategy.fuse_dot_product_attention = False
if build_strategy.fuse_elewise_add_act_ops:
apply_pass("fuse_elewise_add_act_pass")
build_strategy.fuse_elewise_add_act_ops = False
if build_strategy.fuse_all_optimizer_ops:
apply_pass(
[
"coalesce_grad_tensor_pass",
"fuse_adam_op_pass",
"fuse_sgd_op_pass",
"fuse_momentum_op_pass",
]
)
build_strategy.fuse_all_optimizer_ops = False
# TODO(zjl): support fuse all reduce ops
if build_strategy.cache_runtime_context:
apply_pass("runtime_context_cache_pass")
build_strategy.cache_runtime_context = False
build_strategy._clear_finalized()
return build_strategy
+305
View File
@@ -0,0 +1,305 @@
# Copyright (c) 2020 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
from typing import TYPE_CHECKING
import paddle
from paddle.base import core
from paddle.utils.decorator_utils import param_one_alias
if TYPE_CHECKING:
from collections.abc import Sequence
__all__ = []
def seed(seed: int) -> paddle.base.core.Generator:
"""
Sets the seed for global default generator, which manages the random number generation.
Args:
seed(int): The random seed to set. It is recommend to set a large int number.
Returns:
Generator: The global default generator object.
Examples:
.. code-block:: pycon
>>> import paddle
>>> gen = paddle.seed(102)
"""
# TODO(zhiqiu): 1. remove program.random_seed when all random-related op upgrade
# 2. support gpu generator by global device
seed = int(seed)
if paddle.is_compiled_with_cuda():
for i in range(core.get_cuda_device_count()):
core.default_cuda_generator(i).manual_seed(seed)
elif paddle.is_compiled_with_xpu():
for i in range(core.get_xpu_device_count()):
core.default_xpu_generator(i).manual_seed(seed)
place = paddle.framework._current_expected_place()
if isinstance(place, paddle.CustomPlace):
dev_cnt = sum(
[
place.get_device_type() == s.split(':')[0]
for s in core.get_available_custom_device()
]
)
for i in range(dev_cnt):
core.default_custom_device_generator(
paddle.CustomPlace(place.get_device_type(), i)
).manual_seed(seed)
return core.default_cpu_generator().manual_seed(seed)
def get_rng_state(
device: str | None = None,
) -> list[core.GeneratorState]:
"""
Get all random states of random generators of specified device.
Args:
device(str): This parameter determines the specific running device.
It can be ``cpu``, ``gpu``, ``xpu``, Default is None.
If None, return the generators of current device (specified by ``set_device``).
Returns:
list[GeneratorState], object.
Examples:
.. code-block:: pycon
>>> import paddle
>>> sts = paddle.get_rng_state()
"""
state_list = []
if device is None:
place = paddle.framework._current_expected_place_()
else:
place = paddle.device._convert_to_place(device)
if isinstance(place, paddle.CPUPlace):
state_list.append(core.default_cpu_generator().get_state())
elif isinstance(place, paddle.CUDAPlace):
for i in range(core.get_cuda_device_count()):
state_list.append(core.default_cuda_generator(i).get_state())
elif isinstance(place, paddle.XPUPlace):
for i in range(core.get_xpu_device_count()):
state_list.append(core.default_xpu_generator(i).get_state())
elif isinstance(place, paddle.CustomPlace):
dev_cnt = sum(
[
place.get_device_type() == s.split(':')[0]
for s in core.get_available_custom_device()
]
)
for i in range(dev_cnt):
state_list.append(
core.default_custom_device_generator(
core.CustomPlace(place.get_device_type(), i)
).get_state()
)
else:
raise ValueError(
f"get_rng_state is not implemented for current device: {place}"
)
return state_list
def get_cuda_rng_state() -> list[paddle.base.core.GeneratorState]:
"""
Get random state of cuda generators.
Args:
None.
Returns:
GeneratorState: object.
Examples:
.. code-block:: pycon
>>> import paddle
>>> sts = paddle.get_cuda_rng_state()
"""
state_list = []
if paddle.is_compiled_with_cuda():
for i in range(core.get_cuda_device_count()):
state_list.append(core.default_cuda_generator(i).get_state())
return state_list
@param_one_alias(["state_list", "new_state"])
def set_rng_state(
state_list: Sequence[paddle.base.core.GeneratorState],
device: str | None = None,
) -> None:
"""
Sets generator state for all device generators.
Args:
state_list(list|tuple): The device states to set back to device generators. state_list is obtained from get_rng_state().
Alias: ``new_state``.
device(str): This parameter determines the specific running device.
It can be ``cpu``, ``gpu``, ``xpu``, Default is None.
If None, return the generators of current device (specified by ``set_device``).
Returns:
None.
Examples:
.. code-block:: pycon
>>> import paddle
>>> sts = paddle.get_rng_state()
>>> paddle.set_rng_state(sts)
"""
if device is None:
place = paddle.framework._current_expected_place_()
else:
place = paddle.device._convert_to_place(device)
if isinstance(place, paddle.CUDAPlace):
if not len(state_list) == core.get_cuda_device_count():
raise ValueError(
"Length of gpu state list should be equal to the gpu device count"
)
for i in range(core.get_cuda_device_count()):
core.default_cuda_generator(i).set_state(state_list[i])
elif isinstance(place, paddle.XPUPlace):
if not len(state_list) == core.get_xpu_device_count():
raise ValueError(
"Length of xpu state list should be equal to the xpu device count"
)
for i in range(core.get_xpu_device_count()):
core.default_xpu_generator(i).set_state(state_list[i])
elif isinstance(place, paddle.CustomPlace):
dev_types = core.get_all_custom_device_type()
dev_type = dev_types[0]
dev_cnt = core.get_custom_device_count(dev_type)
if not len(state_list) == dev_cnt:
raise ValueError(
f"Length of custom device state list should be equal to the {dev_cnt} device count"
)
for i in range(dev_cnt):
core.default_custom_device_generator(
paddle.CustomPlace(place.get_device_type(), i)
).set_state(state_list[i])
elif isinstance(place, core.CPUPlace):
if not len(state_list) == 1:
raise ValueError("Length of cpu state list should be equal to 1")
core.default_cpu_generator().set_state(state_list[0])
else:
raise ValueError(
f"set_rng_state is not implemented for current device: {place}"
)
def set_cuda_rng_state(
state_list: Sequence[paddle.base.core.GeneratorState],
) -> None:
"""
Sets generator state for all cuda generators.
Args:
state_list(list|tuple): The cuda states to set back to cuda generators. state_list is obtained from get_cuda_rng_state().
Returns:
None.
Examples:
.. code-block:: pycon
>>> import paddle
>>> sts = paddle.get_cuda_rng_state()
>>> paddle.set_cuda_rng_state(sts)
"""
if paddle.is_compiled_with_cuda():
if not len(state_list) == core.get_cuda_device_count():
raise ValueError(
"Length of cuda state list should be equal to the cuda device count"
)
for i in range(core.get_cuda_device_count()):
core.default_cuda_generator(i).set_state(state_list[i])
def _manual_program_seed(seed: int) -> None:
"""
Sets global seed for generating random numbers.
NOTE(zhiqiu): This is the original implementation of seed. Keeps it temporally
since CUDA generator is not developed, so we need it in the unittest.
Args:
seed(int): The random seed to set. It is recommend to set a large int number.
Returns:
None
"""
paddle.static.default_main_program().random_seed = seed
paddle.static.default_startup_program().random_seed = seed
program = paddle.static.Program()
program.global_seed(seed)
def set_random_seed_generator(name: str, seed: int) -> None:
core.set_random_seed_generator(name, seed)
def get_random_seed_generator(name: str) -> paddle.base.core.Generator:
return core.get_random_seed_generator(name)
class Generator:
def __new__(
cls, device: str | int | paddle.core.Place = None
) -> core.Generator:
"""
Generator is a random number generator.
Args:
device(str|int|paddle.core.Place): The device type to create the generator on.
It can be ``cpu``, ``gpu``, ``xpu``, or a paddle.core.Place instance.
default is None, which means using current device.
Examples:
.. code-block:: pycon
>>> import paddle
>>> g_cpu = paddle.Generator()
"""
place = paddle.device.device_to_place(device)
if isinstance(place, core.CPUPlace):
return core.default_cpu_generator()
elif isinstance(place, core.CUDAPlace):
return core.default_cuda_generator(place.gpu_device_id())
elif isinstance(place, core.XPUPlace):
return core.default_xpu_generator(place.gpu_device_id())
elif isinstance(place, core.CustomPlace):
return core.default_custom_device_generator(place)
+30
View File
@@ -0,0 +1,30 @@
# 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 paddle
AADIFF_ERROR = "PaddleRecall error(101): AAdiff"
LOSS_NAN_ERROR = "PaddleRecall error(102): LossNan"
SHARDING_PAD_NON_ZERO_ERROR = "PaddleRecall error(103): ShardingPadNonZero"
LOSS_INF_ERROR = "PaddleRecall error(104): LossInf"
def check_naninf(tensor):
if paddle.isfinite(tensor).all().item():
return None
elif paddle.isnan(tensor).any().item():
return LOSS_NAN_ERROR
else:
return LOSS_INF_ERROR
@@ -0,0 +1,249 @@
# Copyright (c) 2026 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.
"""
Restricted Unpickler for secure deserialization of model files.
This module provides a RestrictedUnpickler that only allows a whitelist
of safe classes to be deserialized, preventing arbitrary code execution
via malicious pickle payloads (CWE-502).
"""
from __future__ import annotations
import pickle
import types
from enum import Enum
# Whitelist of allowed modules and their allowed classes.
# Only these classes can be instantiated during deserialization.
_ALLOWED_CLASSES: dict[str, set[str]] = {
# NumPy types (required for model parameters)
'numpy': {
'ndarray',
'dtype',
'float32',
'float64',
'float16',
'int32',
'int64',
'int16',
'int8',
'uint8',
'bool_',
'complex64',
'complex128',
'bfloat16',
},
'numpy.core.multiarray': {
'_reconstruct',
'scalar',
},
'numpy.core.numeric': {
'*',
},
'numpy._core.multiarray': {
'_reconstruct',
'scalar',
},
'numpy._core.numeric': {
'*',
},
# Collections (required for state_dict structures)
'collections': {
'OrderedDict',
'defaultdict',
},
# Python builtins (required for basic data types in state dicts)
'builtins': {
'dict',
'list',
'tuple',
'set',
'frozenset',
'bytes',
'bytearray',
'str',
'int',
'float',
'bool',
'complex',
'slice',
'range',
'type',
},
# copyreg (used by pickle protocol for reconstructing objects)
'copyreg': {
'_reconstructor',
},
# _codecs (used for encoding in pickle)
'_codecs': {
'encode',
},
# Paddle internal: safe DenseTensor reconstruction function
'paddle.framework.io_utils': {
'_reconstruct_dense_tensor_data',
},
# Paddle internal: generator state for RNG serialization
'paddle.base.libpaddle': {
'GeneratorState',
},
# Paddle internal: distributed flex checkpoint metadata classes
# These dataclasses are serialized via paddle.save() during checkpoint
# operations and must be allowed for paddle.load() to restore them.
'paddle.distributed.flex_checkpoint.dcp.metadata': {
'Metadata',
'LocalTensorMetadata',
'LocalTensorIndex',
},
}
def _is_safe_class(cls) -> bool:
"""Check if a class is safe to deserialize.
Returns True if the class is a user-defined class without dangerous methods.
Returns False for built-in functions, modules, and classes with __reduce__.
This allows paddle.load() to safely deserialize configuration classes
(like PreTrainingArguments) that are saved via paddle.save(), while
blocking potential RCE attacks through __reduce__ exploitation.
"""
# Reject built-in functions and modules
if isinstance(
cls,
(types.BuiltinFunctionType, types.BuiltinMethodType, types.ModuleType),
):
return False
# Only allow actual classes (types)
if not isinstance(cls, type):
return False
# Check if class has __dict__ (user-defined classes do)
cls_dict = getattr(cls, '__dict__', None)
if cls_dict is None:
return False
# Check for dangerous methods that could be exploited for RCE
dangerous_methods = {
'__reduce__',
'__reduce_ex__',
'__getstate__',
'__setstate__',
}
for method in dangerous_methods:
# Check each class in the MRO for dangerous method definitions
for base in cls.__mro__:
# Skip object - its default __reduce__ is safe for user-defined classes
if base is object:
continue
# Enum-related stdlib base implementations are safe.
if base is Enum:
continue
# Check if this base class defines the dangerous method
if method in getattr(base, '__dict__', {}):
return False
return True
class RestrictedUnpickler(pickle.Unpickler):
"""A restricted unpickler that only allows whitelisted classes.
This prevents arbitrary code execution during deserialization by
blocking dangerous modules such as os, subprocess, builtins.eval,
builtins.exec, etc.
Usage:
with open('model.pdparams', 'rb') as f:
data = RestrictedUnpickler(f).load()
"""
def find_class(self, module: str, name: str) -> type:
"""Override find_class to restrict which classes can be loaded.
Args:
module: The module name containing the class.
name: The class name to load.
Returns:
The class object if it is in the whitelist or is a safe class.
Raises:
pickle.UnpicklingError: If the class is not in the whitelist
and is not a safe user-defined class.
"""
allowed_names = _ALLOWED_CLASSES.get(module)
if allowed_names is not None:
if '*' in allowed_names or name in allowed_names:
return super().find_class(module, name)
# Allow safe user-defined classes (without __reduce__)
# This supports loading configuration classes like PreTrainingArguments
try:
cls = super().find_class(module, name)
if _is_safe_class(cls):
return cls
else:
raise pickle.UnpicklingError(
f"Forbidden class: {module}.{name}. "
f"Only user-defined classes without __reduce__ are allowed."
)
except pickle.UnpicklingError:
raise
except (ImportError, AttributeError):
pass
raise pickle.UnpicklingError(
f"Forbidden class: {module}.{name}. "
f"For security, only whitelisted classes are allowed during "
f"deserialization of model files. If you believe this class "
f"should be allowed, please report an issue at "
f"https://github.com/PaddlePaddle/Paddle/issues"
)
def safe_load_pickle(f, encoding='latin1'):
"""Safely load a pickle file using RestrictedUnpickler.
Args:
f: A file-like object (opened in binary mode) to read from.
encoding: The encoding to use for unpickling (default: 'latin1').
Returns:
The deserialized Python object.
Raises:
pickle.UnpicklingError: If the pickle data contains forbidden classes.
"""
return RestrictedUnpickler(f, encoding=encoding).load()
def safe_loads_pickle(data, encoding='latin1'):
"""Safely load pickle data from bytes using RestrictedUnpickler.
Args:
data: Bytes or bytearray containing pickled data.
encoding: The encoding to use for unpickling (default: 'latin1').
Returns:
The deserialized Python object.
Raises:
pickle.UnpicklingError: If the pickle data contains forbidden classes.
"""
import io
return RestrictedUnpickler(io.BytesIO(data), encoding=encoding).load()