numbox 0.1.1__py3-none-any.whl → 0.1.3__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.
Potentially problematic release.
This version of numbox might be problematic. Click here for more details.
- numbox/__init__.py +1 -1
- numbox/core/any_type.py +4 -18
- numbox/core/declare_func.py +2270 -0
- numbox/core/proxy.py +87 -0
- {numbox-0.1.1.dist-info → numbox-0.1.3.dist-info}/METADATA +13 -2
- numbox-0.1.3.dist-info/RECORD +14 -0
- numbox-0.1.1.dist-info/RECORD +0 -12
- {numbox-0.1.1.dist-info → numbox-0.1.3.dist-info}/LICENSE +0 -0
- {numbox-0.1.1.dist-info → numbox-0.1.3.dist-info}/WHEEL +0 -0
- {numbox-0.1.1.dist-info → numbox-0.1.3.dist-info}/top_level.txt +0 -0
numbox/core/proxy.py
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import inspect
|
|
2
|
+
from llvmlite import ir # noqa: F401
|
|
3
|
+
from numba import njit
|
|
4
|
+
from numba.core import cgutils # noqa: F401
|
|
5
|
+
from numba.core.typing.templates import Signature
|
|
6
|
+
from numba.extending import intrinsic # noqa: F401
|
|
7
|
+
from types import FunctionType as PyFunctionType
|
|
8
|
+
from typing import List, Optional, Tuple
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def make_proxy_name(name):
|
|
12
|
+
return f'__{name}'
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def make_params_strings(func):
|
|
16
|
+
func_params = inspect.signature(func).parameters
|
|
17
|
+
func_params_str = ', '.join(
|
|
18
|
+
[k if v.default == inspect._empty else f'{k}={v.default}' for k, v in func_params.items()]
|
|
19
|
+
)
|
|
20
|
+
func_names_params_str = ', '.join(func_params.keys())
|
|
21
|
+
return func_params_str, func_names_params_str
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def proxy(sig, jit_options: Optional[dict] = None):
|
|
25
|
+
""" Create a proxy for the decorated function `func` with the given signature(s) `sig`.
|
|
26
|
+
|
|
27
|
+
The original function `func` will be eagerly JIT-compiled with the given signature(s).
|
|
28
|
+
A proxy with the name `func_proxy_name` will be created to call `func` in the LLVM scope.
|
|
29
|
+
The original function's variable will be bound to the proxy, i.e., calling the decorated
|
|
30
|
+
function will call the proxy.
|
|
31
|
+
|
|
32
|
+
The proxy is a JIT-compiled wrap that invokes the intrinsic that *declares* the `func`
|
|
33
|
+
and calls it with the original arguments. Declaration instructions are relatively cheap
|
|
34
|
+
to statically link into (potential) caller's LLVM code, which is the main motivation behind
|
|
35
|
+
this decorator.
|
|
36
|
+
|
|
37
|
+
Machine code for `func` can be cached when so specified in `jit_options`, in which case its
|
|
38
|
+
JIT-compilation will load the `func` into the LLVM scope. Caching option is the other major
|
|
39
|
+
motivation for this decorator, without the need to cache one can avoid static linking
|
|
40
|
+
of the callee's LLVM code into the caller's by simply ignoring the former.
|
|
41
|
+
|
|
42
|
+
In case when more than one signature is provided as the `sig` parameter, it is assumed
|
|
43
|
+
that the first signature is the 'main' one while the other ones are supplied to
|
|
44
|
+
allow for the `Omitted` types with default values for (some of) the parameters.
|
|
45
|
+
|
|
46
|
+
See tests for some examples of the use cases.
|
|
47
|
+
"""
|
|
48
|
+
main_sig = isinstance(sig, Signature) and sig or isinstance(sig, (List, Tuple)) and sig[0]
|
|
49
|
+
jit_options = isinstance(jit_options, dict) and jit_options or {}
|
|
50
|
+
jit_opts = jit_options.copy()
|
|
51
|
+
jit_opts.update(jit_opts, inline='always')
|
|
52
|
+
|
|
53
|
+
def wrap(func):
|
|
54
|
+
assert isinstance(func, PyFunctionType)
|
|
55
|
+
func_jit = njit(sig, **jit_options)(func)
|
|
56
|
+
llvm_cfunc_wrapper_name = func_jit.get_compile_result(main_sig).fndesc.llvm_cfunc_wrapper_name
|
|
57
|
+
func_args_str, func_names_args_str = make_params_strings(func)
|
|
58
|
+
func_proxy_name = make_proxy_name(func.__name__)
|
|
59
|
+
code_txt = f"""
|
|
60
|
+
@intrinsic
|
|
61
|
+
def _{func_proxy_name}(typingctx, {func_names_args_str}):
|
|
62
|
+
def codegen(context, builder, signature, args):
|
|
63
|
+
func_ty_ll = ir.FunctionType(
|
|
64
|
+
context.get_data_type(main_sig.return_type),
|
|
65
|
+
[context.get_data_type(arg) for arg in main_sig.args]
|
|
66
|
+
)
|
|
67
|
+
f = cgutils.get_or_insert_function(builder.module, func_ty_ll, "{llvm_cfunc_wrapper_name}")
|
|
68
|
+
return builder.call(f, args)
|
|
69
|
+
return main_sig, codegen
|
|
70
|
+
|
|
71
|
+
@njit(sig, **jit_opts)
|
|
72
|
+
def {func_proxy_name}({func_args_str}):
|
|
73
|
+
return _{func_proxy_name}({func_names_args_str})
|
|
74
|
+
"""
|
|
75
|
+
ns = {
|
|
76
|
+
**inspect.getmodule(func).__dict__,
|
|
77
|
+
**{
|
|
78
|
+
'cgutils': cgutils, 'intrinsic': intrinsic, 'ir': ir, 'jit_opts': jit_opts, 'njit': njit,
|
|
79
|
+
'sig': sig, 'main_sig': main_sig
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
if ns.get(func_proxy_name) is not None:
|
|
83
|
+
raise ValueError(f"Name {func_proxy_name} in module {inspect.getmodule(func)} is reserved")
|
|
84
|
+
code = compile(code_txt, inspect.getfile(func), mode='exec')
|
|
85
|
+
exec(code, ns)
|
|
86
|
+
return ns[func_proxy_name]
|
|
87
|
+
return wrap
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: numbox
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.3
|
|
4
4
|
Author: Mikhail Goykhman
|
|
5
5
|
License: MIT License (with Citation Clause)
|
|
6
6
|
|
|
@@ -36,4 +36,15 @@ Description-Content-Type: text/markdown
|
|
|
36
36
|
License-File: LICENSE
|
|
37
37
|
|
|
38
38
|
# numbox
|
|
39
|
-
|
|
39
|
+
|
|
40
|
+
A toolbox of low-level utilities for working with [numba](https://numba.pydata.org/).
|
|
41
|
+
|
|
42
|
+
## Tools
|
|
43
|
+
|
|
44
|
+
- **Any**: A lightweight structure that wraps any value into the same type leveraging a variant of the type erasure technique.
|
|
45
|
+
- **proxy**: Create a proxy for a decorated function with specified signatures, enabling efficient JIT compilation and caching.
|
|
46
|
+
|
|
47
|
+
## Installation
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
pip install numbox
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
numbox/__init__.py,sha256=uZsygMXMKRw-7qhWojAjnpm8GFPXU92xW6XA8O5GwFY,22
|
|
2
|
+
numbox/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
+
numbox/core/any_type.py,sha256=CvEwFk7EcuFwg5VqDJrYQYmWp_t3Kil92wC7gUOEl-Y,1711
|
|
4
|
+
numbox/core/declare_func.py,sha256=zjlou3avyybHvpqNfp9D1_1kaOxLiGSxXtxiXlLsSPQ,150876
|
|
5
|
+
numbox/core/meminfo.py,sha256=-b7wlCRyqOZjvKjEuwNwzqE4XvnEWxu3I2k4DEP3Cqk,1755
|
|
6
|
+
numbox/core/proxy.py,sha256=kGYlEdLK40lxxu56e_S32s9YuQ6AuQnFegt5uQrUw5w,3889
|
|
7
|
+
numbox/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
+
numbox/utils/highlevel.py,sha256=hAmF2y2ayPJT0qpwHrGDt09R4-6Ts9sTkCTh-8FTIUU,319
|
|
9
|
+
numbox/utils/lowlevel.py,sha256=6CRfFbMeBZGM7hqPAQzyClzU_e_IsNpqONJknFWGzJM,1405
|
|
10
|
+
numbox-0.1.3.dist-info/LICENSE,sha256=YYgNvjH_p6-1NsdrIqGJnr1GUbZzA_8DxsP6vVfM6nY,1446
|
|
11
|
+
numbox-0.1.3.dist-info/METADATA,sha256=VOYJC8CJ4qWajTGPcv7LkzoefGEqWHY13rjvtQM354I,2271
|
|
12
|
+
numbox-0.1.3.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
|
|
13
|
+
numbox-0.1.3.dist-info/top_level.txt,sha256=A67jOkfqidCSYYm6ifjN_WZyIiR1B27fjxv6nNbPvjc,7
|
|
14
|
+
numbox-0.1.3.dist-info/RECORD,,
|
numbox-0.1.1.dist-info/RECORD
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
numbox/__init__.py,sha256=ls1camlIoMxEZz9gSkZ1OJo-MXqHWwKPtdPbZJmwp7E,22
|
|
2
|
-
numbox/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
-
numbox/core/any_type.py,sha256=fLdDEXCJ6-2rZpTCY8-iqxUFbOXTS8HrQshNxXdjVbw,2093
|
|
4
|
-
numbox/core/meminfo.py,sha256=-b7wlCRyqOZjvKjEuwNwzqE4XvnEWxu3I2k4DEP3Cqk,1755
|
|
5
|
-
numbox/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
|
-
numbox/utils/highlevel.py,sha256=hAmF2y2ayPJT0qpwHrGDt09R4-6Ts9sTkCTh-8FTIUU,319
|
|
7
|
-
numbox/utils/lowlevel.py,sha256=6CRfFbMeBZGM7hqPAQzyClzU_e_IsNpqONJknFWGzJM,1405
|
|
8
|
-
numbox-0.1.1.dist-info/LICENSE,sha256=YYgNvjH_p6-1NsdrIqGJnr1GUbZzA_8DxsP6vVfM6nY,1446
|
|
9
|
-
numbox-0.1.1.dist-info/METADATA,sha256=jmdNZuvX53cJ9U_At9VQSyFGrFKgohjosGsfLCWz26A,1926
|
|
10
|
-
numbox-0.1.1.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
|
|
11
|
-
numbox-0.1.1.dist-info/top_level.txt,sha256=A67jOkfqidCSYYm6ifjN_WZyIiR1B27fjxv6nNbPvjc,7
|
|
12
|
-
numbox-0.1.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|