array-api-jit 0.0.0__py3-none-any.whl → 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- array_api_jit/__init__.py +4 -1
- array_api_jit/_main.py +178 -0
- {array_api_jit-0.0.0.dist-info → array_api_jit-0.1.0.dist-info}/METADATA +48 -4
- array_api_jit-0.1.0.dist-info/RECORD +8 -0
- array_api_jit/main.py +0 -3
- array_api_jit-0.0.0.dist-info/RECORD +0 -8
- {array_api_jit-0.0.0.dist-info → array_api_jit-0.1.0.dist-info}/WHEEL +0 -0
- {array_api_jit-0.0.0.dist-info → array_api_jit-0.1.0.dist-info}/licenses/LICENSE +0 -0
- {array_api_jit-0.0.0.dist-info → array_api_jit-0.1.0.dist-info}/top_level.txt +0 -0
array_api_jit/__init__.py
CHANGED
array_api_jit/_main.py
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
# https://github.com/search?q=gumerov+translation+language%3APython&type=code&l=Python
|
|
2
|
+
import importlib.util
|
|
3
|
+
import warnings
|
|
4
|
+
from collections.abc import Callable, Mapping, Sequence
|
|
5
|
+
from functools import cache, wraps
|
|
6
|
+
from types import ModuleType
|
|
7
|
+
from typing import Any, ParamSpec, TypeVar
|
|
8
|
+
|
|
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
|
+
)
|
|
17
|
+
from frozendict import frozendict
|
|
18
|
+
|
|
19
|
+
if importlib.util.find_spec("numba"):
|
|
20
|
+
import numpy as np
|
|
21
|
+
from numba.extending import overload
|
|
22
|
+
|
|
23
|
+
@overload(array_namespace)
|
|
24
|
+
def _array_namespace_overload(*args: Any) -> Any:
|
|
25
|
+
def inner(*args: Any) -> Any:
|
|
26
|
+
return np
|
|
27
|
+
|
|
28
|
+
return inner
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
P = ParamSpec("P")
|
|
32
|
+
T = TypeVar("T")
|
|
33
|
+
Pin = ParamSpec("Pin")
|
|
34
|
+
Tin = TypeVar("Tin")
|
|
35
|
+
Pinner = ParamSpec("Pinner")
|
|
36
|
+
Tinner = TypeVar("Tinner")
|
|
37
|
+
STR_TO_IS_NAMESPACE = {
|
|
38
|
+
"numpy": is_numpy_namespace,
|
|
39
|
+
"jax": is_jax_namespace,
|
|
40
|
+
"cupy": is_cupy_namespace,
|
|
41
|
+
"torch": is_torch_namespace,
|
|
42
|
+
"dask": is_dask_namespace,
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _default_decorator(
|
|
47
|
+
module: ModuleType,
|
|
48
|
+
/,
|
|
49
|
+
) -> Callable[[Callable[P, T]], Callable[P, T]]:
|
|
50
|
+
if is_jax_namespace(module):
|
|
51
|
+
import jax
|
|
52
|
+
|
|
53
|
+
return jax.jit
|
|
54
|
+
elif is_numpy_namespace(module) or is_cupy_namespace(module):
|
|
55
|
+
# import numba
|
|
56
|
+
|
|
57
|
+
# return numba.jit()
|
|
58
|
+
# The success rate of numba.jit is low
|
|
59
|
+
return lambda x: x
|
|
60
|
+
elif is_torch_namespace(module):
|
|
61
|
+
import torch
|
|
62
|
+
|
|
63
|
+
return torch.compile
|
|
64
|
+
elif is_dask_namespace(module):
|
|
65
|
+
return lambda x: x
|
|
66
|
+
else:
|
|
67
|
+
return getattr(module, "jit", lambda x: x)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
Decorator = Callable[[Callable[Pin, Tin]], Callable[Pin, Tin]]
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def jit(
|
|
74
|
+
decorator: Mapping[str, Decorator[..., Any]] | None = None,
|
|
75
|
+
/,
|
|
76
|
+
*,
|
|
77
|
+
fail_on_error: bool = False,
|
|
78
|
+
rerun_on_error: bool = False,
|
|
79
|
+
decorator_args: Mapping[str, Sequence[Any]] | None = None,
|
|
80
|
+
decorator_kwargs: Mapping[str, Mapping[str, Any]] | None = None,
|
|
81
|
+
) -> Callable[[Callable[P, T]], Callable[P, T]]:
|
|
82
|
+
"""
|
|
83
|
+
Just-in-time compilation decorator with multiple backends.
|
|
84
|
+
|
|
85
|
+
Parameters
|
|
86
|
+
----------
|
|
87
|
+
decorator : Mapping[str, Callable[[Callable[P, T]], Callable[P, T]]] | None, optional
|
|
88
|
+
The JIT decorator to use for each array namespace, by default None
|
|
89
|
+
fail_on_error : bool, optional
|
|
90
|
+
If True, raise an error if the JIT decorator fails to apply.
|
|
91
|
+
If False, just warn and return the original function, by default False
|
|
92
|
+
rerun_on_error : bool, optional
|
|
93
|
+
If True, rerun the function without JIT if the function
|
|
94
|
+
with JIT applied fails, by default False
|
|
95
|
+
decorator_args : Mapping[str, Sequence[Any]] | None, optional
|
|
96
|
+
Additional positional arguments to be passed along with the function
|
|
97
|
+
to the decorator for each array namespace, by default None
|
|
98
|
+
decorator_kwargs : Mapping[str, Mapping[str, Any]] | None, optional
|
|
99
|
+
Additional keyword arguments to be passed along with the function
|
|
100
|
+
to the decorator for each array namespace, by default None
|
|
101
|
+
|
|
102
|
+
Returns
|
|
103
|
+
-------
|
|
104
|
+
Callable[[Callable[P, T]], Callable[P, T]]
|
|
105
|
+
The JIT decorator that can be applied to a function.
|
|
106
|
+
|
|
107
|
+
Example
|
|
108
|
+
-------
|
|
109
|
+
>>> from array_api_jit import jit
|
|
110
|
+
>>> from array_api_compat import array_namespace
|
|
111
|
+
>>> from typing import Any
|
|
112
|
+
>>> import numba
|
|
113
|
+
>>> @jit(
|
|
114
|
+
... {"numpy": numba.jit()}, # numba.jit is not used by default
|
|
115
|
+
... decorator_kwargs={"jax": {"static_argnames": ["n"]}}, # jax requires static_argnames
|
|
116
|
+
... )
|
|
117
|
+
... def sin_n_times(x: Any, n: int) -> Any:
|
|
118
|
+
... xp = array_namespace(x)
|
|
119
|
+
... for i in range(n):
|
|
120
|
+
... x = xp.sin(x)
|
|
121
|
+
... return x
|
|
122
|
+
|
|
123
|
+
"""
|
|
124
|
+
|
|
125
|
+
def new_decorator(f: Callable[Pinner, Tinner]) -> Callable[Pinner, Tinner]:
|
|
126
|
+
decorator_args_ = frozendict(decorator_args or {})
|
|
127
|
+
decorator_kwargs_ = frozendict(decorator_kwargs or {})
|
|
128
|
+
decorator_ = decorator or {}
|
|
129
|
+
|
|
130
|
+
@cache
|
|
131
|
+
def jit_cached(xp: ModuleType) -> Callable[Pinner, Tinner]:
|
|
132
|
+
for name_, is_namespace in STR_TO_IS_NAMESPACE.items():
|
|
133
|
+
if is_namespace(xp):
|
|
134
|
+
name = name_
|
|
135
|
+
else:
|
|
136
|
+
name = xp.__name__.split(".")[0]
|
|
137
|
+
decorator_args__ = decorator_args_.get(name, ())
|
|
138
|
+
decorator_kwargs__ = decorator_kwargs_.get(name, {})
|
|
139
|
+
if name in decorator_:
|
|
140
|
+
decorator_current = decorator_[name]
|
|
141
|
+
else:
|
|
142
|
+
decorator_current = _default_decorator(xp)
|
|
143
|
+
try:
|
|
144
|
+
return decorator_current(f, *decorator_args__, **decorator_kwargs__)
|
|
145
|
+
except Exception as e:
|
|
146
|
+
if fail_on_error:
|
|
147
|
+
raise RuntimeError(f"Failed to apply JIT decorator for {name}") from e
|
|
148
|
+
warnings.warn(
|
|
149
|
+
f"Failed to apply JIT decorator for {name}: {e}",
|
|
150
|
+
RuntimeWarning,
|
|
151
|
+
stacklevel=2,
|
|
152
|
+
)
|
|
153
|
+
return f
|
|
154
|
+
|
|
155
|
+
@wraps(f)
|
|
156
|
+
def inner(*args_inner: Pinner.args, **kwargs_inner: Pinner.kwargs) -> Tinner:
|
|
157
|
+
try:
|
|
158
|
+
xp = array_namespace(*args_inner)
|
|
159
|
+
except TypeError as e:
|
|
160
|
+
if e.args[0] == "Unrecognized array input":
|
|
161
|
+
return f(*args_inner, **kwargs_inner)
|
|
162
|
+
raise
|
|
163
|
+
f_jit = jit_cached(xp)
|
|
164
|
+
try:
|
|
165
|
+
return f_jit(*args_inner, **kwargs_inner)
|
|
166
|
+
except Exception as e:
|
|
167
|
+
if rerun_on_error:
|
|
168
|
+
warnings.warn(
|
|
169
|
+
f"JIT failed for {xp.__name__}: {e}. Rerunning without JIT.",
|
|
170
|
+
RuntimeWarning,
|
|
171
|
+
stacklevel=2,
|
|
172
|
+
)
|
|
173
|
+
return f(*args_inner, **kwargs_inner)
|
|
174
|
+
raise RuntimeError(f"Failed to run JIT function for {xp.__name__}") from e
|
|
175
|
+
|
|
176
|
+
return inner
|
|
177
|
+
|
|
178
|
+
return new_decorator
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: array-api-jit
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.1.0
|
|
4
4
|
Summary: JIT decorator supporting multiple array API compatible libraries
|
|
5
5
|
Author-email: 34j <34j.95a2p@simplelogin.com>
|
|
6
6
|
License: MIT
|
|
@@ -12,15 +12,17 @@ Classifier: Development Status :: 2 - Pre-Alpha
|
|
|
12
12
|
Classifier: Intended Audience :: Developers
|
|
13
13
|
Classifier: Natural Language :: English
|
|
14
14
|
Classifier: Operating System :: OS Independent
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
16
15
|
Classifier: Programming Language :: Python :: 3.10
|
|
17
16
|
Classifier: Programming Language :: Python :: 3.11
|
|
18
17
|
Classifier: Programming Language :: Python :: 3.12
|
|
19
18
|
Classifier: Programming Language :: Python :: 3.13
|
|
20
19
|
Classifier: Topic :: Software Development :: Libraries
|
|
21
|
-
Requires-Python: >=3.
|
|
20
|
+
Requires-Python: >=3.10
|
|
22
21
|
Description-Content-Type: text/markdown
|
|
23
22
|
License-File: LICENSE
|
|
23
|
+
Requires-Dist: array-api-compat>=1.11.2
|
|
24
|
+
Requires-Dist: cm-time>=0.1.2
|
|
25
|
+
Requires-Dist: frozendict>=2.4.6
|
|
24
26
|
Dynamic: license-file
|
|
25
27
|
|
|
26
28
|
# array API JIT
|
|
@@ -69,7 +71,49 @@ JIT decorator supporting multiple array API compatible libraries
|
|
|
69
71
|
|
|
70
72
|
Install this via pip (or your favourite package manager):
|
|
71
73
|
|
|
72
|
-
|
|
74
|
+
```shell
|
|
75
|
+
pip install array-api-jit
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Usage
|
|
79
|
+
|
|
80
|
+
Simply decorate your function with `@jit()`:
|
|
81
|
+
|
|
82
|
+
```python
|
|
83
|
+
from array_api_jit import jit
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
@jit()
|
|
87
|
+
def my_function(x: Any) -> Any:
|
|
88
|
+
xp = array_namespace(x)
|
|
89
|
+
return xp.sin(x) + xp.cos(x)
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Advanced Usage
|
|
93
|
+
|
|
94
|
+
You can specify the decorator, arguments, and keyword arguments for each library.
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
from array_api_jit import jit
|
|
98
|
+
from array_api_compat import array_namespace
|
|
99
|
+
from typing import Any
|
|
100
|
+
import numba
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
@jit(
|
|
104
|
+
{"numpy": numba.jit()}, # numba.jit is not used by default because it may not succeed
|
|
105
|
+
decorator_kwargs={
|
|
106
|
+
"jax": {"static_argnames": ["n"]}
|
|
107
|
+
}, # jax requires for-loop variable to be "static_argnames"
|
|
108
|
+
# fail_on_error: bool = False, # do not raise an error if the decorator fails (Default)
|
|
109
|
+
# rerun_on_error: bool = True, # re-run the original function if the wrapped function fails (NOT Default)
|
|
110
|
+
)
|
|
111
|
+
def sin_n_times(x: Any, n: int) -> Any:
|
|
112
|
+
xp = array_namespace(x)
|
|
113
|
+
for i in range(n):
|
|
114
|
+
x = xp.sin(x)
|
|
115
|
+
return x
|
|
116
|
+
```
|
|
73
117
|
|
|
74
118
|
## Contributors ✨
|
|
75
119
|
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
array_api_jit/__init__.py,sha256=ex_A2mp0ZTg3y3hvbNxj9s75gW1FL1eLhbd7JPUa-ic,64
|
|
2
|
+
array_api_jit/_main.py,sha256=m_pgnGiMGtHT6eFKTTIGFV2tl7fLwWeyvEQPpIyVSeo,6007
|
|
3
|
+
array_api_jit/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
+
array_api_jit-0.1.0.dist-info/licenses/LICENSE,sha256=Otwb96xcK4QBqXXVdBKpLZVnc4mJuFTa8rsMUEpphMM,1061
|
|
5
|
+
array_api_jit-0.1.0.dist-info/METADATA,sha256=spw7X8EcB6K6YYxTHVyNo4qLd9jd7O_icFRw91BaFrM,5237
|
|
6
|
+
array_api_jit-0.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
7
|
+
array_api_jit-0.1.0.dist-info/top_level.txt,sha256=90tmkew6kqpBt5VZbfvK2cvsOfCn_oFZfDf74F-s7Hg,14
|
|
8
|
+
array_api_jit-0.1.0.dist-info/RECORD,,
|
array_api_jit/main.py
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
array_api_jit/__init__.py,sha256=ShXQBVjyiSOHxoQJS2BvNG395W4KZfqMxZWBAR0MZrE,22
|
|
2
|
-
array_api_jit/main.py,sha256=j2h8YoaIyvMAosyxXlV3rlWEQ7x1yvnZWhdjVG4vXdU,82
|
|
3
|
-
array_api_jit/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
-
array_api_jit-0.0.0.dist-info/licenses/LICENSE,sha256=Otwb96xcK4QBqXXVdBKpLZVnc4mJuFTa8rsMUEpphMM,1061
|
|
5
|
-
array_api_jit-0.0.0.dist-info/METADATA,sha256=45CZdjO99TuZj8qkFY43C6yCaE23YMd9-iW7IKL2Uhw,4182
|
|
6
|
-
array_api_jit-0.0.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
7
|
-
array_api_jit-0.0.0.dist-info/top_level.txt,sha256=90tmkew6kqpBt5VZbfvK2cvsOfCn_oFZfDf74F-s7Hg,14
|
|
8
|
-
array_api_jit-0.0.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|