1010import numpy
1111import paddle
1212import torch
13+ import yaml
1314
1415USE_CACHED_NUMPY = os .getenv ("USE_CACHED_NUMPY" , "False" ).lower () == "true"
1516TEST_NON_CONTIGUOUS = os .getenv ("TEST_NON_CONTIGUOUS" , "0" ).lower () in ("true" , "1" )
1617USE_GPU_CACHE_MODE = os .getenv ("USE_GPU_CACHE_MODE" , "False" ).lower () == "true"
1718SKIP_GPU_CLEANUP = os .getenv ("SKIP_GPU_CLEANUP" , "False" ).lower () == "true"
1819cached_numpy = {}
1920cached_gpu_inputs = {}
21+ AUTOGRAD_DTYPES = frozenset (
22+ ["float32" , "float64" , "float16" , "complex64" , "complex128" , "bfloat16" ]
23+ )
24+ FLOAT8_DTYPES = frozenset (["float8_e5m2" , "float8_e4m3fn" ])
25+ CAST_THROUGH_INTERMEDIATE_DTYPES = frozenset (["bfloat16" ]) | FLOAT8_DTYPES
26+
27+
28+ def _load_forward_only_apis ():
29+ config_path = os .path .join (os .path .dirname (__file__ ), ".." , "base_config.yaml" )
30+ with open (config_path , encoding = "utf-8" ) as f :
31+ return frozenset (yaml .safe_load (f ).get ("forward_only_apis" , []))
32+
33+
34+ FORWARD_ONLY_APIS = _load_forward_only_apis ()
2035
2136
2237def _env_bool (name , default = False ):
@@ -240,16 +255,35 @@ def _use_gpu_cache(self, dtype=None):
240255 return False
241256 return True
242257
258+ def _supports_autograd (self , dtype = None ):
259+ dtype = dtype or self .dtype
260+ return dtype in AUTOGRAD_DTYPES
261+
262+ def _requires_autograd (self , api_config , dtype = None ):
263+ if not self ._supports_autograd (dtype ):
264+ return False
265+ api_name = getattr (api_config , "api_name" , "" )
266+ api = api_name [api_name .rindex ("." ) + 1 :] if "." in api_name else api_name
267+ if api in FORWARD_ONLY_APIS :
268+ return False
269+ return getattr (api_config , "test_backward" , True )
270+
243271 def _gpu_cache_key (self , api_config , dtype = None ):
244272 dtype = dtype or self .dtype
245273 location = (
246274 getattr (self , "index" , None ),
247275 getattr (self , "key" , None ),
248276 tuple (getattr (self , "list_index" , [])),
249277 )
250- return (api_config .config , location , dtype , _shape_tuple (self .shape ))
278+ return (
279+ api_config .config ,
280+ location ,
281+ dtype ,
282+ _shape_tuple (self .shape ),
283+ self ._requires_autograd (api_config , dtype ),
284+ )
251285
252- def _make_gpu_cache_tensors (self , dtype = None ):
286+ def _make_gpu_cache_tensors (self , api_config , dtype = None ):
253287 dtype = dtype or self .dtype
254288 torch_dtype = self .convert_dtype_to_torch_type (dtype )
255289 shape = tuple (self .shape )
@@ -271,21 +305,22 @@ def _make_gpu_cache_tensors(self, dtype=None):
271305 base = (torch .rand (shape , device = device , dtype = torch .float32 ) - 0.5 ) * 1.2
272306 torch_tensor = base .to (dtype = torch_dtype )
273307
308+ requires_autograd = self ._requires_autograd (api_config , dtype )
274309 torch_source = torch_tensor .detach ()
275310 paddle_tensor = paddle .utils .dlpack .from_dlpack (
276311 torch .utils .dlpack .to_dlpack (torch_source .clone ())
277312 )
278- paddle_tensor .stop_gradient = False
313+ paddle_tensor .stop_gradient = not requires_autograd
279314 torch_tensor = torch_source .clone ()
280- if dtype in [ "float32" , "float64" , "float16" , "complex64" , "complex128" , "bfloat16" ] :
281- torch_tensor = torch_tensor .requires_grad_ (True )
315+ if requires_autograd :
316+ torch_tensor = torch_tensor .detach (). requires_grad_ (True )
282317 return paddle_tensor , torch_tensor
283318
284319 def _get_gpu_cache_entry (self , api_config , dtype = None ):
285320 dtype = dtype or self .dtype
286321 key = self ._gpu_cache_key (api_config , dtype )
287322 if key not in cached_gpu_inputs :
288- paddle_tensor , torch_tensor = self ._make_gpu_cache_tensors (dtype )
323+ paddle_tensor , torch_tensor = self ._make_gpu_cache_tensors (api_config , dtype )
289324 cached_gpu_inputs [key ] = {
290325 "paddle" : paddle_tensor ,
291326 "torch" : torch_tensor ,
@@ -3019,24 +3054,23 @@ def get_paddle_tensor(self, api_config):
30193054 f"is_contiguous: { self .paddle_tensor .is_contiguous ()} "
30203055 )
30213056 else :
3057+ requires_autograd = self ._requires_autograd (api_config )
30223058 intermediate_dtype = (
30233059 "float32"
30243060 if self .dtype == "bfloat16"
3025- else (
3026- "float16" if self .dtype in ["float8_e5m2" , "float8_e4m3fn" ] else self .dtype
3027- )
3061+ else ("float16" if self .dtype in FLOAT8_DTYPES else self .dtype )
30283062 )
30293063 self .paddle_tensor = paddle .to_tensor (
30303064 self .get_numpy_tensor (api_config ),
30313065 dtype = intermediate_dtype ,
30323066 place = self .place ,
30333067 )
30343068
3035- self .paddle_tensor .stop_gradient = False
30363069 if self .dtype == "bfloat16" :
30373070 self .paddle_tensor = paddle .cast (self .paddle_tensor , dtype = "bfloat16" )
3038- elif self .dtype in [ "float8_e5m2" , "float8_e4m3fn" ] :
3071+ elif self .dtype in FLOAT8_DTYPES :
30393072 self .paddle_tensor = paddle .cast (self .paddle_tensor , dtype = self .dtype )
3073+ self .paddle_tensor .stop_gradient = not requires_autograd
30403074 if TEST_NON_CONTIGUOUS :
30413075 if not self .shuffle_dims :
30423076 ndim = self .paddle_tensor .dim ()
@@ -3059,9 +3093,7 @@ def _create_strided_paddle_tensor(self, api_config):
30593093 original_flag = paddle .get_flags ([flag_name ])
30603094 paddle .set_flags ({flag_name : False })
30613095 try :
3062- intermediate_dtype = (
3063- "float16" if self .dtype in ["float8_e5m2" , "float8_e4m3fn" ] else self .dtype
3064- )
3096+ intermediate_dtype = "float16" if self .dtype in FLOAT8_DTYPES else self .dtype
30653097 storage_size = self ._strided_storage_size ()
30663098 flat_tensor = paddle .zeros (
30673099 [storage_size ],
@@ -3076,11 +3108,11 @@ def _create_strided_paddle_tensor(self, api_config):
30763108 dtype = intermediate_dtype ,
30773109 place = self .place ,
30783110 )
3079- if self .dtype in [ "float8_e5m2" , "float8_e4m3fn" ] :
3111+ if self .dtype in FLOAT8_DTYPES :
30803112 flat_tensor = paddle .cast (flat_tensor , dtype = self .dtype )
30813113 tensor = paddle .as_strided (flat_tensor , self .shape , self .strides )
30823114
3083- tensor .stop_gradient = False
3115+ tensor .stop_gradient = not self . _requires_autograd ( api_config )
30843116 return tensor
30853117 finally :
30863118 paddle .set_flags (original_flag )
@@ -3094,32 +3126,25 @@ def get_torch_tensor(self, api_config):
30943126 if not self .is_contiguous and self .strides is not None :
30953127 self .torch_tensor = self ._create_strided_torch_tensor (api_config )
30963128 else :
3097- needs_intermediate = self .dtype in [ "bfloat16" , "float8_e5m2" , "float8_e4m3fn" ]
3098- if needs_intermediate :
3129+ needs_cast = self .dtype in CAST_THROUGH_INTERMEDIATE_DTYPES
3130+ if needs_cast :
30993131 intermediate_torch_dtype = (
31003132 torch .float32 if self .dtype == "bfloat16" else torch .float16
31013133 )
31023134 else :
31033135 intermediate_torch_dtype = self .convert_dtype_to_torch_type (self .dtype )
3136+ requires_grad = self ._requires_autograd (api_config )
31043137 self .torch_tensor = torch .tensor (
31053138 self .get_numpy_tensor (api_config ),
31063139 dtype = intermediate_torch_dtype ,
3107- requires_grad = self .dtype
3108- in [
3109- "float32" ,
3110- "float64" ,
3111- "float16" ,
3112- "complex64" ,
3113- "complex128" ,
3114- "bfloat16" ,
3115- ],
3140+ requires_grad = requires_grad and not needs_cast ,
31163141 )
3117- if self .dtype == "bfloat16" :
3118- self .torch_tensor = self .torch_tensor .to (dtype = torch .bfloat16 )
3119- elif self .dtype in ["float8_e5m2" , "float8_e4m3fn" ]:
3142+ if needs_cast :
31203143 self .torch_tensor = self .torch_tensor .to (
31213144 dtype = self .convert_dtype_to_torch_type (self .dtype )
31223145 )
3146+ if requires_grad :
3147+ self .torch_tensor = self .torch_tensor .detach ().requires_grad_ (True )
31233148 if TEST_NON_CONTIGUOUS :
31243149 if not self .shuffle_dims :
31253150 ndim = self .torch_tensor .dim ()
@@ -3132,7 +3157,7 @@ def get_torch_tensor(self, api_config):
31323157 def _create_strided_torch_tensor (self , api_config ):
31333158 """Create a non-contiguous torch tensor from the shared logical numpy input."""
31343159 device = torch .device ("cuda:0" ) if torch .cuda .is_available () else torch .device ("cpu" )
3135- needs_intermediate = self .dtype in [ "float8_e5m2" , "float8_e4m3fn" ]
3160+ needs_intermediate = self .dtype in FLOAT8_DTYPES
31363161 if needs_intermediate :
31373162 intermediate_torch_dtype = torch .float16
31383163 else :
@@ -3153,19 +3178,11 @@ def _create_strided_torch_tensor(self, api_config):
31533178 device = device ,
31543179 )
31553180 )
3156- if self .dtype in [ "float8_e5m2" , "float8_e4m3fn" ] :
3181+ if self .dtype in FLOAT8_DTYPES :
31573182 flat_tensor = flat_tensor .to (dtype = self .convert_dtype_to_torch_type (self .dtype ))
31583183 tensor = torch .as_strided (flat_tensor , self .shape , self .strides )
31593184
3160- requires_grad = self .dtype in [
3161- "float32" ,
3162- "float64" ,
3163- "float16" ,
3164- "complex64" ,
3165- "complex128" ,
3166- "bfloat16" ,
3167- ]
3168- if requires_grad :
3185+ if self ._requires_autograd (api_config ):
31693186 tensor = tensor .detach ().requires_grad_ (True )
31703187 return tensor
31713188
0 commit comments