-
Notifications
You must be signed in to change notification settings - Fork 73
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Experimental AST rewriter and JIT decorator #326
base: experimental/abc-mangling
Are you sure you want to change the base?
Experimental AST rewriter and JIT decorator #326
Conversation
clifford/test/test_jit_func.py
Outdated
|
||
np.testing.assert_allclose(test_func(e1, e2, einf).value, slow_test_func(e1, e2, einf).value) | ||
|
||
def test_benchmark(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's make this an actual benchmark:
def test_benchmark(self): | |
@pytest.mark.parametrize('use_jit', [False, True]) | |
def test_benchmark(self, use_jit, benchmark): |
This pull request introduces 1 alert when merging 8094a61 into c07db7d - view on LGTM.com new alerts:
|
clifford/_layout.py
Outdated
def impl(a, b): | ||
return omt_func(a, b) | ||
return impl | ||
elif isinstance(a, types.Array) and isinstance(b, types.abstract.Number): | ||
def impl(a, b): | ||
return omt_func(a, as_ga(b)) | ||
return impl | ||
elif isinstance(a, types.abstract.Number) and isinstance(b, types.Array): | ||
def impl(a, b): | ||
return omt_func(as_ga(a), b) | ||
return impl | ||
else: | ||
def impl(a, b): | ||
return a^b | ||
return impl |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tempting to make these shorter:
def impl(a, b): | |
return omt_func(a, b) | |
return impl | |
elif isinstance(a, types.Array) and isinstance(b, types.abstract.Number): | |
def impl(a, b): | |
return omt_func(a, as_ga(b)) | |
return impl | |
elif isinstance(a, types.abstract.Number) and isinstance(b, types.Array): | |
def impl(a, b): | |
return omt_func(as_ga(a), b) | |
return impl | |
else: | |
def impl(a, b): | |
return a^b | |
return impl | |
return lambda a, b: omt_func(a, b) | |
elif isinstance(a, types.Array) and isinstance(b, types.abstract.Number): | |
return lambda a, b: omt_func(a, as_ga(b)) | |
elif isinstance(a, types.abstract.Number) and isinstance(b, types.Array): | |
return lambda a, b: omt_func(as_ga(a), b) | |
else: | |
return lambda a, b: return a^b |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Happy to merge this into the experimental branch, if you think you're stabilized now
This pull request introduces 2 alerts when merging e0263f8 into c07db7d - view on LGTM.com new alerts:
|
This pull request introduces 2 alerts when merging e878dbe into c07db7d - view on LGTM.com new alerts:
|
clifford/jit_func.py
Outdated
fname = func.__name__ | ||
source = inspect.getsource(func) | ||
# Remove the decorator first line. | ||
source = '\n'.join(source.splitlines()[1:]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be better to remove this at the ast level
This pull request introduces 2 alerts when merging 482b091 into c07db7d - view on LGTM.com new alerts:
|
|
||
test_compound_func = jit_func(self.layout, | ||
mv_constants={'test_func_1': test_func_1_jit, | ||
'test_func_2': test_func_2_jit})(compound_func) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a way to nest functions by using(abusing?) the mv_constants argument, it is clearly not a great solution but I'm not sure how to pull it off otherwise. Perhaps the decorator has knowledge of what functions are available?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The decorator can probably use inspect.currentframe().f_back.f_locals
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suspect you should be using f_globals
instead of globals()
too.
|
||
test_compound_func = jit_func(self.layout, | ||
mv_constants={'test_func_1': test_func_1_jit, | ||
'test_func_2': test_func_2_jit})(compound_func) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The decorator can probably use inspect.currentframe().f_back.f_locals
clifford/_layout.py
Outdated
@_cached_property | ||
def overload_mul_func(self): | ||
return get_overload_mul(self) | ||
|
||
@_cached_property | ||
def overload_xor_func(self): | ||
return get_overload_xor(self) | ||
|
||
@_cached_property | ||
def overload_or_func(self): | ||
return get_overload_or(self) | ||
|
||
@_cached_property | ||
def overload_add_func(self): | ||
return get_overload_add(self) | ||
|
||
@_cached_property | ||
def overload_sub_func(self): | ||
return get_overload_sub(self) | ||
|
||
@_cached_property | ||
def overload_reverse_func(self): | ||
return get_overload_reverse(self) | ||
|
||
@_cached_property | ||
def project_to_grade_func(self): | ||
return get_project_to_grade_func(self) | ||
|
||
@_cached_property | ||
def overload_call_func(self): | ||
return get_overload_call(self) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think these really belong here. You've put them here because it makes them easy to cache, but I think it would be better to cache them manually in a weakref.WeakKeyDictionary
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So perhaps something like
def weak_cache(f):
_cache = weakref.WeakKeyDictionary()
@functools.wraps(f)
def wrapped(*args, **kwargs):
a, *args = args
try:
return _cache[a]
except KeyError:
ret =_cache[a] = f(a, *args, **kwargs)
return ret
wrapped._cache = _cache
return wrapped
@weak_cache
def _get_jit_impls(layout):
return {
'as_ga': get_as_ga_value_vector_func(layout),
'ga_add': get_overload_add_func(layout),
'ga_sub': get_overload_sub_func(layout),
'ga_mul': get_overload_mul_func(layout),
'ga_xor': get_overload_xor_func(layout),
'ga_or': get_overload_or_func(layout),
'ga_rev': get_overload_reverse_func(layout),
'ga_call': get_overload_call_func(layout),
}
clifford/jit_func.py
Outdated
@@ -0,0 +1,92 @@ | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps clifford/experimental/jit_func
clifford/jit_func.py
Outdated
# Remove the decorators from the function | ||
tree = DecoratorRemover().visit(tree) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Strictly you want to leave behind all the non-jitfunc
decorators, but that's fine as a todo.
@@ -117,7 +117,8 @@ def linear_operator_as_matrix(func, input_blades, output_blades): | |||
ndimout = len(output_blades) | |||
mat = np.zeros((ndimout, ndimin)) | |||
for i, b in enumerate(input_blades): | |||
mat[:, i] = np.array([func(b)[j] for j in output_blades]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice find
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably makes sense to spin out a quick PR with just this fix against master.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah I was thinking that
What do we want to do with this now that we have proper numba support? |
Shall we just close it? I don't think it adds anything on top of what we have, although it was an interesting and fun idea |
No description provided.