forked from deepmodeling/deepmd-kit
-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathcommon.py
126 lines (110 loc) · 3.28 KB
/
common.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# SPDX-License-Identifier: LGPL-3.0-or-later
from abc import (
ABC,
abstractmethod,
)
from typing import (
Any,
Optional,
)
import array_api_compat
import ml_dtypes
import numpy as np
from deepmd.common import (
VALID_PRECISION,
)
from deepmd.env import (
GLOBAL_ENER_FLOAT_PRECISION,
GLOBAL_NP_FLOAT_PRECISION,
)
PRECISION_DICT = {
"float16": np.float16,
"float32": np.float32,
"float64": np.float64,
"half": np.float16,
"single": np.float32,
"double": np.float64,
"int32": np.int32,
"int64": np.int64,
"bool": np.bool_,
"default": GLOBAL_NP_FLOAT_PRECISION,
# NumPy doesn't have bfloat16 (and doesn't plan to add)
# ml_dtypes is a solution, but it seems not supporting np.save/np.load
# hdf5 hasn't supported bfloat16 as well (see https://forum.hdfgroup.org/t/11975)
"bfloat16": ml_dtypes.bfloat16,
}
assert VALID_PRECISION.issubset(PRECISION_DICT.keys())
RESERVED_PRECISON_DICT = {
np.float16: "float16",
np.float32: "float32",
np.float64: "float64",
np.int32: "int32",
np.int64: "int64",
ml_dtypes.bfloat16: "bfloat16",
np.bool_: "bool",
}
assert set(RESERVED_PRECISON_DICT.keys()) == set(PRECISION_DICT.values())
DEFAULT_PRECISION = "float64"
def get_xp_precision(
xp: Any,
precision: str,
):
"""Get the precision from the API compatible namespace."""
if precision == "float16" or precision == "half":
return xp.float16
elif precision == "float32" or precision == "single":
return xp.float32
elif precision == "float64" or precision == "double":
return xp.float64
elif precision == "int32":
return xp.int32
elif precision == "int64":
return xp.int64
elif precision == "bool":
return bool
elif precision == "default":
return get_xp_precision(xp, RESERVED_PRECISON_DICT[PRECISION_DICT[precision]])
elif precision == "global":
return get_xp_precision(xp, RESERVED_PRECISON_DICT[GLOBAL_NP_FLOAT_PRECISION])
elif precision == "bfloat16":
return ml_dtypes.bfloat16
else:
raise ValueError(f"unsupported precision {precision} for {xp}")
class NativeOP(ABC):
"""The unit operation of a native model."""
@abstractmethod
def call(self, *args, **kwargs):
"""Forward pass in NumPy implementation."""
pass
def __call__(self, *args, **kwargs):
"""Forward pass in NumPy implementation."""
return self.call(*args, **kwargs)
def to_numpy_array(x: Any) -> Optional[np.ndarray]:
"""Convert an array to a NumPy array.
Parameters
----------
x : Any
The array to be converted.
Returns
-------
Optional[np.ndarray]
The NumPy array.
"""
if x is None:
return None
try:
# asarray is not within Array API standard, so may fail
return np.asarray(x)
except (ValueError, AttributeError):
xp = array_api_compat.array_namespace(x)
# to fix BufferError: Cannot export readonly array since signalling readonly is unsupported by DLPack.
x = xp.asarray(x, copy=True)
return np.from_dlpack(x)
__all__ = [
"GLOBAL_NP_FLOAT_PRECISION",
"GLOBAL_ENER_FLOAT_PRECISION",
"PRECISION_DICT",
"RESERVED_PRECISON_DICT",
"DEFAULT_PRECISION",
"NativeOP",
]