chore: import upstream snapshot with attribution
This commit is contained in:
Executable
+102
@@ -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__ = []
|
||||
@@ -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)
|
||||
@@ -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: ...
|
||||
@@ -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
@@ -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
|
||||
@@ -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
|
||||
@@ -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)
|
||||
@@ -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()
|
||||
Reference in New Issue
Block a user