1111 Version ,
1212)
1313
14+ from deepmd .dpmodel .common import (
15+ to_numpy_array ,
16+ )
17+
1418# Type alias for array_api compatible arrays
1519Array = np .ndarray | Any # Any to support JAX, PyTorch, etc. arrays
1620
@@ -27,22 +31,28 @@ def xp_asarray_nodetach(
2731 ``torch.asarray`` detaches its input from the autograd graph, so calling
2832 ``xp.asarray`` on a weight attribute that is already a backend tensor
2933 (e.g. a ``torch.nn.Parameter`` registered by the pt_expt backend)
30- silently breaks gradient flow to that weight. This helper converts
31- genuine non-backend data (numpy arrays, python scalars/lists) via
32- ``xp.asarray``; backend tensors are returned as-is, with an optional
33- differentiable dtype cast via ``xp.astype``.
34-
35- The ``device`` argument only applies to the conversion path: backend
36- tensors are assumed to already live on the working device (they are
37- created together with the inputs).
34+ silently breaks gradient flow to that weight. Backend tensors already in
35+ ``xp`` are therefore returned as-is, with an optional differentiable dtype
36+ cast via ``xp.astype``.
37+
38+ An array from another namespace cannot retain its autograd graph. It is
39+ converted through NumPy before entering ``xp``; this also performs the
40+ required device-to-host copy when a CUDA-backed model constant is consumed
41+ by a NumPy statistics path.
42+
43+ The ``device`` argument only applies to the conversion path. Arrays already
44+ in ``xp`` are assumed to live on the working device because model buffers
45+ and inputs are moved together.
3846 """
39- if isinstance (obj , np .ndarray ) or not array_api_compat .is_array_api_obj (obj ):
40- if dtype is None :
41- return xp .asarray (obj , device = device )
42- return xp .asarray (obj , dtype = dtype , device = device )
43- if dtype is not None and obj .dtype != dtype :
44- obj = xp .astype (obj , dtype )
45- return obj
47+ if array_api_compat .is_array_api_obj (obj ):
48+ if array_api_compat .array_namespace (obj ) is xp :
49+ if dtype is not None and obj .dtype != dtype :
50+ obj = xp .astype (obj , dtype )
51+ return obj
52+ obj = to_numpy_array (obj )
53+ if dtype is None :
54+ return xp .asarray (obj , device = device )
55+ return xp .asarray (obj , dtype = dtype , device = device )
4656
4757
4858# array api adds take_along_axis in https://github.com/data-apis/array-api/pull/816
0 commit comments