Add pyfftw sdp#1132
Conversation
|
Review these changes at https://app.gitnotebooks.com/stumpy-dev/stumpy/pull/1132 |
There was a problem hiding this comment.
@NimaSarajpoor I've left some comments for you to address. I think we can afford to be clearer since all of this pyfftw stuff will be hard to maintain. We should probably be as verbose (and add more comments cross referencing their docs as possible). I'll do another few passes after you've responded and made modifications. I think this pyfftw stuff needs to be crystal clear
|
@seanlaw |
|
@NimaSarajpoor This might be a distraction but a (very, very small) part of me was wondering if we should be using a closure instead of a class: https://realpython.com/python-closure/ I don't know if it makes things easier/harder to read. Given all of the array allocations, maybe a class is the right thing to use. I just wanted to bring it to your attention since I'm not sure we're getting the full benefits of a class since:
Just something to consider. No pressure though. |
This is something that bothered me too but thought the reason for being bothered is just my lack of experience and, also, I didn't know/think about an alternative option.
Thanks for sharing this! I will go through this and try to modify the script. Let's see how it will look like. |
|
@seanlaw |
Yeah, it feels pretty natural! There is one thing that still bothers me and that is "how do you change/reset max_n after the function has been created?" The natural thing to do is to overwrite the existing It feels like we're very close.
Indeed. This is partially why I didn't like using the class approach! |
I did not think about this scenario. I am now thinking in what scenario(s) a user might want to change We can define a new function inside |
Okay... on second thought, I think it should be okay to allow the returned callable object has a "callable feature" for resetting |
Can you please show me a complete example of how this works (i.e., from instantiating a new object to changing the |
Maybe I should've used the name |
I don't think I understand what you mean by "user cannot check if the array is resized". Can you articulate what could possibly go wrong? What would somebody need/want to verify? Do the arrays automatically get resized if, later, somebody uses an array that is larger than |
Yes. Based on the current design, if
Please ignore. That was stupid!
What do you think about this? Now that we are planning to add |
I guess I would need to consider what the side effect would be if the preallocated were to be automatically resized (i.e., what would be the problem with this?). Currently, I don't see any issues with automatically resizing the preallocated array |
NimaSarajpoor
left a comment
There was a problem hiding this comment.
@seanlaw
I just left one comment. I think it should be ready to merge after discussing/addressing that comment.
seanlaw
left a comment
There was a problem hiding this comment.
@NimaSarajpoor I've left some comments for you to consider. Once completed, please let me know as I'd like to go over the code in more detail before you move on (as it's been a while since I've gone over things).
|
@seanlaw |
seanlaw
left a comment
There was a problem hiding this comment.
@NimaSarajpoor I think everything looks good. Just a few comments for you to consider
| real-valued array. A complex-valued array of size 1 + (init_len // 2) | ||
| will also be preallocated. If inputs exceed this size, arrays will be | ||
| reallocated to accommodate larger sizes. | ||
| will also be preallocated. If the length of input arrays exceed |
There was a problem hiding this comment.
"if the length of the input arrays exceedS init_len, THEN the preallocated arrays will AUTOMATICALLY be resized..."
| A callable object that computes the sliding dot product between ``Q`` | ||
| and ``T`` using FFTW via pyfftw, and caches FFTW objects if not already | ||
| cached. The callable object automatically resizes the preallocated arrays | ||
| if the length of input arrays exceed the current initial length. |
|
|
||
| # Compute the (circular) convolution between T and Q[::-1], | ||
| # each zero-padded to length next_fast_n by performing | ||
| # each zero-padded to the length `next_fast_n`, by performing |
There was a problem hiding this comment.
"to the length OF next_fast_n"
|
|
||
| # Step 2 | ||
| # Compute RFFT of Q (reversed, scaled, and zero-padded) | ||
| # Scaling is required because the thin wrapper execute |
There was a problem hiding this comment.
remove "execute" at the end of the line?
There was a problem hiding this comment.
Ok... I've decided to expand the explanation. what do you think?
# Step 2
# Compute RFFT of Q (reversed, scaled, and zero-padded)
# Scaling by `1.0 / next_fast_n` needs to be applied
# at some point in the process to ensure that the final result is correct.
# The thin wrapper ".execute()" used in different steps does not include
# scaling.
# This scaling can be applied to "zero_padded T" or its RFFT, or to
# "zero_padded reversed Q" or its RFFT. Or, it can be applied to
# the multiplication of the two RFFTs, or to the final result after the IRFFT!
# Here, we choose to apply the scaling to "reversed zero_padded Q" before its RFFT
# to reduce the number of floating point operations for such scaling process.
np.multiply(Q[::-1], 1.0 / next_fast_n, out=rfft_obj.input_array[:m])
rfft_obj.input_array[m:] = 0.0
rfft_obj.execute()
rfft_Q = rfft_obj.output_array
|
|
||
| return irfft_obj.output_array[m - 1 : n] # valid portion | ||
|
|
||
| def set_init_len(init_len): # pragma: no cover |
There was a problem hiding this comment.
Maybe it is better to do update_init_len and then in the docstring to "Update the size of the preallocated arrays to a new initial length". For some reason set sounds too passive
This is to address
PR 3described in #1118 (comment). Have copied the corresponding notes below: