-
-
Notifications
You must be signed in to change notification settings - Fork 151
Fix bug in local_elemwise_alloc
and add tests
#767
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
Fix bug in local_elemwise_alloc
and add tests
#767
Conversation
Codecov Report
@@ Coverage Diff @@
## main #767 +/- ##
=======================================
Coverage 78.35% 78.35%
=======================================
Files 152 152
Lines 47685 47687 +2
Branches 10881 10880 -1
=======================================
+ Hits 37364 37367 +3
+ Misses 7773 7772 -1
Partials 2548 2548
|
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.
Can you add a MWE that reproduces the issue in the description (and explicitly shows the problematic graphs)?
Done |
I'm starting to see that For instance, some of its |
I don't quite get how this rewrite is supposed to work now that I think about it. If we start with (lambda x, y: at.mul(at.alloc(x, 15, 1), at.alloc(y, 15, 1))),
(lambda x, y: at.mul(at.alloc(x, 15, 2), at.alloc(y, 15, 2))), Nevermind, that's what the |
Yeah, the docstring and logic are both unnecessarily confusing and convoluted. That—combined with a lack of quality (e.g. direct) unit tests—almost necessarily gives rise to these kinds of issues. This is yet another example of why we need to move toward formalizing our rewrites and their descriptions. In this case, the docstring uses its own notation (e.g. |
I cleaned a bit the test logic in a separate commit. The two test conditions with the This is not necessarily a failure, but suggests the original rewrite was not quite able to deliver what it meant to? |
Wouldn't surprise me, but, while we're fixing this, let's at least make our assumptions/goals very clear in the docstring. Also, we need to do something about that Is there a |
Yes that could be done, but according to the comments in the docstrings that would be less efficient in the general case (where |
I don't see how that could be a real problem (for at least the case of adding broadcastable dimensions to an Here's a quick and dirty check: def alloc(v, shape):
res = np.empty(shape)
res[...] = v
return res
%timeit alloc(2, (1000, 1000))
258 µs ± 8.04 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit alloc(2, (1, 1, 1, 1, 1000, 1000, 1, 1, 1, 1))
278 µs ± 19.2 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit np.expand_dims(alloc(2, (1000, 1000)), (0, 1, 2, 3, -1, -2, -3, -4))
282 µs ± 10.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit alloc(2, (5000, 5000))
21.7 ms ± 2.15 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit alloc(2, (1, 1, 1, 1, 5000, 5000, 1, 1, 1, 1))
21 ms ± 166 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit np.expand_dims(alloc(2, (5000, 5000)), (0, 1, 2, 3, -1, -2, -3, -4))
21.4 ms ± 764 µs per loop (mean ± std. dev. of 7 runs, 10 loops each) The old codebase has some confusing "efficiency"-based comments like that—ones that I'm not sure were ever necessarily true or relevant. Regardless of the practical truth of these kinds of statements, if we consider the entire context (e.g. the ability to add complementary rewrites/canonicalizations, the fact that we do multiple passes and have distinct rewrite stages, etc.), they may be completely irrelevant. |
The docstring of In other words, the rewrites and canonical form for Update: Yes, that's definitely the reason, because |
c0e7a3a
to
e4c025f
Compare
The rewrite would sometimes return a new graph identical to the original, resulting in divergence.
e4c025f
to
7e3792c
Compare
Rewrite would return a new graph identical to itself, resulting in an endless rewrite cycle
There are still flaws in the rewrite logic, as indicated by the new triggered assertionFirst showed up in pymc-devs/pymc#5369
TODO:
Dimshuffle
ofAlloc
logic