66from types import ModuleType
77from typing import Any , Callable , ParamSpec , TypeVar
88
9- from array_api_compat import array_namespace
9+ from array_api_compat import (
10+ array_namespace ,
11+ is_cupy_namespace ,
12+ is_dask_namespace ,
13+ is_jax_namespace ,
14+ is_numpy_namespace ,
15+ is_torch_namespace ,
16+ )
1017from frozendict import frozendict
1118
1219if importlib .util .find_spec ("numba" ):
@@ -23,24 +30,35 @@ def inner(*args: Any) -> Any:
2330
2431P = ParamSpec ("P" )
2532T = TypeVar ("T" )
33+ STR_TO_IS_NAMESPACE = {
34+ "numpy" : is_numpy_namespace ,
35+ "jax" : is_jax_namespace ,
36+ "cupy" : is_cupy_namespace ,
37+ "torch" : is_torch_namespace ,
38+ "dask" : is_dask_namespace ,
39+ }
2640
2741
2842def _default_decorator (
2943 module : ModuleType ,
3044 / ,
3145) -> Callable [[Callable [P , T ]], Callable [P , T ]]:
32- if "jax" in module . __name__ :
46+ if is_jax_namespace ( module ) :
3347 import jax
3448
3549 return jax .jit
36- elif any ( x in module . __name__ for x in ( "numpy" , "cupy" ) ):
37- import numba
50+ elif is_numpy_namespace ( module ) or is_cupy_namespace ( module ):
51+ # import numba
3852
39- return numba .jit ()
40- elif "torch" in module .__name__ :
53+ # return numba.jit()
54+ # The success rate of numba.jit is low
55+ return lambda x : x
56+ elif is_torch_namespace (module ):
4157 import torch
4258
4359 return torch .compile
60+ elif is_dask_namespace (module ):
61+ return lambda x : x
4462 else :
4563 return getattr (module , "jit" , lambda x : x )
4664
@@ -79,6 +97,22 @@ def jit(
7997 Callable[[Callable[P, T]], Callable[P, T]]
8098 The JIT decorator that can be applied to a function.
8199
100+ Example
101+ -------
102+ >>> from array_api_jit import jit
103+ >>> from array_api_compat import array_namespace
104+ >>> from typing import Any
105+ >>> import numpy as np
106+ >>> @jit(
107+ ... {"numpy": numba.jit()}, # numba.jit is not used by default
108+ ... decorator_kwargs={"jax": {"static_argnames": ["n"]}}, # jax requires static_argnames
109+ ... )
110+ ... def sin_n_times(x: Any, n: int) -> Any:
111+ ... xp = array_namespace(x)
112+ ... for i in range(n):
113+ ... x = xp.sin(x)
114+ ... return x
115+
82116 """
83117
84118 def new_decorator (f : Callable [P , T ]) -> Callable [P , T ]:
@@ -88,9 +122,11 @@ def new_decorator(f: Callable[P, T]) -> Callable[P, T]:
88122
89123 @cache
90124 def jit_cached (xp : ModuleType ) -> Callable [P , T ]:
91- name = xp .__name__
92- name = name .replace ("array_api_compat." , "" )
93- name = name .split ("." )[0 ]
125+ for name_ , is_namespace in STR_TO_IS_NAMESPACE .items ():
126+ if is_namespace (xp ):
127+ name = name_
128+ else :
129+ name = xp .__name__ .split ("." )[0 ]
94130 decorator_args__ = decorator_args_ .get (name , ())
95131 decorator_kwargs__ = decorator_kwargs_ .get (name , {})
96132 if name in decorator_ :
0 commit comments