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
Add numpy windowing functions support (np.bartlett, np.hamming, np.blackman, np.hanning, np.kaiser) #4076
Conversation
@stuartarchibald I think this is ready for an initial review. I've added the implementations for all of the windowing functions, with associated tests and changes to the docs, but since this is my first code contribution to numba, any feedback would be most appreciated. They are all pretty straightforward translations of the numpy source code, except for |
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.
Thanks for the PR @synapticarbors, I've reviewed the code, it largely looks good! Most of my comments are around creating consistent behaviours for Numba, particularly about ensuring type inference problems are caught early. There's also some refactoring I think may be possible which in the long term should lead to less code to maintain. Thanks again :)
Also, looks like there's some floating point problems on 32bit platforms https://travis-ci.org/numba/numba/jobs/530906188#L3993, perhaps check |
@stuartarchibald -- Thank you for the review. I have done the following:
What still needs to be done:
|
@synapticarbors thanks for making those changes WRT review, on initial inspection the clean-up patch looks good. With regards to I think you should be able to do: @overload(np.i0)
def np_i0(x):
# you may need to dispatch to different impls based on type, this is fine...
# define a few impls here and write branches in the typing scope as needed
if isinstance(x, some_type):
def impl(x):
# the impl that was derived from cephes as per NumPy for "some_type"
return the_result
if isinstance(x, some_other_type):
def impl(x):
# the impl that was derived from cephes as per NumPy for "some_other_type"
return the_result
return impl Once this is working we can take a look at the 32bit floating point issue with source code that is less challenging to manipulate! Hope this helps, and thanks for your contributions :) |
@stuartarchibald it looks like Should we punt for now on |
@synapticarbors I expect type based dispatch can be used to emulate |
@synapticarbors thanks for the update! I think this is just failing due to issues on 32bit platforms now, are you happy to look at this (if not, it's no problem, the Numba farm has all these combinations of machines set up!)? |
@stuartarchibald I set up a Linux VM last night to run a 32-bit version, since I'm on MacOS and it didn't look like one was available for it natively. I'm hoping I can get that configured today and reproduce the failed tests. If not, is there a recommended way to test 32-bit on MacOS? I looked briefly at Docker, but I'm not that familiar with it so wasn't sure what the best route was there. |
@synapticarbors thanks for working on how to reproduce this! I'm not sure about OSX, perhaps VirtualBox? @seibert any ideas? It looks like it's just a floating point problem, but it would be nice to be able to determine if there's something fundamentally wrong where e.g. more extreme inputs would exacerbate the error, or if it is just floating point wobble. |
If it is a precision issue that only manifests on 32-bit, then that sounds like some effect of using the x87 instructions (which have 80-bit precision for intermediate values until you flush to memory) vs. SSE instructions (which have 64-bit precision all the time). |
To be more specific: If for some reason gcc and LLVM are sequencing things differently, and one is running out of x87 registers and having to evict values at a different point than the other, that could do this. |
The difference is 1 ulp, so I think it would be reasonable to loosen up the precision requirement, at least on 32-bit Linux. |
Good point, the error is at 1ULP. |
Thanks for the suggestion. I just pushed a commit to use a different |
Unfortunately still failing with
|
Ah, I see what is happening. In [57]: t.assertPreciseEqual(0.036710892271286669, 0.036710892271286676, prec='exact', ulps=2)
---------------------------------------------------------------------------
AssertionError Traceback (most recent call last)
<ipython-input-57-cb0c14bc8896> in <module>()
----> 1 t.assertPreciseEqual(0.036710892271286669, 0.036710892271286676, prec='exact', ulps=2)
/Users/sseibert/anaconda/lib/python2.7/site-packages/numba/tests/support.pyc in assertPreciseEqual(self, first, second, prec, ulps, msg, ignore_sign_on_zero, abs_tol)
263 return
264 # Decorate the failure message with more information
--> 265 self.fail("when comparing %s and %s: %s" % (first, second, failure_msg))
266
267 def _assertPreciseEqual(self, first, second, prec='exact', ulps=1,
/Users/sseibert/anaconda/lib/python2.7/unittest/case.pyc in fail(self, msg)
408 def fail(self, msg=None):
409 """Fail immediately, with the given message."""
--> 410 raise self.failureException(msg)
411
412 def assertFalse(self, expr, msg=None):
AssertionError: when comparing 0.0367108922713 and 0.0367108922713: 0.03671089227128667 != 0.036710892271286676
In [58]: t.assertPreciseEqual(0.036710892271286669, 0.036710892271286676, prec='double')
In [59]: |
Thanks for the clarification. Should I be using |
ah, thanks @seibert :) totally forgot about that! |
Exact is nice and unambiguous, but I think unrealistic for some floating point algorithms, especially when platforms have unpredictable roundoff error like x87 instructions on x86. I would say it is best to use |
So, a combination of |
I have restarted the CI runs. I think you may have hit some temporary anaconda.org downtime. |
Thanks @seibert. It looks like everything ran without error this time. Is this ready to merge now? If so, can this be slipped into the 0.44.0 release? |
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.
@synapticarbors thanks for persisting with those floating point fixes. I just noticed one last thing to fix on the error handling tests that slipped through, and then I think this is good to go. Thanks again!
numba/tests/test_np_functions.py
Outdated
else: | ||
self.assertPreciseEqual(expected, got, prec='exact') | ||
|
||
with self.assertRaises(TypingError): |
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 think that this comment here #4076 (comment) needs further addressing at this location, whilst this asserts that it's a typing error, it doesn't assert it's the expected typing error. Also, when making this check, recall that the exception handling is in the typing domain, so variations in value have no impact. e.g. a foo(10.0)
would raise the same error as foo(20.0)
, as 10.0 and 20.0 would both be seen as floats.
A typical method of doing this might be:
with self.assertRaises(TypingError) as raises:
np_nbfunc('a', 10)
self.assertIn('M must be an integer', str(raises.exception))
then same for beta
. Thanks.
numba/tests/test_np_functions.py
Outdated
got = np_nbfunc(M) | ||
self.assertPreciseEqual(expected, got) | ||
|
||
with self.assertRaises(TypingError): |
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.
Same comment from below RE testing exceptions applies here.
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.
Thanks for catching this. I think the latest commit fixes the oversight.
One failure on Travis -- another network connectivity issue:
|
@synapticarbors This looks great, marking for merge. Thanks for all your efforts with this and congratulations on your first contribution to Numba! :) |
Thank you both for all of your help getting this one together. Hopefully I can work on a few more of these soon. Also technically this is my first code contribution to numba. I had a doc edit that was merged a long time ago (bc16d77), but this definitely feels more satisfying :-) |
@synapticarbors no problem at all, we look forward to receiving more PRs! Also, you are indeed correct, |
Adding support for
np.bartlett
to address missing numpy features mentioned in #4074.I will also try to tackle all of the windowing functions since they are quite similar.